Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branches 'for-next/misc', 'for-next/cache-ops-dzp', 'for-next/stacktrace', 'for-next/xor-neon', 'for-next/kasan', 'for-next/armv8_7-fp', 'for-next/atomics', 'for-next/bti', 'for-next/sve', 'for-next/kselftest' and 'for-next/kcsan', remote-tracking branch 'arm64/for-next/perf' into for-next/core

* arm64/for-next/perf: (32 commits)
arm64: perf: Don't register user access sysctl handler multiple times
drivers: perf: marvell_cn10k: fix an IS_ERR() vs NULL check
perf/smmuv3: Fix unused variable warning when CONFIG_OF=n
arm64: perf: Support new DT compatibles
arm64: perf: Simplify registration boilerplate
arm64: perf: Support Denver and Carmel PMUs
drivers/perf: hisi: Add driver for HiSilicon PCIe PMU
docs: perf: Add description for HiSilicon PCIe PMU driver
dt-bindings: perf: Add YAML schemas for Marvell CN10K LLC-TAD pmu bindings
drivers: perf: Add LLC-TAD perf counter support
perf/smmuv3: Synthesize IIDR from CoreSight ID registers
perf/smmuv3: Add devicetree support
dt-bindings: Add Arm SMMUv3 PMCG binding
perf/arm-cmn: Add debugfs topology info
perf/arm-cmn: Add CI-700 Support
dt-bindings: perf: arm-cmn: Add CI-700
perf/arm-cmn: Support new IP features
perf/arm-cmn: Demarcate CMN-600 specifics
perf/arm-cmn: Move group validation data off-stack
perf/arm-cmn: Optimise DTC counter accesses
...

* for-next/misc:
: Miscellaneous patches
arm64: Use correct method to calculate nomap region boundaries
arm64: Drop outdated links in comments
arm64: errata: Fix exec handling in erratum 1418040 workaround
arm64: Unhash early pointer print plus improve comment
asm-generic: introduce io_stop_wc() and add implementation for ARM64
arm64: remove __dma_*_area() aliases
docs/arm64: delete a space from tagged-address-abi
arm64/fp: Add comments documenting the usage of state restore functions
arm64: mm: Use asid feature macro for cheanup
arm64: mm: Rename asid2idx() to ctxid2asid()
arm64: kexec: reduce calls to page_address()
arm64: extable: remove unused ex_handler_t definition
arm64: entry: Use SDEI event constants
arm64: Simplify checking for populated DT
arm64/kvm: Fix bitrotted comment for SVE handling in handle_exit.c

* for-next/cache-ops-dzp:
: Avoid DC instructions when DCZID_EL0.DZP == 1
arm64: mte: DC {GVA,GZVA} shouldn't be used when DCZID_EL0.DZP == 1
arm64: clear_page() shouldn't use DC ZVA when DCZID_EL0.DZP == 1

* for-next/stacktrace:
: Unify the arm64 unwind code
arm64: Make some stacktrace functions private
arm64: Make dump_backtrace() use arch_stack_walk()
arm64: Make profile_pc() use arch_stack_walk()
arm64: Make return_address() use arch_stack_walk()
arm64: Make __get_wchan() use arch_stack_walk()
arm64: Make perf_callchain_kernel() use arch_stack_walk()
arm64: Mark __switch_to() as __sched
arm64: Add comment for stack_info::kr_cur
arch: Make ARCH_STACKWALK independent of STACKTRACE

* for-next/xor-neon:
: Use SHA3 instructions to speed up XOR
arm64/xor: use EOR3 instructions when available

* for-next/kasan:
: Log potential KASAN shadow aliases
arm64: mm: log potential KASAN shadow alias
arm64: mm: use die_kernel_fault() in do_mem_abort()

* for-next/armv8_7-fp:
: Add HWCAPS for ARMv8.7 FEAT_AFP amd FEAT_RPRES
arm64: cpufeature: add HWCAP for FEAT_RPRES
arm64: add ID_AA64ISAR2_EL1 sys register
arm64: cpufeature: add HWCAP for FEAT_AFP

* for-next/atomics:
: arm64 atomics clean-ups and codegen improvements
arm64: atomics: lse: define RETURN ops in terms of FETCH ops
arm64: atomics: lse: improve constraints for simple ops
arm64: atomics: lse: define ANDs in terms of ANDNOTs
arm64: atomics lse: define SUBs in terms of ADDs
arm64: atomics: format whitespace consistently

* for-next/bti:
: BTI clean-ups
arm64: Ensure that the 'bti' macro is defined where linkage.h is included
arm64: Use BTI C directly and unconditionally
arm64: Unconditionally override SYM_FUNC macros
arm64: Add macro version of the BTI instruction
arm64: ftrace: add missing BTIs
arm64: kexec: use __pa_symbol(empty_zero_page)
arm64: update PAC description for kernel

* for-next/sve:
: SVE code clean-ups and refactoring in prepararation of Scalable Matrix Extensions
arm64/sve: Minor clarification of ABI documentation
arm64/sve: Generalise vector length configuration prctl() for SME
arm64/sve: Make sysctl interface for SVE reusable by SME

* for-next/kselftest:
: arm64 kselftest additions
kselftest/arm64: Add pidbench for floating point syscall cases
kselftest/arm64: Add a test program to exercise the syscall ABI
kselftest/arm64: Allow signal tests to trigger from a function
kselftest/arm64: Parameterise ptrace vector length information

* for-next/kcsan:
: Enable KCSAN for arm64
arm64: Enable KCSAN

+1438 -626
+17
Documentation/arm64/cpu-feature-registers.rst
··· 275 275 | SVEVer | [3-0] | y | 276 276 +------------------------------+---------+---------+ 277 277 278 + 8) ID_AA64MMFR1_EL1 - Memory model feature register 1 279 + 280 + +------------------------------+---------+---------+ 281 + | Name | bits | visible | 282 + +------------------------------+---------+---------+ 283 + | AFP | [47-44] | y | 284 + +------------------------------+---------+---------+ 285 + 286 + 9) ID_AA64ISAR2_EL1 - Instruction set attribute register 2 287 + 288 + +------------------------------+---------+---------+ 289 + | Name | bits | visible | 290 + +------------------------------+---------+---------+ 291 + | RPRES | [7-4] | y | 292 + +------------------------------+---------+---------+ 293 + 294 + 278 295 Appendix I: Example 279 296 ------------------- 280 297
+8
Documentation/arm64/elf_hwcaps.rst
··· 251 251 252 252 Functionality implied by ID_AA64MMFR0_EL1.ECV == 0b0001. 253 253 254 + HWCAP2_AFP 255 + 256 + Functionality implied by ID_AA64MFR1_EL1.AFP == 0b0001. 257 + 258 + HWCAP2_RPRES 259 + 260 + Functionality implied by ID_AA64ISAR2_EL1.RPRES == 0b0001. 261 + 254 262 4. Unused AT_HWCAP bits 255 263 ----------------------- 256 264
+4 -5
Documentation/arm64/pointer-authentication.rst
··· 53 53 virtual address size configured by the kernel. For example, with a 54 54 virtual address size of 48, the PAC is 7 bits wide. 55 55 56 - Recent versions of GCC can compile code with APIAKey-based return 57 - address protection when passed the -msign-return-address option. This 58 - uses instructions in the HINT space (unless -march=armv8.3-a or higher 59 - is also passed), and such code can run on systems without the pointer 60 - authentication extension. 56 + When ARM64_PTR_AUTH_KERNEL is selected, the kernel will be compiled 57 + with HINT space pointer authentication instructions protecting 58 + function returns. Kernels built with this option will work on hardware 59 + with or without pointer authentication support. 61 60 62 61 In addition to exec(), keys can also be reinitialized to random values 63 62 using the PR_PAC_RESET_KEYS prctl. A bitmask of PR_PAC_APIAKEY,
+1 -1
Documentation/arm64/sve.rst
··· 255 255 vector length change (which would only normally be the case between a 256 256 fork() or vfork() and the corresponding execve() in typical use). 257 257 258 - To extract the vector length from the result, and it with 258 + To extract the vector length from the result, bitwise and it with 259 259 PR_SVE_VL_LEN_MASK. 260 260 261 261 Return value: a nonnegative value on success, or a negative value on error:
+1 -1
Documentation/arm64/tagged-address-abi.rst
··· 49 49 50 50 - ``brk()``, ``mmap()`` and the ``new_address`` argument to 51 51 ``mremap()`` as these have the potential to alias with existing 52 - user addresses. 52 + user addresses. 53 53 54 54 NOTE: This behaviour changed in v5.6 and so some earlier kernels may 55 55 incorrectly accept valid tagged pointers for the ``brk()``,
+8
Documentation/memory-barriers.txt
··· 1950 1950 For load from persistent memory, existing read memory barriers are sufficient 1951 1951 to ensure read ordering. 1952 1952 1953 + (*) io_stop_wc(); 1954 + 1955 + For memory accesses with write-combining attributes (e.g. those returned 1956 + by ioremap_wc(), the CPU may wait for prior accesses to be merged with 1957 + subsequent ones. io_stop_wc() can be used to prevent the merging of 1958 + write-combining memory accesses before this macro with those after it when 1959 + such wait has performance implications. 1960 + 1953 1961 =============================== 1954 1962 IMPLICIT KERNEL MEMORY BARRIERS 1955 1963 ===============================
+8
arch/arm64/Kconfig
··· 150 150 select HAVE_ARCH_KASAN_VMALLOC if HAVE_ARCH_KASAN 151 151 select HAVE_ARCH_KASAN_SW_TAGS if HAVE_ARCH_KASAN 152 152 select HAVE_ARCH_KASAN_HW_TAGS if (HAVE_ARCH_KASAN && ARM64_MTE) 153 + # Some instrumentation may be unsound, hence EXPERT 154 + select HAVE_ARCH_KCSAN if EXPERT 153 155 select HAVE_ARCH_KFENCE 154 156 select HAVE_ARCH_KGDB 155 157 select HAVE_ARCH_MMAP_RND_BITS ··· 1546 1544 endmenu 1547 1545 1548 1546 menu "ARMv8.2 architectural features" 1547 + 1548 + config AS_HAS_ARMV8_2 1549 + def_bool $(cc-option,-Wa$(comma)-march=armv8.2-a) 1550 + 1551 + config AS_HAS_SHA3 1552 + def_bool $(as-instr,.arch armv8.2-a+sha3) 1549 1553 1550 1554 config ARM64_PMEM 1551 1555 bool "Enable support for persistent memory"
+5
arch/arm64/Makefile
··· 58 58 include/generated/asm-offsets.h)) 59 59 endif 60 60 61 + ifeq ($(CONFIG_AS_HAS_ARMV8_2), y) 62 + # make sure to pass the newest target architecture to -march. 63 + asm-arch := armv8.2-a 64 + endif 65 + 61 66 # Ensure that if the compiler supports branch protection we default it 62 67 # off, this will be overridden if we are using branch protection. 63 68 branch-prot-flags-y += $(call cc-option,-mbranch-protection=none)
+5 -5
arch/arm64/crypto/aes-modes.S
··· 363 363 adr x16, 1f 364 364 sub x16, x16, x12, lsl #3 365 365 br x16 366 - hint 34 // bti c 366 + bti c 367 367 mov v0.d[0], vctr.d[0] 368 - hint 34 // bti c 368 + bti c 369 369 mov v1.d[0], vctr.d[0] 370 - hint 34 // bti c 370 + bti c 371 371 mov v2.d[0], vctr.d[0] 372 - hint 34 // bti c 372 + bti c 373 373 mov v3.d[0], vctr.d[0] 374 - ST5( hint 34 ) 374 + ST5( bti c ) 375 375 ST5( mov v4.d[0], vctr.d[0] ) 376 376 1: b 2f 377 377 .previous
+10
arch/arm64/include/asm/assembler.h
··· 791 791 .endm 792 792 793 793 /* 794 + * Branch Target Identifier (BTI) 795 + */ 796 + .macro bti, targets 797 + .equ .L__bti_targets_c, 34 798 + .equ .L__bti_targets_j, 36 799 + .equ .L__bti_targets_jc,38 800 + hint #.L__bti_targets_\targets 801 + .endm 802 + 803 + /* 794 804 * This macro emits a program property note section identifying 795 805 * architecture features which require special handling, mainly for 796 806 * use in assembly files included in the VDSO.
+43 -43
arch/arm64/include/asm/atomic_ll_sc.h
··· 44 44 \ 45 45 asm volatile("// atomic_" #op "\n" \ 46 46 __LL_SC_FALLBACK( \ 47 - " prfm pstl1strm, %2\n" \ 48 - "1: ldxr %w0, %2\n" \ 49 - " " #asm_op " %w0, %w0, %w3\n" \ 50 - " stxr %w1, %w0, %2\n" \ 51 - " cbnz %w1, 1b\n") \ 47 + " prfm pstl1strm, %2\n" \ 48 + "1: ldxr %w0, %2\n" \ 49 + " " #asm_op " %w0, %w0, %w3\n" \ 50 + " stxr %w1, %w0, %2\n" \ 51 + " cbnz %w1, 1b\n") \ 52 52 : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) \ 53 53 : __stringify(constraint) "r" (i)); \ 54 54 } ··· 62 62 \ 63 63 asm volatile("// atomic_" #op "_return" #name "\n" \ 64 64 __LL_SC_FALLBACK( \ 65 - " prfm pstl1strm, %2\n" \ 66 - "1: ld" #acq "xr %w0, %2\n" \ 67 - " " #asm_op " %w0, %w0, %w3\n" \ 68 - " st" #rel "xr %w1, %w0, %2\n" \ 69 - " cbnz %w1, 1b\n" \ 70 - " " #mb ) \ 65 + " prfm pstl1strm, %2\n" \ 66 + "1: ld" #acq "xr %w0, %2\n" \ 67 + " " #asm_op " %w0, %w0, %w3\n" \ 68 + " st" #rel "xr %w1, %w0, %2\n" \ 69 + " cbnz %w1, 1b\n" \ 70 + " " #mb ) \ 71 71 : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) \ 72 72 : __stringify(constraint) "r" (i) \ 73 73 : cl); \ ··· 84 84 \ 85 85 asm volatile("// atomic_fetch_" #op #name "\n" \ 86 86 __LL_SC_FALLBACK( \ 87 - " prfm pstl1strm, %3\n" \ 88 - "1: ld" #acq "xr %w0, %3\n" \ 89 - " " #asm_op " %w1, %w0, %w4\n" \ 90 - " st" #rel "xr %w2, %w1, %3\n" \ 91 - " cbnz %w2, 1b\n" \ 92 - " " #mb ) \ 87 + " prfm pstl1strm, %3\n" \ 88 + "1: ld" #acq "xr %w0, %3\n" \ 89 + " " #asm_op " %w1, %w0, %w4\n" \ 90 + " st" #rel "xr %w2, %w1, %3\n" \ 91 + " cbnz %w2, 1b\n" \ 92 + " " #mb ) \ 93 93 : "=&r" (result), "=&r" (val), "=&r" (tmp), "+Q" (v->counter) \ 94 94 : __stringify(constraint) "r" (i) \ 95 95 : cl); \ ··· 143 143 \ 144 144 asm volatile("// atomic64_" #op "\n" \ 145 145 __LL_SC_FALLBACK( \ 146 - " prfm pstl1strm, %2\n" \ 147 - "1: ldxr %0, %2\n" \ 148 - " " #asm_op " %0, %0, %3\n" \ 149 - " stxr %w1, %0, %2\n" \ 150 - " cbnz %w1, 1b") \ 146 + " prfm pstl1strm, %2\n" \ 147 + "1: ldxr %0, %2\n" \ 148 + " " #asm_op " %0, %0, %3\n" \ 149 + " stxr %w1, %0, %2\n" \ 150 + " cbnz %w1, 1b") \ 151 151 : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) \ 152 152 : __stringify(constraint) "r" (i)); \ 153 153 } ··· 161 161 \ 162 162 asm volatile("// atomic64_" #op "_return" #name "\n" \ 163 163 __LL_SC_FALLBACK( \ 164 - " prfm pstl1strm, %2\n" \ 165 - "1: ld" #acq "xr %0, %2\n" \ 166 - " " #asm_op " %0, %0, %3\n" \ 167 - " st" #rel "xr %w1, %0, %2\n" \ 168 - " cbnz %w1, 1b\n" \ 169 - " " #mb ) \ 164 + " prfm pstl1strm, %2\n" \ 165 + "1: ld" #acq "xr %0, %2\n" \ 166 + " " #asm_op " %0, %0, %3\n" \ 167 + " st" #rel "xr %w1, %0, %2\n" \ 168 + " cbnz %w1, 1b\n" \ 169 + " " #mb ) \ 170 170 : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) \ 171 171 : __stringify(constraint) "r" (i) \ 172 172 : cl); \ ··· 176 176 177 177 #define ATOMIC64_FETCH_OP(name, mb, acq, rel, cl, op, asm_op, constraint)\ 178 178 static inline long \ 179 - __ll_sc_atomic64_fetch_##op##name(s64 i, atomic64_t *v) \ 179 + __ll_sc_atomic64_fetch_##op##name(s64 i, atomic64_t *v) \ 180 180 { \ 181 181 s64 result, val; \ 182 182 unsigned long tmp; \ 183 183 \ 184 184 asm volatile("// atomic64_fetch_" #op #name "\n" \ 185 185 __LL_SC_FALLBACK( \ 186 - " prfm pstl1strm, %3\n" \ 187 - "1: ld" #acq "xr %0, %3\n" \ 188 - " " #asm_op " %1, %0, %4\n" \ 189 - " st" #rel "xr %w2, %1, %3\n" \ 190 - " cbnz %w2, 1b\n" \ 191 - " " #mb ) \ 186 + " prfm pstl1strm, %3\n" \ 187 + "1: ld" #acq "xr %0, %3\n" \ 188 + " " #asm_op " %1, %0, %4\n" \ 189 + " st" #rel "xr %w2, %1, %3\n" \ 190 + " cbnz %w2, 1b\n" \ 191 + " " #mb ) \ 192 192 : "=&r" (result), "=&r" (val), "=&r" (tmp), "+Q" (v->counter) \ 193 193 : __stringify(constraint) "r" (i) \ 194 194 : cl); \ ··· 241 241 242 242 asm volatile("// atomic64_dec_if_positive\n" 243 243 __LL_SC_FALLBACK( 244 - " prfm pstl1strm, %2\n" 245 - "1: ldxr %0, %2\n" 246 - " subs %0, %0, #1\n" 247 - " b.lt 2f\n" 248 - " stlxr %w1, %0, %2\n" 249 - " cbnz %w1, 1b\n" 250 - " dmb ish\n" 251 - "2:") 244 + " prfm pstl1strm, %2\n" 245 + "1: ldxr %0, %2\n" 246 + " subs %0, %0, #1\n" 247 + " b.lt 2f\n" 248 + " stlxr %w1, %0, %2\n" 249 + " cbnz %w1, 1b\n" 250 + " dmb ish\n" 251 + "2:") 252 252 : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) 253 253 : 254 254 : "cc", "memory");
+87 -191
arch/arm64/include/asm/atomic_lse.h
··· 11 11 #define __ASM_ATOMIC_LSE_H 12 12 13 13 #define ATOMIC_OP(op, asm_op) \ 14 - static inline void __lse_atomic_##op(int i, atomic_t *v) \ 14 + static inline void __lse_atomic_##op(int i, atomic_t *v) \ 15 15 { \ 16 16 asm volatile( \ 17 17 __LSE_PREAMBLE \ 18 - " " #asm_op " %w[i], %[v]\n" \ 19 - : [i] "+r" (i), [v] "+Q" (v->counter) \ 20 - : "r" (v)); \ 18 + " " #asm_op " %w[i], %[v]\n" \ 19 + : [v] "+Q" (v->counter) \ 20 + : [i] "r" (i)); \ 21 21 } 22 22 23 23 ATOMIC_OP(andnot, stclr) ··· 25 25 ATOMIC_OP(xor, steor) 26 26 ATOMIC_OP(add, stadd) 27 27 28 + static inline void __lse_atomic_sub(int i, atomic_t *v) 29 + { 30 + __lse_atomic_add(-i, v); 31 + } 32 + 28 33 #undef ATOMIC_OP 29 34 30 35 #define ATOMIC_FETCH_OP(name, mb, op, asm_op, cl...) \ 31 36 static inline int __lse_atomic_fetch_##op##name(int i, atomic_t *v) \ 32 37 { \ 38 + int old; \ 39 + \ 33 40 asm volatile( \ 34 41 __LSE_PREAMBLE \ 35 - " " #asm_op #mb " %w[i], %w[i], %[v]" \ 36 - : [i] "+r" (i), [v] "+Q" (v->counter) \ 37 - : "r" (v) \ 42 + " " #asm_op #mb " %w[i], %w[old], %[v]" \ 43 + : [v] "+Q" (v->counter), \ 44 + [old] "=r" (old) \ 45 + : [i] "r" (i) \ 38 46 : cl); \ 39 47 \ 40 - return i; \ 48 + return old; \ 41 49 } 42 50 43 51 #define ATOMIC_FETCH_OPS(op, asm_op) \ ··· 62 54 #undef ATOMIC_FETCH_OP 63 55 #undef ATOMIC_FETCH_OPS 64 56 65 - #define ATOMIC_OP_ADD_RETURN(name, mb, cl...) \ 66 - static inline int __lse_atomic_add_return##name(int i, atomic_t *v) \ 57 + #define ATOMIC_FETCH_OP_SUB(name) \ 58 + static inline int __lse_atomic_fetch_sub##name(int i, atomic_t *v) \ 67 59 { \ 68 - u32 tmp; \ 69 - \ 70 - asm volatile( \ 71 - __LSE_PREAMBLE \ 72 - " ldadd" #mb " %w[i], %w[tmp], %[v]\n" \ 73 - " add %w[i], %w[i], %w[tmp]" \ 74 - : [i] "+r" (i), [v] "+Q" (v->counter), [tmp] "=&r" (tmp) \ 75 - : "r" (v) \ 76 - : cl); \ 77 - \ 78 - return i; \ 60 + return __lse_atomic_fetch_add##name(-i, v); \ 79 61 } 80 62 81 - ATOMIC_OP_ADD_RETURN(_relaxed, ) 82 - ATOMIC_OP_ADD_RETURN(_acquire, a, "memory") 83 - ATOMIC_OP_ADD_RETURN(_release, l, "memory") 84 - ATOMIC_OP_ADD_RETURN( , al, "memory") 63 + ATOMIC_FETCH_OP_SUB(_relaxed) 64 + ATOMIC_FETCH_OP_SUB(_acquire) 65 + ATOMIC_FETCH_OP_SUB(_release) 66 + ATOMIC_FETCH_OP_SUB( ) 85 67 86 - #undef ATOMIC_OP_ADD_RETURN 68 + #undef ATOMIC_FETCH_OP_SUB 69 + 70 + #define ATOMIC_OP_ADD_SUB_RETURN(name) \ 71 + static inline int __lse_atomic_add_return##name(int i, atomic_t *v) \ 72 + { \ 73 + return __lse_atomic_fetch_add##name(i, v) + i; \ 74 + } \ 75 + \ 76 + static inline int __lse_atomic_sub_return##name(int i, atomic_t *v) \ 77 + { \ 78 + return __lse_atomic_fetch_sub(i, v) - i; \ 79 + } 80 + 81 + ATOMIC_OP_ADD_SUB_RETURN(_relaxed) 82 + ATOMIC_OP_ADD_SUB_RETURN(_acquire) 83 + ATOMIC_OP_ADD_SUB_RETURN(_release) 84 + ATOMIC_OP_ADD_SUB_RETURN( ) 85 + 86 + #undef ATOMIC_OP_ADD_SUB_RETURN 87 87 88 88 static inline void __lse_atomic_and(int i, atomic_t *v) 89 89 { 90 - asm volatile( 91 - __LSE_PREAMBLE 92 - " mvn %w[i], %w[i]\n" 93 - " stclr %w[i], %[v]" 94 - : [i] "+&r" (i), [v] "+Q" (v->counter) 95 - : "r" (v)); 90 + return __lse_atomic_andnot(~i, v); 96 91 } 97 92 98 93 #define ATOMIC_FETCH_OP_AND(name, mb, cl...) \ 99 94 static inline int __lse_atomic_fetch_and##name(int i, atomic_t *v) \ 100 95 { \ 101 - asm volatile( \ 102 - __LSE_PREAMBLE \ 103 - " mvn %w[i], %w[i]\n" \ 104 - " ldclr" #mb " %w[i], %w[i], %[v]" \ 105 - : [i] "+&r" (i), [v] "+Q" (v->counter) \ 106 - : "r" (v) \ 107 - : cl); \ 108 - \ 109 - return i; \ 96 + return __lse_atomic_fetch_andnot##name(~i, v); \ 110 97 } 111 98 112 99 ATOMIC_FETCH_OP_AND(_relaxed, ) ··· 111 108 112 109 #undef ATOMIC_FETCH_OP_AND 113 110 114 - static inline void __lse_atomic_sub(int i, atomic_t *v) 115 - { 116 - asm volatile( 117 - __LSE_PREAMBLE 118 - " neg %w[i], %w[i]\n" 119 - " stadd %w[i], %[v]" 120 - : [i] "+&r" (i), [v] "+Q" (v->counter) 121 - : "r" (v)); 122 - } 123 - 124 - #define ATOMIC_OP_SUB_RETURN(name, mb, cl...) \ 125 - static inline int __lse_atomic_sub_return##name(int i, atomic_t *v) \ 126 - { \ 127 - u32 tmp; \ 128 - \ 129 - asm volatile( \ 130 - __LSE_PREAMBLE \ 131 - " neg %w[i], %w[i]\n" \ 132 - " ldadd" #mb " %w[i], %w[tmp], %[v]\n" \ 133 - " add %w[i], %w[i], %w[tmp]" \ 134 - : [i] "+&r" (i), [v] "+Q" (v->counter), [tmp] "=&r" (tmp) \ 135 - : "r" (v) \ 136 - : cl); \ 137 - \ 138 - return i; \ 139 - } 140 - 141 - ATOMIC_OP_SUB_RETURN(_relaxed, ) 142 - ATOMIC_OP_SUB_RETURN(_acquire, a, "memory") 143 - ATOMIC_OP_SUB_RETURN(_release, l, "memory") 144 - ATOMIC_OP_SUB_RETURN( , al, "memory") 145 - 146 - #undef ATOMIC_OP_SUB_RETURN 147 - 148 - #define ATOMIC_FETCH_OP_SUB(name, mb, cl...) \ 149 - static inline int __lse_atomic_fetch_sub##name(int i, atomic_t *v) \ 150 - { \ 151 - asm volatile( \ 152 - __LSE_PREAMBLE \ 153 - " neg %w[i], %w[i]\n" \ 154 - " ldadd" #mb " %w[i], %w[i], %[v]" \ 155 - : [i] "+&r" (i), [v] "+Q" (v->counter) \ 156 - : "r" (v) \ 157 - : cl); \ 158 - \ 159 - return i; \ 160 - } 161 - 162 - ATOMIC_FETCH_OP_SUB(_relaxed, ) 163 - ATOMIC_FETCH_OP_SUB(_acquire, a, "memory") 164 - ATOMIC_FETCH_OP_SUB(_release, l, "memory") 165 - ATOMIC_FETCH_OP_SUB( , al, "memory") 166 - 167 - #undef ATOMIC_FETCH_OP_SUB 168 - 169 111 #define ATOMIC64_OP(op, asm_op) \ 170 112 static inline void __lse_atomic64_##op(s64 i, atomic64_t *v) \ 171 113 { \ 172 114 asm volatile( \ 173 115 __LSE_PREAMBLE \ 174 - " " #asm_op " %[i], %[v]\n" \ 175 - : [i] "+r" (i), [v] "+Q" (v->counter) \ 176 - : "r" (v)); \ 116 + " " #asm_op " %[i], %[v]\n" \ 117 + : [v] "+Q" (v->counter) \ 118 + : [i] "r" (i)); \ 177 119 } 178 120 179 121 ATOMIC64_OP(andnot, stclr) ··· 126 178 ATOMIC64_OP(xor, steor) 127 179 ATOMIC64_OP(add, stadd) 128 180 181 + static inline void __lse_atomic64_sub(s64 i, atomic64_t *v) 182 + { 183 + __lse_atomic64_add(-i, v); 184 + } 185 + 129 186 #undef ATOMIC64_OP 130 187 131 188 #define ATOMIC64_FETCH_OP(name, mb, op, asm_op, cl...) \ 132 189 static inline long __lse_atomic64_fetch_##op##name(s64 i, atomic64_t *v)\ 133 190 { \ 191 + s64 old; \ 192 + \ 134 193 asm volatile( \ 135 194 __LSE_PREAMBLE \ 136 - " " #asm_op #mb " %[i], %[i], %[v]" \ 137 - : [i] "+r" (i), [v] "+Q" (v->counter) \ 138 - : "r" (v) \ 195 + " " #asm_op #mb " %[i], %[old], %[v]" \ 196 + : [v] "+Q" (v->counter), \ 197 + [old] "=r" (old) \ 198 + : [i] "r" (i) \ 139 199 : cl); \ 140 200 \ 141 - return i; \ 201 + return old; \ 142 202 } 143 203 144 204 #define ATOMIC64_FETCH_OPS(op, asm_op) \ ··· 163 207 #undef ATOMIC64_FETCH_OP 164 208 #undef ATOMIC64_FETCH_OPS 165 209 166 - #define ATOMIC64_OP_ADD_RETURN(name, mb, cl...) \ 167 - static inline long __lse_atomic64_add_return##name(s64 i, atomic64_t *v)\ 210 + #define ATOMIC64_FETCH_OP_SUB(name) \ 211 + static inline long __lse_atomic64_fetch_sub##name(s64 i, atomic64_t *v) \ 168 212 { \ 169 - unsigned long tmp; \ 170 - \ 171 - asm volatile( \ 172 - __LSE_PREAMBLE \ 173 - " ldadd" #mb " %[i], %x[tmp], %[v]\n" \ 174 - " add %[i], %[i], %x[tmp]" \ 175 - : [i] "+r" (i), [v] "+Q" (v->counter), [tmp] "=&r" (tmp) \ 176 - : "r" (v) \ 177 - : cl); \ 178 - \ 179 - return i; \ 213 + return __lse_atomic64_fetch_add##name(-i, v); \ 180 214 } 181 215 182 - ATOMIC64_OP_ADD_RETURN(_relaxed, ) 183 - ATOMIC64_OP_ADD_RETURN(_acquire, a, "memory") 184 - ATOMIC64_OP_ADD_RETURN(_release, l, "memory") 185 - ATOMIC64_OP_ADD_RETURN( , al, "memory") 216 + ATOMIC64_FETCH_OP_SUB(_relaxed) 217 + ATOMIC64_FETCH_OP_SUB(_acquire) 218 + ATOMIC64_FETCH_OP_SUB(_release) 219 + ATOMIC64_FETCH_OP_SUB( ) 186 220 187 - #undef ATOMIC64_OP_ADD_RETURN 221 + #undef ATOMIC64_FETCH_OP_SUB 222 + 223 + #define ATOMIC64_OP_ADD_SUB_RETURN(name) \ 224 + static inline long __lse_atomic64_add_return##name(s64 i, atomic64_t *v)\ 225 + { \ 226 + return __lse_atomic64_fetch_add##name(i, v) + i; \ 227 + } \ 228 + \ 229 + static inline long __lse_atomic64_sub_return##name(s64 i, atomic64_t *v)\ 230 + { \ 231 + return __lse_atomic64_fetch_sub##name(i, v) - i; \ 232 + } 233 + 234 + ATOMIC64_OP_ADD_SUB_RETURN(_relaxed) 235 + ATOMIC64_OP_ADD_SUB_RETURN(_acquire) 236 + ATOMIC64_OP_ADD_SUB_RETURN(_release) 237 + ATOMIC64_OP_ADD_SUB_RETURN( ) 238 + 239 + #undef ATOMIC64_OP_ADD_SUB_RETURN 188 240 189 241 static inline void __lse_atomic64_and(s64 i, atomic64_t *v) 190 242 { 191 - asm volatile( 192 - __LSE_PREAMBLE 193 - " mvn %[i], %[i]\n" 194 - " stclr %[i], %[v]" 195 - : [i] "+&r" (i), [v] "+Q" (v->counter) 196 - : "r" (v)); 243 + return __lse_atomic64_andnot(~i, v); 197 244 } 198 245 199 246 #define ATOMIC64_FETCH_OP_AND(name, mb, cl...) \ 200 247 static inline long __lse_atomic64_fetch_and##name(s64 i, atomic64_t *v) \ 201 248 { \ 202 - asm volatile( \ 203 - __LSE_PREAMBLE \ 204 - " mvn %[i], %[i]\n" \ 205 - " ldclr" #mb " %[i], %[i], %[v]" \ 206 - : [i] "+&r" (i), [v] "+Q" (v->counter) \ 207 - : "r" (v) \ 208 - : cl); \ 209 - \ 210 - return i; \ 249 + return __lse_atomic64_fetch_andnot##name(~i, v); \ 211 250 } 212 251 213 252 ATOMIC64_FETCH_OP_AND(_relaxed, ) ··· 211 260 ATOMIC64_FETCH_OP_AND( , al, "memory") 212 261 213 262 #undef ATOMIC64_FETCH_OP_AND 214 - 215 - static inline void __lse_atomic64_sub(s64 i, atomic64_t *v) 216 - { 217 - asm volatile( 218 - __LSE_PREAMBLE 219 - " neg %[i], %[i]\n" 220 - " stadd %[i], %[v]" 221 - : [i] "+&r" (i), [v] "+Q" (v->counter) 222 - : "r" (v)); 223 - } 224 - 225 - #define ATOMIC64_OP_SUB_RETURN(name, mb, cl...) \ 226 - static inline long __lse_atomic64_sub_return##name(s64 i, atomic64_t *v) \ 227 - { \ 228 - unsigned long tmp; \ 229 - \ 230 - asm volatile( \ 231 - __LSE_PREAMBLE \ 232 - " neg %[i], %[i]\n" \ 233 - " ldadd" #mb " %[i], %x[tmp], %[v]\n" \ 234 - " add %[i], %[i], %x[tmp]" \ 235 - : [i] "+&r" (i), [v] "+Q" (v->counter), [tmp] "=&r" (tmp) \ 236 - : "r" (v) \ 237 - : cl); \ 238 - \ 239 - return i; \ 240 - } 241 - 242 - ATOMIC64_OP_SUB_RETURN(_relaxed, ) 243 - ATOMIC64_OP_SUB_RETURN(_acquire, a, "memory") 244 - ATOMIC64_OP_SUB_RETURN(_release, l, "memory") 245 - ATOMIC64_OP_SUB_RETURN( , al, "memory") 246 - 247 - #undef ATOMIC64_OP_SUB_RETURN 248 - 249 - #define ATOMIC64_FETCH_OP_SUB(name, mb, cl...) \ 250 - static inline long __lse_atomic64_fetch_sub##name(s64 i, atomic64_t *v) \ 251 - { \ 252 - asm volatile( \ 253 - __LSE_PREAMBLE \ 254 - " neg %[i], %[i]\n" \ 255 - " ldadd" #mb " %[i], %[i], %[v]" \ 256 - : [i] "+&r" (i), [v] "+Q" (v->counter) \ 257 - : "r" (v) \ 258 - : cl); \ 259 - \ 260 - return i; \ 261 - } 262 - 263 - ATOMIC64_FETCH_OP_SUB(_relaxed, ) 264 - ATOMIC64_FETCH_OP_SUB(_acquire, a, "memory") 265 - ATOMIC64_FETCH_OP_SUB(_release, l, "memory") 266 - ATOMIC64_FETCH_OP_SUB( , al, "memory") 267 - 268 - #undef ATOMIC64_FETCH_OP_SUB 269 263 270 264 static inline s64 __lse_atomic64_dec_if_positive(atomic64_t *v) 271 265 {
+9
arch/arm64/include/asm/barrier.h
··· 26 26 #define __tsb_csync() asm volatile("hint #18" : : : "memory") 27 27 #define csdb() asm volatile("hint #20" : : : "memory") 28 28 29 + /* 30 + * Data Gathering Hint: 31 + * This instruction prevents merging memory accesses with Normal-NC or 32 + * Device-GRE attributes before the hint instruction with any memory accesses 33 + * appearing after the hint instruction. 34 + */ 35 + #define dgh() asm volatile("hint #6" : : : "memory") 36 + 29 37 #ifdef CONFIG_ARM64_PSEUDO_NMI 30 38 #define pmr_sync() \ 31 39 do { \ ··· 54 46 #define dma_rmb() dmb(oshld) 55 47 #define dma_wmb() dmb(oshst) 56 48 49 + #define io_stop_wc() dgh() 57 50 58 51 #define tsb_csync() \ 59 52 do { \
+1
arch/arm64/include/asm/cpu.h
··· 51 51 u64 reg_id_aa64dfr1; 52 52 u64 reg_id_aa64isar0; 53 53 u64 reg_id_aa64isar1; 54 + u64 reg_id_aa64isar2; 54 55 u64 reg_id_aa64mmfr0; 55 56 u64 reg_id_aa64mmfr1; 56 57 u64 reg_id_aa64mmfr2;
+3 -3
arch/arm64/include/asm/fpsimd.h
··· 51 51 extern void fpsimd_flush_task_state(struct task_struct *target); 52 52 extern void fpsimd_save_and_flush_cpu_state(void); 53 53 54 - /* Maximum VL that SVE VL-agnostic software can transparently support */ 55 - #define SVE_VL_ARCH_MAX 0x100 54 + /* Maximum VL that SVE/SME VL-agnostic software can transparently support */ 55 + #define VL_ARCH_MAX 0x100 56 56 57 57 /* Offset of FFR in the SVE register dump */ 58 58 static inline size_t sve_ffr_offset(int vl) ··· 122 122 extern void sve_sync_to_fpsimd(struct task_struct *task); 123 123 extern void sve_sync_from_fpsimd_zeropad(struct task_struct *task); 124 124 125 - extern int sve_set_vector_length(struct task_struct *task, 125 + extern int vec_set_vector_length(struct task_struct *task, enum vec_type type, 126 126 unsigned long vl, unsigned long flags); 127 127 128 128 extern int sve_set_current_vl(unsigned long arg);
+2
arch/arm64/include/asm/hwcap.h
··· 106 106 #define KERNEL_HWCAP_BTI __khwcap2_feature(BTI) 107 107 #define KERNEL_HWCAP_MTE __khwcap2_feature(MTE) 108 108 #define KERNEL_HWCAP_ECV __khwcap2_feature(ECV) 109 + #define KERNEL_HWCAP_AFP __khwcap2_feature(AFP) 110 + #define KERNEL_HWCAP_RPRES __khwcap2_feature(RPRES) 109 111 110 112 /* 111 113 * This yields a mask that user programs can use to figure out what
+15 -20
arch/arm64/include/asm/linkage.h
··· 1 1 #ifndef __ASM_LINKAGE_H 2 2 #define __ASM_LINKAGE_H 3 3 4 + #ifdef __ASSEMBLY__ 5 + #include <asm/assembler.h> 6 + #endif 7 + 4 8 #define __ALIGN .align 2 5 9 #define __ALIGN_STR ".align 2" 6 10 7 - #if defined(CONFIG_ARM64_BTI_KERNEL) && defined(__aarch64__) 8 - 9 11 /* 10 - * Since current versions of gas reject the BTI instruction unless we 11 - * set the architecture version to v8.5 we use the hint instruction 12 - * instead. 13 - */ 14 - #define BTI_C hint 34 ; 15 - 16 - /* 17 - * When using in-kernel BTI we need to ensure that PCS-conformant assembly 18 - * functions have suitable annotations. Override SYM_FUNC_START to insert 19 - * a BTI landing pad at the start of everything. 12 + * When using in-kernel BTI we need to ensure that PCS-conformant 13 + * assembly functions have suitable annotations. Override 14 + * SYM_FUNC_START to insert a BTI landing pad at the start of 15 + * everything, the override is done unconditionally so we're more 16 + * likely to notice any drift from the overridden definitions. 20 17 */ 21 18 #define SYM_FUNC_START(name) \ 22 19 SYM_START(name, SYM_L_GLOBAL, SYM_A_ALIGN) \ 23 - BTI_C 20 + bti c ; 24 21 25 22 #define SYM_FUNC_START_NOALIGN(name) \ 26 23 SYM_START(name, SYM_L_GLOBAL, SYM_A_NONE) \ 27 - BTI_C 24 + bti c ; 28 25 29 26 #define SYM_FUNC_START_LOCAL(name) \ 30 27 SYM_START(name, SYM_L_LOCAL, SYM_A_ALIGN) \ 31 - BTI_C 28 + bti c ; 32 29 33 30 #define SYM_FUNC_START_LOCAL_NOALIGN(name) \ 34 31 SYM_START(name, SYM_L_LOCAL, SYM_A_NONE) \ 35 - BTI_C 32 + bti c ; 36 33 37 34 #define SYM_FUNC_START_WEAK(name) \ 38 35 SYM_START(name, SYM_L_WEAK, SYM_A_ALIGN) \ 39 - BTI_C 36 + bti c ; 40 37 41 38 #define SYM_FUNC_START_WEAK_NOALIGN(name) \ 42 39 SYM_START(name, SYM_L_WEAK, SYM_A_NONE) \ 43 - BTI_C 44 - 45 - #endif 40 + bti c ; 46 41 47 42 /* 48 43 * Annotate a function as position independent, i.e., safe to be called before
+5 -3
arch/arm64/include/asm/mte-kasan.h
··· 84 84 static inline void mte_set_mem_tag_range(void *addr, size_t size, u8 tag, 85 85 bool init) 86 86 { 87 - u64 curr, mask, dczid_bs, end1, end2, end3; 87 + u64 curr, mask, dczid, dczid_bs, dczid_dzp, end1, end2, end3; 88 88 89 89 /* Read DC G(Z)VA block size from the system register. */ 90 - dczid_bs = 4ul << (read_cpuid(DCZID_EL0) & 0xf); 90 + dczid = read_cpuid(DCZID_EL0); 91 + dczid_bs = 4ul << (dczid & 0xf); 92 + dczid_dzp = (dczid >> 4) & 1; 91 93 92 94 curr = (u64)__tag_set(addr, tag); 93 95 mask = dczid_bs - 1; ··· 108 106 */ 109 107 #define SET_MEMTAG_RANGE(stg_post, dc_gva) \ 110 108 do { \ 111 - if (size >= 2 * dczid_bs) { \ 109 + if (!dczid_dzp && size >= 2 * dczid_bs) {\ 112 110 do { \ 113 111 curr = stg_post(curr); \ 114 112 } while (curr < end1); \
+4 -6
arch/arm64/include/asm/stacktrace.h
··· 47 47 * @prev_type: The type of stack this frame record was on, or a synthetic 48 48 * value of STACK_TYPE_UNKNOWN. This is used to detect a 49 49 * transition from one stack to another. 50 + * 51 + * @kr_cur: When KRETPROBES is selected, holds the kretprobe instance 52 + * associated with the most recently encountered replacement lr 53 + * value. 50 54 */ 51 55 struct stackframe { 52 56 unsigned long fp; ··· 63 59 #endif 64 60 }; 65 61 66 - extern int unwind_frame(struct task_struct *tsk, struct stackframe *frame); 67 - extern void walk_stackframe(struct task_struct *tsk, struct stackframe *frame, 68 - bool (*fn)(void *, unsigned long), void *data); 69 62 extern void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk, 70 63 const char *loglvl); 71 64 ··· 146 145 147 146 return false; 148 147 } 149 - 150 - void start_backtrace(struct stackframe *frame, unsigned long fp, 151 - unsigned long pc); 152 148 153 149 #endif /* __ASM_STACKTRACE_H */
+16
arch/arm64/include/asm/sysreg.h
··· 182 182 183 183 #define SYS_ID_AA64ISAR0_EL1 sys_reg(3, 0, 0, 6, 0) 184 184 #define SYS_ID_AA64ISAR1_EL1 sys_reg(3, 0, 0, 6, 1) 185 + #define SYS_ID_AA64ISAR2_EL1 sys_reg(3, 0, 0, 6, 2) 185 186 186 187 #define SYS_ID_AA64MMFR0_EL1 sys_reg(3, 0, 0, 7, 0) 187 188 #define SYS_ID_AA64MMFR1_EL1 sys_reg(3, 0, 0, 7, 1) ··· 772 771 #define ID_AA64ISAR1_GPI_NI 0x0 773 772 #define ID_AA64ISAR1_GPI_IMP_DEF 0x1 774 773 774 + /* id_aa64isar2 */ 775 + #define ID_AA64ISAR2_RPRES_SHIFT 4 776 + #define ID_AA64ISAR2_WFXT_SHIFT 0 777 + 778 + #define ID_AA64ISAR2_RPRES_8BIT 0x0 779 + #define ID_AA64ISAR2_RPRES_12BIT 0x1 780 + /* 781 + * Value 0x1 has been removed from the architecture, and is 782 + * reserved, but has not yet been removed from the ARM ARM 783 + * as of ARM DDI 0487G.b. 784 + */ 785 + #define ID_AA64ISAR2_WFXT_NI 0x0 786 + #define ID_AA64ISAR2_WFXT_SUPPORTED 0x2 787 + 775 788 /* id_aa64pfr0 */ 776 789 #define ID_AA64PFR0_CSV3_SHIFT 60 777 790 #define ID_AA64PFR0_CSV2_SHIFT 56 ··· 904 889 #endif 905 890 906 891 /* id_aa64mmfr1 */ 892 + #define ID_AA64MMFR1_AFP_SHIFT 44 907 893 #define ID_AA64MMFR1_ETS_SHIFT 36 908 894 #define ID_AA64MMFR1_TWED_SHIFT 32 909 895 #define ID_AA64MMFR1_XNX_SHIFT 28
+2
arch/arm64/include/uapi/asm/hwcap.h
··· 76 76 #define HWCAP2_BTI (1 << 17) 77 77 #define HWCAP2_MTE (1 << 18) 78 78 #define HWCAP2_ECV (1 << 19) 79 + #define HWCAP2_AFP (1 << 20) 80 + #define HWCAP2_RPRES (1 << 21) 79 81 80 82 #endif /* _UAPI__ASM_HWCAP_H */
+14 -21
arch/arm64/kernel/acpi.c
··· 22 22 #include <linux/irq_work.h> 23 23 #include <linux/memblock.h> 24 24 #include <linux/of_fdt.h> 25 + #include <linux/libfdt.h> 25 26 #include <linux/smp.h> 26 27 #include <linux/serial_core.h> 27 28 #include <linux/pgtable.h> ··· 63 62 } 64 63 early_param("acpi", parse_acpi); 65 64 66 - static int __init dt_scan_depth1_nodes(unsigned long node, 67 - const char *uname, int depth, 68 - void *data) 65 + static bool __init dt_is_stub(void) 69 66 { 70 - /* 71 - * Ignore anything not directly under the root node; we'll 72 - * catch its parent instead. 73 - */ 74 - if (depth != 1) 75 - return 0; 67 + int node; 76 68 77 - if (strcmp(uname, "chosen") == 0) 78 - return 0; 69 + fdt_for_each_subnode(node, initial_boot_params, 0) { 70 + const char *name = fdt_get_name(initial_boot_params, node, NULL); 71 + if (strcmp(name, "chosen") == 0) 72 + continue; 73 + if (strcmp(name, "hypervisor") == 0 && 74 + of_flat_dt_is_compatible(node, "xen,xen")) 75 + continue; 79 76 80 - if (strcmp(uname, "hypervisor") == 0 && 81 - of_flat_dt_is_compatible(node, "xen,xen")) 82 - return 0; 77 + return false; 78 + } 83 79 84 - /* 85 - * This node at depth 1 is neither a chosen node nor a xen node, 86 - * which we do not expect. 87 - */ 88 - return 1; 80 + return true; 89 81 } 90 82 91 83 /* ··· 199 205 * and ACPI has not been [force] enabled (acpi=on|force) 200 206 */ 201 207 if (param_acpi_off || 202 - (!param_acpi_on && !param_acpi_force && 203 - of_scan_flat_dt(dt_scan_depth1_nodes, NULL))) 208 + (!param_acpi_on && !param_acpi_force && !dt_is_stub())) 204 209 goto done; 205 210 206 211 /*
+13
arch/arm64/kernel/cpufeature.c
··· 225 225 ARM64_FTR_END, 226 226 }; 227 227 228 + static const struct arm64_ftr_bits ftr_id_aa64isar2[] = { 229 + ARM64_FTR_BITS(FTR_VISIBLE, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_RPRES_SHIFT, 4, 0), 230 + ARM64_FTR_END, 231 + }; 232 + 228 233 static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = { 229 234 ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_CSV3_SHIFT, 4, 0), 230 235 ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_CSV2_SHIFT, 4, 0), ··· 330 325 }; 331 326 332 327 static const struct arm64_ftr_bits ftr_id_aa64mmfr1[] = { 328 + ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_AFP_SHIFT, 4, 0), 333 329 ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_ETS_SHIFT, 4, 0), 334 330 ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_TWED_SHIFT, 4, 0), 335 331 ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_XNX_SHIFT, 4, 0), ··· 643 637 ARM64_FTR_REG(SYS_ID_AA64ISAR0_EL1, ftr_id_aa64isar0), 644 638 ARM64_FTR_REG_OVERRIDE(SYS_ID_AA64ISAR1_EL1, ftr_id_aa64isar1, 645 639 &id_aa64isar1_override), 640 + ARM64_FTR_REG(SYS_ID_AA64ISAR2_EL1, ftr_id_aa64isar2), 646 641 647 642 /* Op1 = 0, CRn = 0, CRm = 7 */ 648 643 ARM64_FTR_REG(SYS_ID_AA64MMFR0_EL1, ftr_id_aa64mmfr0), ··· 940 933 init_cpu_ftr_reg(SYS_ID_AA64DFR1_EL1, info->reg_id_aa64dfr1); 941 934 init_cpu_ftr_reg(SYS_ID_AA64ISAR0_EL1, info->reg_id_aa64isar0); 942 935 init_cpu_ftr_reg(SYS_ID_AA64ISAR1_EL1, info->reg_id_aa64isar1); 936 + init_cpu_ftr_reg(SYS_ID_AA64ISAR2_EL1, info->reg_id_aa64isar2); 943 937 init_cpu_ftr_reg(SYS_ID_AA64MMFR0_EL1, info->reg_id_aa64mmfr0); 944 938 init_cpu_ftr_reg(SYS_ID_AA64MMFR1_EL1, info->reg_id_aa64mmfr1); 945 939 init_cpu_ftr_reg(SYS_ID_AA64MMFR2_EL1, info->reg_id_aa64mmfr2); ··· 1159 1151 info->reg_id_aa64isar0, boot->reg_id_aa64isar0); 1160 1152 taint |= check_update_ftr_reg(SYS_ID_AA64ISAR1_EL1, cpu, 1161 1153 info->reg_id_aa64isar1, boot->reg_id_aa64isar1); 1154 + taint |= check_update_ftr_reg(SYS_ID_AA64ISAR2_EL1, cpu, 1155 + info->reg_id_aa64isar2, boot->reg_id_aa64isar2); 1162 1156 1163 1157 /* 1164 1158 * Differing PARange support is fine as long as all peripherals and ··· 1282 1272 read_sysreg_case(SYS_ID_AA64MMFR2_EL1); 1283 1273 read_sysreg_case(SYS_ID_AA64ISAR0_EL1); 1284 1274 read_sysreg_case(SYS_ID_AA64ISAR1_EL1); 1275 + read_sysreg_case(SYS_ID_AA64ISAR2_EL1); 1285 1276 1286 1277 read_sysreg_case(SYS_CNTFRQ_EL0); 1287 1278 read_sysreg_case(SYS_CTR_EL0); ··· 2487 2476 HWCAP_CAP(SYS_ID_AA64PFR1_EL1, ID_AA64PFR1_MTE_SHIFT, FTR_UNSIGNED, ID_AA64PFR1_MTE, CAP_HWCAP, KERNEL_HWCAP_MTE), 2488 2477 #endif /* CONFIG_ARM64_MTE */ 2489 2478 HWCAP_CAP(SYS_ID_AA64MMFR0_EL1, ID_AA64MMFR0_ECV_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_ECV), 2479 + HWCAP_CAP(SYS_ID_AA64MMFR1_EL1, ID_AA64MMFR1_AFP_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_AFP), 2480 + HWCAP_CAP(SYS_ID_AA64ISAR2_EL1, ID_AA64ISAR2_RPRES_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_RPRES), 2490 2481 {}, 2491 2482 }; 2492 2483
+3
arch/arm64/kernel/cpuinfo.c
··· 95 95 [KERNEL_HWCAP_BTI] = "bti", 96 96 [KERNEL_HWCAP_MTE] = "mte", 97 97 [KERNEL_HWCAP_ECV] = "ecv", 98 + [KERNEL_HWCAP_AFP] = "afp", 99 + [KERNEL_HWCAP_RPRES] = "rpres", 98 100 }; 99 101 100 102 #ifdef CONFIG_COMPAT ··· 393 391 info->reg_id_aa64dfr1 = read_cpuid(ID_AA64DFR1_EL1); 394 392 info->reg_id_aa64isar0 = read_cpuid(ID_AA64ISAR0_EL1); 395 393 info->reg_id_aa64isar1 = read_cpuid(ID_AA64ISAR1_EL1); 394 + info->reg_id_aa64isar2 = read_cpuid(ID_AA64ISAR2_EL1); 396 395 info->reg_id_aa64mmfr0 = read_cpuid(ID_AA64MMFR0_EL1); 397 396 info->reg_id_aa64mmfr1 = read_cpuid(ID_AA64MMFR1_EL1); 398 397 info->reg_id_aa64mmfr2 = read_cpuid(ID_AA64MMFR2_EL1);
+2
arch/arm64/kernel/entry-ftrace.S
··· 77 77 .endm 78 78 79 79 SYM_CODE_START(ftrace_regs_caller) 80 + bti c 80 81 ftrace_regs_entry 1 81 82 b ftrace_common 82 83 SYM_CODE_END(ftrace_regs_caller) 83 84 84 85 SYM_CODE_START(ftrace_caller) 86 + bti c 85 87 ftrace_regs_entry 0 86 88 b ftrace_common 87 89 SYM_CODE_END(ftrace_caller)
+4 -2
arch/arm64/kernel/entry.S
··· 966 966 mov sp, x1 967 967 968 968 mov x1, x0 // address to complete_and_resume 969 - /* x0 = (x0 <= 1) ? EVENT_COMPLETE:EVENT_COMPLETE_AND_RESUME */ 970 - cmp x0, #1 969 + /* x0 = (x0 <= SDEI_EV_FAILED) ? 970 + * EVENT_COMPLETE:EVENT_COMPLETE_AND_RESUME 971 + */ 972 + cmp x0, #SDEI_EV_FAILED 971 973 mov_q x2, SDEI_1_0_FN_SDEI_EVENT_COMPLETE 972 974 mov_q x3, SDEI_1_0_FN_SDEI_EVENT_COMPLETE_AND_RESUME 973 975 csel x0, x2, x3, ls
+39 -30
arch/arm64/kernel/fpsimd.c
··· 15 15 #include <linux/compiler.h> 16 16 #include <linux/cpu.h> 17 17 #include <linux/cpu_pm.h> 18 + #include <linux/ctype.h> 18 19 #include <linux/kernel.h> 19 20 #include <linux/linkage.h> 20 21 #include <linux/irqflags.h> ··· 407 406 408 407 #if defined(CONFIG_ARM64_SVE) && defined(CONFIG_SYSCTL) 409 408 410 - static int sve_proc_do_default_vl(struct ctl_table *table, int write, 409 + static int vec_proc_do_default_vl(struct ctl_table *table, int write, 411 410 void *buffer, size_t *lenp, loff_t *ppos) 412 411 { 413 - struct vl_info *info = &vl_info[ARM64_VEC_SVE]; 412 + struct vl_info *info = table->extra1; 413 + enum vec_type type = info->type; 414 414 int ret; 415 - int vl = get_sve_default_vl(); 415 + int vl = get_default_vl(type); 416 416 struct ctl_table tmp_table = { 417 417 .data = &vl, 418 418 .maxlen = sizeof(vl), ··· 430 428 if (!sve_vl_valid(vl)) 431 429 return -EINVAL; 432 430 433 - set_sve_default_vl(find_supported_vector_length(ARM64_VEC_SVE, vl)); 431 + set_default_vl(type, find_supported_vector_length(type, vl)); 434 432 return 0; 435 433 } 436 434 ··· 438 436 { 439 437 .procname = "sve_default_vector_length", 440 438 .mode = 0644, 441 - .proc_handler = sve_proc_do_default_vl, 439 + .proc_handler = vec_proc_do_default_vl, 440 + .extra1 = &vl_info[ARM64_VEC_SVE], 442 441 }, 443 442 { } 444 443 }; ··· 632 629 __fpsimd_to_sve(sst, fst, vq); 633 630 } 634 631 635 - int sve_set_vector_length(struct task_struct *task, 632 + int vec_set_vector_length(struct task_struct *task, enum vec_type type, 636 633 unsigned long vl, unsigned long flags) 637 634 { 638 635 if (flags & ~(unsigned long)(PR_SVE_VL_INHERIT | ··· 643 640 return -EINVAL; 644 641 645 642 /* 646 - * Clamp to the maximum vector length that VL-agnostic SVE code can 647 - * work with. A flag may be assigned in the future to allow setting 648 - * of larger vector lengths without confusing older software. 643 + * Clamp to the maximum vector length that VL-agnostic code 644 + * can work with. A flag may be assigned in the future to 645 + * allow setting of larger vector lengths without confusing 646 + * older software. 649 647 */ 650 - if (vl > SVE_VL_ARCH_MAX) 651 - vl = SVE_VL_ARCH_MAX; 648 + if (vl > VL_ARCH_MAX) 649 + vl = VL_ARCH_MAX; 652 650 653 - vl = find_supported_vector_length(ARM64_VEC_SVE, vl); 651 + vl = find_supported_vector_length(type, vl); 654 652 655 653 if (flags & (PR_SVE_VL_INHERIT | 656 654 PR_SVE_SET_VL_ONEXEC)) 657 - task_set_sve_vl_onexec(task, vl); 655 + task_set_vl_onexec(task, type, vl); 658 656 else 659 657 /* Reset VL to system default on next exec: */ 660 - task_set_sve_vl_onexec(task, 0); 658 + task_set_vl_onexec(task, type, 0); 661 659 662 660 /* Only actually set the VL if not deferred: */ 663 661 if (flags & PR_SVE_SET_VL_ONEXEC) 664 662 goto out; 665 663 666 - if (vl == task_get_sve_vl(task)) 664 + if (vl == task_get_vl(task, type)) 667 665 goto out; 668 666 669 667 /* 670 668 * To ensure the FPSIMD bits of the SVE vector registers are preserved, 671 669 * write any live register state back to task_struct, and convert to a 672 - * non-SVE thread. 670 + * regular FPSIMD thread. Since the vector length can only be changed 671 + * with a syscall we can't be in streaming mode while reconfiguring. 673 672 */ 674 673 if (task == current) { 675 674 get_cpu_fpsimd_context(); ··· 692 687 */ 693 688 sve_free(task); 694 689 695 - task_set_sve_vl(task, vl); 690 + task_set_vl(task, type, vl); 696 691 697 692 out: 698 - update_tsk_thread_flag(task, TIF_SVE_VL_INHERIT, 693 + update_tsk_thread_flag(task, vec_vl_inherit_flag(type), 699 694 flags & PR_SVE_VL_INHERIT); 700 695 701 696 return 0; ··· 703 698 704 699 /* 705 700 * Encode the current vector length and flags for return. 706 - * This is only required for prctl(): ptrace has separate fields 701 + * This is only required for prctl(): ptrace has separate fields. 702 + * SVE and SME use the same bits for _ONEXEC and _INHERIT. 707 703 * 708 - * flags are as for sve_set_vector_length(). 704 + * flags are as for vec_set_vector_length(). 709 705 */ 710 - static int sve_prctl_status(unsigned long flags) 706 + static int vec_prctl_status(enum vec_type type, unsigned long flags) 711 707 { 712 708 int ret; 713 709 714 710 if (flags & PR_SVE_SET_VL_ONEXEC) 715 - ret = task_get_sve_vl_onexec(current); 711 + ret = task_get_vl_onexec(current, type); 716 712 else 717 - ret = task_get_sve_vl(current); 713 + ret = task_get_vl(current, type); 718 714 719 - if (test_thread_flag(TIF_SVE_VL_INHERIT)) 715 + if (test_thread_flag(vec_vl_inherit_flag(type))) 720 716 ret |= PR_SVE_VL_INHERIT; 721 717 722 718 return ret; ··· 735 729 if (!system_supports_sve() || is_compat_task()) 736 730 return -EINVAL; 737 731 738 - ret = sve_set_vector_length(current, vl, flags); 732 + ret = vec_set_vector_length(current, ARM64_VEC_SVE, vl, flags); 739 733 if (ret) 740 734 return ret; 741 735 742 - return sve_prctl_status(flags); 736 + return vec_prctl_status(ARM64_VEC_SVE, flags); 743 737 } 744 738 745 739 /* PR_SVE_GET_VL */ ··· 748 742 if (!system_supports_sve() || is_compat_task()) 749 743 return -EINVAL; 750 744 751 - return sve_prctl_status(0); 745 + return vec_prctl_status(ARM64_VEC_SVE, 0); 752 746 } 753 747 754 748 static void vec_probe_vqs(struct vl_info *info, ··· 1113 1107 vl = get_default_vl(type); 1114 1108 1115 1109 if (WARN_ON(!sve_vl_valid(vl))) 1116 - vl = SVE_VL_MIN; 1110 + vl = vl_info[type].min_vl; 1117 1111 1118 1112 supported_vl = find_supported_vector_length(type, vl); 1119 1113 if (WARN_ON(supported_vl != vl)) ··· 1219 1213 /* 1220 1214 * Load the userland FPSIMD state of 'current' from memory, but only if the 1221 1215 * FPSIMD state already held in the registers is /not/ the most recent FPSIMD 1222 - * state of 'current' 1216 + * state of 'current'. This is called when we are preparing to return to 1217 + * userspace to ensure that userspace sees a good register state. 1223 1218 */ 1224 1219 void fpsimd_restore_current_state(void) 1225 1220 { ··· 1251 1244 /* 1252 1245 * Load an updated userland FPSIMD state for 'current' from memory and set the 1253 1246 * flag that indicates that the FPSIMD register contents are the most recent 1254 - * FPSIMD state of 'current' 1247 + * FPSIMD state of 'current'. This is used by the signal code to restore the 1248 + * register state when returning from a signal handler in FPSIMD only cases, 1249 + * any SVE context will be discarded. 1255 1250 */ 1256 1251 void fpsimd_update_current_state(struct user_fpsimd_state const *state) 1257 1252 {
-4
arch/arm64/kernel/hibernate.c
··· 7 7 * Ubuntu project, hibernation support for mach-dove 8 8 * Copyright (C) 2010 Nokia Corporation (Hiroshi Doyu) 9 9 * Copyright (C) 2010 Texas Instruments, Inc. (Teerth Reddy et al.) 10 - * https://lkml.org/lkml/2010/6/18/4 11 - * https://lists.linux-foundation.org/pipermail/linux-pm/2010-June/027422.html 12 - * https://patchwork.kernel.org/patch/96442/ 13 - * 14 10 * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl> 15 11 */ 16 12 #define pr_fmt(x) "hibernate: " x
+5 -3
arch/arm64/kernel/machine_kexec.c
··· 104 104 { 105 105 struct kimage *kimage = (struct kimage *)arg; 106 106 struct page *page = kimage_alloc_control_pages(kimage, 0); 107 + void *vaddr = NULL; 107 108 108 109 if (!page) 109 110 return NULL; 110 111 111 - memset(page_address(page), 0, PAGE_SIZE); 112 + vaddr = page_address(page); 113 + memset(vaddr, 0, PAGE_SIZE); 112 114 113 - return page_address(page); 115 + return vaddr; 114 116 } 115 117 116 118 int machine_kexec_post_load(struct kimage *kimage) ··· 149 147 if (rc) 150 148 return rc; 151 149 kimage->arch.ttbr1 = __pa(trans_pgd); 152 - kimage->arch.zero_page = __pa(empty_zero_page); 150 + kimage->arch.zero_page = __pa_symbol(empty_zero_page); 153 151 154 152 reloc_size = __relocate_new_kernel_end - __relocate_new_kernel_start; 155 153 memcpy(reloc_code, __relocate_new_kernel_start, reloc_size);
+3 -12
arch/arm64/kernel/perf_callchain.c
··· 5 5 * Copyright (C) 2015 ARM Limited 6 6 */ 7 7 #include <linux/perf_event.h> 8 + #include <linux/stacktrace.h> 8 9 #include <linux/uaccess.h> 9 10 10 11 #include <asm/pointer_auth.h> 11 - #include <asm/stacktrace.h> 12 12 13 13 struct frame_tail { 14 14 struct frame_tail __user *fp; ··· 132 132 } 133 133 } 134 134 135 - /* 136 - * Gets called by walk_stackframe() for every stackframe. This will be called 137 - * whist unwinding the stackframe and is like a subroutine return so we use 138 - * the PC. 139 - */ 140 135 static bool callchain_trace(void *data, unsigned long pc) 141 136 { 142 137 struct perf_callchain_entry_ctx *entry = data; 143 - perf_callchain_store(entry, pc); 144 - return true; 138 + return perf_callchain_store(entry, pc) == 0; 145 139 } 146 140 147 141 void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, 148 142 struct pt_regs *regs) 149 143 { 150 - struct stackframe frame; 151 - 152 144 if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { 153 145 /* We don't support guest os callchain now */ 154 146 return; 155 147 } 156 148 157 - start_backtrace(&frame, regs->regs[29], regs->pc); 158 - walk_stackframe(current, &frame, callchain_trace, entry); 149 + arch_stack_walk(callchain_trace, entry, current, regs); 159 150 } 160 151 161 152 unsigned long perf_instruction_pointer(struct pt_regs *regs)
+43 -41
arch/arm64/kernel/process.c
··· 40 40 #include <linux/percpu.h> 41 41 #include <linux/thread_info.h> 42 42 #include <linux/prctl.h> 43 + #include <linux/stacktrace.h> 43 44 44 45 #include <asm/alternative.h> 45 46 #include <asm/compat.h> ··· 440 439 441 440 /* 442 441 * ARM erratum 1418040 handling, affecting the 32bit view of CNTVCT. 443 - * Assuming the virtual counter is enabled at the beginning of times: 444 - * 445 - * - disable access when switching from a 64bit task to a 32bit task 446 - * - enable access when switching from a 32bit task to a 64bit task 442 + * Ensure access is disabled when switching to a 32bit task, ensure 443 + * access is enabled when switching to a 64bit task. 447 444 */ 448 - static void erratum_1418040_thread_switch(struct task_struct *prev, 449 - struct task_struct *next) 445 + static void erratum_1418040_thread_switch(struct task_struct *next) 450 446 { 451 - bool prev32, next32; 452 - u64 val; 453 - 454 - if (!IS_ENABLED(CONFIG_ARM64_ERRATUM_1418040)) 447 + if (!IS_ENABLED(CONFIG_ARM64_ERRATUM_1418040) || 448 + !this_cpu_has_cap(ARM64_WORKAROUND_1418040)) 455 449 return; 456 450 457 - prev32 = is_compat_thread(task_thread_info(prev)); 458 - next32 = is_compat_thread(task_thread_info(next)); 459 - 460 - if (prev32 == next32 || !this_cpu_has_cap(ARM64_WORKAROUND_1418040)) 461 - return; 462 - 463 - val = read_sysreg(cntkctl_el1); 464 - 465 - if (!next32) 466 - val |= ARCH_TIMER_USR_VCT_ACCESS_EN; 451 + if (is_compat_thread(task_thread_info(next))) 452 + sysreg_clear_set(cntkctl_el1, ARCH_TIMER_USR_VCT_ACCESS_EN, 0); 467 453 else 468 - val &= ~ARCH_TIMER_USR_VCT_ACCESS_EN; 454 + sysreg_clear_set(cntkctl_el1, 0, ARCH_TIMER_USR_VCT_ACCESS_EN); 455 + } 469 456 470 - write_sysreg(val, cntkctl_el1); 457 + static void erratum_1418040_new_exec(void) 458 + { 459 + preempt_disable(); 460 + erratum_1418040_thread_switch(current); 461 + preempt_enable(); 471 462 } 472 463 473 464 /* ··· 483 490 /* 484 491 * Thread switching. 485 492 */ 486 - __notrace_funcgraph struct task_struct *__switch_to(struct task_struct *prev, 493 + __notrace_funcgraph __sched 494 + struct task_struct *__switch_to(struct task_struct *prev, 487 495 struct task_struct *next) 488 496 { 489 497 struct task_struct *last; ··· 495 501 contextidr_thread_switch(next); 496 502 entry_task_switch(next); 497 503 ssbs_thread_switch(next); 498 - erratum_1418040_thread_switch(prev, next); 504 + erratum_1418040_thread_switch(next); 499 505 ptrauth_thread_switch_user(next); 500 506 501 507 /* ··· 522 528 return last; 523 529 } 524 530 531 + struct wchan_info { 532 + unsigned long pc; 533 + int count; 534 + }; 535 + 536 + static bool get_wchan_cb(void *arg, unsigned long pc) 537 + { 538 + struct wchan_info *wchan_info = arg; 539 + 540 + if (!in_sched_functions(pc)) { 541 + wchan_info->pc = pc; 542 + return false; 543 + } 544 + return wchan_info->count++ < 16; 545 + } 546 + 525 547 unsigned long __get_wchan(struct task_struct *p) 526 548 { 527 - struct stackframe frame; 528 - unsigned long stack_page, ret = 0; 529 - int count = 0; 549 + struct wchan_info wchan_info = { 550 + .pc = 0, 551 + .count = 0, 552 + }; 530 553 531 - stack_page = (unsigned long)try_get_task_stack(p); 532 - if (!stack_page) 554 + if (!try_get_task_stack(p)) 533 555 return 0; 534 556 535 - start_backtrace(&frame, thread_saved_fp(p), thread_saved_pc(p)); 557 + arch_stack_walk(get_wchan_cb, &wchan_info, p, NULL); 536 558 537 - do { 538 - if (unwind_frame(p, &frame)) 539 - goto out; 540 - if (!in_sched_functions(frame.pc)) { 541 - ret = frame.pc; 542 - goto out; 543 - } 544 - } while (count++ < 16); 545 - 546 - out: 547 559 put_task_stack(p); 548 - return ret; 560 + 561 + return wchan_info.pc; 549 562 } 550 563 551 564 unsigned long arch_align_stack(unsigned long sp) ··· 612 611 current->mm->context.flags = mmflags; 613 612 ptrauth_thread_init_user(); 614 613 mte_thread_init_user(); 614 + erratum_1418040_new_exec(); 615 615 616 616 if (task_spec_ssb_noexec(current)) { 617 617 arch_prctl_spec_ctrl_set(current, PR_SPEC_STORE_BYPASS,
+2 -2
arch/arm64/kernel/ptrace.c
··· 812 812 813 813 /* 814 814 * Apart from SVE_PT_REGS_MASK, all SVE_PT_* flags are consumed by 815 - * sve_set_vector_length(), which will also validate them for us: 815 + * vec_set_vector_length(), which will also validate them for us: 816 816 */ 817 - ret = sve_set_vector_length(target, header.vl, 817 + ret = vec_set_vector_length(target, ARM64_VEC_SVE, header.vl, 818 818 ((unsigned long)header.flags & ~SVE_PT_REGS_MASK) << 16); 819 819 if (ret) 820 820 goto out;
+2 -6
arch/arm64/kernel/return_address.c
··· 9 9 #include <linux/export.h> 10 10 #include <linux/ftrace.h> 11 11 #include <linux/kprobes.h> 12 + #include <linux/stacktrace.h> 12 13 13 14 #include <asm/stack_pointer.h> 14 - #include <asm/stacktrace.h> 15 15 16 16 struct return_address_data { 17 17 unsigned int level; ··· 35 35 void *return_address(unsigned int level) 36 36 { 37 37 struct return_address_data data; 38 - struct stackframe frame; 39 38 40 39 data.level = level + 2; 41 40 data.addr = NULL; 42 41 43 - start_backtrace(&frame, 44 - (unsigned long)__builtin_frame_address(0), 45 - (unsigned long)return_address); 46 - walk_stackframe(current, &frame, save_return_addr, &data); 42 + arch_stack_walk(save_return_addr, &data, current, NULL); 47 43 48 44 if (!data.level) 49 45 return data.addr;
+10 -3
arch/arm64/kernel/setup.c
··· 189 189 190 190 if (!dt_virt || !early_init_dt_scan(dt_virt)) { 191 191 pr_crit("\n" 192 - "Error: invalid device tree blob at physical address %pa (virtual address 0x%p)\n" 192 + "Error: invalid device tree blob at physical address %pa (virtual address 0x%px)\n" 193 193 "The dtb must be 8-byte aligned and must not exceed 2 MB in size\n" 194 194 "\nPlease check your bootloader.", 195 195 &dt_phys, dt_virt); 196 196 197 + /* 198 + * Note that in this _really_ early stage we cannot even BUG() 199 + * or oops, so the least terrible thing to do is cpu_relax(), 200 + * or else we could end-up printing non-initialized data, etc. 201 + */ 197 202 while (true) 198 203 cpu_relax(); 199 204 } ··· 237 232 if (memblock_is_nomap(region)) { 238 233 res->name = "reserved"; 239 234 res->flags = IORESOURCE_MEM; 235 + res->start = __pfn_to_phys(memblock_region_reserved_base_pfn(region)); 236 + res->end = __pfn_to_phys(memblock_region_reserved_end_pfn(region)) - 1; 240 237 } else { 241 238 res->name = "System RAM"; 242 239 res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; 240 + res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region)); 241 + res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1; 243 242 } 244 - res->start = __pfn_to_phys(memblock_region_memory_base_pfn(region)); 245 - res->end = __pfn_to_phys(memblock_region_memory_end_pfn(region)) - 1; 246 243 247 244 request_resource(&iomem_resource, res); 248 245
+13 -47
arch/arm64/kernel/stacktrace.c
··· 33 33 */ 34 34 35 35 36 - void start_backtrace(struct stackframe *frame, unsigned long fp, 37 - unsigned long pc) 36 + static void start_backtrace(struct stackframe *frame, unsigned long fp, 37 + unsigned long pc) 38 38 { 39 39 frame->fp = fp; 40 40 frame->pc = pc; ··· 63 63 * records (e.g. a cycle), determined based on the location and fp value of A 64 64 * and the location (but not the fp value) of B. 65 65 */ 66 - int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame) 66 + static int notrace unwind_frame(struct task_struct *tsk, 67 + struct stackframe *frame) 67 68 { 68 69 unsigned long fp = frame->fp; 69 70 struct stack_info info; ··· 142 141 } 143 142 NOKPROBE_SYMBOL(unwind_frame); 144 143 145 - void notrace walk_stackframe(struct task_struct *tsk, struct stackframe *frame, 146 - bool (*fn)(void *, unsigned long), void *data) 144 + static void notrace walk_stackframe(struct task_struct *tsk, 145 + struct stackframe *frame, 146 + bool (*fn)(void *, unsigned long), void *data) 147 147 { 148 148 while (1) { 149 149 int ret; ··· 158 156 } 159 157 NOKPROBE_SYMBOL(walk_stackframe); 160 158 161 - static void dump_backtrace_entry(unsigned long where, const char *loglvl) 159 + static bool dump_backtrace_entry(void *arg, unsigned long where) 162 160 { 161 + char *loglvl = arg; 163 162 printk("%s %pSb\n", loglvl, (void *)where); 163 + return true; 164 164 } 165 165 166 166 void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk, 167 167 const char *loglvl) 168 168 { 169 - struct stackframe frame; 170 - int skip = 0; 171 - 172 169 pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk); 173 170 174 - if (regs) { 175 - if (user_mode(regs)) 176 - return; 177 - skip = 1; 178 - } 171 + if (regs && user_mode(regs)) 172 + return; 179 173 180 174 if (!tsk) 181 175 tsk = current; ··· 179 181 if (!try_get_task_stack(tsk)) 180 182 return; 181 183 182 - if (tsk == current) { 183 - start_backtrace(&frame, 184 - (unsigned long)__builtin_frame_address(0), 185 - (unsigned long)dump_backtrace); 186 - } else { 187 - /* 188 - * task blocked in __switch_to 189 - */ 190 - start_backtrace(&frame, 191 - thread_saved_fp(tsk), 192 - thread_saved_pc(tsk)); 193 - } 194 - 195 184 printk("%sCall trace:\n", loglvl); 196 - do { 197 - /* skip until specified stack frame */ 198 - if (!skip) { 199 - dump_backtrace_entry(frame.pc, loglvl); 200 - } else if (frame.fp == regs->regs[29]) { 201 - skip = 0; 202 - /* 203 - * Mostly, this is the case where this function is 204 - * called in panic/abort. As exception handler's 205 - * stack frame does not contain the corresponding pc 206 - * at which an exception has taken place, use regs->pc 207 - * instead. 208 - */ 209 - dump_backtrace_entry(regs->pc, loglvl); 210 - } 211 - } while (!unwind_frame(tsk, &frame)); 185 + arch_stack_walk(dump_backtrace_entry, (void *)loglvl, tsk, regs); 212 186 213 187 put_task_stack(tsk); 214 188 } ··· 190 220 dump_backtrace(NULL, tsk, loglvl); 191 221 barrier(); 192 222 } 193 - 194 - #ifdef CONFIG_STACKTRACE 195 223 196 224 noinline notrace void arch_stack_walk(stack_trace_consume_fn consume_entry, 197 225 void *cookie, struct task_struct *task, ··· 209 241 210 242 walk_stackframe(task, &frame, consume_entry, cookie); 211 243 } 212 - 213 - #endif
+14 -13
arch/arm64/kernel/time.c
··· 18 18 #include <linux/timex.h> 19 19 #include <linux/errno.h> 20 20 #include <linux/profile.h> 21 + #include <linux/stacktrace.h> 21 22 #include <linux/syscore_ops.h> 22 23 #include <linux/timer.h> 23 24 #include <linux/irq.h> ··· 30 29 #include <clocksource/arm_arch_timer.h> 31 30 32 31 #include <asm/thread_info.h> 33 - #include <asm/stacktrace.h> 34 32 #include <asm/paravirt.h> 33 + 34 + static bool profile_pc_cb(void *arg, unsigned long pc) 35 + { 36 + unsigned long *prof_pc = arg; 37 + 38 + if (in_lock_functions(pc)) 39 + return true; 40 + *prof_pc = pc; 41 + return false; 42 + } 35 43 36 44 unsigned long profile_pc(struct pt_regs *regs) 37 45 { 38 - struct stackframe frame; 46 + unsigned long prof_pc = 0; 39 47 40 - if (!in_lock_functions(regs->pc)) 41 - return regs->pc; 48 + arch_stack_walk(profile_pc_cb, &prof_pc, current, regs); 42 49 43 - start_backtrace(&frame, regs->regs[29], regs->pc); 44 - 45 - do { 46 - int ret = unwind_frame(NULL, &frame); 47 - if (ret < 0) 48 - return 0; 49 - } while (in_lock_functions(frame.pc)); 50 - 51 - return frame.pc; 50 + return prof_pc; 52 51 } 53 52 EXPORT_SYMBOL(profile_pc); 54 53
+1
arch/arm64/kernel/vdso/Makefile
··· 32 32 CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_FTRACE) -Os $(CC_FLAGS_SCS) $(GCC_PLUGINS_CFLAGS) \ 33 33 $(CC_FLAGS_LTO) 34 34 KASAN_SANITIZE := n 35 + KCSAN_SANITIZE := n 35 36 UBSAN_SANITIZE := n 36 37 OBJECT_FILES_NON_STANDARD := y 37 38 KCOV_INSTRUMENT := n
+4 -1
arch/arm64/kvm/handle_exit.c
··· 140 140 return 1; 141 141 } 142 142 143 + /* 144 + * Guest access to SVE registers should be routed to this handler only 145 + * when the system doesn't support SVE. 146 + */ 143 147 static int handle_sve(struct kvm_vcpu *vcpu) 144 148 { 145 - /* Until SVE is supported for guests: */ 146 149 kvm_inject_undefined(vcpu); 147 150 return 1; 148 151 }
+1
arch/arm64/kvm/hyp/nvhe/Makefile
··· 89 89 # cause crashes. Just disable it. 90 90 GCOV_PROFILE := n 91 91 KASAN_SANITIZE := n 92 + KCSAN_SANITIZE := n 92 93 UBSAN_SANITIZE := n 93 94 KCOV_INSTRUMENT := n 94 95
+4 -4
arch/arm64/kvm/reset.c
··· 52 52 * The get_sve_reg()/set_sve_reg() ioctl interface will need 53 53 * to be extended with multiple register slice support in 54 54 * order to support vector lengths greater than 55 - * SVE_VL_ARCH_MAX: 55 + * VL_ARCH_MAX: 56 56 */ 57 - if (WARN_ON(kvm_sve_max_vl > SVE_VL_ARCH_MAX)) 58 - kvm_sve_max_vl = SVE_VL_ARCH_MAX; 57 + if (WARN_ON(kvm_sve_max_vl > VL_ARCH_MAX)) 58 + kvm_sve_max_vl = VL_ARCH_MAX; 59 59 60 60 /* 61 61 * Don't even try to make use of vector lengths that ··· 103 103 * set_sve_vls(). Double-check here just to be sure: 104 104 */ 105 105 if (WARN_ON(!sve_vl_valid(vl) || vl > sve_max_virtualisable_vl() || 106 - vl > SVE_VL_ARCH_MAX)) 106 + vl > VL_ARCH_MAX)) 107 107 return -EIO; 108 108 109 109 buf = kzalloc(SVE_SIG_REGS_SIZE(sve_vq_from_vl(vl)), GFP_KERNEL_ACCOUNT);
+1 -1
arch/arm64/kvm/sys_regs.c
··· 1525 1525 /* CRm=6 */ 1526 1526 ID_SANITISED(ID_AA64ISAR0_EL1), 1527 1527 ID_SANITISED(ID_AA64ISAR1_EL1), 1528 - ID_UNALLOCATED(6,2), 1528 + ID_SANITISED(ID_AA64ISAR2_EL1), 1529 1529 ID_UNALLOCATED(6,3), 1530 1530 ID_UNALLOCATED(6,4), 1531 1531 ID_UNALLOCATED(6,5),
+10
arch/arm64/lib/clear_page.S
··· 16 16 */ 17 17 SYM_FUNC_START_PI(clear_page) 18 18 mrs x1, dczid_el0 19 + tbnz x1, #4, 2f /* Branch if DC ZVA is prohibited */ 19 20 and w1, w1, #0xf 20 21 mov x2, #4 21 22 lsl x1, x2, x1 ··· 25 24 add x0, x0, x1 26 25 tst x0, #(PAGE_SIZE - 1) 27 26 b.ne 1b 27 + ret 28 + 29 + 2: stnp xzr, xzr, [x0] 30 + stnp xzr, xzr, [x0, #16] 31 + stnp xzr, xzr, [x0, #32] 32 + stnp xzr, xzr, [x0, #48] 33 + add x0, x0, #64 34 + tst x0, #(PAGE_SIZE - 1) 35 + b.ne 2b 28 36 ret 29 37 SYM_FUNC_END_PI(clear_page) 30 38 EXPORT_SYMBOL(clear_page)
+1 -3
arch/arm64/lib/kasan_sw_tags.S
··· 38 38 * incremented by 256 prior to return). 39 39 */ 40 40 SYM_CODE_START(__hwasan_tag_mismatch) 41 - #ifdef BTI_C 42 - BTI_C 43 - #endif 41 + bti c 44 42 add x29, sp, #232 45 43 stp x2, x3, [sp, #8 * 2] 46 44 stp x4, x5, [sp, #8 * 4]
+7 -1
arch/arm64/lib/mte.S
··· 43 43 * x0 - address to the beginning of the page 44 44 */ 45 45 SYM_FUNC_START(mte_zero_clear_page_tags) 46 + and x0, x0, #(1 << MTE_TAG_SHIFT) - 1 // clear the tag 46 47 mrs x1, dczid_el0 48 + tbnz x1, #4, 2f // Branch if DC GZVA is prohibited 47 49 and w1, w1, #0xf 48 50 mov x2, #4 49 51 lsl x1, x2, x1 50 - and x0, x0, #(1 << MTE_TAG_SHIFT) - 1 // clear the tag 51 52 52 53 1: dc gzva, x0 53 54 add x0, x0, x1 54 55 tst x0, #(PAGE_SIZE - 1) 55 56 b.ne 1b 57 + ret 58 + 59 + 2: stz2g x0, [x0], #(MTE_GRANULE_SIZE * 2) 60 + tst x0, #(PAGE_SIZE - 1) 61 + b.ne 2b 56 62 ret 57 63 SYM_FUNC_END(mte_zero_clear_page_tags) 58 64
+146 -1
arch/arm64/lib/xor-neon.c
··· 167 167 } while (--lines > 0); 168 168 } 169 169 170 - struct xor_block_template const xor_block_inner_neon = { 170 + struct xor_block_template xor_block_inner_neon __ro_after_init = { 171 171 .name = "__inner_neon__", 172 172 .do_2 = xor_arm64_neon_2, 173 173 .do_3 = xor_arm64_neon_3, ··· 175 175 .do_5 = xor_arm64_neon_5, 176 176 }; 177 177 EXPORT_SYMBOL(xor_block_inner_neon); 178 + 179 + static inline uint64x2_t eor3(uint64x2_t p, uint64x2_t q, uint64x2_t r) 180 + { 181 + uint64x2_t res; 182 + 183 + asm(ARM64_ASM_PREAMBLE ".arch_extension sha3\n" 184 + "eor3 %0.16b, %1.16b, %2.16b, %3.16b" 185 + : "=w"(res) : "w"(p), "w"(q), "w"(r)); 186 + return res; 187 + } 188 + 189 + static void xor_arm64_eor3_3(unsigned long bytes, unsigned long *p1, 190 + unsigned long *p2, unsigned long *p3) 191 + { 192 + uint64_t *dp1 = (uint64_t *)p1; 193 + uint64_t *dp2 = (uint64_t *)p2; 194 + uint64_t *dp3 = (uint64_t *)p3; 195 + 196 + register uint64x2_t v0, v1, v2, v3; 197 + long lines = bytes / (sizeof(uint64x2_t) * 4); 198 + 199 + do { 200 + /* p1 ^= p2 ^ p3 */ 201 + v0 = eor3(vld1q_u64(dp1 + 0), vld1q_u64(dp2 + 0), 202 + vld1q_u64(dp3 + 0)); 203 + v1 = eor3(vld1q_u64(dp1 + 2), vld1q_u64(dp2 + 2), 204 + vld1q_u64(dp3 + 2)); 205 + v2 = eor3(vld1q_u64(dp1 + 4), vld1q_u64(dp2 + 4), 206 + vld1q_u64(dp3 + 4)); 207 + v3 = eor3(vld1q_u64(dp1 + 6), vld1q_u64(dp2 + 6), 208 + vld1q_u64(dp3 + 6)); 209 + 210 + /* store */ 211 + vst1q_u64(dp1 + 0, v0); 212 + vst1q_u64(dp1 + 2, v1); 213 + vst1q_u64(dp1 + 4, v2); 214 + vst1q_u64(dp1 + 6, v3); 215 + 216 + dp1 += 8; 217 + dp2 += 8; 218 + dp3 += 8; 219 + } while (--lines > 0); 220 + } 221 + 222 + static void xor_arm64_eor3_4(unsigned long bytes, unsigned long *p1, 223 + unsigned long *p2, unsigned long *p3, 224 + unsigned long *p4) 225 + { 226 + uint64_t *dp1 = (uint64_t *)p1; 227 + uint64_t *dp2 = (uint64_t *)p2; 228 + uint64_t *dp3 = (uint64_t *)p3; 229 + uint64_t *dp4 = (uint64_t *)p4; 230 + 231 + register uint64x2_t v0, v1, v2, v3; 232 + long lines = bytes / (sizeof(uint64x2_t) * 4); 233 + 234 + do { 235 + /* p1 ^= p2 ^ p3 */ 236 + v0 = eor3(vld1q_u64(dp1 + 0), vld1q_u64(dp2 + 0), 237 + vld1q_u64(dp3 + 0)); 238 + v1 = eor3(vld1q_u64(dp1 + 2), vld1q_u64(dp2 + 2), 239 + vld1q_u64(dp3 + 2)); 240 + v2 = eor3(vld1q_u64(dp1 + 4), vld1q_u64(dp2 + 4), 241 + vld1q_u64(dp3 + 4)); 242 + v3 = eor3(vld1q_u64(dp1 + 6), vld1q_u64(dp2 + 6), 243 + vld1q_u64(dp3 + 6)); 244 + 245 + /* p1 ^= p4 */ 246 + v0 = veorq_u64(v0, vld1q_u64(dp4 + 0)); 247 + v1 = veorq_u64(v1, vld1q_u64(dp4 + 2)); 248 + v2 = veorq_u64(v2, vld1q_u64(dp4 + 4)); 249 + v3 = veorq_u64(v3, vld1q_u64(dp4 + 6)); 250 + 251 + /* store */ 252 + vst1q_u64(dp1 + 0, v0); 253 + vst1q_u64(dp1 + 2, v1); 254 + vst1q_u64(dp1 + 4, v2); 255 + vst1q_u64(dp1 + 6, v3); 256 + 257 + dp1 += 8; 258 + dp2 += 8; 259 + dp3 += 8; 260 + dp4 += 8; 261 + } while (--lines > 0); 262 + } 263 + 264 + static void xor_arm64_eor3_5(unsigned long bytes, unsigned long *p1, 265 + unsigned long *p2, unsigned long *p3, 266 + unsigned long *p4, unsigned long *p5) 267 + { 268 + uint64_t *dp1 = (uint64_t *)p1; 269 + uint64_t *dp2 = (uint64_t *)p2; 270 + uint64_t *dp3 = (uint64_t *)p3; 271 + uint64_t *dp4 = (uint64_t *)p4; 272 + uint64_t *dp5 = (uint64_t *)p5; 273 + 274 + register uint64x2_t v0, v1, v2, v3; 275 + long lines = bytes / (sizeof(uint64x2_t) * 4); 276 + 277 + do { 278 + /* p1 ^= p2 ^ p3 */ 279 + v0 = eor3(vld1q_u64(dp1 + 0), vld1q_u64(dp2 + 0), 280 + vld1q_u64(dp3 + 0)); 281 + v1 = eor3(vld1q_u64(dp1 + 2), vld1q_u64(dp2 + 2), 282 + vld1q_u64(dp3 + 2)); 283 + v2 = eor3(vld1q_u64(dp1 + 4), vld1q_u64(dp2 + 4), 284 + vld1q_u64(dp3 + 4)); 285 + v3 = eor3(vld1q_u64(dp1 + 6), vld1q_u64(dp2 + 6), 286 + vld1q_u64(dp3 + 6)); 287 + 288 + /* p1 ^= p4 ^ p5 */ 289 + v0 = eor3(v0, vld1q_u64(dp4 + 0), vld1q_u64(dp5 + 0)); 290 + v1 = eor3(v1, vld1q_u64(dp4 + 2), vld1q_u64(dp5 + 2)); 291 + v2 = eor3(v2, vld1q_u64(dp4 + 4), vld1q_u64(dp5 + 4)); 292 + v3 = eor3(v3, vld1q_u64(dp4 + 6), vld1q_u64(dp5 + 6)); 293 + 294 + /* store */ 295 + vst1q_u64(dp1 + 0, v0); 296 + vst1q_u64(dp1 + 2, v1); 297 + vst1q_u64(dp1 + 4, v2); 298 + vst1q_u64(dp1 + 6, v3); 299 + 300 + dp1 += 8; 301 + dp2 += 8; 302 + dp3 += 8; 303 + dp4 += 8; 304 + dp5 += 8; 305 + } while (--lines > 0); 306 + } 307 + 308 + static int __init xor_neon_init(void) 309 + { 310 + if (IS_ENABLED(CONFIG_AS_HAS_SHA3) && cpu_have_named_feature(SHA3)) { 311 + xor_block_inner_neon.do_3 = xor_arm64_eor3_3; 312 + xor_block_inner_neon.do_4 = xor_arm64_eor3_4; 313 + xor_block_inner_neon.do_5 = xor_arm64_eor3_5; 314 + } 315 + return 0; 316 + } 317 + module_init(xor_neon_init); 318 + 319 + static void __exit xor_neon_exit(void) 320 + { 321 + } 322 + module_exit(xor_neon_exit); 178 323 179 324 MODULE_AUTHOR("Jackie Liu <liuyun01@kylinos.cn>"); 180 325 MODULE_DESCRIPTION("ARMv8 XOR Extensions");
+3 -21
arch/arm64/mm/cache.S
··· 140 140 * - start - kernel start address of region 141 141 * - end - kernel end address of region 142 142 */ 143 - SYM_FUNC_START_LOCAL(__dma_inv_area) 144 143 SYM_FUNC_START_PI(dcache_inval_poc) 145 - /* FALLTHROUGH */ 146 - 147 - /* 148 - * __dma_inv_area(start, end) 149 - * - start - virtual start address of region 150 - * - end - virtual end address of region 151 - */ 152 144 dcache_line_size x2, x3 153 145 sub x3, x2, #1 154 146 tst x1, x3 // end cache line aligned? ··· 159 167 dsb sy 160 168 ret 161 169 SYM_FUNC_END_PI(dcache_inval_poc) 162 - SYM_FUNC_END(__dma_inv_area) 163 170 164 171 /* 165 172 * dcache_clean_poc(start, end) ··· 169 178 * - start - virtual start address of region 170 179 * - end - virtual end address of region 171 180 */ 172 - SYM_FUNC_START_LOCAL(__dma_clean_area) 173 181 SYM_FUNC_START_PI(dcache_clean_poc) 174 - /* FALLTHROUGH */ 175 - 176 - /* 177 - * __dma_clean_area(start, end) 178 - * - start - virtual start address of region 179 - * - end - virtual end address of region 180 - */ 181 182 dcache_by_line_op cvac, sy, x0, x1, x2, x3 182 183 ret 183 184 SYM_FUNC_END_PI(dcache_clean_poc) 184 - SYM_FUNC_END(__dma_clean_area) 185 185 186 186 /* 187 187 * dcache_clean_pop(start, end) ··· 214 232 SYM_FUNC_START_PI(__dma_map_area) 215 233 add x1, x0, x1 216 234 cmp w2, #DMA_FROM_DEVICE 217 - b.eq __dma_inv_area 218 - b __dma_clean_area 235 + b.eq __pi_dcache_inval_poc 236 + b __pi_dcache_clean_poc 219 237 SYM_FUNC_END_PI(__dma_map_area) 220 238 221 239 /* ··· 227 245 SYM_FUNC_START_PI(__dma_unmap_area) 228 246 add x1, x0, x1 229 247 cmp w2, #DMA_TO_DEVICE 230 - b.ne __dma_inv_area 248 + b.ne __pi_dcache_inval_poc 231 249 ret 232 250 SYM_FUNC_END_PI(__dma_unmap_area)
+11 -11
arch/arm64/mm/context.c
··· 35 35 #define ASID_FIRST_VERSION (1UL << asid_bits) 36 36 37 37 #define NUM_USER_ASIDS ASID_FIRST_VERSION 38 - #define asid2idx(asid) ((asid) & ~ASID_MASK) 39 - #define idx2asid(idx) asid2idx(idx) 38 + #define ctxid2asid(asid) ((asid) & ~ASID_MASK) 39 + #define asid2ctxid(asid, genid) ((asid) | (genid)) 40 40 41 41 /* Get the ASIDBits supported by the current CPU */ 42 42 static u32 get_cpu_asid_bits(void) ··· 50 50 pr_warn("CPU%d: Unknown ASID size (%d); assuming 8-bit\n", 51 51 smp_processor_id(), fld); 52 52 fallthrough; 53 - case 0: 53 + case ID_AA64MMFR0_ASID_8: 54 54 asid = 8; 55 55 break; 56 - case 2: 56 + case ID_AA64MMFR0_ASID_16: 57 57 asid = 16; 58 58 } 59 59 ··· 120 120 */ 121 121 if (asid == 0) 122 122 asid = per_cpu(reserved_asids, i); 123 - __set_bit(asid2idx(asid), asid_map); 123 + __set_bit(ctxid2asid(asid), asid_map); 124 124 per_cpu(reserved_asids, i) = asid; 125 125 } 126 126 ··· 162 162 u64 generation = atomic64_read(&asid_generation); 163 163 164 164 if (asid != 0) { 165 - u64 newasid = generation | (asid & ~ASID_MASK); 165 + u64 newasid = asid2ctxid(ctxid2asid(asid), generation); 166 166 167 167 /* 168 168 * If our current ASID was active during a rollover, we ··· 183 183 * We had a valid ASID in a previous life, so try to re-use 184 184 * it if possible. 185 185 */ 186 - if (!__test_and_set_bit(asid2idx(asid), asid_map)) 186 + if (!__test_and_set_bit(ctxid2asid(asid), asid_map)) 187 187 return newasid; 188 188 } 189 189 ··· 209 209 set_asid: 210 210 __set_bit(asid, asid_map); 211 211 cur_idx = asid; 212 - return idx2asid(asid) | generation; 212 + return asid2ctxid(asid, generation); 213 213 } 214 214 215 215 void check_and_switch_context(struct mm_struct *mm) ··· 300 300 } 301 301 302 302 nr_pinned_asids++; 303 - __set_bit(asid2idx(asid), pinned_asid_map); 303 + __set_bit(ctxid2asid(asid), pinned_asid_map); 304 304 refcount_set(&mm->context.pinned, 1); 305 305 306 306 out_unlock: 307 307 raw_spin_unlock_irqrestore(&cpu_asid_lock, flags); 308 308 309 - asid &= ~ASID_MASK; 309 + asid = ctxid2asid(asid); 310 310 311 311 /* Set the equivalent of USER_ASID_BIT */ 312 312 if (asid && arm64_kernel_unmapped_at_el0()) ··· 327 327 raw_spin_lock_irqsave(&cpu_asid_lock, flags); 328 328 329 329 if (refcount_dec_and_test(&mm->context.pinned)) { 330 - __clear_bit(asid2idx(asid), pinned_asid_map); 330 + __clear_bit(ctxid2asid(asid), pinned_asid_map); 331 331 nr_pinned_asids--; 332 332 } 333 333
-3
arch/arm64/mm/extable.c
··· 10 10 #include <asm/asm-extable.h> 11 11 #include <asm/ptrace.h> 12 12 13 - typedef bool (*ex_handler_t)(const struct exception_table_entry *, 14 - struct pt_regs *); 15 - 16 13 static inline unsigned long 17 14 get_ex_fixup(const struct exception_table_entry *ex) 18 15 {
+4 -5
arch/arm64/mm/fault.c
··· 297 297 pr_alert("Unable to handle kernel %s at virtual address %016lx\n", msg, 298 298 addr); 299 299 300 + kasan_non_canonical_hook(addr); 301 + 300 302 mem_abort_decode(esr); 301 303 302 304 show_pte(addr); ··· 815 813 if (!inf->fn(far, esr, regs)) 816 814 return; 817 815 818 - if (!user_mode(regs)) { 819 - pr_alert("Unhandled fault at 0x%016lx\n", addr); 820 - mem_abort_decode(esr); 821 - show_pte(addr); 822 - } 816 + if (!user_mode(regs)) 817 + die_kernel_fault(inf->name, addr, esr, regs); 823 818 824 819 /* 825 820 * At this point we have an unrecognized fault type whose tag bits may
+1 -2
arch/powerpc/kernel/Makefile
··· 47 47 udbg.o misc.o io.o misc_$(BITS).o \ 48 48 of_platform.o prom_parse.o firmware.o \ 49 49 hw_breakpoint_constraints.o interrupt.o \ 50 - kdebugfs.o 50 + kdebugfs.o stacktrace.o 51 51 obj-y += ptrace/ 52 52 obj-$(CONFIG_PPC64) += setup_64.o \ 53 53 paca.o nvram_64.o note.o ··· 116 116 obj-$(CONFIG_KPROBES_ON_FTRACE) += kprobes-ftrace.o 117 117 obj-$(CONFIG_UPROBES) += uprobes.o 118 118 obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o 119 - obj-$(CONFIG_STACKTRACE) += stacktrace.o 120 119 obj-$(CONFIG_SWIOTLB) += dma-swiotlb.o 121 120 obj-$(CONFIG_ARCH_HAS_DMA_SET_MASK) += dma-mask.o 122 121
-4
arch/riscv/kernel/stacktrace.c
··· 139 139 return pc; 140 140 } 141 141 142 - #ifdef CONFIG_STACKTRACE 143 - 144 142 noinline void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie, 145 143 struct task_struct *task, struct pt_regs *regs) 146 144 { 147 145 walk_stackframe(task, regs, consume_entry, cookie); 148 146 } 149 - 150 - #endif /* CONFIG_STACKTRACE */
+1 -2
arch/s390/kernel/Makefile
··· 40 40 obj-y += runtime_instr.o cache.o fpu.o dumpstack.o guarded_storage.o sthyi.o 41 41 obj-y += entry.o reipl.o relocate_kernel.o kdebugfs.o alternative.o 42 42 obj-y += nospec-branch.o ipl_vmparm.o machine_kexec_reloc.o unwind_bc.o 43 - obj-y += smp.o text_amode31.o 43 + obj-y += smp.o text_amode31.o stacktrace.o 44 44 45 45 extra-y += head64.o vmlinux.lds 46 46 ··· 55 55 obj-$(CONFIG_COMPAT) += compat_linux.o compat_signal.o 56 56 obj-$(CONFIG_COMPAT) += $(compat-obj-y) 57 57 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o 58 - obj-$(CONFIG_STACKTRACE) += stacktrace.o 59 58 obj-$(CONFIG_KPROBES) += kprobes.o 60 59 obj-$(CONFIG_KPROBES) += kprobes_insn_page.o 61 60 obj-$(CONFIG_FUNCTION_TRACER) += mcount.o ftrace.o
+1 -1
arch/x86/kernel/Makefile
··· 84 84 obj-y += step.o 85 85 obj-$(CONFIG_INTEL_TXT) += tboot.o 86 86 obj-$(CONFIG_ISA_DMA_API) += i8237.o 87 - obj-$(CONFIG_STACKTRACE) += stacktrace.o 87 + obj-y += stacktrace.o 88 88 obj-y += cpu/ 89 89 obj-y += acpi/ 90 90 obj-y += reboot.o
+11
include/asm-generic/barrier.h
··· 251 251 #define pmem_wmb() wmb() 252 252 #endif 253 253 254 + /* 255 + * ioremap_wc() maps I/O memory as memory with write-combining attributes. For 256 + * this kind of memory accesses, the CPU may wait for prior accesses to be 257 + * merged with subsequent ones. In some situation, such wait is bad for the 258 + * performance. io_stop_wc() can be used to prevent the merging of 259 + * write-combining memory accesses before this macro with those after it. 260 + */ 261 + #ifndef io_stop_wc 262 + #define io_stop_wc do { } while (0) 263 + #endif 264 + 254 265 #endif /* !__ASSEMBLY__ */ 255 266 #endif /* __ASM_GENERIC_BARRIER_H */
+18 -17
include/linux/stacktrace.h
··· 8 8 struct task_struct; 9 9 struct pt_regs; 10 10 11 - #ifdef CONFIG_STACKTRACE 12 - void stack_trace_print(const unsigned long *trace, unsigned int nr_entries, 13 - int spaces); 14 - int stack_trace_snprint(char *buf, size_t size, const unsigned long *entries, 15 - unsigned int nr_entries, int spaces); 16 - unsigned int stack_trace_save(unsigned long *store, unsigned int size, 17 - unsigned int skipnr); 18 - unsigned int stack_trace_save_tsk(struct task_struct *task, 19 - unsigned long *store, unsigned int size, 20 - unsigned int skipnr); 21 - unsigned int stack_trace_save_regs(struct pt_regs *regs, unsigned long *store, 22 - unsigned int size, unsigned int skipnr); 23 - unsigned int stack_trace_save_user(unsigned long *store, unsigned int size); 24 - unsigned int filter_irq_stacks(unsigned long *entries, unsigned int nr_entries); 25 - 26 - /* Internal interfaces. Do not use in generic code */ 27 11 #ifdef CONFIG_ARCH_STACKWALK 28 12 29 13 /** ··· 60 76 61 77 void arch_stack_walk_user(stack_trace_consume_fn consume_entry, void *cookie, 62 78 const struct pt_regs *regs); 79 + #endif /* CONFIG_ARCH_STACKWALK */ 63 80 64 - #else /* CONFIG_ARCH_STACKWALK */ 81 + #ifdef CONFIG_STACKTRACE 82 + void stack_trace_print(const unsigned long *trace, unsigned int nr_entries, 83 + int spaces); 84 + int stack_trace_snprint(char *buf, size_t size, const unsigned long *entries, 85 + unsigned int nr_entries, int spaces); 86 + unsigned int stack_trace_save(unsigned long *store, unsigned int size, 87 + unsigned int skipnr); 88 + unsigned int stack_trace_save_tsk(struct task_struct *task, 89 + unsigned long *store, unsigned int size, 90 + unsigned int skipnr); 91 + unsigned int stack_trace_save_regs(struct pt_regs *regs, unsigned long *store, 92 + unsigned int size, unsigned int skipnr); 93 + unsigned int stack_trace_save_user(unsigned long *store, unsigned int size); 94 + unsigned int filter_irq_stacks(unsigned long *entries, unsigned int nr_entries); 95 + 96 + #ifndef CONFIG_ARCH_STACKWALK 97 + /* Internal interfaces. Do not use in generic code */ 65 98 struct stack_trace { 66 99 unsigned int nr_entries, max_entries; 67 100 unsigned long *entries;
+1
kernel/kcsan/Makefile
··· 8 8 CFLAGS_REMOVE_report.o = $(CC_FLAGS_FTRACE) 9 9 10 10 CFLAGS_core.o := $(call cc-option,-fno-conserve-stack) \ 11 + $(call cc-option,-mno-outline-atomics) \ 11 12 -fno-stack-protector -DDISABLE_BRANCH_PROFILING 12 13 13 14 obj-y := core.o debugfs.o report.o
+1 -1
tools/testing/selftests/arm64/Makefile
··· 4 4 ARCH ?= $(shell uname -m 2>/dev/null || echo not) 5 5 6 6 ifneq (,$(filter $(ARCH),aarch64 arm64)) 7 - ARM64_SUBTARGETS ?= tags signal pauth fp mte bti 7 + ARM64_SUBTARGETS ?= tags signal pauth fp mte bti abi 8 8 else 9 9 ARM64_SUBTARGETS := 10 10 endif
+1
tools/testing/selftests/arm64/abi/.gitignore
··· 1 + syscall-abi
+8
tools/testing/selftests/arm64/abi/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # Copyright (C) 2021 ARM Limited 3 + 4 + TEST_GEN_PROGS := syscall-abi 5 + 6 + include ../../lib.mk 7 + 8 + $(OUTPUT)/syscall-abi: syscall-abi.c syscall-abi-asm.S
+240
tools/testing/selftests/arm64/abi/syscall-abi-asm.S
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // Copyright (C) 2021 ARM Limited. 3 + // 4 + // Assembly portion of the syscall ABI test 5 + 6 + // 7 + // Load values from memory into registers, invoke a syscall and save the 8 + // register values back to memory for later checking. The syscall to be 9 + // invoked is configured in x8 of the input GPR data. 10 + // 11 + // x0: SVE VL, 0 for FP only 12 + // 13 + // GPRs: gpr_in, gpr_out 14 + // FPRs: fpr_in, fpr_out 15 + // Zn: z_in, z_out 16 + // Pn: p_in, p_out 17 + // FFR: ffr_in, ffr_out 18 + 19 + .arch_extension sve 20 + 21 + .globl do_syscall 22 + do_syscall: 23 + // Store callee saved registers x19-x29 (80 bytes) plus x0 and x1 24 + stp x29, x30, [sp, #-112]! 25 + mov x29, sp 26 + stp x0, x1, [sp, #16] 27 + stp x19, x20, [sp, #32] 28 + stp x21, x22, [sp, #48] 29 + stp x23, x24, [sp, #64] 30 + stp x25, x26, [sp, #80] 31 + stp x27, x28, [sp, #96] 32 + 33 + // Load GPRs x8-x28, and save our SP/FP for later comparison 34 + ldr x2, =gpr_in 35 + add x2, x2, #64 36 + ldp x8, x9, [x2], #16 37 + ldp x10, x11, [x2], #16 38 + ldp x12, x13, [x2], #16 39 + ldp x14, x15, [x2], #16 40 + ldp x16, x17, [x2], #16 41 + ldp x18, x19, [x2], #16 42 + ldp x20, x21, [x2], #16 43 + ldp x22, x23, [x2], #16 44 + ldp x24, x25, [x2], #16 45 + ldp x26, x27, [x2], #16 46 + ldr x28, [x2], #8 47 + str x29, [x2], #8 // FP 48 + str x30, [x2], #8 // LR 49 + 50 + // Load FPRs if we're not doing SVE 51 + cbnz x0, 1f 52 + ldr x2, =fpr_in 53 + ldp q0, q1, [x2] 54 + ldp q2, q3, [x2, #16 * 2] 55 + ldp q4, q5, [x2, #16 * 4] 56 + ldp q6, q7, [x2, #16 * 6] 57 + ldp q8, q9, [x2, #16 * 8] 58 + ldp q10, q11, [x2, #16 * 10] 59 + ldp q12, q13, [x2, #16 * 12] 60 + ldp q14, q15, [x2, #16 * 14] 61 + ldp q16, q17, [x2, #16 * 16] 62 + ldp q18, q19, [x2, #16 * 18] 63 + ldp q20, q21, [x2, #16 * 20] 64 + ldp q22, q23, [x2, #16 * 22] 65 + ldp q24, q25, [x2, #16 * 24] 66 + ldp q26, q27, [x2, #16 * 26] 67 + ldp q28, q29, [x2, #16 * 28] 68 + ldp q30, q31, [x2, #16 * 30] 69 + 1: 70 + 71 + // Load the SVE registers if we're doing SVE 72 + cbz x0, 1f 73 + 74 + ldr x2, =z_in 75 + ldr z0, [x2, #0, MUL VL] 76 + ldr z1, [x2, #1, MUL VL] 77 + ldr z2, [x2, #2, MUL VL] 78 + ldr z3, [x2, #3, MUL VL] 79 + ldr z4, [x2, #4, MUL VL] 80 + ldr z5, [x2, #5, MUL VL] 81 + ldr z6, [x2, #6, MUL VL] 82 + ldr z7, [x2, #7, MUL VL] 83 + ldr z8, [x2, #8, MUL VL] 84 + ldr z9, [x2, #9, MUL VL] 85 + ldr z10, [x2, #10, MUL VL] 86 + ldr z11, [x2, #11, MUL VL] 87 + ldr z12, [x2, #12, MUL VL] 88 + ldr z13, [x2, #13, MUL VL] 89 + ldr z14, [x2, #14, MUL VL] 90 + ldr z15, [x2, #15, MUL VL] 91 + ldr z16, [x2, #16, MUL VL] 92 + ldr z17, [x2, #17, MUL VL] 93 + ldr z18, [x2, #18, MUL VL] 94 + ldr z19, [x2, #19, MUL VL] 95 + ldr z20, [x2, #20, MUL VL] 96 + ldr z21, [x2, #21, MUL VL] 97 + ldr z22, [x2, #22, MUL VL] 98 + ldr z23, [x2, #23, MUL VL] 99 + ldr z24, [x2, #24, MUL VL] 100 + ldr z25, [x2, #25, MUL VL] 101 + ldr z26, [x2, #26, MUL VL] 102 + ldr z27, [x2, #27, MUL VL] 103 + ldr z28, [x2, #28, MUL VL] 104 + ldr z29, [x2, #29, MUL VL] 105 + ldr z30, [x2, #30, MUL VL] 106 + ldr z31, [x2, #31, MUL VL] 107 + 108 + ldr x2, =ffr_in 109 + ldr p0, [x2, #0] 110 + wrffr p0.b 111 + 112 + ldr x2, =p_in 113 + ldr p0, [x2, #0, MUL VL] 114 + ldr p1, [x2, #1, MUL VL] 115 + ldr p2, [x2, #2, MUL VL] 116 + ldr p3, [x2, #3, MUL VL] 117 + ldr p4, [x2, #4, MUL VL] 118 + ldr p5, [x2, #5, MUL VL] 119 + ldr p6, [x2, #6, MUL VL] 120 + ldr p7, [x2, #7, MUL VL] 121 + ldr p8, [x2, #8, MUL VL] 122 + ldr p9, [x2, #9, MUL VL] 123 + ldr p10, [x2, #10, MUL VL] 124 + ldr p11, [x2, #11, MUL VL] 125 + ldr p12, [x2, #12, MUL VL] 126 + ldr p13, [x2, #13, MUL VL] 127 + ldr p14, [x2, #14, MUL VL] 128 + ldr p15, [x2, #15, MUL VL] 129 + 1: 130 + 131 + // Do the syscall 132 + svc #0 133 + 134 + // Save GPRs x8-x30 135 + ldr x2, =gpr_out 136 + add x2, x2, #64 137 + stp x8, x9, [x2], #16 138 + stp x10, x11, [x2], #16 139 + stp x12, x13, [x2], #16 140 + stp x14, x15, [x2], #16 141 + stp x16, x17, [x2], #16 142 + stp x18, x19, [x2], #16 143 + stp x20, x21, [x2], #16 144 + stp x22, x23, [x2], #16 145 + stp x24, x25, [x2], #16 146 + stp x26, x27, [x2], #16 147 + stp x28, x29, [x2], #16 148 + str x30, [x2] 149 + 150 + // Restore x0 and x1 for feature checks 151 + ldp x0, x1, [sp, #16] 152 + 153 + // Save FPSIMD state 154 + ldr x2, =fpr_out 155 + stp q0, q1, [x2] 156 + stp q2, q3, [x2, #16 * 2] 157 + stp q4, q5, [x2, #16 * 4] 158 + stp q6, q7, [x2, #16 * 6] 159 + stp q8, q9, [x2, #16 * 8] 160 + stp q10, q11, [x2, #16 * 10] 161 + stp q12, q13, [x2, #16 * 12] 162 + stp q14, q15, [x2, #16 * 14] 163 + stp q16, q17, [x2, #16 * 16] 164 + stp q18, q19, [x2, #16 * 18] 165 + stp q20, q21, [x2, #16 * 20] 166 + stp q22, q23, [x2, #16 * 22] 167 + stp q24, q25, [x2, #16 * 24] 168 + stp q26, q27, [x2, #16 * 26] 169 + stp q28, q29, [x2, #16 * 28] 170 + stp q30, q31, [x2, #16 * 30] 171 + 172 + // Save the SVE state if we have some 173 + cbz x0, 1f 174 + 175 + ldr x2, =z_out 176 + str z0, [x2, #0, MUL VL] 177 + str z1, [x2, #1, MUL VL] 178 + str z2, [x2, #2, MUL VL] 179 + str z3, [x2, #3, MUL VL] 180 + str z4, [x2, #4, MUL VL] 181 + str z5, [x2, #5, MUL VL] 182 + str z6, [x2, #6, MUL VL] 183 + str z7, [x2, #7, MUL VL] 184 + str z8, [x2, #8, MUL VL] 185 + str z9, [x2, #9, MUL VL] 186 + str z10, [x2, #10, MUL VL] 187 + str z11, [x2, #11, MUL VL] 188 + str z12, [x2, #12, MUL VL] 189 + str z13, [x2, #13, MUL VL] 190 + str z14, [x2, #14, MUL VL] 191 + str z15, [x2, #15, MUL VL] 192 + str z16, [x2, #16, MUL VL] 193 + str z17, [x2, #17, MUL VL] 194 + str z18, [x2, #18, MUL VL] 195 + str z19, [x2, #19, MUL VL] 196 + str z20, [x2, #20, MUL VL] 197 + str z21, [x2, #21, MUL VL] 198 + str z22, [x2, #22, MUL VL] 199 + str z23, [x2, #23, MUL VL] 200 + str z24, [x2, #24, MUL VL] 201 + str z25, [x2, #25, MUL VL] 202 + str z26, [x2, #26, MUL VL] 203 + str z27, [x2, #27, MUL VL] 204 + str z28, [x2, #28, MUL VL] 205 + str z29, [x2, #29, MUL VL] 206 + str z30, [x2, #30, MUL VL] 207 + str z31, [x2, #31, MUL VL] 208 + 209 + ldr x2, =p_out 210 + str p0, [x2, #0, MUL VL] 211 + str p1, [x2, #1, MUL VL] 212 + str p2, [x2, #2, MUL VL] 213 + str p3, [x2, #3, MUL VL] 214 + str p4, [x2, #4, MUL VL] 215 + str p5, [x2, #5, MUL VL] 216 + str p6, [x2, #6, MUL VL] 217 + str p7, [x2, #7, MUL VL] 218 + str p8, [x2, #8, MUL VL] 219 + str p9, [x2, #9, MUL VL] 220 + str p10, [x2, #10, MUL VL] 221 + str p11, [x2, #11, MUL VL] 222 + str p12, [x2, #12, MUL VL] 223 + str p13, [x2, #13, MUL VL] 224 + str p14, [x2, #14, MUL VL] 225 + str p15, [x2, #15, MUL VL] 226 + 227 + ldr x2, =ffr_out 228 + rdffr p0.b 229 + str p0, [x2, #0] 230 + 1: 231 + 232 + // Restore callee saved registers x19-x30 233 + ldp x19, x20, [sp, #32] 234 + ldp x21, x22, [sp, #48] 235 + ldp x23, x24, [sp, #64] 236 + ldp x25, x26, [sp, #80] 237 + ldp x27, x28, [sp, #96] 238 + ldp x29, x30, [sp], #112 239 + 240 + ret
+318
tools/testing/selftests/arm64/abi/syscall-abi.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (C) 2021 ARM Limited. 4 + */ 5 + 6 + #include <errno.h> 7 + #include <stdbool.h> 8 + #include <stddef.h> 9 + #include <stdio.h> 10 + #include <stdlib.h> 11 + #include <string.h> 12 + #include <unistd.h> 13 + #include <sys/auxv.h> 14 + #include <sys/prctl.h> 15 + #include <asm/hwcap.h> 16 + #include <asm/sigcontext.h> 17 + #include <asm/unistd.h> 18 + 19 + #include "../../kselftest.h" 20 + 21 + #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 22 + #define NUM_VL ((SVE_VQ_MAX - SVE_VQ_MIN) + 1) 23 + 24 + extern void do_syscall(int sve_vl); 25 + 26 + static void fill_random(void *buf, size_t size) 27 + { 28 + int i; 29 + uint32_t *lbuf = buf; 30 + 31 + /* random() returns a 32 bit number regardless of the size of long */ 32 + for (i = 0; i < size / sizeof(uint32_t); i++) 33 + lbuf[i] = random(); 34 + } 35 + 36 + /* 37 + * We also repeat the test for several syscalls to try to expose different 38 + * behaviour. 39 + */ 40 + static struct syscall_cfg { 41 + int syscall_nr; 42 + const char *name; 43 + } syscalls[] = { 44 + { __NR_getpid, "getpid()" }, 45 + { __NR_sched_yield, "sched_yield()" }, 46 + }; 47 + 48 + #define NUM_GPR 31 49 + uint64_t gpr_in[NUM_GPR]; 50 + uint64_t gpr_out[NUM_GPR]; 51 + 52 + static void setup_gpr(struct syscall_cfg *cfg, int sve_vl) 53 + { 54 + fill_random(gpr_in, sizeof(gpr_in)); 55 + gpr_in[8] = cfg->syscall_nr; 56 + memset(gpr_out, 0, sizeof(gpr_out)); 57 + } 58 + 59 + static int check_gpr(struct syscall_cfg *cfg, int sve_vl) 60 + { 61 + int errors = 0; 62 + int i; 63 + 64 + /* 65 + * GPR x0-x7 may be clobbered, and all others should be preserved. 66 + */ 67 + for (i = 9; i < ARRAY_SIZE(gpr_in); i++) { 68 + if (gpr_in[i] != gpr_out[i]) { 69 + ksft_print_msg("%s SVE VL %d mismatch in GPR %d: %llx != %llx\n", 70 + cfg->name, sve_vl, i, 71 + gpr_in[i], gpr_out[i]); 72 + errors++; 73 + } 74 + } 75 + 76 + return errors; 77 + } 78 + 79 + #define NUM_FPR 32 80 + uint64_t fpr_in[NUM_FPR * 2]; 81 + uint64_t fpr_out[NUM_FPR * 2]; 82 + 83 + static void setup_fpr(struct syscall_cfg *cfg, int sve_vl) 84 + { 85 + fill_random(fpr_in, sizeof(fpr_in)); 86 + memset(fpr_out, 0, sizeof(fpr_out)); 87 + } 88 + 89 + static int check_fpr(struct syscall_cfg *cfg, int sve_vl) 90 + { 91 + int errors = 0; 92 + int i; 93 + 94 + if (!sve_vl) { 95 + for (i = 0; i < ARRAY_SIZE(fpr_in); i++) { 96 + if (fpr_in[i] != fpr_out[i]) { 97 + ksft_print_msg("%s Q%d/%d mismatch %llx != %llx\n", 98 + cfg->name, 99 + i / 2, i % 2, 100 + fpr_in[i], fpr_out[i]); 101 + errors++; 102 + } 103 + } 104 + } 105 + 106 + return errors; 107 + } 108 + 109 + static uint8_t z_zero[__SVE_ZREG_SIZE(SVE_VQ_MAX)]; 110 + uint8_t z_in[SVE_NUM_PREGS * __SVE_ZREG_SIZE(SVE_VQ_MAX)]; 111 + uint8_t z_out[SVE_NUM_PREGS * __SVE_ZREG_SIZE(SVE_VQ_MAX)]; 112 + 113 + static void setup_z(struct syscall_cfg *cfg, int sve_vl) 114 + { 115 + fill_random(z_in, sizeof(z_in)); 116 + fill_random(z_out, sizeof(z_out)); 117 + } 118 + 119 + static int check_z(struct syscall_cfg *cfg, int sve_vl) 120 + { 121 + size_t reg_size = sve_vl; 122 + int errors = 0; 123 + int i; 124 + 125 + if (!sve_vl) 126 + return 0; 127 + 128 + /* 129 + * After a syscall the low 128 bits of the Z registers should 130 + * be preserved and the rest be zeroed or preserved. 131 + */ 132 + for (i = 0; i < SVE_NUM_ZREGS; i++) { 133 + void *in = &z_in[reg_size * i]; 134 + void *out = &z_out[reg_size * i]; 135 + 136 + if (memcmp(in, out, SVE_VQ_BYTES) != 0) { 137 + ksft_print_msg("%s SVE VL %d Z%d low 128 bits changed\n", 138 + cfg->name, sve_vl, i); 139 + errors++; 140 + } 141 + } 142 + 143 + return errors; 144 + } 145 + 146 + uint8_t p_in[SVE_NUM_PREGS * __SVE_PREG_SIZE(SVE_VQ_MAX)]; 147 + uint8_t p_out[SVE_NUM_PREGS * __SVE_PREG_SIZE(SVE_VQ_MAX)]; 148 + 149 + static void setup_p(struct syscall_cfg *cfg, int sve_vl) 150 + { 151 + fill_random(p_in, sizeof(p_in)); 152 + fill_random(p_out, sizeof(p_out)); 153 + } 154 + 155 + static int check_p(struct syscall_cfg *cfg, int sve_vl) 156 + { 157 + size_t reg_size = sve_vq_from_vl(sve_vl) * 2; /* 1 bit per VL byte */ 158 + 159 + int errors = 0; 160 + int i; 161 + 162 + if (!sve_vl) 163 + return 0; 164 + 165 + /* After a syscall the P registers should be preserved or zeroed */ 166 + for (i = 0; i < SVE_NUM_PREGS * reg_size; i++) 167 + if (p_out[i] && (p_in[i] != p_out[i])) 168 + errors++; 169 + if (errors) 170 + ksft_print_msg("%s SVE VL %d predicate registers non-zero\n", 171 + cfg->name, sve_vl); 172 + 173 + return errors; 174 + } 175 + 176 + uint8_t ffr_in[__SVE_PREG_SIZE(SVE_VQ_MAX)]; 177 + uint8_t ffr_out[__SVE_PREG_SIZE(SVE_VQ_MAX)]; 178 + 179 + static void setup_ffr(struct syscall_cfg *cfg, int sve_vl) 180 + { 181 + /* 182 + * It is only valid to set a contiguous set of bits starting 183 + * at 0. For now since we're expecting this to be cleared by 184 + * a syscall just set all bits. 185 + */ 186 + memset(ffr_in, 0xff, sizeof(ffr_in)); 187 + fill_random(ffr_out, sizeof(ffr_out)); 188 + } 189 + 190 + static int check_ffr(struct syscall_cfg *cfg, int sve_vl) 191 + { 192 + size_t reg_size = sve_vq_from_vl(sve_vl) * 2; /* 1 bit per VL byte */ 193 + int errors = 0; 194 + int i; 195 + 196 + if (!sve_vl) 197 + return 0; 198 + 199 + /* After a syscall the P registers should be preserved or zeroed */ 200 + for (i = 0; i < reg_size; i++) 201 + if (ffr_out[i] && (ffr_in[i] != ffr_out[i])) 202 + errors++; 203 + if (errors) 204 + ksft_print_msg("%s SVE VL %d FFR non-zero\n", 205 + cfg->name, sve_vl); 206 + 207 + return errors; 208 + } 209 + 210 + typedef void (*setup_fn)(struct syscall_cfg *cfg, int sve_vl); 211 + typedef int (*check_fn)(struct syscall_cfg *cfg, int sve_vl); 212 + 213 + /* 214 + * Each set of registers has a setup function which is called before 215 + * the syscall to fill values in a global variable for loading by the 216 + * test code and a check function which validates that the results are 217 + * as expected. Vector lengths are passed everywhere, a vector length 218 + * of 0 should be treated as do not test. 219 + */ 220 + static struct { 221 + setup_fn setup; 222 + check_fn check; 223 + } regset[] = { 224 + { setup_gpr, check_gpr }, 225 + { setup_fpr, check_fpr }, 226 + { setup_z, check_z }, 227 + { setup_p, check_p }, 228 + { setup_ffr, check_ffr }, 229 + }; 230 + 231 + static bool do_test(struct syscall_cfg *cfg, int sve_vl) 232 + { 233 + int errors = 0; 234 + int i; 235 + 236 + for (i = 0; i < ARRAY_SIZE(regset); i++) 237 + regset[i].setup(cfg, sve_vl); 238 + 239 + do_syscall(sve_vl); 240 + 241 + for (i = 0; i < ARRAY_SIZE(regset); i++) 242 + errors += regset[i].check(cfg, sve_vl); 243 + 244 + return errors == 0; 245 + } 246 + 247 + static void test_one_syscall(struct syscall_cfg *cfg) 248 + { 249 + int sve_vq, sve_vl; 250 + 251 + /* FPSIMD only case */ 252 + ksft_test_result(do_test(cfg, 0), 253 + "%s FPSIMD\n", cfg->name); 254 + 255 + if (!(getauxval(AT_HWCAP) & HWCAP_SVE)) 256 + return; 257 + 258 + for (sve_vq = SVE_VQ_MAX; sve_vq > 0; --sve_vq) { 259 + sve_vl = prctl(PR_SVE_SET_VL, sve_vq * 16); 260 + if (sve_vl == -1) 261 + ksft_exit_fail_msg("PR_SVE_SET_VL failed: %s (%d)\n", 262 + strerror(errno), errno); 263 + 264 + sve_vl &= PR_SVE_VL_LEN_MASK; 265 + 266 + if (sve_vq != sve_vq_from_vl(sve_vl)) 267 + sve_vq = sve_vq_from_vl(sve_vl); 268 + 269 + ksft_test_result(do_test(cfg, sve_vl), 270 + "%s SVE VL %d\n", cfg->name, sve_vl); 271 + } 272 + } 273 + 274 + int sve_count_vls(void) 275 + { 276 + unsigned int vq; 277 + int vl_count = 0; 278 + int vl; 279 + 280 + if (!(getauxval(AT_HWCAP) & HWCAP_SVE)) 281 + return 0; 282 + 283 + /* 284 + * Enumerate up to SVE_VQ_MAX vector lengths 285 + */ 286 + for (vq = SVE_VQ_MAX; vq > 0; --vq) { 287 + vl = prctl(PR_SVE_SET_VL, vq * 16); 288 + if (vl == -1) 289 + ksft_exit_fail_msg("PR_SVE_SET_VL failed: %s (%d)\n", 290 + strerror(errno), errno); 291 + 292 + vl &= PR_SVE_VL_LEN_MASK; 293 + 294 + if (vq != sve_vq_from_vl(vl)) 295 + vq = sve_vq_from_vl(vl); 296 + 297 + vl_count++; 298 + } 299 + 300 + return vl_count; 301 + } 302 + 303 + int main(void) 304 + { 305 + int i; 306 + 307 + srandom(getpid()); 308 + 309 + ksft_print_header(); 310 + ksft_set_plan(ARRAY_SIZE(syscalls) * (sve_count_vls() + 1)); 311 + 312 + for (i = 0; i < ARRAY_SIZE(syscalls); i++) 313 + test_one_syscall(&syscalls[i]); 314 + 315 + ksft_print_cnts(); 316 + 317 + return 0; 318 + }
+1
tools/testing/selftests/arm64/fp/.gitignore
··· 1 + fp-pidbench 1 2 fpsimd-test 2 3 rdvl-sve 3 4 sve-probe-vls
+3 -1
tools/testing/selftests/arm64/fp/Makefile
··· 2 2 3 3 CFLAGS += -I../../../../../usr/include/ 4 4 TEST_GEN_PROGS := sve-ptrace sve-probe-vls vec-syscfg 5 - TEST_PROGS_EXTENDED := fpsimd-test fpsimd-stress \ 5 + TEST_PROGS_EXTENDED := fp-pidbench fpsimd-test fpsimd-stress \ 6 6 rdvl-sve \ 7 7 sve-test sve-stress \ 8 8 vlset 9 9 10 10 all: $(TEST_GEN_PROGS) $(TEST_PROGS_EXTENDED) 11 11 12 + fp-pidbench: fp-pidbench.S asm-utils.o 13 + $(CC) -nostdlib $^ -o $@ 12 14 fpsimd-test: fpsimd-test.o asm-utils.o 13 15 $(CC) -nostdlib $^ -o $@ 14 16 rdvl-sve: rdvl-sve.o rdvl.o
+71
tools/testing/selftests/arm64/fp/fp-pidbench.S
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + // Copyright (C) 2021 ARM Limited. 3 + // Original author: Mark Brown <broonie@kernel.org> 4 + // 5 + // Trivial syscall overhead benchmark. 6 + // 7 + // This is implemented in asm to ensure that we don't have any issues with 8 + // system libraries using instructions that disrupt the test. 9 + 10 + #include <asm/unistd.h> 11 + #include "assembler.h" 12 + 13 + .arch_extension sve 14 + 15 + .macro test_loop per_loop 16 + mov x10, x20 17 + mov x8, #__NR_getpid 18 + mrs x11, CNTVCT_EL0 19 + 1: 20 + \per_loop 21 + svc #0 22 + sub x10, x10, #1 23 + cbnz x10, 1b 24 + 25 + mrs x12, CNTVCT_EL0 26 + sub x0, x12, x11 27 + bl putdec 28 + puts "\n" 29 + .endm 30 + 31 + // Main program entry point 32 + .globl _start 33 + function _start 34 + _start: 35 + puts "Iterations per test: " 36 + mov x20, #10000 37 + lsl x20, x20, #8 38 + mov x0, x20 39 + bl putdec 40 + puts "\n" 41 + 42 + // Test having never used SVE 43 + puts "No SVE: " 44 + test_loop 45 + 46 + // Check for SVE support - should use hwcap but that's hard in asm 47 + mrs x0, ID_AA64PFR0_EL1 48 + ubfx x0, x0, #32, #4 49 + cbnz x0, 1f 50 + puts "System does not support SVE\n" 51 + b out 52 + 1: 53 + 54 + // Execute a SVE instruction 55 + puts "SVE VL: " 56 + rdvl x0, #8 57 + bl putdec 58 + puts "\n" 59 + 60 + puts "SVE used once: " 61 + test_loop 62 + 63 + // Use SVE per syscall 64 + puts "SVE used per syscall: " 65 + test_loop "rdvl x0, #8" 66 + 67 + // And we're done 68 + out: 69 + mov x0, #0 70 + mov x8, #__NR_exit 71 + svc #0
+143 -78
tools/testing/selftests/arm64/fp/sve-ptrace.c
··· 21 21 22 22 #include "../../kselftest.h" 23 23 24 - #define VL_TESTS (((SVE_VQ_MAX - SVE_VQ_MIN) + 1) * 3) 25 - #define FPSIMD_TESTS 5 26 - 27 - #define EXPECTED_TESTS (VL_TESTS + FPSIMD_TESTS) 24 + #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 28 25 29 26 /* <linux/elf.h> and <sys/auxv.h> don't like each other, so: */ 30 27 #ifndef NT_ARM_SVE 31 28 #define NT_ARM_SVE 0x405 32 29 #endif 30 + 31 + struct vec_type { 32 + const char *name; 33 + unsigned long hwcap_type; 34 + unsigned long hwcap; 35 + int regset; 36 + int prctl_set; 37 + }; 38 + 39 + static const struct vec_type vec_types[] = { 40 + { 41 + .name = "SVE", 42 + .hwcap_type = AT_HWCAP, 43 + .hwcap = HWCAP_SVE, 44 + .regset = NT_ARM_SVE, 45 + .prctl_set = PR_SVE_SET_VL, 46 + }, 47 + }; 48 + 49 + #define VL_TESTS (((SVE_VQ_MAX - SVE_VQ_MIN) + 1) * 3) 50 + #define FLAG_TESTS 2 51 + #define FPSIMD_TESTS 3 52 + 53 + #define EXPECTED_TESTS ((VL_TESTS + FLAG_TESTS + FPSIMD_TESTS) * ARRAY_SIZE(vec_types)) 33 54 34 55 static void fill_buf(char *buf, size_t size) 35 56 { ··· 80 59 return ptrace(PTRACE_GETREGSET, pid, NT_PRFPREG, &iov); 81 60 } 82 61 83 - static struct user_sve_header *get_sve(pid_t pid, void **buf, size_t *size) 62 + static struct user_sve_header *get_sve(pid_t pid, const struct vec_type *type, 63 + void **buf, size_t *size) 84 64 { 85 65 struct user_sve_header *sve; 86 66 void *p; ··· 102 80 103 81 iov.iov_base = *buf; 104 82 iov.iov_len = sz; 105 - if (ptrace(PTRACE_GETREGSET, pid, NT_ARM_SVE, &iov)) 83 + if (ptrace(PTRACE_GETREGSET, pid, type->regset, &iov)) 106 84 goto error; 107 85 108 86 sve = *buf; ··· 118 96 return NULL; 119 97 } 120 98 121 - static int set_sve(pid_t pid, const struct user_sve_header *sve) 99 + static int set_sve(pid_t pid, const struct vec_type *type, 100 + const struct user_sve_header *sve) 122 101 { 123 102 struct iovec iov; 124 103 125 104 iov.iov_base = (void *)sve; 126 105 iov.iov_len = sve->size; 127 - return ptrace(PTRACE_SETREGSET, pid, NT_ARM_SVE, &iov); 106 + return ptrace(PTRACE_SETREGSET, pid, type->regset, &iov); 128 107 } 129 108 130 109 /* Validate setting and getting the inherit flag */ 131 - static void ptrace_set_get_inherit(pid_t child) 110 + static void ptrace_set_get_inherit(pid_t child, const struct vec_type *type) 132 111 { 133 112 struct user_sve_header sve; 134 113 struct user_sve_header *new_sve = NULL; ··· 141 118 sve.size = sizeof(sve); 142 119 sve.vl = sve_vl_from_vq(SVE_VQ_MIN); 143 120 sve.flags = SVE_PT_VL_INHERIT; 144 - ret = set_sve(child, &sve); 121 + ret = set_sve(child, type, &sve); 145 122 if (ret != 0) { 146 - ksft_test_result_fail("Failed to set SVE_PT_VL_INHERIT\n"); 123 + ksft_test_result_fail("Failed to set %s SVE_PT_VL_INHERIT\n", 124 + type->name); 147 125 return; 148 126 } 149 127 ··· 152 128 * Read back the new register state and verify that we have 153 129 * set the flags we expected. 154 130 */ 155 - if (!get_sve(child, (void **)&new_sve, &new_sve_size)) { 156 - ksft_test_result_fail("Failed to read SVE flags\n"); 131 + if (!get_sve(child, type, (void **)&new_sve, &new_sve_size)) { 132 + ksft_test_result_fail("Failed to read %s SVE flags\n", 133 + type->name); 157 134 return; 158 135 } 159 136 160 137 ksft_test_result(new_sve->flags & SVE_PT_VL_INHERIT, 161 - "SVE_PT_VL_INHERIT set\n"); 138 + "%s SVE_PT_VL_INHERIT set\n", type->name); 162 139 163 140 /* Now clear */ 164 141 sve.flags &= ~SVE_PT_VL_INHERIT; 165 - ret = set_sve(child, &sve); 142 + ret = set_sve(child, type, &sve); 166 143 if (ret != 0) { 167 - ksft_test_result_fail("Failed to clear SVE_PT_VL_INHERIT\n"); 144 + ksft_test_result_fail("Failed to clear %s SVE_PT_VL_INHERIT\n", 145 + type->name); 168 146 return; 169 147 } 170 148 171 - if (!get_sve(child, (void **)&new_sve, &new_sve_size)) { 172 - ksft_test_result_fail("Failed to read SVE flags\n"); 149 + if (!get_sve(child, type, (void **)&new_sve, &new_sve_size)) { 150 + ksft_test_result_fail("Failed to read %s SVE flags\n", 151 + type->name); 173 152 return; 174 153 } 175 154 176 155 ksft_test_result(!(new_sve->flags & SVE_PT_VL_INHERIT), 177 - "SVE_PT_VL_INHERIT cleared\n"); 156 + "%s SVE_PT_VL_INHERIT cleared\n", type->name); 178 157 179 158 free(new_sve); 180 159 } 181 160 182 161 /* Validate attempting to set the specfied VL via ptrace */ 183 - static void ptrace_set_get_vl(pid_t child, unsigned int vl, bool *supported) 162 + static void ptrace_set_get_vl(pid_t child, const struct vec_type *type, 163 + unsigned int vl, bool *supported) 184 164 { 185 165 struct user_sve_header sve; 186 166 struct user_sve_header *new_sve = NULL; ··· 194 166 *supported = false; 195 167 196 168 /* Check if the VL is supported in this process */ 197 - prctl_vl = prctl(PR_SVE_SET_VL, vl); 169 + prctl_vl = prctl(type->prctl_set, vl); 198 170 if (prctl_vl == -1) 199 - ksft_exit_fail_msg("prctl(PR_SVE_SET_VL) failed: %s (%d)\n", 200 - strerror(errno), errno); 171 + ksft_exit_fail_msg("prctl(PR_%s_SET_VL) failed: %s (%d)\n", 172 + type->name, strerror(errno), errno); 201 173 202 174 /* If the VL is not supported then a supported VL will be returned */ 203 175 *supported = (prctl_vl == vl); ··· 206 178 memset(&sve, 0, sizeof(sve)); 207 179 sve.size = sizeof(sve); 208 180 sve.vl = vl; 209 - ret = set_sve(child, &sve); 181 + ret = set_sve(child, type, &sve); 210 182 if (ret != 0) { 211 - ksft_test_result_fail("Failed to set VL %u\n", vl); 183 + ksft_test_result_fail("Failed to set %s VL %u\n", 184 + type->name, vl); 212 185 return; 213 186 } 214 187 ··· 217 188 * Read back the new register state and verify that we have the 218 189 * same VL that we got from prctl() on ourselves. 219 190 */ 220 - if (!get_sve(child, (void **)&new_sve, &new_sve_size)) { 221 - ksft_test_result_fail("Failed to read VL %u\n", vl); 191 + if (!get_sve(child, type, (void **)&new_sve, &new_sve_size)) { 192 + ksft_test_result_fail("Failed to read %s VL %u\n", 193 + type->name, vl); 222 194 return; 223 195 } 224 196 225 - ksft_test_result(new_sve->vl = prctl_vl, "Set VL %u\n", vl); 197 + ksft_test_result(new_sve->vl = prctl_vl, "Set %s VL %u\n", 198 + type->name, vl); 226 199 227 200 free(new_sve); 228 201 } ··· 240 209 } 241 210 242 211 /* Access the FPSIMD registers via the SVE regset */ 243 - static void ptrace_sve_fpsimd(pid_t child) 212 + static void ptrace_sve_fpsimd(pid_t child, const struct vec_type *type) 244 213 { 245 214 void *svebuf = NULL; 246 215 size_t svebufsz = 0; ··· 250 219 unsigned char *p; 251 220 252 221 /* New process should start with FPSIMD registers only */ 253 - sve = get_sve(child, &svebuf, &svebufsz); 222 + sve = get_sve(child, type, &svebuf, &svebufsz); 254 223 if (!sve) { 255 - ksft_test_result_fail("get_sve: %s\n", strerror(errno)); 224 + ksft_test_result_fail("get_sve(%s): %s\n", 225 + type->name, strerror(errno)); 256 226 257 227 return; 258 228 } else { 259 - ksft_test_result_pass("get_sve(FPSIMD)\n"); 229 + ksft_test_result_pass("get_sve(%s FPSIMD)\n", type->name); 260 230 } 261 231 262 232 ksft_test_result((sve->flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_FPSIMD, 263 - "Set FPSIMD registers\n"); 233 + "Set FPSIMD registers via %s\n", type->name); 264 234 if ((sve->flags & SVE_PT_REGS_MASK) != SVE_PT_REGS_FPSIMD) 265 235 goto out; 266 236 ··· 275 243 p[j] = j; 276 244 } 277 245 278 - if (set_sve(child, sve)) { 279 - ksft_test_result_fail("set_sve(FPSIMD): %s\n", 280 - strerror(errno)); 246 + if (set_sve(child, type, sve)) { 247 + ksft_test_result_fail("set_sve(%s FPSIMD): %s\n", 248 + type->name, strerror(errno)); 281 249 282 250 goto out; 283 251 } ··· 289 257 goto out; 290 258 } 291 259 if (memcmp(fpsimd, &new_fpsimd, sizeof(*fpsimd)) == 0) 292 - ksft_test_result_pass("get_fpsimd() gave same state\n"); 260 + ksft_test_result_pass("%s get_fpsimd() gave same state\n", 261 + type->name); 293 262 else 294 - ksft_test_result_fail("get_fpsimd() gave different state\n"); 263 + ksft_test_result_fail("%s get_fpsimd() gave different state\n", 264 + type->name); 295 265 296 266 out: 297 267 free(svebuf); 298 268 } 299 269 300 270 /* Validate attempting to set SVE data and read SVE data */ 301 - static void ptrace_set_sve_get_sve_data(pid_t child, unsigned int vl) 271 + static void ptrace_set_sve_get_sve_data(pid_t child, 272 + const struct vec_type *type, 273 + unsigned int vl) 302 274 { 303 275 void *write_buf; 304 276 void *read_buf = NULL; ··· 317 281 data_size = SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, SVE_PT_REGS_SVE); 318 282 write_buf = malloc(data_size); 319 283 if (!write_buf) { 320 - ksft_test_result_fail("Error allocating %d byte buffer for VL %u\n", 321 - data_size, vl); 284 + ksft_test_result_fail("Error allocating %d byte buffer for %s VL %u\n", 285 + data_size, type->name, vl); 322 286 return; 323 287 } 324 288 write_sve = write_buf; ··· 342 306 343 307 /* TODO: Generate a valid FFR pattern */ 344 308 345 - ret = set_sve(child, write_sve); 309 + ret = set_sve(child, type, write_sve); 346 310 if (ret != 0) { 347 - ksft_test_result_fail("Failed to set VL %u data\n", vl); 311 + ksft_test_result_fail("Failed to set %s VL %u data\n", 312 + type->name, vl); 348 313 goto out; 349 314 } 350 315 351 316 /* Read the data back */ 352 - if (!get_sve(child, (void **)&read_buf, &read_sve_size)) { 353 - ksft_test_result_fail("Failed to read VL %u data\n", vl); 317 + if (!get_sve(child, type, (void **)&read_buf, &read_sve_size)) { 318 + ksft_test_result_fail("Failed to read %s VL %u data\n", 319 + type->name, vl); 354 320 goto out; 355 321 } 356 322 read_sve = read_buf; 357 323 358 324 /* We might read more data if there's extensions we don't know */ 359 325 if (read_sve->size < write_sve->size) { 360 - ksft_test_result_fail("Wrote %d bytes, only read %d\n", 361 - write_sve->size, read_sve->size); 326 + ksft_test_result_fail("%s wrote %d bytes, only read %d\n", 327 + type->name, write_sve->size, 328 + read_sve->size); 362 329 goto out_read; 363 330 } 364 331 ··· 388 349 check_u32(vl, "FPCR", write_buf + SVE_PT_SVE_FPCR_OFFSET(vq), 389 350 read_buf + SVE_PT_SVE_FPCR_OFFSET(vq), &errors); 390 351 391 - ksft_test_result(errors == 0, "Set and get SVE data for VL %u\n", vl); 352 + ksft_test_result(errors == 0, "Set and get %s data for VL %u\n", 353 + type->name, vl); 392 354 393 355 out_read: 394 356 free(read_buf); ··· 398 358 } 399 359 400 360 /* Validate attempting to set SVE data and read SVE data */ 401 - static void ptrace_set_sve_get_fpsimd_data(pid_t child, unsigned int vl) 361 + static void ptrace_set_sve_get_fpsimd_data(pid_t child, 362 + const struct vec_type *type, 363 + unsigned int vl) 402 364 { 403 365 void *write_buf; 404 366 struct user_sve_header *write_sve; ··· 418 376 data_size = SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, SVE_PT_REGS_SVE); 419 377 write_buf = malloc(data_size); 420 378 if (!write_buf) { 421 - ksft_test_result_fail("Error allocating %d byte buffer for VL %u\n", 422 - data_size, vl); 379 + ksft_test_result_fail("Error allocating %d byte buffer for %s VL %u\n", 380 + data_size, type->name, vl); 423 381 return; 424 382 } 425 383 write_sve = write_buf; ··· 437 395 fill_buf(write_buf + SVE_PT_SVE_FPSR_OFFSET(vq), SVE_PT_SVE_FPSR_SIZE); 438 396 fill_buf(write_buf + SVE_PT_SVE_FPCR_OFFSET(vq), SVE_PT_SVE_FPCR_SIZE); 439 397 440 - ret = set_sve(child, write_sve); 398 + ret = set_sve(child, type, write_sve); 441 399 if (ret != 0) { 442 - ksft_test_result_fail("Failed to set VL %u data\n", vl); 400 + ksft_test_result_fail("Failed to set %s VL %u data\n", 401 + type->name, vl); 443 402 goto out; 444 403 } 445 404 446 405 /* Read the data back */ 447 406 if (get_fpsimd(child, &fpsimd_state)) { 448 - ksft_test_result_fail("Failed to read VL %u FPSIMD data\n", 449 - vl); 407 + ksft_test_result_fail("Failed to read %s VL %u FPSIMD data\n", 408 + type->name, vl); 450 409 goto out; 451 410 } 452 411 ··· 462 419 sizeof(tmp)); 463 420 464 421 if (tmp != fpsimd_state.vregs[i]) { 465 - printf("# Mismatch in FPSIMD for VL %u Z%d\n", vl, i); 422 + printf("# Mismatch in FPSIMD for %s VL %u Z%d\n", 423 + type->name, vl, i); 466 424 errors++; 467 425 } 468 426 } ··· 473 429 check_u32(vl, "FPCR", write_buf + SVE_PT_SVE_FPCR_OFFSET(vq), 474 430 &fpsimd_state.fpcr, &errors); 475 431 476 - ksft_test_result(errors == 0, "Set and get FPSIMD data for VL %u\n", 477 - vl); 432 + ksft_test_result(errors == 0, "Set and get FPSIMD data for %s VL %u\n", 433 + type->name, vl); 478 434 479 435 out: 480 436 free(write_buf); ··· 484 440 { 485 441 int ret = EXIT_FAILURE; 486 442 pid_t pid; 487 - int status; 443 + int status, i; 488 444 siginfo_t si; 489 445 unsigned int vq, vl; 490 446 bool vl_supported; ··· 543 499 } 544 500 } 545 501 546 - /* FPSIMD via SVE regset */ 547 - ptrace_sve_fpsimd(child); 548 - 549 - /* prctl() flags */ 550 - ptrace_set_get_inherit(child); 551 - 552 - /* Step through every possible VQ */ 553 - for (vq = SVE_VQ_MIN; vq <= SVE_VQ_MAX; vq++) { 554 - vl = sve_vl_from_vq(vq); 555 - 556 - /* First, try to set this vector length */ 557 - ptrace_set_get_vl(child, vl, &vl_supported); 558 - 559 - /* If the VL is supported validate data set/get */ 560 - if (vl_supported) { 561 - ptrace_set_sve_get_sve_data(child, vl); 562 - ptrace_set_sve_get_fpsimd_data(child, vl); 502 + for (i = 0; i < ARRAY_SIZE(vec_types); i++) { 503 + /* FPSIMD via SVE regset */ 504 + if (getauxval(vec_types[i].hwcap_type) & vec_types[i].hwcap) { 505 + ptrace_sve_fpsimd(child, &vec_types[i]); 563 506 } else { 564 - ksft_test_result_skip("set SVE get SVE for VL %d\n", vl); 565 - ksft_test_result_skip("set SVE get FPSIMD for VL %d\n", vl); 507 + ksft_test_result_skip("%s FPSIMD get via SVE\n", 508 + vec_types[i].name); 509 + ksft_test_result_skip("%s FPSIMD set via SVE\n", 510 + vec_types[i].name); 511 + ksft_test_result_skip("%s set read via FPSIMD\n", 512 + vec_types[i].name); 513 + } 514 + 515 + /* prctl() flags */ 516 + ptrace_set_get_inherit(child, &vec_types[i]); 517 + 518 + /* Step through every possible VQ */ 519 + for (vq = SVE_VQ_MIN; vq <= SVE_VQ_MAX; vq++) { 520 + vl = sve_vl_from_vq(vq); 521 + 522 + /* First, try to set this vector length */ 523 + if (getauxval(vec_types[i].hwcap_type) & 524 + vec_types[i].hwcap) { 525 + ptrace_set_get_vl(child, &vec_types[i], vl, 526 + &vl_supported); 527 + } else { 528 + ksft_test_result_skip("%s get/set VL %d\n", 529 + vec_types[i].name, vl); 530 + vl_supported = false; 531 + } 532 + 533 + /* If the VL is supported validate data set/get */ 534 + if (vl_supported) { 535 + ptrace_set_sve_get_sve_data(child, &vec_types[i], vl); 536 + ptrace_set_sve_get_fpsimd_data(child, &vec_types[i], vl); 537 + } else { 538 + ksft_test_result_skip("%s set SVE get SVE for VL %d\n", 539 + vec_types[i].name, vl); 540 + ksft_test_result_skip("%s set SVE get FPSIMD for VL %d\n", 541 + vec_types[i].name, vl); 542 + } 566 543 } 567 544 } 568 545
+5 -7
tools/testing/selftests/arm64/signal/test_signals_utils.c
··· 310 310 311 311 int test_run(struct tdescr *td) 312 312 { 313 - if (td->sig_trig) { 314 - if (td->trigger) 315 - return td->trigger(td); 316 - else 317 - return default_trigger(td); 318 - } else { 313 + if (td->trigger) 314 + return td->trigger(td); 315 + else if (td->sig_trig) 316 + return default_trigger(td); 317 + else 319 318 return td->run(td, NULL, NULL); 320 - } 321 319 } 322 320 323 321 void test_result(struct tdescr *td)