From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:57136) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SAkSb-0006ki-Cy for qemu-devel@nongnu.org; Thu, 22 Mar 2012 12:02:04 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SAkSR-0004Ul-6B for qemu-devel@nongnu.org; Thu, 22 Mar 2012 12:01:56 -0400 Received: from smtp.citrix.com ([66.165.176.89]:41446) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SAkSR-0004Ua-1o for qemu-devel@nongnu.org; Thu, 22 Mar 2012 12:01:47 -0400 From: Julien Grall Date: Thu, 22 Mar 2012 15:59:24 +0000 Message-ID: <869b10d6ef10def49aa8a94524c2949e6a6039f0.1332430810.git.julien.grall@citrix.com> In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain Subject: [Qemu-devel] [XEN][RFC PATCH 03/15] hvm-pci: Handle PCI config space in Xen List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: xen-devel@lists.xensource.com Cc: Stefano.Stabellini@eu.citrix.com, qemu-devel@nongnu.org, julian.pidancet@citrix.com Add function to register a bdf with a server. To handle cf8 -> cff we add an handler with register_portio_handle. When Xen reveice a pio for cf8, it's store the value inside the current vcpu until it receives a pio for cfc -> cff. In this case, it checks if the bdf is registered and forge the ioreq that will be forward to server later. Signed-off-by: Julien Grall --- xen/arch/x86/hvm/Makefile | 1 + xen/arch/x86/hvm/pci_emul.c | 147 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+), 0 deletions(-) create mode 100644 xen/arch/x86/hvm/pci_emul.c diff --git a/xen/arch/x86/hvm/Makefile b/xen/arch/x86/hvm/Makefile index eea5555..585e9c9 100644 --- a/xen/arch/x86/hvm/Makefile +++ b/xen/arch/x86/hvm/Makefile @@ -12,6 +12,7 @@ obj-y += irq.o obj-y += mtrr.o obj-y += nestedhvm.o obj-y += pmtimer.o +obj-y += pci_emul.o obj-y += quirks.o obj-y += rtc.o obj-y += save.o diff --git a/xen/arch/x86/hvm/pci_emul.c b/xen/arch/x86/hvm/pci_emul.c new file mode 100644 index 0000000..b390e73 --- /dev/null +++ b/xen/arch/x86/hvm/pci_emul.c @@ -0,0 +1,147 @@ +#include +#include +#include +#include +#include + +#define PCI_DEBUGSTR "%x:%x.%x" +#define PCI_DEBUG(bdf) ((bdf) >> 16) & 0xff, ((bdf) >> 11) & 0x1f, ((bdf) >> 8) & 0x7 + +static int handle_config_space(int dir, uint32_t port, uint32_t bytes, + uint32_t *val) +{ + uint32_t pci_cf8; + struct pci_device_emul *pci; + ioreq_t *p = get_ioreq(current); + int rc = X86EMUL_UNHANDLEABLE; + struct vcpu *v = current; + + spin_lock(&v->domain->arch.hvm_domain.pci_root.pci_lock); + + if (port == 0xcf8) + { + rc = X86EMUL_OKAY; + v->arch.hvm_vcpu.pci_cf8 = *val; + goto end_handle; + } + + pci_cf8 = v->arch.hvm_vcpu.pci_cf8; + + /* Retrieve PCI */ + pci = v->domain->arch.hvm_domain.pci_root.pci; + + while (pci && !PCI_CMP_BDF(pci, pci_cf8)) + pci = pci->next; + + /* We just fill the ioreq, hvm_send_assist_req will send the request */ + if (unlikely(pci == NULL)) + { + *val = ~0; + rc = X86EMUL_OKAY; + goto end_handle; + } + + p->type = IOREQ_TYPE_PCI_CONFIG; + p->addr = (pci_cf8 & ~3) + (p->addr & 3); + + set_ioreq(v, &pci->server->ioreq, p); + +end_handle: + spin_unlock(&v->domain->arch.hvm_domain.pci_root.pci_lock); + return rc; +} + +int hvm_register_pcidev(domid_t domid, unsigned int id, u16 bdf) +{ + struct domain *d; + struct hvm_ioreq_server *s; + struct pci_device_emul *x; + int rc = 0; + + rc = rcu_lock_target_domain_by_id(domid, &d); + + if (rc != 0) + return rc; + + if (!is_hvm_domain(d)) + { + rcu_unlock_domain(d); + return -EINVAL; + } + + /* Search server */ + spin_lock(&d->arch.hvm_domain.ioreq_server_lock); + s = d->arch.hvm_domain.ioreq_server_list; + while ((s != NULL) && (s->id != id)) + s = s->next; + + if (s == NULL) + { + dprintk(XENLOG_DEBUG, "Cannot find server\n"); + rc = -ENOENT; + goto create_end; + } + + spin_unlock(&d->arch.hvm_domain.ioreq_server_lock); + + spin_lock(&d->arch.hvm_domain.pci_root.pci_lock); + x = xmalloc(struct pci_device_emul); + + if (!x) + { + dprintk(XENLOG_DEBUG, "Cannot allocate pci\n"); + rc = -ENOMEM; + goto create_end; + } + + x->bdf = PCI_MASK_BDF(bdf); + x->server = s; + x->next = d->arch.hvm_domain.pci_root.pci; + d->arch.hvm_domain.pci_root.pci = x; + +create_end: + spin_unlock(&d->arch.hvm_domain.pci_root.pci_lock); + rcu_unlock_domain(d); + + return rc; +} + +int hvm_init_pci_emul(struct domain *d) +{ + struct pci_root_emul *root = &d->arch.hvm_domain.pci_root; + + spin_lock_init(&root->pci_lock); + + root->pci = NULL; + + /* Register the config space handler */ + register_portio_handler(d, 0xcf8, 8, handle_config_space); + + return 0; +} + +void hvm_destroy_pci_emul(struct domain *d) +{ + struct pci_root_emul *root = &d->arch.hvm_domain.pci_root; + struct pci_device_emul *p; + + spin_lock(&root->pci_lock); + + while ( (p = root->pci) != NULL ) + { + root->pci = p->next; + xfree(p); + } + + spin_unlock(&root->pci_lock); +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ -- Julien Grall From mboxrd@z Thu Jan 1 00:00:00 1970 From: Julien Grall Subject: [XEN][RFC PATCH 03/15] hvm-pci: Handle PCI config space in Xen Date: Thu, 22 Mar 2012 15:59:24 +0000 Message-ID: <869b10d6ef10def49aa8a94524c2949e6a6039f0.1332430810.git.julien.grall@citrix.com> References: Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: xen-devel@lists.xensource.com Cc: Stefano.Stabellini@eu.citrix.com, qemu-devel@nongnu.org, julian.pidancet@citrix.com List-Id: xen-devel@lists.xenproject.org Add function to register a bdf with a server. To handle cf8 -> cff we add an handler with register_portio_handle. When Xen reveice a pio for cf8, it's store the value inside the current vcpu until it receives a pio for cfc -> cff. In this case, it checks if the bdf is registered and forge the ioreq that will be forward to server later. Signed-off-by: Julien Grall --- xen/arch/x86/hvm/Makefile | 1 + xen/arch/x86/hvm/pci_emul.c | 147 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+), 0 deletions(-) create mode 100644 xen/arch/x86/hvm/pci_emul.c diff --git a/xen/arch/x86/hvm/Makefile b/xen/arch/x86/hvm/Makefile index eea5555..585e9c9 100644 --- a/xen/arch/x86/hvm/Makefile +++ b/xen/arch/x86/hvm/Makefile @@ -12,6 +12,7 @@ obj-y += irq.o obj-y += mtrr.o obj-y += nestedhvm.o obj-y += pmtimer.o +obj-y += pci_emul.o obj-y += quirks.o obj-y += rtc.o obj-y += save.o diff --git a/xen/arch/x86/hvm/pci_emul.c b/xen/arch/x86/hvm/pci_emul.c new file mode 100644 index 0000000..b390e73 --- /dev/null +++ b/xen/arch/x86/hvm/pci_emul.c @@ -0,0 +1,147 @@ +#include +#include +#include +#include +#include + +#define PCI_DEBUGSTR "%x:%x.%x" +#define PCI_DEBUG(bdf) ((bdf) >> 16) & 0xff, ((bdf) >> 11) & 0x1f, ((bdf) >> 8) & 0x7 + +static int handle_config_space(int dir, uint32_t port, uint32_t bytes, + uint32_t *val) +{ + uint32_t pci_cf8; + struct pci_device_emul *pci; + ioreq_t *p = get_ioreq(current); + int rc = X86EMUL_UNHANDLEABLE; + struct vcpu *v = current; + + spin_lock(&v->domain->arch.hvm_domain.pci_root.pci_lock); + + if (port == 0xcf8) + { + rc = X86EMUL_OKAY; + v->arch.hvm_vcpu.pci_cf8 = *val; + goto end_handle; + } + + pci_cf8 = v->arch.hvm_vcpu.pci_cf8; + + /* Retrieve PCI */ + pci = v->domain->arch.hvm_domain.pci_root.pci; + + while (pci && !PCI_CMP_BDF(pci, pci_cf8)) + pci = pci->next; + + /* We just fill the ioreq, hvm_send_assist_req will send the request */ + if (unlikely(pci == NULL)) + { + *val = ~0; + rc = X86EMUL_OKAY; + goto end_handle; + } + + p->type = IOREQ_TYPE_PCI_CONFIG; + p->addr = (pci_cf8 & ~3) + (p->addr & 3); + + set_ioreq(v, &pci->server->ioreq, p); + +end_handle: + spin_unlock(&v->domain->arch.hvm_domain.pci_root.pci_lock); + return rc; +} + +int hvm_register_pcidev(domid_t domid, unsigned int id, u16 bdf) +{ + struct domain *d; + struct hvm_ioreq_server *s; + struct pci_device_emul *x; + int rc = 0; + + rc = rcu_lock_target_domain_by_id(domid, &d); + + if (rc != 0) + return rc; + + if (!is_hvm_domain(d)) + { + rcu_unlock_domain(d); + return -EINVAL; + } + + /* Search server */ + spin_lock(&d->arch.hvm_domain.ioreq_server_lock); + s = d->arch.hvm_domain.ioreq_server_list; + while ((s != NULL) && (s->id != id)) + s = s->next; + + if (s == NULL) + { + dprintk(XENLOG_DEBUG, "Cannot find server\n"); + rc = -ENOENT; + goto create_end; + } + + spin_unlock(&d->arch.hvm_domain.ioreq_server_lock); + + spin_lock(&d->arch.hvm_domain.pci_root.pci_lock); + x = xmalloc(struct pci_device_emul); + + if (!x) + { + dprintk(XENLOG_DEBUG, "Cannot allocate pci\n"); + rc = -ENOMEM; + goto create_end; + } + + x->bdf = PCI_MASK_BDF(bdf); + x->server = s; + x->next = d->arch.hvm_domain.pci_root.pci; + d->arch.hvm_domain.pci_root.pci = x; + +create_end: + spin_unlock(&d->arch.hvm_domain.pci_root.pci_lock); + rcu_unlock_domain(d); + + return rc; +} + +int hvm_init_pci_emul(struct domain *d) +{ + struct pci_root_emul *root = &d->arch.hvm_domain.pci_root; + + spin_lock_init(&root->pci_lock); + + root->pci = NULL; + + /* Register the config space handler */ + register_portio_handler(d, 0xcf8, 8, handle_config_space); + + return 0; +} + +void hvm_destroy_pci_emul(struct domain *d) +{ + struct pci_root_emul *root = &d->arch.hvm_domain.pci_root; + struct pci_device_emul *p; + + spin_lock(&root->pci_lock); + + while ( (p = root->pci) != NULL ) + { + root->pci = p->next; + xfree(p); + } + + spin_unlock(&root->pci_lock); +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ -- Julien Grall