[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v4 3/9] x86/passthrough: Extract pt_irq_dpci_setup() from pt_irq_create_bind()



Le 27/04/2026 à 15:57, Julian Vetter a écrit :
> The setup preamble in pt_irq_create_bind(), lazily allocating
> hvm_irq_dpci, looking up the struct pirq, and spinning until any pending
> hvm_dirq_assist softirq has drained, is needed by pt_irq_bind_msi() as
> well. Extract it into a static helper pt_irq_dpci_setup() that returns
> with d->event_lock write-locked on success. Replace the open-coded goto
> restart loop with a do { } while (true) loop and a continue, making the
> retry structure explicit without a label. No functional change.
> 
> Signed-off-by: Julian Vetter <julian.vetter@xxxxxxxxxx>
> ---
> Changes in v4:
> - New patch
> - Split out as a preparatory no-functional-change step to make the diff
>    in patch 5 (pt_irq_bind_msi() interface change) easier to review
> ---
>   xen/drivers/passthrough/x86/hvm.c | 54 +++++++++++++++++++++++--------
>   1 file changed, 40 insertions(+), 14 deletions(-)
> 
> diff --git a/xen/drivers/passthrough/x86/hvm.c 
> b/xen/drivers/passthrough/x86/hvm.c
> index 691fa1b2c7..19463c3406 100644
> --- a/xen/drivers/passthrough/x86/hvm.c
> +++ b/xen/drivers/passthrough/x86/hvm.c
> @@ -217,18 +217,22 @@ static struct vcpu *vector_hashing_dest(const struct 
> domain *d,
>       return dest;
>   }
>   
> -int pt_irq_create_bind(
> -    struct domain *d, const struct xen_domctl_bind_pt_irq *pt_irq_bind)
> +/*
> + * Acquire d->event_lock (write), lazily allocate hvm_irq_dpci if needed, 
> look
> + * up the struct pirq for @pirq, and drain any pending hvm_dirq_assist 
> softirq
> + * on it before returning. Returns 0 with d->event_lock held on success,
> + * negative errno otherwise (lock not held).
> + */
> +static int pt_irq_dpci_setup(struct domain *d, unsigned int pirq,
> +                              struct hvm_irq_dpci **hvm_irq_dpci_out,
> +                              struct hvm_pirq_dpci **pirq_dpci_out,
> +                              struct pirq **info_out)
>   {
>       struct hvm_irq_dpci *hvm_irq_dpci;
>       struct hvm_pirq_dpci *pirq_dpci;
>       struct pirq *info;
> -    int rc, pirq = pt_irq_bind->machine_irq;
>   
> -    if ( pirq < 0 || pirq >= d->nr_pirqs )
> -        return -EINVAL;
> -
> - restart:
> +    do
>       {
>           write_lock(&d->event_lock);
>   
> @@ -238,10 +242,11 @@ int pt_irq_create_bind(
>               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) is completely useless to it.
> +             * 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) is completely
> +             * useless to it.
>                */
>               hvm_irq_dpci = xzalloc(struct hvm_irq_dpci);
>               if ( hvm_irq_dpci == NULL )
> @@ -269,15 +274,36 @@ int pt_irq_create_bind(
>            * We MUST check for this condition as the softirq could be 
> scheduled
>            * and hasn't run yet. Note that this code replaced tasklet_kill 
> which
>            * would have spun forever and would do the same thing (wait to 
> flush out
> -         * outstanding hvm_dirq_assist calls.
> +         * outstanding hvm_dirq_assist calls).
>            */
>           if ( pt_pirq_softirq_active(pirq_dpci) )
>           {
>               write_unlock(&d->event_lock);
>               cpu_relax();
> -            goto restart;
> +            continue;
>           }
> -    }
> +
> +        *hvm_irq_dpci_out = hvm_irq_dpci;
> +        *pirq_dpci_out = pirq_dpci;
> +        *info_out = info;
> +        return 0;
> +    } while ( true );

I would prefer something like

do {
   ...
} while (false);

return 0;

> +}
> +
> +int pt_irq_create_bind(
> +    struct domain *d, const struct xen_domctl_bind_pt_irq *pt_irq_bind)
> +{
> +    struct hvm_irq_dpci *hvm_irq_dpci;
> +    struct hvm_pirq_dpci *pirq_dpci;
> +    struct pirq *info;
> +    int rc, pirq = pt_irq_bind->machine_irq;
> +
> +    if ( pirq < 0 || pirq >= d->nr_pirqs )
> +        return -EINVAL;
> +
> +    rc = pt_irq_dpci_setup(d, pirq, &hvm_irq_dpci, &pirq_dpci, &info);
> +    if ( rc )
> +        return rc;
>   
>       switch ( pt_irq_bind->irq_type )
>       {

The rest looks good to me.
With the do { ... } while (false); change:

Reviewed-by: Teddy Astie <teddy.astie@xxxxxxxxxx>


--
Teddy Astie | Vates XCP-ng Developer

XCP-ng & Xen Orchestra - Vates solutions

web: https://vates.tech

 


Rackspace

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