[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 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.

> @@ -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?

>      {
>          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 ..."

> @@ -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).

>          {
> -            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/ ?

> @@ -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?

> @@ -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 )".

> @@ -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.

Jan

_______________________________________________
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®.