Skip to content

Commit 56e3e5c

Browse files
committed
Merge branch 'kvm-arm64/nv-vgic' into kvmarm/next
* kvm-arm64/nv-vgic: : NV VGICv3 support, courtesy of Marc Zyngier : : Support for emulating the GIC hypervisor controls and managing shadow : VGICv3 state for the L1 hypervisor. As part of it, bring in support for : taking IRQs to the L1 and UAPI to manage the VGIC maintenance interrupt. KVM: arm64: nv: Fail KVM init if asking for NV without GICv3 KVM: arm64: nv: Allow userland to set VGIC maintenance IRQ KVM: arm64: nv: Fold GICv3 host trapping requirements into guest setup KVM: arm64: nv: Propagate used_lrs between L1 and L0 contexts KVM: arm64: nv: Request vPE doorbell upon nested ERET to L2 KVM: arm64: nv: Respect virtual HCR_EL2.TWx setting KVM: arm64: nv: Add Maintenance Interrupt emulation KVM: arm64: nv: Handle L2->L1 transition on interrupt injection KVM: arm64: nv: Nested GICv3 emulation KVM: arm64: nv: Sanitise ICH_HCR_EL2 accesses KVM: arm64: nv: Plumb handling of GICv3 EL2 accesses KVM: arm64: nv: Add ICH_*_EL2 registers to vpcu_sysreg KVM: arm64: nv: Load timer before the GIC arm64: sysreg: Add layout for ICH_MISR_EL2 arm64: sysreg: Add layout for ICH_VTR_EL2 arm64: sysreg: Add layout for ICH_HCR_EL2 Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
2 parents 3ed0dc0 + 83c6cb2 commit 56e3e5c

File tree

26 files changed

+833
-117
lines changed

26 files changed

+833
-117
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/asm/kvm_emulate.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,19 @@ static __always_inline u64 kvm_vcpu_get_esr(const struct kvm_vcpu *vcpu)
275275
return vcpu->arch.fault.esr_el2;
276276
}
277277

278+
static inline bool guest_hyp_wfx_traps_enabled(const struct kvm_vcpu *vcpu)
279+
{
280+
u64 esr = kvm_vcpu_get_esr(vcpu);
281+
bool is_wfe = !!(esr & ESR_ELx_WFx_ISS_WFE);
282+
u64 hcr_el2 = __vcpu_sys_reg(vcpu, HCR_EL2);
283+
284+
if (!vcpu_has_nv(vcpu) || vcpu_is_el2(vcpu))
285+
return false;
286+
287+
return ((is_wfe && (hcr_el2 & HCR_TWE)) ||
288+
(!is_wfe && (hcr_el2 & HCR_TWI)));
289+
}
290+
278291
static __always_inline int kvm_vcpu_get_condition(const struct kvm_vcpu *vcpu)
279292
{
280293
u64 esr = kvm_vcpu_get_esr(vcpu);

arch/arm64/include/asm/kvm_host.h

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,15 @@
4444

4545
#define KVM_REQ_SLEEP \
4646
KVM_ARCH_REQ_FLAGS(0, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
47-
#define KVM_REQ_IRQ_PENDING KVM_ARCH_REQ(1)
48-
#define KVM_REQ_VCPU_RESET KVM_ARCH_REQ(2)
49-
#define KVM_REQ_RECORD_STEAL KVM_ARCH_REQ(3)
50-
#define KVM_REQ_RELOAD_GICv4 KVM_ARCH_REQ(4)
51-
#define KVM_REQ_RELOAD_PMU KVM_ARCH_REQ(5)
52-
#define KVM_REQ_SUSPEND KVM_ARCH_REQ(6)
53-
#define KVM_REQ_RESYNC_PMU_EL0 KVM_ARCH_REQ(7)
54-
#define KVM_REQ_NESTED_S2_UNMAP KVM_ARCH_REQ(8)
47+
#define KVM_REQ_IRQ_PENDING KVM_ARCH_REQ(1)
48+
#define KVM_REQ_VCPU_RESET KVM_ARCH_REQ(2)
49+
#define KVM_REQ_RECORD_STEAL KVM_ARCH_REQ(3)
50+
#define KVM_REQ_RELOAD_GICv4 KVM_ARCH_REQ(4)
51+
#define KVM_REQ_RELOAD_PMU KVM_ARCH_REQ(5)
52+
#define KVM_REQ_SUSPEND KVM_ARCH_REQ(6)
53+
#define KVM_REQ_RESYNC_PMU_EL0 KVM_ARCH_REQ(7)
54+
#define KVM_REQ_NESTED_S2_UNMAP KVM_ARCH_REQ(8)
55+
#define KVM_REQ_GUEST_HYP_IRQ_PENDING KVM_ARCH_REQ(9)
5556

5657
#define KVM_DIRTY_LOG_MANUAL_CAPS (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \
5758
KVM_DIRTY_LOG_INITIALLY_SET)
@@ -557,7 +558,33 @@ enum vcpu_sysreg {
557558
VNCR(CNTP_CVAL_EL0),
558559
VNCR(CNTP_CTL_EL0),
559560

561+
VNCR(ICH_LR0_EL2),
562+
VNCR(ICH_LR1_EL2),
563+
VNCR(ICH_LR2_EL2),
564+
VNCR(ICH_LR3_EL2),
565+
VNCR(ICH_LR4_EL2),
566+
VNCR(ICH_LR5_EL2),
567+
VNCR(ICH_LR6_EL2),
568+
VNCR(ICH_LR7_EL2),
569+
VNCR(ICH_LR8_EL2),
570+
VNCR(ICH_LR9_EL2),
571+
VNCR(ICH_LR10_EL2),
572+
VNCR(ICH_LR11_EL2),
573+
VNCR(ICH_LR12_EL2),
574+
VNCR(ICH_LR13_EL2),
575+
VNCR(ICH_LR14_EL2),
576+
VNCR(ICH_LR15_EL2),
577+
578+
VNCR(ICH_AP0R0_EL2),
579+
VNCR(ICH_AP0R1_EL2),
580+
VNCR(ICH_AP0R2_EL2),
581+
VNCR(ICH_AP0R3_EL2),
582+
VNCR(ICH_AP1R0_EL2),
583+
VNCR(ICH_AP1R1_EL2),
584+
VNCR(ICH_AP1R2_EL2),
585+
VNCR(ICH_AP1R3_EL2),
560586
VNCR(ICH_HCR_EL2),
587+
VNCR(ICH_VMCR_EL2),
561588

562589
NR_SYS_REGS /* Nothing after this line! */
563590
};
@@ -919,6 +946,8 @@ struct kvm_vcpu_arch {
919946
#define PMUSERENR_ON_CPU __vcpu_single_flag(sflags, BIT(5))
920947
/* WFI instruction trapped */
921948
#define IN_WFI __vcpu_single_flag(sflags, BIT(6))
949+
/* KVM is currently emulating a nested ERET */
950+
#define IN_NESTED_ERET __vcpu_single_flag(sflags, BIT(7))
922951

923952

924953
/* Pointer to the vcpu's SVE FFR for sve_{save,load}_state() */

arch/arm64/include/asm/kvm_hyp.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ DECLARE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params);
7676

7777
int __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu);
7878

79+
u64 __gic_v3_get_lr(unsigned int lr);
80+
7981
void __vgic_v3_save_state(struct vgic_v3_cpu_if *cpu_if);
8082
void __vgic_v3_restore_state(struct vgic_v3_cpu_if *cpu_if);
8183
void __vgic_v3_activate_traps(struct vgic_v3_cpu_if *cpu_if);

arch/arm64/include/asm/sysreg.h

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -562,9 +562,6 @@
562562

563563
#define SYS_ICH_VSEIR_EL2 sys_reg(3, 4, 12, 9, 4)
564564
#define SYS_ICC_SRE_EL2 sys_reg(3, 4, 12, 9, 5)
565-
#define SYS_ICH_HCR_EL2 sys_reg(3, 4, 12, 11, 0)
566-
#define SYS_ICH_VTR_EL2 sys_reg(3, 4, 12, 11, 1)
567-
#define SYS_ICH_MISR_EL2 sys_reg(3, 4, 12, 11, 2)
568565
#define SYS_ICH_EISR_EL2 sys_reg(3, 4, 12, 11, 3)
569566
#define SYS_ICH_ELRSR_EL2 sys_reg(3, 4, 12, 11, 5)
570567
#define SYS_ICH_VMCR_EL2 sys_reg(3, 4, 12, 11, 7)
@@ -985,10 +982,6 @@
985982
#define SYS_MPIDR_SAFE_VAL (BIT(31))
986983

987984
/* GIC Hypervisor interface registers */
988-
/* ICH_MISR_EL2 bit definitions */
989-
#define ICH_MISR_EOI (1 << 0)
990-
#define ICH_MISR_U (1 << 1)
991-
992985
/* ICH_LR*_EL2 bit definitions */
993986
#define ICH_LR_VIRTUAL_ID_MASK ((1ULL << 32) - 1)
994987

@@ -1003,17 +996,6 @@
1003996
#define ICH_LR_PRIORITY_SHIFT 48
1004997
#define ICH_LR_PRIORITY_MASK (0xffULL << ICH_LR_PRIORITY_SHIFT)
1005998

1006-
/* ICH_HCR_EL2 bit definitions */
1007-
#define ICH_HCR_EN (1 << 0)
1008-
#define ICH_HCR_UIE (1 << 1)
1009-
#define ICH_HCR_NPIE (1 << 3)
1010-
#define ICH_HCR_TC (1 << 10)
1011-
#define ICH_HCR_TALL0 (1 << 11)
1012-
#define ICH_HCR_TALL1 (1 << 12)
1013-
#define ICH_HCR_TDIR (1 << 14)
1014-
#define ICH_HCR_EOIcount_SHIFT 27
1015-
#define ICH_HCR_EOIcount_MASK (0x1f << ICH_HCR_EOIcount_SHIFT)
1016-
1017999
/* ICH_VMCR_EL2 bit definitions */
10181000
#define ICH_VMCR_ACK_CTL_SHIFT 2
10191001
#define ICH_VMCR_ACK_CTL_MASK (1 << ICH_VMCR_ACK_CTL_SHIFT)
@@ -1034,18 +1016,6 @@
10341016
#define ICH_VMCR_ENG1_SHIFT 1
10351017
#define ICH_VMCR_ENG1_MASK (1 << ICH_VMCR_ENG1_SHIFT)
10361018

1037-
/* ICH_VTR_EL2 bit definitions */
1038-
#define ICH_VTR_PRI_BITS_SHIFT 29
1039-
#define ICH_VTR_PRI_BITS_MASK (7 << ICH_VTR_PRI_BITS_SHIFT)
1040-
#define ICH_VTR_ID_BITS_SHIFT 23
1041-
#define ICH_VTR_ID_BITS_MASK (7 << ICH_VTR_ID_BITS_SHIFT)
1042-
#define ICH_VTR_SEIS_SHIFT 22
1043-
#define ICH_VTR_SEIS_MASK (1 << ICH_VTR_SEIS_SHIFT)
1044-
#define ICH_VTR_A3V_SHIFT 21
1045-
#define ICH_VTR_A3V_MASK (1 << ICH_VTR_A3V_SHIFT)
1046-
#define ICH_VTR_TDS_SHIFT 19
1047-
#define ICH_VTR_TDS_MASK (1 << ICH_VTR_TDS_SHIFT)
1048-
10491019
/*
10501020
* Permission Indirection Extension (PIE) permission encodings.
10511021
* Encodings with the _O suffix, have overlays applied (Permission Overlay Extension).

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/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ kvm-y += arm.o mmu.o mmio.o psci.o hypercalls.o pvtime.o \
2323
vgic/vgic-v3.o vgic/vgic-v4.o \
2424
vgic/vgic-mmio.o vgic/vgic-mmio-v2.o \
2525
vgic/vgic-mmio-v3.o vgic/vgic-kvm-device.o \
26-
vgic/vgic-its.o vgic/vgic-debug.o
26+
vgic/vgic-its.o vgic/vgic-debug.o vgic/vgic-v3-nested.o
2727

2828
kvm-$(CONFIG_HW_PERF_EVENTS) += pmu-emul.o pmu.o
2929
kvm-$(CONFIG_ARM64_PTR_AUTH) += pauth.o

arch/arm64/kvm/arm.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -590,8 +590,12 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
590590
nommu:
591591
vcpu->cpu = cpu;
592592

593-
kvm_vgic_load(vcpu);
593+
/*
594+
* The timer must be loaded before the vgic to correctly set up physical
595+
* interrupt deactivation in nested state (e.g. timer interrupt).
596+
*/
594597
kvm_timer_vcpu_load(vcpu);
598+
kvm_vgic_load(vcpu);
595599
kvm_vcpu_load_debug(vcpu);
596600
if (has_vhe())
597601
kvm_vcpu_load_vhe(vcpu);
@@ -829,6 +833,12 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
829833
if (ret)
830834
return ret;
831835

836+
if (vcpu_has_nv(vcpu)) {
837+
ret = kvm_vgic_vcpu_nv_init(vcpu);
838+
if (ret)
839+
return ret;
840+
}
841+
832842
/*
833843
* This needs to happen after any restriction has been applied
834844
* to the feature set.
@@ -2311,6 +2321,13 @@ static int __init init_subsystems(void)
23112321
goto out;
23122322
}
23132323

2324+
if (kvm_mode == KVM_MODE_NV &&
2325+
!(vgic_present && kvm_vgic_global_state.type == VGIC_V3)) {
2326+
kvm_err("NV support requires GICv3, giving up\n");
2327+
err = -EINVAL;
2328+
goto out;
2329+
}
2330+
23142331
/*
23152332
* Init HYP architected timer support
23162333
*/

arch/arm64/kvm/emulate-nested.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -412,26 +412,26 @@ static const struct trap_bits coarse_trap_bits[] = {
412412
},
413413
[CGT_ICH_HCR_TC] = {
414414
.index = ICH_HCR_EL2,
415-
.value = ICH_HCR_TC,
416-
.mask = ICH_HCR_TC,
415+
.value = ICH_HCR_EL2_TC,
416+
.mask = ICH_HCR_EL2_TC,
417417
.behaviour = BEHAVE_FORWARD_RW,
418418
},
419419
[CGT_ICH_HCR_TALL0] = {
420420
.index = ICH_HCR_EL2,
421-
.value = ICH_HCR_TALL0,
422-
.mask = ICH_HCR_TALL0,
421+
.value = ICH_HCR_EL2_TALL0,
422+
.mask = ICH_HCR_EL2_TALL0,
423423
.behaviour = BEHAVE_FORWARD_RW,
424424
},
425425
[CGT_ICH_HCR_TALL1] = {
426426
.index = ICH_HCR_EL2,
427-
.value = ICH_HCR_TALL1,
428-
.mask = ICH_HCR_TALL1,
427+
.value = ICH_HCR_EL2_TALL1,
428+
.mask = ICH_HCR_EL2_TALL1,
429429
.behaviour = BEHAVE_FORWARD_RW,
430430
},
431431
[CGT_ICH_HCR_TDIR] = {
432432
.index = ICH_HCR_EL2,
433-
.value = ICH_HCR_TDIR,
434-
.mask = ICH_HCR_TDIR,
433+
.value = ICH_HCR_EL2_TDIR,
434+
.mask = ICH_HCR_EL2_TDIR,
435435
.behaviour = BEHAVE_FORWARD_RW,
436436
},
437437
};
@@ -2503,6 +2503,7 @@ void kvm_emulate_nested_eret(struct kvm_vcpu *vcpu)
25032503
}
25042504

25052505
preempt_disable();
2506+
vcpu_set_flag(vcpu, IN_NESTED_ERET);
25062507
kvm_arch_vcpu_put(vcpu);
25072508

25082509
if (!esr_iss_is_eretax(esr))
@@ -2514,6 +2515,7 @@ void kvm_emulate_nested_eret(struct kvm_vcpu *vcpu)
25142515
*vcpu_cpsr(vcpu) = spsr;
25152516

25162517
kvm_arch_vcpu_load(vcpu, smp_processor_id());
2518+
vcpu_clear_flag(vcpu, IN_NESTED_ERET);
25172519
preempt_enable();
25182520

25192521
kvm_pmu_nested_transition(vcpu);

arch/arm64/kvm/handle_exit.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,12 @@ static int kvm_handle_fpasimd(struct kvm_vcpu *vcpu)
129129
static int kvm_handle_wfx(struct kvm_vcpu *vcpu)
130130
{
131131
u64 esr = kvm_vcpu_get_esr(vcpu);
132+
bool is_wfe = !!(esr & ESR_ELx_WFx_ISS_WFE);
132133

133-
if (esr & ESR_ELx_WFx_ISS_WFE) {
134+
if (guest_hyp_wfx_traps_enabled(vcpu))
135+
return kvm_inject_nested_sync(vcpu, kvm_vcpu_get_esr(vcpu));
136+
137+
if (is_wfe) {
134138
trace_kvm_wfx_arm64(*vcpu_pc(vcpu), true);
135139
vcpu->stat.wfe_exit_stat++;
136140
} else {

0 commit comments

Comments
 (0)