Add read/write sysreg variants for capability registers. For the time being unless provided, a valid capability is being created through CVTP instructions which should be replaced by proper setup in a long run.
Signed-off-by: Beata Michalska beata.michalska@arm.com --- arch/arm64/include/asm/kvm_hyp.h | 74 +++++++++++++++++++++++++------- 1 file changed, 58 insertions(+), 16 deletions(-)
diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h index 145ce73fc16c..7631921f7574 100644 --- a/arch/arm64/include/asm/kvm_hyp.h +++ b/arch/arm64/include/asm/kvm_hyp.h @@ -24,12 +24,16 @@ DECLARE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params);
#if defined(__KVM_VHE_HYPERVISOR__)
-#define read_sysreg_el0(r) read_sysreg_s(r##_EL02) -#define write_sysreg_el0(v,r) write_sysreg_s(v, r##_EL02) -#define read_sysreg_el1(r) read_sysreg_s(r##_EL12) -#define write_sysreg_el1(v,r) write_sysreg_s(v, r##_EL12) -#define read_sysreg_el2(r) read_sysreg_s(r##_EL1) -#define write_sysreg_el2(v,r) write_sysreg_s(v, r##_EL1) +#define read_sysreg_el0(r) read_sysreg_s(r##_EL02) +#define write_sysreg_el0(v,r) write_sysreg_s(v, r##_EL02) +#define read_sysreg_el1(r) read_sysreg_s(r##_EL12) +#define read_cap_sysreg_el1(r) read_cap_sysreg_s(r##_EL12) +#define write_sysreg_el1(v,r) write_sysreg_s(v, r##_EL12) +#define write_cap_sysreg_el1(v,r) write_cap_sysreg_s(v, r##_EL12) +#define read_sysreg_el2(r) read_sysreg_s(r##_EL1) +#define read_cap_sysreg_el2(r) read_cap_sysreg_s(r##_EL1) +#define write_sysreg_el2(v,r) write_sysreg_s(v, r##_EL1) +#define write_cap_sysreg_el2(v,r) write_cap_sysreg_s(v, r##_EL1)
#else // !__KVM_VHE_HYPERVISOR__
@@ -49,21 +53,59 @@ DECLARE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params); reg; \ })
+#ifdef CONFIG_ARM64_MORELLO +#define read_cap_sysreg_elx(r,nvh,vh) \ + ({ \ + uintcap_t reg; \ + asm volatile(ALTERNATIVE(__mrs_s_c("%0", r##nvh), \ + __mrs_s_c("%0", r##vh), \ + VHE_ALT_KEY) \ + : "=r" (reg)); \ + reg; \ + }) +#else +#define read_cap_sysreg_elx read_sysreg_elx +#endif + +#define __write_sysreg_elx(v,r,inst,nvh,vh) \ +({ \ + asm volatile(ALTERNATIVE(inst(r##nvh, "%x0"), \ + inst(r##vh, "%x0"), \ + VHE_ALT_KEY) \ + : : "rZ" (v)); \ +}) + #define write_sysreg_elx(v,r,nvh,vh) \ do { \ u64 __val = (u64)(v); \ - asm volatile(ALTERNATIVE(__msr_s(r##nvh, "%x0"), \ - __msr_s(r##vh, "%x0"), \ - VHE_ALT_KEY) \ - : : "rZ" (__val)); \ + __write_sysreg_elx(__val, r, __msr_s, nvh, vh); \ } while (0)
-#define read_sysreg_el0(r) read_sysreg_elx(r, _EL0, _EL02) -#define write_sysreg_el0(v,r) write_sysreg_elx(v, r, _EL0, _EL02) -#define read_sysreg_el1(r) read_sysreg_elx(r, _EL1, _EL12) -#define write_sysreg_el1(v,r) write_sysreg_elx(v, r, _EL1, _EL12) -#define read_sysreg_el2(r) read_sysreg_elx(r, _EL2, _EL1) -#define write_sysreg_el2(v,r) write_sysreg_elx(v, r, _EL2, _EL1) +#ifdef CONFIG_ARM64_MORELLO +#define write_cap_sysreg_elx(v,r,nvh,vh) \ + do { \ + uintcap_t __cval; \ + __cval = __builtin_choose_expr( \ + __builtin_types_compatible_p(typeof(v), \ + uintcap_t),\ + (uintcap_t)(v), \ + __convert_to_cap(v)); \ + __write_sysreg_elx(__cval, r, __msr_s_c, nvh, vh); \ + } while (0) +#else +#define write_cap_sysreg_elx write_sysreg_elx +#endif + +#define read_sysreg_el0(r) read_sysreg_elx(r, _EL0, _EL02) +#define write_sysreg_el0(v,r) write_sysreg_elx(v, r, _EL0, _EL02) +#define read_sysreg_el1(r) read_sysreg_elx(r, _EL1, _EL12) +#define read_cap_sysreg_el1(r) read_cap_sysreg_elx(r, _EL1, _EL12) +#define write_sysreg_el1(v,r) write_sysreg_elx(v, r, _EL1, _EL12) +#define write_cap_sysreg_el1(v,r) write_cap_sysreg_elx(v, r, _EL1, _EL12) +#define read_sysreg_el2(r) read_sysreg_elx(r, _EL2, _EL1) +#define read_cap_sysreg_el2(r) read_cap_sysreg_elx(r, _EL2, _EL1) +#define write_sysreg_el2(v,r) write_sysreg_elx(v, r, _EL2, _EL1) +#define write_cap_sysreg_el2(v,r) write_cap_sysreg_elx(v, r, _EL2, _EL1)
#endif // __KVM_VHE_HYPERVISOR__