diff options
| -rw-r--r-- | arch/xtensa/include/asm/traps.h | 9 | ||||
| -rw-r--r-- | arch/xtensa/kernel/asm-offsets.c | 6 | ||||
| -rw-r--r-- | arch/xtensa/kernel/entry.S | 20 | ||||
| -rw-r--r-- | arch/xtensa/kernel/head.S | 5 | ||||
| -rw-r--r-- | arch/xtensa/kernel/traps.c | 13 | ||||
| -rw-r--r-- | arch/xtensa/kernel/vectors.S | 4 |
6 files changed, 39 insertions, 18 deletions
diff --git a/arch/xtensa/include/asm/traps.h b/arch/xtensa/include/asm/traps.h index 28f33a8b7f5f..3ad151aee6af 100644 --- a/arch/xtensa/include/asm/traps.h +++ b/arch/xtensa/include/asm/traps.h | |||
| @@ -65,4 +65,13 @@ static inline void spill_registers(void) | |||
| 65 | #endif | 65 | #endif |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | struct debug_table { | ||
| 69 | /* Pointer to debug exception handler */ | ||
| 70 | void (*debug_exception)(void); | ||
| 71 | /* Temporary register save area */ | ||
| 72 | unsigned long debug_save[1]; | ||
| 73 | }; | ||
| 74 | |||
| 75 | void debug_exception(void); | ||
| 76 | |||
| 68 | #endif /* _XTENSA_TRAPS_H */ | 77 | #endif /* _XTENSA_TRAPS_H */ |
diff --git a/arch/xtensa/kernel/asm-offsets.c b/arch/xtensa/kernel/asm-offsets.c index b123ace3b67c..8fd46c6404ea 100644 --- a/arch/xtensa/kernel/asm-offsets.c +++ b/arch/xtensa/kernel/asm-offsets.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/kbuild.h> | 23 | #include <linux/kbuild.h> |
| 24 | 24 | ||
| 25 | #include <asm/ptrace.h> | 25 | #include <asm/ptrace.h> |
| 26 | #include <asm/traps.h> | ||
| 26 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
| 27 | 28 | ||
| 28 | int main(void) | 29 | int main(void) |
| @@ -117,5 +118,10 @@ int main(void) | |||
| 117 | DEFINE(_CLONE_UNTRACED, CLONE_UNTRACED); | 118 | DEFINE(_CLONE_UNTRACED, CLONE_UNTRACED); |
| 118 | DEFINE(PG_ARCH_1, PG_arch_1); | 119 | DEFINE(PG_ARCH_1, PG_arch_1); |
| 119 | 120 | ||
| 121 | /* struct debug_table */ | ||
| 122 | DEFINE(DT_DEBUG_EXCEPTION, | ||
| 123 | offsetof(struct debug_table, debug_exception)); | ||
| 124 | DEFINE(DT_DEBUG_SAVE, offsetof(struct debug_table, debug_save)); | ||
| 125 | |||
| 120 | return 0; | 126 | return 0; |
| 121 | } | 127 | } |
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index db5c1765b413..ab7904fd027f 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S | |||
| @@ -789,36 +789,32 @@ ENTRY(debug_exception) | |||
| 789 | 789 | ||
| 790 | movi a2, 1 << PS_EXCM_BIT | 790 | movi a2, 1 << PS_EXCM_BIT |
| 791 | or a2, a0, a2 | 791 | or a2, a0, a2 |
| 792 | movi a0, debug_exception # restore a3, debug jump vector | ||
| 793 | wsr a2, ps | 792 | wsr a2, ps |
| 794 | xsr a0, SREG_EXCSAVE + XCHAL_DEBUGLEVEL | ||
| 795 | 793 | ||
| 796 | /* Switch to kernel/user stack, restore jump vector, and save a0 */ | 794 | /* Switch to kernel/user stack, restore jump vector, and save a0 */ |
| 797 | 795 | ||
| 798 | bbsi.l a2, PS_UM_BIT, 2f # jump if user mode | 796 | bbsi.l a2, PS_UM_BIT, 2f # jump if user mode |
| 799 | 797 | ||
| 800 | addi a2, a1, -16-PT_SIZE # assume kernel stack | 798 | addi a2, a1, -16-PT_SIZE # assume kernel stack |
| 799 | 3: | ||
| 800 | l32i a0, a3, DT_DEBUG_SAVE | ||
| 801 | s32i a1, a2, PT_AREG1 | ||
| 801 | s32i a0, a2, PT_AREG0 | 802 | s32i a0, a2, PT_AREG0 |
| 802 | movi a0, 0 | 803 | movi a0, 0 |
| 803 | s32i a1, a2, PT_AREG1 | ||
| 804 | s32i a0, a2, PT_DEPC # mark it as a regular exception | 804 | s32i a0, a2, PT_DEPC # mark it as a regular exception |
| 805 | xsr a3, SREG_EXCSAVE + XCHAL_DEBUGLEVEL | ||
| 805 | xsr a0, depc | 806 | xsr a0, depc |
| 806 | s32i a3, a2, PT_AREG3 | 807 | s32i a3, a2, PT_AREG3 |
| 807 | s32i a0, a2, PT_AREG2 | 808 | s32i a0, a2, PT_AREG2 |
| 808 | mov a1, a2 | 809 | mov a1, a2 |
| 810 | |||
| 811 | rsr a2, ps | ||
| 812 | bbsi.l a2, PS_UM_BIT, _user_exception | ||
| 809 | j _kernel_exception | 813 | j _kernel_exception |
| 810 | 814 | ||
| 811 | 2: rsr a2, excsave1 | 815 | 2: rsr a2, excsave1 |
| 812 | l32i a2, a2, EXC_TABLE_KSTK # load kernel stack pointer | 816 | l32i a2, a2, EXC_TABLE_KSTK # load kernel stack pointer |
| 813 | s32i a0, a2, PT_AREG0 | 817 | j 3b |
| 814 | movi a0, 0 | ||
| 815 | s32i a1, a2, PT_AREG1 | ||
| 816 | s32i a0, a2, PT_DEPC | ||
| 817 | xsr a0, depc | ||
| 818 | s32i a3, a2, PT_AREG3 | ||
| 819 | s32i a0, a2, PT_AREG2 | ||
| 820 | mov a1, a2 | ||
| 821 | j _user_exception | ||
| 822 | 818 | ||
| 823 | /* Debug exception while in exception mode. */ | 819 | /* Debug exception while in exception mode. */ |
| 824 | 1: j 1b // FIXME!! | 820 | 1: j 1b // FIXME!! |
diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S index 05e1df943856..bc4f4bf05099 100644 --- a/arch/xtensa/kernel/head.S +++ b/arch/xtensa/kernel/head.S | |||
| @@ -197,11 +197,6 @@ ENTRY(_startup) | |||
| 197 | wsr a2, ps # (enable reg-windows; progmode stack) | 197 | wsr a2, ps # (enable reg-windows; progmode stack) |
| 198 | rsync | 198 | rsync |
| 199 | 199 | ||
| 200 | /* Set up EXCSAVE[DEBUGLEVEL] to point to the Debug Exception Handler.*/ | ||
| 201 | |||
| 202 | movi a2, debug_exception | ||
| 203 | wsr a2, SREG_EXCSAVE + XCHAL_DEBUGLEVEL | ||
| 204 | |||
| 205 | #ifdef CONFIG_SMP | 200 | #ifdef CONFIG_SMP |
| 206 | /* | 201 | /* |
| 207 | * Notice that we assume with SMP that cores have PRID | 202 | * Notice that we assume with SMP that cores have PRID |
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c index a8b8dae4139a..e4764f216a7a 100644 --- a/arch/xtensa/kernel/traps.c +++ b/arch/xtensa/kernel/traps.c | |||
| @@ -157,6 +157,8 @@ COPROCESSOR(7), | |||
| 157 | 157 | ||
| 158 | DEFINE_PER_CPU(unsigned long, exc_table[EXC_TABLE_SIZE/4]); | 158 | DEFINE_PER_CPU(unsigned long, exc_table[EXC_TABLE_SIZE/4]); |
| 159 | 159 | ||
| 160 | DEFINE_PER_CPU(struct debug_table, debug_table); | ||
| 161 | |||
| 160 | void die(const char*, struct pt_regs*, long); | 162 | void die(const char*, struct pt_regs*, long); |
| 161 | 163 | ||
| 162 | static inline void | 164 | static inline void |
| @@ -372,6 +374,15 @@ static void trap_init_excsave(void) | |||
| 372 | __asm__ __volatile__("wsr %0, excsave1\n" : : "a" (excsave1)); | 374 | __asm__ __volatile__("wsr %0, excsave1\n" : : "a" (excsave1)); |
| 373 | } | 375 | } |
| 374 | 376 | ||
| 377 | static void trap_init_debug(void) | ||
| 378 | { | ||
| 379 | unsigned long debugsave = (unsigned long)this_cpu_ptr(&debug_table); | ||
| 380 | |||
| 381 | this_cpu_ptr(&debug_table)->debug_exception = debug_exception; | ||
| 382 | __asm__ __volatile__("wsr %0, excsave" __stringify(XCHAL_DEBUGLEVEL) | ||
| 383 | :: "a"(debugsave)); | ||
| 384 | } | ||
| 385 | |||
| 375 | /* | 386 | /* |
| 376 | * Initialize dispatch tables. | 387 | * Initialize dispatch tables. |
| 377 | * | 388 | * |
| @@ -415,12 +426,14 @@ void __init trap_init(void) | |||
| 415 | 426 | ||
| 416 | /* Initialize EXCSAVE_1 to hold the address of the exception table. */ | 427 | /* Initialize EXCSAVE_1 to hold the address of the exception table. */ |
| 417 | trap_init_excsave(); | 428 | trap_init_excsave(); |
| 429 | trap_init_debug(); | ||
| 418 | } | 430 | } |
| 419 | 431 | ||
| 420 | #ifdef CONFIG_SMP | 432 | #ifdef CONFIG_SMP |
| 421 | void secondary_trap_init(void) | 433 | void secondary_trap_init(void) |
| 422 | { | 434 | { |
| 423 | trap_init_excsave(); | 435 | trap_init_excsave(); |
| 436 | trap_init_debug(); | ||
| 424 | } | 437 | } |
| 425 | #endif | 438 | #endif |
| 426 | 439 | ||
diff --git a/arch/xtensa/kernel/vectors.S b/arch/xtensa/kernel/vectors.S index fc25318e75ad..332e9d635fb6 100644 --- a/arch/xtensa/kernel/vectors.S +++ b/arch/xtensa/kernel/vectors.S | |||
| @@ -601,7 +601,9 @@ ENDPROC(window_overflow_restore_a0_fixup) | |||
| 601 | 601 | ||
| 602 | ENTRY(_DebugInterruptVector) | 602 | ENTRY(_DebugInterruptVector) |
| 603 | 603 | ||
| 604 | xsr a0, SREG_EXCSAVE + XCHAL_DEBUGLEVEL | 604 | xsr a3, SREG_EXCSAVE + XCHAL_DEBUGLEVEL |
| 605 | s32i a0, a3, DT_DEBUG_SAVE | ||
| 606 | l32i a0, a3, DT_DEBUG_EXCEPTION | ||
| 605 | jx a0 | 607 | jx a0 |
| 606 | 608 | ||
| 607 | ENDPROC(_DebugInterruptVector) | 609 | ENDPROC(_DebugInterruptVector) |
