diff options
author | Haavard Skinnemoen <hskinnemoen@atmel.com> | 2007-11-28 09:04:01 -0500 |
---|---|---|
committer | Haavard Skinnemoen <hskinnemoen@atmel.com> | 2007-12-07 08:54:46 -0500 |
commit | 2507bc1338e43eadfef5b604d2c47e4f8180718f (patch) | |
tree | 4bc3c14114ba96efb8e9e4f2c0925fb92b669a19 /include/asm-avr32/processor.h | |
parent | 8dfe8f29cd371affcc3c6b35658dc4bd95ee7b61 (diff) |
[AVR32] Follow the rules when dealing with the OCD system
The current debug trap handling code does a number of things that are
illegal according to the AVR32 Architecture manual. Most importantly,
it may try to schedule from Debug Mode, thus clearing the D bit, which
can lead to "undefined behaviour".
It seems like this works in most cases, but several people have
observed somewhat unstable behaviour when debugging programs,
including soft lockups. So there's definitely something which is not
right with the existing code.
The new code will never schedule from Debug mode, it will always exit
Debug mode with a "retd" instruction, and if something not running in
Debug mode needs to do something debug-related (like doing a single
step), it will enter debug mode through a "breakpoint" instruction.
The monitor code will then return directly to user space, bypassing
its own saved registers if necessary (since we don't actually care
about the trapped context, only the one that came before.)
This adds three instructions to the common exception handling code,
including one branch. It does not touch super-hot paths like the TLB
miss handler.
Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
Diffstat (limited to 'include/asm-avr32/processor.h')
-rw-r--r-- | include/asm-avr32/processor.h | 3 |
1 files changed, 3 insertions, 0 deletions
diff --git a/include/asm-avr32/processor.h b/include/asm-avr32/processor.h index 6a64833756a6..a52576b25afe 100644 --- a/include/asm-avr32/processor.h +++ b/include/asm-avr32/processor.h | |||
@@ -139,6 +139,9 @@ extern void show_regs_log_lvl(struct pt_regs *regs, const char *log_lvl); | |||
139 | extern void show_stack_log_lvl(struct task_struct *tsk, unsigned long sp, | 139 | extern void show_stack_log_lvl(struct task_struct *tsk, unsigned long sp, |
140 | struct pt_regs *regs, const char *log_lvl); | 140 | struct pt_regs *regs, const char *log_lvl); |
141 | 141 | ||
142 | #define task_pt_regs(p) \ | ||
143 | ((struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1) | ||
144 | |||
142 | #define KSTK_EIP(tsk) ((tsk)->thread.cpu_context.pc) | 145 | #define KSTK_EIP(tsk) ((tsk)->thread.cpu_context.pc) |
143 | #define KSTK_ESP(tsk) ((tsk)->thread.cpu_context.ksp) | 146 | #define KSTK_ESP(tsk) ((tsk)->thread.cpu_context.ksp) |
144 | 147 | ||