Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6ec7026a authored by Max Filippov's avatar Max Filippov Committed by Chris Zankel
Browse files

xtensa: use context structure for debug exceptions



With implementation of data breakpoints debug exceptions raised when
PS.EXCM is set need to be handled, e.g. window overflow code can write
to watched userspace address. Currently debug exception handler uses
EXCSAVE and DEPC SRs to save temporary registers, but DEPC may not be
available when PS.EXCM is set and more space will be needed to save
additional state.
Reorganize debug context: create per-CPU structure debug_table instance
and store its address in the EXCSAVE<debug level> instead of
debug_exception function address. Expand this structure when more save
space is needed.

Signed-off-by: default avatarMax Filippov <jcmvbkbc@gmail.com>
parent 816aa588
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -65,4 +65,13 @@ static inline void spill_registers(void)
#endif
}

struct debug_table {
	/* Pointer to debug exception handler */
	void (*debug_exception)(void);
	/* Temporary register save area */
	unsigned long debug_save[1];
};

void debug_exception(void);

#endif /* _XTENSA_TRAPS_H */
+6 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <linux/kbuild.h>

#include <asm/ptrace.h>
#include <asm/traps.h>
#include <asm/uaccess.h>

int main(void)
@@ -117,5 +118,10 @@ int main(void)
	DEFINE(_CLONE_UNTRACED, CLONE_UNTRACED);
	DEFINE(PG_ARCH_1, PG_arch_1);

	/* struct debug_table */
	DEFINE(DT_DEBUG_EXCEPTION,
	       offsetof(struct debug_table, debug_exception));
	DEFINE(DT_DEBUG_SAVE, offsetof(struct debug_table, debug_save));

	return 0;
}
+8 −12
Original line number Diff line number Diff line
@@ -789,36 +789,32 @@ ENTRY(debug_exception)

	movi	a2, 1 << PS_EXCM_BIT
	or	a2, a0, a2
	movi	a0, debug_exception	# restore a3, debug jump vector
	wsr	a2, ps
	xsr	a0, SREG_EXCSAVE + XCHAL_DEBUGLEVEL

	/* Switch to kernel/user stack, restore jump vector, and save a0 */

	bbsi.l	a2, PS_UM_BIT, 2f	# jump if user mode

	addi	a2, a1, -16-PT_SIZE	# assume kernel stack
3:
	l32i	a0, a3, DT_DEBUG_SAVE
	s32i	a1, a2, PT_AREG1
	s32i	a0, a2, PT_AREG0
	movi	a0, 0
	s32i	a1, a2, PT_AREG1
	s32i	a0, a2, PT_DEPC		# mark it as a regular exception
	xsr	a3, SREG_EXCSAVE + XCHAL_DEBUGLEVEL
	xsr	a0, depc
	s32i	a3, a2, PT_AREG3
	s32i	a0, a2, PT_AREG2
	mov	a1, a2

	rsr	a2, ps
	bbsi.l	a2, PS_UM_BIT, _user_exception
	j	_kernel_exception

2:	rsr	a2, excsave1
	l32i	a2, a2, EXC_TABLE_KSTK	# load kernel stack pointer
	s32i	a0, a2, PT_AREG0
	movi	a0, 0
	s32i	a1, a2, PT_AREG1
	s32i	a0, a2, PT_DEPC
	xsr	a0, depc
	s32i	a3, a2, PT_AREG3
	s32i	a0, a2, PT_AREG2
	mov	a1, a2
	j	_user_exception
	j	3b

	/* Debug exception while in exception mode. */
1:	j	1b	// FIXME!!
+0 −5
Original line number Diff line number Diff line
@@ -197,11 +197,6 @@ ENTRY(_startup)
	wsr	a2, ps			# (enable reg-windows; progmode stack)
	rsync

	/* Set up EXCSAVE[DEBUGLEVEL] to point to the Debug Exception Handler.*/

	movi	a2, debug_exception
	wsr	a2, SREG_EXCSAVE + XCHAL_DEBUGLEVEL

#ifdef CONFIG_SMP
	/*
	 * Notice that we assume with SMP that cores have PRID
+13 −0
Original line number Diff line number Diff line
@@ -157,6 +157,8 @@ COPROCESSOR(7),

DEFINE_PER_CPU(unsigned long, exc_table[EXC_TABLE_SIZE/4]);

DEFINE_PER_CPU(struct debug_table, debug_table);

void die(const char*, struct pt_regs*, long);

static inline void
@@ -372,6 +374,15 @@ static void trap_init_excsave(void)
	__asm__ __volatile__("wsr  %0, excsave1\n" : : "a" (excsave1));
}

static void trap_init_debug(void)
{
	unsigned long debugsave = (unsigned long)this_cpu_ptr(&debug_table);

	this_cpu_ptr(&debug_table)->debug_exception = debug_exception;
	__asm__ __volatile__("wsr %0, excsave" __stringify(XCHAL_DEBUGLEVEL)
			     :: "a"(debugsave));
}

/*
 * Initialize dispatch tables.
 *
@@ -415,12 +426,14 @@ void __init trap_init(void)

	/* Initialize EXCSAVE_1 to hold the address of the exception table. */
	trap_init_excsave();
	trap_init_debug();
}

#ifdef CONFIG_SMP
void secondary_trap_init(void)
{
	trap_init_excsave();
	trap_init_debug();
}
#endif

Loading