Commit 2e21d853 authored by Will Deacon's avatar Will Deacon
Browse files

Merge branch 'for-next/stacktrace' into for-next/kasan

Merge in stack unwinding work to cater for 8-byte aligned stack frames
which may be generated following optimisations to CONFIG_KASAN_OUTLINE.

* for-next/stacktrace:
  arm64: stacktrace: Relax frame record alignment requirement to 8 bytes
  arm64: Change the on_*stack functions to take a size argument
  arm64: Implement stack trace termination record
parents c4681547 33c222ae
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -332,10 +332,10 @@ long get_tagged_addr_ctrl(struct task_struct *task);
#define current_top_of_stack()								\
({											\
	struct stack_info _info;							\
	BUG_ON(!on_accessible_stack(current, current_stack_pointer, &_info));	\
	BUG_ON(!on_accessible_stack(current, current_stack_pointer, 1, &_info));	\
	_info.high;									\
})
#define on_thread_stack()	(on_task_stack(current, current_stack_pointer, NULL))
#define on_thread_stack()	(on_task_stack(current, current_stack_pointer, 1, NULL))

#endif /* __ASSEMBLY__ */
#endif /* __ASM_PROCESSOR_H */
+4 −3
Original line number Diff line number Diff line
@@ -42,8 +42,9 @@ unsigned long sdei_arch_get_entry_point(int conduit);

struct stack_info;

bool _on_sdei_stack(unsigned long sp, struct stack_info *info);
static inline bool on_sdei_stack(unsigned long sp,
bool _on_sdei_stack(unsigned long sp, unsigned long size,
		    struct stack_info *info);
static inline bool on_sdei_stack(unsigned long sp, unsigned long size,
				struct stack_info *info)
{
	if (!IS_ENABLED(CONFIG_VMAP_STACK))
@@ -51,7 +52,7 @@ static inline bool on_sdei_stack(unsigned long sp,
	if (!IS_ENABLED(CONFIG_ARM_SDE_INTERFACE))
		return false;
	if (in_nmi())
		return _on_sdei_stack(sp, info);
		return _on_sdei_stack(sp, size, info);

	return false;
}
+16 −16
Original line number Diff line number Diff line
@@ -69,14 +69,14 @@ extern void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk,

DECLARE_PER_CPU(unsigned long *, irq_stack_ptr);

static inline bool on_stack(unsigned long sp, unsigned long low,
				unsigned long high, enum stack_type type,
				struct stack_info *info)
static inline bool on_stack(unsigned long sp, unsigned long size,
			    unsigned long low, unsigned long high,
			    enum stack_type type, struct stack_info *info)
{
	if (!low)
		return false;

	if (sp < low || sp >= high)
	if (sp < low || sp + size < sp || sp + size > high)
		return false;

	if (info) {
@@ -87,38 +87,38 @@ static inline bool on_stack(unsigned long sp, unsigned long low,
	return true;
}

static inline bool on_irq_stack(unsigned long sp,
static inline bool on_irq_stack(unsigned long sp, unsigned long size,
				struct stack_info *info)
{
	unsigned long low = (unsigned long)raw_cpu_read(irq_stack_ptr);
	unsigned long high = low + IRQ_STACK_SIZE;

	return on_stack(sp, low, high, STACK_TYPE_IRQ, info);
	return on_stack(sp, size, low, high, STACK_TYPE_IRQ, info);
}

static inline bool on_task_stack(const struct task_struct *tsk,
				 unsigned long sp,
				 unsigned long sp, unsigned long size,
				 struct stack_info *info)
{
	unsigned long low = (unsigned long)task_stack_page(tsk);
	unsigned long high = low + THREAD_SIZE;

	return on_stack(sp, low, high, STACK_TYPE_TASK, info);
	return on_stack(sp, size, low, high, STACK_TYPE_TASK, info);
}

#ifdef CONFIG_VMAP_STACK
DECLARE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)], overflow_stack);

static inline bool on_overflow_stack(unsigned long sp,
static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
				struct stack_info *info)
{
	unsigned long low = (unsigned long)raw_cpu_ptr(overflow_stack);
	unsigned long high = low + OVERFLOW_STACK_SIZE;

	return on_stack(sp, low, high, STACK_TYPE_OVERFLOW, info);
	return on_stack(sp, size, low, high, STACK_TYPE_OVERFLOW, info);
}
#else
static inline bool on_overflow_stack(unsigned long sp,
static inline bool on_overflow_stack(unsigned long sp, unsigned long size,
			struct stack_info *info) { return false; }
#endif

@@ -128,21 +128,21 @@ static inline bool on_overflow_stack(unsigned long sp,
 * context.
 */
static inline bool on_accessible_stack(const struct task_struct *tsk,
				       unsigned long sp,
				       unsigned long sp, unsigned long size,
				       struct stack_info *info)
{
	if (info)
		info->type = STACK_TYPE_UNKNOWN;

	if (on_task_stack(tsk, sp, info))
	if (on_task_stack(tsk, sp, size, info))
		return true;
	if (tsk != current || preemptible())
		return false;
	if (on_irq_stack(sp, info))
	if (on_irq_stack(sp, size, info))
		return true;
	if (on_overflow_stack(sp, info))
	if (on_overflow_stack(sp, size, info))
		return true;
	if (on_sdei_stack(sp, info))
	if (on_sdei_stack(sp, size, info))
		return true;

	return false;
+1 −1
Original line number Diff line number Diff line
@@ -285,7 +285,7 @@ alternative_else_nop_endif
	stp	lr, x21, [sp, #S_LR]

	/*
	 * For exceptions from EL0, create a terminal frame record.
	 * For exceptions from EL0, create a final frame record.
	 * For exceptions from EL1, create a synthetic frame record so the
	 * interrupted code shows up in the backtrace.
	 */
+19 −6
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include <asm/asm_pointer_auth.h>
#include <asm/assembler.h>
#include <asm/boot.h>
#include <asm/bug.h>
#include <asm/ptrace.h>
#include <asm/asm-offsets.h>
#include <asm/cache.h>
@@ -393,6 +394,18 @@ SYM_FUNC_START_LOCAL(__create_page_tables)
	ret	x28
SYM_FUNC_END(__create_page_tables)

	/*
	 * Create a final frame record at task_pt_regs(current)->stackframe, so
	 * that the unwinder can identify the final frame record of any task by
	 * its location in the task stack. We reserve the entire pt_regs space
	 * for consistency with user tasks and kthreads.
	 */
	.macro setup_final_frame
	sub	sp, sp, #PT_REGS_SIZE
	stp	xzr, xzr, [sp, #S_STACKFRAME]
	add	x29, sp, #S_STACKFRAME
	.endm

/*
 * The following fragment of code is executed with the MMU enabled.
 *
@@ -447,9 +460,9 @@ SYM_FUNC_START_LOCAL(__primary_switched)
#endif
	bl	switch_to_vhe			// Prefer VHE if possible
	add	sp, sp, #16
	mov	x29, #0
	mov	x30, #0
	b	start_kernel
	setup_final_frame
	bl	start_kernel
	ASM_BUG()
SYM_FUNC_END(__primary_switched)

	.pushsection ".rodata", "a"
@@ -639,14 +652,14 @@ SYM_FUNC_START_LOCAL(__secondary_switched)
	cbz	x2, __secondary_too_slow
	msr	sp_el0, x2
	scs_load x2, x3
	mov	x29, #0
	mov	x30, #0
	setup_final_frame

#ifdef CONFIG_ARM64_PTR_AUTH
	ptrauth_keys_init_cpu x2, x3, x4, x5
#endif

	b	secondary_start_kernel
	bl	secondary_start_kernel
	ASM_BUG()
SYM_FUNC_END(__secondary_switched)

SYM_FUNC_START_LOCAL(__secondary_too_slow)
Loading