diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-11-02 21:33:15 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-11-02 21:33:15 +0300 |
commit | ab2e7f4b46bf8fccf088ec496b3bb26b43e91340 (patch) | |
tree | 0a3010aa08436bdee650fbf4d0371b8d17555ff3 /arch/arm/include | |
parent | d7e0a795bf37a13554c80cfc5ba97abedf53f391 (diff) | |
parent | 11779842dd6f59505f5685bdd6ebaaa7a5bc1d94 (diff) | |
download | linux-ab2e7f4b46bf8fccf088ec496b3bb26b43e91340.tar.xz |
Merge tag 'for-linus' of git://git.armlinux.org.uk/~rmk/linux-arm
Pull ARM updates from Russell King:
- Rejig task/thread info to place thread info in task struct
- Amba bus cleanups (removing unused functions)
- Handle Amba device probe without IRQ domains
- Parse linux,usable-memory-range in decompressor
- Mark OCRAM as read-only after initialisation
- Refactor page fault handling
- Fix PXN handling with LPAE kernels
- Warning and build fixes from Arnd
* tag 'for-linus' of git://git.armlinux.org.uk/~rmk/linux-arm: (32 commits)
ARM: 9151/1: Thumb2: avoid __builtin_thread_pointer() on Clang
ARM: 9150/1: Fix PID_IN_CONTEXTIDR regression when THREAD_INFO_IN_TASK=y
ARM: 9147/1: add printf format attribute to early_print()
ARM: 9146/1: RiscPC needs older gcc version
ARM: 9145/1: patch: fix BE32 compilation
ARM: 9144/1: forbid ftrace with clang and thumb2_kernel
ARM: 9143/1: add CONFIG_PHYS_OFFSET default values
ARM: 9142/1: kasan: work around LPAE build warning
ARM: 9140/1: allow compile-testing without machine record
ARM: 9137/1: disallow CONFIG_THUMB with ARMv4
ARM: 9136/1: ARMv7-M uses BE-8, not BE-32
ARM: 9135/1: kprobes: address gcc -Wempty-body warning
ARM: 9101/1: sa1100/assabet: convert LEDs to gpiod APIs
ARM: 9131/1: mm: Fix PXN process with LPAE feature
ARM: 9130/1: mm: Provide die_kernel_fault() helper
ARM: 9126/1: mm: Kill page table base print in show_pte()
ARM: 9127/1: mm: Cleanup access_error()
ARM: 9129/1: mm: Kill task_struct argument for __do_page_fault()
ARM: 9128/1: mm: Refactor the __do_page_fault()
ARM: imx6: mark OCRAM mapping read-only
...
Diffstat (limited to 'arch/arm/include')
-rw-r--r-- | arch/arm/include/asm/assembler.h | 29 | ||||
-rw-r--r-- | arch/arm/include/asm/current.h | 55 | ||||
-rw-r--r-- | arch/arm/include/asm/io.h | 1 | ||||
-rw-r--r-- | arch/arm/include/asm/opcodes.h | 9 | ||||
-rw-r--r-- | arch/arm/include/asm/setup.h | 2 | ||||
-rw-r--r-- | arch/arm/include/asm/smp.h | 3 | ||||
-rw-r--r-- | arch/arm/include/asm/stackprotector.h | 2 | ||||
-rw-r--r-- | arch/arm/include/asm/switch_to.h | 16 | ||||
-rw-r--r-- | arch/arm/include/asm/thread_info.h | 26 | ||||
-rw-r--r-- | arch/arm/include/asm/tls.h | 10 |
10 files changed, 140 insertions, 13 deletions
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index e2b1fd558bf3..7d23d4bb2168 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h @@ -199,14 +199,43 @@ .endm .endr + .macro get_current, rd +#ifdef CONFIG_CURRENT_POINTER_IN_TPIDRURO + mrc p15, 0, \rd, c13, c0, 3 @ get TPIDRURO register +#else + get_thread_info \rd + ldr \rd, [\rd, #TI_TASK] +#endif + .endm + + .macro set_current, rn +#ifdef CONFIG_CURRENT_POINTER_IN_TPIDRURO + mcr p15, 0, \rn, c13, c0, 3 @ set TPIDRURO register +#endif + .endm + + .macro reload_current, t1:req, t2:req +#ifdef CONFIG_CURRENT_POINTER_IN_TPIDRURO + adr_l \t1, __entry_task @ get __entry_task base address + mrc p15, 0, \t2, c13, c0, 4 @ get per-CPU offset + ldr \t1, [\t1, \t2] @ load variable + mcr p15, 0, \t1, c13, c0, 3 @ store in TPIDRURO +#endif + .endm + /* * Get current thread_info. */ .macro get_thread_info, rd +#ifdef CONFIG_THREAD_INFO_IN_TASK + /* thread_info is the first member of struct task_struct */ + get_current \rd +#else ARM( mov \rd, sp, lsr #THREAD_SIZE_ORDER + PAGE_SHIFT ) THUMB( mov \rd, sp ) THUMB( lsr \rd, \rd, #THREAD_SIZE_ORDER + PAGE_SHIFT ) mov \rd, \rd, lsl #THREAD_SIZE_ORDER + PAGE_SHIFT +#endif .endm /* diff --git a/arch/arm/include/asm/current.h b/arch/arm/include/asm/current.h new file mode 100644 index 000000000000..6bf0aad672c3 --- /dev/null +++ b/arch/arm/include/asm/current.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021 Keith Packard <keithp@keithp.com> + * Copyright (c) 2021 Google, LLC <ardb@kernel.org> + */ + +#ifndef _ASM_ARM_CURRENT_H +#define _ASM_ARM_CURRENT_H + +#ifndef __ASSEMBLY__ + +struct task_struct; + +static inline void set_current(struct task_struct *cur) +{ + if (!IS_ENABLED(CONFIG_CURRENT_POINTER_IN_TPIDRURO)) + return; + + /* Set TPIDRURO */ + asm("mcr p15, 0, %0, c13, c0, 3" :: "r"(cur) : "memory"); +} + +#ifdef CONFIG_CURRENT_POINTER_IN_TPIDRURO + +static inline struct task_struct *get_current(void) +{ + struct task_struct *cur; + +#if __has_builtin(__builtin_thread_pointer) && \ + !(defined(CONFIG_THUMB2_KERNEL) && \ + defined(CONFIG_CC_IS_CLANG) && CONFIG_CLANG_VERSION < 130001) + /* + * Use the __builtin helper when available - this results in better + * code, especially when using GCC in combination with the per-task + * stack protector, as the compiler will recognize that it needs to + * load the TLS register only once in every function. + * + * Clang < 13.0.1 gets this wrong for Thumb2 builds: + * https://github.com/ClangBuiltLinux/linux/issues/1485 + */ + cur = __builtin_thread_pointer(); +#else + asm("mrc p15, 0, %0, c13, c0, 3" : "=r"(cur)); +#endif + return cur; +} + +#define current get_current() +#else +#include <asm-generic/current.h> +#endif /* CONFIG_CURRENT_POINTER_IN_TPIDRURO */ + +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_ARM_CURRENT_H */ diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index f74944c6fe8d..c576fa7d9bf8 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -138,6 +138,7 @@ extern void __iomem *__arm_ioremap_caller(phys_addr_t, size_t, unsigned int, void *); extern void __iomem *__arm_ioremap_pfn(unsigned long, unsigned long, size_t, unsigned int); extern void __iomem *__arm_ioremap_exec(phys_addr_t, size_t, bool cached); +void __arm_iomem_set_ro(void __iomem *ptr, size_t size); extern void __iounmap(volatile void __iomem *addr); extern void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t, diff --git a/arch/arm/include/asm/opcodes.h b/arch/arm/include/asm/opcodes.h index 6bff94b2372b..38e3eabff5c3 100644 --- a/arch/arm/include/asm/opcodes.h +++ b/arch/arm/include/asm/opcodes.h @@ -110,12 +110,17 @@ extern asmlinkage unsigned int arm_check_condition(u32 opcode, u32 psr); #define __opcode_to_mem_thumb16(x) ___opcode_identity16(x) #define ___asm_opcode_to_mem_arm(x) ___asm_opcode_identity32(x) #define ___asm_opcode_to_mem_thumb16(x) ___asm_opcode_identity16(x) -#ifndef CONFIG_CPU_ENDIAN_BE32 +#ifdef CONFIG_CPU_ENDIAN_BE32 +#ifndef __ASSEMBLY__ /* * On BE32 systems, using 32-bit accesses to store Thumb instructions will not * work in all cases, due to alignment constraints. For now, a correct - * version is not provided for BE32. + * version is not provided for BE32, but the prototype needs to be there + * to compile patch.c. */ +extern __u32 __opcode_to_mem_thumb32(__u32); +#endif +#else #define __opcode_to_mem_thumb32(x) ___opcode_swahw32(x) #define ___asm_opcode_to_mem_thumb32(x) ___asm_opcode_swahw32(x) #endif diff --git a/arch/arm/include/asm/setup.h b/arch/arm/include/asm/setup.h index 3ae68a1b3de6..ba0872a8dcda 100644 --- a/arch/arm/include/asm/setup.h +++ b/arch/arm/include/asm/setup.h @@ -19,7 +19,7 @@ static const struct tagtable __tagtable_##fn __tag = { tag, fn } extern int arm_add_memory(u64 start, u64 size); -extern void early_print(const char *str, ...); +extern __printf(1, 2) void early_print(const char *str, ...); extern void dump_machine_table(void); #ifdef CONFIG_ATAGS_PROC diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h index 5d508f5d56c4..f16cbbd5cda4 100644 --- a/arch/arm/include/asm/smp.h +++ b/arch/arm/include/asm/smp.h @@ -48,7 +48,7 @@ extern void set_smp_ipi_range(int ipi_base, int nr_ipi); * Called from platform specific assembly code, this is the * secondary CPU entry point. */ -asmlinkage void secondary_start_kernel(void); +asmlinkage void secondary_start_kernel(struct task_struct *task); /* @@ -61,6 +61,7 @@ struct secondary_data { }; unsigned long swapper_pg_dir; void *stack; + struct task_struct *task; }; extern struct secondary_data secondary_data; extern void secondary_startup(void); diff --git a/arch/arm/include/asm/stackprotector.h b/arch/arm/include/asm/stackprotector.h index 72a20c3a0a90..088d03161be5 100644 --- a/arch/arm/include/asm/stackprotector.h +++ b/arch/arm/include/asm/stackprotector.h @@ -39,8 +39,6 @@ static __always_inline void boot_init_stack_canary(void) current->stack_canary = canary; #ifndef CONFIG_STACKPROTECTOR_PER_TASK __stack_chk_guard = current->stack_canary; -#else - current_thread_info()->stack_canary = current->stack_canary; #endif } diff --git a/arch/arm/include/asm/switch_to.h b/arch/arm/include/asm/switch_to.h index 007d8fea7157..b55c7b2755e4 100644 --- a/arch/arm/include/asm/switch_to.h +++ b/arch/arm/include/asm/switch_to.h @@ -23,9 +23,25 @@ */ extern struct task_struct *__switch_to(struct task_struct *, struct thread_info *, struct thread_info *); +static inline void set_ti_cpu(struct task_struct *p) +{ +#ifdef CONFIG_THREAD_INFO_IN_TASK + /* + * The core code no longer maintains the thread_info::cpu field once + * CONFIG_THREAD_INFO_IN_TASK is in effect, but we rely on it for + * raw_smp_processor_id(), which cannot access struct task_struct* + * directly for reasons of circular #inclusion hell. + */ + task_thread_info(p)->cpu = task_cpu(p); +#endif +} + #define switch_to(prev,next,last) \ do { \ __complete_pending_tlbi(); \ + set_ti_cpu(next); \ + if (IS_ENABLED(CONFIG_CURRENT_POINTER_IN_TPIDRURO)) \ + __this_cpu_write(__entry_task, next); \ last = __switch_to(prev,task_thread_info(prev), task_thread_info(next)); \ } while (0) diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h index 9a18da3e10cc..164e15f26485 100644 --- a/arch/arm/include/asm/thread_info.h +++ b/arch/arm/include/asm/thread_info.h @@ -29,6 +29,8 @@ struct task_struct; +DECLARE_PER_CPU(struct task_struct *, __entry_task); + #include <asm/types.h> struct cpu_context_save { @@ -52,12 +54,11 @@ struct cpu_context_save { struct thread_info { unsigned long flags; /* low level flags */ int preempt_count; /* 0 => preemptable, <0 => bug */ +#ifndef CONFIG_THREAD_INFO_IN_TASK struct task_struct *task; /* main task structure */ +#endif __u32 cpu; /* cpu */ __u32 cpu_domain; /* cpu domain */ -#ifdef CONFIG_STACKPROTECTOR_PER_TASK - unsigned long stack_canary; -#endif struct cpu_context_save cpu_context; /* cpu context */ __u32 abi_syscall; /* ABI type and syscall nr */ __u8 used_cp[16]; /* thread used copro */ @@ -71,11 +72,27 @@ struct thread_info { #define INIT_THREAD_INFO(tsk) \ { \ - .task = &tsk, \ + INIT_THREAD_INFO_TASK(tsk) \ .flags = 0, \ .preempt_count = INIT_PREEMPT_COUNT, \ } +#ifdef CONFIG_THREAD_INFO_IN_TASK +#define INIT_THREAD_INFO_TASK(tsk) + +static inline struct task_struct *thread_task(struct thread_info* ti) +{ + return (struct task_struct *)ti; +} + +#else +#define INIT_THREAD_INFO_TASK(tsk) .task = &(tsk), + +static inline struct task_struct *thread_task(struct thread_info* ti) +{ + return ti->task; +} + /* * how to get the thread information struct from C */ @@ -86,6 +103,7 @@ static inline struct thread_info *current_thread_info(void) return (struct thread_info *) (current_stack_pointer & ~(THREAD_SIZE - 1)); } +#endif #define thread_saved_pc(tsk) \ ((unsigned long)(task_thread_info(tsk)->cpu_context.pc)) diff --git a/arch/arm/include/asm/tls.h b/arch/arm/include/asm/tls.h index 5a66c3b13c92..c3296499176c 100644 --- a/arch/arm/include/asm/tls.h +++ b/arch/arm/include/asm/tls.h @@ -12,8 +12,8 @@ .macro switch_tls_v6k, base, tp, tpuser, tmp1, tmp2 mrc p15, 0, \tmp2, c13, c0, 2 @ get the user r/w register - mcr p15, 0, \tp, c13, c0, 3 @ set TLS register - mcr p15, 0, \tpuser, c13, c0, 2 @ and the user r/w register + @ TLS register update is deferred until return to user space + mcr p15, 0, \tpuser, c13, c0, 2 @ set the user r/w register str \tmp2, [\base, #TI_TP_VALUE + 4] @ save it .endm @@ -38,18 +38,22 @@ #ifdef CONFIG_TLS_REG_EMUL #define tls_emu 1 #define has_tls_reg 1 +#define defer_tls_reg_update 0 #define switch_tls switch_tls_none #elif defined(CONFIG_CPU_V6) #define tls_emu 0 #define has_tls_reg (elf_hwcap & HWCAP_TLS) +#define defer_tls_reg_update 0 #define switch_tls switch_tls_v6 #elif defined(CONFIG_CPU_32v6K) #define tls_emu 0 #define has_tls_reg 1 +#define defer_tls_reg_update 1 #define switch_tls switch_tls_v6k #else #define tls_emu 0 #define has_tls_reg 0 +#define defer_tls_reg_update 0 #define switch_tls switch_tls_software #endif @@ -77,7 +81,7 @@ static inline void set_tls(unsigned long val) */ barrier(); - if (!tls_emu) { + if (!tls_emu && !defer_tls_reg_update) { if (has_tls_reg) { asm("mcr p15, 0, %0, c13, c0, 3" : : "r" (val)); |