KVM: arm64: Add NV GICv3 support
Subsystems (6)
Marc Zyngier
maintainerv4 cover KVM: arm64: Add NV GICv3 support
Here's a respin of the NV support for GICv3. The integration branch containing this (and the rest of the NV stack) is still at [4].
At this stage, I think this is good to go.
* From v3 [3]:
- Added a comment indicating the relative priority of L2->L1 IRQ handling as a request
- Rebased on 6.14-rc3
* From v2 [2]:
- Picked RBs from Andre, with thanks
- Rebased on 6.14-rc1
* From v1 [1]:
- Fix the default value for the MI INTID to PPI9, instead of something fairly random...
- Fail KVM initialisation if asking for NV on HW without a virtual
GICv3.
[1] https://lore.kernel.org/r/[email protected]
[2] https://lore.kernel.org/r/[email protected]
[3] https://lore.kernel.org/r/[email protected]
[4] https://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git/log/?h=kvm-arm64/nv-next
Andre Przywara (1):
KVM: arm64: nv: Allow userland to set VGIC maintenance IRQ
Jintack Lim (1):
KVM: arm64: nv: Respect virtual HCR_EL2.TWx setting
Marc Zyngier (13):
arm64: sysreg: Add layout for ICH_HCR_EL2
arm64: sysreg: Add layout for ICH_VTR_EL2
arm64: sysreg: Add layout for ICH_MISR_EL2
KVM: arm64: nv: Load timer before the GIC
KVM: arm64: nv: Add ICH_*_EL2 registers to vpcu_sysreg
KVM: arm64: nv: Plumb handling of GICv3 EL2 accesses
KVM: arm64: nv: Sanitise ICH_HCR_EL2 accesses
KVM: arm64: nv: Nested GICv3 emulation
KVM: arm64: nv: Handle L2->L1 transition on interrupt injection
KVM: arm64: nv: Add Maintenance Interrupt emulation
KVM: arm64: nv: Propagate used_lrs between L1 and L0 contexts
KVM: arm64: nv: Fold GICv3 host trapping requirements into guest setup
KVM: arm64: nv: Fail KVM init if asking for NV without GICv3
Oliver Upton (1):
KVM: arm64: nv: Request vPE doorbell upon nested ERET to L2
.../virt/kvm/devices/arm-vgic-v3.rst | 12 +- arch/arm64/include/asm/kvm_emulate.h | 13 + arch/arm64/include/asm/kvm_host.h | 45 +- arch/arm64/include/asm/kvm_hyp.h | 2 + arch/arm64/include/asm/sysreg.h | 30 -- arch/arm64/include/uapi/asm/kvm.h | 1 + arch/arm64/kvm/Makefile | 2 +- arch/arm64/kvm/arm.c | 20 +- arch/arm64/kvm/emulate-nested.c | 18 +- arch/arm64/kvm/handle_exit.c | 6 +- arch/arm64/kvm/hyp/vgic-v3-sr.c | 16 +- arch/arm64/kvm/nested.c | 13 + arch/arm64/kvm/sys_regs.c | 95 +++- arch/arm64/kvm/vgic-sys-reg-v3.c | 8 +- arch/arm64/kvm/vgic/vgic-init.c | 29 ++ arch/arm64/kvm/vgic/vgic-kvm-device.c | 29 +- arch/arm64/kvm/vgic/vgic-v3-nested.c | 409 ++++++++++++++++++ arch/arm64/kvm/vgic/vgic-v3.c | 44 +- arch/arm64/kvm/vgic/vgic-v4.c | 18 +- arch/arm64/kvm/vgic/vgic.c | 38 ++ arch/arm64/kvm/vgic/vgic.h | 6 + arch/arm64/tools/sysreg | 48 ++ drivers/irqchip/irq-apple-aic.c | 8 +- include/kvm/arm_vgic.h | 10 + tools/arch/arm/include/uapi/asm/kvm.h | 1 + tools/arch/arm64/include/asm/sysreg.h | 30 -- 26 files changed, 834 insertions(+), 117 deletions(-) create mode 100644 arch/arm64/kvm/vgic/vgic-v3-nested.c
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH v4 1/16 arm64: sysreg: Add layout for ICH_HCR_EL2
The ICH_HCR_EL2-related macros are missing a number of control bits that we are about to handle. Take this opportunity to fully describe the layout of that register as part of the automatic generation infrastructure.
This results in a bit of churn, unfortunately.
--- arch/arm64/include/asm/sysreg.h | 12 ------------ arch/arm64/kvm/emulate-nested.c | 16 ++++++++-------- arch/arm64/kvm/hyp/vgic-v3-sr.c | 14 +++++++------- arch/arm64/kvm/vgic/vgic-v3.c | 17 +++++++++-------- arch/arm64/tools/sysreg | 22 ++++++++++++++++++++++ drivers/irqchip/irq-apple-aic.c | 8 ++++---- tools/arch/arm64/include/asm/sysreg.h | 12 ------------ 7 files changed, 50 insertions(+), 51 deletions(-)
arch/arm64/include/asm/sysreg.h +0 -12
@@ -562,7 +562,6 @@#define SYS_ICH_VSEIR_EL2 sys_reg(3, 4, 12, 9, 4)#define SYS_ICC_SRE_EL2 sys_reg(3, 4, 12, 9, 5) -#define SYS_ICH_HCR_EL2 sys_reg(3, 4, 12, 11, 0)#define SYS_ICH_VTR_EL2 sys_reg(3, 4, 12, 11, 1)#define SYS_ICH_MISR_EL2 sys_reg(3, 4, 12, 11, 2)#define SYS_ICH_EISR_EL2 sys_reg(3, 4, 12, 11, 3)
@@ -1003,17 +1002,6 @@#define ICH_LR_PRIORITY_SHIFT 48#define ICH_LR_PRIORITY_MASK (0xffULL << ICH_LR_PRIORITY_SHIFT) -/* ICH_HCR_EL2 bit definitions */ -#define ICH_HCR_EN (1 << 0) -#define ICH_HCR_UIE (1 << 1) -#define ICH_HCR_NPIE (1 << 3) -#define ICH_HCR_TC (1 << 10) -#define ICH_HCR_TALL0 (1 << 11) -#define ICH_HCR_TALL1 (1 << 12) -#define ICH_HCR_TDIR (1 << 14) -#define ICH_HCR_EOIcount_SHIFT 27 -#define ICH_HCR_EOIcount_MASK (0x1f << ICH_HCR_EOIcount_SHIFT) -/* ICH_VMCR_EL2 bit definitions */ #define ICH_VMCR_ACK_CTL_SHIFT 2#define ICH_VMCR_ACK_CTL_MASK (1 << ICH_VMCR_ACK_CTL_SHIFT)
arch/arm64/kvm/emulate-nested.c +8 -8
@@ -412,26 +412,26 @@ static const struct trap_bits coarse_trap_bits[] = { }, [CGT_ICH_HCR_TC ] = { .index =ICH_HCR_EL2 , - .value =ICH_HCR_TC , - .mask =ICH_HCR_TC , + .value =ICH_HCR_EL2_TC , + .mask =ICH_HCR_EL2_TC , .behaviour =BEHAVE_FORWARD_RW , }, [CGT_ICH_HCR_TALL0 ] = { .index =ICH_HCR_EL2 , - .value =ICH_HCR_TALL0 , - .mask =ICH_HCR_TALL0 , + .value =ICH_HCR_EL2_TALL0 , + .mask =ICH_HCR_EL2_TALL0 , .behaviour =BEHAVE_FORWARD_RW , }, [CGT_ICH_HCR_TALL1 ] = { .index =ICH_HCR_EL2 , - .value =ICH_HCR_TALL1 , - .mask =ICH_HCR_TALL1 , + .value =ICH_HCR_EL2_TALL1 , + .mask =ICH_HCR_EL2_TALL1 , .behaviour =BEHAVE_FORWARD_RW , }, [CGT_ICH_HCR_TDIR ] = { .index =ICH_HCR_EL2 , - .value =ICH_HCR_TDIR , - .mask =ICH_HCR_TDIR , + .value =ICH_HCR_EL2_TDIR , + .mask =ICH_HCR_EL2_TDIR , .behaviour =BEHAVE_FORWARD_RW , }, };
arch/arm64/kvm/hyp/vgic-v3-sr.c +7 -7
@@ -218,7 +218,7 @@ void __vgic_v3_save_state(struct vgic_v3_cpu_if *cpu_if) elrsr =read_gicreg (ICH_ELRSR_EL2 ); -write_gicreg (cpu_if->vgic_hcr & ~ICH_HCR_EN ,ICH_HCR_EL2 ); +write_gicreg (cpu_if->vgic_hcr & ~ICH_HCR_EL2_En,ICH_HCR_EL2 );for (i =0 ; i < used_lrs; i++) {if (elrsr & (1 << i))
@@ -274,7 +274,7 @@ void __vgic_v3_activate_traps(struct vgic_v3_cpu_if *cpu_if)* system registers to trap to EL1 (duh), force ICC_SRE_EL1.SRE to 1 * so that the trap bits can take effect. Yes, we *loves* the GIC. */ -if (!(cpu_if->vgic_hcr &ICH_HCR_EN )) { +if (!(cpu_if->vgic_hcr & ICH_HCR_EL2_En)) {write_gicreg (ICC_SRE_EL1_SRE ,ICC_SRE_EL1 );isb (); }else if (!cpu_if->vgic_sre) {
@@ -752,7 +752,7 @@ static void __vgic_v3_bump_eoicount(void)u32 hcr; hcr =read_gicreg (ICH_HCR_EL2 ); - hcr +=1 << ICH_HCR_EOIcount_SHIFT; + hcr +=1 << ICH_HCR_EL2_EOIcount_SHIFT;write_gicreg (hcr,ICH_HCR_EL2 ); }
@@ -1069,7 +1069,7 @@ static bool __vgic_v3_check_trap_forwarding(struct kvm_vcpu *vcpu,case SYS_ICC_EOIR0_EL1 :case SYS_ICC_HPPIR0_EL1 :case SYS_ICC_IAR0_EL1 : -return ich_hcr &ICH_HCR_TALL0 ; +return ich_hcr &ICH_HCR_EL2_TALL0 ;case SYS_ICC_IGRPEN1_EL1 : if (is_read &&
@@ -1090,10 +1090,10 @@ static bool __vgic_v3_check_trap_forwarding(struct kvm_vcpu *vcpu,case SYS_ICC_EOIR1_EL1 :case SYS_ICC_HPPIR1_EL1 :case SYS_ICC_IAR1_EL1 : -return ich_hcr &ICH_HCR_TALL1 ; +return ich_hcr &ICH_HCR_EL2_TALL1 ;case SYS_ICC_DIR_EL1 : -if (ich_hcr &ICH_HCR_TDIR ) +if (ich_hcr &ICH_HCR_EL2_TDIR )return true; fallthrough;
@@ -1101,7 +1101,7 @@ static bool __vgic_v3_check_trap_forwarding(struct kvm_vcpu *vcpu,case SYS_ICC_RPR_EL1 :case SYS_ICC_CTLR_EL1 :case SYS_ICC_PMR_EL1 : -return ich_hcr &ICH_HCR_TC ; +return ich_hcr &ICH_HCR_EL2_TC ;default :return false;
arch/arm64/kvm/vgic/vgic-v3.c +9 -8
@@ -24,7 +24,7 @@ void vgic_v3_set_underflow(struct kvm_vcpu *vcpu) {struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3; - cpuif->vgic_hcr |=ICH_HCR_UIE ; + cpuif->vgic_hcr |=ICH_HCR_EL2_UIE ; }static bool lr_signals_eoi_mi (u64 lr_val)
@@ -42,7 +42,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)DEBUG_SPINLOCK_BUG_ON (!irqs_disabled ()); - cpuif->vgic_hcr &= ~ICH_HCR_UIE ; + cpuif->vgic_hcr &= ~ICH_HCR_EL2_UIE ;for (lr =0 ; lr < cpuif->used_lrs; lr++) {u64 val = cpuif->vgic_lr[lr];
@@ -292,7 +292,7 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu) ICH_VTR_PRI_BITS_SHIFT) + 1;/* Get the show on the road... */ - vgic_v3->vgic_hcr =ICH_HCR_EN ; + vgic_v3->vgic_hcr = ICH_HCR_EL2_En; }void vcpu_set_ich_hcr (struct kvm_vcpu *vcpu)
@@ -301,18 +301,19 @@ void vcpu_set_ich_hcr(struct kvm_vcpu *vcpu)/* Hide GICv3 sysreg if necessary */ if (!kvm_has_gicv3 (vcpu->kvm)) { - vgic_v3->vgic_hcr |=ICH_HCR_TALL0 |ICH_HCR_TALL1 |ICH_HCR_TC ; + vgic_v3->vgic_hcr |= (ICH_HCR_EL2_TALL0 |ICH_HCR_EL2_TALL1 | +ICH_HCR_EL2_TC );return ; }if (group0_trap) - vgic_v3->vgic_hcr |=ICH_HCR_TALL0 ; + vgic_v3->vgic_hcr |=ICH_HCR_EL2_TALL0 ;if (group1_trap) - vgic_v3->vgic_hcr |=ICH_HCR_TALL1 ; + vgic_v3->vgic_hcr |=ICH_HCR_EL2_TALL1 ;if (common_trap) - vgic_v3->vgic_hcr |=ICH_HCR_TC ; + vgic_v3->vgic_hcr |=ICH_HCR_EL2_TC ;if (dir_trap) - vgic_v3->vgic_hcr |=ICH_HCR_TDIR ; + vgic_v3->vgic_hcr |=ICH_HCR_EL2_TDIR ; }int vgic_v3_lpi_sync_pending_status (struct kvm *kvm,struct vgic_irq *irq)
arch/arm64/tools/sysreg +22 -0
@@ -3035,6 +3035,28 @@ Field 31:16 PhyPARTID29 Field 15:0 PhyPARTID28 EndSysreg +Sysreg ICH_HCR_EL2 3 4 12 11 0 +Res0 63:32 +Field 31:27 EOIcount +Res0 26:16 +Field 15 DVIM +Field 14 TDIR +Field 13 TSEI +Field 12 TALL1 +Field 11 TALL0 +Field 10 TC +Res0 9 +Field 8 vSGIEOICount +Field 7 VGrp1DIE +Field 6 VGrp1EIE +Field 5 VGrp0DIE +Field 4 VGrp0EIE +Field 3 NPIE +Field 2 LRENPIE +Field 1 UIE +Field 0 En +EndSysreg + Sysreg CONTEXTIDR_EL2 3 4 13 0 1 Fields CONTEXTIDR_ELx EndSysreg
drivers/irqchip/irq-apple-aic.c +4 -4
@@ -409,15 +409,15 @@ static void __exception_irq_entry aic_handle_irq(struct pt_regs *regs)* in use, and be cleared when coming back from the handler. */ if (is_kernel_in_hyp_mode () && - (read_sysreg_s (SYS_ICH_HCR_EL2 ) &ICH_HCR_EN ) && + (read_sysreg_s (SYS_ICH_HCR_EL2 ) & ICH_HCR_EL2_En) &&read_sysreg_s (SYS_ICH_MISR_EL2 ) !=0 ) {generic_handle_domain_irq (aic_irqc->hw_domain,AIC_FIQ_HWIRQ (AIC_VGIC_MI )); -if (unlikely ((read_sysreg_s (SYS_ICH_HCR_EL2 ) &ICH_HCR_EN ) && +if (unlikely ((read_sysreg_s (SYS_ICH_HCR_EL2 ) & ICH_HCR_EL2_En) &&read_sysreg_s (SYS_ICH_MISR_EL2 ))) {pr_err_ratelimited ("vGIC IRQ fired and not handled by KVM, disabling.\n" ); -sysreg_clear_set_s (SYS_ICH_HCR_EL2 ,ICH_HCR_EN ,0 ); +sysreg_clear_set_s (SYS_ICH_HCR_EL2 , ICH_HCR_EL2_En,0 ); } } }
@@ -841,7 +841,7 @@ static int aic_init_cpu(unsigned int cpu) VM_TMR_FIQ_ENABLE_V | VM_TMR_FIQ_ENABLE_P, 0);/* vGIC maintenance IRQ */ -sysreg_clear_set_s (SYS_ICH_HCR_EL2 ,ICH_HCR_EN ,0 ); +sysreg_clear_set_s (SYS_ICH_HCR_EL2 , ICH_HCR_EL2_En,0 ); }/* PMC FIQ */
tools/arch/arm64/include/asm/sysreg.h +0 -12
@@ -558,7 +558,6 @@#define SYS_ICH_VSEIR_EL2 sys_reg(3, 4, 12, 9, 4)#define SYS_ICC_SRE_EL2 sys_reg(3, 4, 12, 9, 5) -#define SYS_ICH_HCR_EL2 sys_reg(3, 4, 12, 11, 0)#define SYS_ICH_VTR_EL2 sys_reg(3, 4, 12, 11, 1)#define SYS_ICH_MISR_EL2 sys_reg(3, 4, 12, 11, 2)#define SYS_ICH_EISR_EL2 sys_reg(3, 4, 12, 11, 3)
@@ -999,17 +998,6 @@#define ICH_LR_PRIORITY_SHIFT 48#define ICH_LR_PRIORITY_MASK (0xffULL << ICH_LR_PRIORITY_SHIFT) -/* ICH_HCR_EL2 bit definitions */ -#define ICH_HCR_EN (1 << 0) -#define ICH_HCR_UIE (1 << 1) -#define ICH_HCR_NPIE (1 << 3) -#define ICH_HCR_TC (1 << 10) -#define ICH_HCR_TALL0 (1 << 11) -#define ICH_HCR_TALL1 (1 << 12) -#define ICH_HCR_TDIR (1 << 14) -#define ICH_HCR_EOIcount_SHIFT 27 -#define ICH_HCR_EOIcount_MASK (0x1f << ICH_HCR_EOIcount_SHIFT) -/* ICH_VMCR_EL2 bit definitions */ #define ICH_VMCR_ACK_CTL_SHIFT 2#define ICH_VMCR_ACK_CTL_MASK (1 << ICH_VMCR_ACK_CTL_SHIFT)
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH v4 2/16 arm64: sysreg: Add layout for ICH_VTR_EL2
In reply to Marc ZyngierThe ICH_VTR_EL2-related macros are missing a number of config bits that we are about to handle. Take this opportunity to fully describe the layout of that register as part of the automatic generation infrastructure.
This results in a bit of churn to repaint constants that are now generated with a different format.
--- arch/arm64/include/asm/sysreg.h | 13 ------------- arch/arm64/kvm/vgic-sys-reg-v3.c | 8 ++++---- arch/arm64/kvm/vgic/vgic-v3.c | 16 +++++++--------- arch/arm64/tools/sysreg | 14 ++++++++++++++ tools/arch/arm64/include/asm/sysreg.h | 13 ------------- 5 files changed, 25 insertions(+), 39 deletions(-)
arch/arm64/include/asm/sysreg.h +0 -13
@@ -562,7 +562,6 @@#define SYS_ICH_VSEIR_EL2 sys_reg(3, 4, 12, 9, 4)#define SYS_ICC_SRE_EL2 sys_reg(3, 4, 12, 9, 5) -#define SYS_ICH_VTR_EL2 sys_reg(3, 4, 12, 11, 1)#define SYS_ICH_MISR_EL2 sys_reg(3, 4, 12, 11, 2)#define SYS_ICH_EISR_EL2 sys_reg(3, 4, 12, 11, 3)#define SYS_ICH_ELRSR_EL2 sys_reg(3, 4, 12, 11, 5)
@@ -1022,18 +1021,6 @@#define ICH_VMCR_ENG1_SHIFT 1#define ICH_VMCR_ENG1_MASK (1 << ICH_VMCR_ENG1_SHIFT) -/* ICH_VTR_EL2 bit definitions */ -#define ICH_VTR_PRI_BITS_SHIFT 29 -#define ICH_VTR_PRI_BITS_MASK (7 << ICH_VTR_PRI_BITS_SHIFT) -#define ICH_VTR_ID_BITS_SHIFT 23 -#define ICH_VTR_ID_BITS_MASK (7 << ICH_VTR_ID_BITS_SHIFT) -#define ICH_VTR_SEIS_SHIFT 22 -#define ICH_VTR_SEIS_MASK (1 << ICH_VTR_SEIS_SHIFT) -#define ICH_VTR_A3V_SHIFT 21 -#define ICH_VTR_A3V_MASK (1 << ICH_VTR_A3V_SHIFT) -#define ICH_VTR_TDS_SHIFT 19 -#define ICH_VTR_TDS_MASK (1 << ICH_VTR_TDS_SHIFT) -/* * Permission Indirection Extension (PIE) permission encodings. * Encodings with the _O suffix, have overlays applied (Permission Overlay Extension).
arch/arm64/kvm/vgic-sys-reg-v3.c +4 -4
@@ -35,12 +35,12 @@ static int set_gic_ctlr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, vgic_v3_cpu->num_id_bits = host_id_bits; - host_seis =FIELD_GET (ICH_VTR_SEIS_MASK , kvm_vgic_global_state.ich_vtr_el2); + host_seis =FIELD_GET (ICH_VTR_EL2_SEIS , kvm_vgic_global_state.ich_vtr_el2); seis =FIELD_GET (ICC_CTLR_EL1_SEIS_MASK , val);if (host_seis != seis)return -EINVAL ; - host_a3v =FIELD_GET (ICH_VTR_A3V_MASK , kvm_vgic_global_state.ich_vtr_el2); + host_a3v =FIELD_GET (ICH_VTR_EL2_A3V , kvm_vgic_global_state.ich_vtr_el2); a3v =FIELD_GET (ICC_CTLR_EL1_A3V_MASK , val);if (host_a3v != a3v)return -EINVAL ;
@@ -68,10 +68,10 @@ static int get_gic_ctlr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, val |=FIELD_PREP (ICC_CTLR_EL1_PRI_BITS_MASK , vgic_v3_cpu->num_pri_bits -1 ); val |=FIELD_PREP (ICC_CTLR_EL1_ID_BITS_MASK , vgic_v3_cpu->num_id_bits); val |=FIELD_PREP (ICC_CTLR_EL1_SEIS_MASK , -FIELD_GET (ICH_VTR_SEIS_MASK , +FIELD_GET (ICH_VTR_EL2_SEIS , kvm_vgic_global_state.ich_vtr_el2)); val |=FIELD_PREP (ICC_CTLR_EL1_A3V_MASK , -FIELD_GET (ICH_VTR_A3V_MASK , kvm_vgic_global_state.ich_vtr_el2)); +FIELD_GET (ICH_VTR_EL2_A3V , kvm_vgic_global_state.ich_vtr_el2));/* * The VMCR.CTLR value is in ICC_CTLR_EL1 layout. * Extract it directly using ICC_CTLR_EL1 reg definitions.
arch/arm64/kvm/vgic/vgic-v3.c +7 -9
@@ -284,12 +284,10 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu) vgic_v3->vgic_sre =0 ; } - vcpu->arch.vgic_cpu.num_id_bits = (kvm_vgic_global_state.ich_vtr_el2 & -ICH_VTR_ID_BITS_MASK ) >> -ICH_VTR_ID_BITS_SHIFT ; - vcpu->arch.vgic_cpu.num_pri_bits = ((kvm_vgic_global_state.ich_vtr_el2 & -ICH_VTR_PRI_BITS_MASK ) >> -ICH_VTR_PRI_BITS_SHIFT ) +1 ; + vcpu->arch.vgic_cpu.num_id_bits =FIELD_GET (ICH_VTR_EL2_IDbits, + kvm_vgic_global_state.ich_vtr_el2); + vcpu->arch.vgic_cpu.num_pri_bits =FIELD_GET (ICH_VTR_EL2_PRIbits, + kvm_vgic_global_state.ich_vtr_el2) +1 ;/* Get the show on the road... */ vgic_v3->vgic_hcr = ICH_HCR_EL2_En;
@@ -633,7 +631,7 @@ static const struct midr_range broken_seis[] = {static bool vgic_v3_broken_seis (void ) { -return ((kvm_vgic_global_state.ich_vtr_el2 &ICH_VTR_SEIS_MASK ) && +return ((kvm_vgic_global_state.ich_vtr_el2 &ICH_VTR_EL2_SEIS ) &&is_midr_in_range_list (read_cpuid_id (), broken_seis)); }
@@ -707,10 +705,10 @@ int vgic_v3_probe(const struct gic_kvm_info *info)if (vgic_v3_broken_seis ()) {kvm_info ("GICv3 with broken locally generated SEI\n" ); - kvm_vgic_global_state.ich_vtr_el2 &= ~ICH_VTR_SEIS_MASK ; + kvm_vgic_global_state.ich_vtr_el2 &= ~ICH_VTR_EL2_SEIS ; group0_trap = true; group1_trap = true; -if (ich_vtr_el2 &ICH_VTR_TDS_MASK ) +if (ich_vtr_el2 &ICH_VTR_EL2_TDS ) dir_trap = true;else common_trap = true;
arch/arm64/tools/sysreg +14 -0
@@ -3057,6 +3057,20 @@ Field 1 UIE Field 0 En EndSysreg +Sysreg ICH_VTR_EL2 3 4 12 11 1 +Res0 63:32 +Field 31:29 PRIbits +Field 28:26 PREbits +Field 25:23 IDbits +Field 22 SEIS +Field 21 A3V +Field 20 nV4 +Field 19 TDS +Field 18 DVIM +Res0 17:5 +Field 4:0 ListRegs +EndSysreg + Sysreg CONTEXTIDR_EL2 3 4 13 0 1 Fields CONTEXTIDR_ELx EndSysreg
tools/arch/arm64/include/asm/sysreg.h +0 -13
@@ -558,7 +558,6 @@#define SYS_ICH_VSEIR_EL2 sys_reg(3, 4, 12, 9, 4)#define SYS_ICC_SRE_EL2 sys_reg(3, 4, 12, 9, 5) -#define SYS_ICH_VTR_EL2 sys_reg(3, 4, 12, 11, 1)#define SYS_ICH_MISR_EL2 sys_reg(3, 4, 12, 11, 2)#define SYS_ICH_EISR_EL2 sys_reg(3, 4, 12, 11, 3)#define SYS_ICH_ELRSR_EL2 sys_reg(3, 4, 12, 11, 5)
@@ -1018,18 +1017,6 @@#define ICH_VMCR_ENG1_SHIFT 1#define ICH_VMCR_ENG1_MASK (1 << ICH_VMCR_ENG1_SHIFT) -/* ICH_VTR_EL2 bit definitions */ -#define ICH_VTR_PRI_BITS_SHIFT 29 -#define ICH_VTR_PRI_BITS_MASK (7 << ICH_VTR_PRI_BITS_SHIFT) -#define ICH_VTR_ID_BITS_SHIFT 23 -#define ICH_VTR_ID_BITS_MASK (7 << ICH_VTR_ID_BITS_SHIFT) -#define ICH_VTR_SEIS_SHIFT 22 -#define ICH_VTR_SEIS_MASK (1 << ICH_VTR_SEIS_SHIFT) -#define ICH_VTR_A3V_SHIFT 21 -#define ICH_VTR_A3V_MASK (1 << ICH_VTR_A3V_SHIFT) -#define ICH_VTR_TDS_SHIFT 19 -#define ICH_VTR_TDS_MASK (1 << ICH_VTR_TDS_SHIFT) -/* * Permission Indirection Extension (PIE) permission encodings. * Encodings with the _O suffix, have overlays applied (Permission Overlay Extension).
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH v4 3/16 arm64: sysreg: Add layout for ICH_MISR_EL2
In reply to Marc ZyngierThe ICH_MISR_EL2-related macros are missing a number of status bits that we are about to handle. Take this opportunity to fully describe the layout of that register as part of the automatic generation infrastructure.
--- arch/arm64/include/asm/sysreg.h | 5 ----- arch/arm64/tools/sysreg | 12 ++++++++++++ tools/arch/arm64/include/asm/sysreg.h | 5 ----- 3 files changed, 12 insertions(+), 10 deletions(-)
arch/arm64/include/asm/sysreg.h +0 -5
@@ -562,7 +562,6 @@#define SYS_ICH_VSEIR_EL2 sys_reg(3, 4, 12, 9, 4)#define SYS_ICC_SRE_EL2 sys_reg(3, 4, 12, 9, 5) -#define SYS_ICH_MISR_EL2 sys_reg(3, 4, 12, 11, 2)#define SYS_ICH_EISR_EL2 sys_reg(3, 4, 12, 11, 3)#define SYS_ICH_ELRSR_EL2 sys_reg(3, 4, 12, 11, 5)#define SYS_ICH_VMCR_EL2 sys_reg(3, 4, 12, 11, 7)
@@ -983,10 +982,6 @@#define SYS_MPIDR_SAFE_VAL (BIT(31))/* GIC Hypervisor interface registers */ -/* ICH_MISR_EL2 bit definitions */ -#define ICH_MISR_EOI (1 << 0) -#define ICH_MISR_U (1 << 1) -/* ICH_LR*_EL2 bit definitions */ #define ICH_LR_VIRTUAL_ID_MASK ((1ULL << 32) - 1)
arch/arm64/tools/sysreg +12 -0
@@ -3071,6 +3071,18 @@ Res0 17:5 Field 4:0 ListRegs EndSysreg +Sysreg ICH_MISR_EL2 3 4 12 11 2 +Res0 63:8 +Field 7 VGrp1D +Field 6 VGrp1E +Field 5 VGrp0D +Field 4 VGrp0E +Field 3 NP +Field 2 LRENP +Field 1 U +Field 0 EOI +EndSysreg + Sysreg CONTEXTIDR_EL2 3 4 13 0 1 Fields CONTEXTIDR_ELx EndSysreg
tools/arch/arm64/include/asm/sysreg.h +0 -5
@@ -558,7 +558,6 @@#define SYS_ICH_VSEIR_EL2 sys_reg(3, 4, 12, 9, 4)#define SYS_ICC_SRE_EL2 sys_reg(3, 4, 12, 9, 5) -#define SYS_ICH_MISR_EL2 sys_reg(3, 4, 12, 11, 2)#define SYS_ICH_EISR_EL2 sys_reg(3, 4, 12, 11, 3)#define SYS_ICH_ELRSR_EL2 sys_reg(3, 4, 12, 11, 5)#define SYS_ICH_VMCR_EL2 sys_reg(3, 4, 12, 11, 7)
@@ -979,10 +978,6 @@#define SYS_MPIDR_SAFE_VAL (BIT(31))/* GIC Hypervisor interface registers */ -/* ICH_MISR_EL2 bit definitions */ -#define ICH_MISR_EOI (1 << 0) -#define ICH_MISR_U (1 << 1) -/* ICH_LR*_EL2 bit definitions */ #define ICH_LR_VIRTUAL_ID_MASK ((1ULL << 32) - 1)
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH v4 4/16 KVM: arm64: nv: Load timer before the GIC
In reply to Marc ZyngierIn order for vgic_v3_load_nested to be able to observe which timer interrupts have the HW bit set for the current context, the timers must have been loaded in the new mode and the right timer mapped to their corresponding HW IRQs.
At the moment, we load the GIC first, meaning that timer interrupts injected to an L2 guest will never have the HW bit set (we see the old configuration).
Swapping the two loads solves this particular problem.
--- arch/arm64/kvm/arm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/kvm/arm.c +1 -1
@@ -576,8 +576,8 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) nommu: vcpu->cpu = cpu; -kvm_vgic_load (vcpu);kvm_timer_vcpu_load (vcpu); +kvm_vgic_load (vcpu);kvm_vcpu_load_debug (vcpu);if (has_vhe ())kvm_vcpu_load_vhe (vcpu);
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH v4 5/16 KVM: arm64: nv: Add ICH_*_EL2 registers to vpcu_sysreg
In reply to Marc ZyngierFEAT_NV2 comes with a bunch of register-to-memory redirection involving the ICH_*_EL2 registers (LRs, APRs, VMCR, HCR).
Adds them to the vcpu_sysreg enumeration.
--- arch/arm64/include/asm/kvm_host.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
arch/arm64/include/asm/kvm_host.h +26 -0
@@ -557,7 +557,33 @@ enum vcpu_sysreg {VNCR (CNTP_CVAL_EL0 ),VNCR (CNTP_CTL_EL0 ), +VNCR (ICH_LR0_EL2 ), +VNCR (ICH_LR1_EL2 ), +VNCR (ICH_LR2_EL2 ), +VNCR (ICH_LR3_EL2 ), +VNCR (ICH_LR4_EL2 ), +VNCR (ICH_LR5_EL2 ), +VNCR (ICH_LR6_EL2 ), +VNCR (ICH_LR7_EL2 ), +VNCR (ICH_LR8_EL2 ), +VNCR (ICH_LR9_EL2 ), +VNCR (ICH_LR10_EL2 ), +VNCR (ICH_LR11_EL2 ), +VNCR (ICH_LR12_EL2 ), +VNCR (ICH_LR13_EL2 ), +VNCR (ICH_LR14_EL2 ), +VNCR (ICH_LR15_EL2 ), + +VNCR (ICH_AP0R0_EL2 ), +VNCR (ICH_AP0R1_EL2 ), +VNCR (ICH_AP0R2_EL2 ), +VNCR (ICH_AP0R3_EL2 ), +VNCR (ICH_AP1R0_EL2 ), +VNCR (ICH_AP1R1_EL2 ), +VNCR (ICH_AP1R2_EL2 ), +VNCR (ICH_AP1R3_EL2 ),VNCR (ICH_HCR_EL2 ), +VNCR (ICH_VMCR_EL2 ),NR_SYS_REGS /* Nothing after this line! */ };
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH v4 6/16 KVM: arm64: nv: Plumb handling of GICv3 EL2 accesses
In reply to Marc ZyngierWire the handling of all GICv3 EL2 registers, and provide emulation for all the non memory-backed registers (ICC_SRE_EL2, ICH_VTR_EL2, ICH_MISR_EL2, ICH_ELRSR_EL2, and ICH_EISR_EL2).
--- arch/arm64/kvm/Makefile | 2 +- arch/arm64/kvm/sys_regs.c | 95 +++++++++++++++++++- arch/arm64/kvm/vgic/vgic-v3-nested.c | 125 +++++++++++++++++++++++++++ include/kvm/arm_vgic.h | 4 + 4 files changed, 224 insertions(+), 2 deletions(-) create mode 100644 arch/arm64/kvm/vgic/vgic-v3-nested.c
arch/arm64/kvm/Makefile +1 -1
@@ -23,7 +23,7 @@ kvm-y += arm.o mmu.o mmio.o psci.o hypercalls.o pvtime.o \ vgic/vgic-v3.o vgic/vgic-v4.o \ vgic/vgic-mmio.o vgic/vgic-mmio-v2.o \ vgic/vgic-mmio-v3.o vgic/vgic-kvm-device.o \ - vgic/vgic-its.o vgic/vgic-debug.o + vgic/vgic-its.o vgic/vgic-debug.o vgic/vgic-v3-nested.o kvm-$(CONFIG_HW_PERF_EVENTS) += pmu-emul.o pmu.o kvm-$(CONFIG_ARM64_PTR_AUTH) += pauth.o
arch/arm64/kvm/sys_regs.c +94 -1
120 lines not on this page · raw message
arch/arm64/kvm/vgic/vgic-v3-nested.c new file +125 -0
125 lines not on this page · raw message
include/kvm/arm_vgic.h +4 -0
@@ -389,6 +389,10 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);void kvm_vgic_load (struct kvm_vcpu *vcpu);void kvm_vgic_put (struct kvm_vcpu *vcpu); +u16 vgic_v3_get_eisr (struct kvm_vcpu *vcpu); +u16 vgic_v3_get_elrsr (struct kvm_vcpu *vcpu); +u64 vgic_v3_get_misr (struct kvm_vcpu *vcpu); +#define irqchip_in_kernel (k) (!!((k)->arch.vgic.in_kernel))#define vgic_initialized (k) ((k)->arch.vgic.initialized)#define vgic_ready (k) ((k)->arch.vgic.ready)
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH v4 7/16 KVM: arm64: nv: Sanitise ICH_HCR_EL2 accesses
In reply to Marc ZyngierAs ICH_HCR_EL2 is a VNCR accessor when runnintg NV, add some sanitising to what gets written. Crucially, mark TDIR as RES0 if the HW doesn't support it (unlikely, but hey...), as well as anything GICv4 related, since we only expose a GICv3 to the uest.
--- arch/arm64/kvm/nested.c | 9 +++++++++ 1 file changed, 9 insertions(+)
arch/arm64/kvm/nested.c +9 -0
@@ -1290,6 +1290,15 @@ int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu) res0 |=GENMASK (11 ,8 );set_sysreg_masks (kvm,CNTHCTL_EL2 , res0, res1); +/* ICH_HCR_EL2 */ + res0 =ICH_HCR_EL2_RES0 ; + res1 =ICH_HCR_EL2_RES1 ; +if (!(kvm_vgic_global_state.ich_vtr_el2 &ICH_VTR_EL2_TDS )) + res0 |=ICH_HCR_EL2_TDIR ; +/* No GICv4 is presented to the guest */ + res0 |=ICH_HCR_EL2_DVIM | ICH_HCR_EL2_vSGIEOICount; +set_sysreg_masks (kvm,ICH_HCR_EL2 , res0, res1); + out:for (enum vcpu_sysreg sr = __SANITISED_REG_START__; sr <NR_SYS_REGS ; sr++) (void )__vcpu_sys_reg (vcpu, sr);
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH v4 8/16 KVM: arm64: nv: Nested GICv3 emulation
In reply to Marc ZyngierWhen entering a nested VM, we set up the hypervisor control interface based on what the guest hypervisor has set. Especially, we investigate each list register written by the guest hypervisor whether HW bit is set. If so, we translate hw irq number from the guest's point of view to the real hardware irq number if there is a mapping.
--- arch/arm64/include/asm/kvm_hyp.h | 2 + arch/arm64/kvm/hyp/vgic-v3-sr.c | 2 +- arch/arm64/kvm/vgic/vgic-v3-nested.c | 218 +++++++++++++++++++++++++++ arch/arm64/kvm/vgic/vgic-v3.c | 11 ++ arch/arm64/kvm/vgic/vgic.c | 6 + arch/arm64/kvm/vgic/vgic.h | 4 + include/kvm/arm_vgic.h | 2 + 7 files changed, 244 insertions(+), 1 deletion(-)
arch/arm64/include/asm/kvm_hyp.h +2 -0
@@ -76,6 +76,8 @@ DECLARE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params);int __vgic_v2_perform_cpuif_access (struct kvm_vcpu *vcpu); +u64 __gic_v3_get_lr (unsigned int lr); +void __vgic_v3_save_state (struct vgic_v3_cpu_if *cpu_if);void __vgic_v3_restore_state (struct vgic_v3_cpu_if *cpu_if);void __vgic_v3_activate_traps (struct vgic_v3_cpu_if *cpu_if);
arch/arm64/kvm/hyp/vgic-v3-sr.c +1 -1
@@ -18,7 +18,7 @@#define vtr_to_nr_pre_bits (v) ((((u32)(v) >> 26) & 7) + 1)#define vtr_to_nr_apr_regs (v) (1 << (vtr_to_nr_pre_bits(v) - 5)) -static u64 __gic_v3_get_lr (unsigned int lr) +u64 __gic_v3_get_lr (unsigned int lr) {switch (lr &0xf ) {case 0 :
arch/arm64/kvm/vgic/vgic-v3-nested.c +218 -0
242 lines not on this page · raw message
arch/arm64/kvm/vgic/vgic-v3.c +11 -0
@@ -734,6 +734,12 @@ void vgic_v3_load(struct kvm_vcpu *vcpu) {struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3; +/* If the vgic is nested, perform the full state loading */ +if (vgic_state_is_nested (vcpu)) { +vgic_v3_load_nested (vcpu); +return ; + } +if (likely (!is_protected_kvm_enabled ()))kvm_call_hyp (__vgic_v3_restore_vmcr_aprs, cpu_if);
@@ -747,6 +753,11 @@ void vgic_v3_put(struct kvm_vcpu *vcpu) {struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3; +if (vgic_state_is_nested (vcpu)) { +vgic_v3_put_nested (vcpu); +return ; + } +if (likely (!is_protected_kvm_enabled ()))kvm_call_hyp (__vgic_v3_save_vmcr_aprs, cpu_if);WARN_ON (vgic_v4_put (vcpu));
arch/arm64/kvm/vgic/vgic.c +6 -0
@@ -872,6 +872,12 @@ void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu) {int used_lrs; +/* If nesting, emulate the HW effect from L0 to L1 */ +if (vgic_state_is_nested (vcpu)) { +vgic_v3_sync_nested (vcpu); +return ; + } +/* An empty ap_list_head implies used_lrs == 0 */ if (list_empty (&vcpu->arch.vgic_cpu.ap_list_head))return ;
arch/arm64/kvm/vgic/vgic.h +4 -0
@@ -353,4 +353,8 @@ static inline bool kvm_has_gicv3(struct kvm *kvm) return kvm_has_feat(kvm, ID_AA64PFR0_EL1, GIC, IMP); } +void vgic_v3_sync_nested (struct kvm_vcpu *vcpu); +void vgic_v3_load_nested (struct kvm_vcpu *vcpu); +void vgic_v3_put_nested (struct kvm_vcpu *vcpu); +#endif
include/kvm/arm_vgic.h +2 -0
@@ -437,6 +437,8 @@ int vgic_v4_load(struct kvm_vcpu *vcpu);void vgic_v4_commit (struct kvm_vcpu *vcpu);int vgic_v4_put (struct kvm_vcpu *vcpu); +bool vgic_state_is_nested (struct kvm_vcpu *vcpu); +/* CPU HP callbacks */ void kvm_vgic_cpu_up (void );void kvm_vgic_cpu_down (void );
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH v4 9/16 KVM: arm64: nv: Handle L2->L1 transition on interrupt injection
In reply to Marc ZyngierAn interrupt being delivered to L1 while running L2 must result in the correct exception being delivered to L1.
This means that if, on entry to L2, we found ourselves with pending interrupts in the L1 distributor, we need to take immediate action. This is done by posting a request which will prevent the entry in L2, and deliver an IRQ exception to L1, forcing the switch.
--- arch/arm64/include/asm/kvm_host.h | 17 +++++++++-------- arch/arm64/kvm/arm.c | 5 +++++ arch/arm64/kvm/nested.c | 4 ++++ arch/arm64/kvm/vgic/vgic.c | 23 +++++++++++++++++++++++ 4 files changed, 41 insertions(+), 8 deletions(-)
arch/arm64/include/asm/kvm_host.h +9 -8
@@ -44,14 +44,15 @@#define KVM_REQ_SLEEP \ KVM_ARCH_REQ_FLAGS(0, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP) -#define KVM_REQ_IRQ_PENDING KVM_ARCH_REQ(1) -#define KVM_REQ_VCPU_RESET KVM_ARCH_REQ(2) -#define KVM_REQ_RECORD_STEAL KVM_ARCH_REQ(3) -#define KVM_REQ_RELOAD_GICv4 KVM_ARCH_REQ(4) -#define KVM_REQ_RELOAD_PMU KVM_ARCH_REQ(5) -#define KVM_REQ_SUSPEND KVM_ARCH_REQ(6) -#define KVM_REQ_RESYNC_PMU_EL0 KVM_ARCH_REQ(7) -#define KVM_REQ_NESTED_S2_UNMAP KVM_ARCH_REQ(8) +#define KVM_REQ_IRQ_PENDING KVM_ARCH_REQ(1) +#define KVM_REQ_VCPU_RESET KVM_ARCH_REQ(2) +#define KVM_REQ_RECORD_STEAL KVM_ARCH_REQ(3) +#define KVM_REQ_RELOAD_GICv4 KVM_ARCH_REQ(4) +#define KVM_REQ_RELOAD_PMU KVM_ARCH_REQ(5) +#define KVM_REQ_SUSPEND KVM_ARCH_REQ(6) +#define KVM_REQ_RESYNC_PMU_EL0 KVM_ARCH_REQ(7) +#define KVM_REQ_NESTED_S2_UNMAP KVM_ARCH_REQ(8) +#define KVM_REQ_GUEST_HYP_IRQ_PENDING KVM_ARCH_REQ(9)#define KVM_DIRTY_LOG_MANUAL_CAPS (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \ KVM_DIRTY_LOG_INITIALLY_SET)
arch/arm64/kvm/arm.c +5 -0
@@ -1144,6 +1144,11 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)* preserved on VMID roll-over if the task was preempted, * making a thread's VMID inactive. So we need to call * kvm_arm_vmid_update() in non-premptible context. +* +* Note that this must happen after the check_vcpu_request() +* call to pick the correct s2_mmu structure, as a pending +* nested exception (IRQ, for example) can trigger a change +* in translation regime. */ if (kvm_arm_vmid_update (&vcpu->arch.hw_mmu->vmid) &&has_vhe ())
arch/arm64/kvm/nested.c +4 -0
@@ -1318,4 +1318,8 @@ void check_nested_vcpu_requests(struct kvm_vcpu *vcpu) }write_unlock (&vcpu->kvm->mmu_lock); } + +/* Must be last, as may switch context! */ +if (kvm_check_request (KVM_REQ_GUEST_HYP_IRQ_PENDING , vcpu)) +kvm_inject_nested_irq (vcpu); }
arch/arm64/kvm/vgic/vgic.c +23 -0
@@ -906,6 +906,29 @@ static inline void vgic_restore_state(struct kvm_vcpu *vcpu)/* Flush our emulation state into the GIC hardware before entering the guest. */ void kvm_vgic_flush_hwstate (struct kvm_vcpu *vcpu) { +/* +* If in a nested state, we must return early. Two possibilities: +* +* - If we have any pending IRQ for the guest and the guest +* expects IRQs to be handled in its virtual EL2 mode (the +* virtual IMO bit is set) and it is not already running in +* virtual EL2 mode, then we have to emulate an IRQ +* exception to virtual EL2. +* +* We do that by placing a request to ourselves which will +* abort the entry procedure and inject the exception at the +* beginning of the run loop. +* +* - Otherwise, do exactly *NOTHING*. The guest state is +* already loaded, and we can carry on with running it. +*/ +if (vgic_state_is_nested (vcpu)) { +if (kvm_vgic_vcpu_pending_irq (vcpu)) +kvm_make_request (KVM_REQ_GUEST_HYP_IRQ_PENDING , vcpu); + +return ; + } +/* * If there are no virtual interrupts active or pending for this * VCPU, then there is no work to do and we can bail out without
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH v4 10/16 KVM: arm64: nv: Add Maintenance Interrupt emulation
In reply to Marc ZyngierEmulating the vGIC means emulating the dreaded Maintenance Interrupt.
This is a two-pronged problem:
- while running L2, getting an MI translates into an MI injected in the L1 based on the state of the HW.
- while running L1, we must accurately reflect the state of the MI line, based on the in-memory state.
The MI INTID is added to the distributor, as expected on any virtualisation-capable implementation, and further patches will allow its configuration.
--- arch/arm64/kvm/arm.c | 6 ++++ arch/arm64/kvm/vgic/vgic-init.c | 29 ++++++++++++++++++ arch/arm64/kvm/vgic/vgic-v3-nested.c | 45 ++++++++++++++++++++++++++++ arch/arm64/kvm/vgic/vgic.c | 9 ++++++ arch/arm64/kvm/vgic/vgic.h | 2 ++ include/kvm/arm_vgic.h | 4 +++ 6 files changed, 95 insertions(+)
arch/arm64/kvm/arm.c +6 -0
@@ -815,6 +815,12 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)if (ret)return ret; +if (vcpu_has_nv (vcpu)) { + ret =kvm_vgic_vcpu_nv_init (vcpu); +if (ret) +return ret; + } +/* * This needs to happen after any restriction has been applied * to the feature set.
arch/arm64/kvm/vgic/vgic-init.c +29 -0
@@ -198,6 +198,27 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)return 0 ; } +/* Default GICv3 Maintenance Interrupt INTID, as per SBSA */ +#define DEFAULT_MI_INTID 25 + +int kvm_vgic_vcpu_nv_init (struct kvm_vcpu *vcpu) +{ +int ret; + +guard (mutex)(&vcpu->kvm->arch.config_lock); + +/* +* Matching the tradition established with the timers, provide +* a default PPI for the maintenance interrupt. It makes +* things easier to reason about. +*/ +if (vcpu->kvm->arch.vgic.mi_intid ==0 ) + vcpu->kvm->arch.vgic.mi_intid =DEFAULT_MI_INTID ; + ret =kvm_vgic_set_owner (vcpu, vcpu->kvm->arch.vgic.mi_intid, vcpu); + +return ret; +} +static int vgic_allocate_private_irqs_locked (struct kvm_vcpu *vcpu,u32 type) {struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
@@ -588,12 +609,20 @@ void kvm_vgic_cpu_down(void)static irqreturn_t vgic_maintenance_handler (int irq,void *data) { +struct kvm_vcpu *vcpu = *(struct kvm_vcpu **)data; +/* * We cannot rely on the vgic maintenance interrupt to be * delivered synchronously. This means we can only use it to * exit the VM, and we perform the handling of EOIed * interrupts on the exit path (see vgic_fold_lr_state). +* +* Of course, NV throws a wrench in this plan, and needs +* something special. */ +if (vcpu &&vgic_state_is_nested (vcpu)) +vgic_v3_handle_nested_maint_irq (vcpu); +return IRQ_HANDLED ; }
arch/arm64/kvm/vgic/vgic-v3-nested.c +45 -0
54 lines not on this page · raw message
arch/arm64/kvm/vgic/vgic.c +9 -0
@@ -878,6 +878,9 @@ void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)return ; } +if (vcpu_has_nv (vcpu)) +vgic_v3_nested_update_mi (vcpu); +/* An empty ap_list_head implies used_lrs == 0 */ if (list_empty (&vcpu->arch.vgic_cpu.ap_list_head))return ;
@@ -921,6 +924,9 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)* * - Otherwise, do exactly *NOTHING*. The guest state is * already loaded, and we can carry on with running it. +* +* If we have NV, but are not in a nested state, compute the +* maintenance interrupt state, as it may fire. */ if (vgic_state_is_nested (vcpu)) {if (kvm_vgic_vcpu_pending_irq (vcpu))
@@ -929,6 +935,9 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)return ; } +if (vcpu_has_nv (vcpu)) +vgic_v3_nested_update_mi (vcpu); +/* * If there are no virtual interrupts active or pending for this * VCPU, then there is no work to do and we can bail out without
arch/arm64/kvm/vgic/vgic.h +2 -0
@@ -356,5 +356,7 @@ static inline bool kvm_has_gicv3(struct kvm *kvm)void vgic_v3_sync_nested (struct kvm_vcpu *vcpu);void vgic_v3_load_nested (struct kvm_vcpu *vcpu);void vgic_v3_put_nested (struct kvm_vcpu *vcpu); +void vgic_v3_handle_nested_maint_irq (struct kvm_vcpu *vcpu); +void vgic_v3_nested_update_mi (struct kvm_vcpu *vcpu);#endif
include/kvm/arm_vgic.h +4 -0
@@ -249,6 +249,9 @@ struct vgic_dist {int nr_spis; +/* The GIC maintenance IRQ for nested hypervisors. */ +u32 mi_intid; +/* base addresses in guest physical address space: */ gpa_t vgic_dist_base;/* distributor */ union {
@@ -369,6 +372,7 @@ extern struct static_key_false vgic_v3_cpuif_trap;int kvm_set_legacy_vgic_v2_addr (struct kvm *kvm,struct kvm_arm_device_addr *dev_addr);void kvm_vgic_early_init (struct kvm *kvm);int kvm_vgic_vcpu_init (struct kvm_vcpu *vcpu); +int kvm_vgic_vcpu_nv_init (struct kvm_vcpu *vcpu);int kvm_vgic_create (struct kvm *kvm,u32 type);void kvm_vgic_destroy (struct kvm *kvm);void kvm_vgic_vcpu_destroy (struct kvm_vcpu *vcpu);
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH v4 11/16 KVM: arm64: nv: Respect virtual HCR_EL2.TWx setting
In reply to Marc ZyngierFrom: Jintack Lim <[email protected]>
Forward exceptions due to WFI or WFE instructions to the virtual EL2 if they are not coming from the virtual EL2 and virtual HCR_EL2.TWx is set.
--- arch/arm64/include/asm/kvm_emulate.h | 13 +++++++++++++ arch/arm64/kvm/handle_exit.c | 6 +++++- 2 files changed, 18 insertions(+), 1 deletion(-)
arch/arm64/include/asm/kvm_emulate.h +13 -0
@@ -275,6 +275,19 @@ static __always_inline u64 kvm_vcpu_get_esr(const struct kvm_vcpu *vcpu)return vcpu->arch.fault.esr_el2; } +static inline bool guest_hyp_wfx_traps_enabled (const struct kvm_vcpu *vcpu) +{ +u64 esr =kvm_vcpu_get_esr (vcpu); +bool is_wfe = !!(esr & ESR_ELx_WFx_ISS_WFE); +u64 hcr_el2 =__vcpu_sys_reg (vcpu,HCR_EL2 ); + +if (!vcpu_has_nv (vcpu) ||vcpu_is_el2 (vcpu)) +return false; + +return ((is_wfe && (hcr_el2 &HCR_TWE )) || + (!is_wfe && (hcr_el2 &HCR_TWI ))); +} + static __always_inline int kvm_vcpu_get_condition(const struct kvm_vcpu *vcpu) {u64 esr =kvm_vcpu_get_esr (vcpu);
arch/arm64/kvm/handle_exit.c +5 -1
@@ -129,8 +129,12 @@ static int kvm_handle_fpasimd(struct kvm_vcpu *vcpu)static int kvm_handle_wfx (struct kvm_vcpu *vcpu) {u64 esr =kvm_vcpu_get_esr (vcpu); +bool is_wfe = !!(esr & ESR_ELx_WFx_ISS_WFE); -if (esr & ESR_ELx_WFx_ISS_WFE) { +if (guest_hyp_wfx_traps_enabled (vcpu)) +return kvm_inject_nested_sync (vcpu,kvm_vcpu_get_esr (vcpu)); + +if (is_wfe) {trace_kvm_wfx_arm64 (*vcpu_pc (vcpu), true); vcpu->stat.wfe_exit_stat++; }else {
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH v4 12/16 KVM: arm64: nv: Request vPE doorbell upon nested ERET to L2
In reply to Marc ZyngierFrom: Oliver Upton <[email protected]>
Running an L2 guest with GICv4 enabled goes absolutely nowhere, and gets into a vicious cycle of nested ERET followed by nested exception entry into the L1.
When KVM does a put on a runnable vCPU, it marks the vPE as nonresident but does not request a doorbell IRQ. Behind the scenes in the ITS driver's view of the vCPU, its_vpe::pending_last gets set to true to indicate that context is still runnable.
This comes to a head when doing the nested ERET into L2. The vPE doesn't get scheduled on the redistributor as it is exclusively part of the L1's VGIC context. kvm_vgic_vcpu_pending_irq() returns true because the vPE appears runnable, and KVM does a nested exception entry into the L1 before L2 ever gets off the ground.
This issue can be papered over by requesting a doorbell IRQ when descheduling a vPE as part of a nested ERET. KVM needs this anyway to kick the vCPU out of the L2 when an IRQ becomes pending for the L1.
--- arch/arm64/include/asm/kvm_host.h | 2 ++ arch/arm64/kvm/emulate-nested.c | 2 ++ arch/arm64/kvm/vgic/vgic-v4.c | 18 +++++++++++++++++- 3 files changed, 21 insertions(+), 1 deletion(-)
arch/arm64/include/asm/kvm_host.h +2 -0
@@ -946,6 +946,8 @@ struct kvm_vcpu_arch {#define PMUSERENR_ON_CPU __vcpu_single_flag(sflags, BIT(5))/* WFI instruction trapped */ #define IN_WFI __vcpu_single_flag(sflags, BIT(6)) +/* KVM is currently emulating a nested ERET */ +#define IN_NESTED_ERET __vcpu_single_flag(sflags, BIT(7))/* Pointer to the vcpu's SVE FFR for sve_{save,load}_state() */
arch/arm64/kvm/emulate-nested.c +2 -0
@@ -2503,6 +2503,7 @@ void kvm_emulate_nested_eret(struct kvm_vcpu *vcpu) }preempt_disable (); +vcpu_set_flag (vcpu,IN_NESTED_ERET );kvm_arch_vcpu_put (vcpu);if (!esr_iss_is_eretax (esr))
@@ -2514,6 +2515,7 @@ void kvm_emulate_nested_eret(struct kvm_vcpu *vcpu) *vcpu_cpsr (vcpu) = spsr;kvm_arch_vcpu_load (vcpu,smp_processor_id ()); +vcpu_clear_flag (vcpu,IN_NESTED_ERET );preempt_enable ();kvm_pmu_nested_transition (vcpu);
arch/arm64/kvm/vgic/vgic-v4.c +17 -1
@@ -336,6 +336,22 @@ void vgic_v4_teardown(struct kvm *kvm) its_vm->vpes =NULL ; } +static inline bool vgic_v4_want_doorbell (struct kvm_vcpu *vcpu) +{ +if (vcpu_get_flag (vcpu,IN_WFI )) +return true; + +if (likely (!vcpu_has_nv (vcpu))) +return false; + +/* +* GICv4 hardware is only ever used for the L1. Mark the vPE (i.e. the +* L1 context) nonresident and request a doorbell to kick us out of the +* L2 when an IRQ becomes pending. +*/ +return vcpu_get_flag (vcpu,IN_NESTED_ERET ); +} +int vgic_v4_put (struct kvm_vcpu *vcpu) {struct its_vpe *vpe = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe;
@@ -343,7 +359,7 @@ int vgic_v4_put(struct kvm_vcpu *vcpu)if (!vgic_supports_direct_msis (vcpu->kvm) || !vpe->resident)return 0 ; -return its_make_vpe_non_resident (vpe, !!vcpu_get_flag (vcpu,IN_WFI )); +return its_make_vpe_non_resident (vpe,vgic_v4_want_doorbell (vcpu)); }int vgic_v4_load (struct kvm_vcpu *vcpu)
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH v4 13/16 KVM: arm64: nv: Propagate used_lrs between L1 and L0 contexts
In reply to Marc ZyngierWe have so far made sure that L1 and L0 vgic contexts were totally independent. There is however one spot of bother with this approach, and that's in the GICv3 emulation code required by our fruity friends.
The issue is that the emulation code needs to know how many LRs are in flight. And while it is easy to reach the L0 version through the vcpu pointer, doing so for the L1 is much more complicated, as these structures are private to the nested code.
We could simply expose that structure and pick one or the other depending on the context, but this seems extra complexity for not much benefit.
Instead, just propagate the number of used LRs from the nested code into the L0 context, and be done with it. Should this become a burden, it can be easily rectified.
--- arch/arm64/kvm/vgic/vgic-v3-nested.c | 7 +++++++ 1 file changed, 7 insertions(+)
arch/arm64/kvm/vgic/vgic-v3-nested.c +7 -0
@@ -323,6 +323,12 @@ void vgic_v3_load_nested(struct kvm_vcpu *vcpu)__vgic_v3_activate_traps (cpu_if);__vgic_v3_restore_state (cpu_if); + +/* +* Propagate the number of used LRs for the benefit of the HYP +* GICv3 emulation code. Yes, this is a pretty sorry hack. +*/ + vcpu->arch.vgic_cpu.vgic_v3.used_lrs = cpu_if->used_lrs; }void vgic_v3_put_nested (struct kvm_vcpu *vcpu)
@@ -358,6 +364,7 @@ void vgic_v3_put_nested(struct kvm_vcpu *vcpu) } shadow_if->lr_map =0 ; + vcpu->arch.vgic_cpu.vgic_v3.used_lrs =0 ; }/*
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH v4 14/16 KVM: arm64: nv: Fold GICv3 host trapping requirements into guest setup
In reply to Marc ZyngierPopular HW that is able to use NV also has a broken vgic implementation that requires trapping.
On such HW, propagate the host trap bits into the guest's shadow ICH_HCR_EL2 register, making sure we don't allow an L2 guest to bring the system down.
This involves a bit of tweaking so that the emulation code correctly poicks up the shadow state as needed, and to only partially sync ICH_HCR_EL2 back with the guest state to capture EOIcount.
--- arch/arm64/kvm/vgic/vgic-v3-nested.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-)
arch/arm64/kvm/vgic/vgic-v3-nested.c +17 -3
@@ -296,9 +296,19 @@ static void vgic_v3_create_shadow_state(struct kvm_vcpu *vcpu, struct vgic_v3_cpu_if *s_cpu_if) {struct vgic_v3_cpu_if *host_if = &vcpu->arch.vgic_cpu.vgic_v3; +u64 val =0 ;int i; - s_cpu_if->vgic_hcr =__vcpu_sys_reg (vcpu,ICH_HCR_EL2 ); +/* +* If we're on a system with a broken vgic that requires +* trapping, propagate the trapping requirements. +* +* Ah, the smell of rotten fruits... +*/ +if (static_branch_unlikely (&vgic_v3_cpuif_trap)) + val = host_if->vgic_hcr & (ICH_HCR_EL2_TALL0 |ICH_HCR_EL2_TALL1 | +ICH_HCR_EL2_TC |ICH_HCR_EL2_TDIR ); + s_cpu_if->vgic_hcr =__vcpu_sys_reg (vcpu,ICH_HCR_EL2 ) | val; s_cpu_if->vgic_vmcr =__vcpu_sys_reg (vcpu,ICH_VMCR_EL2 ); s_cpu_if->vgic_sre = host_if->vgic_sre;
@@ -335,6 +345,7 @@ void vgic_v3_put_nested(struct kvm_vcpu *vcpu) {struct shadow_if *shadow_if =get_shadow_if ();struct vgic_v3_cpu_if *s_cpu_if = &shadow_if->cpuif; +u64 val;int i;__vgic_v3_save_vmcr_aprs (s_cpu_if);
@@ -345,7 +356,10 @@ void vgic_v3_put_nested(struct kvm_vcpu *vcpu)* Translate the shadow state HW fields back to the virtual ones * before copying the shadow struct back to the nested one. */ -__vcpu_sys_reg (vcpu,ICH_HCR_EL2 ) = s_cpu_if->vgic_hcr; + val =__vcpu_sys_reg (vcpu,ICH_HCR_EL2 ); + val &= ~ICH_HCR_EL2_EOIcount_MASK; + val |= (s_cpu_if->vgic_hcr & ICH_HCR_EL2_EOIcount_MASK); +__vcpu_sys_reg (vcpu,ICH_HCR_EL2 ) = val;__vcpu_sys_reg (vcpu,ICH_VMCR_EL2 ) = s_cpu_if->vgic_vmcr;for (i =0 ; i <4 ; i++) {
@@ -354,7 +368,7 @@ void vgic_v3_put_nested(struct kvm_vcpu *vcpu) }for_each_set_bit (i, &shadow_if->lr_map, kvm_vgic_global_state.nr_lr) { -u64 val =__vcpu_sys_reg (vcpu,ICH_LRN (i)); + val =__vcpu_sys_reg (vcpu,ICH_LRN (i)); val &= ~ICH_LR_STATE ; val |= s_cpu_if->vgic_lr[i] &ICH_LR_STATE ;
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH v4 15/16 KVM: arm64: nv: Allow userland to set VGIC maintenance IRQ
In reply to Marc ZyngierFrom: Andre Przywara <[email protected]>
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.
--- .../virt/kvm/devices/arm-vgic-v3.rst | 12 +++++++- arch/arm64/include/uapi/asm/kvm.h | 1 + arch/arm64/kvm/vgic/vgic-kvm-device.c | 29 +++++++++++++++++-- tools/arch/arm/include/uapi/asm/kvm.h | 1 + 4 files changed, 40 insertions(+), 3 deletions(-)
Documentation/virt/kvm/devices/arm-vgic-v3.rst +11 -1
@@ -291,8 +291,18 @@ Groups: | Aff3 | Aff2 | Aff1 | Aff0 | Errors: - ======= ============================================= -EINVAL vINTID is not multiple of 32 or info field is not VGIC_LEVEL_INFO_LINE_LEVEL ======= ============================================= + + KVM_DEV_ARM_VGIC_GRP_MAINT_IRQ + Attributes: + + The attr field of kvm_device_attr encodes the following values: + + bits: | 31 .... 5 | 4 .... 0 | + values: | RES0 | vINTID | + + The vINTID specifies which interrupt is generated when the vGIC + must generate a maintenance interrupt. This must be a PPI.
arch/arm64/include/uapi/asm/kvm.h +1 -0
@@ -403,6 +403,7 @@ enum {#define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6#define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7#define KVM_DEV_ARM_VGIC_GRP_ITS_REGS 8 +#define KVM_DEV_ARM_VGIC_GRP_MAINT_IRQ 9#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \ (0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
arch/arm64/kvm/vgic/vgic-kvm-device.c +27 -2
@@ -303,6 +303,12 @@ static int vgic_get_common_attr(struct kvm_device *dev, VGIC_NR_PRIVATE_IRQS, uaddr);break ; } +case KVM_DEV_ARM_VGIC_GRP_MAINT_IRQ : { +u32 __user *uaddr = (u32 __user *)(long )attr->addr; + + r =put_user (dev->kvm->arch.vgic.mi_intid, uaddr); +break ; + } }return r;
@@ -517,7 +523,7 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev,struct vgic_reg_attr reg_attr;gpa_t addr;struct kvm_vcpu *vcpu; -bool uaccess; +bool uaccess, post_init = true;u32 val;int ret;
@@ -533,6 +539,9 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev,/* Sysregs uaccess is performed by the sysreg handling code */ uaccess = false;break ; +case KVM_DEV_ARM_VGIC_GRP_MAINT_IRQ : + post_init = false; + fallthrough;default : uaccess = true; }
@@ -552,7 +561,7 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev,mutex_lock (&dev->kvm->arch.config_lock); -if (unlikely (!vgic_initialized (dev->kvm))) { +if (post_init !=vgic_initialized (dev->kvm)) { ret = -EBUSY ; goto out; }
@@ -582,6 +591,19 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev, }break ; } +case KVM_DEV_ARM_VGIC_GRP_MAINT_IRQ : +if (!is_write) { + val = dev->kvm->arch.vgic.mi_intid; + ret =0 ; +break ; + } + + ret = -EINVAL ; +if ((val <VGIC_NR_PRIVATE_IRQS ) && (val >=VGIC_NR_SGIS )) { + dev->kvm->arch.vgic.mi_intid = val; + ret =0 ; + } +break ;default : ret = -EINVAL ;break ;
@@ -608,6 +630,7 @@ static int vgic_v3_set_attr(struct kvm_device *dev,case KVM_DEV_ARM_VGIC_GRP_REDIST_REGS :case KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS :case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO : +case KVM_DEV_ARM_VGIC_GRP_MAINT_IRQ :return vgic_v3_attr_regs_access (dev, attr, true);default :return vgic_set_common_attr (dev, attr);
@@ -622,6 +645,7 @@ static int vgic_v3_get_attr(struct kvm_device *dev,case KVM_DEV_ARM_VGIC_GRP_REDIST_REGS :case KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS :case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO : +case KVM_DEV_ARM_VGIC_GRP_MAINT_IRQ :return vgic_v3_attr_regs_access (dev, attr, false);default :return vgic_get_common_attr (dev, attr);
@@ -645,6 +669,7 @@ static int vgic_v3_has_attr(struct kvm_device *dev,case KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS :return vgic_v3_has_attr_regs (dev, attr);case KVM_DEV_ARM_VGIC_GRP_NR_IRQS : +case KVM_DEV_ARM_VGIC_GRP_MAINT_IRQ :return 0 ;case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO : { if (((attr->attr & KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK) >>
tools/arch/arm/include/uapi/asm/kvm.h +1 -0
@@ -246,6 +246,7 @@ struct kvm_vcpu_events {#define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6#define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7#define KVM_DEV_ARM_VGIC_GRP_ITS_REGS 8 +#define KVM_DEV_ARM_VGIC_GRP_MAINT_IRQ 9#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \ (0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
Signature · 1 line
2.39.2
Marc Zyngier
maintainerPATCH v4 16/16 KVM: arm64: nv: Fail KVM init if asking for NV without GICv3
In reply to Marc ZyngierAlthough there is nothing in NV that is fundamentally incompatible with the lack of GICv3, there is no HW implementation without one, at least on the virtual side (yes, even fruits have some form of vGICv3).
We therefore make the decision to require GICv3, which will only affect models such as QEMU. Booting with a GICv2 or something even more exotic while asking for NV will result in KVM being disabled.
--- arch/arm64/kvm/arm.c | 7 +++++++ 1 file changed, 7 insertions(+)
arch/arm64/kvm/arm.c +7 -0
@@ -2321,6 +2321,13 @@ static int __init init_subsystems(void) goto out; } +if (kvm_mode ==KVM_MODE_NV && + !(vgic_present && kvm_vgic_global_state.type ==VGIC_V3 )) { +kvm_err ("NV support requires GICv3, giving up\n" ); + err = -EINVAL ; + goto out; + } +/* * Init HYP architected timer support */
Signature · 1 line
2.39.2
Oliver Upton
AppliedQuoted 8 lines · Marc Zyngier
Here's a respin of the NV support for GICv3. The integration branch containing this (and the rest of the NV stack) is still at [4].
At this stage, I think this is good to go.
* From v3 [3]:
[...]
Fixed up a few typos here but overall this is in great shape, thank you.
Applied to next, thanks!
[01/16] arm64: sysreg: Add layout for ICH_HCR_EL2
https://git.kernel.org/kvmarm/kvmarm/c/22513c0d2ad8 [02/16] arm64: sysreg: Add layout for ICH_VTR_EL2 https://git.kernel.org/kvmarm/kvmarm/c/5815fb82dc67 [03/16] arm64: sysreg: Add layout for ICH_MISR_EL2 https://git.kernel.org/kvmarm/kvmarm/c/b7a252e881f3 [04/16] KVM: arm64: nv: Load timer before the GIC https://git.kernel.org/kvmarm/kvmarm/c/16abeb60be62 [05/16] KVM: arm64: nv: Add ICH_*_EL2 registers to vpcu_sysreg https://git.kernel.org/kvmarm/kvmarm/c/182f1596941e [06/16] KVM: arm64: nv: Plumb handling of GICv3 EL2 accesses https://git.kernel.org/kvmarm/kvmarm/c/96c2f03311de [07/16] KVM: arm64: nv: Sanitise ICH_HCR_EL2 accesses https://git.kernel.org/kvmarm/kvmarm/c/21d29cd814d7 [08/16] KVM: arm64: nv: Nested GICv3 emulation https://git.kernel.org/kvmarm/kvmarm/c/146a050f2d8c [09/16] KVM: arm64: nv: Handle L2->L1 transition on interrupt injection https://git.kernel.org/kvmarm/kvmarm/c/4b1b97f0d7cf [10/16] KVM: arm64: nv: Add Maintenance Interrupt emulation https://git.kernel.org/kvmarm/kvmarm/c/201c8d40dde9 [11/16] KVM: arm64: nv: Respect virtual HCR_EL2.TWx setting https://git.kernel.org/kvmarm/kvmarm/c/69c9176c3862 [12/16] KVM: arm64: nv: Request vPE doorbell upon nested ERET to L2 https://git.kernel.org/kvmarm/kvmarm/c/93078ae63f20 [13/16] KVM: arm64: nv: Propagate used_lrs between L1 and L0 contexts https://git.kernel.org/kvmarm/kvmarm/c/7682c023212e [14/16] KVM: arm64: nv: Fold GICv3 host trapping requirements into guest setup https://git.kernel.org/kvmarm/kvmarm/c/89896cc15911 [15/16] KVM: arm64: nv: Allow userland to set VGIC maintenance IRQ https://git.kernel.org/kvmarm/kvmarm/c/faf7714a47a2 [16/16] KVM: arm64: nv: Fail KVM init if asking for NV without GICv3 https://git.kernel.org/kvmarm/kvmarm/c/83c6cb20147b
--
Best,
Oliver