Skip to content

Commit e0838f6

Browse files
brooniectmarinas
authored andcommitted
arm64/sme: Save and restore streaming mode over EFI runtime calls
When 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. Signed-off-by: Mark Brown <[email protected]> Reviewed-by: Catalin Marinas <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Catalin Marinas <[email protected]>
1 parent d45d7ff commit e0838f6

File tree

1 file changed

+42
-6
lines changed

1 file changed

+42
-6
lines changed

arch/arm64/kernel/fpsimd.c

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,21 +1056,25 @@ int vec_verify_vq_map(enum vec_type type)
10561056

10571057
static void __init sve_efi_setup(void)
10581058
{
1059-
struct vl_info *info = &vl_info[ARM64_VEC_SVE];
1059+
int max_vl = 0;
1060+
int i;
10601061

10611062
if (!IS_ENABLED(CONFIG_EFI))
10621063
return;
10631064

1065+
for (i = 0; i < ARRAY_SIZE(vl_info); i++)
1066+
max_vl = max(vl_info[i].max_vl, max_vl);
1067+
10641068
/*
10651069
* alloc_percpu() warns and prints a backtrace if this goes wrong.
10661070
* This is evidence of a crippled system and we are returning void,
10671071
* so no attempt is made to handle this situation here.
10681072
*/
1069-
if (!sve_vl_valid(info->max_vl))
1073+
if (!sve_vl_valid(max_vl))
10701074
goto fail;
10711075

10721076
efi_sve_state = __alloc_percpu(
1073-
SVE_SIG_REGS_SIZE(sve_vq_from_vl(info->max_vl)), SVE_VQ_BYTES);
1077+
SVE_SIG_REGS_SIZE(sve_vq_from_vl(max_vl)), SVE_VQ_BYTES);
10741078
if (!efi_sve_state)
10751079
goto fail;
10761080

@@ -1845,6 +1849,7 @@ EXPORT_SYMBOL(kernel_neon_end);
18451849
static DEFINE_PER_CPU(struct user_fpsimd_state, efi_fpsimd_state);
18461850
static DEFINE_PER_CPU(bool, efi_fpsimd_state_used);
18471851
static DEFINE_PER_CPU(bool, efi_sve_state_used);
1852+
static DEFINE_PER_CPU(bool, efi_sm_state);
18481853

18491854
/*
18501855
* EFI runtime services support functions
@@ -1879,12 +1884,28 @@ void __efi_fpsimd_begin(void)
18791884
*/
18801885
if (system_supports_sve() && likely(efi_sve_state)) {
18811886
char *sve_state = this_cpu_ptr(efi_sve_state);
1887+
bool ffr = true;
1888+
u64 svcr;
18821889

18831890
__this_cpu_write(efi_sve_state_used, true);
18841891

1892+
if (system_supports_sme()) {
1893+
svcr = read_sysreg_s(SYS_SVCR_EL0);
1894+
1895+
if (!system_supports_fa64())
1896+
ffr = svcr & SYS_SVCR_EL0_SM_MASK;
1897+
1898+
__this_cpu_write(efi_sm_state, ffr);
1899+
}
1900+
18851901
sve_save_state(sve_state + sve_ffr_offset(sve_max_vl()),
18861902
&this_cpu_ptr(&efi_fpsimd_state)->fpsr,
1887-
true);
1903+
ffr);
1904+
1905+
if (system_supports_sme())
1906+
sysreg_clear_set_s(SYS_SVCR_EL0,
1907+
SYS_SVCR_EL0_SM_MASK, 0);
1908+
18881909
} else {
18891910
fpsimd_save_state(this_cpu_ptr(&efi_fpsimd_state));
18901911
}
@@ -1907,11 +1928,26 @@ void __efi_fpsimd_end(void)
19071928
if (system_supports_sve() &&
19081929
likely(__this_cpu_read(efi_sve_state_used))) {
19091930
char const *sve_state = this_cpu_ptr(efi_sve_state);
1931+
bool ffr = true;
1932+
1933+
/*
1934+
* Restore streaming mode; EFI calls are
1935+
* normal function calls so should not return in
1936+
* streaming mode.
1937+
*/
1938+
if (system_supports_sme()) {
1939+
if (__this_cpu_read(efi_sm_state)) {
1940+
sysreg_clear_set_s(SYS_SVCR_EL0,
1941+
0,
1942+
SYS_SVCR_EL0_SM_MASK);
1943+
if (!system_supports_fa64())
1944+
ffr = efi_sm_state;
1945+
}
1946+
}
19101947

1911-
sve_set_vq(sve_vq_from_vl(sve_get_vl()) - 1);
19121948
sve_load_state(sve_state + sve_ffr_offset(sve_max_vl()),
19131949
&this_cpu_ptr(&efi_fpsimd_state)->fpsr,
1914-
true);
1950+
ffr);
19151951

19161952
__this_cpu_write(efi_sve_state_used, false);
19171953
} else {

0 commit comments

Comments
 (0)