Skip to content

Commit 24172e0

Browse files
committed
Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull arm64 fixes from Will Deacon: "There's more here than I would ideally like at this stage, but there's been a steady trickle of fixes and some of them took a few rounds of review. The bulk of the changes are fixing some fallout from the recent BBM level two support which allows the linear map to be split from block to page mappings at runtime, but inadvertently led to sleeping in atomic context on some paths where the linear map was already mapped with page granularity. The fix is simply to avoid splitting in those cases but the implementation of that is a little involved. The other interesting fix is addressing a catastophic performance issue with our per-cpu atomics discovered by Paul in the SRCU locking code but which took some interactions with the hardware folks to resolve. Summary: - Avoid sleeping in atomic context when changing linear map permissions for DEBUG_PAGEALLOC or KFENCE - Rework printing of Spectre mitigation status to avoid hardlockup when enabling per-task mitigations on the context-switch path - Reject kernel modules when instruction patching fails either due to the DWARF-based SCS patching or because of an alternatives callback residing outside of the core kernel text - Propagate error when updating kernel memory permissions in kprobes - Drop pointless, incorrect message when enabling the ACPI SPCR console - Use value-returning LSE instructions for per-cpu atomics to reduce latency in SRCU locking routines" * tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: arm64: Reject modules with internal alternative callbacks arm64: Fail module loading if dynamic SCS patching fails arm64: proton-pack: Fix hard lockup due to print in scheduler context arm64: proton-pack: Drop print when !CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY arm64: mm: Tidy up force_pte_mapping() arm64: mm: Optimize range_split_to_ptes() arm64: mm: Don't sleep in split_kernel_leaf_mapping() when in atomic context arm64: kprobes: check the return value of set_memory_rox() arm64: acpi: Drop message logging SPCR default console Revert "ACPI: Suppress misleading SPCR console message when SPCR table is absent" arm64: Use load LSE atomics for the non-return per-CPU atomic operations
2 parents 8341374 + 8e8ae78 commit 24172e0

15 files changed

Lines changed: 165 additions & 82 deletions

File tree

arch/arm64/include/asm/alternative.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,12 @@ void __init apply_alternatives_all(void);
2626
bool alternative_is_applied(u16 cpucap);
2727

2828
#ifdef CONFIG_MODULES
29-
void apply_alternatives_module(void *start, size_t length);
29+
int apply_alternatives_module(void *start, size_t length);
3030
#else
31-
static inline void apply_alternatives_module(void *start, size_t length) { }
31+
static inline int apply_alternatives_module(void *start, size_t length)
32+
{
33+
return 0;
34+
}
3235
#endif
3336

3437
void alt_cb_patch_nops(struct alt_instr *alt, __le32 *origptr,

arch/arm64/include/asm/kfence.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010

1111
#include <asm/set_memory.h>
1212

13-
static inline bool arch_kfence_init_pool(void) { return true; }
14-
1513
static inline bool kfence_protect_page(unsigned long addr, bool protect)
1614
{
1715
set_memory_valid(addr, 1, !protect);
@@ -25,6 +23,7 @@ static inline bool arm64_kfence_can_set_direct_map(void)
2523
{
2624
return !kfence_early_init;
2725
}
26+
bool arch_kfence_init_pool(void);
2827
#else /* CONFIG_KFENCE */
2928
static inline bool arm64_kfence_can_set_direct_map(void) { return false; }
3029
#endif /* CONFIG_KFENCE */

arch/arm64/include/asm/percpu.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ __percpu_##name##_case_##sz(void *ptr, unsigned long val) \
7777
" stxr" #sfx "\t%w[loop], %" #w "[tmp], %[ptr]\n" \
7878
" cbnz %w[loop], 1b", \
7979
/* LSE atomics */ \
80-
#op_lse "\t%" #w "[val], %[ptr]\n" \
80+
#op_lse "\t%" #w "[val], %" #w "[tmp], %[ptr]\n" \
8181
__nops(3)) \
8282
: [loop] "=&r" (loop), [tmp] "=&r" (tmp), \
8383
[ptr] "+Q"(*(u##sz *)ptr) \
@@ -124,9 +124,16 @@ PERCPU_RW_OPS(8)
124124
PERCPU_RW_OPS(16)
125125
PERCPU_RW_OPS(32)
126126
PERCPU_RW_OPS(64)
127-
PERCPU_OP(add, add, stadd)
128-
PERCPU_OP(andnot, bic, stclr)
129-
PERCPU_OP(or, orr, stset)
127+
128+
/*
129+
* Use value-returning atomics for CPU-local ops as they are more likely
130+
* to execute "near" to the CPU (e.g. in L1$).
131+
*
132+
* https://lore.kernel.org/r/e7d539ed-ced0-4b96-8ecd-048a5b803b85@paulmck-laptop
133+
*/
134+
PERCPU_OP(add, add, ldadd)
135+
PERCPU_OP(andnot, bic, ldclr)
136+
PERCPU_OP(or, orr, ldset)
130137
PERCPU_RET_OP(add, add, ldadd)
131138

132139
#undef PERCPU_RW_OPS

arch/arm64/include/asm/scs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ enum {
5353
EDYNSCS_INVALID_CFA_OPCODE = 4,
5454
};
5555

56-
int __pi_scs_patch(const u8 eh_frame[], int size);
56+
int __pi_scs_patch(const u8 eh_frame[], int size, bool skip_dry_run);
5757

5858
#endif /* __ASSEMBLY __ */
5959

arch/arm64/include/asm/spectre.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ void spectre_bhb_patch_wa3(struct alt_instr *alt,
117117
__le32 *origptr, __le32 *updptr, int nr_inst);
118118
void spectre_bhb_patch_clearbhb(struct alt_instr *alt,
119119
__le32 *origptr, __le32 *updptr, int nr_inst);
120+
void spectre_print_disabled_mitigations(void);
120121

121122
#endif /* __ASSEMBLY__ */
122123
#endif /* __ASM_SPECTRE_H */

arch/arm64/kernel/acpi.c

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,6 @@ static int __init acpi_fadt_sanity_check(void)
197197
*/
198198
void __init acpi_boot_table_init(void)
199199
{
200-
int ret;
201-
202200
/*
203201
* Enable ACPI instead of device tree unless
204202
* - ACPI has been disabled explicitly (acpi=off), or
@@ -252,12 +250,8 @@ void __init acpi_boot_table_init(void)
252250
* behaviour, use acpi=nospcr to disable console in ACPI SPCR
253251
* table as default serial console.
254252
*/
255-
ret = acpi_parse_spcr(earlycon_acpi_spcr_enable,
253+
acpi_parse_spcr(earlycon_acpi_spcr_enable,
256254
!param_acpi_nospcr);
257-
if (!ret || param_acpi_nospcr || !IS_ENABLED(CONFIG_ACPI_SPCR_TABLE))
258-
pr_info("Use ACPI SPCR as default console: No\n");
259-
else
260-
pr_info("Use ACPI SPCR as default console: Yes\n");
261255

262256
if (IS_ENABLED(CONFIG_ACPI_BGRT))
263257
acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt);

arch/arm64/kernel/alternative.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,9 @@ static noinstr void clean_dcache_range_nopatch(u64 start, u64 end)
139139
} while (cur += d_size, cur < end);
140140
}
141141

142-
static void __apply_alternatives(const struct alt_region *region,
143-
bool is_module,
144-
unsigned long *cpucap_mask)
142+
static int __apply_alternatives(const struct alt_region *region,
143+
bool is_module,
144+
unsigned long *cpucap_mask)
145145
{
146146
struct alt_instr *alt;
147147
__le32 *origptr, *updptr;
@@ -166,10 +166,13 @@ static void __apply_alternatives(const struct alt_region *region,
166166
updptr = is_module ? origptr : lm_alias(origptr);
167167
nr_inst = alt->orig_len / AARCH64_INSN_SIZE;
168168

169-
if (ALT_HAS_CB(alt))
169+
if (ALT_HAS_CB(alt)) {
170170
alt_cb = ALT_REPL_PTR(alt);
171-
else
171+
if (is_module && !core_kernel_text((unsigned long)alt_cb))
172+
return -ENOEXEC;
173+
} else {
172174
alt_cb = patch_alternative;
175+
}
173176

174177
alt_cb(alt, origptr, updptr, nr_inst);
175178

@@ -193,6 +196,8 @@ static void __apply_alternatives(const struct alt_region *region,
193196
bitmap_and(applied_alternatives, applied_alternatives,
194197
system_cpucaps, ARM64_NCAPS);
195198
}
199+
200+
return 0;
196201
}
197202

198203
static void __init apply_alternatives_vdso(void)
@@ -277,7 +282,7 @@ void __init apply_boot_alternatives(void)
277282
}
278283

279284
#ifdef CONFIG_MODULES
280-
void apply_alternatives_module(void *start, size_t length)
285+
int apply_alternatives_module(void *start, size_t length)
281286
{
282287
struct alt_region region = {
283288
.begin = start,
@@ -287,7 +292,7 @@ void apply_alternatives_module(void *start, size_t length)
287292

288293
bitmap_fill(all_capabilities, ARM64_NCAPS);
289294

290-
__apply_alternatives(&region, true, &all_capabilities[0]);
295+
return __apply_alternatives(&region, true, &all_capabilities[0]);
291296
}
292297
#endif
293298

arch/arm64/kernel/cpufeature.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
#include <asm/vectors.h>
9696
#include <asm/virt.h>
9797

98+
#include <asm/spectre.h>
9899
/* Kernel representation of AT_HWCAP and AT_HWCAP2 */
99100
static DECLARE_BITMAP(elf_hwcap, MAX_CPU_FEATURES) __read_mostly;
100101

@@ -3875,6 +3876,11 @@ static void __init setup_system_capabilities(void)
38753876
*/
38763877
if (system_uses_ttbr0_pan())
38773878
pr_info("emulated: Privileged Access Never (PAN) using TTBR0_EL1 switching\n");
3879+
3880+
/*
3881+
* Report Spectre mitigations status.
3882+
*/
3883+
spectre_print_disabled_mitigations();
38783884
}
38793885

38803886
void __init setup_system_features(void)

arch/arm64/kernel/module.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -489,16 +489,29 @@ int module_finalize(const Elf_Ehdr *hdr,
489489
int ret;
490490

491491
s = find_section(hdr, sechdrs, ".altinstructions");
492-
if (s)
493-
apply_alternatives_module((void *)s->sh_addr, s->sh_size);
492+
if (s) {
493+
ret = apply_alternatives_module((void *)s->sh_addr, s->sh_size);
494+
if (ret < 0) {
495+
pr_err("module %s: error occurred when applying alternatives\n", me->name);
496+
return ret;
497+
}
498+
}
494499

495500
if (scs_is_dynamic()) {
496501
s = find_section(hdr, sechdrs, ".init.eh_frame");
497502
if (s) {
498-
ret = __pi_scs_patch((void *)s->sh_addr, s->sh_size);
499-
if (ret)
503+
/*
504+
* Because we can reject modules that are malformed
505+
* so SCS patching fails, skip dry run and try to patch
506+
* it in place. If patching fails, the module would not
507+
* be loaded anyway.
508+
*/
509+
ret = __pi_scs_patch((void *)s->sh_addr, s->sh_size, true);
510+
if (ret) {
500511
pr_err("module %s: error occurred during dynamic SCS patching (%d)\n",
501512
me->name, ret);
513+
return -ENOEXEC;
514+
}
502515
}
503516
}
504517

arch/arm64/kernel/pi/map_kernel.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ static void __init map_kernel(u64 kaslr_offset, u64 va_offset, int root_level)
104104

105105
if (enable_scs) {
106106
scs_patch(__eh_frame_start + va_offset,
107-
__eh_frame_end - __eh_frame_start);
107+
__eh_frame_end - __eh_frame_start, false);
108108
asm("ic ialluis");
109109

110110
dynamic_scs_is_enabled = true;

0 commit comments

Comments
 (0)