Skip to content

Commit 18dfd1c

Browse files
committed
Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull arm64 fixes from Catalin Marinas: "Two left-over updates that could not go into -rc1 due to conflicts with other series: - Simplify checks in arch_kfence_init_pool() since force_pte_mapping() already takes BBML2-noabort (break-before-make Level 2 with no aborts generated) into account - Remove unneeded SVE/SME fallback preserve/store handling in the arm64 EFI. With the recent updates, the fallback path is only taken for EFI runtime calls from hardirq or NMI contexts. In practice, this only happens under panic/oops/emergency_restart() and no restoring of the user state expected. There's a corresponding lkdtm update to trigger a BUG() or panic() from hardirq context together with a fixup not to confuse clang/objtool about the control flow GCS (guarded control stacks) fix: flush the GCS locking state on exec, otherwise the new task will not be able to enable GCS (locked as disabled)" * tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: lkdtm/bugs: Do not confuse the clang/objtool with busy wait loop arm64/gcs: Flush the GCS locking state on exec arm64/efi: Remove unneeded SVE/SME fallback preserve/store handling lkdtm/bugs: Add cases for BUG and PANIC occurring in hardirq context arm64: mm: Simplify check in arch_kfence_init_pool()
2 parents 072c0b4 + f4ea8e0 commit 18dfd1c

5 files changed

Lines changed: 92 additions & 127 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

arch/arm64/kernel/process.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ static void flush_gcs(void)
292292
current->thread.gcs_base = 0;
293293
current->thread.gcs_size = 0;
294294
current->thread.gcs_el0_mode = 0;
295+
current->thread.gcs_el0_locked = 0;
295296
write_sysreg_s(GCSCRE0_EL1_nTR, SYS_GCSCRE0_EL1);
296297
write_sysreg_s(0, SYS_GCSPR_EL0);
297298
}

arch/arm64/mm/mmu.c

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -767,30 +767,29 @@ static inline bool force_pte_mapping(void)
767767
return rodata_full || arm64_kfence_can_set_direct_map() || is_realm_world();
768768
}
769769

770-
static inline bool split_leaf_mapping_possible(void)
771-
{
772-
/*
773-
* !BBML2_NOABORT systems should never run into scenarios where we would
774-
* have to split. So exit early and let calling code detect it and raise
775-
* a warning.
776-
*/
777-
if (!system_supports_bbml2_noabort())
778-
return false;
779-
return !force_pte_mapping();
780-
}
781-
782770
static DEFINE_MUTEX(pgtable_split_lock);
783771

784772
int split_kernel_leaf_mapping(unsigned long start, unsigned long end)
785773
{
786774
int ret;
787775

788776
/*
789-
* Exit early if the region is within a pte-mapped area or if we can't
790-
* split. For the latter case, the permission change code will raise a
791-
* warning if not already pte-mapped.
777+
* !BBML2_NOABORT systems should not be trying to change permissions on
778+
* anything that is not pte-mapped in the first place. Just return early
779+
* and let the permission change code raise a warning if not already
780+
* pte-mapped.
792781
*/
793-
if (!split_leaf_mapping_possible() || is_kfence_address((void *)start))
782+
if (!system_supports_bbml2_noabort())
783+
return 0;
784+
785+
/*
786+
* If the region is within a pte-mapped area, there is no need to try to
787+
* split. Additionally, CONFIG_DEBUG_PAGEALLOC and CONFIG_KFENCE may
788+
* change permissions from atomic context so for those cases (which are
789+
* always pte-mapped), we must not go any further because taking the
790+
* mutex below may sleep.
791+
*/
792+
if (force_pte_mapping() || is_kfence_address((void *)start))
794793
return 0;
795794

796795
/*
@@ -1089,7 +1088,7 @@ bool arch_kfence_init_pool(void)
10891088
int ret;
10901089

10911090
/* Exit early if we know the linear map is already pte-mapped. */
1092-
if (!split_leaf_mapping_possible())
1091+
if (force_pte_mapping())
10931092
return true;
10941093

10951094
/* Kfence pool is already pte-mapped for the early init case. */

drivers/misc/lkdtm/bugs.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "lkdtm.h"
99
#include <linux/cpu.h>
1010
#include <linux/list.h>
11+
#include <linux/hrtimer.h>
1112
#include <linux/sched.h>
1213
#include <linux/sched/signal.h>
1314
#include <linux/sched/task_stack.h>
@@ -100,11 +101,61 @@ static void lkdtm_PANIC_STOP_IRQOFF(void)
100101
stop_machine(panic_stop_irqoff_fn, &v, cpu_online_mask);
101102
}
102103

104+
static bool wait_for_panic;
105+
106+
static enum hrtimer_restart panic_in_hardirq(struct hrtimer *timer)
107+
{
108+
panic("from hard IRQ context");
109+
110+
wait_for_panic = false;
111+
return HRTIMER_NORESTART;
112+
}
113+
114+
static void lkdtm_PANIC_IN_HARDIRQ(void)
115+
{
116+
struct hrtimer timer;
117+
118+
wait_for_panic = true;
119+
hrtimer_setup_on_stack(&timer, panic_in_hardirq,
120+
CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD);
121+
hrtimer_start(&timer, us_to_ktime(100), HRTIMER_MODE_REL_HARD);
122+
123+
while (READ_ONCE(wait_for_panic))
124+
cpu_relax();
125+
126+
hrtimer_cancel(&timer);
127+
}
128+
103129
static void lkdtm_BUG(void)
104130
{
105131
BUG();
106132
}
107133

134+
static bool wait_for_bug;
135+
136+
static enum hrtimer_restart bug_in_hardirq(struct hrtimer *timer)
137+
{
138+
BUG();
139+
140+
wait_for_bug = false;
141+
return HRTIMER_NORESTART;
142+
}
143+
144+
static void lkdtm_BUG_IN_HARDIRQ(void)
145+
{
146+
struct hrtimer timer;
147+
148+
wait_for_bug = true;
149+
hrtimer_setup_on_stack(&timer, bug_in_hardirq,
150+
CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD);
151+
hrtimer_start(&timer, us_to_ktime(100), HRTIMER_MODE_REL_HARD);
152+
153+
while (READ_ONCE(wait_for_bug))
154+
cpu_relax();
155+
156+
hrtimer_cancel(&timer);
157+
}
158+
108159
static int warn_counter;
109160

110161
static void lkdtm_WARNING(void)
@@ -696,7 +747,9 @@ static noinline void lkdtm_CORRUPT_PAC(void)
696747
static struct crashtype crashtypes[] = {
697748
CRASHTYPE(PANIC),
698749
CRASHTYPE(PANIC_STOP_IRQOFF),
750+
CRASHTYPE(PANIC_IN_HARDIRQ),
699751
CRASHTYPE(BUG),
752+
CRASHTYPE(BUG_IN_HARDIRQ),
700753
CRASHTYPE(WARNING),
701754
CRASHTYPE(WARNING_MESSAGE),
702755
CRASHTYPE(EXCEPTION),

tools/testing/selftests/lkdtm/tests.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#PANIC
22
#PANIC_STOP_IRQOFF Crashes entire system
3+
#PANIC_IN_HARDIRQ Crashes entire system
34
BUG kernel BUG at
5+
#BUG_IN_HARDIRQ Crashes entire system
46
WARNING WARNING:
57
WARNING_MESSAGE message trigger
68
EXCEPTION

0 commit comments

Comments
 (0)