[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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.