Skip to content

Commit 3d3dd59

Browse files
committed
Merge remote-tracking branch 'stable/linux-6.18.y' into rpi-6.18.y
2 parents f58c91b + 1fe0606 commit 3d3dd59

69 files changed

Lines changed: 880 additions & 217 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Documentation/arch/arm64/silicon-errata.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,8 @@ stable kernels.
202202
+----------------+-----------------+-----------------+-----------------------------+
203203
| ARM | Neoverse-V3AE | #3312417 | ARM64_ERRATUM_3194386 |
204204
+----------------+-----------------+-----------------+-----------------------------+
205+
| ARM | C1-Pro | #4193714 | ARM64_ERRATUM_4193714 |
206+
+----------------+-----------------+-----------------+-----------------------------+
205207
| ARM | MMU-500 | #841119,826419 | ARM_SMMU_MMU_500_CPRE_ERRATA|
206208
| | | #562869,1047329 | |
207209
+----------------+-----------------+-----------------+-----------------------------+

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# SPDX-License-Identifier: GPL-2.0
22
VERSION = 6
33
PATCHLEVEL = 18
4-
SUBLEVEL = 24
4+
SUBLEVEL = 26
55
EXTRAVERSION =
66
NAME = Baby Opossum Posse
77

arch/arm64/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,6 +1155,18 @@ config ARM64_ERRATUM_3194386
11551155

11561156
If unsure, say Y.
11571157

1158+
config ARM64_ERRATUM_4193714
1159+
bool "C1-Pro: 4193714: SME DVMSync early acknowledgement"
1160+
depends on ARM64_SME
1161+
default y
1162+
help
1163+
Enable workaround for C1-Pro acknowledging the DVMSync before
1164+
the SME memory accesses are complete. This will cause TLB
1165+
maintenance for processes using SME to also issue an IPI to
1166+
the affected CPUs.
1167+
1168+
If unsure, say Y.
1169+
11581170
config CAVIUM_ERRATUM_22375
11591171
bool "Cavium erratum 22375, 24313"
11601172
default y

arch/arm64/include/asm/cpucaps.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ cpucap_is_possible(const unsigned int cap)
6666
return IS_ENABLED(CONFIG_ARM64_WORKAROUND_REPEAT_TLBI);
6767
case ARM64_WORKAROUND_SPECULATIVE_SSBS:
6868
return IS_ENABLED(CONFIG_ARM64_ERRATUM_3194386);
69+
case ARM64_WORKAROUND_4193714:
70+
return IS_ENABLED(CONFIG_ARM64_ERRATUM_4193714);
6971
case ARM64_MPAM:
7072
/*
7173
* KVM MPAM support doesn't rely on the host kernel supporting MPAM.

arch/arm64/include/asm/cputype.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898
#define ARM_CPU_PART_CORTEX_A725 0xD87
9999
#define ARM_CPU_PART_CORTEX_A720AE 0xD89
100100
#define ARM_CPU_PART_NEOVERSE_N3 0xD8E
101+
#define ARM_CPU_PART_C1_PRO 0xD8B
101102

102103
#define APM_CPU_PART_XGENE 0x000
103104
#define APM_CPU_VAR_POTENZA 0x00
@@ -189,6 +190,7 @@
189190
#define MIDR_CORTEX_A725 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A725)
190191
#define MIDR_CORTEX_A720AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A720AE)
191192
#define MIDR_NEOVERSE_N3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N3)
193+
#define MIDR_C1_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_C1_PRO)
192194
#define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
193195
#define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
194196
#define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX)

arch/arm64/include/asm/fpsimd.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,24 @@ static inline size_t sme_state_size(struct task_struct const *task)
428428
return __sme_state_size(task_get_sme_vl(task));
429429
}
430430

431+
void sme_enable_dvmsync(void);
432+
void sme_set_active(void);
433+
void sme_clear_active(void);
434+
435+
static inline void sme_enter_from_user_mode(void)
436+
{
437+
if (alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714) &&
438+
test_thread_flag(TIF_SME))
439+
sme_clear_active();
440+
}
441+
442+
static inline void sme_exit_to_user_mode(void)
443+
{
444+
if (alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714) &&
445+
test_thread_flag(TIF_SME))
446+
sme_set_active();
447+
}
448+
431449
#else
432450

433451
static inline void sme_user_disable(void) { BUILD_BUG(); }
@@ -456,6 +474,9 @@ static inline size_t sme_state_size(struct task_struct const *task)
456474
return 0;
457475
}
458476

477+
static inline void sme_enter_from_user_mode(void) { }
478+
static inline void sme_exit_to_user_mode(void) { }
479+
459480
#endif /* ! CONFIG_ARM64_SME */
460481

461482
/* For use by EFI runtime services calls only */

arch/arm64/include/asm/tlbbatch.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,17 @@
22
#ifndef _ARCH_ARM64_TLBBATCH_H
33
#define _ARCH_ARM64_TLBBATCH_H
44

5+
#include <linux/cpumask.h>
6+
57
struct arch_tlbflush_unmap_batch {
8+
#ifdef CONFIG_ARM64_ERRATUM_4193714
69
/*
7-
* For arm64, HW can do tlb shootdown, so we don't
8-
* need to record cpumask for sending IPI
10+
* Track CPUs that need SME DVMSync on completion of this batch.
11+
* Otherwise, the arm64 HW can do tlb shootdown, so we don't need to
12+
* record cpumask for sending IPI
913
*/
14+
cpumask_var_t cpumask;
15+
#endif
1016
};
1117

1218
#endif /* _ARCH_ARM64_TLBBATCH_H */

arch/arm64/include/asm/tlbflush.h

Lines changed: 117 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,11 @@
3131
*/
3232
#define __TLBI_0(op, arg) asm (ARM64_ASM_PREAMBLE \
3333
"tlbi " #op "\n" \
34-
ALTERNATIVE("nop\n nop", \
35-
"dsb ish\n tlbi " #op, \
36-
ARM64_WORKAROUND_REPEAT_TLBI, \
37-
CONFIG_ARM64_WORKAROUND_REPEAT_TLBI) \
3834
: : )
3935

4036
#define __TLBI_1(op, arg) asm (ARM64_ASM_PREAMBLE \
41-
"tlbi " #op ", %0\n" \
42-
ALTERNATIVE("nop\n nop", \
43-
"dsb ish\n tlbi " #op ", %0", \
44-
ARM64_WORKAROUND_REPEAT_TLBI, \
45-
CONFIG_ARM64_WORKAROUND_REPEAT_TLBI) \
46-
: : "r" (arg))
37+
"tlbi " #op ", %x0\n" \
38+
: : "rZ" (arg))
4739

4840
#define __TLBI_N(op, arg, n, ...) __TLBI_##n(op, arg)
4941

@@ -88,6 +80,71 @@ static inline unsigned long get_trans_granule(void)
8880
}
8981
}
9082

83+
#ifdef CONFIG_ARM64_ERRATUM_4193714
84+
85+
void sme_do_dvmsync(const struct cpumask *mask);
86+
87+
static inline void sme_dvmsync(struct mm_struct *mm)
88+
{
89+
if (!alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714))
90+
return;
91+
92+
sme_do_dvmsync(mm_cpumask(mm));
93+
}
94+
95+
static inline void sme_dvmsync_add_pending(struct arch_tlbflush_unmap_batch *batch,
96+
struct mm_struct *mm)
97+
{
98+
if (!alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714))
99+
return;
100+
101+
/*
102+
* Order the mm_cpumask() read after the hardware DVMSync.
103+
*/
104+
dsb(ish);
105+
if (cpumask_empty(mm_cpumask(mm)))
106+
return;
107+
108+
/*
109+
* Allocate the batch cpumask on first use. Fall back to an immediate
110+
* IPI for this mm in case of failure.
111+
*/
112+
if (!cpumask_available(batch->cpumask) &&
113+
!zalloc_cpumask_var(&batch->cpumask, GFP_ATOMIC)) {
114+
sme_do_dvmsync(mm_cpumask(mm));
115+
return;
116+
}
117+
118+
cpumask_or(batch->cpumask, batch->cpumask, mm_cpumask(mm));
119+
}
120+
121+
static inline void sme_dvmsync_batch(struct arch_tlbflush_unmap_batch *batch)
122+
{
123+
if (!alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714))
124+
return;
125+
126+
if (!cpumask_available(batch->cpumask))
127+
return;
128+
129+
sme_do_dvmsync(batch->cpumask);
130+
cpumask_clear(batch->cpumask);
131+
}
132+
133+
#else
134+
135+
static inline void sme_dvmsync(struct mm_struct *mm)
136+
{
137+
}
138+
static inline void sme_dvmsync_add_pending(struct arch_tlbflush_unmap_batch *batch,
139+
struct mm_struct *mm)
140+
{
141+
}
142+
static inline void sme_dvmsync_batch(struct arch_tlbflush_unmap_batch *batch)
143+
{
144+
}
145+
146+
#endif /* CONFIG_ARM64_ERRATUM_4193714 */
147+
91148
/*
92149
* Level-based TLBI operations.
93150
*
@@ -181,6 +238,48 @@ static inline unsigned long get_trans_granule(void)
181238
(__pages >> (5 * (scale) + 1)) - 1; \
182239
})
183240

241+
#define __repeat_tlbi_sync(op, arg...) \
242+
do { \
243+
if (!alternative_has_cap_unlikely(ARM64_WORKAROUND_REPEAT_TLBI)) \
244+
break; \
245+
__tlbi(op, ##arg); \
246+
dsb(ish); \
247+
} while (0)
248+
249+
/*
250+
* Complete broadcast TLB maintenance issued by the host which invalidates
251+
* stage 1 information in the host's own translation regime.
252+
*/
253+
static inline void __tlbi_sync_s1ish(struct mm_struct *mm)
254+
{
255+
dsb(ish);
256+
__repeat_tlbi_sync(vale1is, 0);
257+
sme_dvmsync(mm);
258+
}
259+
260+
static inline void __tlbi_sync_s1ish_batch(struct arch_tlbflush_unmap_batch *batch)
261+
{
262+
dsb(ish);
263+
__repeat_tlbi_sync(vale1is, 0);
264+
sme_dvmsync_batch(batch);
265+
}
266+
267+
static inline void __tlbi_sync_s1ish_kernel(void)
268+
{
269+
dsb(ish);
270+
__repeat_tlbi_sync(vale1is, 0);
271+
}
272+
273+
/*
274+
* Complete broadcast TLB maintenance issued by hyp code which invalidates
275+
* stage 1 translation information in any translation regime.
276+
*/
277+
static inline void __tlbi_sync_s1ish_hyp(void)
278+
{
279+
dsb(ish);
280+
__repeat_tlbi_sync(vale2is, 0);
281+
}
282+
184283
/*
185284
* TLB Invalidation
186285
* ================
@@ -266,7 +365,7 @@ static inline void flush_tlb_all(void)
266365
{
267366
dsb(ishst);
268367
__tlbi(vmalle1is);
269-
dsb(ish);
368+
__tlbi_sync_s1ish_kernel();
270369
isb();
271370
}
272371

@@ -278,7 +377,7 @@ static inline void flush_tlb_mm(struct mm_struct *mm)
278377
asid = __TLBI_VADDR(0, ASID(mm));
279378
__tlbi(aside1is, asid);
280379
__tlbi_user(aside1is, asid);
281-
dsb(ish);
380+
__tlbi_sync_s1ish(mm);
282381
mmu_notifier_arch_invalidate_secondary_tlbs(mm, 0, -1UL);
283382
}
284383

@@ -305,20 +404,11 @@ static inline void flush_tlb_page(struct vm_area_struct *vma,
305404
unsigned long uaddr)
306405
{
307406
flush_tlb_page_nosync(vma, uaddr);
308-
dsb(ish);
407+
__tlbi_sync_s1ish(vma->vm_mm);
309408
}
310409

311410
static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm)
312411
{
313-
/*
314-
* TLB flush deferral is not required on systems which are affected by
315-
* ARM64_WORKAROUND_REPEAT_TLBI, as __tlbi()/__tlbi_user() implementation
316-
* will have two consecutive TLBI instructions with a dsb(ish) in between
317-
* defeating the purpose (i.e save overall 'dsb ish' cost).
318-
*/
319-
if (alternative_has_cap_unlikely(ARM64_WORKAROUND_REPEAT_TLBI))
320-
return false;
321-
322412
return true;
323413
}
324414

@@ -334,7 +424,7 @@ static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm)
334424
*/
335425
static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch)
336426
{
337-
dsb(ish);
427+
__tlbi_sync_s1ish_batch(batch);
338428
}
339429

340430
/*
@@ -469,7 +559,7 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma,
469559
{
470560
__flush_tlb_range_nosync(vma->vm_mm, start, end, stride,
471561
last_level, tlb_level);
472-
dsb(ish);
562+
__tlbi_sync_s1ish(vma->vm_mm);
473563
}
474564

475565
static inline void flush_tlb_range(struct vm_area_struct *vma,
@@ -501,7 +591,7 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end
501591
dsb(ishst);
502592
__flush_tlb_range_op(vaale1is, start, pages, stride, 0,
503593
TLBI_TTL_UNKNOWN, false, lpa2_is_enabled());
504-
dsb(ish);
594+
__tlbi_sync_s1ish_kernel();
505595
isb();
506596
}
507597

@@ -515,14 +605,15 @@ static inline void __flush_tlb_kernel_pgtable(unsigned long kaddr)
515605

516606
dsb(ishst);
517607
__tlbi(vaae1is, addr);
518-
dsb(ish);
608+
__tlbi_sync_s1ish_kernel();
519609
isb();
520610
}
521611

522612
static inline void arch_tlbbatch_add_pending(struct arch_tlbflush_unmap_batch *batch,
523613
struct mm_struct *mm, unsigned long start, unsigned long end)
524614
{
525615
__flush_tlb_range_nosync(mm, start, end, PAGE_SIZE, true, 3);
616+
sme_dvmsync_add_pending(batch, mm);
526617
}
527618
#endif
528619

arch/arm64/kernel/cpu_errata.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <asm/cpu.h>
1212
#include <asm/cputype.h>
1313
#include <asm/cpufeature.h>
14+
#include <asm/fpsimd.h>
1415
#include <asm/kvm_asm.h>
1516
#include <asm/smp_plat.h>
1617

@@ -551,6 +552,23 @@ static const struct midr_range erratum_spec_ssbs_list[] = {
551552
};
552553
#endif
553554

555+
#ifdef CONFIG_ARM64_ERRATUM_4193714
556+
static bool has_sme_dvmsync_erratum(const struct arm64_cpu_capabilities *entry,
557+
int scope)
558+
{
559+
if (!id_aa64pfr1_sme(read_sanitised_ftr_reg(SYS_ID_AA64PFR1_EL1)))
560+
return false;
561+
562+
return is_affected_midr_range(entry, scope);
563+
}
564+
565+
static void cpu_enable_sme_dvmsync(const struct arm64_cpu_capabilities *__unused)
566+
{
567+
if (this_cpu_has_cap(ARM64_WORKAROUND_4193714))
568+
sme_enable_dvmsync();
569+
}
570+
#endif
571+
554572
#ifdef CONFIG_AMPERE_ERRATUM_AC03_CPU_38
555573
static const struct midr_range erratum_ac03_cpu_38_list[] = {
556574
MIDR_ALL_VERSIONS(MIDR_AMPERE1),
@@ -870,6 +888,18 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
870888
ERRATA_MIDR_RANGE_LIST(erratum_spec_ssbs_list),
871889
},
872890
#endif
891+
#ifdef CONFIG_ARM64_ERRATUM_4193714
892+
{
893+
.desc = "C1-Pro SME DVMSync early acknowledgement",
894+
.capability = ARM64_WORKAROUND_4193714,
895+
.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
896+
.matches = has_sme_dvmsync_erratum,
897+
.cpu_enable = cpu_enable_sme_dvmsync,
898+
/* C1-Pro r0p0 - r1p2 (the latter only when REVIDR_EL1[0]==0) */
899+
.midr_range = MIDR_RANGE(MIDR_C1_PRO, 0, 0, 1, 2),
900+
MIDR_FIXED(MIDR_CPU_VAR_REV(1, 2), BIT(0)),
901+
},
902+
#endif
873903
#ifdef CONFIG_ARM64_WORKAROUND_SPECULATIVE_UNPRIV_LOAD
874904
{
875905
.desc = "ARM errata 2966298, 3117295",

0 commit comments

Comments
 (0)