KVM/arm64 fixes for 5.12, take #1
Subsystems (4)
Marc Zyngier
maintainerHi Paolo,
Here's the first batch of fixes for 5.12. We have a handful of low level world-switch regressions, a page table walker fix, more PMU tidying up, and a workaround for systems with creative firmware.
Note that this is based on -rc1 despite the breakage, as I didn't feel like holding these patches until -rc2.
Please pull,
M.
The following changes since commit fe07bfda2fb9cdef8a4d4008a409bb02f35f1bd8:
Linux 5.12-rc1 (2021-02-28 16:05:19 -0800)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git tags/kvmarm-fixes-5.12-1
for you to fetch changes up to e85583b3f1fe62c9b371a3100c1c91af94005ca9:
KVM: arm64: Fix range alignment when walking page tables (2021-03-04 09:54:12 +0000)
----------------------------------------------------------------
KVM/arm64 fixes for 5.12, take #1
- Fix SPE context save/restore on nVHE
- Fix some subtle host context corruption on vcpu exit
- Fix panic handling on nVHE
- Prevent the hypervisor from accessing PMU registers when there is none
- Workaround broken firmwares advertising bogus GICv2 compatibility
- Fix Stage-2 unaligned range unmapping
----------------------------------------------------------------
Andrew Scull (1):
KVM: arm64: Fix nVHE hyp panic host context restore
Jia He (1):
KVM: arm64: Fix range alignment when walking page tables
Marc Zyngier (4):
KVM: arm64: Turn kvm_arm_support_pmu_v3() into a static key
KVM: arm64: Don't access PMSELR_EL0/PMUSERENR_EL0 when no PMU is available
KVM: arm64: Rename __vgic_v3_get_ich_vtr_el2() to __vgic_v3_get_gic_config()
KVM: arm64: Workaround firmware wrongly advertising GICv2-on-v3 compatibility
Suzuki K Poulose (1):
KVM: arm64: nvhe: Save the SPE context early
Will Deacon (1):
KVM: arm64: Avoid corrupting vCPU context register in guest exit
arch/arm64/include/asm/kvm_asm.h | 4 ++-- arch/arm64/include/asm/kvm_hyp.h | 8 ++++++- arch/arm64/kernel/image-vars.h | 3 +++ arch/arm64/kvm/hyp/entry.S | 2 +- arch/arm64/kvm/hyp/include/hyp/switch.h | 9 +++++--- arch/arm64/kvm/hyp/nvhe/debug-sr.c | 12 ++++++++-- arch/arm64/kvm/hyp/nvhe/host.S | 15 +++++++------ arch/arm64/kvm/hyp/nvhe/hyp-main.c | 6 ++--- arch/arm64/kvm/hyp/nvhe/switch.c | 14 +++++++++--- arch/arm64/kvm/hyp/pgtable.c | 1 + arch/arm64/kvm/hyp/vgic-v3-sr.c | 40 +++++++++++++++++++++++++++++++-- arch/arm64/kvm/perf.c | 10 +++++++++ arch/arm64/kvm/pmu-emul.c | 10 --------- arch/arm64/kvm/vgic/vgic-v3.c | 12 +++++++--- include/kvm/arm_pmu.h | 9 ++++++-- 15 files changed, 116 insertions(+), 39 deletions(-)
_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Paolo Bonzini
maintainerQuoted 17 lines · Marc Zyngier
Hi Paolo,
Here's the first batch of fixes for 5.12. We have a handful of low level world-switch regressions, a page table walker fix, more PMU tidying up, and a workaround for systems with creative firmware.
Note that this is based on -rc1 despite the breakage, as I didn't feel like holding these patches until -rc2.
Please pull,
M.The following changes since commit
fe07bfda2fb9cdef8a4d4008a409bb02f35f1bd8:Linux 5.12-rc1 (2021-02-28 16:05:19 -0800)
Quoted 7 lines
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.gittags/kvmarm-fixes-5.12-1for you to fetch changes up to
e85583b3f1fe62c9b371a3100c1c91af94005ca9:KVM: arm64: Fix range alignment when walking page tables (2021-03-04 09:54:12 +0000)
Hi Marc,
due to a severe data corruption bug in 5.12-rc1, Linus suggested not including 5.12-rc1 in trees to avoid it eating our filesystems unwittingly during future bisections.
Would it be a problem for you to rebase on top of your merge window pull request? If there are conflicts, another possibility is for you to just send me the patch series. I will handle all the topic branch juggling.
This will mean rewriting kvmarm.git's history, but it does seem to be the lesser (or the most future-proof) evil.
Thanks,
Paolo
Quoted 29 lines
----------------------------------------------------------------
KVM/arm64 fixes for 5.12, take #1- Fix SPE context save/restore on nVHE
- Fix some subtle host context corruption on vcpu exit
- Fix panic handling on nVHE
- Prevent the hypervisor from accessing PMU registers when there is none
- Workaround broken firmwares advertising bogus GICv2 compatibility
- Fix Stage-2 unaligned range unmapping----------------------------------------------------------------
Andrew Scull (1):
KVM: arm64: Fix nVHE hyp panic host context restoreJia He (1):
KVM: arm64: Fix range alignment when walking page tablesMarc Zyngier (4):
KVM: arm64: Turnkvm_arm_support_pmu_v3()into a static key
KVM: arm64: Don't access PMSELR_EL0/PMUSERENR_EL0 when no PMU is available
KVM: arm64: Rename__vgic_v3_get_ich_vtr_el2()to__vgic_v3_get_gic_config()
KVM: arm64: Workaround firmware wrongly advertising GICv2-on-v3 compatibilitySuzuki K Poulose (1):
KVM: arm64: nvhe: Save the SPE context earlyWill Deacon (1):
KVM: arm64: Avoid corrupting vCPU context register in guest exit
Quoted 17 lines
arch/arm64/include/asm/kvm_asm.h | 4 ++-- arch/arm64/include/asm/kvm_hyp.h | 8 ++++++- arch/arm64/kernel/image-vars.h | 3 +++ arch/arm64/kvm/hyp/entry.S | 2 +- arch/arm64/kvm/hyp/include/hyp/switch.h | 9 +++++--- arch/arm64/kvm/hyp/nvhe/debug-sr.c | 12 ++++++++-- arch/arm64/kvm/hyp/nvhe/host.S | 15 +++++++------ arch/arm64/kvm/hyp/nvhe/hyp-main.c | 6 ++--- arch/arm64/kvm/hyp/nvhe/switch.c | 14 +++++++++--- arch/arm64/kvm/hyp/pgtable.c | 1 + arch/arm64/kvm/hyp/vgic-v3-sr.c | 40 +++++++++++++++++++++++++++++++-- arch/arm64/kvm/perf.c | 10 +++++++++ arch/arm64/kvm/pmu-emul.c | 10 --------- arch/arm64/kvm/vgic/vgic-v3.c | 12 +++++++--- include/kvm/arm_pmu.h | 9 ++++++-- 15 files changed, 116 insertions(+), 39 deletions(-)
_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Marc Zyngier
maintainerHi Paolo,
Quoted 33 lines · Paolo Bonzini
Quoted 17 lines · Marc Zyngier
Hi Paolo,
Here's the first batch of fixes for 5.12. We have a handful of low level world-switch regressions, a page table walker fix, more PMU tidying up, and a workaround for systems with creative firmware.
Note that this is based on -rc1 despite the breakage, as I didn't feel like holding these patches until -rc2.
Please pull,
M.The following changes since commit
fe07bfda2fb9cdef8a4d4008a409bb02f35f1bd8:Linux 5.12-rc1 (2021-02-28 16:05:19 -0800)Quoted 7 lines
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.gittags/kvmarm-fixes-5.12-1for you to fetch changes up to
e85583b3f1fe62c9b371a3100c1c91af94005ca9:KVM: arm64: Fix range alignment when walking page tables (2021-03-04 09:54:12 +0000)
Hi Marc,
due to a severe data corruption bug in 5.12-rc1, Linus suggested not including 5.12-rc1 in trees to avoid it eating our filesystems unwittingly during future bisections.
Quoted 7 lines
Would it be a problem for you to rebase on top of your merge window pull request? If there are conflicts, another possibility is for you to just send me the patch series. I will handle all the topic branch juggling.
This will mean rewriting kvmarm.git's history, but it does seem to be the lesser (or the most future-proof) evil.
The problem is that this is not only kvmarm, but also the Android tree, which directly pulls from the kvmarm stable branches. I guess we'll have to live with it.
I'll reply to this email with the patch series.
Thanks,
M.
Signature · 5 lines
Without deviation from the norm, progress is not possible. _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Marc Zyngier
maintainercover KVM/arm64 fixes for 5.12, take #1
Hi Paolo,
Here's the first batch of fixes for 5.12. We have a handful of low level world-switch regressions, a page table walker fix, more PMU tidying up, and a workaround for systems with creative firmware.
This will need to go on top of the current state of mainline.
Please apply,
M.
Andrew Scull (1):
KVM: arm64: Fix nVHE hyp panic host context restore
Jia He (1):
KVM: arm64: Fix range alignment when walking page tables
Marc Zyngier (4):
KVM: arm64: Turn kvm_arm_support_pmu_v3() into a static key
KVM: arm64: Don't access PMSELR_EL0/PMUSERENR_EL0 when no PMU is available
KVM: arm64: Rename __vgic_v3_get_ich_vtr_el2() to __vgic_v3_get_gic_config()
KVM: arm64: Workaround firmware wrongly advertising GICv2-on-v3 compatibility
Suzuki K Poulose (1):
KVM: arm64: nvhe: Save the SPE context early
Will Deacon (1):
KVM: arm64: Avoid corrupting vCPU context register in guest exit
arch/arm64/include/asm/kvm_asm.h | 4 ++-- arch/arm64/include/asm/kvm_hyp.h | 8 ++++++- arch/arm64/kernel/image-vars.h | 3 +++ arch/arm64/kvm/hyp/entry.S | 2 +- arch/arm64/kvm/hyp/include/hyp/switch.h | 9 +++++--- arch/arm64/kvm/hyp/nvhe/debug-sr.c | 12 ++++++++-- arch/arm64/kvm/hyp/nvhe/host.S | 15 +++++++------ arch/arm64/kvm/hyp/nvhe/hyp-main.c | 6 ++--- arch/arm64/kvm/hyp/nvhe/switch.c | 14 +++++++++--- arch/arm64/kvm/hyp/pgtable.c | 1 + arch/arm64/kvm/hyp/vgic-v3-sr.c | 40 +++++++++++++++++++++++++++++++-- arch/arm64/kvm/perf.c | 10 +++++++++ arch/arm64/kvm/pmu-emul.c | 10 --------- arch/arm64/kvm/vgic/vgic-v3.c | 12 +++++++--- include/kvm/arm_pmu.h | 9 ++++++-- 15 files changed, 116 insertions(+), 39 deletions(-)
_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Marc Zyngier
maintainerPATCH 1/8 KVM: arm64: nvhe: Save the SPE context early
From: Suzuki K Poulose <[email protected]>
The nVHE KVM hyp drains and disables the SPE buffer, before entering the guest, as the EL1&0 translation regime is going to be loaded with that of the guest.
But this operation is performed way too late, because :
- The owning translation regime of the SPE buffer
is transferred to EL2. (MDCR_EL2_E2PB == 0)
- The guest Stage1 is loaded.
Thus the flush could use the host EL1 virtual address, but use the EL2 translations instead of host EL1, for writing out any cached data.
Fix this by moving the SPE buffer handling early enough. The restore path is doing the right thing.
--- arch/arm64/include/asm/kvm_hyp.h | 5 +++++ arch/arm64/kvm/hyp/nvhe/debug-sr.c | 12 ++++++++++-- arch/arm64/kvm/hyp/nvhe/switch.c | 11 ++++++++++- 3 files changed, 25 insertions(+), 3 deletions(-)
arch/arm64/include/asm/kvm_hyp.h +5 -0
@@ -83,6 +83,11 @@ void sysreg_restore_guest_state_vhe(struct kvm_cpu_context *ctxt);void __debug_switch_to_guest (struct kvm_vcpu *vcpu);void __debug_switch_to_host (struct kvm_vcpu *vcpu); +#ifdef __KVM_NVHE_HYPERVISOR__ +void __debug_save_host_buffers_nvhe (struct kvm_vcpu *vcpu); +void __debug_restore_host_buffers_nvhe (struct kvm_vcpu *vcpu); +#endif +void __fpsimd_save_state (struct user_fpsimd_state *fp_regs);void __fpsimd_restore_state (struct user_fpsimd_state *fp_regs);
arch/arm64/kvm/hyp/nvhe/debug-sr.c +10 -2
@@ -58,16 +58,24 @@ static void __debug_restore_spe(u64 pmscr_el1)write_sysreg_s (pmscr_el1,SYS_PMSCR_EL1 ); } -void __debug_switch_to_guest (struct kvm_vcpu *vcpu) +void __debug_save_host_buffers_nvhe (struct kvm_vcpu *vcpu) {/* Disable and flush SPE data generation */ __debug_save_spe (&vcpu->arch.host_debug_state.pmscr_el1); +} + +void __debug_switch_to_guest (struct kvm_vcpu *vcpu) +{__debug_switch_to_guest_common (vcpu); } -void __debug_switch_to_host (struct kvm_vcpu *vcpu) +void __debug_restore_host_buffers_nvhe (struct kvm_vcpu *vcpu) {__debug_restore_spe (vcpu->arch.host_debug_state.pmscr_el1); +} + +void __debug_switch_to_host (struct kvm_vcpu *vcpu) +{__debug_switch_to_host_common (vcpu); }
arch/arm64/kvm/hyp/nvhe/switch.c +10 -1
@@ -192,6 +192,14 @@ int __kvm_vcpu_run(struct kvm_vcpu *vcpu) pmu_switch_needed =__pmu_switch_to_guest (host_ctxt);__sysreg_save_state_nvhe (host_ctxt); +/* +* We must flush and disable the SPE buffer for nVHE, as +* the translation regime(EL1&0) is going to be loaded with +* that of the guest. And we must do this before we change the +* translation regime to EL2 (via MDCR_EL2_E2PB == 0) and +* before we load guest Stage1. +*/ +__debug_save_host_buffers_nvhe (vcpu);__adjust_pc (vcpu);
@@ -234,11 +242,12 @@ int __kvm_vcpu_run(struct kvm_vcpu *vcpu)if (vcpu->arch.flags &KVM_ARM64_FP_ENABLED )__fpsimd_save_fpexc32 (vcpu); +__debug_switch_to_host (vcpu);/* * This must come after restoring the host sysregs, since a non-VHE * system may enable SPE here and make use of the TTBRs. */ -__debug_switch_to_host (vcpu); +__debug_restore_host_buffers_nvhe (vcpu);if (pmu_switch_needed)__pmu_switch_to_host (host_ctxt);
Signature · 6 lines
2.29.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Marc Zyngier
maintainerPATCH 2/8 KVM: arm64: Avoid corrupting vCPU context register in guest exit
In reply to Marc ZyngierFrom: Will Deacon <[email protected]>
Commit 7db21530479f ("KVM: arm64: Restore hyp when panicking in guest context") tracks the currently running vCPU, clearing the pointer to NULL on exit from a guest.
Unfortunately, the use of 'set_loaded_vcpu' clobbers x1 to point at the kvm_hyp_ctxt instead of the vCPU context, causing the subsequent RAS code to go off into the weeds when it saves the DISR assuming that the CPU context is embedded in a struct vCPU.
Leave x1 alone and use x3 as a temporary register instead when clearing the vCPU on the guest exit path.
--- arch/arm64/kvm/hyp/entry.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/kvm/hyp/entry.S +1 -1
@@ -146,7 +146,7 @@ SYM_INNER_LABEL(__guest_exit, SYM_L_GLOBAL) // Now restore the hyp regs restore_callee_saved_regs x2 - set_loaded_vcpu xzr, x1, x2 + set_loaded_vcpu xzr, x2, x3 alternative_if ARM64_HAS_RAS_EXTN // If we have the RAS extensions we can consume a pending error
Signature · 6 lines
2.29.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Marc Zyngier
maintainerPATCH 3/8 KVM: arm64: Fix nVHE hyp panic host context restore
In reply to Marc ZyngierFrom: Andrew Scull <[email protected]>
When panicking from the nVHE hyp and restoring the host context, x29 is expected to hold a pointer to the host context. This wasn't being done so fix it to make sure there's a valid pointer the host context being used.
Rather than passing a boolean indicating whether or not the host context should be restored, instead pass the pointer to the host context. NULL is passed to indicate that no context should be restored.
--- arch/arm64/include/asm/kvm_hyp.h | 3 ++- arch/arm64/kvm/hyp/nvhe/host.S | 15 ++++++++------- arch/arm64/kvm/hyp/nvhe/switch.c | 3 +-- 3 files changed, 11 insertions(+), 10 deletions(-)
arch/arm64/include/asm/kvm_hyp.h +2 -1
@@ -102,7 +102,8 @@ bool kvm_host_psci_handler(struct kvm_cpu_context *host_ctxt);void __noreturn hyp_panic (void );#ifdef __KVM_NVHE_HYPERVISOR__ -void __noreturn __hyp_do_panic (bool restore_host,u64 spsr,u64 elr,u64 par); +void __noreturn __hyp_do_panic (struct kvm_cpu_context *host_ctxt,u64 spsr, +u64 elr,u64 par);#endif #endif /* __ARM64_KVM_HYP_H__ */
arch/arm64/kvm/hyp/nvhe/host.S +8 -7
@@ -71,7 +71,8 @@ SYM_FUNC_START(__host_enter) SYM_FUNC_END(__host_enter) /* - * void __noreturn __hyp_do_panic(bool restore_host, u64 spsr, u64 elr, u64 par); + * void __noreturn __hyp_do_panic(struct kvm_cpu_context *host_ctxt, u64 spsr, + * u64 elr, u64 par); */ SYM_FUNC_START(__hyp_do_panic) /* Prepare and exit to the host's panic funciton. */
@@ -82,9 +83,11 @@ SYM_FUNC_START(__hyp_do_panic) hyp_kimg_va lr, x6 msr elr_el2, lr - /* Set the panic format string. Use the, now free, LR as scratch. */ - ldr lr, =__hyp_panic_string - hyp_kimg_va lr, x6 + mov x29, x0 + + /* Load the format string into x0 and arguments into x1-7 */ + ldr x0, =__hyp_panic_string + hyp_kimg_va x0, x6 /* Load the format arguments into x1-7. */ mov x6, x3
@@ -94,9 +97,7 @@ SYM_FUNC_START(__hyp_do_panic) mrs x5, hpfar_el2 /* Enter the host, conditionally restoring the host context. */ - cmp x0, xzr - mov x0, lr - b.eq __host_enter_without_restoring + cbz x29, __host_enter_without_restoring b __host_enter_for_panic SYM_FUNC_END(__hyp_do_panic)
arch/arm64/kvm/hyp/nvhe/switch.c +1 -2
@@ -266,7 +266,6 @@ void __noreturn hyp_panic(void)u64 spsr =read_sysreg_el2 (SYS_SPSR );u64 elr =read_sysreg_el2 (SYS_ELR );u64 par =read_sysreg_par (); -bool restore_host = true;struct kvm_cpu_context *host_ctxt;struct kvm_vcpu *vcpu;
@@ -280,7 +279,7 @@ void __noreturn hyp_panic(void)__sysreg_restore_state_nvhe (host_ctxt); } -__hyp_do_panic (restore_host, spsr, elr, par); +__hyp_do_panic (host_ctxt, spsr, elr, par);unreachable (); }
Signature · 6 lines
2.29.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Marc Zyngier
maintainerPATCH 4/8 KVM: arm64: Turn kvm_arm_support_pmu_v3() into a static key
In reply to Marc ZyngierWe currently find out about the presence of a HW PMU (or the handling of that PMU by perf, which amounts to the same thing) in a fairly roundabout way, by checking the number of counters available to perf. That's good enough for now, but we will soon need to find about about that on paths where perf is out of reach (in the world switch).
Instead, let's turn kvm_arm_support_pmu_v3() into a static key.
--- arch/arm64/kvm/perf.c | 10 ++++++++++ arch/arm64/kvm/pmu-emul.c | 10 ---------- include/kvm/arm_pmu.h | 9 +++++++-- 3 files changed, 17 insertions(+), 12 deletions(-)
arch/arm64/kvm/perf.c +10 -0
@@ -11,6 +11,8 @@#include <asm/kvm_emulate.h> +DEFINE_STATIC_KEY_FALSE (kvm_arm_pmu_available); +static int kvm_is_in_guest (void ) {return kvm_get_running_vcpu () !=NULL ;
@@ -48,6 +50,14 @@ static struct perf_guest_info_callbacks kvm_guest_cbs = {int kvm_perf_init (void ) { +/* +* Check if HW_PERF_EVENTS are supported by checking the number of +* hardware performance counters. This could ensure the presence of +* a physical PMU and CONFIG_PERF_EVENT is selected. +*/ +if (IS_ENABLED (CONFIG_ARM_PMU ) &&perf_num_counters () >0 ) +static_branch_enable (&kvm_arm_pmu_available); +return perf_register_guest_info_callbacks (&kvm_guest_cbs); }
arch/arm64/kvm/pmu-emul.c +0 -10
@@ -823,16 +823,6 @@ u64 kvm_pmu_get_pmceid(struct kvm_vcpu *vcpu, bool pmceid1)return val & mask; } -bool kvm_arm_support_pmu_v3 (void ) -{ -/* -* Check if HW_PERF_EVENTS are supported by checking the number of -* hardware performance counters. This could ensure the presence of -* a physical PMU and CONFIG_PERF_EVENT is selected. -*/ -return (perf_num_counters () >0 ); -} -int kvm_arm_pmu_v3_enable (struct kvm_vcpu *vcpu) {if (!kvm_vcpu_has_pmu (vcpu))
include/kvm/arm_pmu.h +7 -2
@@ -13,6 +13,13 @@#define ARMV8_PMU_CYCLE_IDX (ARMV8_PMU_MAX_COUNTERS - 1)#define ARMV8_PMU_MAX_COUNTER_PAIRS ((ARMV8_PMU_MAX_COUNTERS + 1) >> 1) +DECLARE_STATIC_KEY_FALSE (kvm_arm_pmu_available); + +static __always_inline bool kvm_arm_support_pmu_v3(void) +{ +return static_branch_likely (&kvm_arm_pmu_available); +} +#ifdef CONFIG_HW_PERF_EVENTS struct kvm_pmc {
@@ -47,7 +54,6 @@ void kvm_pmu_software_increment(struct kvm_vcpu *vcpu, u64 val);void kvm_pmu_handle_pmcr (struct kvm_vcpu *vcpu,u64 val);void kvm_pmu_set_counter_event_type (struct kvm_vcpu *vcpu,u64 data,u64 select_idx); -bool kvm_arm_support_pmu_v3 (void );int kvm_arm_pmu_v3_set_attr (struct kvm_vcpu *vcpu,struct kvm_device_attr *attr); int kvm_arm_pmu_v3_get_attr(struct kvm_vcpu *vcpu,
@@ -87,7 +93,6 @@ static inline void kvm_pmu_software_increment(struct kvm_vcpu *vcpu, u64 val) {}static inline void kvm_pmu_handle_pmcr (struct kvm_vcpu *vcpu,u64 val) {}static inline void kvm_pmu_set_counter_event_type (struct kvm_vcpu *vcpu,u64 data,u64 select_idx) {} -static inline bool kvm_arm_support_pmu_v3 (void ) {return false; }static inline int kvm_arm_pmu_v3_set_attr (struct kvm_vcpu *vcpu,struct kvm_device_attr *attr) {
Signature · 6 lines
2.29.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Marc Zyngier
maintainerPATCH 5/8 KVM: arm64: Don't access PMSELR_EL0/PMUSERENR_EL0 when no PMU is available
In reply to Marc ZyngierWhen running under a nesting hypervisor, it isn't guaranteed that the virtual HW will include a PMU. In which case, let's not try to access the PMU registers in the world switch, as that'd be deadly.
--- arch/arm64/kernel/image-vars.h | 3 +++ arch/arm64/kvm/hyp/include/hyp/switch.h | 9 ++++++--- 2 files changed, 9 insertions(+), 3 deletions(-)
arch/arm64/kernel/image-vars.h +3 -0
@@ -101,6 +101,9 @@ KVM_NVHE_ALIAS(__stop___kvm_ex_table);/* Array containing bases of nVHE per-CPU memory regions. */ KVM_NVHE_ALIAS (kvm_arm_hyp_percpu_base); +/* PMU available static key */ +KVM_NVHE_ALIAS (kvm_arm_pmu_available); +#endif /* CONFIG_KVM */ #endif /* __ARM64_KERNEL_IMAGE_VARS_H */
arch/arm64/kvm/hyp/include/hyp/switch.h +6 -3
@@ -90,15 +90,18 @@ static inline void __activate_traps_common(struct kvm_vcpu *vcpu)* counter, which could make a PMXEVCNTR_EL0 access UNDEF at * EL1 instead of being trapped to EL2. */ -write_sysreg (0 , pmselr_el0); -write_sysreg (ARMV8_PMU_USERENR_MASK , pmuserenr_el0); +if (kvm_arm_support_pmu_v3 ()) { +write_sysreg (0 , pmselr_el0); +write_sysreg (ARMV8_PMU_USERENR_MASK , pmuserenr_el0); + }write_sysreg (vcpu->arch.mdcr_el2, mdcr_el2); }static inline void __deactivate_traps_common (void ) {write_sysreg (0 , hstr_el2); -write_sysreg (0 , pmuserenr_el0); +if (kvm_arm_support_pmu_v3 ()) +write_sysreg (0 , pmuserenr_el0); }static inline void ___activate_traps (struct kvm_vcpu *vcpu)
Signature · 6 lines
2.29.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Marc Zyngier
maintainerPATCH 6/8 KVM: arm64: Rename __vgic_v3_get_ich_vtr_el2() to __vgic_v3_get_gic_config()
In reply to Marc ZyngierAs we are about to report a bit more information to the rest of the kernel, rename __vgic_v3_get_ich_vtr_el2() to the more explicit __vgic_v3_get_gic_config().
No functional change.
--- arch/arm64/include/asm/kvm_asm.h | 4 ++-- arch/arm64/kvm/hyp/nvhe/hyp-main.c | 6 +++--- arch/arm64/kvm/hyp/vgic-v3-sr.c | 7 ++++++- arch/arm64/kvm/vgic/vgic-v3.c | 4 +++- 4 files changed, 14 insertions(+), 7 deletions(-)
arch/arm64/include/asm/kvm_asm.h +2 -2
@@ -50,7 +50,7 @@#define __KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_local_vmid 5#define __KVM_HOST_SMCCC_FUNC___kvm_timer_set_cntvoff 6#define __KVM_HOST_SMCCC_FUNC___kvm_enable_ssbs 7 -#define __KVM_HOST_SMCCC_FUNC___vgic_v3_get_ich_vtr_el2 8 +#define __KVM_HOST_SMCCC_FUNC___vgic_v3_get_gic_config 8#define __KVM_HOST_SMCCC_FUNC___vgic_v3_read_vmcr 9#define __KVM_HOST_SMCCC_FUNC___vgic_v3_write_vmcr 10#define __KVM_HOST_SMCCC_FUNC___vgic_v3_init_lrs 11
@@ -192,7 +192,7 @@ extern void __kvm_timer_set_cntvoff(u64 cntvoff);extern int __kvm_vcpu_run (struct kvm_vcpu *vcpu); -extern u64 __vgic_v3_get_ich_vtr_el2 (void ); +extern u64 __vgic_v3_get_gic_config (void );extern u64 __vgic_v3_read_vmcr (void );extern void __vgic_v3_write_vmcr (u32 vmcr);extern void __vgic_v3_init_lrs (void );
arch/arm64/kvm/hyp/nvhe/hyp-main.c +3 -3
@@ -67,9 +67,9 @@ static void handle___kvm_enable_ssbs(struct kvm_cpu_context *host_ctxt)write_sysreg_el2 (tmp,SYS_SCTLR ); } -static void handle___vgic_v3_get_ich_vtr_el2 (struct kvm_cpu_context *host_ctxt) +static void handle___vgic_v3_get_gic_config (struct kvm_cpu_context *host_ctxt) { -cpu_reg (host_ctxt,1 ) =__vgic_v3_get_ich_vtr_el2 (); +cpu_reg (host_ctxt,1 ) =__vgic_v3_get_gic_config (); }static void handle___vgic_v3_read_vmcr (struct kvm_cpu_context *host_ctxt)
@@ -118,7 +118,7 @@ static const hcall_t host_hcall[] = {HANDLE_FUNC (__kvm_tlb_flush_local_vmid),HANDLE_FUNC (__kvm_timer_set_cntvoff),HANDLE_FUNC (__kvm_enable_ssbs), -HANDLE_FUNC (__vgic_v3_get_ich_vtr_el2), +HANDLE_FUNC (__vgic_v3_get_gic_config),HANDLE_FUNC (__vgic_v3_read_vmcr),HANDLE_FUNC (__vgic_v3_write_vmcr), HANDLE_FUNC(__vgic_v3_init_lrs),
arch/arm64/kvm/hyp/vgic-v3-sr.c +6 -1
@@ -405,7 +405,12 @@ void __vgic_v3_init_lrs(void)__gic_v3_set_lr (0 , i); } -u64 __vgic_v3_get_ich_vtr_el2 (void ) +/* +* Return the GIC CPU configuration: +* - [31:0] ICH_VTR_EL2 +* - [63:32] RES0 +*/ +u64 __vgic_v3_get_gic_config (void ) {return read_gicreg (ICH_VTR_EL2 ); }
arch/arm64/kvm/vgic/vgic-v3.c +3 -1
@@ -574,9 +574,11 @@ early_param("kvm-arm.vgic_v4_enable", early_gicv4_enable);*/ int vgic_v3_probe (const struct gic_kvm_info *info) { -u32 ich_vtr_el2 =kvm_call_hyp_ret (__vgic_v3_get_ich_vtr_el2); +u64 ich_vtr_el2 =kvm_call_hyp_ret (__vgic_v3_get_gic_config);int ret; + ich_vtr_el2 = (u32 )ich_vtr_el2; +/* * The ListRegs field is 5 bits, but there is an architectural * maximum of 16 list registers. Just ignore bit 4...
Signature · 6 lines
2.29.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Marc Zyngier
maintainerPATCH 7/8 KVM: arm64: Workaround firmware wrongly advertising GICv2-on-v3 compatibility
In reply to Marc ZyngierIt looks like we have broken firmware out there that wrongly advertises a GICv2 compatibility interface, despite the CPUs not being able to deal with it.
To work around this, check that the CPU initialising KVM is actually able to switch to MMIO instead of system registers, and use that as a precondition to enable GICv2 compatibility in KVM.
Note that the detection happens on a single CPU. If the firmware is lying *and* that the CPUs are asymetric, all hope is lost anyway.
--- arch/arm64/kvm/hyp/vgic-v3-sr.c | 35 +++++++++++++++++++++++++++++++-- arch/arm64/kvm/vgic/vgic-v3.c | 8 ++++++-- 2 files changed, 39 insertions(+), 4 deletions(-)
arch/arm64/kvm/hyp/vgic-v3-sr.c +33 -2
@@ -408,11 +408,42 @@ void __vgic_v3_init_lrs(void)/* * Return the GIC CPU configuration: * - [31:0] ICH_VTR_EL2 -* - [63:32] RES0 +* - [62:32] RES0 +* - [63] MMIO (GICv2) capable */ u64 __vgic_v3_get_gic_config (void ) { -return read_gicreg (ICH_VTR_EL2 ); +u64 val, sre =read_gicreg (ICC_SRE_EL1 ); +unsigned long flags =0 ; + +/* +* To check whether we have a MMIO-based (GICv2 compatible) +* CPU interface, we need to disable the system register +* view. To do that safely, we have to prevent any interrupt +* from firing (which would be deadly). +* +* Note that this only makes sense on VHE, as interrupts are +* already masked for nVHE as part of the exception entry to +* EL2. +*/ +if (has_vhe ()) + flags =local_daif_save (); + +write_gicreg (0 ,ICC_SRE_EL1 ); +isb (); + + val =read_gicreg (ICC_SRE_EL1 ); + +write_gicreg (sre,ICC_SRE_EL1 ); +isb (); + +if (has_vhe ()) +local_daif_restore (flags); + + val = (val &ICC_SRE_EL1_SRE ) ?0 : (1ULL <<63 ); + val |=read_gicreg (ICH_VTR_EL2 ); + +return val; }u64 __vgic_v3_read_vmcr (void )
arch/arm64/kvm/vgic/vgic-v3.c +6 -2
@@ -575,8 +575,10 @@ early_param("kvm-arm.vgic_v4_enable", early_gicv4_enable);int vgic_v3_probe (const struct gic_kvm_info *info) {u64 ich_vtr_el2 =kvm_call_hyp_ret (__vgic_v3_get_gic_config); +bool has_v2;int ret; + has_v2 = ich_vtr_el2 >>63 ; ich_vtr_el2 = (u32 )ich_vtr_el2;/*
@@ -596,13 +598,15 @@ int vgic_v3_probe(const struct gic_kvm_info *info) gicv4_enable ? "en" : "dis"); } + kvm_vgic_global_state.vcpu_base =0 ; +if (!info->vcpu.start) {kvm_info ("GICv3: no GICV resource entry\n" ); - kvm_vgic_global_state.vcpu_base =0 ; + }else if (!has_v2) { +pr_warn (FW_BUG "CPU interface incapable of MMIO access\n" ); }else if (!PAGE_ALIGNED (info->vcpu.start)) {pr_warn ("GICV physical address 0x%llx not page aligned\n" , (unsigned long long )info->vcpu.start); - kvm_vgic_global_state.vcpu_base =0 ; }else { kvm_vgic_global_state.vcpu_base = info->vcpu.start; kvm_vgic_global_state.can_emulate_gicv2 = true;
Signature · 6 lines
2.29.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
RE: [PATCH 7/8] KVM: arm64: Workaround firmware wrongly advertising GICv2-on-v3 compatibility
Quoted 28 lines
-----Original Message-----
From: Marc Zyngier [mailto:[email protected]]
Sent: 05 March 2021 18:53
To: Paolo Bonzini <[email protected]>
Cc: Alexandru Elisei <[email protected]>; Andre Przywara <[email protected]>; Andrew Scull <[email protected]>; Catalin Marinas <[email protected]>; Christoffer Dall <[email protected]>; Howard Zhang <[email protected]>; Jia He <[email protected]>; Mark Rutland <[email protected]>; Quentin Perret <[email protected]>; Shameerali Kolothum Thodi <[email protected]>; Suzuki K Poulose <[email protected]>; Will Deacon <[email protected]>; James Morse <[email protected]>; Julien Thierry <[email protected]>; [email protected]; [email protected]; [email protected]; [email protected]
Subject: [PATCH 7/8] KVM: arm64: Workaround firmware wrongly advertising GICv2-on-v3 compatibilityIt looks like we have broken firmware out there that wrongly advertises a GICv2 compatibility interface, despite the CPUs not being able to deal with it.
To work around this, check that the CPU initialising KVM is actually able to switch to MMIO instead of system registers, and use that as a precondition to enable GICv2 compatibility in KVM.
Quoted 7 lines
Note that the detection happens on a single CPU. If the firmware is lying *and* that the CPUs are asymetric, all hope is lost anyway.
Reported-by: Shameerali Kolothum Thodi
<[email protected]>Tested-by Shameer Kolothum <[email protected]>Signed-off-by Marc Zyngier <[email protected]>
Is it possible to add stable tag for this? Looks like we do have systems out there and reports issues.
Thanks,
Shameer
Quoted 90 lines
--- arch/arm64/kvm/hyp/vgic-v3-sr.c | 35 +++++++++++++++++++++++++++++++-- arch/arm64/kvm/vgic/vgic-v3.c | 8 ++++++-- 2 files changed, 39 insertions(+), 4 deletions(-)arch/arm64/kvm/hyp/vgic-v3-sr.c +33
-2@@ -408,11 +408,42 @@ void __vgic_v3_init_lrs(void)/* * Return the GIC CPU configuration: * - [31:0] ICH_VTR_EL2 -* - [63:32] RES0 +* - [62:32] RES0 +* - [63] MMIO (GICv2) capable */ u64 __vgic_v3_get_gic_config (void ) { -return read_gicreg (ICH_VTR_EL2 ); +u64 val, sre =read_gicreg (ICC_SRE_EL1 ); +unsigned long flags =0 ; + +/* +* To check whether we have a MMIO-based (GICv2 compatible) +* CPU interface, we need to disable the system register +* view. To do that safely, we have to prevent any interrupt +* from firing (which would be deadly). +* +* Note that this only makes sense on VHE, as interrupts are +* already masked for nVHE as part of the exception entry to +* EL2. +*/ +if (has_vhe ()) + flags =local_daif_save (); + +write_gicreg (0 ,ICC_SRE_EL1 ); +isb (); + + val =read_gicreg (ICC_SRE_EL1 ); + +write_gicreg (sre,ICC_SRE_EL1 ); +isb (); + +if (has_vhe ()) +local_daif_restore (flags); + + val = (val &ICC_SRE_EL1_SRE ) ?0 : (1ULL <<63 ); + val |=read_gicreg (ICH_VTR_EL2 ); + +return val; }u64 __vgic_v3_read_vmcr (void )arch/arm64/kvm/vgic/vgic-v3.c +2
-0@@ -575,8 +575,10 @@ early_param("kvm-arm.vgic_v4_enable", early_gicv4_enable);int vgic_v3_probe (const struct gic_kvm_info *info) {u64 ich_vtr_el2 =kvm_call_hyp_ret (__vgic_v3_get_gic_config); +bool has_v2;int ret; + has_v2 = ich_vtr_el2 >>63 ; ich_vtr_el2 = (u32 )ich_vtr_el2;arch/arm64/kvm/vgic/vgic-v3.c +4
-3/* @@ -596,13 +598,15 @@ int vgic_v3_probe(const struct gic_kvm_info *info) gicv4_enable ? "en" : "dis"); } + kvm_vgic_global_state.vcpu_base =0 ; +if (!info->vcpu.start) {kvm_info ("GICv3: no GICV resource entry\n" ); - kvm_vgic_global_state.vcpu_base =0 ; + }else if (!has_v2) { +pr_warn (FW_BUG "CPU interface incapable of MMIO access\n" ); }else if (!PAGE_ALIGNED (info->vcpu.start)) {pr_warn ("GICV physical address 0x%llx not page aligned\n" , (unsigned long long )info->vcpu.start); - kvm_vgic_global_state.vcpu_base =0 ; }else { kvm_vgic_global_state.vcpu_base = info->vcpu.start; kvm_vgic_global_state.can_emulate_gicv2 = true; --
Quoted 1 line
2.29.2
_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Marc Zyngier
maintainerRe: [PATCH 7/8] KVM: arm64: Workaround firmware wrongly advertising GICv2-on-v3 compatibility
Quoted 32 lines · Shameerali Kolothum Thodi
Quoted 32 lines
-----Original Message-----
From: Marc Zyngier [mailto:[email protected]]
Sent: 05 March 2021 18:53
To: Paolo Bonzini <[email protected]>
Cc: Alexandru Elisei <[email protected]>; Andre Przywara <[email protected]>; Andrew Scull <[email protected]>; Catalin Marinas <[email protected]>; Christoffer Dall <[email protected]>; Howard Zhang <[email protected]>; Jia He <[email protected]>; Mark Rutland <[email protected]>; Quentin Perret <[email protected]>; Shameerali Kolothum Thodi <[email protected]>; Suzuki K Poulose <[email protected]>; Will Deacon <[email protected]>; James Morse <[email protected]>; Julien Thierry <[email protected]>; [email protected]; [email protected]; [email protected]; [email protected]
Subject: [PATCH 7/8] KVM: arm64: Workaround firmware wrongly advertising GICv2-on-v3 compatibilityIt looks like we have broken firmware out there that wrongly advertises a GICv2 compatibility interface, despite the CPUs not being able to deal with it.
To work around this, check that the CPU initialising KVM is actually able to switch to MMIO instead of system registers, and use that as a precondition to enable GICv2 compatibility in KVM.
Note that the detection happens on a single CPU. If the firmware is lying *and* that the CPUs are asymetric, all hope is lost anyway.
Quoted 7 lines
Quoted 4 lines
Reported-by: Shameerali Kolothum Thodi
<[email protected]>Tested-by Shameer Kolothum <[email protected]>Signed-off-by Marc Zyngier <[email protected]>Is it possible to add stable tag for this? Looks like we do have systems out there and reports issues.
It is already merged. Which kernel versions do you need that for? In any case, please submit the backports, and I'll review them.
Thanks,
M.
Signature · 5 lines
Without deviation from the norm, progress is not possible. _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Marc Zyngier
maintainerPATCH 8/8 KVM: arm64: Fix range alignment when walking page tables
In reply to Marc ZyngierFrom: Jia He <[email protected]>
When walking the page tables at a given level, and if the start address for the range isn't aligned for that level, we propagate the misalignment on each iteration at that level.
This results in the walker ignoring a number of entries (depending on the original misalignment) on each subsequent iteration.
Properly aligning the address before the next iteration addresses this issue.
--- arch/arm64/kvm/hyp/pgtable.c | 1 + 1 file changed, 1 insertion(+)
arch/arm64/kvm/hyp/pgtable.c +1 -0
@@ -223,6 +223,7 @@ static inline int __kvm_pgtable_visit(struct kvm_pgtable_walk_data *data, goto out;if (!table) { + data->addr =ALIGN_DOWN (data->addr,kvm_granule_size (level)); data->addr +=kvm_granule_size (level); goto out; }
Signature · 6 lines
2.29.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Quoted 7 lines · Marc Zyngier
Hi Paolo,
Here's the first batch of fixes for 5.12. We have a handful of low level world-switch regressions, a page table walker fix, more PMU tidying up, and a workaround for systems with creative firmware.
This will need to go on top of the current state of mainline.
Applied to kvm/next (because kvm/master is also on the problematic 5.12-rc1 tags), thanks.
Paolo
Quoted 22 lines
Please apply,
M.Andrew Scull (1):
KVM: arm64: Fix nVHE hyp panic host context restoreJia He (1):
KVM: arm64: Fix range alignment when walking page tablesMarc Zyngier (4):
KVM: arm64: Turnkvm_arm_support_pmu_v3()into a static key
KVM: arm64: Don't access PMSELR_EL0/PMUSERENR_EL0 when no PMU is available
KVM: arm64: Rename__vgic_v3_get_ich_vtr_el2()to__vgic_v3_get_gic_config()
KVM: arm64: Workaround firmware wrongly advertising GICv2-on-v3 compatibilitySuzuki K Poulose (1):
KVM: arm64: nvhe: Save the SPE context earlyWill Deacon (1):
KVM: arm64: Avoid corrupting vCPU context register in guest exit
Quoted 17 lines
arch/arm64/include/asm/kvm_asm.h | 4 ++-- arch/arm64/include/asm/kvm_hyp.h | 8 ++++++- arch/arm64/kernel/image-vars.h | 3 +++ arch/arm64/kvm/hyp/entry.S | 2 +- arch/arm64/kvm/hyp/include/hyp/switch.h | 9 +++++--- arch/arm64/kvm/hyp/nvhe/debug-sr.c | 12 ++++++++-- arch/arm64/kvm/hyp/nvhe/host.S | 15 +++++++------ arch/arm64/kvm/hyp/nvhe/hyp-main.c | 6 ++--- arch/arm64/kvm/hyp/nvhe/switch.c | 14 +++++++++--- arch/arm64/kvm/hyp/pgtable.c | 1 + arch/arm64/kvm/hyp/vgic-v3-sr.c | 40 +++++++++++++++++++++++++++++++-- arch/arm64/kvm/perf.c | 10 +++++++++ arch/arm64/kvm/pmu-emul.c | 10 --------- arch/arm64/kvm/vgic/vgic-v3.c | 12 +++++++--- include/kvm/arm_pmu.h | 9 ++++++-- 15 files changed, 116 insertions(+), 39 deletions(-)
_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm