From: David Woodhouse <[email protected]>
Allow userspace to select GICD_IIDR revision 1, which restores the
original pre-d53c2c29ae0d ("KVM: arm/arm64: vgic: Allow configuration
of interrupt groups") behaviour where interrupt groups are not
guest-configurable.
When revision 1 is selected:
- GICv2: IGROUPR reads as zero (group 0), writes are ignored
- GICv3: IGROUPR reads as all-ones (group 1), writes are ignored
- v2_groups_user_writable is not set
This is implemented by checking the implementation revision in
vgic_mmio_write_group() and suppressing writes when the revision is
below 2. The read side needs no change since the per-IRQ group reset
values already match the expected behaviour.
Note that d53c2c29ae0d wired guest IGROUPR writes directly to
vgic_mmio_write_group() without any revision check, while only gating
the userspace write path via v2_groups_user_writable. This meant a
guest could modify interrupt groups even at revision 1, which was
never intended. The write_group revision check fixes both the guest
and GICv3 userspace paths.
Fixes: d53c2c29ae0d ("KVM: arm/arm64: vgic: Allow configuration of interrupt
groups")
Signed-off-by: David Woodhouse <[email protected]>
---
arch/arm64/kvm/vgic/vgic-mmio-v2.c | 3 +++
arch/arm64/kvm/vgic/vgic-mmio-v3.c | 4 ++++
arch/arm64/kvm/vgic/vgic-mmio.c | 4 ++++
include/kvm/arm_vgic.h | 1 +
4 files changed, 12 insertions(+)
diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v2.c
b/arch/arm64/kvm/vgic/vgic-mmio-v2.c
index 0643e333db35..e5714f7fd2ec 100644
--- a/arch/arm64/kvm/vgic/vgic-mmio-v2.c
+++ b/arch/arm64/kvm/vgic/vgic-mmio-v2.c
@@ -20,6 +20,7 @@
* Revision 1: Report GICv2 interrupts as group 0 instead of group 1
* Revision 2: Interrupt groups are guest-configurable and signaled using
* their configured groups.
+ * Revision 3: GICv2 behaviour is unchanged from revision 2.
*/
static unsigned long vgic_mmio_read_v2_misc(struct kvm_vcpu *vcpu,
@@ -96,6 +97,8 @@ static int vgic_mmio_uaccess_write_v2_misc(struct kvm_vcpu
*vcpu,
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:
diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v3.c
b/arch/arm64/kvm/vgic/vgic-mmio-v3.c
index 5913a20d8301..0130db71cfc9 100644
--- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c
+++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c
@@ -74,8 +74,11 @@ bool vgic_supports_direct_sgis(struct kvm *kvm)
/*
* The Revision field in the IIDR have the following meanings:
*
+ * Revision 1: Interrupt groups are not guest-configurable.
+ * IGROUPR reads as all-ones (group 1), writes ignored.
* Revision 2: Interrupt groups are guest-configurable and signaled using
* their configured groups.
+ * Revision 3: GICR_CTLR.{IR,CES} are advertised.
*/
static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
@@ -196,6 +199,7 @@ static int vgic_mmio_uaccess_write_v3_misc(struct kvm_vcpu
*vcpu,
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:
dist->implementation_rev = reg;
diff --git a/arch/arm64/kvm/vgic/vgic-mmio.c b/arch/arm64/kvm/vgic/vgic-mmio.c
index a573b1f0c6cb..4fbe0ad22adf 100644
--- a/arch/arm64/kvm/vgic/vgic-mmio.c
+++ b/arch/arm64/kvm/vgic/vgic-mmio.c
@@ -73,6 +73,10 @@ void vgic_mmio_write_group(struct kvm_vcpu *vcpu, gpa_t addr,
int i;
unsigned long flags;
+ /* Revision 1 and below: groups are not guest-configurable. */
+ if (vgic_get_implementation_rev(vcpu) < KVM_VGIC_IMP_REV_2)
+ return;
+
for (i = 0; i < len * 8; i++) {
struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index f2eafc65bbf4..90fb6cd3c91c 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -248,6 +248,7 @@ struct vgic_dist {
/* Implementation revision as reported in the GICD_IIDR */
u32 implementation_rev;
+#define KVM_VGIC_IMP_REV_1 1 /* GICv2 interrupts as group 0 */
#define KVM_VGIC_IMP_REV_2 2 /* GICv2 restorable groups */
#define KVM_VGIC_IMP_REV_3 3 /* GICv3 GICR_CTLR.{IW,CES,RWP} */
#define KVM_VGIC_IMP_REV_LATEST KVM_VGIC_IMP_REV_3
--
2.51.0