diff mbox series

[RFC,v2,11/22] KVM: arm64: Make SMPRI_EL1 RES0 for SME guests

Message ID 20231222-kvm-arm64-sme-v2-11-da226cb180bb@kernel.org (mailing list archive)
State New
Headers show
Series KVM: arm64: Implement support for SME in non-protected guests | expand

Commit Message

Mark Brown Dec. 22, 2023, 4:21 p.m. UTC
SME priorities are entirely implementation defined and Linux currently has
no support for SME priorities so we do not expose them to SME capable
guests, reporting SMIDR_EL1.SMPS as 0. This means that on a host which
supports SME priorities we need to trap writes to SMPRI_EL1 and make the
whole register RES0. For a guest that does not support SME at all the
register should instead be undefined.

If the host does not support SME priorities we could disable the trap but
since there is no reason to access SMPRI_EL1 on a system that does not
support priorities it seems more trouble than it is worth to detect and
handle this eventuality, especially given the lack of SME priority support
in the host and potential user confusion that may result if we report that
the feature is detected but do not provide any interface for it.

With the current specification and host implementation we could disable
read traps for all guests since we initialise SMPRI_EL1.Priority to 0
but for robustness when we do start implementing host support for
priorities or if more fields are added just leave the traps enabled.

Once we have physical implementations that implement SME priorities and an
understanding of how their use impacts the system we can consider exposing
the feature to guests in some form but this will require substantial study.

Signed-off-by: Mark Brown <broonie@kernel.org>
---
 arch/arm64/kvm/hyp/include/hyp/switch.h |  5 +++++
 arch/arm64/kvm/sys_regs.c               | 14 +++++++++++++-
 2 files changed, 18 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index 72982e752972..0cf4770b9d70 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -93,6 +93,11 @@  static inline void __activate_traps_hfgxtr(struct kvm_vcpu *vcpu)
 	ctxt_sys_reg(hctxt, HFGWTR_EL2) = read_sysreg_s(SYS_HFGWTR_EL2);
 
 	if (cpus_have_final_cap(ARM64_SME)) {
+		/*
+		 * We hide priorities from guests so need to trap
+		 * access to SMPRI_EL1 in order to map it to RES0
+		 * even if the guest has SME.
+		 */
 		tmp = HFGxTR_EL2_nSMPRI_EL1_MASK;
 
 		if (!vcpu_has_sme(vcpu))
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index a33ad12dc3ab..b618bcab526e 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -351,6 +351,18 @@  static bool access_gic_sre(struct kvm_vcpu *vcpu,
 	return true;
 }
 
+static bool access_res0(struct kvm_vcpu *vcpu,
+			struct sys_reg_params *p,
+			const struct sys_reg_desc *r)
+{
+	if (p->is_write)
+		return ignore_write(vcpu, p);
+
+	p->regval = 0;
+
+	return true;
+}
+
 static bool trap_raz_wi(struct kvm_vcpu *vcpu,
 			struct sys_reg_params *p,
 			const struct sys_reg_desc *r)
@@ -2224,7 +2236,7 @@  static const struct sys_reg_desc sys_reg_descs[] = {
 
 	{ SYS_DESC(SYS_ZCR_EL1), NULL, reset_val, ZCR_EL1, 0, .visibility = sve_visibility },
 	{ SYS_DESC(SYS_TRFCR_EL1), undef_access },
-	{ SYS_DESC(SYS_SMPRI_EL1), undef_access },
+	{ SYS_DESC(SYS_SMPRI_EL1), .access = access_res0, .visibility = sme_visibility },
 	{ SYS_DESC(SYS_SMCR_EL1), NULL, reset_val, SMCR_EL1, 0, .visibility = sme_visibility },
 	{ SYS_DESC(SYS_TTBR0_EL1), access_vm_reg, reset_unknown, TTBR0_EL1 },
 	{ SYS_DESC(SYS_TTBR1_EL1), access_vm_reg, reset_unknown, TTBR1_EL1 },