diff options
author | Paul Mundt <lethal@linux-sh.org> | 2012-04-10 01:00:30 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2012-04-10 01:00:30 -0400 |
commit | 10c5e4e137dc97e54cabd62a6109988ff8670faa (patch) | |
tree | 7c7a87cc5550fbc657d66b51733b1a33c459d35d /arch/sh | |
parent | fd03e81812a8fb6121773226a4e0c702926077ae (diff) |
sh: kgdb: Fill out sleeping_thread_to_gdb_regs() state.
Presently we're using a pretty dumbed-down implementation that copies
over register state visible from the thread info, leaving the bulk of the
switch_to state uncopied.
Given that we're also depending on register bank toggling for switch_to
optimization we ought to also explicitly zero out the GP regs that reside
in an alternate bank in order to prevent handing back garbage.
There are a few extra registers that we have state for in switch_to, so
copy those over while we're at it.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh')
-rw-r--r-- | arch/sh/kernel/kgdb.c | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/arch/sh/kernel/kgdb.c b/arch/sh/kernel/kgdb.c index d25b5ed68b24..ba8e76325d12 100644 --- a/arch/sh/kernel/kgdb.c +++ b/arch/sh/kernel/kgdb.c | |||
@@ -222,8 +222,31 @@ char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs) | |||
222 | 222 | ||
223 | void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) | 223 | void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) |
224 | { | 224 | { |
225 | struct pt_regs *thread_regs = task_pt_regs(p); | ||
226 | int reg; | ||
227 | |||
228 | /* Initialize to zero */ | ||
229 | for (reg = 0; reg < DBG_MAX_REG_NUM; reg++) | ||
230 | gdb_regs[reg] = 0; | ||
231 | |||
232 | /* | ||
233 | * Copy out GP regs 8 to 14. | ||
234 | * | ||
235 | * switch_to() relies on SR.RB toggling, so regs 0->7 are banked | ||
236 | * and need privileged instructions to get to. The r15 value we | ||
237 | * fetch from the thread info directly. | ||
238 | */ | ||
239 | for (reg = GDB_R8; reg < GDB_R15; reg++) | ||
240 | gdb_regs[reg] = thread_regs->regs[reg]; | ||
241 | |||
225 | gdb_regs[GDB_R15] = p->thread.sp; | 242 | gdb_regs[GDB_R15] = p->thread.sp; |
226 | gdb_regs[GDB_PC] = p->thread.pc; | 243 | gdb_regs[GDB_PC] = p->thread.pc; |
244 | |||
245 | /* | ||
246 | * Additional registers we have context for | ||
247 | */ | ||
248 | gdb_regs[GDB_PR] = thread_regs->pr; | ||
249 | gdb_regs[GDB_GBR] = thread_regs->gbr; | ||
227 | } | 250 | } |
228 | 251 | ||
229 | int kgdb_arch_handle_exception(int e_vector, int signo, int err_code, | 252 | int kgdb_arch_handle_exception(int e_vector, int signo, int err_code, |