Skip to content

Commit 63de2b3

Browse files
ardbiesheuvelctmarinas
authored andcommitted
arm64/efi: Remove unneeded SVE/SME fallback preserve/store handling
Since commit 7137a20 ("arm64/fpsimd: Permit kernel mode NEON with IRQs off"), the only condition under which the fallback path is taken for FP/SIMD preserve/restore across a EFI runtime call is when it is called from hardirq or NMI context. In practice, this only happens when the EFI pstore driver is called to dump the kernel log buffer into a EFI variable under a panic, oops or emergency_restart() condition, and none of these can be expected to result in a return to user space for the task in question. This means that the existing EFI-specific logic for preserving and restoring SVE/SME state is pointless, and can be removed. Instead, kill the task, so that an exceedingly unlikely inadvertent return to user space does not proceed with a corrupted FP/SIMD state. Also, retain the preserve and restore of the base FP/SIMD state, as that might belong to kernel mode use of FP/SIMD. (Note that EFI runtime calls are never invoked reentrantly, even in this case, and so any interrupted kernel mode FP/SIMD usage will be unrelated to EFI) Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
1 parent eb972ea commit 63de2b3

1 file changed

Lines changed: 20 additions & 110 deletions

File tree

arch/arm64/kernel/fpsimd.c

Lines changed: 20 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -180,13 +180,6 @@ static inline void set_sve_default_vl(int val)
180180
set_default_vl(ARM64_VEC_SVE, val);
181181
}
182182

183-
static u8 *efi_sve_state;
184-
185-
#else /* ! CONFIG_ARM64_SVE */
186-
187-
/* Dummy declaration for code that will be optimised out: */
188-
extern u8 *efi_sve_state;
189-
190183
#endif /* ! CONFIG_ARM64_SVE */
191184

192185
#ifdef CONFIG_ARM64_SME
@@ -1095,36 +1088,6 @@ int vec_verify_vq_map(enum vec_type type)
10951088
return 0;
10961089
}
10971090

1098-
static void __init sve_efi_setup(void)
1099-
{
1100-
int max_vl = 0;
1101-
int i;
1102-
1103-
if (!IS_ENABLED(CONFIG_EFI))
1104-
return;
1105-
1106-
for (i = 0; i < ARRAY_SIZE(vl_info); i++)
1107-
max_vl = max(vl_info[i].max_vl, max_vl);
1108-
1109-
/*
1110-
* alloc_percpu() warns and prints a backtrace if this goes wrong.
1111-
* This is evidence of a crippled system and we are returning void,
1112-
* so no attempt is made to handle this situation here.
1113-
*/
1114-
if (!sve_vl_valid(max_vl))
1115-
goto fail;
1116-
1117-
efi_sve_state = kmalloc(SVE_SIG_REGS_SIZE(sve_vq_from_vl(max_vl)),
1118-
GFP_KERNEL);
1119-
if (!efi_sve_state)
1120-
goto fail;
1121-
1122-
return;
1123-
1124-
fail:
1125-
panic("Cannot allocate memory for EFI SVE save/restore");
1126-
}
1127-
11281091
void cpu_enable_sve(const struct arm64_cpu_capabilities *__always_unused p)
11291092
{
11301093
write_sysreg(read_sysreg(CPACR_EL1) | CPACR_EL1_ZEN_EL1EN, CPACR_EL1);
@@ -1185,8 +1148,6 @@ void __init sve_setup(void)
11851148
if (sve_max_virtualisable_vl() < sve_max_vl())
11861149
pr_warn("%s: unvirtualisable vector lengths present\n",
11871150
info->name);
1188-
1189-
sve_efi_setup();
11901151
}
11911152

11921153
/*
@@ -1947,9 +1908,6 @@ EXPORT_SYMBOL_GPL(kernel_neon_end);
19471908
#ifdef CONFIG_EFI
19481909

19491910
static struct user_fpsimd_state efi_fpsimd_state;
1950-
static bool efi_fpsimd_state_used;
1951-
static bool efi_sve_state_used;
1952-
static bool efi_sm_state;
19531911

19541912
/*
19551913
* EFI runtime services support functions
@@ -1976,43 +1934,26 @@ void __efi_fpsimd_begin(void)
19761934
if (may_use_simd()) {
19771935
kernel_neon_begin(&efi_fpsimd_state);
19781936
} else {
1979-
WARN_ON(preemptible());
1980-
19811937
/*
1982-
* If !efi_sve_state, SVE can't be in use yet and doesn't need
1983-
* preserving:
1938+
* We are running in hardirq or NMI context, and the only
1939+
* legitimate case where this might happen is when EFI pstore
1940+
* is attempting to record the system's dying gasps into EFI
1941+
* variables. This could be due to an oops, a panic or a call
1942+
* to emergency_restart(), and in none of those cases, we can
1943+
* expect the current task to ever return to user space again,
1944+
* or for the kernel to resume any normal execution, for that
1945+
* matter (an oops in hardirq context triggers a panic too).
1946+
*
1947+
* Therefore, there is no point in attempting to preserve any
1948+
* SVE/SME state here. On the off chance that we might have
1949+
* ended up here for a different reason inadvertently, kill the
1950+
* task and preserve/restore the base FP/SIMD state, which
1951+
* might belong to kernel mode FP/SIMD.
19841952
*/
1985-
if (system_supports_sve() && efi_sve_state != NULL) {
1986-
bool ffr = true;
1987-
u64 svcr;
1988-
1989-
efi_sve_state_used = true;
1990-
1991-
if (system_supports_sme()) {
1992-
svcr = read_sysreg_s(SYS_SVCR);
1993-
1994-
efi_sm_state = svcr & SVCR_SM_MASK;
1995-
1996-
/*
1997-
* Unless we have FA64 FFR does not
1998-
* exist in streaming mode.
1999-
*/
2000-
if (!system_supports_fa64())
2001-
ffr = !(svcr & SVCR_SM_MASK);
2002-
}
2003-
2004-
sve_save_state(efi_sve_state + sve_ffr_offset(sve_max_vl()),
2005-
&efi_fpsimd_state.fpsr, ffr);
2006-
2007-
if (system_supports_sme())
2008-
sysreg_clear_set_s(SYS_SVCR,
2009-
SVCR_SM_MASK, 0);
2010-
2011-
} else {
2012-
fpsimd_save_state(&efi_fpsimd_state);
2013-
}
2014-
2015-
efi_fpsimd_state_used = true;
1953+
pr_warn_ratelimited("Calling EFI runtime from %s context\n",
1954+
in_nmi() ? "NMI" : "hardirq");
1955+
force_signal_inject(SIGKILL, SI_KERNEL, 0, 0);
1956+
fpsimd_save_state(&efi_fpsimd_state);
20161957
}
20171958
}
20181959

@@ -2024,41 +1965,10 @@ void __efi_fpsimd_end(void)
20241965
if (!system_supports_fpsimd())
20251966
return;
20261967

2027-
if (!efi_fpsimd_state_used) {
1968+
if (may_use_simd()) {
20281969
kernel_neon_end(&efi_fpsimd_state);
20291970
} else {
2030-
if (system_supports_sve() && efi_sve_state_used) {
2031-
bool ffr = true;
2032-
2033-
/*
2034-
* Restore streaming mode; EFI calls are
2035-
* normal function calls so should not return in
2036-
* streaming mode.
2037-
*/
2038-
if (system_supports_sme()) {
2039-
if (efi_sm_state) {
2040-
sysreg_clear_set_s(SYS_SVCR,
2041-
0,
2042-
SVCR_SM_MASK);
2043-
2044-
/*
2045-
* Unless we have FA64 FFR does not
2046-
* exist in streaming mode.
2047-
*/
2048-
if (!system_supports_fa64())
2049-
ffr = false;
2050-
}
2051-
}
2052-
2053-
sve_load_state(efi_sve_state + sve_ffr_offset(sve_max_vl()),
2054-
&efi_fpsimd_state.fpsr, ffr);
2055-
2056-
efi_sve_state_used = false;
2057-
} else {
2058-
fpsimd_load_state(&efi_fpsimd_state);
2059-
}
2060-
2061-
efi_fpsimd_state_used = false;
1971+
fpsimd_load_state(&efi_fpsimd_state);
20621972
}
20631973
}
20641974

0 commit comments

Comments
 (0)