[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v2 2/3] x86/pt: enable binding of GSIs to a PVH Dom0
On Fri, May 12, 2017 at 07:42:51AM -0600, Jan Beulich wrote: > >>> On 19.04.17 at 17:11, <roger.pau@xxxxxxxxxx> wrote: > > Note that currently there's no support for unbinding this interrupts. > > Do you plan to deal with that before this changes goes in? Aiui this > not working means you can't pass through devices with pin based > interrupts once Dom0 chose to bind to them. Otoh hand you modify > pt_irq_destroy_bind(), so I'm a little puzzled ... Yes, I modify pt_irq_destroy_bind to return EOPNOTSUPP when trying to unbind such an interrupt. I can implement the unbind, but it's not going to be used ATM. > > --- a/xen/arch/x86/hvm/irq.c > > +++ b/xen/arch/x86/hvm/irq.c > > @@ -126,6 +126,34 @@ void hvm_pci_intx_deassert( > > spin_unlock(&d->arch.hvm_domain.irq_lock); > > } > > > > +void hvm_gsi_assert(struct domain *d, unsigned int gsi) > > +{ > > + struct hvm_irq *hvm_irq = hvm_domain_irq(d); > > + > > + ASSERT(gsi < hvm_irq->nr_gsis); > > This would probably better match the alternative construct in > __hvm_pci_intx_assert(). OK, changed. > > + ASSERT(!has_vpic(d)); > > This doesn't look to be relevant for the rest of the function. Is there > a particular reason you've added it? If so, a brief comment might > help. I've added this because hvm_gsi_assert doesn't call assert_irq, so a PIC would not work properly, but it's probably pointless. > > + spin_lock(&d->arch.hvm_domain.irq_lock); > > + if ( !hvm_irq->gsi_assert_count[gsi] ) > > + { > > + hvm_irq->gsi_assert_count[gsi]++; > > Why is this an increment instead of a simple write of 1? Or the > other way around - why is this not always incrementing, just like > __hvm_pci_intx_assert() does? (Symmetric questions then for > hvm_gsi_deassert()). __hvm_pci_intx_{de}assert has an array that tracks the status of each interrupt line, and Xen does the routing based on that (the __test_and_clear_bit at the top of __hvm_pci_intx_assert). That prevents the same line from triggering multiple times, which is not available here, and thus Xen needs to rely on gsi_assert_count in order to know if the GSI is pending or not. Switched to use a set to 1/0 instead of the increment, which I agree makes this clearer. > > > @@ -274,10 +289,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) ) > > { > > 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 for it. > > "...) is completely useless to it." Fixed, thanks. > > @@ -422,35 +443,51 @@ 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) ) > > { > > - 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); > > + > > + 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); > > > > - hvm_irq_dpci->link_cnt[link]++; > > + guest_gsi = hvm_pci_intx_gsi(digl->device, digl->intx); > > + link = hvm_pci_intx_link(digl->device, digl->intx); > > > > - digl->bus = bus; > > - digl->device = device; > > - digl->intx = intx; > > - list_add_tail(&digl->list, &pirq_dpci->digl_list); > > + hvm_irq_dpci->link_cnt[link]++; > > > > - girq->bus = bus; > > - girq->device = device; > > - girq->intx = intx; > > - girq->machine_gsi = pirq; > > - list_add_tail(&girq->list, &hvm_irq_dpci->girq[guest_gsi]); > > + 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. */ > > + ASSERT(pt_irq_bind->irq_type == PT_IRQ_TYPE_PCI); > > + guest_gsi = pirq; > > + ASSERT(guest_gsi < hvm_domain_irq(d)->nr_gsis); > > + } > > This is dangerous: For one it is impossible to judge the correctness > of at least the first of these assertions for the hwdom case without > looking at patch 3. And then the domctl path leading here does not > exclude the subject domain equaling the calling one, i.e. you > potentially assert guest input correctness here. Yes, we have XSA-77 > in place, but no, we shouldn't introduce new issues anywhere unless > that's entirely unavoidable. OK, let me return error instead to be on the safe side then. > > @@ -504,10 +567,18 @@ 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[50]; > > + > > + 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); > > The buffer array seems heavily over-sized - my counting gives at best > slightly over 20 characters you actually need. AFAICT max length should be 21, would you be fine with me setting it to 24 to be safe? > > > @@ -522,7 +593,6 @@ int pt_irq_create_bind( > > int pt_irq_destroy_bind( > > struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind) > > { > > - struct hvm_irq_dpci *hvm_irq_dpci; > > struct hvm_pirq_dpci *pirq_dpci; > > unsigned int machine_gsi = pt_irq_bind->machine_irq; > > struct pirq *pirq; > > @@ -552,17 +622,15 @@ int pt_irq_destroy_bind( > > > > spin_lock(&d->event_lock); > > > > - hvm_irq_dpci = domain_get_irq_dpci(d); > > - > > - if ( hvm_irq_dpci == NULL ) > > + pirq = pirq_info(d, machine_gsi); > > + pirq_dpci = pirq_dpci(pirq); > > + if ( pirq_dpci->flags & HVM_IRQ_DPCI_IDENTITY_GSI ) > > I'm sure we've discussed aspects of this before: pirq_dpci may be > NULL here, i.e. you can't blindly dereference it. All other uses in > the function indeed have a NULL check first. OK, I've removed this and fixed the function so it can unbind HVM_IRQ_DPCI_IDENTITY_GSI. > > @@ -570,9 +638,16 @@ int pt_irq_destroy_bind( > > 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 hvm_irq_dpci *hvm_irq_dpci = domain_get_irq_dpci(d); > > struct hvm_girq_dpci_mapping *girq; > > struct dev_intx_gsi_link *digl, *tmp; > > > > + if ( hvm_irq_dpci == NULL ) > > + { > > + spin_unlock(&d->event_lock); > > + return -EINVAL; > > + } > > Moving this check here is a behavioral modification. Perhaps a > good one, yet it doesn't belong into this patch. Instead it should > be properly reasoned about in a separate patch, if it is a correct > thing to do. I've left it in it's previous place and added a !is_hardware_domain check. > > @@ -814,17 +896,12 @@ static void hvm_dirq_assist(struct domain *d, struct > > hvm_pirq_dpci *pirq_dpci) > > spin_unlock(&d->event_lock); > > } > > > > -static void __hvm_dpci_eoi(struct domain *d, > > - const struct hvm_girq_dpci_mapping *girq, > > +static void __hvm_pirq_eoi(struct pirq *pirq, > > Please drop the double leading underscores. Done. > > > const union vioapic_redir_entry *ent) > > { > > - struct pirq *pirq = pirq_info(d, girq->machine_gsi); > > - struct hvm_pirq_dpci *pirq_dpci; > > - > > - if ( !hvm_domain_use_pirq(d, pirq) ) > > - hvm_pci_intx_deassert(d, girq->device, girq->intx); > > + struct hvm_pirq_dpci *pirq_dpci = pirq_dpci(pirq); > > > > - pirq_dpci = pirq_dpci(pirq); > > + ASSERT(pirq_dpci); > > Why is this useful / needed all of the sudden? Hm, I don't think it's needed, probably just a leftover from when I was testing the patches. > > @@ -839,6 +916,32 @@ static void __hvm_dpci_eoi(struct domain *d, > > pirq_guest_eoi(pirq); > > } > > > > +static void __hvm_dpci_eoi(struct domain *d, > > + const struct hvm_girq_dpci_mapping *girq, > > + const union vioapic_redir_entry *ent) > > +{ > > + struct pirq *pirq = pirq_info(d, girq->machine_gsi); > > + > > + if ( !hvm_domain_use_pirq(d, pirq) ) > > + hvm_pci_intx_deassert(d, girq->device, girq->intx); > > + > > + __hvm_pirq_eoi(pirq, ent); > > +} > > + > > +static void __hvm_gsi_eoi(struct domain *d, unsigned int gsi, > > Same here for the double underscores. For the pre-existing > function I'd leave it up to you whether to also drop them. What > I care about is that we don't gain new non-conforming names. I will leave the others as they are, or else they should be changed in a separate patch. > > + const union vioapic_redir_entry *ent) > > +{ > > + struct pirq *pirq = pirq_info(d, gsi); > > + struct hvm_pirq_dpci *pirq_dpci = pirq_dpci(pirq); > > + > > + /* Check if GSI is actually mapped. */ > > + if ( !pirq_dpci ) > > Please avoid the local variable when used just once here. Done. Thanks for the review, Roger. _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |