[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v4.1 3/4] x86/pt: enable binding of GSIs to a PVH Dom0
On Wed, Jun 07, 2017 at 07:17:16AM -0600, Jan Beulich wrote: > >>> On 02.06.17 at 15:58, <roger.pau@xxxxxxxxxx> wrote: > > --- a/xen/drivers/passthrough/io.c > > +++ b/xen/drivers/passthrough/io.c > > @@ -164,6 +164,25 @@ static void pt_irq_time_out(void *data) > > > > spin_lock(&irq_map->dom->event_lock); > > > > + if ( irq_map->flags & HVM_IRQ_DPCI_IDENTITY_GSI ) > > + { > > + struct pirq *pirq = dpci_pirq(irq_map); > > This could (and hence should) be const. However, ... > > > + ASSERT(is_hardware_domain(irq_map->dom)); > > + /* > > + * Identity mapped, no need to iterate over the guest GSI list to > > find > > + * other pirqs sharing the same guest GSI. > > + * > > + * In the identity mapped case the EOI can also be done now, this > > way > > + * the iteration over the list of domain pirqs is avoided. > > + */ > > + hvm_gsi_deassert(irq_map->dom, pirq->pirq); > > ... this is its only use, so I'm not convinced a local variable is > needed at all. Done, I've removed the local variable. > > @@ -274,10 +293,16 @@ int pt_irq_create_bind( > > spin_lock(&d->event_lock); > > > > hvm_irq_dpci = domain_get_irq_dpci(d); > > - if ( hvm_irq_dpci == NULL ) > > + if ( hvm_irq_dpci == NULL && !is_hardware_domain(d) ) > > Would you mind at once switching to the shorter !hvm_irq_dpci > (also further down), the more that you're using the inverse > without " != NULL" elsewhere? Done. > > { > > unsigned int i; > > > > + /* > > + * NB: the hardware domain doesn't use a hvm_irq_dpci struct > > because > > + * it's only allowed to identity map GSIs, and so the data > > contained in > > + * that struct (used to map guest GSIs into machine GSIs and > > perform > > + * interrupt routing) it's completely useless to it. > > "is completely ..." Fixed. > > @@ -422,35 +447,52 @@ int pt_irq_create_bind( > > case PT_IRQ_TYPE_PCI: > > case PT_IRQ_TYPE_MSI_TRANSLATE: > > { > > - unsigned int bus = pt_irq_bind->u.pci.bus; > > - unsigned int device = pt_irq_bind->u.pci.device; > > - unsigned int intx = pt_irq_bind->u.pci.intx; > > - unsigned int guest_gsi = hvm_pci_intx_gsi(device, intx); > > - unsigned int link = hvm_pci_intx_link(device, intx); > > - struct dev_intx_gsi_link *digl = xmalloc(struct dev_intx_gsi_link); > > - struct hvm_girq_dpci_mapping *girq = > > - xmalloc(struct hvm_girq_dpci_mapping); > > + struct dev_intx_gsi_link *digl = NULL; > > + struct hvm_girq_dpci_mapping *girq = NULL; > > + unsigned int guest_gsi; > > > > - if ( !digl || !girq ) > > + /* > > + * Mapping GSIs for the hardware domain is different than doing it > > for > > + * an unpriviledged guest, the hardware domain is only allowed to > > + * identity map GSIs, and as such all the data in the u.pci union > > is > > + * discarded. > > + */ > > + if ( !is_hardware_domain(d) ) > > I think I did indicate before that it would feel more safe if you > checked hvm_irq_dpci here (which is NULL if and only if d is > hwdom). At the very least I'd expect a respective ASSERT() > below (but I think the alternative condition here and > ASSERT(is_hardware_domain(d)) in the "else" block would be > better). I've changed this to: if ( hvm_irq_dpci ) { ... } else { ASSERT(is_hardware_domain(d)); ... } > > { > > - spin_unlock(&d->event_lock); > > - xfree(girq); > > - xfree(digl); > > - return -ENOMEM; > > - } > > + unsigned int link; > > + > > + digl = xmalloc(struct dev_intx_gsi_link); > > + girq = xmalloc(struct hvm_girq_dpci_mapping); > > > > - hvm_irq_dpci->link_cnt[link]++; > > + if ( !digl || !girq ) > > + { > > + spin_unlock(&d->event_lock); > > + xfree(girq); > > + xfree(digl); > > + return -ENOMEM; > > + } > > + > > + girq->bus = digl->bus = pt_irq_bind->u.pci.bus; > > + girq->device = digl->device = pt_irq_bind->u.pci.device; > > + girq->intx = digl->intx = pt_irq_bind->u.pci.intx; > > + list_add_tail(&digl->list, &pirq_dpci->digl_list); > > > > - digl->bus = bus; > > - digl->device = device; > > - digl->intx = intx; > > - list_add_tail(&digl->list, &pirq_dpci->digl_list); > > + guest_gsi = hvm_pci_intx_gsi(digl->device, digl->intx); > > + link = hvm_pci_intx_link(digl->device, digl->intx); > > > > - girq->bus = bus; > > - girq->device = device; > > - girq->intx = intx; > > - girq->machine_gsi = pirq; > > - list_add_tail(&girq->list, &hvm_irq_dpci->girq[guest_gsi]); > > + hvm_irq_dpci->link_cnt[link]++; > > + > > + girq->machine_gsi = pirq; > > + list_add_tail(&girq->list, &hvm_irq_dpci->girq[guest_gsi]); > > + } > > + else > > + { > > + /* MSI_TRANSLATE is not supported by the hardware domain. */ > > s/by/for/ ? OK. I guess this is better because d is a target in this context? > > @@ -472,7 +514,28 @@ int pt_irq_create_bind( > > pirq_dpci->flags = HVM_IRQ_DPCI_MAPPED | > > HVM_IRQ_DPCI_MACH_PCI | > > HVM_IRQ_DPCI_GUEST_PCI; > > - share = BIND_PIRQ__WILL_SHARE; > > + if ( !is_hardware_domain(d) ) > > + share = BIND_PIRQ__WILL_SHARE; > > + else > > + { > > + unsigned int pin; > > + struct hvm_vioapic *vioapic = gsi_vioapic(d, guest_gsi, > > + &pin); > > const > > > @@ -489,9 +552,16 @@ int pt_irq_create_bind( > > * IRQ_GUEST is not set. As such we can reset 'dom' > > directly. > > */ > > pirq_dpci->dom = NULL; > > - list_del(&girq->list); > > - list_del(&digl->list); > > - hvm_irq_dpci->link_cnt[link]--; > > + if ( girq || digl ) > > + { > > + unsigned int link; > > + > > + ASSERT(girq && digl); > > Perhaps even "ASSERT(girq && digl && hvm_irq_dpci)" or follow the > model outlined above for consistency? I've changed the condition to "if ( hvm_irq_dpci )" and left the ASSERT as-is. > > @@ -504,10 +574,17 @@ int pt_irq_create_bind( > > spin_unlock(&d->event_lock); > > > > if ( iommu_verbose ) > > - printk(XENLOG_G_INFO > > - "d%d: bind: m_gsi=%u g_gsi=%u dev=%02x.%02x.%u > > intx=%u\n", > > - d->domain_id, pirq, guest_gsi, bus, > > - PCI_SLOT(device), PCI_FUNC(device), intx); > > + { > > + char buf[24] = ""; > > + > > + if ( !is_hardware_domain(d) ) > > + snprintf(buf, ARRAY_SIZE(buf), " dev=%02x.%02x.%u intx=%u", > > + digl->bus, PCI_SLOT(digl->device), > > + PCI_FUNC(digl->device), digl->intx); > > Perhaps again better "if ( digl )". Yes, I think that's better. > > @@ -696,7 +777,8 @@ int hvm_do_IRQ_dpci(struct domain *d, struct pirq *pirq) > > struct hvm_irq_dpci *dpci = domain_get_irq_dpci(d); > > struct hvm_pirq_dpci *pirq_dpci = pirq_dpci(pirq); > > > > - if ( !iommu_enabled || !dpci || !pirq_dpci || > > + if ( !is_hvm_domain(d) || !iommu_enabled || > > + (!is_hardware_domain(d) && !dpci) || !pirq_dpci || > > !(pirq_dpci->flags & HVM_IRQ_DPCI_MAPPED) ) > > return 0; > > So why again do we suddenly need !is_hvm_domain() here? With > the name of the function there shouldn't be any caller invoking it > for a PV guest. Sadly there is, in __do_IRQ_guest the following is used: if ( !hvm_do_IRQ_dpci(d, pirq) ) send_guest_pirq(d, pirq); Without checking if d is a HVM or PV guest, so the check is needed (or needs to be moved further up in the call chain into __do_IRQ_guest). Thanks, Roger. _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |