[PATCH v2 3/3] arm64: Allow nVHE impaired CPUs to boot without CONFIG_ARM64_VHE
From: Marc Zyngier <maz@kernel.org>
Date: 2021-03-30 17:41:56
Subsystem:
arm64 port (aarch64 architecture), kernel virtual machine for arm64 (kvm/arm64), the rest · Maintainers:
Catalin Marinas, Will Deacon, Marc Zyngier, Oliver Upton, Linus Torvalds
CPUs stuck in VHE mode need some additional care if the kernel is compiled without CONFIG_ARM64_VHE. Treat this case as another version of a mismatched boot, and prevent KVM from being initialised. The machine will boot in some bizarre state, using TPIDR_EL1 instead of TPIDR_EL2, but otherwise be functional. Signed-off-by: Marc Zyngier <maz@kernel.org> --- arch/arm64/include/asm/virt.h | 18 +++++++++++++----- arch/arm64/kvm/va_layout.c | 9 +++++++++ 2 files changed, 22 insertions(+), 5 deletions(-)
diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
index 7379f35ae2c6..69bc4e26aa26 100644
--- a/arch/arm64/include/asm/virt.h
+++ b/arch/arm64/include/asm/virt.h@@ -72,6 +72,11 @@ void __hyp_reset_vectors(void); DECLARE_STATIC_KEY_FALSE(kvm_protected_mode_initialized); +static inline bool is_kernel_in_hyp_mode(void) +{ + return read_sysreg(CurrentEL) == CurrentEL_EL2; +} + /* Reports the availability of HYP mode */ static inline bool is_hyp_mode_available(void) {
@@ -83,6 +88,10 @@ static inline bool is_hyp_mode_available(void) static_branch_likely(&kvm_protected_mode_initialized)) return true; + /* Catch braindead CPUs */ + if (!IS_ENABLED(CONFIG_ARM64_VHE) && is_kernel_in_hyp_mode()) + return false; + return (__boot_cpu_mode[0] == BOOT_CPU_MODE_EL2 && __boot_cpu_mode[1] == BOOT_CPU_MODE_EL2); }
@@ -98,12 +107,11 @@ static inline bool is_hyp_mode_mismatched(void) static_branch_likely(&kvm_protected_mode_initialized)) return false; - return __boot_cpu_mode[0] != __boot_cpu_mode[1]; -} + /* Catch braindead CPUs */ + if (!IS_ENABLED(CONFIG_ARM64_VHE) && is_kernel_in_hyp_mode()) + return true; -static inline bool is_kernel_in_hyp_mode(void) -{ - return read_sysreg(CurrentEL) == CurrentEL_EL2; + return __boot_cpu_mode[0] != __boot_cpu_mode[1]; } static __always_inline bool has_vhe(void)
diff --git a/arch/arm64/kvm/va_layout.c b/arch/arm64/kvm/va_layout.c
index 978301392d67..edb048654e00 100644
--- a/arch/arm64/kvm/va_layout.c
+++ b/arch/arm64/kvm/va_layout.c@@ -156,6 +156,9 @@ void __init kvm_update_va_mask(struct alt_instr *alt, { int i; + if (!is_hyp_mode_available()) + return; + BUG_ON(nr_inst != 5); for (i = 0; i < nr_inst; i++) {
@@ -191,6 +194,9 @@ void kvm_patch_vector_branch(struct alt_instr *alt, u64 addr; u32 insn; + if (!is_hyp_mode_available()) + return; + BUG_ON(nr_inst != 4); if (!cpus_have_const_cap(ARM64_SPECTRE_V3A) || WARN_ON_ONCE(has_vhe()))
@@ -244,6 +250,9 @@ static void generate_mov_q(u64 val, __le32 *origptr, __le32 *updptr, int nr_inst { u32 insn, oinsn, rd; + if (!is_hyp_mode_available()) + return; + BUG_ON(nr_inst != 4); /* Compute target register */
--
2.29.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel