aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
authorTiejun Chen <tiejun.chen@windriver.com>2012-08-22 12:10:20 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-08-24 06:26:06 -0400
commit5f630401f9e98bd062733b5bbef096dbf2158066 (patch)
tree4d4d1d6fe382982119028473a14f9021d931684b /arch/powerpc/kernel
parent949616cf2d3095d1bb6b3d155c1cc963abd98b5c (diff)
powerpc/kgdb: Restore current_thread_info properly
For powerpc BooKE and e200, singlestep is handled on the critical/dbg exception stack. This causes current_thread_info() to fail for kgdb internal, so previously We work around this issue by copying the thread_info from the kernel stack before calling kgdb_handle_exception, and copying it back afterwards. But actually we don't do this properly. We should backup current_thread_info then restore that when exit. Signed-off-by: Tiejun Chen <tiejun.chen@windriver.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/kgdb.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c
index 05adb69febf..c470a40b29f 100644
--- a/arch/powerpc/kernel/kgdb.c
+++ b/arch/powerpc/kernel/kgdb.c
@@ -25,6 +25,7 @@
25#include <asm/processor.h> 25#include <asm/processor.h>
26#include <asm/machdep.h> 26#include <asm/machdep.h>
27#include <asm/debug.h> 27#include <asm/debug.h>
28#include <linux/slab.h>
28 29
29/* 30/*
30 * This table contains the mapping between PowerPC hardware trap types, and 31 * This table contains the mapping between PowerPC hardware trap types, and
@@ -153,6 +154,8 @@ static int kgdb_handle_breakpoint(struct pt_regs *regs)
153static int kgdb_singlestep(struct pt_regs *regs) 154static int kgdb_singlestep(struct pt_regs *regs)
154{ 155{
155 struct thread_info *thread_info, *exception_thread_info; 156 struct thread_info *thread_info, *exception_thread_info;
157 struct thread_info *backup_current_thread_info = \
158 (struct thread_info *)kmalloc(sizeof(struct thread_info), GFP_KERNEL);
156 159
157 if (user_mode(regs)) 160 if (user_mode(regs))
158 return 0; 161 return 0;
@@ -170,13 +173,17 @@ static int kgdb_singlestep(struct pt_regs *regs)
170 thread_info = (struct thread_info *)(regs->gpr[1] & ~(THREAD_SIZE-1)); 173 thread_info = (struct thread_info *)(regs->gpr[1] & ~(THREAD_SIZE-1));
171 exception_thread_info = current_thread_info(); 174 exception_thread_info = current_thread_info();
172 175
173 if (thread_info != exception_thread_info) 176 if (thread_info != exception_thread_info) {
177 /* Save the original current_thread_info. */
178 memcpy(backup_current_thread_info, exception_thread_info, sizeof *thread_info);
174 memcpy(exception_thread_info, thread_info, sizeof *thread_info); 179 memcpy(exception_thread_info, thread_info, sizeof *thread_info);
180 }
175 181
176 kgdb_handle_exception(0, SIGTRAP, 0, regs); 182 kgdb_handle_exception(0, SIGTRAP, 0, regs);
177 183
178 if (thread_info != exception_thread_info) 184 if (thread_info != exception_thread_info)
179 memcpy(thread_info, exception_thread_info, sizeof *thread_info); 185 /* Restore current_thread_info lastly. */
186 memcpy(exception_thread_info, backup_current_thread_info, sizeof *thread_info);
180 187
181 return 1; 188 return 1;
182} 189}