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

Re: [Xen-devel] [PATCH v2 5/7] x86/vioapic: introduce support for multiple vIO APICS



>>> On 27.03.17 at 12:18, <roger.pau@xxxxxxxxxx> wrote:
> Changes since v1:
>  - Constify some parameters.

Considering this I'm surprised the first thing I have to ask is ...

> --- a/xen/arch/x86/hvm/vioapic.c
> +++ b/xen/arch/x86/hvm/vioapic.c
> @@ -44,6 +44,54 @@
>  
>  static void vioapic_deliver(struct hvm_vioapic *vioapic, int irq);
>  
> +static struct hvm_vioapic *addr_vioapic(struct domain *d, unsigned long addr)

... const? The more that you have it like this ...

> +struct hvm_vioapic *gsi_vioapic(const struct domain *d, unsigned int gsi,

... here.

> +                                unsigned int *base_gsi)

All callers of the function really want the pin number rather than
the base GSI - why don't you make the function provide that
instead?

> +{
> +    unsigned int i;
> +    *base_gsi = 0;

Blank line between declaration(s) and statement(s) please.

> +static unsigned int pin_gsi(const struct domain *d,
> +                            const struct hvm_vioapic *vioapic,
> +                            unsigned int pin)
> +{
> +    const struct hvm_vioapic *tmp;
> +    unsigned int base_gsi = 0;
> +
> +    for ( tmp = domain_vioapic(d, 0); tmp != vioapic; tmp++ )
> +        base_gsi += tmp->nr_pins;
> +
> +    return base_gsi + pin;
> +}

Didn't we settle on having a function base_gsi(), with callers
adding in the pin number as needed? The only reason the function
here takes pin as a parameter is this final addition.

Also shouldn't this function somehow guard itself against
overrunning the array?

> @@ -275,16 +327,17 @@ static inline int pit_channel0_enabled(void)
>      return pt_active(&current->domain->arch.vpit.pt0);
>  }
>  
> -static void vioapic_deliver(struct hvm_vioapic *vioapic, int irq)
> +static void vioapic_deliver(struct hvm_vioapic *vioapic, int pin)

Occasionally we pass around negative IRQ numbers, but if this
really is a pin number, I think the type wants changing to unsigned
int - the more that it is being used as an array index below.

> @@ -454,33 +517,70 @@ HVM_REGISTER_SAVE_RESTORE(IOAPIC, ioapic_save, 
> ioapic_load, 1, HVMSR_PER_DOM);
>  
>  void vioapic_reset(struct domain *d)
>  {
> -    struct hvm_vioapic *vioapic = domain_vioapic(d);
> -    uint32_t nr_pins = vioapic->nr_pins;
> -    int i;
> +    unsigned int i;
>  
>      if ( !has_vioapic(d) )
> +    {
> +        ASSERT(!d->arch.hvm_domain.nr_vioapics);
>          return;
> +    }
>  
> -    memset(vioapic, 0, hvm_vioapic_size(nr_pins));
> -    vioapic->domain = d;
> -    vioapic->nr_pins = nr_pins;
> -    for ( i = 0; i < nr_pins; i++ )
> -        vioapic->redirtbl[i].fields.mask = 1;
> -    vioapic->base_address = VIOAPIC_DEFAULT_BASE_ADDRESS;
> +    for ( i = 0; i < d->arch.hvm_domain.nr_vioapics; i++ )
> +    {
> +        struct hvm_vioapic *vioapic = domain_vioapic(d, i);
> +        unsigned int j, nr_pins = vioapic->nr_pins;
> +
> +        memset(vioapic, 0, hvm_vioapic_size(nr_pins));
> +        for ( j = 0; j < nr_pins; j++ )
> +            vioapic->redirtbl[j].fields.mask = 1;
> +        vioapic->base_address = VIOAPIC_DEFAULT_BASE_ADDRESS +
> +                                VIOAPIC_MEM_LENGTH * i;
> +        vioapic->id = i;
> +        vioapic->nr_pins = nr_pins;
> +        vioapic->domain = d;
> +    }
> +}

Is this function validly reachable for Dom0? If not, better leave it
alone (adding a nr_vioapics == 1 check), as at least the base
address calculation looks rather suspicious (there shouldn't be
multiple IO-APICs on a single page). If so, that same memory
address calculation is actively wrong in the Dom0 case.

> +static void vioapic_free(const struct domain *d, unsigned int nr_vioapics)
> +{
> +    unsigned int i;
> +
> +    for ( i = 0; i < nr_vioapics; i++)
> +    {
> +       if ( domain_vioapic(d, i) == NULL )
> +          break;

Is this if() really needed?

>  int vioapic_init(struct domain *d)
>  {
> +    unsigned int i, nr_vioapics = 1;
> +
>      if ( !has_vioapic(d) )
> +    {
> +        ASSERT(!d->arch.hvm_domain.nr_vioapics);
>          return 0;
> +    }
>  
>      if ( (d->arch.hvm_domain.vioapic == NULL) &&
>           ((d->arch.hvm_domain.vioapic =
> -           xmalloc_bytes(hvm_vioapic_size(VIOAPIC_NUM_PINS))) == NULL) )
> +           xzalloc_array(struct hvm_vioapic *, nr_vioapics)) == NULL) )
>          return -ENOMEM;
>  
> -    d->arch.hvm_domain.vioapic->domain = d;
> -    d->arch.hvm_domain.vioapic->nr_pins = VIOAPIC_NUM_PINS;
> +    for ( i = 0; i < nr_vioapics; i++ )
> +    {
> +        if ( (domain_vioapic(d, i) =
> +              xmalloc_bytes(hvm_vioapic_size(VIOAPIC_NUM_PINS))) == NULL )
> +        {
> +            vioapic_free(d, nr_vioapics);
> +            return -ENOMEM;
> +        }
> +        domain_vioapic(d, i)->nr_pins = VIOAPIC_NUM_PINS;
> +    }
> +
> +    d->arch.hvm_domain.nr_vioapics = nr_vioapics;
>      vioapic_reset(d);

These adjustments again don't look right for nr_vioapics > 1, so I
wonder whether again this function wouldn't better be left alone.
Alternatively, if Dom0 needs to come here, a comment is going to
be needed to explain the (temporary) wrong setting of nr_pins.

> @@ -91,13 +92,22 @@ static int pt_irq_vector(struct periodic_time *pt, enum 
> hvm_intsrc src)
>                  + (isa_irq & 7));
>  
>      ASSERT(src == hvm_intsrc_lapic);
> -    return domain_vioapic(v->domain)->redirtbl[gsi].fields.vector;
> +    vioapic = gsi_vioapic(v->domain, gsi, &base_gsi);
> +    if ( !vioapic )
> +    {
> +        gdprintk(XENLOG_WARNING, "Invalid GSI (%u) for platform timer\n", 
> gsi);
> +        domain_crash(v->domain);
> +        return -1;
> +    }

Now that you have this check, ...

> @@ -110,9 +120,10 @@ static int pt_irq_masked(struct periodic_time *pt)
>      isa_irq = pt->irq;
>      gsi = hvm_isa_irq_to_gsi(isa_irq);
>      pic_imr = v->domain->arch.hvm_domain.vpic[isa_irq >> 3].imr;
> +    vioapic = gsi_vioapic(v->domain, gsi, &base_gsi);
>  
>      return (((pic_imr & (1 << (isa_irq & 7))) || !vlapic_accept_pic_intr(v)) 
> &&
> -            domain_vioapic(v->domain)->redirtbl[gsi].fields.mask);
> +            vioapic->redirtbl[gsi - base_gsi].fields.mask);
>  }

... why is there still none here?

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