arm64/sme: Initial support for the Scalable Matrix Extension
Subsystems (6)
v8 cover arm64/sme: Initial support for the Scalable Matrix Extension
This series provides initial support for the ARMv9 Scalable Matrix Extension (SME). SME takes the approach used for vectors in SVE and extends this to provide architectural support for matrix operations. A more detailed overview can be found in [1].
For the kernel SME can be thought of as a series of features which are intended to be used together by applications but operate mostly orthogonally:
- The ZA matrix register.
- Streaming mode, in which ZA can be accessed and a subset of SVE features are available.
- A second vector length, used for streaming mode SVE and ZA and controlled using a similar interface to that for SVE.
- TPIDR2, a new userspace controllable system register intended for use by the C library for storing context related to the ZA ABI.
A substantial part of the series is dedicated to refactoring the existing SVE support so that we don't need to duplicate code for handling vector lengths and the SVE registers, this involves creating an array of vector types and making the users take the vector type as a parameter. I'm not 100% happy with this but wasn't able to come up with anything better, duplicating code definitely felt like a bad idea so this felt like the least bad thing. If this approach makes sense to people it might make sense to split this off into a separate series and/or merge it while the rest is pending review to try to make things a little more digestable, the series is very large so it'd probably make things easier to digest if some of the preparatory refactoring could be merged before the rest is ready.
One feature of the architecture of particular note is that switching to and from streaming mode may change the size of and invalidate the contents of the SVE registers, and when in streaming mode the FFR is not accessible. This complicates aspects of the ABI like signal handling and ptrace.
This initial implementation is mainly intended to get the ABI in place, there are several areas which will be worked on going forwards - some of these will be blockers, others could be handled in followup serieses:
- SME is currently not supported for KVM guests, this will be done as a followup series. A host system can use SME and run KVM guests but SME is not available in the guests.
- The KVM host support is done in a very simplistic way, were anyone to attempt to use it in production there would be performance impacts on hosts with SME support. As part of this we also add enumeration of fine grained traps.
- There is not currently ptrace or signal support TPIDR2, this will be done as a followup series.
- No support is currently provided for scheduler control of SME or SME applications, given the size of the SME register state the context switch overhead may be noticable so this may be needed especially for real time applications. Similar concerns already exist for larger SVE vector lengths but are amplified for SME, particularly as the vector length increases.
- There has been no work on optimising the performance of anything the kernel does.
It is not expected that any systems will be encountered that support SME but not SVE, SME is an ARMv9 feature and SVE is mandatory for ARMv9. The code attempts to handle any such systems that are encountered but this hasn't been tested extensively.
v8:
- Rebase onto v5.17-rc1.
- Support interoperation with KVM, SME is disabled for KVM guests with minimal handling for cleaning up SME state when entering and leaving the guest.
- Document and implement that signal handlers are invoked with ZA and streaming mode disabled.
- Use the RDSVL instruction introduced in EAC2 of the architecture to obtain the streaming mode vector length during enumeration, ZA state loading/saving and in test programs.
- Store a pointer to SVCR in fpsimd_last_state and use it in fpsimd_save() for interoperation with KVM.
- Add a test case sme_trap_no_sm checking that we generate a SIGILL when using an instruction that requires streaming mode without enabling it.
- Add basic ZA context form validation to testcases helper library.
- Move signal tests over to validating streaming VL from ZA information.
- Pulled in patch removing ARRAY_SIZE() so that kselftest builds cleanly and to avoid trivial conflicts.
v7:
- Rebase onto v5.16-rc3.
- Reduce indentation when supporting custom triggers for signal tests as suggested by Catalin.
- Change to specifying a width for all CPU features rather than adding single bit specific infrastructure.
- Don't require zeroing of non-shared SVE state during syscalls.
v6:
- Rebase onto v5.16-rc1.
- Return to disabling TIF_SVE on kernel entry even if we have SME state, this avoids the need for KVM to handle the case where TIF_SVE is set on guest entry.
- Add syscall-abi.h to SME updates to syscall-abi, mistakenly omitted from commit.
v5:
- Rebase onto currently merged SVE and kselftest patches.
- Add support for the FA64 option, introduced in the recently published EAC1 update to the specification.
- Pull in test program for the syscall ABI previously sent separately with some revisions and add coverage for the SME ABI.
- Fix checking for options with 1 bit fields in ID_AA64SMFR0_EL1.
- Minor fixes and clarifications to the ABI documentation.
v4:
- Rebase onto merged patches.
- Remove an uneeded NULL check in vec_proc_do_default_vl().
- Include patch to factor out utility routines in kselftests written in assembler.
- Specify -ffreestanding when building TPIDR2 test.
v3:
- Skip FFR rather than predicate registers in sve_flush_live().
- Don't assume a bool is all zeros in sve_flush_live() as per AAPCS.
- Don't redundantly specify a zero index when clearing FFR.
v2:
- Fix several issues with !SME and !SVE configurations.
- Preserve TPIDR2 when creating a new thread/process unless CLONE_SETTLS is set.
- Report traps due to using features in an invalid mode as SIGILL.
- Spell out streaming mode behaviour in SVE ABI documentation more directly.
- Document TPIDR2 in the ABI document.
- Use SMSTART and SMSTOP rather than read/modify/write sequences.
- Rework logic for exiting streaming mode on syscall.
- Don't needlessly initialise SVCR on access trap.
- Always restore SME VL for userspace if SME traps are disabled.
- Only yield to encourage preemption every 128 iterations in za-test, otherwise do a getpid(), and validate SVCR after syscall.
- Leave streaming mode disabled except when reading the vector length in za-test, and disable ZA after detecting a mismatch.
- Add SME support to vlset.
- Clarifications and typo fixes in comments.
- Move sme_alloc() forward declaration back a patch.
Mark Brown (38):
arm64: cpufeature: Always specify and use a field width for
capabilities
arm64: Add feature detection for fine grained traps kselftest/arm64: Remove local ARRAY_SIZE() definitions arm64/sme: Provide ABI documentation for SME
arm64/sme: System register and exception syndrome definitions arm64/sme: Manually encode SME instructions
arm64/sme: Early CPU setup for SME
arm64/sme: Basic enumeration support
arm64/sme: Identify supported SME vector lengths at boot arm64/sme: Implement sysctl to set the default vector length arm64/sme: Implement vector length configuration prctl()s arm64/sme: Implement support for TPIDR2
arm64/sme: Implement SVCR context switching
arm64/sme: Implement streaming SVE context switching arm64/sme: Implement ZA context switching
arm64/sme: Implement traps and syscall handling for SME arm64/sme: Disable ZA and streaming mode when handling signals arm64/sme: Implement streaming SVE signal handling arm64/sme: Implement ZA signal handling
arm64/sme: Implement ptrace support for streaming mode SVE registers arm64/sme: Add ptrace support for ZA
arm64/sme: Disable streaming mode and ZA when flushing CPU state arm64/sme: Save and restore streaming mode over EFI runtime calls
KVM: arm64: Hide SME system registers from guests
KVM: arm64: Trap SME usage in guest
KVM: arm64: Handle SME host state when running guests arm64/sme: Provide Kconfig for SME
kselftest/arm64: sme: Add streaming SME support to vlset kselftest/arm64: Add tests for TPIDR2
kselftest/arm64: Extend vector configuration API tests to cover SME kselftest/arm64: sme: Provide streaming mode SVE stress test kselftest/arm64: signal: Allow tests to be incompatible with features kselftest/arm64: signal: Handle ZA signal context in core code kselftest/arm64: Add stress test for SME ZA context switching kselftest/arm64: signal: Add SME signal handling tests kselftest/arm64: Add streaming SVE to SVE ptrace tests kselftest/arm64: Add coverage for the ZA ptrace interface kselftest/arm64: Add SME support to syscall ABI test
Documentation/arm64/elf_hwcaps.rst | 33 + Documentation/arm64/index.rst | 1 + Documentation/arm64/sme.rst | 432 +++++++++++++ Documentation/arm64/sve.rst | 70 ++- arch/arm64/Kconfig | 11 + arch/arm64/include/asm/cpu.h | 4 + arch/arm64/include/asm/cpufeature.h | 25 + arch/arm64/include/asm/el2_setup.h | 64 +- arch/arm64/include/asm/esr.h | 13 +- arch/arm64/include/asm/exception.h | 1 + arch/arm64/include/asm/fpsimd.h | 110 +++- arch/arm64/include/asm/fpsimdmacros.h | 86 +++ arch/arm64/include/asm/hwcap.h | 8 + arch/arm64/include/asm/kvm_arm.h | 1 + arch/arm64/include/asm/kvm_host.h | 4 + arch/arm64/include/asm/processor.h | 18 +- arch/arm64/include/asm/sysreg.h | 64 ++ arch/arm64/include/asm/thread_info.h | 2 + arch/arm64/include/uapi/asm/hwcap.h | 8 + arch/arm64/include/uapi/asm/ptrace.h | 69 ++- arch/arm64/include/uapi/asm/sigcontext.h | 55 +- arch/arm64/kernel/cpufeature.c | 284 +++++++-- arch/arm64/kernel/cpuinfo.c | 13 + arch/arm64/kernel/entry-common.c | 11 + arch/arm64/kernel/entry-fpsimd.S | 36 ++ arch/arm64/kernel/fpsimd.c | 585 ++++++++++++++++-- arch/arm64/kernel/process.c | 28 +- arch/arm64/kernel/ptrace.c | 356 +++++++++-- arch/arm64/kernel/signal.c | 194 +++++- arch/arm64/kernel/syscall.c | 34 +- arch/arm64/kernel/traps.c | 1 + arch/arm64/kvm/fpsimd.c | 45 +- arch/arm64/kvm/hyp/nvhe/switch.c | 30 + arch/arm64/kvm/hyp/vhe/switch.c | 10 +- arch/arm64/kvm/sys_regs.c | 9 +- arch/arm64/tools/cpucaps | 3 + include/uapi/linux/elf.h | 2 + include/uapi/linux/prctl.h | 9 + kernel/sys.c | 12 + tools/testing/selftests/arm64/abi/.gitignore | 1 + tools/testing/selftests/arm64/abi/Makefile | 9 +- .../selftests/arm64/abi/syscall-abi-asm.S | 69 ++- .../testing/selftests/arm64/abi/syscall-abi.c | 205 +++++- .../testing/selftests/arm64/abi/syscall-abi.h | 15 + tools/testing/selftests/arm64/abi/tpidr2.c | 298 +++++++++ tools/testing/selftests/arm64/fp/.gitignore | 4 + tools/testing/selftests/arm64/fp/Makefile | 12 +- tools/testing/selftests/arm64/fp/rdvl-sme.c | 14 + tools/testing/selftests/arm64/fp/rdvl.S | 8 + tools/testing/selftests/arm64/fp/rdvl.h | 1 + tools/testing/selftests/arm64/fp/ssve-stress | 59 ++ tools/testing/selftests/arm64/fp/sve-ptrace.c | 13 +- tools/testing/selftests/arm64/fp/sve-test.S | 30 + tools/testing/selftests/arm64/fp/vec-syscfg.c | 10 + tools/testing/selftests/arm64/fp/vlset.c | 10 +- tools/testing/selftests/arm64/fp/za-ptrace.c | 354 +++++++++++ tools/testing/selftests/arm64/fp/za-stress | 59 ++ tools/testing/selftests/arm64/fp/za-test.S | 426 +++++++++++++ .../testing/selftests/arm64/signal/.gitignore | 2 + .../selftests/arm64/signal/test_signals.h | 5 + .../arm64/signal/test_signals_utils.c | 40 +- .../arm64/signal/test_signals_utils.h | 2 + .../testcases/fake_sigreturn_sme_change_vl.c | 92 +++ .../arm64/signal/testcases/sme_trap_no_sm.c | 38 ++ .../signal/testcases/sme_trap_non_streaming.c | 45 ++ .../arm64/signal/testcases/sme_trap_za.c | 36 ++ .../selftests/arm64/signal/testcases/sme_vl.c | 68 ++ .../arm64/signal/testcases/ssve_regs.c | 129 ++++ .../arm64/signal/testcases/testcases.c | 36 ++ .../arm64/signal/testcases/testcases.h | 3 +- 70 files changed, 4590 insertions(+), 244 deletions(-) create mode 100644 Documentation/arm64/sme.rst create mode 100644 tools/testing/selftests/arm64/abi/syscall-abi.h create mode 100644 tools/testing/selftests/arm64/abi/tpidr2.c create mode 100644 tools/testing/selftests/arm64/fp/rdvl-sme.c create mode 100644 tools/testing/selftests/arm64/fp/ssve-stress create mode 100644 tools/testing/selftests/arm64/fp/za-ptrace.c create mode 100644 tools/testing/selftests/arm64/fp/za-stress create mode 100644 tools/testing/selftests/arm64/fp/za-test.S create mode 100644 tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sme_change_vl.c create mode 100644 tools/testing/selftests/arm64/signal/testcases/sme_trap_no_sm.c create mode 100644 tools/testing/selftests/arm64/signal/testcases/sme_trap_non_streaming.c create mode 100644 tools/testing/selftests/arm64/signal/testcases/sme_trap_za.c create mode 100644 tools/testing/selftests/arm64/signal/testcases/sme_vl.c create mode 100644 tools/testing/selftests/arm64/signal/testcases/ssve_regs.c
base-commit: e783362eb54cd99b2cac8b3a9aeac942e6f6ac07
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 1/38 arm64: cpufeature: Always specify and use a field width for capabilities
Since all the fields in the main ID registers are 4 bits wide we have up until now not bothered specifying the width in the code. Since we now wish to use this mechanism to enumerate features from the floating point feature registers which do not follow this pattern add a width to the table. This means updating all the existing table entries but makes it less likely that we run into issues in future due to implicitly assuming a 4 bit width.
--- arch/arm64/include/asm/cpufeature.h | 1 + arch/arm64/kernel/cpufeature.c | 167 +++++++++++++++++----------- 2 files changed, 102 insertions(+), 66 deletions(-)
arch/arm64/include/asm/cpufeature.h +1 -0
@@ -356,6 +356,7 @@ struct arm64_cpu_capabilities {struct {/* Feature register checking */ u32 sys_reg;u8 field_pos; +u8 field_width;u8 min_field_value;u8 hwcap_type;bool sign;
arch/arm64/kernel/cpufeature.c +101 -66
417 lines not on this page · raw message
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Suzuki K Poulose
reviewerRe: [PATCH v8 01/38] arm64: cpufeature: Always specify and use a field width for capabilities
Quoted 34 lines · Mark Brown
Since all the fields in the main ID registers are 4 bits wide we have up until now not bothered specifying the width in the code. Since we now wish to use this mechanism to enumerate features from the floating point feature registers which do not follow this pattern add a width to the table. This means updating all the existing table entries but makes it less likely that we run into issues in future due to implicitly assuming a 4 bit width.
Signed-off-by Mark Brown <[email protected]>Cc Suzuki K Poulose <[email protected]>--- arch/arm64/include/asm/cpufeature.h | 1 + arch/arm64/kernel/cpufeature.c | 167 +++++++++++++++++----------- 2 files changed, 102 insertions(+), 66 deletions(-)arch/arm64/include/asm/cpufeature.h +1
-0@@ -356,6 +356,7 @@ struct arm64_cpu_capabilities {struct {/* Feature register checking */ u32 sys_reg;u8 field_pos; +u8 field_width;u8 min_field_value;u8 hwcap_type;bool sign;arch/arm64/kernel/cpufeature.c +0
-0
arch/arm64/kernel/cpufeature.c u64 __read_sysreg_by_encoding(u32 sys_id) · line 1313
Quoted 8 lines
arch/arm64/kernel/cpufeature.c +3
-1@@ -1307,7 +1307,9 @@ u64 __read_sysreg_by_encoding(u32 sys_id)static bool feature_matches (u64 reg,const struct arm64_cpu_capabilities *entry) { -int val =cpuid_feature_extract_field (reg, entry->field_pos, entry->sign); +int val =cpuid_feature_extract_field_width (reg, entry->field_pos, + entry->field_width, + entry->sign);
Could we do something like :
+ int val = cpuid_feature_extract_field_width(reg, entry->field_pos,
entry->field_width ? : 4, .. );
and leave the existing structures as they are ?
arch/arm64/kernel/cpufeature.c static const struct arm64_cpu_capabilities arm64_features[] = {
Quoted 3 lines
arch/arm64/kernel/cpufeature.c +0
-0return val >= entry->min_field_value; }@@ -1952,6 +1954,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
There is arm64_errata[] array in cpu_errata.c. So, if we use the above proposal we could leave things unchanged for all existing uses.
Quoted 7 lines
arch/arm64/kernel/cpufeature.c +1
-0.matches = has_cpuid_feature, .sys_reg = SYS_ID_AA64MMFR0_EL1, .field_pos = ID_AA64MMFR0_ECV_SHIFT, + .field_width = 4, .sign = FTR_UNSIGNED, .min_field_value = 1, },
...
arch/arm64/kernel/cpufeature.c static const struct arm64_cpu_capabilities arm64_features[] = { · line 2412
Quoted 8 lines
arch/arm64/kernel/cpufeature.c +2
-1-#define HWCAP_CPUID_MATCH (reg, field, s, min_value) \ +#define HWCAP_CPUID_MATCH (reg, field, width, s, min_value) \ .matches = has_cpuid_feature, \ .sys_reg = reg, \ .field_pos = field, \ + .field_width = width, \ .sign = s, \ .min_field_value = min_value,
And that could avoid these changes too. We could add :
#define HWCAP_CPUID_MATCH_WIDTH(...)
when/if we need one, which sets the width.
Cheers
Suzuki
_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Re: [PATCH v8 01/38] arm64: cpufeature: Always specify and use a field width for capabilities
Quoted 8 lines · Suzuki K Poulose
arch/arm64/kernel/cpufeature.c u64 __read_sysreg_by_encoding(u32 sys_id) · line 1312
Quoted 3 lines · Mark Brown
arch/arm64/kernel/cpufeature.c +3
-0+int val =cpuid_feature_extract_field_width (reg, entry->field_pos, + entry->field_width, + entry->sign);Could we do something like :
Quoted 6 lines
+ int val = cpuid_feature_extract_field_width(reg,
entry->field_pos,entry->field_width ? : 4, .. );and leave the existing structures as they are ?
Obviously we *could* (ideally without the ternery operator) but having the implicit default like that makes me nervous that it's too easy to just forget to fill it in and get the wrong default.
Quoted 5 lines
And that could avoid these changes too. We could add :
#define
HWCAP_CPUID_MATCH_WIDTH(...)when/if we need one, which sets the width.
I'd originally had a completely separate set of definitions for single bit fields but Catlain wanted to get everything in one. I'm not sure I see a huge advantage in sharing the match function and not also sharing the macro TBH.
_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 2/38 arm64: Add feature detection for fine grained traps
In reply to Mark BrownSome of the traps for nVHE SME support are provided as fine grained traps so add detection of fine grained traps in order to allow us to guard usage.
--- arch/arm64/kernel/cpufeature.c | 11 +++++++++++ arch/arm64/tools/cpucaps | 1 + 2 files changed, 12 insertions(+)
arch/arm64/kernel/cpufeature.c +11 -0
@@ -2400,6 +2400,17 @@ static const struct arm64_cpu_capabilities arm64_features[] = { .matches = has_cpuid_feature, .min_field_value = 1, }, + { + .desc = "Fine Grained Traps", + .type = ARM64_CPUCAP_SYSTEM_FEATURE, + .capability = ARM64_HAS_FGT, + .sys_reg = SYS_ID_AA64MMFR0_EL1, + .sign = FTR_UNSIGNED, + .field_pos = ID_AA64MMFR0_FGT_SHIFT, + .field_width = 4, + .min_field_value = 1, + .matches = has_cpuid_feature, + }, {}, };
arch/arm64/tools/cpucaps +1 -0
@@ -20,6 +20,7 @@ HAS_DCPOP HAS_E0PD HAS_ECV HAS_EPAN +HAS_FGT HAS_GENERIC_AUTH HAS_GENERIC_AUTH_ARCH HAS_GENERIC_AUTH_IMP_DEF
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 3/38 kselftest/arm64: Remove local ARRAY_SIZE() definitions
In reply to Mark BrownAn ARRAY_SIZE() has been added to kselftest.h so remove the local versions in some of the arm64 selftests.
--- tools/testing/selftests/arm64/abi/syscall-abi.c | 1 - tools/testing/selftests/arm64/fp/sve-ptrace.c | 2 -- 2 files changed, 3 deletions(-)
tools/testing/selftests/arm64/abi/syscall-abi.c +0 -1
@@ -18,7 +18,6 @@#include "../../kselftest.h" -#define ARRAY_SIZE (a) (sizeof(a) / sizeof(a[0]))#define NUM_VL ((SVE_VQ_MAX - SVE_VQ_MIN) + 1)extern void do_syscall (int sve_vl);
tools/testing/selftests/arm64/fp/sve-ptrace.c +0 -2
@@ -21,8 +21,6 @@#include "../../kselftest.h" -#define ARRAY_SIZE (a) (sizeof(a) / sizeof(a[0])) -/* <linux/elf.h> and <sys/auxv.h> don't like each other, so: */ #ifndef NT_ARM_SVE #define NT_ARM_SVE 0x405
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 4/38 arm64/sme: Provide ABI documentation for SME
In reply to Mark BrownProvide ABI documentation for SME similar to that for SVE. Due to the very large overlap around streaming SVE mode in both implementation and interfaces documentation for streaming mode SVE is added to the SVE document rather than the SME one.
--- Documentation/arm64/index.rst | 1 + Documentation/arm64/sme.rst | 432 ++++++++++++++++++++++++++++++++++ Documentation/arm64/sve.rst | 70 +++++- 3 files changed, 493 insertions(+), 10 deletions(-) create mode 100644 Documentation/arm64/sme.rst
Documentation/arm64/index.rst +1 -0
@@ -21,6 +21,7 @@ ARM64 Architecture perf pointer-authentication silicon-errata + sme sve tagged-address-abi tagged-pointers
Documentation/arm64/sme.rst new file +432 -0
432 lines not on this page · raw message
Documentation/arm64/sve.rst +60 -10
139 lines not on this page · raw message
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 5/38 arm64/sme: System register and exception syndrome definitions
In reply to Mark BrownThe arm64 Scalable Matrix Extension (SME) adds some new system registers, fields in existing system registers and exception syndromes. This patch adds definitions for these for use in future patches implementing support for this extension.
Since SME will be the first user of FEAT_HCX in the kernel also include the definitions for enumerating it and the HCRX system register it adds.
--- arch/arm64/include/asm/esr.h | 12 +++++- arch/arm64/include/asm/kvm_arm.h | 1 + arch/arm64/include/asm/sysreg.h | 64 ++++++++++++++++++++++++++++++++ arch/arm64/kernel/traps.c | 1 + 4 files changed, 77 insertions(+), 1 deletion(-)
arch/arm64/include/asm/esr.h +11 -1
@@ -37,7 +37,8 @@#define ESR_ELx_EC_ERET (0x1a)/* EL2 only */ /* Unallocated EC: 0x1B */ #define ESR_ELx_EC_FPAC (0x1C)/* EL1 and above */ -/* Unallocated EC: 0x1D - 0x1E */ +#define ESR_ELx_EC_SME (0x1D) +/* Unallocated EC: 0x1E */ #define ESR_ELx_EC_IMP_DEF (0x1f)/* EL3 only */ #define ESR_ELx_EC_IABT_LOW (0x20)#define ESR_ELx_EC_IABT_CUR (0x21)
@@ -327,6 +328,15 @@#define ESR_ELx_CP15_32_ISS_SYS_CNTFRQ (ESR_ELx_CP15_32_ISS_SYS_VAL(0, 0, 14, 0) |\ ESR_ELx_CP15_32_ISS_DIR_READ) +/* +* ISS values for SME traps +*/ + +#define ESR_ELx_SME_ISS_SME_DISABLED 0 +#define ESR_ELx_SME_ISS_ILL 1 +#define ESR_ELx_SME_ISS_SM_DISABLED 2 +#define ESR_ELx_SME_ISS_ZA_DISABLED 3 +#ifndef __ASSEMBLY__#include <asm/types.h>
arch/arm64/include/asm/kvm_arm.h +1 -0
@@ -279,6 +279,7 @@#define CPTR_EL2_TCPAC (1U << 31)#define CPTR_EL2_TAM (1 << 30)#define CPTR_EL2_TTA (1 << 20) +#define CPTR_EL2_TSM (1 << 12)#define CPTR_EL2_TFP (1 << CPTR_EL2_TFP_SHIFT)#define CPTR_EL2_TZ (1 << 8)#define CPTR_NVHE_EL2_RES1 0x000032ff/* known RES1 bits in CPTR_EL2 (nVHE) */
arch/arm64/include/asm/sysreg.h +64 -0
162 lines not on this page · raw message
arch/arm64/kernel/traps.c +1 -0
@@ -822,6 +822,7 @@ static const char *esr_class_str[] = { [ESR_ELx_EC_SVE] = "SVE", [ESR_ELx_EC_ERET] = "ERET/ERETAA/ERETAB", [ESR_ELx_EC_FPAC] = "FPAC", + [ESR_ELx_EC_SME] = "SME", [ESR_ELx_EC_IMP_DEF] = "EL3 IMP DEF", [ESR_ELx_EC_IABT_LOW] = "IABT (lower EL)", [ESR_ELx_EC_IABT_CUR] = "IABT (current EL)",
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Marc Zyngier
maintainerRe: [PATCH v8 05/38] arm64/sme: System register and exception syndrome definitions
arch/arm64/include/asm/sysreg.h line 1276
Quoted 4 lines · Mark Brown
arch/arm64/include/asm/sysreg.h +3
-0+/* HFG[WR]TR_EL2 bit definitions */ +#define HFGxTR_EL2_nTPIDR_EL0_SHIFT 55 +#define HFGxTR_EL2_nTPIDR_EL0_MASK (1 << HFGxTR_EL2_nTPIDR_EL0_SHIFT)
This annoyingly clashes with bit 35 of the same registers, which maps to TPIDR_EL0. I have the feeling that this really should be TPIDR2_EL0.
M.
Signature · 5 lines
Without deviation from the norm, progress is not possible. _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Re: [PATCH v8 05/38] arm64/sme: System register and exception syndrome definitions
Quoted 9 lines · Marc Zyngier
arch/arm64/include/asm/sysreg.h line 1276
Quoted 3 lines · Mark Brown
arch/arm64/include/asm/sysreg.h +3
-0+/* HFG[WR]TR_EL2 bit definitions */ +#define HFGxTR_EL2_nTPIDR_EL0_SHIFT 55 +#define HFGxTR_EL2_nTPIDR_EL0_MASK (1 << HFGxTR_EL2_nTPIDR_EL0_SHIFT)This annoyingly clashes with bit 35 of the same registers, which maps to
TPIDR_EL0. I have the feeling that this really should beTPIDR2_EL0.
Yes, it should be.
_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 6/38 arm64/sme: Manually encode SME instructions
In reply to Mark BrownAs with SVE rather than impose ambitious toolchain requirements for SME we manually encode the few instructions which we require in order to perform the work the kernel needs to do. The instructions used to save and restore context are provided as assembler macros while those for entering and leaving streaming mode are done in asm volatile blocks since they are expected to be used from C.
We could do the SMSTART and SMSTOP operations with read/modify/write cycles on SVCR but using the aliases provided for individual field accesses should be slightly faster. These instructions are aliases for MSR but since our minimum toolchain requirements are old enough to mean that we can't use the sX_X_cX_cX_X form and they always use xzr rather than taking a value like write_sysreg_s() wants we just use .inst.
--- arch/arm64/include/asm/fpsimd.h | 25 +++++++++++++ arch/arm64/include/asm/fpsimdmacros.h | 53 +++++++++++++++++++++++++++ 2 files changed, 78 insertions(+)
arch/arm64/include/asm/fpsimd.h +25 -0
@@ -249,6 +249,31 @@ static inline void sve_setup(void) { }#endif /* ! CONFIG_ARM64_SVE */ +#ifdef CONFIG_ARM64_SME + +static inline void sme_smstart_sm (void ) +{ + asmvolatile (".inst 0xd503437f" ); +} + +static inline void sme_smstop_sm (void ) +{ + asmvolatile (".inst 0xd503427f" ); +} + +static inline void sme_smstop (void ) +{ + asmvolatile (".inst 0xd503467f" ); +} + +#else + +static inline void sme_smstart_sm (void ) { } +static inline void sme_smstop_sm (void ) { } +static inline void sme_smstop (void ) { } + +#endif /* ! CONFIG_ARM64_SME */ +/* For use by EFI runtime services calls only */ extern void __efi_fpsimd_begin (void );extern void __efi_fpsimd_end (void );
arch/arm64/include/asm/fpsimdmacros.h +53 -0
65 lines not on this page · raw message
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 7/38 arm64/sme: Early CPU setup for SME
In reply to Mark BrownSME requires similar setup to that for SVE: disable traps to EL2 and make sure that the maximum vector length is available to EL1, for SME we have two traps - one for SME itself and one for TPIDR2.
In addition since we currently make no active use of priority control for SCMUs we map all SME priorities lower ELs may configure to 0, the architecture specified minimum priority, to ensure that nothing we manage is able to configure itself to consume excessive resources. This will need to be revisited should there be a need to manage SME priorities at runtime.
--- arch/arm64/include/asm/el2_setup.h | 64 ++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 4 deletions(-)
arch/arm64/include/asm/el2_setup.h +60 -4
@@ -143,6 +143,50 @@ .Lskip_sve_\@: .endm +/* SME register access and priority mapping */ +.macro __init_el2_nvhe_sme + mrs x1, id_aa64pfr1_el1 + ubfx x1, x1, #ID_AA64PFR1_SME_SHIFT, #4 + cbz x1, .Lskip_sme_\@ + + bic x0, x0, #CPTR_EL2_TSM // Also disable SME traps + msr cptr_el2, x0 // Disable copro. traps to EL2 + isb + + mrs x1, sctlr_el2 + orr x1, x1, #SCTLR_ELx_ENTP2 // Disable TPIDR2 traps + msr sctlr_el2, x1 + isb + + mov x1, #0 // SMCR controls + + mrs_s x2, SYS_ID_AA64SMFR0_EL1 + ubfx x2, x2, #ID_AA64SMFR0_FA64_SHIFT, #1 // Full FP in SM? + cbz x2, .Lskip_sme_fa64_\@ + + orr x1, x1, SMCR_ELx_FA64_MASK +.Lskip_sme_fa64_\@: + + orr x1, x1, #SMCR_ELx_LEN_MASK // Enable full SME vector + msr_s SYS_SMCR_EL2, x1 // length for EL1. + + mrs_s x1, SYS_SMIDR_EL1 // Priority mapping supported? + ubfx x1, x1, #SYS_SMIDR_EL1_SMPS_SHIFT, #1 + cbz x1, .Lskip_sme_\@ + + msr_s SYS_SMPRIMAP_EL2, xzr // Make all priorities equal + + mrs x1, id_aa64mmfr1_el1 // HCRX_EL2 present? + ubfx x1, x1, #ID_AA64MMFR1_HCX_SHIFT, #4 + cbz x1, .Lskip_sme_\@ + + mrs_s x1, SYS_HCRX_EL2 + orr x1, x1, #HCRX_EL2_SMPME_MASK // Enable priority mapping + msr_s SYS_HCRX_EL2, x1 + +.Lskip_sme_\@: +.endm + /* Disable any fine grained traps */ .macro __init_el2_fgt mrs x1, id_aa64mmfr0_el1
@@ -153,15 +197,26 @@mrs x1, id_aa64dfr0_el1 ubfx x1, x1, #ID_AA64DFR0_PMSVER_SHIFT, #4 cmp x1, #3 - b.lt .Lset_fgt_\@ + b.lt .Lset_debug_fgt_\@/* Disable PMSNEVFR_EL1 read and write traps */ orr x0, x0, #(1 << 62) -.Lset_fgt_\@: +.Lset_debug_fgt_\@: msr_s SYS_HDFGRTR_EL2, x0 msr_s SYS_HDFGWTR_EL2, x0 - msr_s SYS_HFGRTR_EL2, xzr - msr_s SYS_HFGWTR_EL2, xzr + + mov x0, xzr + mrs x1, id_aa64pfr1_el1 + ubfx x1, x1, #ID_AA64PFR1_SME_SHIFT, #4 + cbz x1, .Lset_fgt_\@ + +/* Disable nVHE traps of TPIDR2 and SMPRI */ + orr x0, x0, #HFGxTR_EL2_nSMPRI_EL1_MASK + orr x0, x0, #HFGxTR_EL2_nTPIDR_EL0_MASK + +.Lset_fgt_\@: + msr_s SYS_HFGRTR_EL2, x0 + msr_s SYS_HFGWTR_EL2, x0 msr_s SYS_HFGITR_EL2, xzr mrs x1, id_aa64pfr0_el1 // AMU traps UNDEF without AMU
@@ -196,6 +251,7 @@__init_el2_nvhe_idregs __init_el2_nvhe_cptr__init_el2_nvhe_sve + __init_el2_nvhe_sme__init_el2_fgt __init_el2_nvhe_prepare_eret .endm
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 8/38 arm64/sme: Basic enumeration support
In reply to Mark BrownThis patch introduces basic cpufeature support for discovering the presence of the Scalable Matrix Extension and reporting hwcaps for the detected features.
--- Documentation/arm64/elf_hwcaps.rst | 33 +++++++++++++++++ arch/arm64/include/asm/cpu.h | 1 + arch/arm64/include/asm/cpufeature.h | 12 ++++++ arch/arm64/include/asm/fpsimd.h | 2 + arch/arm64/include/asm/hwcap.h | 8 ++++ arch/arm64/include/uapi/asm/hwcap.h | 8 ++++ arch/arm64/kernel/cpufeature.c | 57 +++++++++++++++++++++++++++++ arch/arm64/kernel/cpuinfo.c | 9 +++++ arch/arm64/kernel/fpsimd.c | 30 +++++++++++++++ arch/arm64/tools/cpucaps | 2 + 10 files changed, 162 insertions(+)
Documentation/arm64/elf_hwcaps.rst +33 -0
@@ -259,6 +259,39 @@ HWCAP2_RPRES Functionality implied by ID_AA64ISAR2_EL1.RPRES == 0b0001. +HWCAP2_SME + + Functionality implied by ID_AA64PFR1_EL1.SME == 0b0001, as described + by Documentation/arm64/sme.rst. + +HWCAP2_SME_I16I64 + + Functionality implied by ID_AA64SMFR0_EL1.I16I64 == 0b1111. + +HWCAP2_SME_F64F64 + + Functionality implied by ID_AA64SMFR0_EL1.F64F64 == 0b1. + +HWCAP2_SME_I8I32 + + Functionality implied by ID_AA64SMFR0_EL1.I8I32 == 0b1111. + +HWCAP2_SME_F16F32 + + Functionality implied by ID_AA64SMFR0_EL1.F16F32 == 0b1. + +HWCAP2_SME_B16F32 + + Functionality implied by ID_AA64SMFR0_EL1.B16F32 == 0b1. + +HWCAP2_SME_F32F32 + + Functionality implied by ID_AA64SMFR0_EL1.F32F32 == 0b1. + +HWCAP2_SME_FA64 + + Functionality implied by ID_AA64SMFR0_EL1.FA64 == 0b1. + 4. Unused AT_HWCAP bits -----------------------
arch/arm64/include/asm/cpu.h +1 -0
@@ -58,6 +58,7 @@ struct cpuinfo_arm64 {u64 reg_id_aa64pfr0;u64 reg_id_aa64pfr1;u64 reg_id_aa64zfr0; +u64 reg_id_aa64smfr0;struct cpuinfo_32bit aarch32;
arch/arm64/include/asm/cpufeature.h +12 -0
@@ -728,6 +728,18 @@ static __always_inline bool system_supports_sve(void)cpus_have_const_cap (ARM64_SVE ); } +static __always_inline bool system_supports_sme(void) +{ +return IS_ENABLED (CONFIG_ARM64_SME ) && +cpus_have_const_cap (ARM64_SME ); +} + +static __always_inline bool system_supports_fa64(void) +{ +return IS_ENABLED (CONFIG_ARM64_SME ) && +cpus_have_const_cap (ARM64_SME_FA64 ); +} + static __always_inline bool system_supports_cnp(void) { return IS_ENABLED(CONFIG_ARM64_CNP) &&
arch/arm64/include/asm/fpsimd.h +2 -0
@@ -74,6 +74,8 @@ extern void sve_set_vq(unsigned long vq_minus_1);struct arm64_cpu_capabilities ;extern void sve_kernel_enable (const struct arm64_cpu_capabilities *__unused); +extern void sme_kernel_enable (const struct arm64_cpu_capabilities *__unused); +extern void fa64_kernel_enable (const struct arm64_cpu_capabilities *__unused);extern u64 read_zcr_features (void );
arch/arm64/include/asm/hwcap.h +8 -0
@@ -108,6 +108,14 @@#define KERNEL_HWCAP_ECV __khwcap2_feature(ECV)#define KERNEL_HWCAP_AFP __khwcap2_feature(AFP)#define KERNEL_HWCAP_RPRES __khwcap2_feature(RPRES) +#define KERNEL_HWCAP_SME __khwcap2_feature(SME) +#define KERNEL_HWCAP_SME_I16I64 __khwcap2_feature(SME_I16I64) +#define KERNEL_HWCAP_SME_F64F64 __khwcap2_feature(SME_F64F64) +#define KERNEL_HWCAP_SME_I8I32 __khwcap2_feature(SME_I8I32) +#define KERNEL_HWCAP_SME_F16F32 __khwcap2_feature(SME_F16F32) +#define KERNEL_HWCAP_SME_B16F32 __khwcap2_feature(SME_B16F32) +#define KERNEL_HWCAP_SME_F32F32 __khwcap2_feature(SME_F32F32) +#define KERNEL_HWCAP_SME_FA64 __khwcap2_feature(SME_FA64)/* * This yields a mask that user programs can use to figure out what
arch/arm64/include/uapi/asm/hwcap.h +8 -0
@@ -78,5 +78,13 @@#define HWCAP2_ECV (1 << 19)#define HWCAP2_AFP (1 << 20)#define HWCAP2_RPRES (1 << 21) +#define HWCAP2_SME (1 << 22) +#define HWCAP2_SME_I16I64 (1 << 23) +#define HWCAP2_SME_F64F64 (1 << 24) +#define HWCAP2_SME_I8I32 (1 << 25) +#define HWCAP2_SME_F16F32 (1 << 26) +#define HWCAP2_SME_B16F32 (1 << 27) +#define HWCAP2_SME_F32F32 (1 << 28) +#define HWCAP2_SME_FA64 (1 << 29)#endif /* _UAPI__ASM_HWCAP_H */
arch/arm64/kernel/cpufeature.c +57 -0
93 lines not on this page · raw message
arch/arm64/kernel/cpuinfo.c +9 -0
@@ -97,6 +97,14 @@ static const char *const hwcap_str[] = { [KERNEL_HWCAP_ECV] = "ecv", [KERNEL_HWCAP_AFP] = "afp", [KERNEL_HWCAP_RPRES] = "rpres", + [KERNEL_HWCAP_SME] = "sme", + [KERNEL_HWCAP_SME_I16I64] = "smei16i64", + [KERNEL_HWCAP_SME_F64F64] = "smef64f64", + [KERNEL_HWCAP_SME_I8I32] = "smei8i32", + [KERNEL_HWCAP_SME_F16F32] = "smef16f32", + [KERNEL_HWCAP_SME_B16F32] = "smeb16f32", + [KERNEL_HWCAP_SME_F32F32] = "smef32f32", + [KERNEL_HWCAP_SME_FA64] = "smefa64", };#ifdef CONFIG_COMPAT
@@ -400,6 +408,7 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info) info->reg_id_aa64pfr0 =read_cpuid (ID_AA64PFR0_EL1 ); info->reg_id_aa64pfr1 =read_cpuid (ID_AA64PFR1_EL1 ); info->reg_id_aa64zfr0 =read_cpuid (ID_AA64ZFR0_EL1 ); + info->reg_id_aa64smfr0 =read_cpuid (ID_AA64SMFR0_EL1 );if (id_aa64pfr1_mte (info->reg_id_aa64pfr1)) info->reg_gmid =read_cpuid (GMID_EL1 );
arch/arm64/kernel/fpsimd.c +30 -0
@@ -987,6 +987,32 @@ void fpsimd_release_task(struct task_struct *dead_task)#endif /* CONFIG_ARM64_SVE */ +#ifdef CONFIG_ARM64_SME + +void sme_kernel_enable (const struct arm64_cpu_capabilities *__always_unused p) +{ +/* Set priority for all PEs to architecturally defined minimum */ +write_sysreg_s (read_sysreg_s (SYS_SMPRI_EL1 ) & ~SMPRI_EL1_PRIORITY_MASK , +SYS_SMPRI_EL1 ); + +/* Allow SME in kernel */ +write_sysreg (read_sysreg (CPACR_EL1 ) |CPACR_EL1_SMEN_EL1EN ,CPACR_EL1 ); +isb (); +} + +/* +* This must be called after sme_kernel_enable(), we rely on the +* feature table being sorted to ensure this. +*/ +void fa64_kernel_enable (const struct arm64_cpu_capabilities *__always_unused p) +{ +/* Allow use of FA64 */ +write_sysreg_s (read_sysreg_s (SYS_SMCR_EL1 ) | SMCR_ELx_FA64_MASK, +SYS_SMCR_EL1 ); +} + +#endif /* CONFIG_ARM64_SVE */ +/* * Trapped SVE access *
@@ -1532,6 +1558,10 @@ static int __init fpsimd_init(void)if (!cpu_have_named_feature (ASIMD ))pr_notice ("Advanced SIMD is not implemented\n" ); + +if (cpu_have_named_feature (SME ) && !cpu_have_named_feature (SVE )) +pr_notice ("SME is implemented but not SVE\n" ); +return sve_sysctl_init (); }core_initcall (fpsimd_init);
arch/arm64/tools/cpucaps +2 -0
@@ -42,6 +42,8 @@ KVM_PROTECTED_MODE MISMATCHED_CACHE_TYPE MTE MTE_ASYMM +SME +SME_FA64 SPECTRE_V2 SPECTRE_V3A SPECTRE_V4
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 9/38 arm64/sme: Identify supported SME vector lengths at boot
In reply to Mark BrownThe vector lengths used for SME are controlled through a similar set of registers to those for SVE and enumerated using a similar algorithm with some slight differences due to the fact that unlike SVE there are no restrictions on which combinations of vector lengths can be supported nor any mandatory vector lengths which must be implemented. Add a new vector type and implement support for enumerating it.
One slightly awkward feature is that we need to read the current vector length using a different instruction (or enter streaming mode which would have the same issue and be higher cost). Rather than add an ops structure we add special cases directly in the otherwise generic vec_probe_vqs() function, this is a bit inelegant but it's the only place where this is an issue.
--- arch/arm64/include/asm/cpu.h | 3 + arch/arm64/include/asm/cpufeature.h | 7 ++ arch/arm64/include/asm/fpsimd.h | 26 ++++++ arch/arm64/include/asm/processor.h | 1 + arch/arm64/kernel/cpufeature.c | 49 +++++++++++ arch/arm64/kernel/cpuinfo.c | 4 + arch/arm64/kernel/entry-fpsimd.S | 9 ++ arch/arm64/kernel/fpsimd.c | 123 +++++++++++++++++++++++++++- 8 files changed, 220 insertions(+), 2 deletions(-)
arch/arm64/include/asm/cpu.h +3 -0
@@ -64,6 +64,9 @@ struct cpuinfo_arm64 {/* pseudo-ZCR for recording maximum ZCR_EL1 LEN value: */ u64 reg_zcr; + +/* pseudo-SMCR for recording maximum ZCR_EL1 LEN value: */ +u64 reg_smcr; }; DECLARE_PER_CPU(struct cpuinfo_arm64, cpu_data);
arch/arm64/include/asm/cpufeature.h +7 -0
@@ -620,6 +620,13 @@ static inline bool id_aa64pfr0_sve(u64 pfr0)return val >0 ; } +static inline bool id_aa64pfr1_sme (u64 pfr1) +{ +u32 val =cpuid_feature_extract_unsigned_field (pfr1,ID_AA64PFR1_SME_SHIFT ); + +return val >0 ; +} +static inline bool id_aa64pfr1_mte (u64 pfr1) {u32 val =cpuid_feature_extract_unsigned_field (pfr1,ID_AA64PFR1_MTE_SHIFT );
arch/arm64/include/asm/fpsimd.h +26 -0
@@ -78,6 +78,7 @@ extern void sme_kernel_enable(const struct arm64_cpu_capabilities *__unused);extern void fa64_kernel_enable (const struct arm64_cpu_capabilities *__unused);extern u64 read_zcr_features (void ); +extern u64 read_smcr_features (void );/* * Helpers to translate bit indices in sve_vq_map to VQ values (and
@@ -172,6 +173,12 @@ static inline void write_vl(enum vec_type type, u64 val) tmp =read_sysreg_s (SYS_ZCR_EL1 ) & ~ZCR_ELx_LEN_MASK;write_sysreg_s (tmp | val,SYS_ZCR_EL1 );break ; +#endif +#ifdef CONFIG_ARM64_SME +case ARM64_VEC_SME : + tmp =read_sysreg_s (SYS_SMCR_EL1 ) & ~SMCR_ELx_LEN_MASK; +write_sysreg_s (tmp | val,SYS_SMCR_EL1 ); +break ;#endif default :WARN_ON_ONCE (1 );
@@ -268,12 +275,31 @@ static inline void sme_smstop(void) asmvolatile (".inst 0xd503467f" ); } +extern void __init sme_setup (void ); + +static inline int sme_max_vl (void ) +{ +return vec_max_vl (ARM64_VEC_SME ); +} + +static inline int sme_max_virtualisable_vl (void ) +{ +return vec_max_virtualisable_vl (ARM64_VEC_SME ); +} + +extern unsigned int sme_get_vl (void ); +#else static inline void sme_smstart_sm (void ) { }static inline void sme_smstop_sm (void ) { }static inline void sme_smstop (void ) { } +static inline void sme_setup (void ) { } +static inline unsigned int sme_get_vl (void ) {return 0 ; } +static inline int sme_max_vl (void ) {return 0 ; } +static inline int sme_max_virtualisable_vl (void ) {return 0 ; } +#endif /* ! CONFIG_ARM64_SME */ /* For use by EFI runtime services calls only */
arch/arm64/include/asm/processor.h +1 -0
@@ -117,6 +117,7 @@ struct debug_info {enum vec_type {ARM64_VEC_SVE =0 , +ARM64_VEC_SME ,ARM64_VEC_MAX , };
arch/arm64/kernel/cpufeature.c +49 -0
97 lines not on this page · raw message
arch/arm64/kernel/cpuinfo.c +4 -0
@@ -420,6 +420,10 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info) id_aa64pfr0_sve(info->reg_id_aa64pfr0)) info->reg_zcr = read_zcr_features(); +if (IS_ENABLED (CONFIG_ARM64_SME ) && +id_aa64pfr1_sme (info->reg_id_aa64pfr1)) + info->reg_smcr =read_smcr_features (); +cpuinfo_detect_icache_policy (info); }
arch/arm64/kernel/entry-fpsimd.S +9 -0
@@ -86,3 +86,12 @@ SYM_FUNC_START(sve_flush_live) SYM_FUNC_END(sve_flush_live) #endif /* CONFIG_ARM64_SVE */ + +#ifdef CONFIG_ARM64_SME + +SYM_FUNC_START(sme_get_vl) + _sme_rdsvl 0, 1 + ret +SYM_FUNC_END(sme_get_vl) + +#endif /* CONFIG_ARM64_SME */
arch/arm64/kernel/fpsimd.c +121 -2
153 lines not on this page · raw message
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 10/38 arm64/sme: Implement sysctl to set the default vector length
In reply to Mark BrownAs for SVE provide a sysctl which allows the default SME vector length to be configured.
--- arch/arm64/kernel/fpsimd.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-)
arch/arm64/kernel/fpsimd.c +28 -1
@@ -483,6 +483,30 @@ static int __init sve_sysctl_init(void)static int __init sve_sysctl_init (void ) {return 0 ; }#endif /* ! (CONFIG_ARM64_SVE && CONFIG_SYSCTL) */ +#if defined(CONFIG_ARM64_SME ) && defined(CONFIG_SYSCTL ) +static struct ctl_table sme_default_vl_table[] = { + { + .procname ="sme_default_vector_length" , + .mode =0644 , + .proc_handler = vec_proc_do_default_vl, + .extra1 = &vl_info[ARM64_VEC_SME ], + }, + { } +}; + +static int __init sme_sysctl_init (void ) +{ +if (system_supports_sme ()) +if (!register_sysctl ("abi" , sme_default_vl_table)) +return -EINVAL ; + +return 0 ; +} + +#else /* ! (CONFIG_ARM64_SME && CONFIG_SYSCTL) */ +static int __init sme_sysctl_init (void ) {return 0 ; } +#endif /* ! (CONFIG_ARM64_SME && CONFIG_SYSCTL) */ +#define ZREG (sve_state, vq, n) ((char *)(sve_state) + \ (SVE_SIG_ZREG_OFFSET(vq, n) - SVE_SIG_REGS_OFFSET))
@@ -1681,6 +1705,9 @@ static int __init fpsimd_init(void)if (cpu_have_named_feature (SME ) && !cpu_have_named_feature (SVE ))pr_notice ("SME is implemented but not SVE\n" ); -return sve_sysctl_init (); +sve_sysctl_init (); +sme_sysctl_init (); + +return 0 ; }core_initcall (fpsimd_init);
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 11/38 arm64/sme: Implement vector length configuration prctl()s
In reply to Mark BrownAs for SVE provide a prctl() interface which allows processes to configure their SME vector length.
--- arch/arm64/include/asm/fpsimd.h | 4 ++++ arch/arm64/include/asm/processor.h | 4 +++- arch/arm64/include/asm/thread_info.h | 1 + arch/arm64/kernel/fpsimd.c | 32 ++++++++++++++++++++++++++++ include/uapi/linux/prctl.h | 9 ++++++++ kernel/sys.c | 12 +++++++++++ 6 files changed, 61 insertions(+), 1 deletion(-)
arch/arm64/include/asm/fpsimd.h +4 -0
@@ -288,6 +288,8 @@ static inline int sme_max_virtualisable_vl(void) }extern unsigned int sme_get_vl (void ); +extern int sme_set_current_vl (unsigned long arg); +extern int sme_get_current_vl (void );#else
@@ -299,6 +301,8 @@ static inline void sme_setup(void) { }static inline unsigned int sme_get_vl (void ) {return 0 ; }static inline int sme_max_vl (void ) {return 0 ; }static inline int sme_max_virtualisable_vl (void ) {return 0 ; } +static inline int sme_set_current_vl (unsigned long arg) {return -EINVAL ; } +static inline int sme_get_current_vl (void ) {return -EINVAL ; }#endif /* ! CONFIG_ARM64_SME */
arch/arm64/include/asm/processor.h +3 -1
@@ -354,9 +354,11 @@ extern void __init minsigstksz_setup(void);*/ #include <asm/fpsimd.h> -/* Userspace interface for PR_SVE_{SET,GET}_VL prctl()s: */ +/* Userspace interface for PR_S[MV]E_{SET,GET}_VL prctl()s: */ #define SVE_SET_VL (arg) sve_set_current_vl(arg)#define SVE_GET_VL () sve_get_current_vl() +#define SME_SET_VL (arg) sme_set_current_vl(arg) +#define SME_GET_VL () sme_get_current_vl()/* PR_PAC_RESET_KEYS prctl */ #define PAC_RESET_KEYS (tsk, arg) ptrauth_prctl_reset_keys(tsk, arg)
arch/arm64/include/asm/thread_info.h +1 -0
@@ -82,6 +82,7 @@ int arch_dup_task_struct(struct task_struct *dst,#define TIF_SVE_VL_INHERIT 24/* Inherit SVE vl_onexec across exec */ #define TIF_SSBD 25/* Wants SSB mitigation */ #define TIF_TAGGED_ADDR 26/* Allow tagged user addresses */ +#define TIF_SME_VL_INHERIT 28/* Inherit SME vl_onexec across exec */ #define _TIF_SIGPENDING (1 << TIF_SIGPENDING)#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
arch/arm64/kernel/fpsimd.c +32 -0
@@ -149,6 +149,8 @@ static unsigned int vec_vl_inherit_flag(enum vec_type type)switch (type) {case ARM64_VEC_SVE :return TIF_SVE_VL_INHERIT ; +case ARM64_VEC_SME : +return TIF_SME_VL_INHERIT ;default :WARN_ON_ONCE (1 );return 0 ;
@@ -801,6 +803,36 @@ int sve_get_current_vl(void)return vec_prctl_status (ARM64_VEC_SVE ,0 ); } +#ifdef CONFIG_ARM64_SME +/* PR_SME_SET_VL */ +int sme_set_current_vl (unsigned long arg) +{ +unsigned long vl, flags; +int ret; + + vl = arg &PR_SME_VL_LEN_MASK ; + flags = arg & ~vl; + +if (!system_supports_sme () ||is_compat_task ()) +return -EINVAL ; + + ret =vec_set_vector_length (current,ARM64_VEC_SME , vl, flags); +if (ret) +return ret; + +return vec_prctl_status (ARM64_VEC_SME , flags); +} + +/* PR_SME_GET_VL */ +int sme_get_current_vl (void ) +{ +if (!system_supports_sme () ||is_compat_task ()) +return -EINVAL ; + +return vec_prctl_status (ARM64_VEC_SME ,0 ); +} +#endif /* CONFIG_ARM64_SME */ +static void vec_probe_vqs (struct vl_info *info,DECLARE_BITMAP (map ,SVE_VQ_MAX )) {
include/uapi/linux/prctl.h +9 -0
@@ -272,6 +272,15 @@ struct prctl_mm_map {# define PR_SCHED_CORE_SCOPE_THREAD_GROUP 1# define PR_SCHED_CORE_SCOPE_PROCESS_GROUP 2 +/* arm64 Scalable Matrix Extension controls */ +/* Flag values must be in sync with SVE versions */ +#define PR_SME_SET_VL 63/* set task vector length */ +# define PR_SME_SET_VL_ONEXEC (1 << 18)/* defer effect until exec */ +#define PR_SME_GET_VL 64/* get task vector length */ +/* Bits common to PR_SME_SET_VL and PR_SME_GET_VL */ +# define PR_SME_VL_LEN_MASK 0xffff +# define PR_SME_VL_INHERIT (1 << 17)/* inherit across exec */ +#define PR_SET_VMA 0x53564d41# define PR_SET_VMA_ANON_NAME 0
kernel/sys.c +12 -0
@@ -116,6 +116,12 @@#ifndef SVE_GET_VL # define SVE_GET_VL () (-EINVAL)#endif +#ifndef SME_SET_VL +# define SME_SET_VL (a) (-EINVAL) +#endif +#ifndef SME_GET_VL +# define SME_GET_VL () (-EINVAL) +#endif #ifndef PAC_RESET_KEYS # define PAC_RESET_KEYS (a, b) (-EINVAL)#endif
@@ -2523,6 +2529,12 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,case PR_SVE_GET_VL : error =SVE_GET_VL ();break ; +case PR_SME_SET_VL : + error =SME_SET_VL (arg2); +break ; +case PR_SME_GET_VL : + error =SME_GET_VL (); +break ;case PR_GET_SPECULATION_CTRL :if (arg3 || arg4 || arg5)return -EINVAL ;
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 12/38 arm64/sme: Implement support for TPIDR2
In reply to Mark BrownThe Scalable Matrix Extension introduces support for a new thread specific data register TPIDR2 intended for use by libc. The kernel must save the value of TPIDR2 on context switch and should ensure that all new threads start off with a default value of 0. Add a field to the thread_struct to store TPIDR2 and context switch it with the other thread specific data.
In case there are future extensions which also use TPIDR2 we introduce system_supports_tpidr2() and use that rather than system_supports_sme() for TPIDR2 handling.
--- arch/arm64/include/asm/cpufeature.h | 5 +++++ arch/arm64/include/asm/processor.h | 1 + arch/arm64/kernel/fpsimd.c | 4 ++++ arch/arm64/kernel/process.c | 14 ++++++++++++-- 4 files changed, 22 insertions(+), 2 deletions(-)
arch/arm64/include/asm/cpufeature.h +5 -0
@@ -747,6 +747,11 @@ static __always_inline bool system_supports_fa64(void)cpus_have_const_cap (ARM64_SME_FA64 ); } +static __always_inline bool system_supports_tpidr2(void) +{ +return system_supports_sme (); +} + static __always_inline bool system_supports_cnp(void) { return IS_ENABLED(CONFIG_ARM64_CNP) &&
arch/arm64/include/asm/processor.h +1 -0
@@ -168,6 +168,7 @@ struct thread_struct {u64 mte_ctrl;#endif u64 sctlr_user; +u64 tpidr2_el0; }; static inline unsigned int thread_get_vl(struct thread_struct *thread,
arch/arm64/kernel/fpsimd.c +4 -0
@@ -1092,6 +1092,10 @@ void sme_kernel_enable(const struct arm64_cpu_capabilities *__always_unused p)/* Allow SME in kernel */ write_sysreg (read_sysreg (CPACR_EL1 ) |CPACR_EL1_SMEN_EL1EN ,CPACR_EL1 );isb (); + +/* Allow EL0 to access TPIDR2 */ +write_sysreg (read_sysreg (SCTLR_EL1 ) | SCTLR_ELx_ENTP2,SCTLR_EL1 ); +isb (); }/*
arch/arm64/kernel/process.c +12 -2
@@ -250,6 +250,8 @@ void show_regs(struct pt_regs *regs)static void tls_thread_flush (void ) {write_sysreg (0 , tpidr_el0); +if (system_supports_tpidr2 ()) +write_sysreg_s (0 ,SYS_TPIDR2_EL0 );if (is_compat_task ()) { current->thread.uw.tp_value =0 ;
@@ -343,6 +345,8 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,* out-of-sync with the saved value. */ *task_user_tls (p) =read_sysreg (tpidr_el0); +if (system_supports_tpidr2 ()) + p->thread.tpidr2_el0 =read_sysreg_s (SYS_TPIDR2_EL0 );if (stack_start) {if (is_compat_thread (task_thread_info (p)))
@@ -353,10 +357,12 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,/* * If a TLS pointer was passed to clone, use it for the new -* thread. +* thread. We also reset TPIDR2 if it's in use. */ -if (clone_flags &CLONE_SETTLS ) +if (clone_flags &CLONE_SETTLS ) { p->thread.uw.tp_value = tls; + p->thread.tpidr2_el0 =0 ; + } }else {/* * A kthread has no context to ERET to, so ensure any buggy
@@ -387,6 +393,8 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,void tls_preserve_current_state (void ) { *task_user_tls (current) =read_sysreg (tpidr_el0); +if (system_supports_tpidr2 () && !is_compat_task ()) + current->thread.tpidr2_el0 =read_sysreg_s (SYS_TPIDR2_EL0 ); }static void tls_thread_switch (struct task_struct *next)
@@ -399,6 +407,8 @@ static void tls_thread_switch(struct task_struct *next)write_sysreg (0 , tpidrro_el0);write_sysreg (*task_user_tls (next), tpidr_el0); +if (system_supports_tpidr2 ()) +write_sysreg_s (next->thread.tpidr2_el0,SYS_TPIDR2_EL0 ); }/*
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 13/38 arm64/sme: Implement SVCR context switching
In reply to Mark BrownIn SME the use of both streaming SVE mode and ZA are tracked through PSTATE.SM and PSTATE.ZA, visible through the system register SVCR. In order to context switch the floating point state for SME we need to context switch the contents of this register as part of context switching the floating point state.
Since changing the vector length exits streaming SVE mode and disables ZA we also make sure we update SVCR appropriately when setting vector length, and similarly ensure that new threads have streaming SVE mode and ZA disabled.
--- arch/arm64/include/asm/fpsimd.h | 3 ++- arch/arm64/include/asm/processor.h | 1 + arch/arm64/include/asm/thread_info.h | 1 + arch/arm64/kernel/fpsimd.c | 18 +++++++++++++++++- arch/arm64/kernel/process.c | 2 ++ arch/arm64/kvm/fpsimd.c | 4 ++++ 6 files changed, 27 insertions(+), 2 deletions(-)
arch/arm64/include/asm/fpsimd.h +2 -1
@@ -46,7 +46,8 @@ extern void fpsimd_restore_current_state(void);extern void fpsimd_update_current_state (struct user_fpsimd_state const *state);extern void fpsimd_bind_state_to_cpu (struct user_fpsimd_state *state, -void *sve_state,unsigned int sve_vl); +void *sve_state,unsigned int sve_vl, +u64 *svcr);extern void fpsimd_flush_task_state (struct task_struct *target);extern void fpsimd_save_and_flush_cpu_state (void );
arch/arm64/include/asm/processor.h +1 -0
@@ -168,6 +168,7 @@ struct thread_struct {u64 mte_ctrl;#endif u64 sctlr_user; +u64 svcr;u64 tpidr2_el0; };
arch/arm64/include/asm/thread_info.h +1 -0
@@ -82,6 +82,7 @@ int arch_dup_task_struct(struct task_struct *dst,#define TIF_SVE_VL_INHERIT 24/* Inherit SVE vl_onexec across exec */ #define TIF_SSBD 25/* Wants SSB mitigation */ #define TIF_TAGGED_ADDR 26/* Allow tagged user addresses */ +#define TIF_SME 27/* SME in use */ #define TIF_SME_VL_INHERIT 28/* Inherit SME vl_onexec across exec */ #define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
arch/arm64/kernel/fpsimd.c +17 -1
@@ -121,6 +121,7 @@struct fpsimd_last_state_struct {struct user_fpsimd_state *st;void *sve_state; +u64 *svcr;unsigned int sve_vl; };
@@ -359,6 +360,9 @@ static void task_fpsimd_load(void)WARN_ON (!system_supports_fpsimd ());WARN_ON (!have_cpu_fpsimd_context ()); +if (IS_ENABLED (CONFIG_ARM64_SME ) &&test_thread_flag (TIF_SME )) +write_sysreg_s (current->thread.svcr,SYS_SVCR_EL0 ); +if (IS_ENABLED (CONFIG_ARM64_SVE ) &&test_thread_flag (TIF_SVE )) {sve_set_vq (sve_vq_from_vl (task_get_sve_vl (current)) -1 ); sve_load_state(sve_pffr(¤t->thread),
@@ -384,6 +388,12 @@ static void fpsimd_save(void)if (test_thread_flag (TIF_FOREIGN_FPSTATE ))return ; +if (IS_ENABLED (CONFIG_ARM64_SME ) && +test_thread_flag (TIF_SME )) { +u64 *svcr = last->svcr; + *svcr =read_sysreg_s (SYS_SVCR_EL0 ); + } +if (IS_ENABLED (CONFIG_ARM64_SVE ) &&test_thread_flag (TIF_SVE )) {if (WARN_ON (sve_get_vl () != last->sve_vl)) {
@@ -735,6 +745,10 @@ int vec_set_vector_length(struct task_struct *task, enum vec_type type,if (test_and_clear_tsk_thread_flag (task,TIF_SVE ))sve_to_fpsimd (task); +if (system_supports_sme () && type ==ARM64_VEC_SME ) + task->thread.svcr &= ~(SYS_SVCR_EL0_SM_MASK | +SYS_SVCR_EL0_ZA_MASK ); +if (task == current)put_cpu_fpsimd_context ();
@@ -1398,6 +1412,7 @@ static void fpsimd_bind_task_to_cpu(void) last->st = ¤t->thread.uw.fpsimd_state; last->sve_state = current->thread.sve_state; last->sve_vl =task_get_sve_vl (current); + last->svcr = ¤t->thread.svcr; current->thread.fpsimd_cpu =smp_processor_id ();if (system_supports_sve ()) {
@@ -1412,7 +1427,7 @@ static void fpsimd_bind_task_to_cpu(void) }void fpsimd_bind_state_to_cpu (struct user_fpsimd_state *st,void *sve_state, -unsigned int sve_vl) +unsigned int sve_vl,u64 *svcr) {struct fpsimd_last_state_struct *last =this_cpu_ptr (&fpsimd_last_state);
@@ -1421,6 +1436,7 @@ void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *st, void *sve_state,WARN_ON (!in_softirq () && !irqs_disabled ()); last->st = st; + last->svcr = svcr; last->sve_state = sve_state; last->sve_vl = sve_vl; }
arch/arm64/kernel/process.c +2 -0
@@ -310,6 +310,8 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) dst->thread.sve_state =NULL ;clear_tsk_thread_flag (dst,TIF_SVE ); + dst->thread.svcr =0 ; +/* clear any pending asynchronous tag fault raised by the parent */ clear_tsk_thread_flag (dst,TIF_MTE_ASYNC_FAULT );
arch/arm64/kvm/fpsimd.c +4 -0
@@ -103,6 +103,10 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu)WARN_ON_ONCE (!irqs_disabled ());if (vcpu->arch.flags &KVM_ARM64_FP_ENABLED ) { +/* +* Currently we do not support SME guests so SVCR is +* always 0 and we just need a variable to point to. +*/ fpsimd_bind_state_to_cpu (&vcpu->arch.ctxt.fp_regs, vcpu->arch.sve_state, vcpu->arch.sve_max_vl);
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 14/38 arm64/sme: Implement streaming SVE context switching
In reply to Mark BrownWhen in streaming mode we need to save and restore the streaming mode SVE register state rather than the regular SVE register state. This uses the streaming mode vector length and omits FFR but is otherwise identical, if TIF_SVE is enabled when we are in streaming mode then streaming mode takes precedence.
This does not handle use of streaming SVE state with KVM, ptrace or signals. This will be updated in further patches.
--- arch/arm64/include/asm/fpsimd.h | 22 +++++- arch/arm64/include/asm/fpsimdmacros.h | 11 +++ arch/arm64/include/asm/processor.h | 10 +++ arch/arm64/kernel/entry-fpsimd.S | 5 ++ arch/arm64/kernel/fpsimd.c | 109 +++++++++++++++++++++----- arch/arm64/kvm/fpsimd.c | 3 +- 6 files changed, 137 insertions(+), 23 deletions(-)
arch/arm64/include/asm/fpsimd.h +20 -2
@@ -47,11 +47,21 @@ extern void fpsimd_update_current_state(struct user_fpsimd_state const *state);extern void fpsimd_bind_state_to_cpu (struct user_fpsimd_state *state,void *sve_state,unsigned int sve_vl, -u64 *svcr); +unsigned int sme_vl,u64 *svcr);extern void fpsimd_flush_task_state (struct task_struct *target);extern void fpsimd_save_and_flush_cpu_state (void ); +static inline bool thread_sm_enabled (struct thread_struct *thread) +{ +return system_supports_sme () && (thread->svcr &SYS_SVCR_EL0_SM_MASK ); +} + +static inline bool thread_za_enabled (struct thread_struct *thread) +{ +return system_supports_sme () && (thread->svcr &SYS_SVCR_EL0_ZA_MASK ); +} +/* Maximum VL that SVE/SME VL-agnostic software can transparently support */ #define VL_ARCH_MAX 0x100
@@ -63,7 +73,14 @@ static inline size_t sve_ffr_offset(int vl)static inline void *sve_pffr (struct thread_struct *thread) { -return (char *)thread->sve_state +sve_ffr_offset (thread_get_sve_vl (thread)); +unsigned int vl; + +if (system_supports_sme () &&thread_sm_enabled (thread)) + vl =thread_get_sme_vl (thread); +else + vl =thread_get_sve_vl (thread); + +return (char *)thread->sve_state +sve_ffr_offset (vl); }extern void sve_save_state (void *state,u32 *pfpsr,int save_ffr);
@@ -72,6 +89,7 @@ extern void sve_load_state(void const *state, u32 const *pfpsr,extern void sve_flush_live (bool flush_ffr,unsigned long vq_minus_1);extern unsigned int sve_get_vl (void );extern void sve_set_vq (unsigned long vq_minus_1); +extern void sme_set_vq (unsigned long vq_minus_1);struct arm64_cpu_capabilities ;extern void sve_kernel_enable (const struct arm64_cpu_capabilities *__unused);
arch/arm64/include/asm/fpsimdmacros.h +11 -0
@@ -261,6 +261,17 @@ 921: .endm +/* Update SMCR_EL1.LEN with the new VQ */ +.macro sme_load_vq xvqminus1, xtmp, xtmp2 + mrs_s \xtmp, SYS_SMCR_EL1 + bic \xtmp2, \xtmp, SMCR_ELx_LEN_MASK + orr \xtmp2, \xtmp2, \xvqminus1 + cmp \xtmp2, \xtmp + b.eq 921f + msr_s SYS_SMCR_EL1, \xtmp2 //self-synchronising +921: +.endm + /* Preserve the first 128-bits of Znz and zero the rest. */ .macro _sve_flush_z nz _sve_check_zreg \nz
arch/arm64/include/asm/processor.h +10 -0
@@ -183,6 +183,11 @@ static inline unsigned int thread_get_sve_vl(struct thread_struct *thread)return thread_get_vl (thread,ARM64_VEC_SVE ); } +static inline unsigned int thread_get_sme_vl (struct thread_struct *thread) +{ +return thread_get_vl (thread,ARM64_VEC_SME ); +} +unsigned int task_get_vl (const struct task_struct *task,enum vec_type type);void task_set_vl (struct task_struct *task,enum vec_type type,unsigned long vl);
@@ -196,6 +201,11 @@ static inline unsigned int task_get_sve_vl(const struct task_struct *task)return task_get_vl (task,ARM64_VEC_SVE ); } +static inline unsigned int task_get_sme_vl (const struct task_struct *task) +{ +return task_get_vl (task,ARM64_VEC_SME ); +} +static inline void task_set_sve_vl (struct task_struct *task,unsigned long vl) {task_set_vl (task,ARM64_VEC_SVE , vl);
arch/arm64/kernel/entry-fpsimd.S +5 -0
@@ -94,4 +94,9 @@ SYM_FUNC_START(sme_get_vl) ret SYM_FUNC_END(sme_get_vl) +SYM_FUNC_START(sme_set_vq) + sme_load_vq x0, x1, x2 + ret +SYM_FUNC_END(sme_set_vq) + #endif /* CONFIG_ARM64_SME */
arch/arm64/kernel/fpsimd.c +89 -20
206 lines not on this page · raw message
arch/arm64/kvm/fpsimd.c +2 -1
@@ -109,7 +109,8 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu)*/ fpsimd_bind_state_to_cpu (&vcpu->arch.ctxt.fp_regs, vcpu->arch.sve_state, - vcpu->arch.sve_max_vl); + vcpu->arch.sve_max_vl, +0 );clear_thread_flag (TIF_FOREIGN_FPSTATE );update_thread_flag (TIF_SVE ,vcpu_has_sve (vcpu));
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 15/38 arm64/sme: Implement ZA context switching
In reply to Mark BrownAllocate space for storing ZA on first access to SME and use that to save and restore ZA state when context switching. We do this by using the vector form of the LDR and STR ZA instructions, these do not require streaming mode and have implementation recommendations that they avoid contention issues in shared SMCU implementations.
Since ZA is architecturally guaranteed to be zeroed when enabled we do not need to explicitly zero ZA, either we will be restoring from a saved copy or trapping on first use of SME so we know that ZA must be disabled.
--- arch/arm64/include/asm/fpsimd.h | 5 ++++- arch/arm64/include/asm/fpsimdmacros.h | 22 ++++++++++++++++++++++ arch/arm64/include/asm/kvm_host.h | 3 +++ arch/arm64/include/asm/processor.h | 1 + arch/arm64/kernel/entry-fpsimd.S | 22 ++++++++++++++++++++++ arch/arm64/kernel/fpsimd.c | 20 +++++++++++++------- arch/arm64/kvm/fpsimd.c | 2 +- 7 files changed, 66 insertions(+), 9 deletions(-)
arch/arm64/include/asm/fpsimd.h +4 -1
@@ -47,7 +47,8 @@ extern void fpsimd_update_current_state(struct user_fpsimd_state const *state);extern void fpsimd_bind_state_to_cpu (struct user_fpsimd_state *state,void *sve_state,unsigned int sve_vl, -unsigned int sme_vl,u64 *svcr); +void *za_state,unsigned int sme_vl, +u64 *svcr);extern void fpsimd_flush_task_state (struct task_struct *target);extern void fpsimd_save_and_flush_cpu_state (void );
@@ -90,6 +91,8 @@ extern void sve_flush_live(bool flush_ffr, unsigned long vq_minus_1);extern unsigned int sve_get_vl (void );extern void sve_set_vq (unsigned long vq_minus_1);extern void sme_set_vq (unsigned long vq_minus_1); +extern void za_save_state (void *state); +extern void za_load_state (void const *state);struct arm64_cpu_capabilities ;extern void sve_kernel_enable (const struct arm64_cpu_capabilities *__unused);
arch/arm64/include/asm/fpsimdmacros.h +22 -0
@@ -318,3 +318,25 @@ ldr w\nxtmp, [\xpfpsr, #4] msr fpcr, x\nxtmp .endm + +.macro sme_save_za nxbase, xvl, nw + mov w\nw, #0 + +423: + _sme_str_zav \nw, \nxbase + add x\nxbase, x\nxbase, \xvl + add x\nw, x\nw, #1 + cmp \xvl, x\nw + bne 423b +.endm + +.macro sme_load_za nxbase, xvl, nw + mov w\nw, #0 + +423: + _sme_ldr_zav \nw, \nxbase + add x\nxbase, x\nxbase, \xvl + add x\nw, x\nw, #1 + cmp \xvl, x\nw + bne 423b +.endm
arch/arm64/include/asm/kvm_host.h +3 -0
@@ -280,8 +280,11 @@ struct vcpu_reset_state {struct kvm_vcpu_arch {struct kvm_cpu_context ctxt; + +/* Guest floating point state */ void *sve_state;unsigned int sve_max_vl; +u64 svcr;/* Stage 2 paging state used by the hardware on next switch */ struct kvm_s2_mmu *hw_mmu;
arch/arm64/include/asm/processor.h +1 -0
@@ -153,6 +153,7 @@ struct thread_struct {unsigned int fpsimd_cpu;void *sve_state;/* SVE registers, if any */ +void *za_state;/* ZA register, if any */ unsigned int vl[ARM64_VEC_MAX ];/* vector length */ unsigned int vl_onexec[ARM64_VEC_MAX ];/* vl after next exec */ unsigned long fault_address;/* fault info */
arch/arm64/kernel/entry-fpsimd.S +22 -0
@@ -99,4 +99,26 @@ SYM_FUNC_START(sme_set_vq) ret SYM_FUNC_END(sme_set_vq) +/* + * Save the SME state + * + * x0 - pointer to buffer for state + */ +SYM_FUNC_START(za_save_state) + _sme_rdsvl 1, 1 // x1 = VL/8 + sme_save_za 0, x1, 12 + ret +SYM_FUNC_END(za_save_state) + +/* + * Load the SME state + * + * x0 - pointer to buffer for state + */ +SYM_FUNC_START(za_load_state) + _sme_rdsvl 1, 1 // x1 = VL/8 + sme_load_za 0, x1, 12 + ret +SYM_FUNC_END(za_load_state) + #endif /* CONFIG_ARM64_SME */
arch/arm64/kernel/fpsimd.c +13 -7
@@ -121,6 +121,7 @@struct fpsimd_last_state_struct {struct user_fpsimd_state *st;void *sve_state; +void *za_state;u64 *svcr;unsigned int sve_vl;unsigned int sme_vl;
@@ -387,11 +388,15 @@ static void task_fpsimd_load(void)if (system_supports_sme ()) {unsigned long sme_vl =task_get_sme_vl (current); +/* Ensure VL is set up for restoring data */ if (test_thread_flag (TIF_SME ))sme_set_vq (sve_vq_from_vl (sme_vl) -1 );write_sysreg_s (current->thread.svcr,SYS_SVCR_EL0 ); +if (thread_za_enabled (¤t->thread)) +za_load_state (current->thread.za_state); +if (thread_sm_enabled (¤t->thread)) { restore_sve_regs = true; restore_ffr =system_supports_fa64 ();
@@ -435,11 +440,10 @@ static void fpsimd_save(void)u64 *svcr = last->svcr; *svcr =read_sysreg_s (SYS_SVCR_EL0 ); -if (thread_za_enabled (¤t->thread)) { -/* ZA state managment is not implemented yet */ -force_signal_inject (SIGKILL ,SI_KERNEL ,0 ,0 ); -return ; - } + *svcr =read_sysreg_s (SYS_SVCR_EL0 ); + +if (*svcr &SYS_SVCR_EL0_ZA_MASK ) +za_save_state (last->za_state);/* If we are in streaming mode override regular SVE. */ if (*svcr &SYS_SVCR_EL0_SM_MASK ) {
@@ -1477,6 +1481,7 @@ static void fpsimd_bind_task_to_cpu(void)WARN_ON (!system_supports_fpsimd ()); last->st = ¤t->thread.uw.fpsimd_state; last->sve_state = current->thread.sve_state; + last->za_state = current->thread.za_state; last->sve_vl =task_get_sve_vl (current); last->sme_vl =task_get_sme_vl (current); last->svcr = ¤t->thread.svcr;
@@ -1494,8 +1499,8 @@ static void fpsimd_bind_task_to_cpu(void) }void fpsimd_bind_state_to_cpu (struct user_fpsimd_state *st,void *sve_state, -unsigned int sve_vl,unsigned int sme_vl, -u64 *svcr) +unsigned int sve_vl,void *za_state, +unsigned int sme_vl,u64 *svcr) {struct fpsimd_last_state_struct *last =this_cpu_ptr (&fpsimd_last_state);
@@ -1506,6 +1511,7 @@ void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *st, void *sve_state, last->st = st; last->svcr = svcr; last->sve_state = sve_state; + last->za_state = za_state; last->sve_vl = sve_vl; last->sme_vl = sme_vl; }
arch/arm64/kvm/fpsimd.c +1 -1
@@ -110,7 +110,7 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu)fpsimd_bind_state_to_cpu (&vcpu->arch.ctxt.fp_regs, vcpu->arch.sve_state, vcpu->arch.sve_max_vl, -0 ); +NULL ,0 , &vcpu->arch.svcr);clear_thread_flag (TIF_FOREIGN_FPSTATE );update_thread_flag (TIF_SVE ,vcpu_has_sve (vcpu));
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 16/38 arm64/sme: Implement traps and syscall handling for SME
In reply to Mark BrownBy default all SME operations in userspace will trap. When this happens we allocate storage space for the SME register state, set up the SVE registers and disable traps. We do not need to initialize ZA since the architecture guarantees that it will be zeroed when enabled and when we trap ZA is disabled.
On syscall we exit streaming mode if we were previously in it and ensure that all but the lower 128 bits of the registers are zeroed while preserving the state of ZA. This follows the aarch64 PCS for SME, ZA state is preserved over a function call and streaming mode is exited. Since the traps for SME do not distinguish between streaming mode SVE and ZA usage if ZA is in use rather than reenabling traps we instead zero the parts of the SVE registers not shared with FPSIMD and leave SME enabled, this simplifies handling SME traps. If ZA is not in use then we reenable SME traps and fall through to normal handling of SVE.
--- arch/arm64/include/asm/esr.h | 1 + arch/arm64/include/asm/exception.h | 1 + arch/arm64/include/asm/fpsimd.h | 27 +++++ arch/arm64/kernel/entry-common.c | 11 ++ arch/arm64/kernel/fpsimd.c | 180 ++++++++++++++++++++++++++--- arch/arm64/kernel/process.c | 12 +- arch/arm64/kernel/syscall.c | 34 +++++- 7 files changed, 242 insertions(+), 24 deletions(-)
arch/arm64/include/asm/esr.h +1 -0
@@ -76,6 +76,7 @@#define ESR_ELx_IL_SHIFT (25)#define ESR_ELx_IL (UL(1) << ESR_ELx_IL_SHIFT)#define ESR_ELx_ISS_MASK (ESR_ELx_IL - 1) +#define ESR_ELx_ISS (esr) ((esr) & ESR_ELx_ISS_MASK)/* ISS field definitions shared by different classes */ #define ESR_ELx_WNR_SHIFT (6)
arch/arm64/include/asm/exception.h +1 -0
@@ -64,6 +64,7 @@ void do_debug_exception(unsigned long addr_if_watchpoint, unsigned int esr, struct pt_regs *regs);void do_fpsimd_acc (unsigned int esr,struct pt_regs *regs);void do_sve_acc (unsigned int esr,struct pt_regs *regs); +void do_sme_acc (unsigned int esr,struct pt_regs *regs);void do_fpsimd_exc (unsigned int esr,struct pt_regs *regs);void do_sysinstr (unsigned int esr,struct pt_regs *regs);void do_sp_pc_abort (unsigned long addr,unsigned int esr,struct pt_regs *regs);
arch/arm64/include/asm/fpsimd.h +27 -0
@@ -282,6 +282,16 @@ static inline void sve_setup(void) { }#ifdef CONFIG_ARM64_SME +static inline void sme_user_disable (void ) +{ +sysreg_clear_set (cpacr_el1,CPACR_EL1_SMEN_EL0EN ,0 ); +} + +static inline void sme_user_enable (void ) +{ +sysreg_clear_set (cpacr_el1,0 ,CPACR_EL1_SMEN_EL0EN ); +} +static inline void sme_smstart_sm (void ) { asmvolatile (".inst 0xd503437f" );
@@ -309,16 +319,33 @@ static inline int sme_max_virtualisable_vl(void)return vec_max_virtualisable_vl (ARM64_VEC_SME ); } +extern void sme_alloc (struct task_struct *task);extern unsigned int sme_get_vl (void );extern int sme_set_current_vl (unsigned long arg);extern int sme_get_current_vl (void ); +/* +* Return how many bytes of memory are required to store the full SME +* specific state (currently just ZA) for task, given task's currently +* configured vector length. +*/ +static inline size_t za_state_size (struct task_struct const *task) +{ +unsigned int vl =task_get_sme_vl (task); + +return ZA_SIG_REGS_SIZE (sve_vq_from_vl (vl)); +} +#else +static inline void sme_user_disable (void ) {BUILD_BUG (); } +static inline void sme_user_enable (void ) {BUILD_BUG (); } +static inline void sme_smstart_sm (void ) { }static inline void sme_smstop_sm (void ) { }static inline void sme_smstop (void ) { } +static inline void sme_alloc (struct task_struct *task) { }static inline void sme_setup (void ) { }static inline unsigned int sme_get_vl (void ) {return 0 ; }static inline int sme_max_vl (void ) {return 0 ; }
arch/arm64/kernel/entry-common.c +11 -0
@@ -524,6 +524,14 @@ static void noinstr el0_sve_acc(struct pt_regs *regs, unsigned long esr)exit_to_user_mode (regs); } +static void noinstr el0_sme_acc(struct pt_regs *regs, unsigned long esr) +{ +enter_from_user_mode (regs); +local_daif_restore (DAIF_PROCCTX ); +do_sme_acc (esr, regs); +exit_to_user_mode (regs); +} + static void noinstr el0_fpsimd_exc(struct pt_regs *regs, unsigned long esr) {enter_from_user_mode (regs);
@@ -632,6 +640,9 @@ asmlinkage void noinstr el0t_64_sync_handler(struct pt_regs *regs)case ESR_ELx_EC_SVE:el0_sve_acc (regs, esr);break ; +case ESR_ELx_EC_SME: +el0_sme_acc (regs, esr); +break ;case ESR_ELx_EC_FP_EXC64:el0_fpsimd_exc (regs, esr);break ;
arch/arm64/kernel/fpsimd.c +163 -17
256 lines not on this page · raw message
arch/arm64/kernel/process.c +7 -5
@@ -299,17 +299,19 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)BUILD_BUG_ON (!IS_ENABLED (CONFIG_THREAD_INFO_IN_TASK ));/* -* Detach src's sve_state (if any) from dst so that it does not -* get erroneously used or freed prematurely. dst's sve_state -* will be allocated on demand later on if dst uses SVE. -* For consistency, also clear TIF_SVE here: this could be done +* Detach src's sve/za_state (if any) from dst so that it does not +* get erroneously used or freed prematurely. dst's copies +* will be allocated on demand later on if dst uses SVE/SME. +* For consistency, also clear TIF_SVE/SME here: this could be done * later in copy_process(), but to avoid tripping up future -* maintainers it is best not to leave TIF_SVE and sve_state in +* maintainers it is best not to leave TIF flags and buffers in * an inconsistent state, even temporarily. */ dst->thread.sve_state =NULL ;clear_tsk_thread_flag (dst,TIF_SVE ); + dst->thread.za_state =NULL ; +clear_tsk_thread_flag (dst,TIF_SME ); dst->thread.svcr =0 ;/* clear any pending asynchronous tag fault raised by the parent */
arch/arm64/kernel/syscall.c +32 -2
@@ -158,11 +158,41 @@ 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 +* that after a syscall we never have any SME 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 (); + +if (!(svcr &SYS_SVCR_EL0_ZA_MASK )) { +clear_thread_flag (TIF_SME ); +sme_user_disable (); + } + } + +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 );/*
@@ -177,7 +207,7 @@ static inline void sve_user_discard(void)void do_el0_svc (struct pt_regs *regs) { -sve_user_discard (); +fp_user_discard ();el0_svc_common (regs, regs->regs[8 ], __NR_syscalls, sys_call_table); }
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 17/38 arm64/sme: Disable ZA and streaming mode when handling signals
In reply to Mark BrownThe ABI requires that streaming mode and ZA are disabled when invoking signal handlers, do this in setup_return() when we prepare the task state for the signal handler.
--- arch/arm64/kernel/signal.c | 7 +++++++ 1 file changed, 7 insertions(+)
arch/arm64/kernel/signal.c +7 -0
@@ -758,6 +758,13 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,/* TCO (Tag Check Override) always cleared for signal handlers */ regs->pstate &= ~PSR_TCO_BIT ; +/* Signal handlers are invoked with ZA and streaming mode disabled */ +if (system_supports_sme ()) { + current->thread.svcr &= ~(SYS_SVCR_EL0_ZA_MASK | +SYS_SVCR_EL0_SM_MASK ); +sme_smstop (); + } +if (ka->sa.sa_flags &SA_RESTORER ) sigtramp = ka->sa.sa_restorer;else
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 18/38 arm64/sme: Implement streaming SVE signal handling
In reply to Mark BrownWhen in streaming mode we have the same set of SVE registers as we do in regular SVE mode with the exception of FFR and the use of the SME vector length. Provide signal handling for these registers by taking one of the reserved words in the SVE signal context as a flags field and defining a flag with a flag which is set for streaming mode. When the flag is set the vector length is set to the streaming mode vector length and we save and restore streaming mode data. We support entering or leaving streaming mode based on the value of the flag but do not support changing the vector length, this is not currently supported SVE signal handling.
We could instead allocate a separate record in the signal frame for the streaming mode SVE context but this inflates the size of the maximal signal frame required and adds complication when validating signal frames from userspace, especially given the current structure of the code.
Any implementation of support for streaming mode vectors in signals will have some potential for causing issues for applications that attempt to handle SVE vectors in signals, use streaming mode but do not understand streaming mode in their signal handling code, it is hard to identify a case that is clearly better than any other - they all have cases where they could cause unexpected register corruption or faults.
--- arch/arm64/include/uapi/asm/sigcontext.h | 16 ++++++-- arch/arm64/kernel/signal.c | 48 ++++++++++++++++++------ 2 files changed, 50 insertions(+), 14 deletions(-)
arch/arm64/include/uapi/asm/sigcontext.h +13 -3
@@ -134,9 +134,12 @@ struct extra_context {struct sve_context {struct _aarch64_ctx head;__u16 vl; -__u16 __reserved[3 ]; +__u16 flags; +__u16 __reserved[2 ]; }; +#define SVE_SIG_FLAG_SM 0x1/* Context describes streaming mode */ +#endif /* !__ASSEMBLY__ */ #include <asm/sve_context.h>
@@ -186,9 +189,16 @@ struct sve_context {* sve_context.vl must equal the thread's current vector length when * doing a sigreturn. * +* On systems with support for SME the SVE register state may reflect either +* streaming or non-streaming mode. In streaming mode the streaming mode +* vector length will be used and the flag SVE_SIG_FLAG_SM will be set in +* the flags field. It is permitted to enter or leave streaming mode in +* a signal return, applications should take care to ensure that any difference +* in vector length between the two modes is handled, including any resixing +* and movement of context blocks. * -* Note: for all these macros, the "vq" argument denotes the SVE -* vector length in quadwords (i.e., units of 128 bits). +* Note: for all these macros, the "vq" argument denotes the vector length +* in quadwords (i.e., units of 128 bits). * * The correct way to obtain vq is to use sve_vq_from_vl(vl). The * result is valid if and only if sve_vl_valid(vl) is true. This is
arch/arm64/kernel/signal.c +37 -11
105 lines not on this page · raw message
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 19/38 arm64/sme: Implement ZA signal handling
In reply to Mark BrownImplement support for ZA in signal handling in a very similar way to how we implement support for SVE registers, using a signal context structure with optional register state after it. Where present this register state stores the ZA matrix as a series of horizontal vectors numbered from 0 to VL/8 in the endinanness independent format used for vectors.
As with SVE we do not allow changes in the vector length during signal return but we do allow ZA to be enabled or disabled.
--- arch/arm64/include/uapi/asm/sigcontext.h | 41 +++++++ arch/arm64/kernel/fpsimd.c | 3 - arch/arm64/kernel/signal.c | 139 +++++++++++++++++++++++ 3 files changed, 180 insertions(+), 3 deletions(-)
arch/arm64/include/uapi/asm/sigcontext.h +41 -0
@@ -140,6 +140,14 @@ struct sve_context {#define SVE_SIG_FLAG_SM 0x1/* Context describes streaming mode */ +#define ZA_MAGIC 0x54366345 + +struct za_context { +struct _aarch64_ctx head; +__u16 vl; +__u16 __reserved[3 ]; +}; +#endif /* !__ASSEMBLY__ */ #include <asm/sve_context.h>
@@ -259,4 +267,37 @@ struct sve_context {#define SVE_SIG_CONTEXT_SIZE (vq) \ (SVE_SIG_REGS_OFFSET + SVE_SIG_REGS_SIZE(vq)) +/* +* If the ZA register is enabled for the thread at signal delivery then, +* za_context.head.size >= ZA_SIG_CONTEXT_SIZE(sve_vq_from_vl(za_context.vl)) +* and the register data may be accessed using the ZA_SIG_*() macros. +* +* If za_context.head.size < ZA_SIG_CONTEXT_SIZE(sve_vq_from_vl(za_context.vl)) +* then ZA was not enabled and no register data was included in which case +* ZA register was not enabled for the thread and no register data +* the ZA_SIG_*() macros should not be used except for this check. +* +* The same convention applies when returning from a signal: a caller +* will need to remove or resize the za_context block if it wants to +* enable the ZA register when it was previously non-live or vice-versa. +* This may require the caller to allocate fresh memory and/or move other +* context blocks in the signal frame. +* +* Changing the vector length during signal return is not permitted: +* za_context.vl must equal the thread's current SME vector length when +* doing a sigreturn. +*/ + +#define ZA_SIG_REGS_OFFSET \ + ((sizeof(struct za_context) + (__SVE_VQ_BYTES - 1)) \ + / __SVE_VQ_BYTES * __SVE_VQ_BYTES) + +#define ZA_SIG_REGS_SIZE (vq) ((vq * __SVE_VQ_BYTES) * (vq * __SVE_VQ_BYTES)) + +#define ZA_SIG_ZAV_OFFSET (vq, n) (ZA_SIG_REGS_OFFSET + \ + (SVE_SIG_ZREG_SIZE(vq) * n)) + +#define ZA_SIG_CONTEXT_SIZE (vq) \ + (ZA_SIG_REGS_OFFSET + ZA_SIG_REGS_SIZE(vq)) +#endif /* _UAPI__ASM_SIGCONTEXT_H */
arch/arm64/kernel/fpsimd.c +0 -3
@@ -1190,9 +1190,6 @@ void fpsimd_release_task(struct task_struct *dead_task)#ifdef CONFIG_ARM64_SME -/* This will move to uapi/asm/sigcontext.h when signals are implemented */ -#define ZA_SIG_REGS_SIZE (vq) ((vq * __SVE_VQ_BYTES) * (vq * __SVE_VQ_BYTES)) -/* * Ensure that task->thread.za_state is allocated and sufficiently large. *
arch/arm64/kernel/signal.c +139 -0
187 lines not on this page · raw message
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 20/38 arm64/sme: Implement ptrace support for streaming mode SVE registers
In reply to Mark BrownThe streaming mode SVE registers are represented using the same data structures as for SVE but since the vector lengths supported and in use may not be the same as SVE we represent them with a new type NT_ARM_SSVE. Unfortunately we only have a single 16 bit reserved field available in the header so there is no space to fit the current and maximum vector length for both standard and streaming SVE mode without redefining the structure in a way the creates a complicatd and fragile ABI. Since FFR is not present in streaming mode it is read and written as zero.
Setting NT_ARM_SSVE registers will put the task into streaming mode, similarly setting NT_ARM_SVE registers will exit it. Reads that do not correspond to the current mode of the task will return the header with no register data. For compatibility reasons on write setting no flag for the register type will be interpreted as setting SVE registers, though users can provide no register data as an alternative mechanism for doing so.
--- arch/arm64/include/uapi/asm/ptrace.h | 13 +- arch/arm64/kernel/fpsimd.c | 21 ++- arch/arm64/kernel/ptrace.c | 212 +++++++++++++++++++++------ include/uapi/linux/elf.h | 1 + 4 files changed, 190 insertions(+), 57 deletions(-)
arch/arm64/include/uapi/asm/ptrace.h +8 -5
@@ -109,7 +109,7 @@ struct user_hwdebug_state { } dbg_regs[16 ]; }; -/* SVE/FP/SIMD state (NT_ARM_SVE) */ +/* SVE/FP/SIMD state (NT_ARM_SVE & NT_ARM_SSVE) */ struct user_sve_header {__u32 size;/* total meaningful regset content in bytes */
@@ -220,6 +220,7 @@ struct user_sve_header { (SVE_PT_SVE_PREG_OFFSET (vq, __SVE_NUM_PREGS) - \SVE_PT_SVE_PREGS_OFFSET (vq)) +/* For streaming mode SVE (SSVE) FFR must be read and written as zero */#define SVE_PT_SVE_FFR_OFFSET (vq) \ (SVE_PT_REGS_OFFSET + __SVE_FFR_OFFSET(vq))
@@ -240,10 +241,12 @@ struct user_sve_header { - SVE_PT_SVE_OFFSET + (__SVE_VQ_BYTES - 1)) \ / __SVE_VQ_BYTES * __SVE_VQ_BYTES) -#define SVE_PT_SIZE (vq, flags) \ - (((flags) & SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE ? \ - SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, flags) \ - : SVE_PT_FPSIMD_OFFSET + SVE_PT_FPSIMD_SIZE(vq, flags)) +#define SVE_PT_SIZE (vq, flags) \ + (((flags) & SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE ? \ + SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, flags) \ + : ((((flags) & SVE_PT_REGS_MASK) == SVE_PT_REGS_FPSIMD ? \ + SVE_PT_FPSIMD_OFFSET + SVE_PT_FPSIMD_SIZE(vq, flags) \ + : SVE_PT_REGS_OFFSET)))/* pointer authentication masks (NT_ARM_PAC_MASK) */
arch/arm64/kernel/fpsimd.c +15 -6
@@ -645,14 +645,19 @@ static void __fpsimd_to_sve(void *sst, struct user_fpsimd_state const *fst,*/ static void fpsimd_to_sve (struct task_struct *task) { -unsigned int vq; +unsigned int vq, vl;void *sst = task->thread.sve_state;struct user_fpsimd_state const *fst = &task->thread.uw.fpsimd_state;if (!system_supports_sve ())return ; - vq =sve_vq_from_vl (task_get_sve_vl (task)); +if (thread_sm_enabled (&task->thread)) + vl =task_get_sme_vl (task); +else + vl =task_get_sve_vl (task); + + vq =sve_vq_from_vl (vl);__fpsimd_to_sve (sst, fst, vq); }
@@ -669,7 +674,7 @@ static void fpsimd_to_sve(struct task_struct *task)*/ static void sve_to_fpsimd (struct task_struct *task) { -unsigned int vq; +unsigned int vq, vl;void const *sst = task->thread.sve_state;struct user_fpsimd_state *fst = &task->thread.uw.fpsimd_state;unsigned int i;
@@ -678,7 +683,12 @@ static void sve_to_fpsimd(struct task_struct *task)if (!system_supports_sve ())return ; - vq =sve_vq_from_vl (task_get_sve_vl (task)); +if (thread_sm_enabled (&task->thread)) + vl =task_get_sme_vl (task); +else + vl =task_get_sve_vl (task); + + vq =sve_vq_from_vl (vl);for (i =0 ; i <SVE_NUM_ZREGS ; ++i) { p = (__uint128_t const *)ZREG (sst, vq, i); fst->vregs[i] =arm64_le128_to_cpu (*p);
@@ -819,8 +829,7 @@ int vec_set_vector_length(struct task_struct *task, enum vec_type type,/* * To ensure the FPSIMD bits of the SVE vector registers are preserved, * write any live register state back to task_struct, and convert to a -* regular FPSIMD thread. Since the vector length can only be changed -* with a syscall we can't be in streaming mode while reconfiguring. +* regular FPSIMD thread. */ if (task == current) {get_cpu_fpsimd_context ();
arch/arm64/kernel/ptrace.c +166 -46
303 lines not on this page · raw message
include/uapi/linux/elf.h +1 -0
@@ -427,6 +427,7 @@ typedef struct elf64_shdr {#define NT_ARM_PACG_KEYS 0x408/* ARM pointer authentication generic key */ #define NT_ARM_TAGGED_ADDR_CTRL 0x409/* arm64 tagged address control (prctl()) */ #define NT_ARM_PAC_ENABLED_KEYS 0x40a/* arm64 ptr auth enabled keys (prctl()) */ +#define NT_ARM_SSVE 0x40b/* ARM Streaming SVE registers */ #define NT_ARC_V2 0x600/* ARCv2 accumulator/extra registers */ #define NT_VMCOREDD 0x700/* Vmcore Device Dump Note */ #define NT_MIPS_DSP 0x800/* MIPS DSP ASE registers */
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 21/38 arm64/sme: Add ptrace support for ZA
In reply to Mark BrownThe ZA array can be read and written with the NT_ARM_ZA. Similarly to our interface for the SVE vector registers the regset consists of a header with information on the current vector length followed by an optional register data payload, represented as for signals as a series of horizontal vectors from 0 to VL/8 in the endianness independent format used for vectors.
On get if ZA is enabled then register data will be provided, otherwise it will be omitted. On set if register data is provided then ZA is enabled and initialized using the provided data, otherwise it is disabled.
--- arch/arm64/include/uapi/asm/ptrace.h | 56 +++++++++++ arch/arm64/kernel/ptrace.c | 144 +++++++++++++++++++++++++++ include/uapi/linux/elf.h | 1 + 3 files changed, 201 insertions(+)
arch/arm64/include/uapi/asm/ptrace.h +56 -0
@@ -268,6 +268,62 @@ struct user_pac_generic_keys {__uint128_t apgakey; }; +/* ZA state (NT_ARM_ZA) */ + +struct user_za_header { +__u32 size;/* total meaningful regset content in bytes */ +__u32 max_size;/* maxmium possible size for this thread */ +__u16 vl;/* current vector length */ +__u16 max_vl;/* maximum possible vector length */ +__u16 flags; +__u16 __reserved; +}; + +/* +* Common ZA_PT_* flags: +* These must be kept in sync with prctl interface in <linux/prctl.h> +*/ +#define ZA_PT_VL_INHERIT ((1 << 17) /* PR_SME_VL_INHERIT */ >> 16) +#define ZA_PT_VL_ONEXEC ((1 << 18) /* PR_SME_SET_VL_ONEXEC */ >> 16) + + +/* +* The remainder of the ZA state follows struct user_za_header. The +* total size of the ZA state (including header) depends on the +* metadata in the header: ZA_PT_SIZE(vq, flags) gives the total size +* of the state in bytes, including the header. +* +* Refer to <asm/sigcontext.h> for details of how to pass the correct +* "vq" argument to these macros. +*/ + +/* Offset from the start of struct user_za_header to the register data */ +#define ZA_PT_ZA_OFFSET \ + ((sizeof(struct user_za_header) + (__SVE_VQ_BYTES - 1)) \ + / __SVE_VQ_BYTES * __SVE_VQ_BYTES) + +/* +* The payload starts at offset ZA_PT_ZA_OFFSET, and is of size +* ZA_PT_ZA_SIZE(vq, flags). +* +* The ZA array is stored as a sequence of horizontal vectors ZAV of SVL/8 +* bytes each, starting from vector 0. +* +* Additional data might be appended in the future. +* +* The ZA matrix is represented in memory in an endianness-invariant layout +* which differs from the layout used for the FPSIMD V-registers on big-endian +* systems: see sigcontext.h for more explanation. +*/ + +#define ZA_PT_ZAV_OFFSET (vq, n) \ + (ZA_PT_ZA_OFFSET + ((vq * __SVE_VQ_BYTES) * n)) + +#define ZA_PT_ZA_SIZE (vq) ((vq * __SVE_VQ_BYTES) * (vq * __SVE_VQ_BYTES)) + +#define ZA_PT_SIZE (vq) \ + (ZA_PT_ZA_OFFSET + ZA_PT_ZA_SIZE(vq)) +#endif /* __ASSEMBLY__ */ #endif /* _UAPI__ASM_PTRACE_H */
arch/arm64/kernel/ptrace.c +144 -0
162 lines not on this page · raw message
include/uapi/linux/elf.h +1 -0
@@ -428,6 +428,7 @@ typedef struct elf64_shdr {#define NT_ARM_TAGGED_ADDR_CTRL 0x409/* arm64 tagged address control (prctl()) */ #define NT_ARM_PAC_ENABLED_KEYS 0x40a/* arm64 ptr auth enabled keys (prctl()) */ #define NT_ARM_SSVE 0x40b/* ARM Streaming SVE registers */ +#define NT_ARM_ZA 0x40c/* ARM SME ZA registers */ #define NT_ARC_V2 0x600/* ARCv2 accumulator/extra registers */ #define NT_VMCOREDD 0x700/* Vmcore Device Dump Note */ #define NT_MIPS_DSP 0x800/* MIPS DSP ASE registers */
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 22/38 arm64/sme: Disable streaming mode and ZA when flushing CPU state
In reply to Mark BrownBoth streaming mode and ZA may increase power consumption when they are enabled and streaming mode makes many FPSIMD and SVE instructions undefined which will cause problems for any kernel mode floating point so disable both when we flush the CPU state. This covers both kernel_neon_begin() and idle and after flushing the state a reload is always required anyway.
--- arch/arm64/kernel/fpsimd.c | 9 +++++++++ 1 file changed, 9 insertions(+)
arch/arm64/kernel/fpsimd.c +9 -0
@@ -1762,6 +1762,15 @@ static void fpsimd_flush_cpu_state(void) {WARN_ON (!system_supports_fpsimd ());__this_cpu_write (fpsimd_last_state.st,NULL ); + +/* +* Leaving streaming mode enabled will cause issues for any kernel +* NEON and leaving streaming mode or ZA enabled may increase power +* consumption. +*/ +if (system_supports_sme ()) +sme_smstop (); +set_thread_flag (TIF_FOREIGN_FPSTATE ); }
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 23/38 arm64/sme: Save and restore streaming mode over EFI runtime calls
In reply to Mark BrownWhen saving and restoring the floating point state over an EFI runtime call ensure that we handle streaming mode, only handling FFR if we are not in streaming mode and ensuring that we are in normal mode over the call into runtime services.
We currently assume that ZA will not be modified by runtime services, the specification is not yet finalised so this may need updating if that changes.
--- arch/arm64/kernel/fpsimd.c | 47 +++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 6 deletions(-)
arch/arm64/kernel/fpsimd.c +41 -6
@@ -1059,21 +1059,25 @@ int vec_verify_vq_map(enum vec_type type)static void __init sve_efi_setup (void ) { -struct vl_info *info = &vl_info[ARM64_VEC_SVE ]; +int max_vl =0 ; +int i;if (!IS_ENABLED (CONFIG_EFI ))return ; +for (i =0 ; i <ARRAY_SIZE (vl_info); i++) + max_vl =max (vl_info[i].max_vl, max_vl); +/* * alloc_percpu() warns and prints a backtrace if this goes wrong. * This is evidence of a crippled system and we are returning void, * so no attempt is made to handle this situation here. */ -if (!sve_vl_valid (info->max_vl)) +if (!sve_vl_valid (max_vl)) goto fail; efi_sve_state =__alloc_percpu ( -SVE_SIG_REGS_SIZE (sve_vq_from_vl (info->max_vl)),SVE_VQ_BYTES ); +SVE_SIG_REGS_SIZE (sve_vq_from_vl (max_vl)),SVE_VQ_BYTES );if (!efi_sve_state) goto fail;
@@ -1848,6 +1852,7 @@ EXPORT_SYMBOL(kernel_neon_end); static DEFINE_PER_CPU(struct user_fpsimd_state, efi_fpsimd_state); static DEFINE_PER_CPU(bool, efi_fpsimd_state_used); static DEFINE_PER_CPU(bool, efi_sve_state_used); +static DEFINE_PER_CPU(bool, efi_sm_state);/* * EFI runtime services support functions
@@ -1882,12 +1887,28 @@ void __efi_fpsimd_begin(void)*/ if (system_supports_sve () &&likely (efi_sve_state)) {char *sve_state =this_cpu_ptr (efi_sve_state); +bool ffr = true; +u64 svcr;__this_cpu_write (efi_sve_state_used, true); +/* If we are in streaming mode don't touch FFR */ +if (system_supports_sme ()) { + svcr =read_sysreg_s (SYS_SVCR_EL0 ); + + ffr = svcr &SYS_SVCR_EL0_SM_MASK ; + +__this_cpu_write (efi_sm_state, ffr); + } +sve_save_state (sve_state +sve_ffr_offset (sve_max_vl ()), &this_cpu_ptr (&efi_fpsimd_state)->fpsr, - true); + ffr); + +if (system_supports_sme ()) +sysreg_clear_set_s (SYS_SVCR_EL0 , +SYS_SVCR_EL0_SM_MASK ,0 ); + }else {fpsimd_save_state (this_cpu_ptr (&efi_fpsimd_state)); }
@@ -1910,11 +1931,25 @@ void __efi_fpsimd_end(void)if (system_supports_sve () &&likely (__this_cpu_read (efi_sve_state_used))) {char const *sve_state =this_cpu_ptr (efi_sve_state); +bool ffr = true; + +/* +* Restore streaming mode; EFI calls are +* normal function calls so should not return in +* streaming mode. +*/ +if (system_supports_sme ()) { +if (__this_cpu_read (efi_sm_state)) { +sysreg_clear_set_s (SYS_SVCR_EL0 , +0 , +SYS_SVCR_EL0_SM_MASK ); + ffr = false; + } + } -sve_set_vq (sve_vq_from_vl (sve_get_vl ()) -1 );sve_load_state (sve_state +sve_ffr_offset (sve_max_vl ()), &this_cpu_ptr (&efi_fpsimd_state)->fpsr, - true); + ffr);__this_cpu_write (efi_sve_state_used, false); }else {
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 24/38 KVM: arm64: Hide SME system registers from guests
In reply to Mark BrownFor the time being we do not support use of SME by KVM guests, support for this will be enabled in future. In order to prevent any side effects or side channels via the new system registers, including the EL0 read/write register TPIDR2, explicitly undefine all the system registers added by SME and mask out the SME bitfield in SYS_ID_AA64PFR1.
--- arch/arm64/kvm/sys_regs.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
arch/arm64/kvm/sys_regs.c +8 -1
@@ -1089,6 +1089,8 @@ static u64 read_id_reg(const struct kvm_vcpu *vcpu,case SYS_ID_AA64PFR1_EL1 :if (!kvm_has_mte (vcpu->kvm)) val &= ~ARM64_FEATURE_MASK (ID_AA64PFR1_MTE ); + + val &= ~ARM64_FEATURE_MASK (ID_AA64PFR1_SME );break ;case SYS_ID_AA64ISAR1_EL1 :if (!vcpu_has_ptrauth (vcpu))
@@ -1508,7 +1510,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {ID_UNALLOCATED (4 ,2 ),ID_UNALLOCATED (4 ,3 ),ID_SANITISED (ID_AA64ZFR0_EL1 ), -ID_UNALLOCATED (4 ,5 ), +ID_HIDDEN (ID_AA64SMFR0_EL1 ),ID_UNALLOCATED (4 ,6 ), ID_UNALLOCATED(4,7),
@@ -1551,6 +1553,8 @@ 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_SMCR_EL1), undef_access }, { SYS_DESC(SYS_TTBR0_EL1), access_vm_reg, reset_unknown, TTBR0_EL1 }, { SYS_DESC(SYS_TTBR1_EL1), access_vm_reg, reset_unknown, TTBR1_EL1 }, { SYS_DESC(SYS_TCR_EL1), access_vm_reg, reset_val, TCR_EL1, 0 },
@@ -1633,8 +1637,10 @@ static const struct sys_reg_desc sys_reg_descs[] = { { SYS_DESC(SYS_CCSIDR_EL1), access_ccsidr }, { SYS_DESC(SYS_CLIDR_EL1), access_clidr }, + { SYS_DESC(SYS_SMIDR_EL1), undef_access }, { SYS_DESC(SYS_CSSELR_EL1), access_csselr, reset_unknown, CSSELR_EL1 }, { SYS_DESC(SYS_CTR_EL0), access_ctr }, + { SYS_DESC(SYS_SVCR_EL0), undef_access }, { PMU_SYS_REG(SYS_PMCR_EL0), .access = access_pmcr, .reset = reset_pmcr, .reg = PMCR_EL0 },
@@ -1674,6 +1680,7 @@ static const struct sys_reg_desc sys_reg_descs[] = { { SYS_DESC(SYS_TPIDR_EL0), NULL, reset_unknown, TPIDR_EL0 }, { SYS_DESC(SYS_TPIDRRO_EL0), NULL, reset_unknown, TPIDRRO_EL0 }, + { SYS_DESC(SYS_TPIDR2_EL0), undef_access }, { SYS_DESC(SYS_SCXTNUM_EL0), undef_access },
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 25/38 KVM: arm64: Trap SME usage in guest
In reply to Mark BrownSME defines two new traps which need to be enabled for guests to ensure that they can't use SME, one for the main SME operations which mirrors the traps for SVE and another for access to TPIDR2 in SCTLR_EL2.
For VHE manage SMEN along with ZEN in activate_traps() and the FP state management callbacks.
For nVHE the value to be used for CPTR_EL2 in the guest is stored in vcpu->arch.cptr_el2, set TSM there during initialisation. It will be cleared in __deactivate_traps_common() by virtue of not being set in CPTR_EL2_DEFAULT.
For both VHE and nVHE cases handle SCTLR_EL2.EnTPIDR2 in the shared __active_traps_common() and __deactivate_traps_common(), there is no existing dynamic management of SCTLR_EL2.
--- arch/arm64/kvm/hyp/nvhe/switch.c | 30 ++++++++++++++++++++++++++++++ arch/arm64/kvm/hyp/vhe/switch.c | 10 +++++++++- 2 files changed, 39 insertions(+), 1 deletion(-)
arch/arm64/kvm/hyp/nvhe/switch.c +30 -0
@@ -47,10 +47,25 @@ static void __activate_traps(struct kvm_vcpu *vcpu) val |=CPTR_EL2_TFP |CPTR_EL2_TZ ;__activate_traps_fpsimd32 (vcpu); } +if (IS_ENABLED (CONFIG_ARM64_SME ) &&cpus_have_final_cap (ARM64_SME )) + val |=CPTR_EL2_TSM ;write_sysreg (val, cptr_el2);write_sysreg (__this_cpu_read (kvm_hyp_vector), vbar_el2); +if (IS_ENABLED (CONFIG_ARM64_SME ) &&cpus_have_final_cap (ARM64_SME ) && +cpus_have_final_cap (ARM64_HAS_FGT )) { + val =read_sysreg_s (SYS_HFGRTR_EL2 ); + val &= ~(HFGxTR_EL2_nTPIDR_EL0_MASK | + HFGxTR_EL2_nSMPRI_EL1_MASK); +write_sysreg_s (val,SYS_HFGRTR_EL2 ); + + val =read_sysreg_s (SYS_HFGWTR_EL2 ); + val &= ~(HFGxTR_EL2_nTPIDR_EL0_MASK | + HFGxTR_EL2_nSMPRI_EL1_MASK); +write_sysreg_s (val,SYS_HFGWTR_EL2 ); + } +if (cpus_have_final_cap (ARM64_WORKAROUND_SPECULATIVE_AT )) {struct kvm_cpu_context *ctxt = &vcpu->arch.ctxt;
@@ -94,9 +109,24 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu)write_sysreg (this_cpu_ptr (&kvm_init_params)->hcr_el2, hcr_el2); +if (IS_ENABLED (CONFIG_ARM64_SME ) &&cpus_have_final_cap (ARM64_SME ) && +cpus_have_final_cap (ARM64_HAS_FGT )) { +u64 val; + + val =read_sysreg_s (SYS_HFGRTR_EL2 ); + val |= HFGxTR_EL2_nTPIDR_EL0_MASK | HFGxTR_EL2_nSMPRI_EL1_MASK; +write_sysreg_s (val,SYS_HFGRTR_EL2 ); + + val =read_sysreg_s (SYS_HFGWTR_EL2 ); + val |= HFGxTR_EL2_nTPIDR_EL0_MASK | HFGxTR_EL2_nSMPRI_EL1_MASK; +write_sysreg_s (val,SYS_HFGWTR_EL2 ); + } + cptr =CPTR_EL2_DEFAULT ;if (vcpu_has_sve (vcpu) && (vcpu->arch.flags &KVM_ARM64_FP_ENABLED )) cptr |=CPTR_EL2_TZ ; +if (IS_ENABLED (CONFIG_ARM64_SME ) &&cpus_have_final_cap (ARM64_SME )) + cptr &= ~CPTR_EL2_TSM ;write_sysreg (cptr, cptr_el2);write_sysreg (__kvm_hyp_host_vector, vbar_el2);
arch/arm64/kvm/hyp/vhe/switch.c +9 -1
@@ -38,7 +38,7 @@ static void __activate_traps(struct kvm_vcpu *vcpu) val =read_sysreg (cpacr_el1); val |=CPACR_EL1_TTA ; - val &= ~CPACR_EL1_ZEN ; + val &= ~(CPACR_EL1_ZEN |CPACR_EL1_SMEN );/* * With VHE (HCR.E2H == 1), accesses to CPACR_EL1 are routed to
@@ -59,6 +59,10 @@ static void __activate_traps(struct kvm_vcpu *vcpu)__activate_traps_fpsimd32 (vcpu); } +if (IS_ENABLED (CONFIG_ARM64_SME ) &&cpus_have_final_cap (ARM64_SME )) +write_sysreg (read_sysreg (sctlr_el2) & ~SCTLR_ELx_ENTP2, + sctlr_el2); +write_sysreg (val, cpacr_el1);write_sysreg (__this_cpu_read (kvm_hyp_vector), vbar_el1);
@@ -80,6 +84,10 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu)*/ asm(ALTERNATIVE("nop", "isb", ARM64_WORKAROUND_SPECULATIVE_AT)); +if (IS_ENABLED (CONFIG_ARM64_SME ) &&cpus_have_final_cap (ARM64_SME )) +write_sysreg (read_sysreg (sctlr_el2) | SCTLR_ELx_ENTP2, + sctlr_el2); +write_sysreg (CPACR_EL1_DEFAULT , cpacr_el1);write_sysreg (vectors, vbar_el1); }
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Marc Zyngier
maintainerRe: [PATCH v8 25/38] KVM: arm64: Trap SME usage in guest
Quoted 28 lines · Mark Brown
SME defines two new traps which need to be enabled for guests to ensure that they can't use SME, one for the main SME operations which mirrors the traps for SVE and another for access to TPIDR2 in
SCTLR_EL2.For VHE manage SMEN along with ZEN in
activate_traps()and the FP state management callbacks.For nVHE the value to be used for
CPTR_EL2in the guest is stored invcpu->arch.cptr_el2, set TSM there during initialisation. It will be cleared in__deactivate_traps_common()by virtue of not being set inCPTR_EL2_DEFAULT.For both VHE and nVHE cases handle SCTLR_EL2.EnTPIDR2 in the shared
__active_traps_common()and__deactivate_traps_common(), there is no existing dynamic management ofSCTLR_EL2.Signed-off-by Mark Brown <[email protected]>--- arch/arm64/kvm/hyp/nvhe/switch.c | 30 ++++++++++++++++++++++++++++++ arch/arm64/kvm/hyp/vhe/switch.c | 10 +++++++++- 2 files changed, 39 insertions(+), 1 deletion(-)arch/arm64/kvm/hyp/nvhe/switch.c +0
-0
arch/arm64/kvm/hyp/nvhe/switch.c static void __activate_traps(struct kvm_vcpu *vcpu) · line 50
Quoted 4 lines
arch/arm64/kvm/hyp/nvhe/switch.c +1
-0@@ -47,10 +47,25 @@ static void __activate_traps(struct kvm_vcpu *vcpu) val |=CPTR_EL2_TFP |CPTR_EL2_TZ ;__activate_traps_fpsimd32 (vcpu); } +if (IS_ENABLED (CONFIG_ARM64_SME ) &&cpus_have_final_cap (ARM64_SME ))
Please drop the IS_ENABLED(). We purposely avoid conditional compilation in KVM in order to avoid bitrot, and the amount of code you save isn't significant. Having a static key is more than enough to avoid runtime costs.
Quoted 7 lines
arch/arm64/kvm/hyp/nvhe/switch.c +3
-0+ val |=CPTR_EL2_TSM ;write_sysreg (val, cptr_el2);write_sysreg (__this_cpu_read (kvm_hyp_vector), vbar_el2); +if (IS_ENABLED (CONFIG_ARM64_SME ) &&cpus_have_final_cap (ARM64_SME ) && +cpus_have_final_cap (ARM64_HAS_FGT )) {
arch/arm64/kvm/hyp/nvhe/switch.c static void __activate_traps(struct kvm_vcpu *vcpu) · line 67
Quoted 10 lines
arch/arm64/kvm/hyp/nvhe/switch.c +10
-0+ val =read_sysreg_s (SYS_HFGRTR_EL2 ); + val &= ~(HFGxTR_EL2_nTPIDR_EL0_MASK | + HFGxTR_EL2_nSMPRI_EL1_MASK); +write_sysreg_s (val,SYS_HFGRTR_EL2 ); + + val =read_sysreg_s (SYS_HFGWTR_EL2 ); + val &= ~(HFGxTR_EL2_nTPIDR_EL0_MASK | + HFGxTR_EL2_nSMPRI_EL1_MASK); +write_sysreg_s (val,SYS_HFGWTR_EL2 ); + }
If the CPUs do not have FGT, what provides the equivalent trapping? If FGT is mandatory when SME exists, then you should simplify the condition.
M.
Signature · 5 lines
Without deviation from the norm, progress is not possible. _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Re: [PATCH v8 25/38] KVM: arm64: Trap SME usage in guest
Quoted 8 lines · Marc Zyngier
Review
Quoted 1 line · Mark Brown
(quoted diff) +1
-0+ if (IS_ENABLED(CONFIG_ARM64_SME) && cpus_have_final_cap(ARM64_SME))Please drop the
IS_ENABLED(). We purposely avoid conditional compilation in KVM in order to avoid bitrot, and the amount of code you save isn't significant. Having a static key is more than enough to avoid runtime costs.
Sure, I wanted to be extra careful here as this is all in hot paths and going to get moved elsewhere when we have real guest support.
Quoted 6 lines
Quoted 6 lines
arch/arm64/kvm/hyp/nvhe/switch.c +6
-0+if (IS_ENABLED (CONFIG_ARM64_SME ) &&cpus_have_final_cap (ARM64_SME ) && +cpus_have_final_cap (ARM64_HAS_FGT )) { + val =read_sysreg_s (SYS_HFGRTR_EL2 ); + val &= ~(HFGxTR_EL2_nTPIDR_EL0_MASK | + HFGxTR_EL2_nSMPRI_EL1_MASK); +write_sysreg_s (val,SYS_HFGRTR_EL2 );
Quoted 8 lines
arch/arm64/kvm/hyp/nvhe/switch.c static void __activate_traps(struct kvm_vcpu *vcpu) · line 67
Quoted 6 lines
arch/arm64/kvm/hyp/nvhe/switch.c +6
-0+ + val =read_sysreg_s (SYS_HFGWTR_EL2 ); + val &= ~(HFGxTR_EL2_nTPIDR_EL0_MASK | + HFGxTR_EL2_nSMPRI_EL1_MASK); +write_sysreg_s (val,SYS_HFGWTR_EL2 ); + }If the CPUs do not have FGT, what provides the equivalent trapping?
Nothing for nVHE mode.
Quoted 2 lines
If FGT is mandatory when SME exists, then you should simplify the condition.
OK, I'll remove the defensiveness here. FGT is mandatory from v8.6 and SME is a v9 feature so people shouldn't build a SME implementation that lacks FGT.
_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Marc Zyngier
maintainerRe: [PATCH v8 25/38] KVM: arm64: Trap SME usage in guest
Quoted 30 lines · Mark Brown
[1 <text/plain; us-ascii (7bit)>]
Quoted 8 lines · Marc Zyngier
Review
Quoted 1 line · Mark Brown
(quoted diff) +1
-0+ if (IS_ENABLED(CONFIG_ARM64_SME) && cpus_have_final_cap(ARM64_SME))Please drop the
IS_ENABLED(). We purposely avoid conditional compilation in KVM in order to avoid bitrot, and the amount of code you save isn't significant. Having a static key is more than enough to avoid runtime costs.Sure, I wanted to be extra careful here as this is all in hot paths and going to get moved elsewhere when we have real guest support.
Quoted 6 lines
Quoted 6 lines
arch/arm64/kvm/hyp/nvhe/switch.c +6
-0+if (IS_ENABLED (CONFIG_ARM64_SME ) &&cpus_have_final_cap (ARM64_SME ) && +cpus_have_final_cap (ARM64_HAS_FGT )) { + val =read_sysreg_s (SYS_HFGRTR_EL2 ); + val &= ~(HFGxTR_EL2_nTPIDR_EL0_MASK | + HFGxTR_EL2_nSMPRI_EL1_MASK); +write_sysreg_s (val,SYS_HFGRTR_EL2 );Quoted 8 lines
arch/arm64/kvm/hyp/nvhe/switch.c static void __activate_traps(struct kvm_vcpu *vcpu) · line 67
Quoted 6 lines
arch/arm64/kvm/hyp/nvhe/switch.c +6
-0+ + val =read_sysreg_s (SYS_HFGWTR_EL2 ); + val &= ~(HFGxTR_EL2_nTPIDR_EL0_MASK | + HFGxTR_EL2_nSMPRI_EL1_MASK); +write_sysreg_s (val,SYS_HFGWTR_EL2 ); + }If the CPUs do not have FGT, what provides the equivalent trapping?
Quoted 1 line
Nothing for nVHE mode.
That's what I feared.
Quoted 7 lines
Quoted 3 lines
If FGT is mandatory when SME exists, then you should simplify the condition.
OK, I'll remove the defensiveness here. FGT is mandatory from v8.6 and SME is a v9 feature so people shouldn't build a SME implementation that lacks FGT.
Can you then please make it that SME doesn't get enabled at all if FGT isn't present? It would also be good to have a clarification in the architecture that it isn't allowed to build SME without FGT (specially given that v9.0 is congruent to v8.5, and thus doesn't have FGT).
Thanks,
M.
Signature · 5 lines
Without deviation from the norm, progress is not possible. _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Re: [PATCH v8 25/38] KVM: arm64: Trap SME usage in guest
Quoted 10 lines · Marc Zyngier
Quoted 3 lines · Mark Brown
OK, I'll remove the defensiveness here. FGT is mandatory from v8.6 and SME is a v9 feature so people shouldn't build a SME implementation that lacks FGT.
Can you then please make it that SME doesn't get enabled at all if FGT isn't present? It would also be good to have a clarification in the architecture that it isn't allowed to build SME without FGT (specially given that v9.0 is congruent to v8.5, and thus doesn't have FGT).
Right, this should be handled by the time the full spec is published - it's an issue people are aware of and it's not something that should ever get built.
It would be good to explicitly handle the dependency in the cpufeature stuff, we'll have other issues like this, but I'd like to handle that separately since at first look doing it properly is a bit of surgery on cpufeature and the series is already rather large.
_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
kernel test robot
build botRe: [PATCH v8 25/38] KVM: arm64: Trap SME usage in guest
In reply to Mark BrownI love your patch! Perhaps something to improve:
Hi Mark,
I love your patch! Perhaps something to improve:
[auto build test WARNING on e783362eb54cd99b2cac8b3a9aeac942e6f6ac07]
url: https://github.com/0day-ci/linux/commits/Mark-Brown/arm64-sme-Initial-support-for-the-Scalable-Matrix-Extension/20220125-120723 base: e783362eb54cd99b2cac8b3a9aeac942e6f6ac07 config: arm64-randconfig-r033-20220124 (https://download.01.org/0day-ci/archive/20220125/202201252032.d2MrIFVb-lkp(a)intel.com/config) compiler: aarch64-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# https://github.com/0day-ci/linux/commit/35adc3582db36b4cefefdbdf3afa245a69e529ae
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Mark-Brown/arm64-sme-Initial-support-for-the-Scalable-Matrix-Extension/20220125-120723 git checkout 35adc3582db36b4cefefdbdf3afa245a69e529ae
# save the config file to linux build tree
mkdir build_dir
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=arm64 SHELL=/bin/bash arch/arm64/
If you fix the issue, kindly add following tag as appropriate
All warnings (new ones prefixed by >>):
In file included from arch/arm64/include/asm/cputype.h:148,
from arch/arm64/include/asm/cache.h:8,
from include/linux/cache.h:6,
from include/linux/printk.h:9,
from include/asm-generic/bug.h:22,
from arch/arm64/include/asm/bug.h:26,
from include/linux/bug.h:5,
from include/linux/mmdebug.h:5,
from include/linux/percpu.h:5,
from include/linux/context_tracking_state.h:5,
from include/linux/hardirq.h:5,
from include/linux/kvm_host.h:7,
from arch/arm64/include/asm/kvm_emulate.h:14,
from arch/arm64/kvm/hyp/include/hyp/adjust_pc.h:13,
from arch/arm64/kvm/hyp/include/hyp/switch.h:10,
from arch/arm64/kvm/hyp/nvhe/switch.c:7:
arch/arm64/kvm/hyp/nvhe/switch.c: In function '__activate_traps':
>> arch/arm64/include/asm/sysreg.h:1276:44: warning: left shift count >= width of type [-Wshift-count-overflow]
1276 | #define HFGxTR_EL2_nTPIDR_EL0_MASK (1 << HFGxTR_EL2_nTPIDR_EL0_SHIFT)
| ^~
arch/arm64/kvm/hyp/nvhe/switch.c:59:26: note: in expansion of macro 'HFGxTR_EL2_nTPIDR_EL0_MASK'
59 | val &= ~(HFGxTR_EL2_nTPIDR_EL0_MASK |
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
arch/arm64/include/asm/sysreg.h:1278:44: warning: left shift count >= width of type [-Wshift-count-overflow]
1278 | #define HFGxTR_EL2_nSMPRI_EL1_MASK (1 << HFGxTR_EL2_nSMPRI_EL1_SHIFT)
| ^~
arch/arm64/kvm/hyp/nvhe/switch.c:60:26: note: in expansion of macro 'HFGxTR_EL2_nSMPRI_EL1_MASK'
60 | HFGxTR_EL2_nSMPRI_EL1_MASK);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
>> arch/arm64/include/asm/sysreg.h:1276:44: warning: left shift count >= width of type [-Wshift-count-overflow]
1276 | #define HFGxTR_EL2_nTPIDR_EL0_MASK (1 << HFGxTR_EL2_nTPIDR_EL0_SHIFT)
| ^~
arch/arm64/kvm/hyp/nvhe/switch.c:64:26: note: in expansion of macro 'HFGxTR_EL2_nTPIDR_EL0_MASK'
64 | val &= ~(HFGxTR_EL2_nTPIDR_EL0_MASK |
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
arch/arm64/include/asm/sysreg.h:1278:44: warning: left shift count >= width of type [-Wshift-count-overflow]
1278 | #define HFGxTR_EL2_nSMPRI_EL1_MASK (1 << HFGxTR_EL2_nSMPRI_EL1_SHIFT)
| ^~
arch/arm64/kvm/hyp/nvhe/switch.c:65:26: note: in expansion of macro 'HFGxTR_EL2_nSMPRI_EL1_MASK'
65 | HFGxTR_EL2_nSMPRI_EL1_MASK);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
arch/arm64/kvm/hyp/nvhe/switch.c: In function '__deactivate_traps':
>> arch/arm64/include/asm/sysreg.h:1276:44: warning: left shift count >= width of type [-Wshift-count-overflow]
1276 | #define HFGxTR_EL2_nTPIDR_EL0_MASK (1 << HFGxTR_EL2_nTPIDR_EL0_SHIFT)
| ^~
arch/arm64/kvm/hyp/nvhe/switch.c:117:24: note: in expansion of macro 'HFGxTR_EL2_nTPIDR_EL0_MASK'
117 | val |= HFGxTR_EL2_nTPIDR_EL0_MASK | HFGxTR_EL2_nSMPRI_EL1_MASK;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
arch/arm64/include/asm/sysreg.h:1278:44: warning: left shift count >= width of type [-Wshift-count-overflow]
1278 | #define HFGxTR_EL2_nSMPRI_EL1_MASK (1 << HFGxTR_EL2_nSMPRI_EL1_SHIFT)
| ^~
arch/arm64/kvm/hyp/nvhe/switch.c:117:53: note: in expansion of macro 'HFGxTR_EL2_nSMPRI_EL1_MASK'
117 | val |= HFGxTR_EL2_nTPIDR_EL0_MASK | HFGxTR_EL2_nSMPRI_EL1_MASK;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
>> arch/arm64/include/asm/sysreg.h:1276:44: warning: left shift count >= width of type [-Wshift-count-overflow]
1276 | #define HFGxTR_EL2_nTPIDR_EL0_MASK (1 << HFGxTR_EL2_nTPIDR_EL0_SHIFT)
| ^~
arch/arm64/kvm/hyp/nvhe/switch.c:121:24: note: in expansion of macro 'HFGxTR_EL2_nTPIDR_EL0_MASK'
121 | val |= HFGxTR_EL2_nTPIDR_EL0_MASK | HFGxTR_EL2_nSMPRI_EL1_MASK;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
arch/arm64/include/asm/sysreg.h:1278:44: warning: left shift count >= width of type [-Wshift-count-overflow]
1278 | #define HFGxTR_EL2_nSMPRI_EL1_MASK (1 << HFGxTR_EL2_nSMPRI_EL1_SHIFT)
| ^~
arch/arm64/kvm/hyp/nvhe/switch.c:121:53: note: in expansion of macro 'HFGxTR_EL2_nSMPRI_EL1_MASK'
121 | val |= HFGxTR_EL2_nTPIDR_EL0_MASK | HFGxTR_EL2_nSMPRI_EL1_MASK;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
arch/arm64/kvm/hyp/nvhe/switch.c: At top level:
arch/arm64/kvm/hyp/nvhe/switch.c:227:43: warning: initialized field overwritten [-Woverride-init]
227 | [ESR_ELx_EC_CP15_32] = kvm_hyp_handle_cp15_32,
| ^~~~~~~~~~~~~~~~~~~~~~
arch/arm64/kvm/hyp/nvhe/switch.c:227:43: note: (near initialization for 'hyp_exit_handlers[3]')
arch/arm64/kvm/hyp/nvhe/switch.c:228:43: warning: initialized field overwritten [-Woverride-init]
228 | [ESR_ELx_EC_SYS64] = kvm_hyp_handle_sysreg,
| ^~~~~~~~~~~~~~~~~~~~~
arch/arm64/kvm/hyp/nvhe/switch.c:228:43: note: (near initialization for 'hyp_exit_handlers[24]')
arch/arm64/kvm/hyp/nvhe/switch.c:229:43: warning: initialized field overwritten [-Woverride-init]
229 | [ESR_ELx_EC_SVE] = kvm_hyp_handle_fpsimd,
| ^~~~~~~~~~~~~~~~~~~~~
arch/arm64/kvm/hyp/nvhe/switch.c:229:43: note: (near initialization for 'hyp_exit_handlers[25]')
arch/arm64/kvm/hyp/nvhe/switch.c:230:43: warning: initialized field overwritten [-Woverride-init]
230 | [ESR_ELx_EC_FP_ASIMD] = kvm_hyp_handle_fpsimd,
| ^~~~~~~~~~~~~~~~~~~~~
arch/arm64/kvm/hyp/nvhe/switch.c:230:43: note: (near initialization for 'hyp_exit_handlers[7]')
arch/arm64/kvm/hyp/nvhe/switch.c:231:43: warning: initialized field overwritten [-Woverride-init]
231 | [ESR_ELx_EC_IABT_LOW] = kvm_hyp_handle_iabt_low,
| ^~~~~~~~~~~~~~~~~~~~~~~
arch/arm64/kvm/hyp/nvhe/switch.c:231:43: note: (near initialization for 'hyp_exit_handlers[32]')
arch/arm64/kvm/hyp/nvhe/switch.c:232:43: warning: initialized field overwritten [-Woverride-init]
232 | [ESR_ELx_EC_DABT_LOW] = kvm_hyp_handle_dabt_low,
| ^~~~~~~~~~~~~~~~~~~~~~~
arch/arm64/kvm/hyp/nvhe/switch.c:232:43: note: (near initialization for 'hyp_exit_handlers[36]')
arch/arm64/kvm/hyp/nvhe/switch.c:233:43: warning: initialized field overwritten [-Woverride-init]
233 | [ESR_ELx_EC_PAC] = kvm_hyp_handle_ptrauth,
| ^~~~~~~~~~~~~~~~~~~~~~
arch/arm64/kvm/hyp/nvhe/switch.c:233:43: note: (near initialization for 'hyp_exit_handlers[9]')
arch/arm64/kvm/hyp/nvhe/switch.c:238:43: warning: initialized field overwritten [-Woverride-init]
238 | [ESR_ELx_EC_SYS64] = kvm_handle_pvm_sys64,
| ^~~~~~~~~~~~~~~~~~~~ arch/arm64/kvm/hyp/nvhe/switch.c:238:43: note: (near initialization for 'pvm_exit_handlers[24]') arch/arm64/kvm/hyp/nvhe/switch.c:239:43: warning: initialized field overwritten [-Woverride-init]
239 | [ESR_ELx_EC_SVE] = kvm_handle_pvm_restricted,
| ^~~~~~~~~~~~~~~~~~~~~~~~~
arch/arm64/kvm/hyp/nvhe/switch.c:239:43: note: (near initialization for 'pvm_exit_handlers[25]') arch/arm64/kvm/hyp/nvhe/switch.c:240:43: warning: initialized field overwritten [-Woverride-init]
240 | [ESR_ELx_EC_FP_ASIMD] = kvm_handle_pvm_fpsimd,
| ^~~~~~~~~~~~~~~~~~~~~
arch/arm64/kvm/hyp/nvhe/switch.c:240:43: note: (near initialization for 'pvm_exit_handlers[7]') arch/arm64/kvm/hyp/nvhe/switch.c:241:43: warning: initialized field overwritten [-Woverride-init]
241 | [ESR_ELx_EC_IABT_LOW] = kvm_hyp_handle_iabt_low,
| ^~~~~~~~~~~~~~~~~~~~~~~
arch/arm64/kvm/hyp/nvhe/switch.c:241:43: note: (near initialization for 'pvm_exit_handlers[32]') arch/arm64/kvm/hyp/nvhe/switch.c:242:43: warning: initialized field overwritten [-Woverride-init]
242 | [ESR_ELx_EC_DABT_LOW] = kvm_hyp_handle_dabt_low,
| ^~~~~~~~~~~~~~~~~~~~~~~
arch/arm64/kvm/hyp/nvhe/switch.c:242:43: note: (near initialization for 'pvm_exit_handlers[36]') arch/arm64/kvm/hyp/nvhe/switch.c:243:43: warning: initialized field overwritten [-Woverride-init]
243 | [ESR_ELx_EC_PAC] = kvm_hyp_handle_ptrauth,
| ^~~~~~~~~~~~~~~~~~~~~~
arch/arm64/kvm/hyp/nvhe/switch.c:243:43: note: (near initialization for 'pvm_exit_handlers[9]') arch/arm64/kvm/hyp/nvhe/switch.c:380:17: warning: no previous prototype for 'hyp_panic' [-Wmissing-prototypes]
380 | void __noreturn hyp_panic(void)
| ^~~~~~~~~
arch/arm64/kvm/hyp/nvhe/switch.c:402:17: warning: no previous prototype for 'kvm_unexpected_el2_exception' [-Wmissing-prototypes]
402 | asmlinkage void kvm_unexpected_el2_exception(void)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
vim +1276 arch/arm64/include/asm/sysreg.h
8a657f71705f9f Hector Martin 2021-03-01 1273 3574e3c8f58afa Mark Brown 2022-01-25 1274 /* HFG[WR]TR_EL2 bit definitions */ 3574e3c8f58afa Mark Brown 2022-01-25 1275 #define HFGxTR_EL2_nTPIDR_EL0_SHIFT 55 3574e3c8f58afa Mark Brown 2022-01-25 @1276 #define HFGxTR_EL2_nTPIDR_EL0_MASK (1 << HFGxTR_EL2_nTPIDR_EL0_SHIFT) 3574e3c8f58afa Mark Brown 2022-01-25 1277 #define HFGxTR_EL2_nSMPRI_EL1_SHIFT 54 3574e3c8f58afa Mark Brown 2022-01-25 1278 #define HFGxTR_EL2_nSMPRI_EL1_MASK (1 << HFGxTR_EL2_nSMPRI_EL1_SHIFT) 3574e3c8f58afa Mark Brown 2022-01-25 1279
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/[email protected]
PATCH v8 26/38 KVM: arm64: Handle SME host state when running guests
In reply to Mark BrownWhile we don't currently support SME in guests we do currently support it for the host system so we need to take care of SME's impact, including the floating point register state, when running guests. Simiarly to SVE we need to manage the traps in CPACR_RL1, what is new is the handling of streaming mode and ZA.
Normally we defer any handling of the floating point register state until the guest first uses it however if the system is in streaming mode FPSIMD and SVE operations may generate SME traps which we would need to distinguish from actual attempts by the guest to use SME. Rather than do this for the time being if we are in streaming mode when entering the guest we force the floating point state to be saved immediately and exit streaming mode, meaning that the guest won't generate SME traps for supported operations.
We could handle ZA in the access trap similarly to the FPSIMD/SVE state without the disruption caused by streaming mode but for simplicity handle it the same way as streaming mode for now.
This will be revisited when we support SME for guests (hopefully before SME hardware becomes available), for now it will only incur additional cost on systems with SME and even there only if streaming mode or ZA are enabled.
--- arch/arm64/include/asm/kvm_host.h | 1 + arch/arm64/kvm/fpsimd.c | 38 +++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+)
arch/arm64/include/asm/kvm_host.h +1 -0
@@ -438,6 +438,7 @@ struct kvm_vcpu_arch {#define KVM_ARM64_DEBUG_STATE_SAVE_SPE (1 << 12)/* Save SPE context if active */ #define KVM_ARM64_DEBUG_STATE_SAVE_TRBE (1 << 13)/* Save TRBE context if active */ #define KVM_ARM64_FP_FOREIGN_FPSTATE (1 << 14) +#define KVM_ARM64_HOST_SME_ENABLED (1 << 15)/* SME enabled for EL0 */ #define KVM_GUESTDBG_VALID_MASK (KVM_GUESTDBG_ENABLE | \ KVM_GUESTDBG_USE_SW_BP | \
arch/arm64/kvm/fpsimd.c +38 -0
@@ -82,6 +82,26 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)if (read_sysreg (cpacr_el1) &CPACR_EL1_ZEN_EL0EN ) vcpu->arch.flags |=KVM_ARM64_HOST_SVE_ENABLED ; + +/* +* We don't currently support SME guests but if we leave +* things in streaming mode then when the guest starts running +* FPSIMD or SVE code it may generate SME traps so as a +* special case if we are in streaming mode we force the host +* state to be saved now and exit streaming mode so that we +* don't have to handle any SME traps for valid guest +* operations. Do this for ZA as well for now for simplicity. +*/ +if (system_supports_sme ()) { +if (read_sysreg (cpacr_el1) &CPACR_EL1_SMEN_EL0EN ) + vcpu->arch.flags |=KVM_ARM64_HOST_SME_ENABLED ; + +if (read_sysreg_s (SYS_SVCR_EL0 ) & + (SYS_SVCR_EL0_SM_MASK |SYS_SVCR_EL0_ZA_MASK )) { + vcpu->arch.flags &= ~KVM_ARM64_FP_HOST ; +fpsimd_save_and_flush_cpu_state (); + } + } }void kvm_arch_vcpu_ctxflush_fp (struct kvm_vcpu *vcpu)
@@ -129,6 +149,24 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)local_irq_save (flags); +/* +* If we have VHE then the Hyp code will reset CPACR_EL1 to +* CPACR_EL1_DEFAULT and we need to reenable SME. +*/ +if (has_vhe ()) { +if (system_supports_sme ()) { +/* Also restore EL0 state seen on entry */ +if (vcpu->arch.flags &KVM_ARM64_HOST_SME_ENABLED ) +sysreg_clear_set (CPACR_EL1 ,0 , +CPACR_EL1_SMEN_EL0EN | +CPACR_EL1_SMEN_EL1EN ); +else +sysreg_clear_set (CPACR_EL1 , +CPACR_EL1_SMEN_EL0EN , +CPACR_EL1_SMEN_EL1EN ); + } + } +if (vcpu->arch.flags &KVM_ARM64_FP_ENABLED ) {if (vcpu_has_sve (vcpu)) {__vcpu_sys_reg (vcpu,ZCR_EL1 ) =read_sysreg_el1 (SYS_ZCR );
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Marc Zyngier
maintainerRe: [PATCH v8 26/38] KVM: arm64: Handle SME host state when running guests
Quoted 73 lines · Mark Brown
While we don't currently support SME in guests we do currently support it for the host system so we need to take care of SME's impact, including the floating point register state, when running guests. Simiarly to SVE we need to manage the traps in
CPACR_RL1, what is new is the handling of streaming mode and ZA.Normally we defer any handling of the floating point register state until the guest first uses it however if the system is in streaming mode FPSIMD and SVE operations may generate SME traps which we would need to distinguish from actual attempts by the guest to use SME. Rather than do this for the time being if we are in streaming mode when entering the guest we force the floating point state to be saved immediately and exit streaming mode, meaning that the guest won't generate SME traps for supported operations.
We could handle ZA in the access trap similarly to the FPSIMD/SVE state without the disruption caused by streaming mode but for simplicity handle it the same way as streaming mode for now.
This will be revisited when we support SME for guests (hopefully before SME hardware becomes available), for now it will only incur additional cost on systems with SME and even there only if streaming mode or ZA are enabled.
Signed-off-by Mark Brown <[email protected]>--- arch/arm64/include/asm/kvm_host.h | 1 + arch/arm64/kvm/fpsimd.c | 38 +++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+)arch/arm64/include/asm/kvm_host.h +1
-0@@ -438,6 +438,7 @@ struct kvm_vcpu_arch {#define KVM_ARM64_DEBUG_STATE_SAVE_SPE (1 << 12)/* Save SPE context if active */ #define KVM_ARM64_DEBUG_STATE_SAVE_TRBE (1 << 13)/* Save TRBE context if active */ #define KVM_ARM64_FP_FOREIGN_FPSTATE (1 << 14) +#define KVM_ARM64_HOST_SME_ENABLED (1 << 15)/* SME enabled for EL0 */ #define KVM_GUESTDBG_VALID_MASK (KVM_GUESTDBG_ENABLE | \ KVM_GUESTDBG_USE_SW_BP | \arch/arm64/kvm/fpsimd.c +20
-0@@ -82,6 +82,26 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)if (read_sysreg (cpacr_el1) &CPACR_EL1_ZEN_EL0EN ) vcpu->arch.flags |=KVM_ARM64_HOST_SVE_ENABLED ; + +/* +* We don't currently support SME guests but if we leave +* things in streaming mode then when the guest starts running +* FPSIMD or SVE code it may generate SME traps so as a +* special case if we are in streaming mode we force the host +* state to be saved now and exit streaming mode so that we +* don't have to handle any SME traps for valid guest +* operations. Do this for ZA as well for now for simplicity. +*/ +if (system_supports_sme ()) { +if (read_sysreg (cpacr_el1) &CPACR_EL1_SMEN_EL0EN ) + vcpu->arch.flags |=KVM_ARM64_HOST_SME_ENABLED ; + +if (read_sysreg_s (SYS_SVCR_EL0 ) & + (SYS_SVCR_EL0_SM_MASK |SYS_SVCR_EL0_ZA_MASK )) { + vcpu->arch.flags &= ~KVM_ARM64_FP_HOST ; +fpsimd_save_and_flush_cpu_state (); + } + } }void kvm_arch_vcpu_ctxflush_fp (struct kvm_vcpu *vcpu)
arch/arm64/kvm/fpsimd.c void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu) · line 157
Quoted 9 lines
arch/arm64/kvm/fpsimd.c +6
-0@@ -129,6 +149,24 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)local_irq_save (flags); +/* +* If we have VHE then the Hyp code will reset CPACR_EL1 to +* CPACR_EL1_DEFAULT and we need to reenable SME. +*/ +if (has_vhe ()) { +if (system_supports_sme ()) {
nit: if (has_vhe() && system_supports_sme()) {
saves you one level of indentation.
arch/arm64/kvm/fpsimd.c void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu) · line 166
Quoted 9 lines
arch/arm64/kvm/fpsimd.c +9
-0+/* Also restore EL0 state seen on entry */ +if (vcpu->arch.flags &KVM_ARM64_HOST_SME_ENABLED ) +sysreg_clear_set (CPACR_EL1 ,0 , +CPACR_EL1_SMEN_EL0EN | +CPACR_EL1_SMEN_EL1EN ); +else +sysreg_clear_set (CPACR_EL1 , +CPACR_EL1_SMEN_EL0EN , +CPACR_EL1_SMEN_EL1EN );
I find the use of CPACR_EL1_SMEN in some cases and its individual bits in some others pretty confusing. I understand that you have modelled it after the SVE code, but maybe this is a mistake we don't need to repeat. I'd be in favour of directly exposing the individual bits in all cases.
Thanks,
M.
Signature · 5 lines
Without deviation from the norm, progress is not possible. _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Re: [PATCH v8 26/38] KVM: arm64: Handle SME host state when running guests
Quoted 8 lines · Marc Zyngier
arch/arm64/kvm/fpsimd.c void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu) · line 157
Quoted 2 lines · Mark Brown
arch/arm64/kvm/fpsimd.c +2
-0+if (has_vhe ()) { +if (system_supports_sme ()) {nit: if (
has_vhe()&&system_supports_sme()) {saves you one level of indentation.
Yes, for now. IIRC there was some other stuff there when I had some of the code for doing the register switching properly.
Quoted 7 lines
Quoted 7 lines
arch/arm64/kvm/fpsimd.c +7
-0+/* Also restore EL0 state seen on entry */ +if (vcpu->arch.flags &KVM_ARM64_HOST_SME_ENABLED ) +sysreg_clear_set (CPACR_EL1 ,0 , +CPACR_EL1_SMEN_EL0EN | +CPACR_EL1_SMEN_EL1EN ); +else + sysreg_clear_set(CPACR_EL1,
Quoted 8 lines
arch/arm64/kvm/fpsimd.c void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu) · line 166
Quoted 2 lines
arch/arm64/kvm/fpsimd.c +2
-0+CPACR_EL1_SMEN_EL0EN , + CPACR_EL1_SMEN_EL1EN);I find the use of
CPACR_EL1_SMENin some cases and its individual bits in some others pretty confusing. I understand that you have modelled it after the SVE code, but maybe this is a mistake we don't need to repeat. I'd be in favour of directly exposing the individual bits in all cases.
OK, it is just the KVM code that uses the plain ZEN. I'll add a cleanup patch for that at the start of the series for ZEN I guess otherwise it looks worse, though that will inflate the size of the series a bit.
_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Marc Zyngier
maintainerRe: [PATCH v8 26/38] KVM: arm64: Handle SME host state when running guests
Quoted 31 lines · Mark Brown
[1 <text/plain; us-ascii (7bit)>]
Quoted 8 lines · Marc Zyngier
arch/arm64/kvm/fpsimd.c void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu) · line 157
Quoted 2 lines · Mark Brown
arch/arm64/kvm/fpsimd.c +2
-0+if (has_vhe ()) { +if (system_supports_sme ()) {nit: if (
has_vhe()&&system_supports_sme()) {saves you one level of indentation.
Yes, for now. IIRC there was some other stuff there when I had some of the code for doing the register switching properly.
Quoted 7 lines
Quoted 7 lines
arch/arm64/kvm/fpsimd.c +7
-0+/* Also restore EL0 state seen on entry */ +if (vcpu->arch.flags &KVM_ARM64_HOST_SME_ENABLED ) +sysreg_clear_set (CPACR_EL1 ,0 , +CPACR_EL1_SMEN_EL0EN | +CPACR_EL1_SMEN_EL1EN ); +else + sysreg_clear_set(CPACR_EL1,Quoted 8 lines
arch/arm64/kvm/fpsimd.c void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu) · line 166
Quoted 2 lines
arch/arm64/kvm/fpsimd.c +2
-0+CPACR_EL1_SMEN_EL0EN , + CPACR_EL1_SMEN_EL1EN);I find the use of
CPACR_EL1_SMENin some cases and its individual bits in some others pretty confusing. I understand that you have modelled it after the SVE code, but maybe this is a mistake we don't need to repeat. I'd be in favour of directly exposing the individual bits in all cases.
Quoted 3 lines
OK, it is just the KVM code that uses the plain ZEN. I'll add a cleanup patch for that at the start of the series for ZEN I guess otherwise it looks worse, though that will inflate the size of the series a bit.
I'm happy to merge such a patch early if that helps.
M.
Signature · 5 lines
Without deviation from the norm, progress is not possible. _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Re: [PATCH v8 26/38] KVM: arm64: Handle SME host state when running guests
Quoted 8 lines · Marc Zyngier
Quoted 5 lines · Mark Brown
Quoted 5 lines
I find the use of
CPACR_EL1_SMENin some cases and its individual bits in some others pretty confusing. I understand that you have modelled it after the SVE code, but maybe this is a mistake we don't need to repeat. I'd be in favour of directly exposing the individual bits in all cases.
Quoted 5 lines
Quoted 3 lines
OK, it is just the KVM code that uses the plain ZEN. I'll add a cleanup patch for that at the start of the series for ZEN I guess otherwise it looks worse, though that will inflate the size of the series a bit.
I'm happy to merge such a patch early if that helps.
That'd be good. There's also similar stuff going on with FPEN BTW (which is I imagine where the SVE stuff came from).
_______________________________________________
kvmarm mailing list
[email protected]
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 27/38 arm64/sme: Provide Kconfig for SME
In reply to Mark BrownNow that basline support for the Scalable Matrix Extension (SME) is present introduce the Kconfig option allowing it to be built. While the feature registers don't impose a strong requirement for a system with SME to support SVE at runtime the support for streaming mode SVE is mostly shared with normal SVE so depend on SVE.
--- arch/arm64/Kconfig | 11 +++++++++++ 1 file changed, 11 insertions(+)
arch/arm64/Kconfig +11 -0
@@ -1839,6 +1839,17 @@ config ARM64_SVE booting the kernel. If unsure and you are not observing these symptoms, you should assume that it is safe to say Y. +config ARM64_SME + bool "ARM Scalable Matrix Extension support" + default y + depends on ARM64_SVE + help + The Scalable Matrix Extension (SME) is an extension to the AArch64 + execution state which utilises a substantial subset of the SVE + instruction set, together with the addition of new architectural + register state capable of holding two dimensional matrix tiles to + enable various matrix operations. + config ARM64_MODULE_PLTS bool "Use PLTs to allow module memory to spill over into vmalloc area" depends on MODULES
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 28/38 kselftest/arm64: sme: Add streaming SME support to vlset
In reply to Mark BrownThe Scalable Matrix Extenions (SME) introduces additional register state with configurable vector lengths, similar to SVE but configured separately. Extend vlset to support configuring this state with a --sme or -s command line option.
--- tools/testing/selftests/arm64/fp/vlset.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
tools/testing/selftests/arm64/fp/vlset.c +8 -2
@@ -22,12 +22,15 @@ static int inherit = 0;static int no_inherit =0 ;static int force =0 ;static unsigned long vl; +static int set_ctl =PR_SVE_SET_VL ; +static int get_ctl =PR_SVE_GET_VL ;static const struct option options[] = { {"force" , no_argument,NULL ,'f' }, {"inherit" , no_argument,NULL ,'i' }, {"max" , no_argument,NULL ,'M' }, {"no-inherit" , no_argument, &no_inherit,1 }, + {"sme" , no_argument,NULL ,'s' }, {"help" , no_argument,NULL ,'?' }, {} };
@@ -50,6 +53,9 @@ static int parse_options(int argc, char **argv)case 'M' : vl =SVE_VL_MAX ;break ;case 'f' : force =1 ;break ;case 'i' : inherit =1 ;break ; +case 's' : set_ctl =PR_SME_SET_VL ; + get_ctl =PR_SME_GET_VL ; +break ;case 0 :break ;default : goto error; }
@@ -125,14 +131,14 @@ int main(int argc, char **argv)if (inherit) flags |=PR_SVE_VL_INHERIT ; - t =prctl (PR_SVE_SET_VL , vl | flags); + t =prctl (set_ctl, vl | flags);if (t <0 ) {fprintf (stderr,"%s: PR_SVE_SET_VL: %s\n" , program_name,strerror (errno)); goto error; } - t =prctl (PR_SVE_GET_VL ); + t =prctl (get_ctl);if (t ==-1 ) {fprintf (stderr,"%s: PR_SVE_GET_VL: %s\n" , program_name,strerror (errno));
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 29/38 kselftest/arm64: Add tests for TPIDR2
In reply to Mark BrownThe Scalable Matrix Extension adds a new system register TPIDR2 intended to be used by libc for its own thread specific use, add some kselftests which exercise the ABI for it.
Since this test should with some adjustment work for TPIDR and any other similar registers added in future add tests for it in a separate directory rather than placing it with the other floating point tests, nothing existing looked suitable so I created a new test directory called "abi".
Since this feature is intended to be used by libc the test is built as freestanding code using nolibc so we don't end up with the test program and libc both trying to manage the register simultaneously and distrupting each other. As a result of being written using nolibc rather than using hwcaps to identify if SME is available in the system we check for the default SME vector length configuration in proc, adding hwcap support to nolibc seems like disproportionate effort and didn't feel entirely idiomatic for what nolibc is trying to do.
--- tools/testing/selftests/arm64/abi/.gitignore | 1 + tools/testing/selftests/arm64/abi/Makefile | 9 +- tools/testing/selftests/arm64/abi/tpidr2.c | 298 +++++++++++++++++++ 3 files changed, 307 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/arm64/abi/tpidr2.c
tools/testing/selftests/arm64/abi/.gitignore +1 -0
@@ -1 +1,2 @@ syscall-abi +tpidr2
tools/testing/selftests/arm64/abi/Makefile +8 -1
@@ -1,8 +1,15 @@ # SPDX-License-Identifier: GPL-2.0 # Copyright (C) 2021 ARM Limited -TEST_GEN_PROGS := syscall-abi +TEST_GEN_PROGS := syscall-abi tpidr2 include ../../lib.mk $(OUTPUT)/syscall-abi: syscall-abi.c syscall-abi-asm.S + +# Build with nolibc since TPIDR2 is intended to be actively managed by +# libc and we're trying to test the functionality that it depends on here. +$(OUTPUT)/tpidr2: tpidr2.c + $(CC) -fno-asynchronous-unwind-tables -fno-ident -s -Os -nostdlib \ + -static -include ../../../../include/nolibc/nolibc.h \ + -ffreestanding -Wall $^ -o $@ -lgcc
tools/testing/selftests/arm64/abi/tpidr2.c new file +298 -0
298 lines not on this page · raw message
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 30/38 kselftest/arm64: Extend vector configuration API tests to cover SME
In reply to Mark BrownProvide RDVL helpers for SME and extend the main vector configuration tests to cover SME.
--- tools/testing/selftests/arm64/fp/.gitignore | 1 + tools/testing/selftests/arm64/fp/Makefile | 3 ++- tools/testing/selftests/arm64/fp/rdvl-sme.c | 14 ++++++++++++++ tools/testing/selftests/arm64/fp/rdvl.S | 8 ++++++++ tools/testing/selftests/arm64/fp/rdvl.h | 1 + tools/testing/selftests/arm64/fp/vec-syscfg.c | 10 ++++++++++ 6 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/arm64/fp/rdvl-sme.c
tools/testing/selftests/arm64/fp/.gitignore +1 -0
@@ -1,5 +1,6 @@ fp-pidbench fpsimd-test +rdvl-sme rdvl-sve sve-probe-vls sve-ptrace
tools/testing/selftests/arm64/fp/Makefile +2 -1
@@ -3,7 +3,7 @@ CFLAGS += -I../../../../../usr/include/ TEST_GEN_PROGS := sve-ptrace sve-probe-vls vec-syscfg TEST_PROGS_EXTENDED := fp-pidbench fpsimd-test fpsimd-stress \ - rdvl-sve \ + rdvl-sme rdvl-sve \ sve-test sve-stress \ vlset
@@ -13,6 +13,7 @@ fp-pidbench: fp-pidbench.S asm-utils.o $(CC) -nostdlib $^ -o $@ fpsimd-test: fpsimd-test.o asm-utils.o $(CC) -nostdlib $^ -o $@ +rdvl-sme: rdvl-sme.o rdvl.o rdvl-sve: rdvl-sve.o rdvl.o sve-ptrace: sve-ptrace.o sve-probe-vls: sve-probe-vls.o rdvl.o
tools/testing/selftests/arm64/fp/rdvl-sme.c new file +14 -0
@@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include <stdio.h> + +#include "rdvl.h" + +int main (void ) +{ +int vl =rdvl_sme (); + +printf ("%d\n" , vl); + +return 0 ; +}
tools/testing/selftests/arm64/fp/rdvl.S +8 -0
@@ -8,3 +8,11 @@ rdvl_sve: hint 34 // BTI C rdvl x0, #1 ret + +.globl rdvl_sme +rdvl_sme: + hint 34 // BTI C + + .inst 0x4bf5820 // RDSVL x0, #1 + + ret
tools/testing/selftests/arm64/fp/rdvl.h +1 -0
@@ -3,6 +3,7 @@#ifndef RDVL_H #define RDVL_H +int rdvl_sme (void );int rdvl_sve (void );#endif
tools/testing/selftests/arm64/fp/vec-syscfg.c +10 -0
@@ -51,6 +51,16 @@ static struct vec_data vec_data[] = { .prctl_set = PR_SVE_SET_VL, .default_vl_file = "/proc/sys/abi/sve_default_vector_length", }, + { + .name = "SME", + .hwcap_type = AT_HWCAP2, + .hwcap = HWCAP2_SME, + .rdvl = rdvl_sme, + .rdvl_binary = "./rdvl-sme", + .prctl_get = PR_SME_GET_VL, + .prctl_set = PR_SME_SET_VL, + .default_vl_file = "/proc/sys/abi/sme_default_vector_length", + }, };static int stdio_read_integer (FILE *f,const char *what,int *val)
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 31/38 kselftest/arm64: sme: Provide streaming mode SVE stress test
In reply to Mark BrownOne of the features of SME is the addition of streaming mode, in which we have access to a set of streaming mode SVE registers at the SME vector length. Since these are accessed using the SVE instructions let's reuse the existing SVE stress test for testing with a compile time option for controlling the few small differences needed:
- Enter streaming mode immediately on starting the program.
- In streaming mode FFR is removed so skip reading and writing FFR.
In order to avoid requiring a cutting edge toolchain with SME support use the op/CR form for specifying SVCR.
--- tools/testing/selftests/arm64/fp/.gitignore | 1 + tools/testing/selftests/arm64/fp/Makefile | 3 + tools/testing/selftests/arm64/fp/ssve-stress | 59 ++++++++++++++++++++ tools/testing/selftests/arm64/fp/sve-test.S | 30 ++++++++++ 4 files changed, 93 insertions(+) create mode 100644 tools/testing/selftests/arm64/fp/ssve-stress
tools/testing/selftests/arm64/fp/.gitignore +1 -0
@@ -5,5 +5,6 @@ rdvl-sve sve-probe-vls sve-ptrace sve-test +ssve-test vec-syscfg vlset
tools/testing/selftests/arm64/fp/Makefile +3 -0
@@ -5,6 +5,7 @@ TEST_GEN_PROGS := sve-ptrace sve-probe-vls vec-syscfg TEST_PROGS_EXTENDED := fp-pidbench fpsimd-test fpsimd-stress \ rdvl-sme rdvl-sve \ sve-test sve-stress \ + ssve-test ssve-stress \ vlset all: $(TEST_GEN_PROGS) $(TEST_PROGS_EXTENDED)
@@ -19,6 +20,8 @@ sve-ptrace: sve-ptrace.o sve-probe-vls: sve-probe-vls.o rdvl.o sve-test: sve-test.o asm-utils.o $(CC) -nostdlib $^ -o $@ +ssve-test: sve-test.S asm-utils.o + $(CC) -DSSVE -nostdlib $^ -o $@ vec-syscfg: vec-syscfg.o rdvl.o vlset: vlset.o
tools/testing/selftests/arm64/fp/ssve-stress new file +59 -0
59 lines not on this page · raw message
tools/testing/selftests/arm64/fp/sve-test.S +30 -0
@@ -156,6 +156,7 @@ endfunction // We fill the upper lanes of FFR with zeros. // Beware: corrupts P0. function setup_ffr +#ifndef SSVE mov x4, x30 and w0, w0, #0x3
@@ -178,6 +179,9 @@ function setup_ffr wrffr p0.b ret x4 +#else + ret +#endif endfunction // Trivial memory compare: compare x2 bytes starting at address x0 with
@@ -260,6 +264,7 @@ endfunction // Beware -- corrupts P0. // Clobbers x0-x5. function check_ffr +#ifndef SSVE mov x3, x30 ldr x4, =scratch
@@ -280,6 +285,9 @@ function check_ffr mov x2, x5 mov x30, x3 b memcmp +#else + ret +#endif endfunction // Any SVE register modified here can cause corruption in the main
@@ -295,13 +303,26 @@ function irritator_handler movi v0.8b, #1 movi v9.16b, #2 movi v31.8b, #3 +#ifndef SSVE // And P0 rdffr p0.b // And FFR wrffr p15.b +#endif + + ret +endfunction + +#ifdef SSVE +function enable_sm + // Set SVCR.SM to 1, equivalent to SMSTART SM but doesn't need a + // SME capable toolchain. + mov x0, #1 + msr S3_3_C4_C2_2, x0 ret endfunction +#endif function terminate_handler mov w21, w0
@@ -359,6 +380,11 @@ endfunction .globl _start function _start _start: +#ifdef SSVE + puts "Streaming mode " + bl enable_sm +#endif + // Sanity-check and report the vector length rdvl x19, #8
@@ -407,6 +433,10 @@ _start: orr w2, w2, #SA_NODEFER bl setsignal +#ifdef SSVE + bl enable_sm // syscalls will have exited streaming mode +#endif + mov x22, #0 // generation number, increments per iteration .Ltest_loop: rdvl x0, #8
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 32/38 kselftest/arm64: signal: Allow tests to be incompatible with features
In reply to Mark BrownSome features may invalidate some tests, for example by supporting an operation which would trap otherwise. Allow tests to list features that they are incompatible with so we can cover the case where a signal will be generated without disruption on systems where that won't happen.
--- .../selftests/arm64/signal/test_signals.h | 1 + .../arm64/signal/test_signals_utils.c | 34 ++++++++++++++----- .../arm64/signal/test_signals_utils.h | 2 ++ 3 files changed, 28 insertions(+), 9 deletions(-)
tools/testing/selftests/arm64/signal/test_signals.h +1 -0
@@ -53,6 +53,7 @@ struct tdescr {char *name;char *descr;unsigned long feats_required; +unsigned long feats_incompatible;/* bitmask of effectively supported feats: populated at run-time */ unsigned long feats_supported;bool initialized;
tools/testing/selftests/arm64/signal/test_signals_utils.c +25 -9
@@ -36,6 +36,8 @@ static inline char *feats_to_string(unsigned long feats) {size_t flen =MAX_FEATS_SZ -1 ; + feats_string[0 ] ='\0' ; +for (int i =0 ; i <FMAX_END ; i++) {if (feats & (1UL << i)) {size_t tlen =strlen (feats_names[i]);
@@ -256,7 +258,7 @@ int test_init(struct tdescr *td) td->minsigstksz =MINSIGSTKSZ ;fprintf (stderr,"Detected MINSTKSIGSZ:%d\n" , td->minsigstksz); -if (td->feats_required) { +if (td->feats_required || td->feats_incompatible) { td->feats_supported =0 ;/* * Checking for CPU required features using both the
@@ -267,15 +269,29 @@ int test_init(struct tdescr *td)if (getauxval (AT_HWCAP ) &HWCAP_SVE ) td->feats_supported |=FEAT_SVE ;if (feats_ok (td)) { -fprintf (stderr, -"Required Features: [%s] supported\n" , -feats_to_string (td->feats_required & - td->feats_supported)); +if (td->feats_required & td->feats_supported) +fprintf (stderr, +"Required Features: [%s] supported\n" , +feats_to_string (td->feats_required & + td->feats_supported)); +if (!(td->feats_incompatible & td->feats_supported)) +fprintf (stderr, +"Incompatible Features: [%s] absent\n" , +feats_to_string (td->feats_incompatible)); }else { -fprintf (stderr, -"Required Features: [%s] NOT supported\n" , -feats_to_string (td->feats_required & - ~td->feats_supported)); +if ((td->feats_required & td->feats_supported) != + td->feats_supported) +fprintf (stderr, +"Required Features: [%s] NOT supported\n" , +feats_to_string (td->feats_required & + ~td->feats_supported)); +if (td->feats_incompatible & td->feats_supported) +fprintf (stderr, +"Incompatible Features: [%s] supported\n" , +feats_to_string (td->feats_incompatible & + ~td->feats_supported)); + + td->result =KSFT_SKIP ;return 0 ; }
tools/testing/selftests/arm64/signal/test_signals_utils.h +2 -0
@@ -18,6 +18,8 @@ void test_result(struct tdescr *td);static inline bool feats_ok (struct tdescr *td) { +if (td->feats_incompatible & td->feats_supported) +return false;return (td->feats_required & td->feats_supported) == td->feats_required; }
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 33/38 kselftest/arm64: signal: Handle ZA signal context in core code
In reply to Mark BrownAs part of the generic code for signal handling test cases we parse all signal frames to make sure they have at least the basic form we expect and that there are no unexpected frames present in the signal context. Add coverage of the ZA signal frame to this code.
--- .../arm64/signal/testcases/testcases.c | 36 +++++++++++++++++++ .../arm64/signal/testcases/testcases.h | 3 +- 2 files changed, 38 insertions(+), 1 deletion(-)
tools/testing/selftests/arm64/signal/testcases/testcases.c +36 -0
@@ -75,6 +75,31 @@ bool validate_sve_context(struct sve_context *sve, char **err)return true; } +bool validate_za_context (struct za_context *za,char **err) +{ +/* Size will be rounded up to a multiple of 16 bytes */ +size_t regs_size + = ((ZA_SIG_CONTEXT_SIZE (sve_vq_from_vl (za->vl)) +15 ) /16 ) *16 ; + +if (!za || !err) +return false; + +/* Either a bare za_context or a za_context followed by regs data */ +if ((za->head.size !=sizeof (struct za_context )) && + (za->head.size != regs_size)) { + *err ="bad size for ZA context" ; +return false; + } + +if (!sve_vl_valid (za->vl)) { + *err ="SME VL in ZA context invalid" ; + +return false; + } + +return true; +} +bool validate_reserved (ucontext_t *uc,size_t resv_sz,char **err) {bool terminated = false;
@@ -82,6 +107,7 @@ bool validate_reserved(ucontext_t *uc, size_t resv_sz, char **err)int flags =0 ;struct extra_context *extra =NULL ;struct sve_context *sve =NULL ; +struct za_context *za =NULL ;struct _aarch64_ctx *head = (struct _aarch64_ctx *)uc->uc_mcontext.__reserved;
@@ -120,6 +146,13 @@ bool validate_reserved(ucontext_t *uc, size_t resv_sz, char **err) sve = (struct sve_context *)head; flags |=SVE_CTX ;break ; +case ZA_MAGIC : +if (flags &ZA_CTX ) + *err ="Multiple ZA_MAGIC" ; +/* Size is validated in validate_za_context() */ + za = (struct za_context *)head; + flags |=ZA_CTX ; +break ;case EXTRA_MAGIC :if (flags &EXTRA_CTX ) *err ="Multiple EXTRA_MAGIC" ;
@@ -165,6 +198,9 @@ bool validate_reserved(ucontext_t *uc, size_t resv_sz, char **err)if (flags &SVE_CTX )if (!validate_sve_context (sve, err))return false; +if (flags &ZA_CTX ) +if (!validate_za_context (za, err)) +return false; head =GET_RESV_NEXT_HEAD (head); }
tools/testing/selftests/arm64/signal/testcases/testcases.h +2 -1
@@ -16,7 +16,8 @@#define FPSIMD_CTX (1 << 0)#define SVE_CTX (1 << 1) -#define EXTRA_CTX (1 << 2) +#define ZA_CTX (1 << 2) +#define EXTRA_CTX (1 << 3)#define KSFT_BAD_MAGIC 0xdeadbeef
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 34/38 kselftest/arm64: Add stress test for SME ZA context switching
In reply to Mark BrownAdd a stress test for context switching of the ZA register state based on the similar tests Dave Martin wrote for FPSIMD and SVE registers. The test loops indefinitely writing a data pattern to ZA then reading it back and verifying that it's what was expected.
Unlike the other tests we manually assemble the SME instructions since at present no released toolchain has SME support integrated.
--- tools/testing/selftests/arm64/fp/.gitignore | 1 + tools/testing/selftests/arm64/fp/Makefile | 3 + tools/testing/selftests/arm64/fp/za-stress | 59 +++ tools/testing/selftests/arm64/fp/za-test.S | 426 ++++++++++++++++++++ 4 files changed, 489 insertions(+) create mode 100644 tools/testing/selftests/arm64/fp/za-stress create mode 100644 tools/testing/selftests/arm64/fp/za-test.S
tools/testing/selftests/arm64/fp/.gitignore +1 -0
@@ -8,3 +8,4 @@ sve-test ssve-test vec-syscfg vlset +za-test
tools/testing/selftests/arm64/fp/Makefile +3 -0
@@ -6,6 +6,7 @@ TEST_PROGS_EXTENDED := fp-pidbench fpsimd-test fpsimd-stress \ rdvl-sme rdvl-sve \ sve-test sve-stress \ ssve-test ssve-stress \ + za-test za-stress \ vlset all: $(TEST_GEN_PROGS) $(TEST_PROGS_EXTENDED)
@@ -24,5 +25,7 @@ ssve-test: sve-test.S asm-utils.o $(CC) -DSSVE -nostdlib $^ -o $@ vec-syscfg: vec-syscfg.o rdvl.o vlset: vlset.o +za-test: za-test.o asm-utils.o + $(CC) -nostdlib $^ -o $@ include ../../lib.mk
tools/testing/selftests/arm64/fp/za-stress new file +59 -0
59 lines not on this page · raw message
tools/testing/selftests/arm64/fp/za-test.S new file +426 -0
426 lines not on this page · raw message
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 35/38 kselftest/arm64: signal: Add SME signal handling tests
In reply to Mark BrownAdd test cases for the SME signal handing ABI patterned off the SVE tests. Due to the small size of the tests and the differences in ABI (especially around needing to account for both streaming SVE and ZA) there is some code duplication here.
We currently cover:
- Reporting of the vector length.
- Lack of support for changing vector length.
- Presence and size of register state for streaming SVE and ZA.
As with the SVE tests we do not yet have any validation of register contents.
--- .../testing/selftests/arm64/signal/.gitignore | 2 + .../selftests/arm64/signal/test_signals.h | 4 + .../arm64/signal/test_signals_utils.c | 6 + .../testcases/fake_sigreturn_sme_change_vl.c | 92 +++++++++++++ .../arm64/signal/testcases/sme_trap_no_sm.c | 38 ++++++ .../signal/testcases/sme_trap_non_streaming.c | 45 ++++++ .../arm64/signal/testcases/sme_trap_za.c | 36 +++++ .../selftests/arm64/signal/testcases/sme_vl.c | 68 +++++++++ .../arm64/signal/testcases/ssve_regs.c | 129 ++++++++++++++++++ 9 files changed, 420 insertions(+) create mode 100644 tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sme_change_vl.c create mode 100644 tools/testing/selftests/arm64/signal/testcases/sme_trap_no_sm.c create mode 100644 tools/testing/selftests/arm64/signal/testcases/sme_trap_non_streaming.c create mode 100644 tools/testing/selftests/arm64/signal/testcases/sme_trap_za.c create mode 100644 tools/testing/selftests/arm64/signal/testcases/sme_vl.c create mode 100644 tools/testing/selftests/arm64/signal/testcases/ssve_regs.c
tools/testing/selftests/arm64/signal/.gitignore +2 -0
@@ -1,5 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only mangle_* fake_sigreturn_* +sme_* +ssve_* sve_* !*.[ch]
tools/testing/selftests/arm64/signal/test_signals.h +4 -0
@@ -34,11 +34,15 @@enum {FSSBS_BIT ,FSVE_BIT , +FSME_BIT , +FSME_FA64_BIT ,FMAX_END };#define FEAT_SSBS (1UL << FSSBS_BIT)#define FEAT_SVE (1UL << FSVE_BIT) +#define FEAT_SME (1UL << FSME_BIT) +#define FEAT_SME_FA64 (1UL << FSME_FA64_BIT)/* * A descriptor used to describe and configure a test case.
tools/testing/selftests/arm64/signal/test_signals_utils.c +6 -0
@@ -27,6 +27,8 @@ static int sig_copyctx = SIGTRAP;static char const *const feats_names[FMAX_END ] = {" SSBS " ," SVE " , +" SME " , +" FA64 " , };#define MAX_FEATS_SZ 128
@@ -268,6 +270,10 @@ int test_init(struct tdescr *td) td->feats_supported |=FEAT_SSBS ;if (getauxval (AT_HWCAP ) &HWCAP_SVE ) td->feats_supported |=FEAT_SVE ; +if (getauxval (AT_HWCAP2 ) &HWCAP2_SME ) + td->feats_supported |=FEAT_SME ; +if (getauxval (AT_HWCAP2 ) &HWCAP2_SME_FA64 ) + td->feats_supported |=FEAT_SME_FA64 ;if (feats_ok (td)) {if (td->feats_required & td->feats_supported) fprintf(stderr,
tools/testing/selftests/arm64/signal/testcases/fake_sigreturn_sme_change_vl.c new file +92 -0
92 lines not on this page · raw message
tools/testing/selftests/arm64/signal/testcases/sme_trap_no_sm.c new file +38 -0
@@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Copyright (C) 2021 ARM Limited +* +* Verify that using a streaming mode instruction without enabling it +* generates a SIGILL. +*/ + +#include <signal.h> +#include <ucontext.h> +#include <sys/prctl.h> + +#include "test_signals_utils.h" +#include "testcases.h" + +int sme_trap_no_sm_trigger (struct tdescr *td) +{ +/* SMSTART ZA ; ADDHA ZA0.S, P0/M, P0/M, Z0.S */ + asmvolatile (".inst 0xd503457f ; .inst 0xc0900000" ); + +return 0 ; +} + +int sme_trap_no_sm_run (struct tdescr *td,siginfo_t *si,ucontext_t *uc) +{ +return 1 ; +} + +struct tdescr tde = { + .name ="SME trap without SM" , + .descr ="Check that we get a SIGILL if we use streaming mode without enabling it" , + .timeout =3 , + .feats_required =FEAT_SME ,/* We need a SMSTART ZA */ + .sanity_disabled = true, + .trigger = sme_trap_no_sm_trigger, + .run = sme_trap_no_sm_run, + .sig_ok =SIGILL , +};
tools/testing/selftests/arm64/signal/testcases/sme_trap_non_streaming.c new file +45 -0
45 lines not on this page · raw message
tools/testing/selftests/arm64/signal/testcases/sme_trap_za.c new file +36 -0
@@ -0,0 +1,36 @@ +// SPDX-License-Identifier: GPL-2.0 +/* +* Copyright (C) 2021 ARM Limited +* +* Verify that accessing ZA without enabling it generates a SIGILL. +*/ + +#include <signal.h> +#include <ucontext.h> +#include <sys/prctl.h> + +#include "test_signals_utils.h" +#include "testcases.h" + +int sme_trap_za_trigger (struct tdescr *td) +{ +/* ZERO ZA */ + asmvolatile (".inst 0xc00800ff" ); + +return 0 ; +} + +int sme_trap_za_run (struct tdescr *td,siginfo_t *si,ucontext_t *uc) +{ +return 1 ; +} + +struct tdescr tde = { + .name ="SME ZA trap" , + .descr ="Check that we get a SIGILL if we access ZA without enabling" , + .timeout =3 , + .sanity_disabled = true, + .trigger = sme_trap_za_trigger, + .run = sme_trap_za_run, + .sig_ok =SIGILL , +};
tools/testing/selftests/arm64/signal/testcases/sme_vl.c new file +68 -0
68 lines not on this page · raw message
tools/testing/selftests/arm64/signal/testcases/ssve_regs.c new file +129 -0
129 lines not on this page · raw message
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 36/38 kselftest/arm64: Add streaming SVE to SVE ptrace tests
In reply to Mark BrownIn order to allow ptrace of streaming mode SVE registers we have added a new regset for streaming mode which in isolation offers the same ABI as regular SVE with a different vector type. Add this to the array of regsets we handle, together with additional tests for the interoperation of the two regsets.
--- tools/testing/selftests/arm64/fp/sve-ptrace.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
tools/testing/selftests/arm64/fp/sve-ptrace.c +11 -0
@@ -26,6 +26,10 @@#define NT_ARM_SVE 0x405#endif +#ifndef NT_ARM_SSVE +#define NT_ARM_SSVE 0x40b +#endif +struct vec_type {const char *name;unsigned long hwcap_type;
@@ -42,6 +46,13 @@ static const struct vec_type vec_types[] = { .regset = NT_ARM_SVE, .prctl_set = PR_SVE_SET_VL, }, + { + .name = "Streaming SVE", + .hwcap_type = AT_HWCAP2, + .hwcap = HWCAP2_SME, + .regset = NT_ARM_SSVE, + .prctl_set = PR_SME_SET_VL, + }, };#define VL_TESTS (((SVE_VQ_MAX - SVE_VQ_MIN) + 1) * 3)
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 37/38 kselftest/arm64: Add coverage for the ZA ptrace interface
In reply to Mark BrownAdd some basic coverage for the ZA ptrace interface, including walking through all the vector lengths supported in the system. As with SVE we do not currently validate the data all the way through to the running process.
--- tools/testing/selftests/arm64/fp/.gitignore | 1 + tools/testing/selftests/arm64/fp/Makefile | 3 +- tools/testing/selftests/arm64/fp/za-ptrace.c | 354 +++++++++++++++++++ 3 files changed, 357 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/arm64/fp/za-ptrace.c
tools/testing/selftests/arm64/fp/.gitignore +1 -0
@@ -8,4 +8,5 @@ sve-test ssve-test vec-syscfg vlset +za-ptrace za-test
tools/testing/selftests/arm64/fp/Makefile +2 -1
@@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 CFLAGS += -I../../../../../usr/include/ -TEST_GEN_PROGS := sve-ptrace sve-probe-vls vec-syscfg +TEST_GEN_PROGS := sve-ptrace sve-probe-vls vec-syscfg za-ptrace TEST_PROGS_EXTENDED := fp-pidbench fpsimd-test fpsimd-stress \ rdvl-sme rdvl-sve \ sve-test sve-stress \
@@ -27,5 +27,6 @@ vec-syscfg: vec-syscfg.o rdvl.o vlset: vlset.o za-test: za-test.o asm-utils.o $(CC) -nostdlib $^ -o $@ +za-ptrace: za-ptrace.o include ../../lib.mk
tools/testing/selftests/arm64/fp/za-ptrace.c new file +354 -0
354 lines not on this page · raw message
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v8 38/38 kselftest/arm64: Add SME support to syscall ABI test
In reply to Mark BrownFor every possible combination of SVE and SME vector length verify that for each possible value of SVCR after a syscall we leave streaming mode and ZA is preserved. We don't need to take account of any streaming/non streaming SVE vector length changes in the assembler code since the store instructions will handle the vector length for us. We log if the system supports FA64 and only try to set FFR in streaming mode if it does.
--- .../selftests/arm64/abi/syscall-abi-asm.S | 69 +++++- .../testing/selftests/arm64/abi/syscall-abi.c | 204 ++++++++++++++++-- .../testing/selftests/arm64/abi/syscall-abi.h | 15 ++ 3 files changed, 265 insertions(+), 23 deletions(-) create mode 100644 tools/testing/selftests/arm64/abi/syscall-abi.h
tools/testing/selftests/arm64/abi/syscall-abi-asm.S +68 -1
@@ -9,15 +9,42 @@ // invoked is configured in x8 of the input GPR data. // // x0: SVE VL, 0 for FP only +// x1: SME VL // // GPRs: gpr_in, gpr_out // FPRs: fpr_in, fpr_out // Zn: z_in, z_out // Pn: p_in, p_out // FFR: ffr_in, ffr_out +// ZA: za_in, za_out +// SVCR: svcr_in, svcr_out + +#include "syscall-abi.h" .arch_extension sve +/* + * LDR (vector to ZA array): + * LDR ZA[\nw, #\offset], [X\nxbase, #\offset, MUL VL] + */ +.macro _ldr_za nw, nxbase, offset=0 + .inst 0xe1000000 \ + | (((\nw) & 3) << 13) \ + | ((\nxbase) << 5) \ + | ((\offset) & 7) +.endm + +/* + * STR (vector from ZA array): + * STR ZA[\nw, #\offset], [X\nxbase, #\offset, MUL VL] + */ +.macro _str_za nw, nxbase, offset=0 + .inst 0xe1200000 \ + | (((\nw) & 3) << 13) \ + | ((\nxbase) << 5) \ + | ((\offset) & 7) +.endm + .globl do_syscall do_syscall: // Store callee saved registers x19-x29 (80 bytes) plus x0 and x1
@@ -30,6 +57,24 @@ do_syscall: stp x25, x26, [sp, #80] stp x27, x28, [sp, #96] + // Set SVCR if we're doing SME + cbz x1, 1f + adrp x2, svcr_in + ldr x2, [x2, :lo12:svcr_in] + msr S3_3_C4_C2_2, x2 +1: + + // Load ZA if it's enabled - uses x12 as scratch due to SME LDR + tbz x2, #SVCR_ZA_SHIFT, 1f + mov w12, #0 + ldr x2, =za_in +2: _ldr_za 12, 2 + add x2, x2, x1 + add x12, x12, #1 + cmp x1, x12 + bne 2b +1: + // Load GPRs x8-x28, and save our SP/FP for later comparison ldr x2, =gpr_in add x2, x2, #64
@@ -68,7 +113,7 @@ do_syscall: ldp q30, q31, [x2, #16 * 30] 1: - // Load the SVE registers if we're doing SVE + // Load the SVE registers if we're doing SVE/SME cbz x0, 1f ldr x2, =z_in
@@ -105,9 +150,13 @@ do_syscall: ldr z30, [x2, #30, MUL VL] ldr z31, [x2, #31, MUL VL] + // Only set a non-zero FFR, test patterns must be zero since the + // syscall should clear it - this lets us handle FA64. ldr x2, =ffr_in + cbz x2, 2f ldr p0, [x2, #0] wrffr p0.b +2: ldr x2, =p_in ldr p0, [x2, #0, MUL VL]
@@ -169,6 +218,24 @@ do_syscall: stp q28, q29, [x2, #16 * 28] stp q30, q31, [x2, #16 * 30] + // Save SVCR if we're doing SME + cbz x1, 1f + mrs x2, S3_3_C4_C2_2 + adrp x3, svcr_out + str x2, [x3, :lo12:svcr_out] +1: + + // Save ZA if it's enabled - uses x12 as scratch due to SME STR + tbz x2, #SVCR_ZA_SHIFT, 1f + mov w12, #0 + ldr x2, =za_out +2: _str_za 12, 2 + add x2, x2, x1 + add x12, x12, #1 + cmp x1, x12 + bne 2b +1: + // Save the SVE state if we have some cbz x0, 1f
tools/testing/selftests/arm64/abi/syscall-abi.c +182 -22
337 lines not on this page · raw message
tools/testing/selftests/arm64/abi/syscall-abi.h new file +15 -0
@@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +* Copyright (C) 2021 ARM Limited. +*/ + +#ifndef SYSCALL_ABI_H +#define SYSCALL_ABI_H + +#define SVCR_ZA_MASK 2 +#define SVCR_SM_MASK 1 + +#define SVCR_ZA_SHIFT 1 +#define SVCR_SM_SHIFT 0 + +#endif
Signature · 6 lines
2.30.2 _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm