From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Jan Beulich" Subject: [PATCH v2 3/3] pt-irq fixes and improvements Date: Wed, 04 Jun 2014 09:24:00 +0100 Message-ID: <538EF3C00200007800017A1C@mail.emea.novell.com> References: <538DEF42020000780001767A@mail.emea.novell.com> <538DF12A020000780001769C@mail.emea.novell.com> <538DE0C3.5010203@citrix.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=__PartD2E002B0.3__=" Return-path: Received: from mail6.bemta4.messagelabs.com ([85.158.143.247]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1Ws6UR-0002WI-US for xen-devel@lists.xenproject.org; Wed, 04 Jun 2014 08:24:08 +0000 In-Reply-To: <538DE0C3.5010203@citrix.com> 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 Cc: Kevin Tian , Keir Fraser , Andrew Cooper , Ian Jackson , Ian Campbell , Stefano Stabellini , Yang Z Zhang List-Id: xen-devel@lists.xenproject.org This is a MIME message. If you are reading this text, you may want to consider changing to a mail reader or gateway that understands how to properly handle MIME multipart messages. --=__PartD2E002B0.3__= Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Tools side: - don't silently ignore unrecognized PT_IRQ_TYPE_* values - respect that the interface type contains a union, making the code at once no longer depend on the hypervisor ignoring the bus field of the PCI portion of the interface structure) Hypervisor side: - don't ignore the PCI bus number passed in - don't store values (gsi, link) calculated from other stored values - avoid calling xfree() with a spin lock held where easily possible - have pt_irq_destroy_bind() respect the passed in type - scope reduction and constification of various variables - use switch instead of if/else-if chains - formatting Signed-off-by: Jan Beulich Reviewed-by: Andrew Cooper --- v2: A few extra coding style corrections according to Andrew's suggestions. --- a/tools/libxc/xc_domain.c +++ b/tools/libxc/xc_domain.c @@ -1702,16 +1702,21 @@ int xc_domain_bind_pt_irq( bind->hvm_domid =3D domid; bind->irq_type =3D irq_type; bind->machine_irq =3D machine_irq; - if ( irq_type =3D=3D PT_IRQ_TYPE_PCI || - irq_type =3D=3D PT_IRQ_TYPE_MSI_TRANSLATE ) + switch ( irq_type ) { + case PT_IRQ_TYPE_PCI: + case PT_IRQ_TYPE_MSI_TRANSLATE: bind->u.pci.bus =3D bus; - bind->u.pci.device =3D device; =20 + bind->u.pci.device =3D device; bind->u.pci.intx =3D intx; - }=20 - else if ( irq_type =3D=3D PT_IRQ_TYPE_ISA ) + case PT_IRQ_TYPE_ISA: bind->u.isa.isa_irq =3D isa_irq; - =20 + break; + default: + errno =3D EINVAL; + return -1; + } + rc =3D do_domctl(xch, &domctl); return rc; } @@ -1737,11 +1742,22 @@ int xc_domain_unbind_pt_irq( bind->hvm_domid =3D domid; bind->irq_type =3D irq_type; bind->machine_irq =3D machine_irq; - bind->u.pci.bus =3D bus; - bind->u.pci.device =3D device; =20 - bind->u.pci.intx =3D intx; - bind->u.isa.isa_irq =3D isa_irq; - =20 + switch ( irq_type ) + { + case PT_IRQ_TYPE_PCI: + case PT_IRQ_TYPE_MSI_TRANSLATE: + bind->u.pci.bus =3D bus; + bind->u.pci.device =3D device; + bind->u.pci.intx =3D intx; + break; + case PT_IRQ_TYPE_ISA: + bind->u.isa.isa_irq =3D isa_irq; + break; + default: + errno =3D EINVAL; + return -1; + } + rc =3D do_domctl(xch, &domctl); return rc; } --- a/xen/arch/x86/physdev.c +++ b/xen/arch/x86/physdev.c @@ -37,9 +37,8 @@ static int physdev_hvm_map_pirq( switch ( type ) { case MAP_PIRQ_TYPE_GSI: { - struct hvm_irq_dpci *hvm_irq_dpci; - struct hvm_girq_dpci_mapping *girq; - uint32_t machine_gsi =3D 0; + const struct hvm_irq_dpci *hvm_irq_dpci; + unsigned int machine_gsi =3D 0; =20 if ( *index < 0 || *index >=3D NR_HVM_IRQS ) { @@ -52,6 +51,8 @@ static int physdev_hvm_map_pirq( hvm_irq_dpci =3D domain_get_irq_dpci(d); if ( hvm_irq_dpci ) { + const struct hvm_girq_dpci_mapping *girq; + BUILD_BUG_ON(ARRAY_SIZE(hvm_irq_dpci->girq) < NR_HVM_IRQS); list_for_each_entry ( girq, &hvm_irq_dpci->girq[*index], --- a/xen/drivers/passthrough/io.c +++ b/xen/drivers/passthrough/io.c @@ -51,11 +51,8 @@ static int pt_irq_guest_eoi(struct domai static void pt_irq_time_out(void *data) { struct hvm_pirq_dpci *irq_map =3D data; - unsigned int guest_gsi; - struct hvm_irq_dpci *dpci =3D NULL; - struct dev_intx_gsi_link *digl; - struct hvm_girq_dpci_mapping *girq; - uint32_t device, intx; + const struct hvm_irq_dpci *dpci; + const struct dev_intx_gsi_link *digl; =20 spin_lock(&irq_map->dom->event_lock); =20 @@ -63,16 +60,16 @@ static void pt_irq_time_out(void *data) ASSERT(dpci); list_for_each_entry ( digl, &irq_map->digl_list, list ) { - guest_gsi =3D digl->gsi; + unsigned int guest_gsi =3D hvm_pci_intx_gsi(digl->device, = digl->intx); + const struct hvm_girq_dpci_mapping *girq; + list_for_each_entry ( girq, &dpci->girq[guest_gsi], list ) { struct pirq *pirq =3D pirq_info(irq_map->dom, girq->machine_gs= i); =20 pirq_dpci(pirq)->flags |=3D HVM_IRQ_DPCI_EOI_LATCH; } - device =3D digl->device; - intx =3D digl->intx; - hvm_pci_intx_deassert(irq_map->dom, device, intx); + hvm_pci_intx_deassert(irq_map->dom, digl->device, digl->intx); } =20 pt_pirq_iterate(irq_map->dom, pt_irq_guest_eoi, NULL); @@ -96,13 +93,9 @@ void free_hvm_irq_dpci(struct hvm_irq_dp int pt_irq_create_bind( struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind) { - struct hvm_irq_dpci *hvm_irq_dpci =3D NULL; + struct hvm_irq_dpci *hvm_irq_dpci; struct hvm_pirq_dpci *pirq_dpci; struct pirq *info; - uint32_t guest_gsi; - uint32_t device, intx, link; - struct dev_intx_gsi_link *digl; - struct hvm_girq_dpci_mapping *girq; int rc, pirq =3D pt_irq_bind->machine_irq; =20 if ( pirq < 0 || pirq >=3D d->nr_pirqs ) @@ -113,6 +106,8 @@ int pt_irq_create_bind( hvm_irq_dpci =3D domain_get_irq_dpci(d); if ( hvm_irq_dpci =3D=3D NULL ) { + unsigned int i; + hvm_irq_dpci =3D xzalloc(struct hvm_irq_dpci); if ( hvm_irq_dpci =3D=3D NULL ) { @@ -122,7 +117,7 @@ int pt_irq_create_bind( softirq_tasklet_init( &hvm_irq_dpci->dirq_tasklet, hvm_dirq_assist, (unsigned long)d); - for ( int i =3D 0; i < NR_HVM_IRQS; i++ ) + for ( i =3D 0; i < NR_HVM_IRQS; i++ ) INIT_LIST_HEAD(&hvm_irq_dpci->girq[i]); =20 d->arch.hvm_domain.irq.dpci =3D hvm_irq_dpci; @@ -136,7 +131,9 @@ int pt_irq_create_bind( } pirq_dpci =3D pirq_dpci(info); =20 - if ( pt_irq_bind->irq_type =3D=3D PT_IRQ_TYPE_MSI ) + switch ( pt_irq_bind->irq_type ) + { + case PT_IRQ_TYPE_MSI: { uint8_t dest, dest_mode; int dest_vcpu_id; @@ -169,15 +166,16 @@ int pt_irq_create_bind( { uint32_t mask =3D HVM_IRQ_DPCI_MACH_MSI | HVM_IRQ_DPCI_GUEST_M= SI; =20 - if ( (pirq_dpci->flags & mask) !=3D mask) + if ( (pirq_dpci->flags & mask) !=3D mask ) { - spin_unlock(&d->event_lock); - return -EBUSY; + spin_unlock(&d->event_lock); + return -EBUSY; } =20 - /* if pirq is already mapped as vmsi, update the guest = data/addr */ + /* If pirq is already mapped as vmsi, update guest data/addr. = */ if ( pirq_dpci->gmsi.gvec !=3D pt_irq_bind->u.msi.gvec || - pirq_dpci->gmsi.gflags !=3D pt_irq_bind->u.msi.gflags) { + pirq_dpci->gmsi.gflags !=3D pt_irq_bind->u.msi.gflags ) + { /* Directly clear pending EOIs before enabling new MSI = info. */ pirq_guest_eoi(info); =20 @@ -185,7 +183,7 @@ int pt_irq_create_bind( pirq_dpci->gmsi.gflags =3D pt_irq_bind->u.msi.gflags; } } - /* Caculate dest_vcpu_id for MSI-type pirq migration */ + /* Calculate dest_vcpu_id for MSI-type pirq migration. */ dest =3D pirq_dpci->gmsi.gflags & VMSI_DEST_ID_MASK; dest_mode =3D !!(pirq_dpci->gmsi.gflags & VMSI_DM_MASK); dest_vcpu_id =3D hvm_girq_dest_2_vcpu_id(d, dest, dest_mode); @@ -193,36 +191,37 @@ int pt_irq_create_bind( spin_unlock(&d->event_lock); if ( dest_vcpu_id >=3D 0 ) hvm_migrate_pirqs(d->vcpu[dest_vcpu_id]); + break; } - else + + case PT_IRQ_TYPE_PCI: + case PT_IRQ_TYPE_MSI_TRANSLATE: { - device =3D pt_irq_bind->u.pci.device; - intx =3D pt_irq_bind->u.pci.intx; - guest_gsi =3D hvm_pci_intx_gsi(device, intx); - link =3D hvm_pci_intx_link(device, intx); - hvm_irq_dpci->link_cnt[link]++; + unsigned int bus =3D pt_irq_bind->u.pci.bus; + unsigned int device =3D pt_irq_bind->u.pci.device; + unsigned int intx =3D pt_irq_bind->u.pci.intx; + unsigned int guest_gsi =3D hvm_pci_intx_gsi(device, intx); + unsigned int link =3D hvm_pci_intx_link(device, intx); + struct dev_intx_gsi_link *digl =3D xmalloc(struct dev_intx_gsi_lin= k); + struct hvm_girq_dpci_mapping *girq =3D + xmalloc(struct hvm_girq_dpci_mapping); =20 - digl =3D xmalloc(struct dev_intx_gsi_link); - if ( !digl ) + if ( !digl || !girq ) { spin_unlock(&d->event_lock); - return -ENOMEM; - } - - girq =3D xmalloc(struct hvm_girq_dpci_mapping); - if ( !girq ) - { + xfree(girq); xfree(digl); - spin_unlock(&d->event_lock); return -ENOMEM; } =20 + hvm_irq_dpci->link_cnt[link]++; + + digl->bus =3D bus; digl->device =3D device; digl->intx =3D intx; - digl->gsi =3D guest_gsi; - digl->link =3D link; list_add_tail(&digl->list, &pirq_dpci->digl_list); =20 + girq->bus =3D bus; girq->device =3D device; girq->intx =3D intx; girq->machine_gsi =3D pirq; @@ -261,12 +260,12 @@ int pt_irq_create_bind( kill_timer(&pirq_dpci->timer); pirq_dpci->dom =3D NULL; list_del(&girq->list); - xfree(girq); list_del(&digl->list); hvm_irq_dpci->link_cnt[link]--; pirq_dpci->flags =3D 0; pirq_cleanup_check(info, d); spin_unlock(&d->event_lock); + xfree(girq); xfree(digl); return rc; } @@ -276,33 +275,51 @@ int pt_irq_create_bind( =20 if ( iommu_verbose ) dprintk(XENLOG_G_INFO, - "d%d: bind: m_gsi=3D%u g_gsi=3D%u device=3D%u = intx=3D%u\n", - d->domain_id, pirq, guest_gsi, device, intx); + "d%d: bind: m_gsi=3D%u g_gsi=3D%u dev=3D%02x.%02x.%u = intx=3D%u\n", + d->domain_id, pirq, guest_gsi, bus, + PCI_SLOT(device), PCI_FUNC(device), intx); + break; } + + default: + spin_unlock(&d->event_lock); + return -EOPNOTSUPP; + } + return 0; } =20 int pt_irq_destroy_bind( struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind) { - struct hvm_irq_dpci *hvm_irq_dpci =3D NULL; + struct hvm_irq_dpci *hvm_irq_dpci; struct hvm_pirq_dpci *pirq_dpci; - uint32_t machine_gsi, guest_gsi; - uint32_t device, intx, link; + unsigned int machine_gsi =3D pt_irq_bind->machine_irq; + unsigned int bus =3D pt_irq_bind->u.pci.bus; + unsigned int device =3D pt_irq_bind->u.pci.device; + unsigned int intx =3D pt_irq_bind->u.pci.intx; + unsigned int guest_gsi =3D hvm_pci_intx_gsi(device, intx); + unsigned int link =3D hvm_pci_intx_link(device, intx); struct dev_intx_gsi_link *digl, *tmp; struct hvm_girq_dpci_mapping *girq; struct pirq *pirq; =20 - machine_gsi =3D pt_irq_bind->machine_irq; - device =3D pt_irq_bind->u.pci.device; - intx =3D pt_irq_bind->u.pci.intx; - guest_gsi =3D hvm_pci_intx_gsi(device, intx); - link =3D hvm_pci_intx_link(device, intx); + switch ( pt_irq_bind->irq_type ) + { + case PT_IRQ_TYPE_PCI: + case PT_IRQ_TYPE_MSI_TRANSLATE: + break; + case PT_IRQ_TYPE_MSI: + return 0; + default: + return -EOPNOTSUPP; + } =20 if ( iommu_verbose ) dprintk(XENLOG_G_INFO, - "d%d: unbind: m_gsi=3D%u g_gsi=3D%u device=3D%u intx=3D%u\= n", - d->domain_id, machine_gsi, guest_gsi, device, intx); + "d%d: unbind: m_gsi=3D%u g_gsi=3D%u dev=3D%02x:%02x.%u = intx=3D%u\n", + d->domain_id, machine_gsi, guest_gsi, bus, + PCI_SLOT(device), PCI_FUNC(device), intx); =20 spin_lock(&d->event_lock); =20 @@ -314,18 +331,28 @@ int pt_irq_destroy_bind( return -EINVAL; } =20 - hvm_irq_dpci->link_cnt[link]--; - list_for_each_entry ( girq, &hvm_irq_dpci->girq[guest_gsi], list ) { - if ( girq->machine_gsi =3D=3D machine_gsi ) + if ( girq->bus =3D=3D bus && + girq->device =3D=3D device && + girq->intx =3D=3D intx && + girq->machine_gsi =3D=3D machine_gsi ) { - list_del(&girq->list); - xfree(girq); - break; + list_del(&girq->list); + xfree(girq); + girq =3D NULL; + break; } } =20 + if ( girq ) + { + spin_unlock(&d->event_lock); + return -EINVAL; + } + + hvm_irq_dpci->link_cnt[link]--; + pirq =3D pirq_info(d, machine_gsi); pirq_dpci =3D pirq_dpci(pirq); =20 @@ -334,10 +361,9 @@ int pt_irq_destroy_bind( { list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list = ) { - if ( digl->device =3D=3D device && - digl->intx =3D=3D intx && - digl->link =3D=3D link && - digl->gsi =3D=3D guest_gsi ) + if ( digl->bus =3D=3D bus && + digl->device =3D=3D device && + digl->intx =3D=3D intx ) { list_del(&digl->list); xfree(digl); @@ -359,8 +385,9 @@ int pt_irq_destroy_bind( =20 if ( iommu_verbose ) dprintk(XENLOG_G_INFO, - "d%d unmap: m_irq=3D%u device=3D%u intx=3D%u\n", - d->domain_id, machine_gsi, device, intx); + "d%d unmap: m_irq=3D%u dev=3D%02x:%02x.%u intx=3D%u\n", + d->domain_id, machine_gsi, bus, + PCI_SLOT(device), PCI_FUNC(device), intx); =20 return 0; } @@ -481,11 +508,10 @@ static void hvm_pci_msi_assert( static int _hvm_dirq_assist(struct domain *d, struct hvm_pirq_dpci = *pirq_dpci, void *arg) { - uint32_t device, intx; - struct dev_intx_gsi_link *digl; - if ( test_and_clear_bool(pirq_dpci->masked) ) { + const struct dev_intx_gsi_link *digl; + if ( pirq_dpci->flags & HVM_IRQ_DPCI_GUEST_MSI ) { hvm_pci_msi_assert(d, pirq_dpci); @@ -496,12 +522,10 @@ static int _hvm_dirq_assist(struct domai { struct pirq *info =3D dpci_pirq(pirq_dpci); =20 - device =3D digl->device; - intx =3D digl->intx; if ( hvm_domain_use_pirq(d, info) ) send_guest_pirq(d, info); else - hvm_pci_intx_assert(d, device, intx); + hvm_pci_intx_assert(d, digl->device, digl->intx); pirq_dpci->pending++; =20 if ( pirq_dpci->flags & HVM_IRQ_DPCI_TRANSLATE ) @@ -537,16 +561,13 @@ static void hvm_dirq_assist(unsigned lon } =20 static void __hvm_dpci_eoi(struct domain *d, - struct hvm_girq_dpci_mapping *girq, - union vioapic_redir_entry *ent) + const struct hvm_girq_dpci_mapping *girq, + const union vioapic_redir_entry *ent) { - uint32_t device, intx; struct pirq *pirq; struct hvm_pirq_dpci *pirq_dpci; =20 - device =3D girq->device; - intx =3D girq->intx; - hvm_pci_intx_deassert(d, device, intx); + hvm_pci_intx_deassert(d, girq->device, girq->intx); =20 pirq =3D pirq_info(d, girq->machine_gsi); pirq_dpci =3D pirq_dpci(pirq); @@ -556,8 +577,8 @@ static void __hvm_dpci_eoi(struct domain * since interrupt is still not EOIed */ if ( --pirq_dpci->pending || - ( ent && ent->fields.mask ) || - ! pt_irq_need_timer(pirq_dpci->flags) ) + (ent && ent->fields.mask) || + !pt_irq_need_timer(pirq_dpci->flags) ) return; =20 stop_timer(&pirq_dpci->timer); @@ -565,10 +586,10 @@ static void __hvm_dpci_eoi(struct domain } =20 void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi, - union vioapic_redir_entry *ent) + const union vioapic_redir_entry *ent) { - struct hvm_irq_dpci *hvm_irq_dpci; - struct hvm_girq_dpci_mapping *girq; + const struct hvm_irq_dpci *hvm_irq_dpci; + const struct hvm_girq_dpci_mapping *girq; =20 if ( !iommu_enabled ) return; --- a/xen/drivers/passthrough/vtd/x86/vtd.c +++ b/xen/drivers/passthrough/vtd/x86/vtd.c @@ -69,11 +69,13 @@ static int _hvm_dpci_isairq_eoi(struct d { struct hvm_irq *hvm_irq =3D &d->arch.hvm_domain.irq; unsigned int isairq =3D (long)arg; - struct dev_intx_gsi_link *digl, *tmp; + const struct dev_intx_gsi_link *digl; =20 - list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list ) + list_for_each_entry ( digl, &pirq_dpci->digl_list, list ) { - if ( hvm_irq->pci_link.route[digl->link] =3D=3D isairq ) + unsigned int link =3D hvm_pci_intx_link(digl->device, digl->intx);= + + if ( hvm_irq->pci_link.route[link] =3D=3D isairq ) { hvm_pci_intx_deassert(d, digl->device, digl->intx); if ( --pirq_dpci->pending =3D=3D 0 ) --- a/xen/include/asm-x86/hvm/io.h +++ b/xen/include/asm-x86/hvm/io.h @@ -123,7 +123,7 @@ int handle_pio(uint16_t port, unsigned i void hvm_interrupt_post(struct vcpu *v, int vector, int type); void hvm_io_assist(ioreq_t *p); void hvm_dpci_eoi(struct domain *d, unsigned int guest_irq, - union vioapic_redir_entry *ent); + const union vioapic_redir_entry *ent); void msix_write_completion(struct vcpu *); =20 struct hvm_hw_stdvga { --- a/xen/include/xen/hvm/irq.h +++ b/xen/include/xen/hvm/irq.h @@ -30,10 +30,9 @@ =20 struct dev_intx_gsi_link { struct list_head list; + uint8_t bus; uint8_t device; uint8_t intx; - uint8_t gsi; - uint8_t link; }; =20 #define _HVM_IRQ_DPCI_MACH_PCI_SHIFT 0 @@ -69,6 +68,7 @@ struct hvm_gmsi_info { =20 struct hvm_girq_dpci_mapping { struct list_head list; + uint8_t bus; uint8_t device; uint8_t intx; uint8_t machine_gsi; --=__PartD2E002B0.3__= Content-Type: text/plain; name="pt-irq-binding.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="pt-irq-binding.patch" pt-irq fixes and improvements=0A=0ATools side:=0A- don't silently ignore = unrecognized PT_IRQ_TYPE_* values=0A- respect that the interface type = contains a union, making the code at=0A once no longer depend on the = hypervisor ignoring the bus field of the=0A PCI portion of the interface = structure)=0A=0AHypervisor side:=0A- don't ignore the PCI bus number = passed in=0A- don't store values (gsi, link) calculated from other stored = values=0A- avoid calling xfree() with a spin lock held where easily = possible=0A- have pt_irq_destroy_bind() respect the passed in type=0A- = scope reduction and constification of various variables=0A- use switch = instead of if/else-if chains=0A- formatting=0A=0ASigned-off-by: Jan = Beulich =0AReviewed-by: Andrew Cooper =0A---=0Av2: A few extra coding style corrections according to = Andrew's=0A suggestions.=0A=0A--- a/tools/libxc/xc_domain.c=0A+++ = b/tools/libxc/xc_domain.c=0A@@ -1702,16 +1702,21 @@ int xc_domain_bind_pt_i= rq(=0A bind->hvm_domid =3D domid;=0A bind->irq_type =3D = irq_type;=0A bind->machine_irq =3D machine_irq;=0A- if ( irq_type = =3D=3D PT_IRQ_TYPE_PCI ||=0A- irq_type =3D=3D PT_IRQ_TYPE_MSI_TRANS= LATE )=0A+ switch ( irq_type )=0A {=0A+ case PT_IRQ_TYPE_PCI:=0A+= case PT_IRQ_TYPE_MSI_TRANSLATE:=0A bind->u.pci.bus =3D = bus;=0A- bind->u.pci.device =3D device; =0A+ bind->u.pci.d= evice =3D device;=0A bind->u.pci.intx =3D intx;=0A- } =0A- = else if ( irq_type =3D=3D PT_IRQ_TYPE_ISA )=0A+ case PT_IRQ_TYPE_ISA:=0A= bind->u.isa.isa_irq =3D isa_irq;=0A- =0A+ break;=0A+ = default:=0A+ errno =3D EINVAL;=0A+ return -1;=0A+ = }=0A+=0A rc =3D do_domctl(xch, &domctl);=0A return rc;=0A }=0A@@ = -1737,11 +1742,22 @@ int xc_domain_unbind_pt_irq(=0A bind->hvm_domid = =3D domid;=0A bind->irq_type =3D irq_type;=0A bind->machine_irq = =3D machine_irq;=0A- bind->u.pci.bus =3D bus;=0A- bind->u.pci.device = =3D device; =0A- bind->u.pci.intx =3D intx;=0A- bind->u.isa.isa_ir= q =3D isa_irq;=0A- =0A+ switch ( irq_type )=0A+ {=0A+ case = PT_IRQ_TYPE_PCI:=0A+ case PT_IRQ_TYPE_MSI_TRANSLATE:=0A+ = bind->u.pci.bus =3D bus;=0A+ bind->u.pci.device =3D device;=0A+ = bind->u.pci.intx =3D intx;=0A+ break;=0A+ case PT_IRQ_TYPE_ISA= :=0A+ bind->u.isa.isa_irq =3D isa_irq;=0A+ break;=0A+ = default:=0A+ errno =3D EINVAL;=0A+ return -1;=0A+ = }=0A+=0A rc =3D do_domctl(xch, &domctl);=0A return rc;=0A }=0A--- = a/xen/arch/x86/physdev.c=0A+++ b/xen/arch/x86/physdev.c=0A@@ -37,9 +37,8 = @@ static int physdev_hvm_map_pirq(=0A switch ( type )=0A {=0A = case MAP_PIRQ_TYPE_GSI: {=0A- struct hvm_irq_dpci *hvm_irq_dpci;=0A-= struct hvm_girq_dpci_mapping *girq;=0A- uint32_t machine_gsi= =3D 0;=0A+ const struct hvm_irq_dpci *hvm_irq_dpci;=0A+ = unsigned int machine_gsi =3D 0;=0A =0A if ( *index < 0 || *index = >=3D NR_HVM_IRQS )=0A {=0A@@ -52,6 +51,8 @@ static int physdev_hvm_= map_pirq(=0A hvm_irq_dpci =3D domain_get_irq_dpci(d);=0A = if ( hvm_irq_dpci )=0A {=0A+ const struct hvm_girq_dpci_= mapping *girq;=0A+=0A BUILD_BUG_ON(ARRAY_SIZE(hvm_irq_dpci->gir= q) < NR_HVM_IRQS);=0A list_for_each_entry ( girq,=0A = &hvm_irq_dpci->girq[*index],=0A--- a/xen/drivers/pa= ssthrough/io.c=0A+++ b/xen/drivers/passthrough/io.c=0A@@ -51,11 +51,8 @@ = static int pt_irq_guest_eoi(struct domai=0A static void pt_irq_time_out(voi= d *data)=0A {=0A struct hvm_pirq_dpci *irq_map =3D data;=0A- = unsigned int guest_gsi;=0A- struct hvm_irq_dpci *dpci =3D NULL;=0A- = struct dev_intx_gsi_link *digl;=0A- struct hvm_girq_dpci_mapping = *girq;=0A- uint32_t device, intx;=0A+ const struct hvm_irq_dpci = *dpci;=0A+ const struct dev_intx_gsi_link *digl;=0A =0A spin_lock(&i= rq_map->dom->event_lock);=0A =0A@@ -63,16 +60,16 @@ static void pt_irq_time= _out(void *data)=0A ASSERT(dpci);=0A list_for_each_entry ( digl, = &irq_map->digl_list, list )=0A {=0A- guest_gsi =3D digl->gsi;=0A= + unsigned int guest_gsi =3D hvm_pci_intx_gsi(digl->device, = digl->intx);=0A+ const struct hvm_girq_dpci_mapping *girq;=0A+=0A = list_for_each_entry ( girq, &dpci->girq[guest_gsi], list )=0A = {=0A struct pirq *pirq =3D pirq_info(irq_map->dom, girq->machi= ne_gsi);=0A =0A pirq_dpci(pirq)->flags |=3D HVM_IRQ_DPCI_EOI_LA= TCH;=0A }=0A- device =3D digl->device;=0A- intx =3D = digl->intx;=0A- hvm_pci_intx_deassert(irq_map->dom, device, = intx);=0A+ hvm_pci_intx_deassert(irq_map->dom, digl->device, = digl->intx);=0A }=0A =0A pt_pirq_iterate(irq_map->dom, pt_irq_guest= _eoi, NULL);=0A@@ -96,13 +93,9 @@ void free_hvm_irq_dpci(struct hvm_irq_dp= =0A int pt_irq_create_bind(=0A struct domain *d, xen_domctl_bind_pt_irq= _t *pt_irq_bind)=0A {=0A- struct hvm_irq_dpci *hvm_irq_dpci =3D = NULL;=0A+ struct hvm_irq_dpci *hvm_irq_dpci;=0A struct hvm_pirq_dpci= *pirq_dpci;=0A struct pirq *info;=0A- uint32_t guest_gsi;=0A- = uint32_t device, intx, link;=0A- struct dev_intx_gsi_link *digl;=0A- = struct hvm_girq_dpci_mapping *girq;=0A int rc, pirq =3D pt_irq_bind->ma= chine_irq;=0A =0A if ( pirq < 0 || pirq >=3D d->nr_pirqs )=0A@@ -113,6 = +106,8 @@ int pt_irq_create_bind(=0A hvm_irq_dpci =3D domain_get_irq_dp= ci(d);=0A if ( hvm_irq_dpci =3D=3D NULL )=0A {=0A+ unsigned = int i;=0A+=0A hvm_irq_dpci =3D xzalloc(struct hvm_irq_dpci);=0A = if ( hvm_irq_dpci =3D=3D NULL )=0A {=0A@@ -122,7 +117,7 @@ = int pt_irq_create_bind(=0A softirq_tasklet_init(=0A = &hvm_irq_dpci->dirq_tasklet,=0A hvm_dirq_assist, (unsigned = long)d);=0A- for ( int i =3D 0; i < NR_HVM_IRQS; i++ )=0A+ = for ( i =3D 0; i < NR_HVM_IRQS; i++ )=0A INIT_LIST_HEAD(&hvm_ir= q_dpci->girq[i]);=0A =0A d->arch.hvm_domain.irq.dpci =3D hvm_irq_dp= ci;=0A@@ -136,7 +131,9 @@ int pt_irq_create_bind(=0A }=0A = pirq_dpci =3D pirq_dpci(info);=0A =0A- if ( pt_irq_bind->irq_type = =3D=3D PT_IRQ_TYPE_MSI )=0A+ switch ( pt_irq_bind->irq_type )=0A+ = {=0A+ case PT_IRQ_TYPE_MSI:=0A {=0A uint8_t dest, dest_mode;= =0A int dest_vcpu_id;=0A@@ -169,15 +166,16 @@ int pt_irq_create_bin= d(=0A {=0A uint32_t mask =3D HVM_IRQ_DPCI_MACH_MSI | = HVM_IRQ_DPCI_GUEST_MSI;=0A =0A- if ( (pirq_dpci->flags & mask) = !=3D mask)=0A+ if ( (pirq_dpci->flags & mask) !=3D mask )=0A = {=0A- spin_unlock(&d->event_lock);=0A- = return -EBUSY;=0A+ spin_unlock(&d->event_lock);=0A+ = return -EBUSY;=0A }=0A =0A- /* if pirq is = already mapped as vmsi, update the guest data/addr */=0A+ /* If = pirq is already mapped as vmsi, update guest data/addr. */=0A = if ( pirq_dpci->gmsi.gvec !=3D pt_irq_bind->u.msi.gvec ||=0A- = pirq_dpci->gmsi.gflags !=3D pt_irq_bind->u.msi.gflags) {=0A+ = pirq_dpci->gmsi.gflags !=3D pt_irq_bind->u.msi.gflags )=0A+ = {=0A /* Directly clear pending EOIs before enabling new = MSI info. */=0A pirq_guest_eoi(info);=0A =0A@@ -185,7 = +183,7 @@ int pt_irq_create_bind(=0A pirq_dpci->gmsi.gflags= =3D pt_irq_bind->u.msi.gflags;=0A }=0A }=0A- = /* Caculate dest_vcpu_id for MSI-type pirq migration */=0A+ /* = Calculate dest_vcpu_id for MSI-type pirq migration. */=0A dest =3D = pirq_dpci->gmsi.gflags & VMSI_DEST_ID_MASK;=0A dest_mode =3D = !!(pirq_dpci->gmsi.gflags & VMSI_DM_MASK);=0A dest_vcpu_id =3D = hvm_girq_dest_2_vcpu_id(d, dest, dest_mode);=0A@@ -193,36 +191,37 @@ int = pt_irq_create_bind(=0A spin_unlock(&d->event_lock);=0A if = ( dest_vcpu_id >=3D 0 )=0A hvm_migrate_pirqs(d->vcpu[dest_vcpu_= id]);=0A+ break;=0A }=0A- else=0A+=0A+ case PT_IRQ_TYPE_PC= I:=0A+ case PT_IRQ_TYPE_MSI_TRANSLATE:=0A {=0A- device =3D = pt_irq_bind->u.pci.device;=0A- intx =3D pt_irq_bind->u.pci.intx;=0A-= guest_gsi =3D hvm_pci_intx_gsi(device, intx);=0A- link =3D = hvm_pci_intx_link(device, intx);=0A- hvm_irq_dpci->link_cnt[link]++;= =0A+ unsigned int bus =3D pt_irq_bind->u.pci.bus;=0A+ = unsigned int device =3D pt_irq_bind->u.pci.device;=0A+ unsigned int = intx =3D pt_irq_bind->u.pci.intx;=0A+ unsigned int guest_gsi =3D = hvm_pci_intx_gsi(device, intx);=0A+ unsigned int link =3D hvm_pci_in= tx_link(device, intx);=0A+ struct dev_intx_gsi_link *digl =3D = xmalloc(struct dev_intx_gsi_link);=0A+ struct hvm_girq_dpci_mapping = *girq =3D=0A+ xmalloc(struct hvm_girq_dpci_mapping);=0A =0A- = digl =3D xmalloc(struct dev_intx_gsi_link);=0A- if ( !digl = )=0A+ if ( !digl || !girq )=0A {=0A spin_unlock(= &d->event_lock);=0A- return -ENOMEM;=0A- }=0A-=0A- = girq =3D xmalloc(struct hvm_girq_dpci_mapping);=0A- if ( !girq = )=0A- {=0A+ xfree(girq);=0A xfree(digl);=0A- = spin_unlock(&d->event_lock);=0A return -ENOMEM;=0A = }=0A =0A+ hvm_irq_dpci->link_cnt[link]++;=0A+=0A+ = digl->bus =3D bus;=0A digl->device =3D device;=0A = digl->intx =3D intx;=0A- digl->gsi =3D guest_gsi;=0A- = digl->link =3D link;=0A list_add_tail(&digl->list, &pirq_dpci->digl= _list);=0A =0A+ girq->bus =3D bus;=0A girq->device =3D = device;=0A girq->intx =3D intx;=0A girq->machine_gsi =3D = pirq;=0A@@ -261,12 +260,12 @@ int pt_irq_create_bind(=0A = kill_timer(&pirq_dpci->timer);=0A pirq_dpci->dom =3D = NULL;=0A list_del(&girq->list);=0A- = xfree(girq);=0A list_del(&digl->list);=0A = hvm_irq_dpci->link_cnt[link]--;=0A pirq_dpci->flags =3D = 0;=0A pirq_cleanup_check(info, d);=0A = spin_unlock(&d->event_lock);=0A+ xfree(girq);=0A = xfree(digl);=0A return rc;=0A }=0A@@ = -276,33 +275,51 @@ int pt_irq_create_bind(=0A =0A if ( iommu_verbos= e )=0A dprintk(XENLOG_G_INFO,=0A- "d%d: = bind: m_gsi=3D%u g_gsi=3D%u device=3D%u intx=3D%u\n",=0A- = d->domain_id, pirq, guest_gsi, device, intx);=0A+ = "d%d: bind: m_gsi=3D%u g_gsi=3D%u dev=3D%02x.%02x.%u intx=3D%u\n",=0A+ = d->domain_id, pirq, guest_gsi, bus,=0A+ = PCI_SLOT(device), PCI_FUNC(device), intx);=0A+ break;=0A = }=0A+=0A+ default:=0A+ spin_unlock(&d->event_lock);=0A+ = return -EOPNOTSUPP;=0A+ }=0A+=0A return 0;=0A }=0A =0A int = pt_irq_destroy_bind(=0A struct domain *d, xen_domctl_bind_pt_irq_t = *pt_irq_bind)=0A {=0A- struct hvm_irq_dpci *hvm_irq_dpci =3D NULL;=0A+ = struct hvm_irq_dpci *hvm_irq_dpci;=0A struct hvm_pirq_dpci *pirq_dpci= ;=0A- uint32_t machine_gsi, guest_gsi;=0A- uint32_t device, intx, = link;=0A+ unsigned int machine_gsi =3D pt_irq_bind->machine_irq;=0A+ = unsigned int bus =3D pt_irq_bind->u.pci.bus;=0A+ unsigned int device = =3D pt_irq_bind->u.pci.device;=0A+ unsigned int intx =3D pt_irq_bind->u.= pci.intx;=0A+ unsigned int guest_gsi =3D hvm_pci_intx_gsi(device, = intx);=0A+ unsigned int link =3D hvm_pci_intx_link(device, intx);=0A = struct dev_intx_gsi_link *digl, *tmp;=0A struct hvm_girq_dpci_mapping = *girq;=0A struct pirq *pirq;=0A =0A- machine_gsi =3D pt_irq_bind->ma= chine_irq;=0A- device =3D pt_irq_bind->u.pci.device;=0A- intx =3D = pt_irq_bind->u.pci.intx;=0A- guest_gsi =3D hvm_pci_intx_gsi(device, = intx);=0A- link =3D hvm_pci_intx_link(device, intx);=0A+ switch ( = pt_irq_bind->irq_type )=0A+ {=0A+ case PT_IRQ_TYPE_PCI:=0A+ case = PT_IRQ_TYPE_MSI_TRANSLATE:=0A+ break;=0A+ case PT_IRQ_TYPE_MSI:= =0A+ return 0;=0A+ default:=0A+ return -EOPNOTSUPP;=0A+ = }=0A =0A if ( iommu_verbose )=0A dprintk(XENLOG_G_INFO,=0A- = "d%d: unbind: m_gsi=3D%u g_gsi=3D%u device=3D%u intx=3D%u\n",= =0A- d->domain_id, machine_gsi, guest_gsi, device, = intx);=0A+ "d%d: unbind: m_gsi=3D%u g_gsi=3D%u dev=3D%02x:%0= 2x.%u intx=3D%u\n",=0A+ d->domain_id, machine_gsi, = guest_gsi, bus,=0A+ PCI_SLOT(device), PCI_FUNC(device), = intx);=0A =0A spin_lock(&d->event_lock);=0A =0A@@ -314,18 +331,28 @@ = int pt_irq_destroy_bind(=0A return -EINVAL;=0A }=0A =0A- = hvm_irq_dpci->link_cnt[link]--;=0A-=0A list_for_each_entry ( girq, = &hvm_irq_dpci->girq[guest_gsi], list )=0A {=0A- if ( girq->machi= ne_gsi =3D=3D machine_gsi )=0A+ if ( girq->bus =3D=3D bus = &&=0A+ girq->device =3D=3D device &&=0A+ = girq->intx =3D=3D intx &&=0A+ girq->machine_gsi =3D=3D = machine_gsi )=0A {=0A- list_del(&girq->list);=0A- = xfree(girq);=0A- break;=0A+ = list_del(&girq->list);=0A+ xfree(girq);=0A+ girq =3D = NULL;=0A+ break;=0A }=0A }=0A =0A+ if ( girq = )=0A+ {=0A+ spin_unlock(&d->event_lock);=0A+ return = -EINVAL;=0A+ }=0A+=0A+ hvm_irq_dpci->link_cnt[link]--;=0A+=0A = pirq =3D pirq_info(d, machine_gsi);=0A pirq_dpci =3D pirq_dpci(pirq);= =0A =0A@@ -334,10 +361,9 @@ int pt_irq_destroy_bind(=0A {=0A = list_for_each_entry_safe ( digl, tmp, &pirq_dpci->digl_list, list )=0A = {=0A- if ( digl->device =3D=3D device &&=0A- = digl->intx =3D=3D intx &&=0A- digl->link =3D=3D link = &&=0A- digl->gsi =3D=3D guest_gsi )=0A+ if ( = digl->bus =3D=3D bus &&=0A+ digl->device =3D=3D device = &&=0A+ digl->intx =3D=3D intx )=0A {=0A = list_del(&digl->list);=0A xfree(digl);=0A@@ = -359,8 +385,9 @@ int pt_irq_destroy_bind(=0A =0A if ( iommu_verbose = )=0A dprintk(XENLOG_G_INFO,=0A- "d%d unmap: = m_irq=3D%u device=3D%u intx=3D%u\n",=0A- d->domain_id, = machine_gsi, device, intx);=0A+ "d%d unmap: m_irq=3D%u = dev=3D%02x:%02x.%u intx=3D%u\n",=0A+ d->domain_id, = machine_gsi, bus,=0A+ PCI_SLOT(device), PCI_FUNC(device), = intx);=0A =0A return 0;=0A }=0A@@ -481,11 +508,10 @@ static void = hvm_pci_msi_assert(=0A static int _hvm_dirq_assist(struct domain *d, = struct hvm_pirq_dpci *pirq_dpci,=0A void = *arg)=0A {=0A- uint32_t device, intx;=0A- struct dev_intx_gsi_link = *digl;=0A-=0A if ( test_and_clear_bool(pirq_dpci->masked) )=0A = {=0A+ const struct dev_intx_gsi_link *digl;=0A+=0A if ( = pirq_dpci->flags & HVM_IRQ_DPCI_GUEST_MSI )=0A {=0A = hvm_pci_msi_assert(d, pirq_dpci);=0A@@ -496,12 +522,10 @@ static int = _hvm_dirq_assist(struct domai=0A {=0A struct pirq = *info =3D dpci_pirq(pirq_dpci);=0A =0A- device =3D digl->device;= =0A- intx =3D digl->intx;=0A if ( hvm_domain_use_pir= q(d, info) )=0A send_guest_pirq(d, info);=0A = else=0A- hvm_pci_intx_assert(d, device, intx);=0A+ = hvm_pci_intx_assert(d, digl->device, digl->intx);=0A = pirq_dpci->pending++;=0A =0A if ( pirq_dpci->flags & HVM_IRQ_DP= CI_TRANSLATE )=0A@@ -537,16 +561,13 @@ static void hvm_dirq_assist(unsigned= lon=0A }=0A =0A static void __hvm_dpci_eoi(struct domain *d,=0A- = struct hvm_girq_dpci_mapping *girq,=0A- = union vioapic_redir_entry *ent)=0A+ = const struct hvm_girq_dpci_mapping *girq,=0A+ = const union vioapic_redir_entry *ent)=0A {=0A- uint32_t device, = intx;=0A struct pirq *pirq;=0A struct hvm_pirq_dpci *pirq_dpci;=0A = =0A- device =3D girq->device;=0A- intx =3D girq->intx;=0A- = hvm_pci_intx_deassert(d, device, intx);=0A+ hvm_pci_intx_deassert(d, = girq->device, girq->intx);=0A =0A pirq =3D pirq_info(d, girq->machine_g= si);=0A pirq_dpci =3D pirq_dpci(pirq);=0A@@ -556,8 +577,8 @@ static = void __hvm_dpci_eoi(struct domain=0A * since interrupt is still not = EOIed=0A */=0A if ( --pirq_dpci->pending ||=0A- ( ent && = ent->fields.mask ) ||=0A- ! pt_irq_need_timer(pirq_dpci->flags) = )=0A+ (ent && ent->fields.mask) ||=0A+ !pt_irq_need_timer(p= irq_dpci->flags) )=0A return;=0A =0A stop_timer(&pirq_dpci->tim= er);=0A@@ -565,10 +586,10 @@ static void __hvm_dpci_eoi(struct domain=0A = }=0A =0A void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi,=0A- = union vioapic_redir_entry *ent)=0A+ const = union vioapic_redir_entry *ent)=0A {=0A- struct hvm_irq_dpci *hvm_irq_dp= ci;=0A- struct hvm_girq_dpci_mapping *girq;=0A+ const struct = hvm_irq_dpci *hvm_irq_dpci;=0A+ const struct hvm_girq_dpci_mapping = *girq;=0A =0A if ( !iommu_enabled )=0A return;=0A--- a/xen/driv= ers/passthrough/vtd/x86/vtd.c=0A+++ b/xen/drivers/passthrough/vtd/x86/vtd.c= =0A@@ -69,11 +69,13 @@ static int _hvm_dpci_isairq_eoi(struct d=0A {=0A = struct hvm_irq *hvm_irq =3D &d->arch.hvm_domain.irq;=0A unsigned int = isairq =3D (long)arg;=0A- struct dev_intx_gsi_link *digl, *tmp;=0A+ = const struct dev_intx_gsi_link *digl;=0A =0A- list_for_each_entry_safe = ( digl, tmp, &pirq_dpci->digl_list, list )=0A+ list_for_each_entry ( = digl, &pirq_dpci->digl_list, list )=0A {=0A- if ( hvm_irq->pci_l= ink.route[digl->link] =3D=3D isairq )=0A+ unsigned int link =3D = hvm_pci_intx_link(digl->device, digl->intx);=0A+=0A+ if ( hvm_irq->p= ci_link.route[link] =3D=3D isairq )=0A {=0A hvm_pci_int= x_deassert(d, digl->device, digl->intx);=0A if ( --pirq_dpci->p= ending =3D=3D 0 )=0A--- a/xen/include/asm-x86/hvm/io.h=0A+++ b/xen/include/= asm-x86/hvm/io.h=0A@@ -123,7 +123,7 @@ int handle_pio(uint16_t port, = unsigned i=0A void hvm_interrupt_post(struct vcpu *v, int vector, int = type);=0A void hvm_io_assist(ioreq_t *p);=0A void hvm_dpci_eoi(struct = domain *d, unsigned int guest_irq,=0A- union vioapic_redir= _entry *ent);=0A+ const union vioapic_redir_entry = *ent);=0A void msix_write_completion(struct vcpu *);=0A =0A struct = hvm_hw_stdvga {=0A--- a/xen/include/xen/hvm/irq.h=0A+++ b/xen/include/xen/h= vm/irq.h=0A@@ -30,10 +30,9 @@=0A =0A struct dev_intx_gsi_link {=0A = struct list_head list;=0A+ uint8_t bus;=0A uint8_t device;=0A = uint8_t intx;=0A- uint8_t gsi;=0A- uint8_t link;=0A };=0A =0A = #define _HVM_IRQ_DPCI_MACH_PCI_SHIFT 0=0A@@ -69,6 +68,7 @@ = struct hvm_gmsi_info {=0A =0A struct hvm_girq_dpci_mapping {=0A struct = list_head list;=0A+ uint8_t bus;=0A uint8_t device;=0A uint8_t = intx;=0A uint8_t machine_gsi;=0A --=__PartD2E002B0.3__= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel --=__PartD2E002B0.3__=--