qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Konrad Rzeszutek Wilk <konrad@darnok.org>
To: Anthony PERARD <anthony.perard@citrix.com>
Cc: Guy Zana <guy@neocleus.com>,
	Xen Devel <xen-devel@lists.xensource.com>,
	Allen Kay <allen.m.kay@intel.com>,
	QEMU-devel <qemu-devel@nongnu.org>,
	Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Subject: Re: [Qemu-devel] [Xen-devel] [PATCH V11 5/8] Introduce Xen PCI Passthrough, qdevice (1/3)
Date: Wed, 16 May 2012 07:31:43 -0400	[thread overview]
Message-ID: <20120516113142.GC21609@andromeda.dapyr.net> (raw)
In-Reply-To: <1333467163-25795-6-git-send-email-anthony.perard@citrix.com>

> +void xen_pt_log(const PCIDevice *d, const char *f, ...)
> +{
> +    va_list ap;
> +
> +    va_start(ap, f);
> +    if (d) {
> +        fprintf(stderr, "[%02x:%02x.%x] ", pci_bus_num(d->bus),

%d at the end and in the other location pls fix it up..

> +                PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
> +    }
> +    vfprintf(stderr, f, ap);
> +    va_end(ap);
> +}
> +
> +/* Config Space */
> +

.. Is there a way to make this function (and the following one) squahed?

> +static uint32_t xen_pt_pci_read_config(PCIDevice *d, uint32_t addr, int len)
> +{
> +    XenPCIPassthroughState *s = DO_UPCAST(XenPCIPassthroughState, dev, d);
> +    uint32_t val = 0;
> +    XenPTRegGroup *reg_grp_entry = NULL;
> +    XenPTReg *reg_entry = NULL;
> +    int rc = 0;
> +    int emul_len = 0;
> +    uint32_t find_addr = addr;
> +
> +    if (xen_pt_pci_config_access_check(d, addr, len)) {
> +        goto exit;
> +    }
> +
> +    /* find register group entry */
> +    reg_grp_entry = xen_pt_find_reg_grp(s, addr);
> +    if (reg_grp_entry) {
> +        /* check 0-Hardwired register group */
> +        if (reg_grp_entry->reg_grp->grp_type == XEN_PT_GRP_TYPE_HARDWIRED) {
> +            /* no need to emulate, just return 0 */
> +            val = 0;
> +            goto exit;
> +        }
> +    }
> +
> +    /* read I/O device register value */
> +    rc = xen_host_pci_get_block(&s->real_device, addr, (uint8_t *)&val, len);
> +    if (rc < 0) {
> +        XEN_PT_ERR(d, "pci_read_block failed. return value: %d.\n", rc);
> +        memset(&val, 0xff, len);
> +    }
> +
> +    /* just return the I/O device register value for
> +     * passthrough type register group */
> +    if (reg_grp_entry == NULL) {
> +        goto exit;
> +    }
> +
> +    /* adjust the read value to appropriate CFC-CFF window */
> +    val <<= (addr & 3) << 3;
> +    emul_len = len;
> +
> +    /* loop around the guest requested size */
> +    while (emul_len > 0) {
> +        /* find register entry to be emulated */
> +        reg_entry = xen_pt_find_reg(reg_grp_entry, find_addr);
> +        if (reg_entry) {
> +            XenPTRegInfo *reg = reg_entry->reg;
> +            uint32_t real_offset = reg_grp_entry->base_offset + reg->offset;
> +            uint32_t valid_mask = 0xFFFFFFFF >> ((4 - emul_len) << 3);
> +            uint8_t *ptr_val = NULL;
> +
> +            valid_mask <<= (find_addr - real_offset) << 3;
> +            ptr_val = (uint8_t *)&val + (real_offset & 3);
> +
> +            /* do emulation based on register size */
> +            switch (reg->size) {
> +            case 1:
> +                if (reg->u.b.read) {
> +                    rc = reg->u.b.read(s, reg_entry, ptr_val, valid_mask);
> +                }
> +                break;
> +            case 2:
> +                if (reg->u.w.read) {
> +                    rc = reg->u.w.read(s, reg_entry,
> +                                       (uint16_t *)ptr_val, valid_mask);
> +                }
> +                break;
> +            case 4:
> +                if (reg->u.dw.read) {
> +                    rc = reg->u.dw.read(s, reg_entry,
> +                                        (uint32_t *)ptr_val, valid_mask);
> +                }
> +                break;
> +            }
> +
> +            if (rc < 0) {
> +                xen_shutdown_fatal_error("Internal error: Invalid read "
> +                                         "emulation. (%s, rc: %d)\n",
> +                                         __func__, rc);
> +                return 0;
> +            }
> +
> +            /* calculate next address to find */
> +            emul_len -= reg->size;
> +            if (emul_len > 0) {
> +                find_addr = real_offset + reg->size;
> +            }
> +        } else {
> +            /* nothing to do with passthrough type register,
> +             * continue to find next byte */
> +            emul_len--;
> +            find_addr++;
> +        }
> +    }
> +
> +    /* need to shift back before returning them to pci bus emulator */
> +    val >>= ((addr & 3) << 3);
> +
> +exit:
> +    XEN_PT_LOG_CONFIG(d, addr, val, len);
> +    return val;
> +}
> +
> +static void xen_pt_pci_write_config(PCIDevice *d, uint32_t addr,
> +                                    uint32_t val, int len)
> +{
> +    XenPCIPassthroughState *s = DO_UPCAST(XenPCIPassthroughState, dev, d);
> +    int index = 0;
> +    XenPTRegGroup *reg_grp_entry = NULL;
> +    int rc = 0;
> +    uint32_t read_val = 0;
> +    int emul_len = 0;
> +    XenPTReg *reg_entry = NULL;
> +    uint32_t find_addr = addr;
> +    XenPTRegInfo *reg = NULL;
> +
> +    if (xen_pt_pci_config_access_check(d, addr, len)) {
> +        return;
> +    }
> +
> +    XEN_PT_LOG_CONFIG(d, addr, val, len);
> +
> +    /* check unused BAR register */
> +    index = xen_pt_bar_offset_to_index(addr);
> +    if ((index >= 0) && (val > 0 && val < XEN_PT_BAR_ALLF) &&
> +        (s->bases[index].bar_flag == XEN_PT_BAR_FLAG_UNUSED)) {
> +        XEN_PT_WARN(d, "Guest attempt to set address to unused Base Address "
> +                    "Register. (addr: 0x%02x, len: %d)\n", addr, len);
> +    }
> +
> +    /* find register group entry */
> +    reg_grp_entry = xen_pt_find_reg_grp(s, addr);
> +    if (reg_grp_entry) {
> +        /* check 0-Hardwired register group */
> +        if (reg_grp_entry->reg_grp->grp_type == XEN_PT_GRP_TYPE_HARDWIRED) {
> +            /* ignore silently */
> +            XEN_PT_WARN(d, "Access to 0-Hardwired register. "
> +                        "(addr: 0x%02x, len: %d)\n", addr, len);
> +            return;
> +        }
> +    }
> +
> +    rc = xen_host_pci_get_block(&s->real_device, addr,
> +                                (uint8_t *)&read_val, len);
> +    if (rc < 0) {
> +        XEN_PT_ERR(d, "pci_read_block failed. return value: %d.\n", rc);
> +        memset(&read_val, 0xff, len);
> +    }
> +
> +    /* pass directly to the real device for passthrough type register group */
> +    if (reg_grp_entry == NULL) {
> +        goto out;
> +    }
> +
> +    memory_region_transaction_begin();
> +    pci_default_write_config(d, addr, val, len);
> +
> +    /* adjust the read and write value to appropriate CFC-CFF window */
> +    read_val <<= (addr & 3) << 3;
> +    val <<= (addr & 3) << 3;
> +    emul_len = len;
> +
> +    /* loop around the guest requested size */
> +    while (emul_len > 0) {
> +        /* find register entry to be emulated */
> +        reg_entry = xen_pt_find_reg(reg_grp_entry, find_addr);
> +        if (reg_entry) {
> +            reg = reg_entry->reg;
> +            uint32_t real_offset = reg_grp_entry->base_offset + reg->offset;
> +            uint32_t valid_mask = 0xFFFFFFFF >> ((4 - emul_len) << 3);
> +            uint8_t *ptr_val = NULL;
> +
> +            valid_mask <<= (find_addr - real_offset) << 3;
> +            ptr_val = (uint8_t *)&val + (real_offset & 3);
> +
> +            /* do emulation based on register size */
> +            switch (reg->size) {
> +            case 1:
> +                if (reg->u.b.write) {
> +                    rc = reg->u.b.write(s, reg_entry, ptr_val,
> +                                        read_val >> ((real_offset & 3) << 3),
> +                                        valid_mask);
> +                }
> +                break;
> +            case 2:
> +                if (reg->u.w.write) {
> +                    rc = reg->u.w.write(s, reg_entry, (uint16_t *)ptr_val,
> +                                        (read_val >> ((real_offset & 3) << 3)),
> +                                        valid_mask);
> +                }
> +                break;
> +            case 4:
> +                if (reg->u.dw.write) {
> +                    rc = reg->u.dw.write(s, reg_entry, (uint32_t *)ptr_val,
> +                                         (read_val >> ((real_offset & 3) << 3)),
> +                                         valid_mask);
> +                }
> +                break;
> +            }
> +
> +            if (rc < 0) {
> +                xen_shutdown_fatal_error("Internal error: Invalid write"
> +                                         " emulation. (%s, rc: %d)\n",
> +                                         __func__, rc);
> +                return;
> +            }
> +
> +            /* calculate next address to find */
> +            emul_len -= reg->size;
> +            if (emul_len > 0) {
> +                find_addr = real_offset + reg->size;
> +            }
> +        } else {
> +            /* nothing to do with passthrough type register,
> +             * continue to find next byte */
> +            emul_len--;
> +            find_addr++;
> +        }
> +    }
> +
> +    /* need to shift back before passing them to xen_host_pci_device */
> +    val >>= (addr & 3) << 3;
> +
> +    memory_region_transaction_commit();

  reply	other threads:[~2012-05-16 11:32 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-04-03 15:32 [Qemu-devel] [PATCH V11 0/8] Xen PCI Passthrough Anthony PERARD
2012-04-03 15:32 ` [Qemu-devel] [PATCH V11 1/8] pci_ids: Add INTEL_82599_SFP_VF id Anthony PERARD
2012-04-03 15:32 ` [Qemu-devel] [PATCH V11 2/8] configure: Introduce --enable-xen-pci-passthrough Anthony PERARD
2012-04-03 15:32 ` [Qemu-devel] [PATCH V11 3/8] Introduce XenHostPCIDevice to access a pci device on the host Anthony PERARD
2012-05-16 11:24   ` [Qemu-devel] [Xen-devel] " Konrad Rzeszutek Wilk
2012-05-22 12:52     ` Anthony PERARD
2012-04-03 15:32 ` [Qemu-devel] [PATCH V11 4/8] pci.c: Add opaque argument to pci_for_each_device Anthony PERARD
2012-04-03 15:32 ` [Qemu-devel] [PATCH V11 5/8] Introduce Xen PCI Passthrough, qdevice (1/3) Anthony PERARD
2012-05-16 11:31   ` Konrad Rzeszutek Wilk [this message]
2012-04-03 15:32 ` [Qemu-devel] [PATCH V11 6/8] Introduce Xen PCI Passthrough, PCI config space helpers (2/3) Anthony PERARD
2012-04-03 15:32 ` [Qemu-devel] [PATCH V11 7/8] Introduce apic-msidef.h Anthony PERARD
2012-04-03 15:32 ` [Qemu-devel] [PATCH V11 8/8] Introduce Xen PCI Passthrough, MSI (3/3) Anthony PERARD

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=20120516113142.GC21609@andromeda.dapyr.net \
    --to=konrad@darnok.org \
    --cc=allen.m.kay@intel.com \
    --cc=anthony.perard@citrix.com \
    --cc=guy@neocleus.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefano.stabellini@eu.citrix.com \
    --cc=xen-devel@lists.xensource.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).