[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [XEN v5] xen/arm: vGICv3: Emulate properly 32-bit access on GICR_PENDBASER
On Thu, 27 Oct 2022 19:55:55 +0100 Ayan Kumar Halder <ayankuma@xxxxxxx> wrote: > If a guest is running in 32 bit mode and it tries to access > "GICR_PENDBASER + 4" mmio reg, it will be trapped to Xen. vreg_reg64_extract() > will return the value stored "v->arch.vgic.rdist_pendbase + 4". > This will be stored in a 64bit cpu register. > So now we have the top 32 bits of GICR_PENDBASER (a 64 bit MMIO register) > stored > in the lower 32 bits of the 64bit cpu register. > > This 64bit cpu register is then modified bitwise with a mask (ie > GICR_PENDBASER_PTZ, it clears the 62nd bit). But the PTZ (which is bit 30 in > the > 64 bit cpu register) is not cleared as expected by the specification. > > The correct thing to do here is to store the value of > "v->arch.vgic.rdist_pendbase" in a temporary 64 bit variable. This variable is > then modified bitwise with GICR_PENDBASER_PTZ mask. It is then passed to > vreg_reg64_extract() which will extract 32 bits from the given offset. > > Also, we have removed spin_lock_irqsave()/spin_unlock_irqrestore() to protect > v->arch.vgic.rdist_pendbase in __vgic_v3_rdistr_rd_mmio_read(). The reason > being v->arch.vgic.rdist_pendbase is now being read in an atomic manner. > > Similarly in __vgic_v3_rdistr_rd_mmio_write(), we have used read_atomic(), > write_atomic() to read/write v->arch.vgic.rdist_pendbase. > > Fixes: fe7fa1332dabd9ce4 ("ARM: vGICv3: handle virtual LPI pending and > property tables") > Signed-off-by: Ayan Kumar Halder <ayankuma@xxxxxxx> > Release-acked-by: Henry Wang <Henry.Wang@xxxxxxx> Reviewed-by: Andre Przywara <andre.przywara@xxxxxxx> Cheers, Andre > --- > > Changes from:- > > v1 - 1. Extracted this fix from "[RFC PATCH v1 05/12] Arm: GICv3: Emulate > GICR_PENDBASER and GICR_PROPBASER on AArch32" into a separate patch with an > appropriate commit message. > > v2 - 1. Removed spin_lock_irqsave(). Used read_atomic() to read > v->arch.vgic.rdist_pendbase in an atomic context. > 2. Rectified the commit message to state that the cpu register is 64 bit. > (because currently, GICv3 is supported on Arm64 only). Reworded to make it > clear. > > v3 - 1. Added read_atomic()/write_atomic() for access to > v->arch.vgic.rdist_pendbase > in __vgic_v3_rdistr_rd_mmio_write(). > 2. Removed spin_lock_irqsave()/spin_unlock_irqrestore() for access to > v->arch.vgic.rdist_pendbase in __vgic_v3_rdistr_rd_mmio_write(). > > v4 - 1. Retained the spin_lock_irqsave()/spin_unlock_irqrestore() for access > to > v->arch.vgic.rdist_pendbase in __vgic_v3_rdistr_rd_mmio_write(). This is > because > there could be a potential race while read-modify-write is performed on > v->arch.vgic.rdist_pendbase, with another caller performing the same > operation. > > xen/arch/arm/vgic-v3.c | 13 ++++++------- > 1 file changed, 6 insertions(+), 7 deletions(-) > > diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c > index 0c23f6df9d..d0e265634e 100644 > --- a/xen/arch/arm/vgic-v3.c > +++ b/xen/arch/arm/vgic-v3.c > @@ -249,16 +249,15 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct vcpu > *v, mmio_info_t *info, > > case VREG64(GICR_PENDBASER): > { > - unsigned long flags; > + uint64_t val; > > if ( !v->domain->arch.vgic.has_its ) > goto read_as_zero_64; > if ( !vgic_reg64_check_access(dabt) ) goto bad_width; > > - spin_lock_irqsave(&v->arch.vgic.lock, flags); > - *r = vreg_reg64_extract(v->arch.vgic.rdist_pendbase, info); > - *r &= ~GICR_PENDBASER_PTZ; /* WO, reads as 0 */ > - spin_unlock_irqrestore(&v->arch.vgic.lock, flags); > + val = read_atomic(&v->arch.vgic.rdist_pendbase); > + val &= ~GICR_PENDBASER_PTZ; /* WO, reads as 0 */ > + *r = vreg_reg64_extract(val, info); > return 1; > } > > @@ -577,10 +576,10 @@ static int __vgic_v3_rdistr_rd_mmio_write(struct vcpu > *v, mmio_info_t *info, > /* Writing PENDBASER with LPIs enabled is UNPREDICTABLE. */ > if ( !(v->arch.vgic.flags & VGIC_V3_LPIS_ENABLED) ) > { > - reg = v->arch.vgic.rdist_pendbase; > + reg = read_atomic(&v->arch.vgic.rdist_pendbase); > vreg_reg64_update(®, r, info); > reg = sanitize_pendbaser(reg); > - v->arch.vgic.rdist_pendbase = reg; > + write_atomic(&v->arch.vgic.rdist_pendbase, reg); > } > > spin_unlock_irqrestore(&v->arch.vgic.lock, false);
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |