KVM: arm64: Generate final CTR_EL0 value when running in Protected mode
authorMarc Zyngier <maz@kernel.org>
Mon, 22 Mar 2021 12:09:51 +0000 (12:09 +0000)
committerMarc Zyngier <maz@kernel.org>
Thu, 25 Mar 2021 11:00:33 +0000 (11:00 +0000)
In protected mode, late CPUs are not allowed to boot (enforced by
the PSCI relay). We can thus specialise the read_ctr macro to
always return a pre-computed, sanitised value. Special care is
taken to prevent the use of this custome version outside of
the protected mode.

Reviewed-by: Quentin Perret <qperret@google.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/include/asm/assembler.h
arch/arm64/kernel/image-vars.h
arch/arm64/kvm/va_layout.c

index fb651c1..34ddd8a 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm-generic/export.h>
 
 #include <asm/asm-offsets.h>
+#include <asm/asm-bug.h>
 #include <asm/cpufeature.h>
 #include <asm/cputype.h>
 #include <asm/debug-monitors.h>
@@ -270,12 +271,24 @@ alternative_endif
  * provide the system wide safe value from arm64_ftr_reg_ctrel0.sys_val
  */
        .macro  read_ctr, reg
+#ifndef __KVM_NVHE_HYPERVISOR__
 alternative_if_not ARM64_MISMATCHED_CACHE_TYPE
        mrs     \reg, ctr_el0                   // read CTR
        nop
 alternative_else
        ldr_l   \reg, arm64_ftr_reg_ctrel0 + ARM64_FTR_SYSVAL
 alternative_endif
+#else
+alternative_if_not ARM64_KVM_PROTECTED_MODE
+       ASM_BUG()
+alternative_else_nop_endif
+alternative_cb kvm_compute_final_ctr_el0
+       movz    \reg, #0
+       movk    \reg, #0, lsl #16
+       movk    \reg, #0, lsl #32
+       movk    \reg, #0, lsl #48
+alternative_cb_end
+#endif
        .endm
 
 
index d5dc2b7..fdd60cd 100644 (file)
@@ -65,6 +65,7 @@ __efistub__ctype              = _ctype;
 KVM_NVHE_ALIAS(kvm_patch_vector_branch);
 KVM_NVHE_ALIAS(kvm_update_va_mask);
 KVM_NVHE_ALIAS(kvm_get_kimage_voffset);
+KVM_NVHE_ALIAS(kvm_compute_final_ctr_el0);
 
 /* Global kernel state accessed by nVHE hyp code. */
 KVM_NVHE_ALIAS(kvm_vgic_global_state);
index 9783013..acdb7b3 100644 (file)
@@ -288,3 +288,10 @@ void kvm_get_kimage_voffset(struct alt_instr *alt,
 {
        generate_mov_q(kimage_voffset, origptr, updptr, nr_inst);
 }
+
+void kvm_compute_final_ctr_el0(struct alt_instr *alt,
+                              __le32 *origptr, __le32 *updptr, int nr_inst)
+{
+       generate_mov_q(read_sanitised_ftr_reg(SYS_CTR_EL0),
+                      origptr, updptr, nr_inst);
+}