Skip to content

Commit 18b5cb6

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: "I think the main one is fixing the dynamic SCS patching when full LTO is enabled (clang was silently getting this horribly wrong), but it's all good stuff. Rob just pointed out that the fix to the workaround for erratum #2966298 might not be necessary, but in the worst case it's harmless and since the official description leaves a little to be desired here, I've left it in. Summary: - Fix shadow call stack patching with LTO=full - Fix voluntary preemption of the FPSIMD registers from assembly code - Fix workaround for A520 CPU erratum #2966298 and extend to A510 - Fix SME issues that resulted in corruption of the register state - Minor fixes (missing includes, formatting)" * tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: arm64: Fix silcon-errata.rst formatting arm64/sme: Always exit sme_alloc() early with existing storage arm64/fpsimd: Remove spurious check for SVE support arm64/ptrace: Don't flush ZA/ZT storage when writing ZA via ptrace arm64: entry: simplify kernel_exit logic arm64: entry: fix ARM64_WORKAROUND_SPECULATIVE_UNPRIV_LOAD arm64: errata: Add Cortex-A510 speculative unprivileged load workaround arm64: Rename ARM64_WORKAROUND_2966298 arm64: fpsimd: Bring cond_yield asm macro in line with new rules arm64: scs: Work around full LTO issue with dynamic SCS arm64: irq: include <linux/cpumask.h>
2 parents 24fdd51 + 1b20d04 commit 18b5cb6

File tree

11 files changed

+83
-49
lines changed

11 files changed

+83
-49
lines changed

Documentation/arch/arm64/silicon-errata.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ stable kernels.
7171
+----------------+-----------------+-----------------+-----------------------------+
7272
| ARM | Cortex-A510 | #2658417 | ARM64_ERRATUM_2658417 |
7373
+----------------+-----------------+-----------------+-----------------------------+
74+
| ARM | Cortex-A510 | #3117295 | ARM64_ERRATUM_3117295 |
75+
+----------------+-----------------+-----------------+-----------------------------+
7476
| ARM | Cortex-A520 | #2966298 | ARM64_ERRATUM_2966298 |
7577
+----------------+-----------------+-----------------+-----------------------------+
7678
| ARM | Cortex-A53 | #826319 | ARM64_ERRATUM_826319 |
@@ -235,11 +237,9 @@ stable kernels.
235237
+----------------+-----------------+-----------------+-----------------------------+
236238
| Rockchip | RK3588 | #3588001 | ROCKCHIP_ERRATUM_3588001 |
237239
+----------------+-----------------+-----------------+-----------------------------+
238-
239240
+----------------+-----------------+-----------------+-----------------------------+
240241
| Fujitsu | A64FX | E#010001 | FUJITSU_ERRATUM_010001 |
241242
+----------------+-----------------+-----------------+-----------------------------+
242-
243243
+----------------+-----------------+-----------------+-----------------------------+
244244
| ASR | ASR8601 | #8601001 | N/A |
245245
+----------------+-----------------+-----------------+-----------------------------+

arch/arm64/Kconfig

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,8 +1039,12 @@ config ARM64_ERRATUM_2645198
10391039

10401040
If unsure, say Y.
10411041

1042+
config ARM64_WORKAROUND_SPECULATIVE_UNPRIV_LOAD
1043+
bool
1044+
10421045
config ARM64_ERRATUM_2966298
10431046
bool "Cortex-A520: 2966298: workaround for speculatively executed unprivileged load"
1047+
select ARM64_WORKAROUND_SPECULATIVE_UNPRIV_LOAD
10441048
default y
10451049
help
10461050
This option adds the workaround for ARM Cortex-A520 erratum 2966298.
@@ -1052,6 +1056,20 @@ config ARM64_ERRATUM_2966298
10521056

10531057
If unsure, say Y.
10541058

1059+
config ARM64_ERRATUM_3117295
1060+
bool "Cortex-A510: 3117295: workaround for speculatively executed unprivileged load"
1061+
select ARM64_WORKAROUND_SPECULATIVE_UNPRIV_LOAD
1062+
default y
1063+
help
1064+
This option adds the workaround for ARM Cortex-A510 erratum 3117295.
1065+
1066+
On an affected Cortex-A510 core, a speculatively executed unprivileged
1067+
load might leak data from a privileged level via a cache side channel.
1068+
1069+
Work around this problem by executing a TLBI before returning to EL0.
1070+
1071+
If unsure, say Y.
1072+
10551073
config CAVIUM_ERRATUM_22375
10561074
bool "Cavium erratum 22375, 24313"
10571075
default y

arch/arm64/include/asm/assembler.h

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -760,32 +760,25 @@ alternative_endif
760760
.endm
761761

762762
/*
763-
* Check whether preempt/bh-disabled asm code should yield as soon as
764-
* it is able. This is the case if we are currently running in task
765-
* context, and either a softirq is pending, or the TIF_NEED_RESCHED
766-
* flag is set and re-enabling preemption a single time would result in
767-
* a preempt count of zero. (Note that the TIF_NEED_RESCHED flag is
768-
* stored negated in the top word of the thread_info::preempt_count
763+
* Check whether asm code should yield as soon as it is able. This is
764+
* the case if we are currently running in task context, and the
765+
* TIF_NEED_RESCHED flag is set. (Note that the TIF_NEED_RESCHED flag
766+
* is stored negated in the top word of the thread_info::preempt_count
769767
* field)
770768
*/
771-
.macro cond_yield, lbl:req, tmp:req, tmp2:req
769+
.macro cond_yield, lbl:req, tmp:req, tmp2
770+
#ifdef CONFIG_PREEMPT_VOLUNTARY
772771
get_current_task \tmp
773772
ldr \tmp, [\tmp, #TSK_TI_PREEMPT]
774773
/*
775774
* If we are serving a softirq, there is no point in yielding: the
776775
* softirq will not be preempted no matter what we do, so we should
777-
* run to completion as quickly as we can.
776+
* run to completion as quickly as we can. The preempt_count field will
777+
* have BIT(SOFTIRQ_SHIFT) set in this case, so the zero check will
778+
* catch this case too.
778779
*/
779-
tbnz \tmp, #SOFTIRQ_SHIFT, .Lnoyield_\@
780-
#ifdef CONFIG_PREEMPTION
781-
sub \tmp, \tmp, #PREEMPT_DISABLE_OFFSET
782780
cbz \tmp, \lbl
783781
#endif
784-
adr_l \tmp, irq_stat + IRQ_CPUSTAT_SOFTIRQ_PENDING
785-
get_this_cpu_offset \tmp2
786-
ldr w\tmp, [\tmp, \tmp2]
787-
cbnz w\tmp, \lbl // yield on pending softirq in task context
788-
.Lnoyield_\@:
789782
.endm
790783

791784
/*

arch/arm64/include/asm/irq.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
#ifndef __ASSEMBLER__
66

7+
#include <linux/cpumask.h>
8+
79
#include <asm-generic/irq.h>
810

911
void arch_trigger_cpumask_backtrace(const cpumask_t *mask, int exclude_cpu);

arch/arm64/kernel/Makefile

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,13 @@ obj-$(CONFIG_ARM64_MTE) += mte.o
7373
obj-y += vdso-wrap.o
7474
obj-$(CONFIG_COMPAT_VDSO) += vdso32-wrap.o
7575
obj-$(CONFIG_UNWIND_PATCH_PAC_INTO_SCS) += patch-scs.o
76-
CFLAGS_patch-scs.o += -mbranch-protection=none
76+
77+
# We need to prevent the SCS patching code from patching itself. Using
78+
# -mbranch-protection=none here to avoid the patchable PAC opcodes from being
79+
# generated triggers an issue with full LTO on Clang, which stops emitting PAC
80+
# instructions altogether. So instead, omit the unwind tables used by the
81+
# patching code, so it will not be able to locate its own PAC instructions.
82+
CFLAGS_patch-scs.o += -fno-asynchronous-unwind-tables -fno-unwind-tables
7783

7884
# Force dependency (vdso*-wrap.S includes vdso.so through incbin)
7985
$(obj)/vdso-wrap.o: $(obj)/vdso/vdso.so

arch/arm64/kernel/asm-offsets.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,6 @@ int main(void)
117117
DEFINE(DMA_FROM_DEVICE, DMA_FROM_DEVICE);
118118
BLANK();
119119
DEFINE(PREEMPT_DISABLE_OFFSET, PREEMPT_DISABLE_OFFSET);
120-
DEFINE(SOFTIRQ_SHIFT, SOFTIRQ_SHIFT);
121-
DEFINE(IRQ_CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
122120
BLANK();
123121
DEFINE(CPU_BOOT_TASK, offsetof(struct secondary_data, task));
124122
BLANK();

arch/arm64/kernel/cpu_errata.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,19 @@ static struct midr_range broken_aarch32_aes[] = {
416416
};
417417
#endif /* CONFIG_ARM64_WORKAROUND_TRBE_WRITE_OUT_OF_RANGE */
418418

419+
#ifdef CONFIG_ARM64_WORKAROUND_SPECULATIVE_UNPRIV_LOAD
420+
static const struct midr_range erratum_spec_unpriv_load_list[] = {
421+
#ifdef CONFIG_ARM64_ERRATUM_3117295
422+
MIDR_ALL_VERSIONS(MIDR_CORTEX_A510),
423+
#endif
424+
#ifdef CONFIG_ARM64_ERRATUM_2966298
425+
/* Cortex-A520 r0p0 to r0p1 */
426+
MIDR_REV_RANGE(MIDR_CORTEX_A520, 0, 0, 1),
427+
#endif
428+
{},
429+
};
430+
#endif
431+
419432
const struct arm64_cpu_capabilities arm64_errata[] = {
420433
#ifdef CONFIG_ARM64_WORKAROUND_CLEAN_CACHE
421434
{
@@ -713,12 +726,12 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
713726
MIDR_FIXED(MIDR_CPU_VAR_REV(1,1), BIT(25)),
714727
},
715728
#endif
716-
#ifdef CONFIG_ARM64_ERRATUM_2966298
729+
#ifdef CONFIG_ARM64_WORKAROUND_SPECULATIVE_UNPRIV_LOAD
717730
{
718-
.desc = "ARM erratum 2966298",
719-
.capability = ARM64_WORKAROUND_2966298,
731+
.desc = "ARM errata 2966298, 3117295",
732+
.capability = ARM64_WORKAROUND_SPECULATIVE_UNPRIV_LOAD,
720733
/* Cortex-A520 r0p0 - r0p1 */
721-
ERRATA_MIDR_REV_RANGE(MIDR_CORTEX_A520, 0, 0, 1),
734+
ERRATA_MIDR_RANGE_LIST(erratum_spec_unpriv_load_list),
722735
},
723736
#endif
724737
#ifdef CONFIG_AMPERE_ERRATUM_AC03_CPU_38

arch/arm64/kernel/entry.S

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -428,16 +428,9 @@ alternative_else_nop_endif
428428
ldp x28, x29, [sp, #16 * 14]
429429

430430
.if \el == 0
431-
alternative_if ARM64_WORKAROUND_2966298
432-
tlbi vale1, xzr
433-
dsb nsh
434-
alternative_else_nop_endif
435-
alternative_if_not ARM64_UNMAP_KERNEL_AT_EL0
436-
ldr lr, [sp, #S_LR]
437-
add sp, sp, #PT_REGS_SIZE // restore sp
438-
eret
439-
alternative_else_nop_endif
440431
#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
432+
alternative_insn "b .L_skip_tramp_exit_\@", nop, ARM64_UNMAP_KERNEL_AT_EL0
433+
441434
msr far_el1, x29
442435

443436
ldr_this_cpu x30, this_cpu_vector, x29
@@ -446,16 +439,26 @@ alternative_else_nop_endif
446439
ldr lr, [sp, #S_LR] // restore x30
447440
add sp, sp, #PT_REGS_SIZE // restore sp
448441
br x29
442+
443+
.L_skip_tramp_exit_\@:
449444
#endif
450-
.else
445+
.endif
446+
451447
ldr lr, [sp, #S_LR]
452448
add sp, sp, #PT_REGS_SIZE // restore sp
453449

450+
.if \el == 0
451+
/* This must be after the last explicit memory access */
452+
alternative_if ARM64_WORKAROUND_SPECULATIVE_UNPRIV_LOAD
453+
tlbi vale1, xzr
454+
dsb nsh
455+
alternative_else_nop_endif
456+
.else
454457
/* Ensure any device/NC reads complete */
455458
alternative_insn nop, "dmb sy", ARM64_WORKAROUND_1508412
459+
.endif
456460

457461
eret
458-
.endif
459462
sb
460463
.endm
461464

arch/arm64/kernel/fpsimd.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -898,10 +898,8 @@ int vec_set_vector_length(struct task_struct *task, enum vec_type type,
898898
* allocate SVE now in case it is needed for use in streaming
899899
* mode.
900900
*/
901-
if (system_supports_sve()) {
902-
sve_free(task);
903-
sve_alloc(task, true);
904-
}
901+
sve_free(task);
902+
sve_alloc(task, true);
905903

906904
if (free_sme)
907905
sme_free(task);
@@ -1219,8 +1217,10 @@ void fpsimd_release_task(struct task_struct *dead_task)
12191217
*/
12201218
void sme_alloc(struct task_struct *task, bool flush)
12211219
{
1222-
if (task->thread.sme_state && flush) {
1223-
memset(task->thread.sme_state, 0, sme_state_size(task));
1220+
if (task->thread.sme_state) {
1221+
if (flush)
1222+
memset(task->thread.sme_state, 0,
1223+
sme_state_size(task));
12241224
return;
12251225
}
12261226

arch/arm64/kernel/ptrace.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,12 +1108,13 @@ static int za_set(struct task_struct *target,
11081108
}
11091109
}
11101110

1111-
/* Allocate/reinit ZA storage */
1112-
sme_alloc(target, true);
1113-
if (!target->thread.sme_state) {
1114-
ret = -ENOMEM;
1115-
goto out;
1116-
}
1111+
/*
1112+
* Only flush the storage if PSTATE.ZA was not already set,
1113+
* otherwise preserve any existing data.
1114+
*/
1115+
sme_alloc(target, !thread_za_enabled(&target->thread));
1116+
if (!target->thread.sme_state)
1117+
return -ENOMEM;
11171118

11181119
/* If there is no data then disable ZA */
11191120
if (!count) {

0 commit comments

Comments
 (0)