diff options
Diffstat (limited to 'arch/sparc64/kernel/process.c')
-rw-r--r-- | arch/sparc64/kernel/process.c | 110 |
1 files changed, 35 insertions, 75 deletions
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 8a9cd3e165b9..7f5debdc5fed 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c | |||
@@ -52,8 +52,6 @@ | |||
52 | #include <asm/irq_regs.h> | 52 | #include <asm/irq_regs.h> |
53 | #include <asm/smp.h> | 53 | #include <asm/smp.h> |
54 | 54 | ||
55 | /* #define VERBOSE_SHOWREGS */ | ||
56 | |||
57 | static void sparc64_yield(int cpu) | 55 | static void sparc64_yield(int cpu) |
58 | { | 56 | { |
59 | if (tlb_type != hypervisor) | 57 | if (tlb_type != hypervisor) |
@@ -213,22 +211,8 @@ static void show_regwindow(struct pt_regs *regs) | |||
213 | printk("I7: <%pS>\n", (void *) rwk->ins[7]); | 211 | printk("I7: <%pS>\n", (void *) rwk->ins[7]); |
214 | } | 212 | } |
215 | 213 | ||
216 | #ifdef CONFIG_SMP | 214 | void show_regs(struct pt_regs *regs) |
217 | static DEFINE_SPINLOCK(regdump_lock); | ||
218 | #endif | ||
219 | |||
220 | void __show_regs(struct pt_regs * regs) | ||
221 | { | 215 | { |
222 | #ifdef CONFIG_SMP | ||
223 | unsigned long flags; | ||
224 | |||
225 | /* Protect against xcall ipis which might lead to livelock on the lock */ | ||
226 | __asm__ __volatile__("rdpr %%pstate, %0\n\t" | ||
227 | "wrpr %0, %1, %%pstate" | ||
228 | : "=r" (flags) | ||
229 | : "i" (PSTATE_IE)); | ||
230 | spin_lock(®dump_lock); | ||
231 | #endif | ||
232 | printk("TSTATE: %016lx TPC: %016lx TNPC: %016lx Y: %08x %s\n", regs->tstate, | 216 | printk("TSTATE: %016lx TPC: %016lx TNPC: %016lx Y: %08x %s\n", regs->tstate, |
233 | regs->tpc, regs->tnpc, regs->y, print_tainted()); | 217 | regs->tpc, regs->tnpc, regs->y, print_tainted()); |
234 | printk("TPC: <%pS>\n", (void *) regs->tpc); | 218 | printk("TPC: <%pS>\n", (void *) regs->tpc); |
@@ -246,64 +230,24 @@ void __show_regs(struct pt_regs * regs) | |||
246 | regs->u_regs[15]); | 230 | regs->u_regs[15]); |
247 | printk("RPC: <%pS>\n", (void *) regs->u_regs[15]); | 231 | printk("RPC: <%pS>\n", (void *) regs->u_regs[15]); |
248 | show_regwindow(regs); | 232 | show_regwindow(regs); |
249 | #ifdef CONFIG_SMP | ||
250 | spin_unlock(®dump_lock); | ||
251 | __asm__ __volatile__("wrpr %0, 0, %%pstate" | ||
252 | : : "r" (flags)); | ||
253 | #endif | ||
254 | } | 233 | } |
255 | 234 | ||
256 | #ifdef VERBOSE_SHOWREGS | 235 | struct global_reg_snapshot global_reg_snapshot[NR_CPUS]; |
257 | static void idump_from_user (unsigned int *pc) | 236 | static DEFINE_SPINLOCK(global_reg_snapshot_lock); |
258 | { | ||
259 | int i; | ||
260 | int code; | ||
261 | |||
262 | if((((unsigned long) pc) & 3)) | ||
263 | return; | ||
264 | |||
265 | pc -= 3; | ||
266 | for(i = -3; i < 6; i++) { | ||
267 | get_user(code, pc); | ||
268 | printk("%c%08x%c",i?' ':'<',code,i?' ':'>'); | ||
269 | pc++; | ||
270 | } | ||
271 | printk("\n"); | ||
272 | } | ||
273 | #endif | ||
274 | 237 | ||
275 | void show_regs(struct pt_regs *regs) | 238 | static bool kstack_valid(struct thread_info *tp, struct reg_window *rw) |
276 | { | 239 | { |
277 | #ifdef VERBOSE_SHOWREGS | 240 | unsigned long thread_base, fp; |
278 | extern long etrap, etraptl1; | ||
279 | #endif | ||
280 | __show_regs(regs); | ||
281 | #if 0 | ||
282 | #ifdef CONFIG_SMP | ||
283 | { | ||
284 | extern void smp_report_regs(void); | ||
285 | 241 | ||
286 | smp_report_regs(); | 242 | thread_base = (unsigned long) tp; |
287 | } | 243 | fp = (unsigned long) rw; |
288 | #endif | ||
289 | #endif | ||
290 | 244 | ||
291 | #ifdef VERBOSE_SHOWREGS | 245 | if (fp < (thread_base + sizeof(struct thread_info)) || |
292 | if (regs->tpc >= &etrap && regs->tpc < &etraptl1 && | 246 | fp >= (thread_base + THREAD_SIZE)) |
293 | regs->u_regs[14] >= (long)current - PAGE_SIZE && | 247 | return false; |
294 | regs->u_regs[14] < (long)current + 6 * PAGE_SIZE) { | 248 | return true; |
295 | printk ("*********parent**********\n"); | ||
296 | __show_regs((struct pt_regs *)(regs->u_regs[14] + PTREGS_OFF)); | ||
297 | idump_from_user(((struct pt_regs *)(regs->u_regs[14] + PTREGS_OFF))->tpc); | ||
298 | printk ("*********endpar**********\n"); | ||
299 | } | ||
300 | #endif | ||
301 | } | 249 | } |
302 | 250 | ||
303 | #ifdef CONFIG_MAGIC_SYSRQ | ||
304 | struct global_reg_snapshot global_reg_snapshot[NR_CPUS]; | ||
305 | static DEFINE_SPINLOCK(global_reg_snapshot_lock); | ||
306 | |||
307 | static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs, | 251 | static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs, |
308 | int this_cpu) | 252 | int this_cpu) |
309 | { | 253 | { |
@@ -315,14 +259,22 @@ static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs, | |||
315 | global_reg_snapshot[this_cpu].o7 = regs->u_regs[UREG_I7]; | 259 | global_reg_snapshot[this_cpu].o7 = regs->u_regs[UREG_I7]; |
316 | 260 | ||
317 | if (regs->tstate & TSTATE_PRIV) { | 261 | if (regs->tstate & TSTATE_PRIV) { |
262 | struct thread_info *tp = current_thread_info(); | ||
318 | struct reg_window *rw; | 263 | struct reg_window *rw; |
319 | 264 | ||
320 | rw = (struct reg_window *) | 265 | rw = (struct reg_window *) |
321 | (regs->u_regs[UREG_FP] + STACK_BIAS); | 266 | (regs->u_regs[UREG_FP] + STACK_BIAS); |
322 | global_reg_snapshot[this_cpu].i7 = rw->ins[6]; | 267 | if (kstack_valid(tp, rw)) { |
323 | } else | 268 | global_reg_snapshot[this_cpu].i7 = rw->ins[7]; |
269 | rw = (struct reg_window *) | ||
270 | (rw->ins[6] + STACK_BIAS); | ||
271 | if (kstack_valid(tp, rw)) | ||
272 | global_reg_snapshot[this_cpu].rpc = rw->ins[7]; | ||
273 | } | ||
274 | } else { | ||
324 | global_reg_snapshot[this_cpu].i7 = 0; | 275 | global_reg_snapshot[this_cpu].i7 = 0; |
325 | 276 | global_reg_snapshot[this_cpu].rpc = 0; | |
277 | } | ||
326 | global_reg_snapshot[this_cpu].thread = tp; | 278 | global_reg_snapshot[this_cpu].thread = tp; |
327 | } | 279 | } |
328 | 280 | ||
@@ -341,7 +293,7 @@ static void __global_reg_poll(struct global_reg_snapshot *gp) | |||
341 | } | 293 | } |
342 | } | 294 | } |
343 | 295 | ||
344 | static void sysrq_handle_globreg(int key, struct tty_struct *tty) | 296 | void __trigger_all_cpu_backtrace(void) |
345 | { | 297 | { |
346 | struct thread_info *tp = current_thread_info(); | 298 | struct thread_info *tp = current_thread_info(); |
347 | struct pt_regs *regs = get_irq_regs(); | 299 | struct pt_regs *regs = get_irq_regs(); |
@@ -375,13 +327,14 @@ static void sysrq_handle_globreg(int key, struct tty_struct *tty) | |||
375 | ((tp && tp->task) ? tp->task->pid : -1)); | 327 | ((tp && tp->task) ? tp->task->pid : -1)); |
376 | 328 | ||
377 | if (gp->tstate & TSTATE_PRIV) { | 329 | if (gp->tstate & TSTATE_PRIV) { |
378 | printk(" TPC[%pS] O7[%pS] I7[%pS]\n", | 330 | printk(" TPC[%pS] O7[%pS] I7[%pS] RPC[%pS]\n", |
379 | (void *) gp->tpc, | 331 | (void *) gp->tpc, |
380 | (void *) gp->o7, | 332 | (void *) gp->o7, |
381 | (void *) gp->i7); | 333 | (void *) gp->i7, |
334 | (void *) gp->rpc); | ||
382 | } else { | 335 | } else { |
383 | printk(" TPC[%lx] O7[%lx] I7[%lx]\n", | 336 | printk(" TPC[%lx] O7[%lx] I7[%lx] RPC[%lx]\n", |
384 | gp->tpc, gp->o7, gp->i7); | 337 | gp->tpc, gp->o7, gp->i7, gp->rpc); |
385 | } | 338 | } |
386 | } | 339 | } |
387 | 340 | ||
@@ -390,6 +343,13 @@ static void sysrq_handle_globreg(int key, struct tty_struct *tty) | |||
390 | spin_unlock_irqrestore(&global_reg_snapshot_lock, flags); | 343 | spin_unlock_irqrestore(&global_reg_snapshot_lock, flags); |
391 | } | 344 | } |
392 | 345 | ||
346 | #ifdef CONFIG_MAGIC_SYSRQ | ||
347 | |||
348 | static void sysrq_handle_globreg(int key, struct tty_struct *tty) | ||
349 | { | ||
350 | __trigger_all_cpu_backtrace(); | ||
351 | } | ||
352 | |||
393 | static struct sysrq_key_op sparc_globalreg_op = { | 353 | static struct sysrq_key_op sparc_globalreg_op = { |
394 | .handler = sysrq_handle_globreg, | 354 | .handler = sysrq_handle_globreg, |
395 | .help_msg = "Globalregs", | 355 | .help_msg = "Globalregs", |