Commit 9cf72c35 authored by Russell King (Oracle)'s avatar Russell King (Oracle)
Browse files

Merge tag 'arm-irq-and-vmap-stacks-for-rmk' of...

Merge tag 'arm-irq-and-vmap-stacks-for-rmk' of git://git.kernel.org/pub/scm/linux/kernel/git/ardb/linux into devel-stable

ARM: support for IRQ and vmap'ed stacks

This PR covers all the work related to implementing IRQ stacks and
vmap'ed stacks for all 32-bit ARM systems that are currently supported
by the Linux kernel, including RiscPC and Footbridge. It has been
submitted for review in three different waves:
- IRQ stacks support for v7 SMP systems [0],
- vmap'ed stacks support for v7 SMP systems[1],
- extending support for both IRQ stacks and vmap'ed stacks for all
  remaining configurations, including v6/v7 SMP multiplatform kernels
  and uniprocessor configurations including v7-M [2]

[0] https://lore.kernel.org/linux-arm-kernel/20211115084732.3704393-1-ardb@kernel.org/
[1] https://lore.kernel.org/linux-arm-kernel/20211122092816.2865873-1-ardb@kernel.org/
[2] https://lore.kernel.org/linux-arm-kernel/20211206164659.1495084-1-ardb@kernel.org/
parents fa55b7dc cafc0eab
Loading
Loading
Loading
Loading
+15 −16
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ config ARM
	select GENERIC_CPU_AUTOPROBE
	select GENERIC_EARLY_IOREMAP
	select GENERIC_IDLE_POLL_SETUP
	select GENERIC_IRQ_MULTI_HANDLER if MMU
	select GENERIC_IRQ_PROBE
	select GENERIC_IRQ_SHOW
	select GENERIC_IRQ_SHOW_LEVEL
@@ -126,7 +127,8 @@ 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 THREAD_INFO_IN_TASK
	select HAVE_ARCH_VMAP_STACK if MMU && (!LD_IS_LLD || LLD_VERSION >= 140000)
	select TRACE_IRQFLAGS_SUPPORT if !CPU_V7M
	# Above selects are sorted alphabetically; please add new ones
	# according to that.  Thanks.
@@ -226,9 +228,6 @@ config GENERIC_ISA_DMA
config FIQ
	bool

config NEED_RET_TO_USER
	bool

config ARCH_MTD_XIP
	bool

@@ -322,7 +321,6 @@ config ARCH_MULTIPLATFORM
	select AUTO_ZRELADDR
	select TIMER_OF
	select COMMON_CLK
	select GENERIC_IRQ_MULTI_HANDLER
	select HAVE_PCI
	select PCI_DOMAINS_GENERIC if PCI
	select SPARSE_IRQ
@@ -346,7 +344,6 @@ config ARCH_EP93XX
	select ARM_AMBA
	imply ARM_PATCH_PHYS_VIRT
	select ARM_VIC
	select GENERIC_IRQ_MULTI_HANDLER
	select AUTO_ZRELADDR
	select CLKSRC_MMIO
	select CPU_ARM920T
@@ -371,7 +368,6 @@ config ARCH_IOP32X
	select CPU_XSCALE
	select GPIO_IOP
	select GPIOLIB
	select NEED_RET_TO_USER
	select FORCE_PCI
	select PLAT_IOP
	help
@@ -385,7 +381,6 @@ config ARCH_IXP4XX
	select ARCH_SUPPORTS_BIG_ENDIAN
	select CPU_XSCALE
	select DMABOUNCE if PCI
	select GENERIC_IRQ_MULTI_HANDLER
	select GPIO_IXP4XX
	select GPIOLIB
	select HAVE_PCI
@@ -401,7 +396,6 @@ config ARCH_IXP4XX
config ARCH_DOVE
	bool "Marvell Dove"
	select CPU_PJ4
	select GENERIC_IRQ_MULTI_HANDLER
	select GPIOLIB
	select HAVE_PCI
	select MVEBU_MBUS
@@ -424,7 +418,6 @@ config ARCH_PXA
	select CLKSRC_MMIO
	select TIMER_OF
	select CPU_XSCALE if !CPU_XSC3
	select GENERIC_IRQ_MULTI_HANDLER
	select GPIO_PXA
	select GPIOLIB
	select IRQ_DOMAIN
@@ -463,7 +456,6 @@ config ARCH_SA1100
	select COMMON_CLK
	select CPU_FREQ
	select CPU_SA1100
	select GENERIC_IRQ_MULTI_HANDLER
	select GPIOLIB
	select IRQ_DOMAIN
	select ISA
@@ -478,7 +470,6 @@ config ARCH_S3C24XX
	select CLKSRC_SAMSUNG_PWM
	select GPIO_SAMSUNG
	select GPIOLIB
	select GENERIC_IRQ_MULTI_HANDLER
	select HAVE_S3C2410_I2C if I2C
	select NEED_MACH_IO_H
	select S3C2410_WATCHDOG
@@ -497,7 +488,6 @@ config ARCH_OMAP1
	select ARCH_OMAP
	select CLKSRC_MMIO
	select GENERIC_IRQ_CHIP
	select GENERIC_IRQ_MULTI_HANDLER
	select GPIOLIB
	select HAVE_LEGACY_CLK
	select IRQ_DOMAIN
@@ -1164,7 +1154,12 @@ config SMP_ON_UP

config CURRENT_POINTER_IN_TPIDRURO
	def_bool y
	depends on SMP && CPU_32v6K && !CPU_V6
	depends on CPU_32v6K && !CPU_V6

config IRQSTACKS
	def_bool y
	select HAVE_IRQ_EXIT_ON_IRQ_STACK
	select HAVE_SOFTIRQ_ON_OWN_STACK

config ARM_CPU_TOPOLOGY
	bool "Support cpu topology definition"
@@ -1607,10 +1602,14 @@ config XEN
	help
	  Say Y if you want to run Linux in a Virtual Machine on Xen on ARM.

config CC_HAVE_STACKPROTECTOR_TLS
	def_bool $(cc-option,-mtp=cp15 -mstack-protector-guard=tls -mstack-protector-guard-offset=0)

config STACKPROTECTOR_PER_TASK
	bool "Use a unique stack canary value for each task"
	depends on GCC_PLUGINS && STACKPROTECTOR && THREAD_INFO_IN_TASK && !XIP_DEFLATED_DATA
	select GCC_PLUGIN_ARM_SSP_PER_TASK
	depends on STACKPROTECTOR && CURRENT_POINTER_IN_TPIDRURO && !XIP_DEFLATED_DATA
	depends on GCC_PLUGINS || CC_HAVE_STACKPROTECTOR_TLS
	select GCC_PLUGIN_ARM_SSP_PER_TASK if !CC_HAVE_STACKPROTECTOR_TLS
	default y
	help
	  Due to the fact that GCC uses an ordinary symbol reference from
+9 −0
Original line number Diff line number Diff line
@@ -275,6 +275,14 @@ endif

ifeq ($(CONFIG_STACKPROTECTOR_PER_TASK),y)
prepare: stack_protector_prepare
ifeq ($(CONFIG_CC_HAVE_STACKPROTECTOR_TLS),y)
stack_protector_prepare: prepare0
	$(eval KBUILD_CFLAGS += \
		-mstack-protector-guard=tls \
		-mstack-protector-guard-offset=$(shell	\
			awk '{if ($$2 == "TSK_STACK_CANARY") print $$3;}'\
				include/generated/asm-offsets.h))
else
stack_protector_prepare: prepare0
	$(eval SSP_PLUGIN_CFLAGS := \
		-fplugin-arg-arm_ssp_per_task_plugin-offset=$(shell	\
@@ -283,6 +291,7 @@ stack_protector_prepare: prepare0
	$(eval KBUILD_CFLAGS += $(SSP_PLUGIN_CFLAGS))
	$(eval GCC_PLUGINS_CFLAGS += $(SSP_PLUGIN_CFLAGS))
endif
endif

all:	$(notdir $(KBUILD_IMAGE))

+1 −5
Original line number Diff line number Diff line
@@ -93,11 +93,6 @@ ifeq ($(CONFIG_USE_OF),y)
OBJS	+= $(libfdt_objs) fdt_check_mem_start.o
endif

# -fstack-protector-strong triggers protection checks in this code,
# but it is being used too early to link to meaningful stack_chk logic.
$(foreach o, $(libfdt_objs) atags_to_fdt.o fdt_check_mem_start.o, \
	$(eval CFLAGS_$(o) := -I $(srctree)/scripts/dtc/libfdt -fno-stack-protector))

targets       := vmlinux vmlinux.lds piggy_data piggy.o \
		 lib1funcs.o ashldi3.o bswapsdi2.o \
		 head.o $(OBJS)
@@ -107,6 +102,7 @@ clean-files += lib1funcs.S ashldi3.S bswapsdi2.S hyp-stub.S
KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING

ccflags-y := -fpic $(call cc-option,-mno-single-pic-base,) -fno-builtin \
	     -I$(srctree)/scripts/dtc/libfdt -fno-stack-protector \
	     -I$(obj) $(DISABLE_ARM_SSP_PER_TASK_PLUGIN)
ccflags-remove-$(CONFIG_FUNCTION_TRACER) += -pg
asflags-y := -DZIMAGE
+0 −7
Original line number Diff line number Diff line
@@ -128,13 +128,6 @@ asmlinkage void __div0(void)
	error("Attempting division by 0!");
}

const unsigned long __stack_chk_guard = 0x000a0dff;

void __stack_chk_fail(void)
{
	error("stack-protector: Kernel stack is corrupted\n");
}

extern int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x));


+169 −35
Original line number Diff line number Diff line
@@ -86,6 +86,10 @@

#define IMM12_MASK 0xfff

/* the frame pointer used for stack unwinding */
ARM(	fpreg	.req	r11	)
THUMB(	fpreg	.req	r7	)

/*
 * Enable and disable interrupts
 */
@@ -199,43 +203,12 @@
	.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

/*
@@ -308,6 +281,80 @@
#define ALT_UP_B(label) b label
#endif

	/*
	 * this_cpu_offset - load the per-CPU offset of this CPU into
	 * 		     register 'rd'
	 */
	.macro		this_cpu_offset, rd:req
#ifdef CONFIG_SMP
ALT_SMP(mrc		p15, 0, \rd, c13, c0, 4)
#ifdef CONFIG_CPU_V6
ALT_UP_B(.L1_\@)
.L0_\@:
	.subsection	1
.L1_\@: ldr_va		\rd, __per_cpu_offset
	b		.L0_\@
	.previous
#endif
#else
	mov		\rd, #0
#endif
	.endm

	/*
	 * set_current - store the task pointer of this CPU's current task
	 */
	.macro		set_current, rn:req, tmp:req
#if defined(CONFIG_CURRENT_POINTER_IN_TPIDRURO) || defined(CONFIG_SMP)
9998:	mcr		p15, 0, \rn, c13, c0, 3		@ set TPIDRURO register
#ifdef CONFIG_CPU_V6
ALT_UP_B(.L0_\@)
	.subsection	1
.L0_\@: str_va		\rn, __current, \tmp
	b		.L1_\@
	.previous
.L1_\@:
#endif
#else
	str_va		\rn, __current, \tmp
#endif
	.endm

	/*
	 * get_current - load the task pointer of this CPU's current task
	 */
	.macro		get_current, rd:req
#if defined(CONFIG_CURRENT_POINTER_IN_TPIDRURO) || defined(CONFIG_SMP)
9998:	mrc		p15, 0, \rd, c13, c0, 3		@ get TPIDRURO register
#ifdef CONFIG_CPU_V6
ALT_UP_B(.L0_\@)
	.subsection	1
.L0_\@: ldr_va		\rd, __current
	b		.L1_\@
	.previous
.L1_\@:
#endif
#else
	ldr_va		\rd, __current
#endif
	.endm

	/*
	 * reload_current - reload the task pointer of this CPU's current task
	 *		    into the TLS register
	 */
	.macro		reload_current, t1:req, t2:req
#if defined(CONFIG_CURRENT_POINTER_IN_TPIDRURO) || defined(CONFIG_SMP)
#ifdef CONFIG_CPU_V6
ALT_SMP(nop)
ALT_UP_B(.L0_\@)
#endif
	ldr_this_cpu	\t1, __entry_task, \t1, \t2
	mcr		p15, 0, \t1, c13, c0, 3		@ store in TPIDRURO
.L0_\@:
#endif
	.endm

/*
 * Instruction barrier
 */
@@ -564,12 +611,12 @@ THUMB( orr \reg , \reg , #PSR_T_BIT )
	/*
	 * mov_l - move a constant value or [relocated] address into a register
	 */
	.macro		mov_l, dst:req, imm:req
	.macro		mov_l, dst:req, imm:req, cond
	.if		__LINUX_ARM_ARCH__ < 7
	ldr		\dst, =\imm
	ldr\cond	\dst, =\imm
	.else
	movw		\dst, #:lower16:\imm
	movt		\dst, #:upper16:\imm
	movw\cond	\dst, #:lower16:\imm
	movt\cond	\dst, #:upper16:\imm
	.endif
	.endm

@@ -607,6 +654,78 @@ THUMB( orr \reg , \reg , #PSR_T_BIT )
	__adldst_l	str, \src, \sym, \tmp, \cond
	.endm

	.macro		__ldst_va, op, reg, tmp, sym, cond
#if __LINUX_ARM_ARCH__ >= 7 || \
    (defined(MODULE) && defined(CONFIG_ARM_MODULE_PLTS)) || \
    (defined(CONFIG_LD_IS_LLD) && CONFIG_LLD_VERSION < 140000)
	mov_l		\tmp, \sym, \cond
	\op\cond	\reg, [\tmp]
#else
	/*
	 * Avoid a literal load, by emitting a sequence of ADD/LDR instructions
	 * with the appropriate relocations. The combined sequence has a range
	 * of -/+ 256 MiB, which should be sufficient for the core kernel and
	 * for modules loaded into the module region.
	 */
	.globl		\sym
	.reloc		.L0_\@, R_ARM_ALU_PC_G0_NC, \sym
	.reloc		.L1_\@, R_ARM_ALU_PC_G1_NC, \sym
	.reloc		.L2_\@, R_ARM_LDR_PC_G2, \sym
.L0_\@: sub\cond	\tmp, pc, #8
.L1_\@: sub\cond	\tmp, \tmp, #4
.L2_\@: \op\cond	\reg, [\tmp, #0]
#endif
	.endm

	/*
	 * ldr_va - load a 32-bit word from the virtual address of \sym
	 */
	.macro		ldr_va, rd:req, sym:req, cond
	__ldst_va	ldr, \rd, \rd, \sym, \cond
	.endm

	/*
	 * str_va - store a 32-bit word to the virtual address of \sym
	 */
	.macro		str_va, rn:req, sym:req, tmp:req, cond
	__ldst_va	str, \rn, \tmp, \sym, \cond
	.endm

	/*
	 * ldr_this_cpu_armv6 - Load a 32-bit word from the per-CPU variable 'sym',
	 *			without using a temp register. Supported in ARM mode
	 *			only.
	 */
	.macro		ldr_this_cpu_armv6, rd:req, sym:req
	this_cpu_offset	\rd
	.globl		\sym
	.reloc		.L0_\@, R_ARM_ALU_PC_G0_NC, \sym
	.reloc		.L1_\@, R_ARM_ALU_PC_G1_NC, \sym
	.reloc		.L2_\@, R_ARM_LDR_PC_G2, \sym
	add		\rd, \rd, pc
.L0_\@: sub		\rd, \rd, #4
.L1_\@: sub		\rd, \rd, #0
.L2_\@: ldr		\rd, [\rd, #4]
	.endm

	/*
	 * ldr_this_cpu - Load a 32-bit word from the per-CPU variable 'sym'
	 *		  into register 'rd', which may be the stack pointer,
	 *		  using 't1' and 't2' as general temp registers. These
	 *		  are permitted to overlap with 'rd' if != sp
	 */
	.macro		ldr_this_cpu, rd:req, sym:req, t1:req, t2:req
#if __LINUX_ARM_ARCH__ >= 7 || \
    (defined(MODULE) && defined(CONFIG_ARM_MODULE_PLTS)) || \
    (defined(CONFIG_LD_IS_LLD) && CONFIG_LLD_VERSION < 140000)
	this_cpu_offset	\t1
	mov_l		\t2, \sym
	ldr		\rd, [\t1, \t2]
#else
	ldr_this_cpu_armv6 \rd, \sym
#endif
	.endm

	/*
	 * rev_l - byte-swap a 32-bit value
	 *
@@ -624,4 +743,19 @@ THUMB( orr \reg , \reg , #PSR_T_BIT )
	.endif
	.endm

	/*
	 * bl_r - branch and link to register
	 *
	 * @dst: target to branch to
	 * @c: conditional opcode suffix
	 */
	.macro		bl_r, dst:req, c
	.if		__LINUX_ARM_ARCH__ < 6
	mov\c		lr, pc
	mov\c		pc, \dst
	.else
	blx\c		\dst
	.endif
	.endm

#endif /* __ASM_ASSEMBLER_H__ */
Loading