Skip to content

Commit 0e2adab

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: "The main thing here is a long-awaited workaround for a CPU erratum on ThunderX2 which we have developed in conjunction with engineers from Cavium/Marvell. At the moment, the workaround is unconditionally enabled for affected CPUs at runtime but we may add a command-line option to disable it in future if performance numbers show up indicating a significant cost for real workloads. Summary: - Work around Cavium/Marvell ThunderX2 erratum #219 - Fix regression in mlock() ABI caused by sign-extension of TTBR1 addresses - More fixes to the spurious kernel fault detection logic - Fix pathological preemption race when enabling some CPU features at boot - Drop broken kcore macros in favour of generic implementations - Fix userspace view of ID_AA64ZFR0_EL1 when SVE is disabled - Avoid NULL dereference on allocation failure during hibernation" * tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: arm64: tags: Preserve tags for addresses translated via TTBR1 arm64: mm: fix inverted PAR_EL1.F check arm64: sysreg: fix incorrect definition of SYS_PAR_EL1_F arm64: entry.S: Do not preempt from IRQ before all cpufeatures are enabled arm64: hibernate: check pgd table allocation arm64: cpufeature: Treat ID_AA64ZFR0_EL1 as RAZ when SVE is not enabled arm64: Fix kcore macros after 52-bit virtual addressing fallout arm64: Allow CAVIUM_TX2_ERRATUM_219 to be selected arm64: Avoid Cavium TX2 erratum 219 when switching TTBR arm64: Enable workaround for Cavium TX2 erratum 219 when running SMT arm64: KVM: Trap VM ops when ARM64_WORKAROUND_CAVIUM_TX2_219_TVM is set
2 parents ad32fd7 + 777d062 commit 0e2adab

File tree

15 files changed

+186
-23
lines changed

15 files changed

+186
-23
lines changed

Documentation/arm64/silicon-errata.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ stable kernels.
107107
+----------------+-----------------+-----------------+-----------------------------+
108108
| Cavium | ThunderX2 SMMUv3| #126 | N/A |
109109
+----------------+-----------------+-----------------+-----------------------------+
110+
| Cavium | ThunderX2 Core | #219 | CAVIUM_TX2_ERRATUM_219 |
111+
+----------------+-----------------+-----------------+-----------------------------+
110112
+----------------+-----------------+-----------------+-----------------------------+
111113
| Freescale/NXP | LS2080A/LS1043A | A-008585 | FSL_ERRATUM_A008585 |
112114
+----------------+-----------------+-----------------+-----------------------------+

arch/arm64/Kconfig

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,23 @@ config CAVIUM_ERRATUM_30115
616616

617617
If unsure, say Y.
618618

619+
config CAVIUM_TX2_ERRATUM_219
620+
bool "Cavium ThunderX2 erratum 219: PRFM between TTBR change and ISB fails"
621+
default y
622+
help
623+
On Cavium ThunderX2, a load, store or prefetch instruction between a
624+
TTBR update and the corresponding context synchronizing operation can
625+
cause a spurious Data Abort to be delivered to any hardware thread in
626+
the CPU core.
627+
628+
Work around the issue by avoiding the problematic code sequence and
629+
trapping KVM guest TTBRx_EL1 writes to EL2 when SMT is enabled. The
630+
trap handler performs the corresponding register access, skips the
631+
instruction and ensures context synchronization by virtue of the
632+
exception return.
633+
634+
If unsure, say Y.
635+
619636
config QCOM_FALKOR_ERRATUM_1003
620637
bool "Falkor E1003: Incorrect translation due to ASID change"
621638
default y

arch/arm64/include/asm/asm-uaccess.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,9 @@ alternative_else_nop_endif
7878
/*
7979
* Remove the address tag from a virtual address, if present.
8080
*/
81-
.macro clear_address_tag, dst, addr
82-
tst \addr, #(1 << 55)
83-
bic \dst, \addr, #(0xff << 56)
84-
csel \dst, \dst, \addr, eq
81+
.macro untagged_addr, dst, addr
82+
sbfx \dst, \addr, #0, #56
83+
and \dst, \dst, \addr
8584
.endm
8685

8786
#endif

arch/arm64/include/asm/cpucaps.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@
5252
#define ARM64_HAS_IRQ_PRIO_MASKING 42
5353
#define ARM64_HAS_DCPODP 43
5454
#define ARM64_WORKAROUND_1463225 44
55+
#define ARM64_WORKAROUND_CAVIUM_TX2_219_TVM 45
56+
#define ARM64_WORKAROUND_CAVIUM_TX2_219_PRFM 46
5557

56-
#define ARM64_NCAPS 45
58+
#define ARM64_NCAPS 47
5759

5860
#endif /* __ASM_CPUCAPS_H */

arch/arm64/include/asm/memory.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,12 +215,18 @@ static inline unsigned long kaslr_offset(void)
215215
* up with a tagged userland pointer. Clear the tag to get a sane pointer to
216216
* pass on to access_ok(), for instance.
217217
*/
218-
#define untagged_addr(addr) \
218+
#define __untagged_addr(addr) \
219219
((__force __typeof__(addr))sign_extend64((__force u64)(addr), 55))
220220

221+
#define untagged_addr(addr) ({ \
222+
u64 __addr = (__force u64)addr; \
223+
__addr &= __untagged_addr(__addr); \
224+
(__force __typeof__(addr))__addr; \
225+
})
226+
221227
#ifdef CONFIG_KASAN_SW_TAGS
222228
#define __tag_shifted(tag) ((u64)(tag) << 56)
223-
#define __tag_reset(addr) untagged_addr(addr)
229+
#define __tag_reset(addr) __untagged_addr(addr)
224230
#define __tag_get(addr) (__u8)((u64)(addr) >> 56)
225231
#else
226232
#define __tag_shifted(tag) 0UL

arch/arm64/include/asm/pgtable.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -876,9 +876,6 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
876876

877877
#define update_mmu_cache_pmd(vma, address, pmd) do { } while (0)
878878

879-
#define kc_vaddr_to_offset(v) ((v) & ~PAGE_END)
880-
#define kc_offset_to_vaddr(o) ((o) | PAGE_END)
881-
882879
#ifdef CONFIG_ARM64_PA_BITS_52
883880
#define phys_to_ttbr(addr) (((addr) | ((addr) >> 46)) & TTBR_BADDR_MASK_52)
884881
#else

arch/arm64/include/asm/sysreg.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@
212212
#define SYS_FAR_EL1 sys_reg(3, 0, 6, 0, 0)
213213
#define SYS_PAR_EL1 sys_reg(3, 0, 7, 4, 0)
214214

215-
#define SYS_PAR_EL1_F BIT(1)
215+
#define SYS_PAR_EL1_F BIT(0)
216216
#define SYS_PAR_EL1_FST GENMASK(6, 1)
217217

218218
/*** Statistical Profiling Extension ***/

arch/arm64/kernel/cpu_errata.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <asm/cpu.h>
1313
#include <asm/cputype.h>
1414
#include <asm/cpufeature.h>
15+
#include <asm/smp_plat.h>
1516

1617
static bool __maybe_unused
1718
is_affected_midr_range(const struct arm64_cpu_capabilities *entry, int scope)
@@ -623,6 +624,30 @@ check_branch_predictor(const struct arm64_cpu_capabilities *entry, int scope)
623624
return (need_wa > 0);
624625
}
625626

627+
static const __maybe_unused struct midr_range tx2_family_cpus[] = {
628+
MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
629+
MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
630+
{},
631+
};
632+
633+
static bool __maybe_unused
634+
needs_tx2_tvm_workaround(const struct arm64_cpu_capabilities *entry,
635+
int scope)
636+
{
637+
int i;
638+
639+
if (!is_affected_midr_range_list(entry, scope) ||
640+
!is_hyp_mode_available())
641+
return false;
642+
643+
for_each_possible_cpu(i) {
644+
if (MPIDR_AFFINITY_LEVEL(cpu_logical_map(i), 0) != 0)
645+
return true;
646+
}
647+
648+
return false;
649+
}
650+
626651
#ifdef CONFIG_HARDEN_EL2_VECTORS
627652

628653
static const struct midr_range arm64_harden_el2_vectors[] = {
@@ -851,6 +876,19 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
851876
.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
852877
.matches = has_cortex_a76_erratum_1463225,
853878
},
879+
#endif
880+
#ifdef CONFIG_CAVIUM_TX2_ERRATUM_219
881+
{
882+
.desc = "Cavium ThunderX2 erratum 219 (KVM guest sysreg trapping)",
883+
.capability = ARM64_WORKAROUND_CAVIUM_TX2_219_TVM,
884+
ERRATA_MIDR_RANGE_LIST(tx2_family_cpus),
885+
.matches = needs_tx2_tvm_workaround,
886+
},
887+
{
888+
.desc = "Cavium ThunderX2 erratum 219 (PRFM removal)",
889+
.capability = ARM64_WORKAROUND_CAVIUM_TX2_219_PRFM,
890+
ERRATA_MIDR_RANGE_LIST(tx2_family_cpus),
891+
},
854892
#endif
855893
{
856894
}

arch/arm64/kernel/cpufeature.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,16 @@ static const struct arm64_ftr_bits ftr_id_aa64pfr1[] = {
176176
};
177177

178178
static const struct arm64_ftr_bits ftr_id_aa64zfr0[] = {
179-
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_SM4_SHIFT, 4, 0),
180-
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_SHA3_SHIFT, 4, 0),
181-
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_BITPERM_SHIFT, 4, 0),
182-
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_AES_SHIFT, 4, 0),
183-
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_SVEVER_SHIFT, 4, 0),
179+
ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SVE),
180+
FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_SM4_SHIFT, 4, 0),
181+
ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SVE),
182+
FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_SHA3_SHIFT, 4, 0),
183+
ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SVE),
184+
FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_BITPERM_SHIFT, 4, 0),
185+
ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SVE),
186+
FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_AES_SHIFT, 4, 0),
187+
ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SVE),
188+
FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_SVEVER_SHIFT, 4, 0),
184189
ARM64_FTR_END,
185190
};
186191

arch/arm64/kernel/entry.S

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@ el1_da:
604604
*/
605605
mrs x3, far_el1
606606
inherit_daif pstate=x23, tmp=x2
607-
clear_address_tag x0, x3
607+
untagged_addr x0, x3
608608
mov x2, sp // struct pt_regs
609609
bl do_mem_abort
610610

@@ -680,7 +680,7 @@ alternative_if ARM64_HAS_IRQ_PRIO_MASKING
680680
orr x24, x24, x0
681681
alternative_else_nop_endif
682682
cbnz x24, 1f // preempt count != 0 || NMI return path
683-
bl preempt_schedule_irq // irq en/disable is done inside
683+
bl arm64_preempt_schedule_irq // irq en/disable is done inside
684684
1:
685685
#endif
686686

@@ -808,7 +808,7 @@ el0_da:
808808
mrs x26, far_el1
809809
ct_user_exit_irqoff
810810
enable_daif
811-
clear_address_tag x0, x26
811+
untagged_addr x0, x26
812812
mov x1, x25
813813
mov x2, sp
814814
bl do_mem_abort
@@ -1071,7 +1071,9 @@ alternative_insn isb, nop, ARM64_WORKAROUND_QCOM_FALKOR_E1003
10711071
#else
10721072
ldr x30, =vectors
10731073
#endif
1074+
alternative_if_not ARM64_WORKAROUND_CAVIUM_TX2_219_PRFM
10741075
prfm plil1strm, [x30, #(1b - tramp_vectors)]
1076+
alternative_else_nop_endif
10751077
msr vbar_el1, x30
10761078
add x30, x30, #(1b - tramp_vectors)
10771079
isb

0 commit comments

Comments
 (0)