On 2022/4/19 19:22, Mark Brown wrote:
diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c index c938603b3ba0..92c69e5ac269 100644 --- a/arch/arm64/kernel/syscall.c +++ b/arch/arm64/kernel/syscall.c @@ -158,11 +158,36 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr, syscall_trace_exit(regs); } -static inline void sve_user_discard(void) +/*
- As per the ABI exit SME streaming mode and clear the SVE state not
- shared with FPSIMD on syscall entry.
- */
+static inline void fp_user_discard(void) {
- /*
* If SME is active then exit streaming mode. If ZA is active
* then flush the SVE registers but leave userspace access to
* both SVE and SME enabled, otherwise disable SME for the
* task and fall through to disabling SVE too. This means
It looks a bit confusing to me that in the current implementation, if ZA is *not* active, we don't actually go to disable SME for the task (which IMHO can be disabled as user-space is not actively using it now).
* that after a syscall we never have any streaming mode
* register state to track, if this changes the KVM code will
* need updating.
*/
- if (system_supports_sme() && test_thread_flag(TIF_SME)) {
u64 svcr = read_sysreg_s(SYS_SVCR_EL0);
if (svcr & SYS_SVCR_EL0_SM_MASK)
sme_smstop_sm();
As per the SME syscall ABI
| On syscall PSTATE.SM will be cleared and the SVE registers will be | handled as per the standard SVE ABI.
and the SVE syscall ABI
| On syscall, V0..V31 are preserved (as without SVE). Thus, bits | [127:0] of Z0..Z31 are preserved. All other bits of Z0..Z31, and all | of P0..P15 and FFR become zero on return from a syscall.
Can we infer from the documentation that V0-V31 should be preserved on return from a syscall? But with sme_smstop_sm(), all implemented bits of Z0-Z31 are set to zero by hardware. Is this intentional?
Please fix me up if I've mis-read things here.
- }
- if (!system_supports_sve()) return;
- /*
* If SME is not active then disable SVE, the registers will
* be cleared when userspace next attempts to access them and
* we do not need to track the SVE register state until then.
clear_thread_flag(TIF_SVE);*/
/*
Thanks, Zenghui