summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2021-11-02 11:33:15 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2021-11-02 11:33:15 -0700
commitab2e7f4b46bf8fccf088ec496b3bb26b43e91340 (patch)
tree0a3010aa08436bdee650fbf4d0371b8d17555ff3
parentd7e0a795bf37a13554c80cfc5ba97abedf53f391 (diff)
parent11779842dd6f59505f5685bdd6ebaaa7a5bc1d94 (diff)
downloadlinux-ab2e7f4b46bf8fccf088ec496b3bb26b43e91340.tar.gz
linux-ab2e7f4b46bf8fccf088ec496b3bb26b43e91340.tar.bz2
linux-ab2e7f4b46bf8fccf088ec496b3bb26b43e91340.zip
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 ...
-rw-r--r--arch/arm/Kconfig19
-rw-r--r--arch/arm/Makefile9
-rw-r--r--arch/arm/boot/compressed/fdt_check_mem_start.c48
-rw-r--r--arch/arm/common/scoop.c3
-rw-r--r--arch/arm/include/asm/assembler.h29
-rw-r--r--arch/arm/include/asm/current.h55
-rw-r--r--arch/arm/include/asm/io.h1
-rw-r--r--arch/arm/include/asm/opcodes.h9
-rw-r--r--arch/arm/include/asm/setup.h2
-rw-r--r--arch/arm/include/asm/smp.h3
-rw-r--r--arch/arm/include/asm/stackprotector.h2
-rw-r--r--arch/arm/include/asm/switch_to.h16
-rw-r--r--arch/arm/include/asm/thread_info.h26
-rw-r--r--arch/arm/include/asm/tls.h10
-rw-r--r--arch/arm/kernel/asm-offsets.c6
-rw-r--r--arch/arm/kernel/entry-armv.S5
-rw-r--r--arch/arm/kernel/entry-common.S1
-rw-r--r--arch/arm/kernel/entry-header.S8
-rw-r--r--arch/arm/kernel/head-common.S5
-rw-r--r--arch/arm/kernel/head-nommu.S1
-rw-r--r--arch/arm/kernel/head.S5
-rw-r--r--arch/arm/kernel/process.c8
-rw-r--r--arch/arm/kernel/smp.c13
-rw-r--r--arch/arm/kernel/vmlinux-xip.lds.S2
-rw-r--r--arch/arm/kernel/vmlinux.lds.S2
-rw-r--r--arch/arm/mach-imx/pm-imx6.c2
-rw-r--r--arch/arm/mach-sa1100/assabet.c24
-rw-r--r--arch/arm/mm/Kconfig4
-rw-r--r--arch/arm/mm/context.c2
-rw-r--r--arch/arm/mm/fault.c119
-rw-r--r--arch/arm/mm/fault.h4
-rw-r--r--arch/arm/mm/ioremap.c6
-rw-r--r--arch/arm/mm/kasan_init.c2
-rw-r--r--arch/arm/mm/proc-macros.S3
-rw-r--r--arch/arm/probes/kprobes/test-core.h2
-rw-r--r--drivers/amba/bus.c100
-rw-r--r--drivers/of/platform.c6
-rw-r--r--include/linux/amba/bus.h18
-rw-r--r--scripts/gcc-plugins/arm_ssp_per_task_plugin.c27
39 files changed, 372 insertions, 235 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 5d3b030e78e3..d96209b20736 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -91,7 +91,7 @@ config ARM
select HAVE_FAST_GUP if ARM_LPAE
select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL
select HAVE_FUNCTION_GRAPH_TRACER if !THUMB2_KERNEL && !CC_IS_CLANG
- select HAVE_FUNCTION_TRACER if !XIP_KERNEL
+ select HAVE_FUNCTION_TRACER if !XIP_KERNEL && !(THUMB2_KERNEL && CC_IS_CLANG)
select HAVE_FUTEX_CMPXCHG if FUTEX
select HAVE_GCC_PLUGINS
select HAVE_HW_BREAKPOINT if PERF_EVENTS && (CPU_V6 || CPU_V6K || CPU_V7)
@@ -126,6 +126,7 @@ config ARM
select PERF_USE_VMALLOC
select RTC_LIB
select SYS_SUPPORTS_APM_EMULATION
+ select THREAD_INFO_IN_TASK if CURRENT_POINTER_IN_TPIDRURO
select TRACE_IRQFLAGS_SUPPORT if !CPU_V7M
# Above selects are sorted alphabetically; please add new ones
# according to that. Thanks.
@@ -265,10 +266,12 @@ config PHYS_OFFSET
hex "Physical address of main memory" if MMU
depends on !ARM_PATCH_PHYS_VIRT
default DRAM_BASE if !MMU
- default 0x00000000 if ARCH_FOOTBRIDGE
+ default 0x00000000 if ARCH_FOOTBRIDGE || ARCH_IXP4XX
default 0x10000000 if ARCH_OMAP1 || ARCH_RPC
- default 0x20000000 if ARCH_S5PV210
- default 0xc0000000 if ARCH_SA1100
+ default 0x30000000 if ARCH_S3C24XX
+ default 0xa0000000 if ARCH_IOP32X || ARCH_PXA
+ default 0xc0000000 if ARCH_EP93XX || ARCH_SA1100
+ default 0
help
Please provide the physical address corresponding to the
location of main memory in your system.
@@ -433,6 +436,7 @@ config ARCH_PXA
config ARCH_RPC
bool "RiscPC"
depends on MMU
+ depends on !CC_IS_CLANG && GCC_VERSION < 90100 && GCC_VERSION >= 60000
select ARCH_ACORN
select ARCH_MAY_HAVE_PC_FDC
select ARCH_SPARSEMEM_ENABLE
@@ -1158,6 +1162,11 @@ config SMP_ON_UP
If you don't know what to do here, say Y.
+
+config CURRENT_POINTER_IN_TPIDRURO
+ def_bool y
+ depends on SMP && CPU_32v6K && !CPU_V6
+
config ARM_CPU_TOPOLOGY
bool "Support cpu topology definition"
depends on SMP && CPU_V7
@@ -1601,7 +1610,7 @@ config XEN
config STACKPROTECTOR_PER_TASK
bool "Use a unique stack canary value for each task"
- depends on GCC_PLUGINS && STACKPROTECTOR && SMP && !XIP_DEFLATED_DATA
+ depends on GCC_PLUGINS && STACKPROTECTOR && THREAD_INFO_IN_TASK && !XIP_DEFLATED_DATA
select GCC_PLUGIN_ARM_SSP_PER_TASK
default y
help
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 847c31e7c368..1c540157e283 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -113,6 +113,10 @@ ifeq ($(CONFIG_CC_IS_CLANG),y)
CFLAGS_ABI += -meabi gnu
endif
+ifeq ($(CONFIG_CURRENT_POINTER_IN_TPIDRURO),y)
+CFLAGS_ABI += -mtp=cp15
+endif
+
# Accept old syntax despite ".syntax unified"
AFLAGS_NOWARN :=$(call as-option,-Wa$(comma)-mno-warn-deprecated,-Wa$(comma)-W)
@@ -273,11 +277,8 @@ ifeq ($(CONFIG_STACKPROTECTOR_PER_TASK),y)
prepare: stack_protector_prepare
stack_protector_prepare: prepare0
$(eval SSP_PLUGIN_CFLAGS := \
- -fplugin-arg-arm_ssp_per_task_plugin-tso=$(shell \
- awk '{if ($$2 == "THREAD_SZ_ORDER") print $$3;}'\
- include/generated/asm-offsets.h) \
-fplugin-arg-arm_ssp_per_task_plugin-offset=$(shell \
- awk '{if ($$2 == "TI_STACK_CANARY") print $$3;}'\
+ awk '{if ($$2 == "TSK_STACK_CANARY") print $$3;}'\
include/generated/asm-offsets.h))
$(eval KBUILD_CFLAGS += $(SSP_PLUGIN_CFLAGS))
$(eval GCC_PLUGINS_CFLAGS += $(SSP_PLUGIN_CFLAGS))
diff --git a/arch/arm/boot/compressed/fdt_check_mem_start.c b/arch/arm/boot/compressed/fdt_check_mem_start.c
index 62450d824c3c..9291a2661bdf 100644
--- a/arch/arm/boot/compressed/fdt_check_mem_start.c
+++ b/arch/arm/boot/compressed/fdt_check_mem_start.c
@@ -55,16 +55,17 @@ static uint64_t get_val(const fdt32_t *cells, uint32_t ncells)
* DTB, and, if out-of-range, replace it by the real start address.
* To preserve backwards compatibility (systems reserving a block of memory
* at the start of physical memory, kdump, ...), the traditional method is
- * always used if it yields a valid address.
+ * used if it yields a valid address, unless the "linux,usable-memory-range"
+ * property is present.
*
* Return value: start address of physical memory to use
*/
uint32_t fdt_check_mem_start(uint32_t mem_start, const void *fdt)
{
- uint32_t addr_cells, size_cells, base;
+ uint32_t addr_cells, size_cells, usable_base, base;
uint32_t fdt_mem_start = 0xffffffff;
- const fdt32_t *reg, *endp;
- uint64_t size, end;
+ const fdt32_t *usable, *reg, *endp;
+ uint64_t size, usable_end, end;
const char *type;
int offset, len;
@@ -80,6 +81,27 @@ uint32_t fdt_check_mem_start(uint32_t mem_start, const void *fdt)
if (addr_cells > 2 || size_cells > 2)
return mem_start;
+ /*
+ * Usable memory in case of a crash dump kernel
+ * This property describes a limitation: memory within this range is
+ * only valid when also described through another mechanism
+ */
+ usable = get_prop(fdt, "/chosen", "linux,usable-memory-range",
+ (addr_cells + size_cells) * sizeof(fdt32_t));
+ if (usable) {
+ size = get_val(usable + addr_cells, size_cells);
+ if (!size)
+ return mem_start;
+
+ if (addr_cells > 1 && fdt32_ld(usable)) {
+ /* Outside 32-bit address space */
+ return mem_start;
+ }
+
+ usable_base = fdt32_ld(usable + addr_cells - 1);
+ usable_end = usable_base + size;
+ }
+
/* Walk all memory nodes and regions */
for (offset = fdt_next_node(fdt, -1, NULL); offset >= 0;
offset = fdt_next_node(fdt, offset, NULL)) {
@@ -107,7 +129,20 @@ uint32_t fdt_check_mem_start(uint32_t mem_start, const void *fdt)
base = fdt32_ld(reg + addr_cells - 1);
end = base + size;
- if (mem_start >= base && mem_start < end) {
+ if (usable) {
+ /*
+ * Clip to usable range, which takes precedence
+ * over mem_start
+ */
+ if (base < usable_base)
+ base = usable_base;
+
+ if (end > usable_end)
+ end = usable_end;
+
+ if (end <= base)
+ continue;
+ } else if (mem_start >= base && mem_start < end) {
/* Calculated address is valid, use it */
return mem_start;
}
@@ -123,7 +158,8 @@ uint32_t fdt_check_mem_start(uint32_t mem_start, const void *fdt)
}
/*
- * The calculated address is not usable.
+ * The calculated address is not usable, or was overridden by the
+ * "linux,usable-memory-range" property.
* Use the lowest usable physical memory address from the DTB instead,
* and make sure this is a multiple of 2 MiB for phys/virt patching.
*/
diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c
index 6edb961bd6c1..e74c5bfdc6d3 100644
--- a/arch/arm/common/scoop.c
+++ b/arch/arm/common/scoop.c
@@ -240,9 +240,6 @@ static int scoop_remove(struct platform_device *pdev)
{
struct scoop_dev *sdev = platform_get_drvdata(pdev);
- if (!sdev)
- return -EINVAL;
-
if (sdev->gpio.base != -1)
gpiochip_remove(&sdev->gpio);
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));
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index a646a3f6440f..645845e4982a 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -43,7 +43,9 @@ int main(void)
BLANK();
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
+#ifndef CONFIG_THREAD_INFO_IN_TASK
DEFINE(TI_TASK, offsetof(struct thread_info, task));
+#endif
DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
DEFINE(TI_CPU_DOMAIN, offsetof(struct thread_info, cpu_domain));
DEFINE(TI_CPU_SAVE, offsetof(struct thread_info, cpu_context));
@@ -63,10 +65,6 @@ int main(void)
#ifdef CONFIG_IWMMXT
DEFINE(TI_IWMMXT_STATE, offsetof(struct thread_info, fpstate.iwmmxt));
#endif
-#ifdef CONFIG_STACKPROTECTOR_PER_TASK
- DEFINE(TI_STACK_CANARY, offsetof(struct thread_info, stack_canary));
-#endif
- DEFINE(THREAD_SZ_ORDER, THREAD_SIZE_ORDER);
BLANK();
DEFINE(S_R0, offsetof(struct pt_regs, ARM_r0));
DEFINE(S_R1, offsetof(struct pt_regs, ARM_r1));
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 3d0b6169ab86..deff286eb5ea 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -381,6 +381,8 @@ ENDPROC(__fiq_abt)
ATRAP( teq r8, r7)
ATRAP( mcrne p15, 0, r8, c1, c0, 0)
+ reload_current r7, r8
+
@
@ Clear FP to mark the first stack frame
@
@@ -759,6 +761,8 @@ ENTRY(__switch_to)
add r7, r7, #TSK_STACK_CANARY & ~IMM12_MASK
.endif
ldr r7, [r7, #TSK_STACK_CANARY & IMM12_MASK]
+#elif defined(CONFIG_CURRENT_POINTER_IN_TPIDRURO)
+ mov r7, r2 @ Preserve 'next'
#endif
#ifdef CONFIG_CPU_USE_DOMAINS
mcr p15, 0, r6, c3, c0, 0 @ Set domain register
@@ -773,6 +777,7 @@ ENTRY(__switch_to)
#endif
THUMB( mov ip, r4 )
mov r0, r5
+ set_current r7
ARM( ldmia r4, {r4 - sl, fp, sp, pc} ) @ Load all regs saved previously
THUMB( ldmia ip!, {r4 - sl, fp} ) @ Load all regs saved previously
THUMB( ldr sp, [ip], #4 )
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index d9c99db50243..ac86c34682bb 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -170,6 +170,7 @@ ENTRY(vector_swi)
str saved_psr, [sp, #S_PSR] @ Save CPSR
str r0, [sp, #S_OLD_R0] @ Save OLD_R0
#endif
+ reload_current r10, ip
zero_fp
alignment_trap r10, ip, __cr_alignment
asm_trace_hardirqs_on save=0
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index 40db0f9188b6..ae24dd54e9ef 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -292,6 +292,14 @@
.macro restore_user_regs, fast = 0, offset = 0
+#if defined(CONFIG_CPU_32v6K) && !defined(CONFIG_CPU_V6)
+ @ The TLS register update is deferred until return to user space so we
+ @ can use it for other things while running in the kernel
+ get_thread_info r1
+ ldr r1, [r1, #TI_TP_VALUE]
+ mcr p15, 0, r1, c13, c0, 3 @ set TLS register
+#endif
+
uaccess_enable r1, isb=0
#ifndef CONFIG_THUMB2_KERNEL
@ ARM mode restore
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
index 29b2eda136bb..da18e0a17dc2 100644
--- a/arch/arm/kernel/head-common.S
+++ b/arch/arm/kernel/head-common.S
@@ -105,6 +105,11 @@ __mmap_switched:
mov r1, #0
bl __memset @ clear .bss
+#ifdef CONFIG_CURRENT_POINTER_IN_TPIDRURO
+ adr_l r0, init_task @ get swapper task_struct
+ set_current r0
+#endif
+
ldmia r4, {r0, r1, r2, r3}
str r9, [r0] @ Save processor ID
str r7, [r1] @ Save machine type
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index 0fc814bbc34b..fadfee9e2b45 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -115,6 +115,7 @@ ENTRY(secondary_startup)
ret r12
1: bl __after_proc_init
ldr sp, [r7, #12] @ set up the stack pointer
+ ldr r0, [r7, #16] @ set up task pointer
mov fp, #0
b secondary_start_kernel
ENDPROC(secondary_startup)
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 3fc7f9750ce4..c04dd94630c7 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -424,8 +424,9 @@ ENDPROC(secondary_startup)
ENDPROC(secondary_startup_arm)
ENTRY(__secondary_switched)
- ldr_l r7, secondary_data + 12 @ get secondary_data.stack
- mov sp, r7
+ adr_l r7, secondary_data + 12 @ get secondary_data.stack
+ ldr sp, [r7]
+ ldr r0, [r7, #4] @ get secondary_data.task
mov fp, #0
b secondary_start_kernel
ENDPROC(__secondary_switched)
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 96f577e59595..d47159f3791c 100644
--- a/arch/arm/kernel/process.c
+++ b/