From: David Woodhouse The v2_groups_user_writable flag was introduced to gate GICv2 userspace IGROUPR writes until userspace explicitly wrote the IIDR, signalling awareness of the group semantics. However, the guest write path through vgic_mmio_write_group() was never gated by this flag, allowing a GICv2 guest to modify interrupt groups regardless of whether userspace had opted in. Rather than adding the same flag check to the guest path, remove the flag entirely and make both guest and userspace IGROUPR writability follow the IIDR implementation revision directly. Groups are writable when the revision is >= 2, which is the case when userspace explicitly sets the IIDR to revision 2 or 3. When userspace does not write the IIDR, vgic_init() defaults to KVM_VGIC_IMP_REV_LATEST (currently 3), so the behaviour is unchanged for userspace that doesn't set the IIDR. This also fixes the inconsistency where a GICv2 guest could write IGROUPR even when the IIDR had not been explicitly set by userspace. Fixes: d53c2c29ae0d ("KVM: arm/arm64: vgic: Allow configuration of interrupt groups") Signed-off-by: David Woodhouse --- arch/arm64/kvm/vgic/vgic-mmio-v2.c | 16 +++++----------- include/kvm/arm_vgic.h | 3 --- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v2.c b/arch/arm64/kvm/vgic/vgic-mmio-v2.c index e5714f7fd2ec..e5fc673a1ea9 100644 --- a/arch/arm64/kvm/vgic/vgic-mmio-v2.c +++ b/arch/arm64/kvm/vgic/vgic-mmio-v2.c @@ -84,21 +84,15 @@ static int vgic_mmio_uaccess_write_v2_misc(struct kvm_vcpu *vcpu, return -EINVAL; /* - * If we observe a write to GICD_IIDR we know that userspace - * has been updated and has had a chance to cope with older - * kernels (VGICv2 IIDR.Revision == 0) incorrectly reporting - * interrupts as group 1, and therefore we now allow groups to - * be user writable. Doing this by default would break - * migration from old kernels to new kernels with legacy - * userspace. + * Allow userspace to select the GICv2 IIDR revision. + * Group writability follows the revision directly: + * groups are guest/user writable for revision >= 2. */ reg = FIELD_GET(GICD_IIDR_REVISION_MASK, val); switch (reg) { + case KVM_VGIC_IMP_REV_1: case KVM_VGIC_IMP_REV_2: case KVM_VGIC_IMP_REV_3: - vcpu->kvm->arch.vgic.v2_groups_user_writable = true; - fallthrough; - case KVM_VGIC_IMP_REV_1: dist->implementation_rev = reg; return 0; default: @@ -114,7 +108,7 @@ static int vgic_mmio_uaccess_write_v2_group(struct kvm_vcpu *vcpu, gpa_t addr, unsigned int len, unsigned long val) { - if (vcpu->kvm->arch.vgic.v2_groups_user_writable) + if (vgic_get_implementation_rev(vcpu) >= KVM_VGIC_IMP_REV_2) vgic_mmio_write_group(vcpu, addr, len, val); return 0; diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h index 90fb6cd3c91c..cdfab2c20877 100644 --- a/include/kvm/arm_vgic.h +++ b/include/kvm/arm_vgic.h @@ -253,9 +253,6 @@ struct vgic_dist { #define KVM_VGIC_IMP_REV_3 3 /* GICv3 GICR_CTLR.{IW,CES,RWP} */ #define KVM_VGIC_IMP_REV_LATEST KVM_VGIC_IMP_REV_3 - /* Userspace can write to GICv2 IGROUPR */ - bool v2_groups_user_writable; - /* Do injected MSIs require an additional device ID? */ bool msis_require_devid; -- 2.51.0