Skip to content

Commit faf7714

Browse files
Andre-ARMoupton
authored andcommitted
KVM: arm64: nv: Allow userland to set VGIC maintenance IRQ
The VGIC maintenance IRQ signals various conditions about the LRs, when the GIC's virtualization extension is used. So far we didn't need it, but nested virtualization needs to know about this interrupt, so add a userland interface to setup the IRQ number. The architecture mandates that it must be a PPI, on top of that this code only exports a per-device option, so the PPI is the same on all VCPUs. Signed-off-by: Andre Przywara <andre.przywara@arm.com> [added some bits of documentation] Signed-off-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20250225172930.1850838-16-maz@kernel.org Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
1 parent 89896cc commit faf7714

File tree

4 files changed

+40
-3
lines changed

4 files changed

+40
-3
lines changed

Documentation/virt/kvm/devices/arm-vgic-v3.rst

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,8 +291,18 @@ Groups:
291291
| Aff3 | Aff2 | Aff1 | Aff0 |
292292

293293
Errors:
294-
295294
======= =============================================
296295
-EINVAL vINTID is not multiple of 32 or info field is
297296
not VGIC_LEVEL_INFO_LINE_LEVEL
298297
======= =============================================
298+
299+
KVM_DEV_ARM_VGIC_GRP_MAINT_IRQ
300+
Attributes:
301+
302+
The attr field of kvm_device_attr encodes the following values:
303+
304+
bits: | 31 .... 5 | 4 .... 0 |
305+
values: | RES0 | vINTID |
306+
307+
The vINTID specifies which interrupt is generated when the vGIC
308+
must generate a maintenance interrupt. This must be a PPI.

arch/arm64/include/uapi/asm/kvm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@ enum {
403403
#define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6
404404
#define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7
405405
#define KVM_DEV_ARM_VGIC_GRP_ITS_REGS 8
406+
#define KVM_DEV_ARM_VGIC_GRP_MAINT_IRQ 9
406407
#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10
407408
#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
408409
(0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)

arch/arm64/kvm/vgic/vgic-kvm-device.c

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,12 @@ static int vgic_get_common_attr(struct kvm_device *dev,
303303
VGIC_NR_PRIVATE_IRQS, uaddr);
304304
break;
305305
}
306+
case KVM_DEV_ARM_VGIC_GRP_MAINT_IRQ: {
307+
u32 __user *uaddr = (u32 __user *)(long)attr->addr;
308+
309+
r = put_user(dev->kvm->arch.vgic.mi_intid, uaddr);
310+
break;
311+
}
306312
}
307313

308314
return r;
@@ -517,7 +523,7 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev,
517523
struct vgic_reg_attr reg_attr;
518524
gpa_t addr;
519525
struct kvm_vcpu *vcpu;
520-
bool uaccess;
526+
bool uaccess, post_init = true;
521527
u32 val;
522528
int ret;
523529

@@ -533,6 +539,9 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev,
533539
/* Sysregs uaccess is performed by the sysreg handling code */
534540
uaccess = false;
535541
break;
542+
case KVM_DEV_ARM_VGIC_GRP_MAINT_IRQ:
543+
post_init = false;
544+
fallthrough;
536545
default:
537546
uaccess = true;
538547
}
@@ -552,7 +561,7 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev,
552561

553562
mutex_lock(&dev->kvm->arch.config_lock);
554563

555-
if (unlikely(!vgic_initialized(dev->kvm))) {
564+
if (post_init != vgic_initialized(dev->kvm)) {
556565
ret = -EBUSY;
557566
goto out;
558567
}
@@ -582,6 +591,19 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev,
582591
}
583592
break;
584593
}
594+
case KVM_DEV_ARM_VGIC_GRP_MAINT_IRQ:
595+
if (!is_write) {
596+
val = dev->kvm->arch.vgic.mi_intid;
597+
ret = 0;
598+
break;
599+
}
600+
601+
ret = -EINVAL;
602+
if ((val < VGIC_NR_PRIVATE_IRQS) && (val >= VGIC_NR_SGIS)) {
603+
dev->kvm->arch.vgic.mi_intid = val;
604+
ret = 0;
605+
}
606+
break;
585607
default:
586608
ret = -EINVAL;
587609
break;
@@ -608,6 +630,7 @@ static int vgic_v3_set_attr(struct kvm_device *dev,
608630
case KVM_DEV_ARM_VGIC_GRP_REDIST_REGS:
609631
case KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS:
610632
case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO:
633+
case KVM_DEV_ARM_VGIC_GRP_MAINT_IRQ:
611634
return vgic_v3_attr_regs_access(dev, attr, true);
612635
default:
613636
return vgic_set_common_attr(dev, attr);
@@ -622,6 +645,7 @@ static int vgic_v3_get_attr(struct kvm_device *dev,
622645
case KVM_DEV_ARM_VGIC_GRP_REDIST_REGS:
623646
case KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS:
624647
case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO:
648+
case KVM_DEV_ARM_VGIC_GRP_MAINT_IRQ:
625649
return vgic_v3_attr_regs_access(dev, attr, false);
626650
default:
627651
return vgic_get_common_attr(dev, attr);
@@ -645,6 +669,7 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
645669
case KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS:
646670
return vgic_v3_has_attr_regs(dev, attr);
647671
case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
672+
case KVM_DEV_ARM_VGIC_GRP_MAINT_IRQ:
648673
return 0;
649674
case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {
650675
if (((attr->attr & KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK) >>

tools/arch/arm/include/uapi/asm/kvm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ struct kvm_vcpu_events {
246246
#define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6
247247
#define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7
248248
#define KVM_DEV_ARM_VGIC_GRP_ITS_REGS 8
249+
#define KVM_DEV_ARM_VGIC_GRP_MAINT_IRQ 9
249250
#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10
250251
#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
251252
(0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)

0 commit comments

Comments
 (0)