]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: arm64: vgic: Fix IIDR revision field extracted from wrong value
authorDavid Woodhouse <dwmw@amazon.co.uk>
Tue, 7 Apr 2026 20:27:02 +0000 (21:27 +0100)
committerMarc Zyngier <maz@kernel.org>
Fri, 24 Apr 2026 11:03:47 +0000 (12:03 +0100)
The uaccess write handlers for GICD_IIDR in both GICv2 and GICv3
extract the revision field from 'reg' (the current IIDR value read back
from the emulated distributor) instead of 'val' (the value userspace is
trying to write). This means userspace can never actually change the
implementation revision — the extracted value is always the current one.

Fix the FIELD_GET to use 'val' so that userspace can select a different
revision for migration compatibility.

Fixes: 49a1a2c70a7f ("KVM: arm64: vgic-v3: Advertise GICR_CTLR.{IR, CES} as a new GICD_IIDR revision")
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Link: https://patch.msgid.link/20260407210949.2076251-2-dwmw2@infradead.org
Signed-off-by: Marc Zyngier <maz@kernel.org>
Cc: stable@vger.kernel.org
arch/arm64/kvm/vgic/vgic-mmio-v2.c
arch/arm64/kvm/vgic/vgic-mmio-v3.c

index 406845b3117cfb280c64320fed3e038b9420f5cb..0643e333db35dc6fa0105afe4ef3c0f87d7907f0 100644 (file)
@@ -91,7 +91,7 @@ static int vgic_mmio_uaccess_write_v2_misc(struct kvm_vcpu *vcpu,
                 * migration from old kernels to new kernels with legacy
                 * userspace.
                 */
-               reg = FIELD_GET(GICD_IIDR_REVISION_MASK, reg);
+               reg = FIELD_GET(GICD_IIDR_REVISION_MASK, val);
                switch (reg) {
                case KVM_VGIC_IMP_REV_2:
                case KVM_VGIC_IMP_REV_3:
index 89edb84d1ac6d29db08f99fd276e0e67ecab7ac2..5913a20d830191bd7c54c7ac862f16da42d0fa28 100644 (file)
@@ -194,7 +194,7 @@ static int vgic_mmio_uaccess_write_v3_misc(struct kvm_vcpu *vcpu,
                if ((reg ^ val) & ~GICD_IIDR_REVISION_MASK)
                        return -EINVAL;
 
-               reg = FIELD_GET(GICD_IIDR_REVISION_MASK, reg);
+               reg = FIELD_GET(GICD_IIDR_REVISION_MASK, val);
                switch (reg) {
                case KVM_VGIC_IMP_REV_2:
                case KVM_VGIC_IMP_REV_3: