qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Nicholas A. Bellinger" <nab@linux-iscsi.org>
To: qemu-devel <qemu-devel@nongnu.org>
Cc: Kevin Wolf <kwolf@redhat.com>,
	Stefan Hajnoczi <stefanha@gmail.com>,
	Hannes Reinecke <hare@suse.de>,
	Paolo Bonzini <pbonzini@redhat.com>,
	Christoph Hellwig <hch@lst.de>, Gerd Hoffmann <kraxel@redhat.com>
Subject: [Qemu-devel] megasas: Usage of is_write in megasas_map_sgl()
Date: Thu, 02 Dec 2010 14:24:23 -0800	[thread overview]
Message-ID: <1291328663.15305.105.camel@haakon2.linux-iscsi.org> (raw)

Hi Hannes and Co,

I had a quick question wrt to megassas_map_sgl() ->
cpu_physical_memory_map() and usage of the 'is_write' parameter.

In megasas.v3 code on v0.13.0, this appears as:

static int megasas_map_sgl(struct megasas_cmd_t *cmd, int pa_offset)
{
    int i;
    uint16_t flags = le16_to_cpu(cmd->frame->header.flags);
    int is_sgl64 = (flags & MFI_FRAME_SGL64) ? 1 : 0;
    int is_write = (flags & MFI_FRAME_DIR_WRITE) ? 1 : 0;
    int sgl_addr_size = is_sgl64 ? sizeof(uint64_t) : sizeof(uint32_t);
    size_t iov_count = 0;

    cmd->iov = qemu_mallocz(sizeof(struct iovec) * (cmd->frame->header.sge_count + 1));
    for (i = 0; i < cmd->frame->header.sge_count; i++) {
        target_phys_addr_t pa, iov_pa, iov_size;

        pa = cmd->pa + pa_offset;
        if (is_sgl64)
            iov_pa = ldq_phys(pa);
        else
            iov_pa = ldl_phys(pa);
        iov_size = ldl_phys(pa + sgl_addr_size);
        DPRINTF_IO("iov_pa: %lx iov_size: %d, is_write: %d\n", iov_pa, (int)iov_size, is_write);
        cmd->iov[i].iov_base = cpu_physical_memory_map(iov_pa, &iov_size, is_write);
        cmd->iov[i].iov_len = iov_size;
        pa_offset += sgl_addr_size + sizeof(uint32_t);
        iov_count += iov_size;
    }

    <SNIP>

which I believe is following incoming SCSI CDB WRITE/READ
classification, right..?  So for cpu_physical_memory_map() with the
initial 16-byte INQUIRY with the lastest code, this is set to
is_write=0..

Looking at v0.12.5 code, the is_write is inverted in it's equivilent
form inside hw/scsi-generic.c:scsi_generic_map() using the QEMUSGList
that is being setup in the working version megasas_map_sgl():

static void megasas_map_sgl(struct megasas_cmd_t *cmd, int pa_offset)
{
    int i;
    int is_sgl64 = (cmd->frame->header.flags & MFI_FRAME_SGL64) ? 1 : 0;
    int sgl_addr_size = is_sgl64 ? sizeof(uint64_t) : sizeof(uint32_t);

    qemu_sglist_init(&cmd->sg, cmd->frame->header.sge_count);
    for (i = 0; i < cmd->frame->header.sge_count; i++) {
        target_phys_addr_t pa, iov_pa;

        pa = cmd->pa + pa_offset;
        if (is_sgl64)
            iov_pa = ldq_phys(pa);
        else
            iov_pa = ldl_phys(pa);
        qemu_sglist_add(&cmd->sg, iov_pa, ldl_phys(pa + sgl_addr_size));
        pa_offset += sgl_addr_size + sizeof(uint32_t);
    }
}

to scsi_req_sgl() -> scsi-generic.c:scsi_generic_req_sgl() to down
to scsi_generic_map and the inverted is_write:

static int scsi_generic_map(SCSIGenericReq *r, QEMUSGList *sg)
{
    int is_write = !scsi_req_is_write(&r->req);
    target_phys_addr_t cur_addr, cur_len, cur_offset = 0;
    void *mem;
    int i;

    qemu_iovec_reset(&r->iov);
    for (i = 0; i < sg->nsg;) {
        cur_addr = sg->sg[i].base + cur_offset;
        cur_len = sg->sg[i].len - cur_offset;
        DPRINTF("Using cur_addr: 0x%016lx cur_len: 0x%016lx\n", cur_addr, cur_len);

        mem = cpu_physical_memory_map(cur_addr, &cur_len, is_write);
        if (!mem)
            goto err;

        DPRINTF("Adding iovec for mem: %p len: 0x%016lx\n", mem, cur_len);
        qemu_iovec_add(&r->iov, mem, cur_len);
        cur_offset += cur_len;
        if (cur_offset == sg->sg[i].len) {
            cur_offset = 0;
            i++;
        }
    }
    return 0;

    <SNIP>

and here the first 16-byte INQUIRY appears as is_write=1..

The usage of a inverted is_write with cpu_physical_memory_map() also
seems to be the case in dma-helpers.c:dma_brdv_cb():

	mem = cpu_physical_memory_map(cur_addr, &cur_len, !dbs->is_write);

After changing to an inverted is_write in megasas.v3/megasas-upstream-v1
code, this still does *not* seem to make a difference wrt to the 64-bit
Win7 case, and the same BSOD appears..  In any event, we should verify
this with QEMU folks in terms of what the proper usage of is_write for
cpu_physical_memory_map().  Gerd and Kevin comments here..?

I am also wondering if Gerd's original v0.12.5 SCSI rewrite with
the following logic could be having a subtle affect:

*) megasas_map_sgl() being split up into a QEMUSGList at cmd->sg and
   down to cpu_physical_memory_map() -> qemu_iovec_add(&r->iov, ...)

instead of the new:

*) megasas_map_sgl() using a freshly qemu_malloc()'s cmd->iov buffer
   down to cpu_physical_memory_map() for cmd->iov[i].base, and not using
   an QEMUSGList intermediary.

AFAICT this does not seem to be an issue (not tested with a patch yet),
but wanted to double check that the usage of ld*_phys() for iov_pa and
iov_size directly preceeding cpu_physical_memory_map() is OK in
megasas.v3, and that skipping the QEMUSGList part of the mapping from
megasas_cmd->pa to megas_cmd->sg in v0.12.5 code is not creating some
subtle effect to break some guests..?

Any thoughts guys..?

--nab

             reply	other threads:[~2010-12-02 22:30 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-12-02 22:24 Nicholas A. Bellinger [this message]
2010-12-03 10:25 ` [Qemu-devel] Re: megasas: Usage of is_write in megasas_map_sgl() Kevin Wolf
2010-12-03 10:42   ` Hannes Reinecke

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1291328663.15305.105.camel@haakon2.linux-iscsi.org \
    --to=nab@linux-iscsi.org \
    --cc=hare@suse.de \
    --cc=hch@lst.de \
    --cc=kraxel@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).