From: Oliver Upton Date: Thu, 24 Jul 2025 06:28:02 +0000 (-0700) Subject: KVM: arm64: vgic-v3: Allow access to GICD_IIDR prior to initialization X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f26e6af75782fad6efdc883f33e1c40f1a6d37e7;p=thirdparty%2Flinux.git KVM: arm64: vgic-v3: Allow access to GICD_IIDR prior to initialization KVM allows userspace to write GICD_IIDR for backwards-compatibility with older kernels, where new implementation revisions have new features. Unfortunately this is allowed to happen at runtime, and ripping features out from underneath a running guest is a terrible idea. While we can't do anything about the ABI, prepare for more ID-like registers by allowing access to GICD_IIDR prior to VGIC initialization. Hoist initializaiton of the default value to kvm_vgic_create() and discard the incorrect comment that assumed userspace could access the register before initialization (until now). Subsequent changes will allow the VMM to further provision the GIC feature set, e.g. the presence of nASSGIcap. Reviewed-by: Eric Auger Reviewed-by: Marc Zyngier Link: https://lore.kernel.org/r/20250724062805.2658919-4-oliver.upton@linux.dev Signed-off-by: Oliver Upton --- diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c index 0d8bc2ac627a2..31462ba093c9b 100644 --- a/arch/arm64/kvm/vgic/vgic-init.c +++ b/arch/arm64/kvm/vgic/vgic-init.c @@ -157,6 +157,7 @@ int kvm_vgic_create(struct kvm *kvm, u32 type) kvm->arch.vgic.in_kernel = true; kvm->arch.vgic.vgic_model = type; + kvm->arch.vgic.implementation_rev = KVM_VGIC_IMP_REV_LATEST; kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF; @@ -408,15 +409,7 @@ int vgic_init(struct kvm *kvm) goto out; vgic_debug_init(kvm); - - /* - * If userspace didn't set the GIC implementation revision, - * default to the latest and greatest. You know want it. - */ - if (!dist->implementation_rev) - dist->implementation_rev = KVM_VGIC_IMP_REV_LATEST; dist->initialized = true; - out: return ret; } diff --git a/arch/arm64/kvm/vgic/vgic-kvm-device.c b/arch/arm64/kvm/vgic/vgic-kvm-device.c index 00c011cc86278..8e24d550d9d29 100644 --- a/arch/arm64/kvm/vgic/vgic-kvm-device.c +++ b/arch/arm64/kvm/vgic/vgic-kvm-device.c @@ -5,6 +5,7 @@ * Copyright (C) 2015 ARM Ltd. * Author: Marc Zyngier */ +#include #include #include #include @@ -503,6 +504,23 @@ int vgic_v3_parse_attr(struct kvm_device *dev, struct kvm_device_attr *attr, return 0; } +/* + * Allow access to certain ID-like registers prior to VGIC initialization, + * thereby allowing the VMM to provision the features / sizing of the VGIC. + */ +static bool reg_allowed_pre_init(struct kvm_device_attr *attr) +{ + if (attr->group != KVM_DEV_ARM_VGIC_GRP_DIST_REGS) + return false; + + switch (attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK) { + case GICD_IIDR: + return true; + default: + return false; + } +} + /* * vgic_v3_attr_regs_access - allows user space to access VGIC v3 state * @@ -552,7 +570,7 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev, mutex_lock(&dev->kvm->arch.config_lock); - if (!vgic_initialized(dev->kvm)) { + if (!(vgic_initialized(dev->kvm) || reg_allowed_pre_init(attr))) { ret = -EBUSY; goto out; }