Re: [Xen-devel] [PATCH for-4.9] x86/vioapic: allow holes in the GSI range for PVH Dom0

2017-04-18 Thread Jan Beulich
>>> On 18.04.17 at 10:49,  wrote:
> On Tue, Apr 18, 2017 at 02:39:34AM -0600, Jan Beulich wrote:
>> >>> On 17.04.17 at 18:09,  wrote:
>> > @@ -601,7 +587,12 @@ int vioapic_init(struct domain *d)
>> >  nr_gsis += nr_pins;
>> >  }
>> >  
>> > -ASSERT(hvm_domain_irq(d)->nr_gsis == nr_gsis);
>> > +/*
>> > + * NB: hvm_domain_irq(d)->nr_gsis is actually the highest GSI + 1, but
>> > + * there might be holes in this range (ie: GSIs that don't belong to 
>> > any
>> > + * vIO APIC).
>> > + */
>> > +ASSERT(hvm_domain_irq(d)->nr_gsis >= nr_gsis);
>> 
>> This becomes too weak then, as you want to index the array using
>> the GSI (and not some compressed representation with the holes
>> squashed). Which in turn means the nr_gsis calculation in this
>> function is now wrong - you need to accumulate the maximum
>> base_gsi + nr_pins value here instead. With that >= will actually
>> be fine to use here.
> 
> Is the array of IO APICs guaranteed to be ordered from lower GSI to highest
> one?  So far it seems like it is on all the machines I've tested, but I'm not
> sure this is a guarantee, thus I'm going to use:
> 
> nr_gsis = max(nr_gsis, base_gsi + nr_pins);

Yes - as Andrew has already said, don't make assumptions here.

Jan


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH for-4.9] x86/vioapic: allow holes in the GSI range for PVH Dom0

2017-04-18 Thread Andrew Cooper
On 18/04/2017 09:49, Roger Pau Monne wrote:
> On Tue, Apr 18, 2017 at 02:39:34AM -0600, Jan Beulich wrote:
> On 17.04.17 at 18:09,  wrote:
>>> @@ -601,7 +587,12 @@ int vioapic_init(struct domain *d)
>>>  nr_gsis += nr_pins;
>>>  }
>>>  
>>> -ASSERT(hvm_domain_irq(d)->nr_gsis == nr_gsis);
>>> +/*
>>> + * NB: hvm_domain_irq(d)->nr_gsis is actually the highest GSI + 1, but
>>> + * there might be holes in this range (ie: GSIs that don't belong to 
>>> any
>>> + * vIO APIC).
>>> + */
>>> +ASSERT(hvm_domain_irq(d)->nr_gsis >= nr_gsis);
>> This becomes too weak then, as you want to index the array using
>> the GSI (and not some compressed representation with the holes
>> squashed). Which in turn means the nr_gsis calculation in this
>> function is now wrong - you need to accumulate the maximum
>> base_gsi + nr_pins value here instead. With that >= will actually
>> be fine to use here.
> Is the array of IO APICs guaranteed to be ordered from lower GSI to highest
> one?

I would certainly not bet on it.

>   So far it seems like it is on all the machines I've tested, but I'm not
> sure this is a guarantee, thus I'm going to use:
>
> nr_gsis = max(nr_gsis, base_gsi + nr_pins);

This is indeed the right thing to do.

~Andrew

___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH for-4.9] x86/vioapic: allow holes in the GSI range for PVH Dom0

2017-04-18 Thread Roger Pau Monne
On Tue, Apr 18, 2017 at 02:39:34AM -0600, Jan Beulich wrote:
> >>> On 17.04.17 at 18:09,  wrote:
> > @@ -601,7 +587,12 @@ int vioapic_init(struct domain *d)
> >  nr_gsis += nr_pins;
> >  }
> >  
> > -ASSERT(hvm_domain_irq(d)->nr_gsis == nr_gsis);
> > +/*
> > + * NB: hvm_domain_irq(d)->nr_gsis is actually the highest GSI + 1, but
> > + * there might be holes in this range (ie: GSIs that don't belong to 
> > any
> > + * vIO APIC).
> > + */
> > +ASSERT(hvm_domain_irq(d)->nr_gsis >= nr_gsis);
> 
> This becomes too weak then, as you want to index the array using
> the GSI (and not some compressed representation with the holes
> squashed). Which in turn means the nr_gsis calculation in this
> function is now wrong - you need to accumulate the maximum
> base_gsi + nr_pins value here instead. With that >= will actually
> be fine to use here.

Is the array of IO APICs guaranteed to be ordered from lower GSI to highest
one?  So far it seems like it is on all the machines I've tested, but I'm not
sure this is a guarantee, thus I'm going to use:

nr_gsis = max(nr_gsis, base_gsi + nr_pins);

Just in case.

Thanks, Roger.


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH for-4.9] x86/vioapic: allow holes in the GSI range for PVH Dom0

2017-04-18 Thread Jan Beulich
>>> On 17.04.17 at 18:09,  wrote:
> @@ -601,7 +587,12 @@ int vioapic_init(struct domain *d)
>  nr_gsis += nr_pins;
>  }
>  
> -ASSERT(hvm_domain_irq(d)->nr_gsis == nr_gsis);
> +/*
> + * NB: hvm_domain_irq(d)->nr_gsis is actually the highest GSI + 1, but
> + * there might be holes in this range (ie: GSIs that don't belong to any
> + * vIO APIC).
> + */
> +ASSERT(hvm_domain_irq(d)->nr_gsis >= nr_gsis);

This becomes too weak then, as you want to index the array using
the GSI (and not some compressed representation with the holes
squashed). Which in turn means the nr_gsis calculation in this
function is now wrong - you need to accumulate the maximum
base_gsi + nr_pins value here instead. With that >= will actually
be fine to use here.

Jan


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH for-4.9] x86/vioapic: allow holes in the GSI range for PVH Dom0

2017-04-18 Thread Roger Pau Monne
On Mon, Apr 17, 2017 at 05:09:22PM +0100, Roger Pau Monne wrote:
> The current vIO APIC for PVH Dom0 doesn't allow non-contiguous GSIs, which
> means that all GSIs must belong to an IO APIC. This doesn't match reality,
> where there are systems with non-contiguous GSIs.
> 
> In order to fix this add a base_gsi field to each hvm_vioapic struct, in order
> to store the base GSI for each emulated IO APIC. For PVH Dom0 those values are
> populated based on the hardware ones.
> 
> Signed-off-by: Roger Pau Monné 
> Reported-by: Chao Gao 

For consistency I think the following chunk should also be merged into it, now
that Xen can get the base GSI from the vIO APIC struct itself.

Roger.
---8<---
diff --git a/xen/arch/x86/hvm/dom0_build.c b/xen/arch/x86/hvm/dom0_build.c
index db9be87612..020c355faf 100644
--- a/xen/arch/x86/hvm/dom0_build.c
+++ b/xen/arch/x86/hvm/dom0_build.c
@@ -719,7 +719,7 @@ static int __init pvh_setup_acpi_madt(struct domain *d, 
paddr_t *addr)
 io_apic->header.length = sizeof(*io_apic);
 io_apic->id = domain_vioapic(d, i)->id;
 io_apic->address = domain_vioapic(d, i)->base_address;
-io_apic->global_irq_base = io_apic_gsi_base(i);
+io_apic->global_irq_base = domain_vioapic(d, i)->base_gsi;
 io_apic++;
 }
 


___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH for-4.9] x86/vioapic: allow holes in the GSI range for PVH Dom0

2017-04-17 Thread Chao Gao
On Mon, Apr 17, 2017 at 05:09:22PM +0100, Roger Pau Monne wrote:
>The current vIO APIC for PVH Dom0 doesn't allow non-contiguous GSIs, which
>means that all GSIs must belong to an IO APIC. This doesn't match reality,
>where there are systems with non-contiguous GSIs.
>
>In order to fix this add a base_gsi field to each hvm_vioapic struct, in order
>to store the base GSI for each emulated IO APIC. For PVH Dom0 those values are
>populated based on the hardware ones.
>
>Signed-off-by: Roger Pau Monné 
>Reported-by: Chao Gao 

Tested-by: Chao Gao 

Thanks
Chao

___
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel


[Xen-devel] [PATCH for-4.9] x86/vioapic: allow holes in the GSI range for PVH Dom0

2017-04-17 Thread Roger Pau Monne
The current vIO APIC for PVH Dom0 doesn't allow non-contiguous GSIs, which
means that all GSIs must belong to an IO APIC. This doesn't match reality,
where there are systems with non-contiguous GSIs.

In order to fix this add a base_gsi field to each hvm_vioapic struct, in order
to store the base GSI for each emulated IO APIC. For PVH Dom0 those values are
populated based on the hardware ones.

Signed-off-by: Roger Pau Monné 
Reported-by: Chao Gao 
---
Cc: Jan Beulich 
Cc: Andrew Cooper 
Cc: Julien Grall 
Cc: Chao Gao 
---
I think this is a good canditate to be included in 4.9, it's a bugfix, and it's
only used by PVH Dom0, so the risk is low IMHO.
---
 xen/arch/x86/hvm/vioapic.c| 41 +++
 xen/include/asm-x86/hvm/vioapic.h |  1 +
 2 files changed, 17 insertions(+), 25 deletions(-)

diff --git a/xen/arch/x86/hvm/vioapic.c b/xen/arch/x86/hvm/vioapic.c
index 5157db7a4e..ec87a97651 100644
--- a/xen/arch/x86/hvm/vioapic.c
+++ b/xen/arch/x86/hvm/vioapic.c
@@ -64,37 +64,23 @@ static struct hvm_vioapic *addr_vioapic(const struct domain 
*d,
 struct hvm_vioapic *gsi_vioapic(const struct domain *d, unsigned int gsi,
 unsigned int *pin)
 {
-unsigned int i, base_gsi = 0;
+unsigned int i;
 
 for ( i = 0; i < d->arch.hvm_domain.nr_vioapics; i++ )
 {
 struct hvm_vioapic *vioapic = domain_vioapic(d, i);
 
-if ( gsi >= base_gsi && gsi < base_gsi + vioapic->nr_pins )
+if ( gsi >= vioapic->base_gsi &&
+ gsi < vioapic->base_gsi + vioapic->nr_pins )
 {
-*pin = gsi - base_gsi;
+*pin = gsi - vioapic->base_gsi;
 return vioapic;
 }
-
-base_gsi += vioapic->nr_pins;
 }
 
 return NULL;
 }
 
-static unsigned int base_gsi(const struct domain *d,
- const struct hvm_vioapic *vioapic)
-{
-unsigned int nr_vioapics = d->arch.hvm_domain.nr_vioapics;
-unsigned int base_gsi = 0, i = 0;
-const struct hvm_vioapic *tmp;
-
-while ( i < nr_vioapics && (tmp = domain_vioapic(d, i++)) != vioapic )
-base_gsi += tmp->nr_pins;
-
-return base_gsi;
-}
-
 static uint32_t vioapic_read_indirect(const struct hvm_vioapic *vioapic)
 {
 uint32_t result = 0;
@@ -180,7 +166,7 @@ static void vioapic_write_redirent(
 struct hvm_irq *hvm_irq = hvm_domain_irq(d);
 union vioapic_redir_entry *pent, ent;
 int unmasked = 0;
-unsigned int gsi = base_gsi(d, vioapic) + idx;
+unsigned int gsi = vioapic->base_gsi + idx;
 
 spin_lock(&d->arch.hvm_domain.irq_lock);
 
@@ -340,7 +326,7 @@ static void vioapic_deliver(struct hvm_vioapic *vioapic, 
unsigned int pin)
 struct domain *d = vioapic_domain(vioapic);
 struct vlapic *target;
 struct vcpu *v;
-unsigned int irq = base_gsi(d, vioapic) + pin;
+unsigned int irq = vioapic->base_gsi + pin;
 
 ASSERT(spin_is_locked(&d->arch.hvm_domain.irq_lock));
 
@@ -451,7 +437,7 @@ void vioapic_update_EOI(struct domain *d, u8 vector)
 {
 struct hvm_irq *hvm_irq = hvm_domain_irq(d);
 union vioapic_redir_entry *ent;
-unsigned int i, base_gsi = 0;
+unsigned int i;
 
 ASSERT(has_vioapic(d));
 
@@ -473,19 +459,18 @@ void vioapic_update_EOI(struct domain *d, u8 vector)
 if ( iommu_enabled )
 {
 spin_unlock(&d->arch.hvm_domain.irq_lock);
-hvm_dpci_eoi(d, base_gsi + pin, ent);
+hvm_dpci_eoi(d, vioapic->base_gsi + pin, ent);
 spin_lock(&d->arch.hvm_domain.irq_lock);
 }
 
 if ( (ent->fields.trig_mode == VIOAPIC_LEVEL_TRIG) &&
  !ent->fields.mask &&
- hvm_irq->gsi_assert_count[base_gsi + pin] )
+ hvm_irq->gsi_assert_count[vioapic->base_gsi + pin] )
 {
 ent->fields.remote_irr = 1;
 vioapic_deliver(vioapic, pin);
 }
 }
-base_gsi += vioapic->nr_pins;
 }
 
 spin_unlock(&d->arch.hvm_domain.irq_lock);
@@ -554,6 +539,7 @@ void vioapic_reset(struct domain *d)
 {
 vioapic->base_address = mp_ioapics[i].mpc_apicaddr;
 vioapic->id = mp_ioapics[i].mpc_apicid;
+vioapic->base_gsi = io_apic_gsi_base(i);
 }
 vioapic->nr_pins = nr_pins;
 vioapic->domain = d;
@@ -601,7 +587,12 @@ int vioapic_init(struct domain *d)
 nr_gsis += nr_pins;
 }
 
-ASSERT(hvm_domain_irq(d)->nr_gsis == nr_gsis);
+/*
+ * NB: hvm_domain_irq(d)->nr_gsis is actually the highest GSI + 1, but
+ * there might be holes in this range (ie: GSIs that don't belong to any
+ * vIO APIC).
+ */
+ASSERT(hvm_domain_irq(d)->nr_gsis >= nr_gsis);
 
 d->arch.hvm_domain.nr_vioapics = nr_vioapics;
 vioapic_reset(d);
diff --git a/xen/include/asm-x86/hvm/vioapic.h 
b/xen/include/asm-x86/hvm/vioapic.h
index 8ec91d2bd1..2ceb60eaef 100644
--- a/xen/include/asm-x86/