aboutsummaryrefslogtreecommitdiffstats
path: root/arch/tile/kernel/stack.c
diff options
context:
space:
mode:
authorGrant Likely <grant.likely@secretlab.ca>2010-12-30 00:20:30 -0500
committerGrant Likely <grant.likely@secretlab.ca>2010-12-30 00:21:47 -0500
commitd392da5207352f09030e95d9ea335a4225667ec0 (patch)
tree7d6cd1932afcad0a5619a5c504a6d93ca318187c /arch/tile/kernel/stack.c
parente39d5ef678045d61812c1401f04fe8edb14d6359 (diff)
parent387c31c7e5c9805b0aef8833d1731a5fe7bdea14 (diff)
Merge v2.6.37-rc8 into powerpc/next
Diffstat (limited to 'arch/tile/kernel/stack.c')
-rw-r--r--arch/tile/kernel/stack.c45
1 files changed, 23 insertions, 22 deletions
diff --git a/arch/tile/kernel/stack.c b/arch/tile/kernel/stack.c
index b6268d3ae869..0d54106be3d6 100644
--- a/arch/tile/kernel/stack.c
+++ b/arch/tile/kernel/stack.c
@@ -30,6 +30,10 @@
30#include <arch/abi.h> 30#include <arch/abi.h>
31#include <arch/interrupts.h> 31#include <arch/interrupts.h>
32 32
33#define KBT_ONGOING 0 /* Backtrace still ongoing */
34#define KBT_DONE 1 /* Backtrace cleanly completed */
35#define KBT_RUNNING 2 /* Can't run backtrace on a running task */
36#define KBT_LOOP 3 /* Backtrace entered a loop */
33 37
34/* Is address on the specified kernel stack? */ 38/* Is address on the specified kernel stack? */
35static int in_kernel_stack(struct KBacktraceIterator *kbt, VirtualAddress sp) 39static int in_kernel_stack(struct KBacktraceIterator *kbt, VirtualAddress sp)
@@ -108,7 +112,6 @@ static bool read_memory_func(void *result, VirtualAddress address,
108/* Return a pt_regs pointer for a valid fault handler frame */ 112/* Return a pt_regs pointer for a valid fault handler frame */
109static struct pt_regs *valid_fault_handler(struct KBacktraceIterator* kbt) 113static struct pt_regs *valid_fault_handler(struct KBacktraceIterator* kbt)
110{ 114{
111#ifndef __tilegx__
112 const char *fault = NULL; /* happy compiler */ 115 const char *fault = NULL; /* happy compiler */
113 char fault_buf[64]; 116 char fault_buf[64];
114 VirtualAddress sp = kbt->it.sp; 117 VirtualAddress sp = kbt->it.sp;
@@ -146,7 +149,6 @@ static struct pt_regs *valid_fault_handler(struct KBacktraceIterator* kbt)
146 } 149 }
147 if (!kbt->profile || (INT_MASK(p->faultnum) & QUEUED_INTERRUPTS) == 0) 150 if (!kbt->profile || (INT_MASK(p->faultnum) & QUEUED_INTERRUPTS) == 0)
148 return p; 151 return p;
149#endif
150 return NULL; 152 return NULL;
151} 153}
152 154
@@ -177,7 +179,7 @@ static struct pt_regs *valid_sigframe(struct KBacktraceIterator* kbt)
177 pr_err(" <received signal %d>\n", 179 pr_err(" <received signal %d>\n",
178 frame->info.si_signo); 180 frame->info.si_signo);
179 } 181 }
180 return &frame->uc.uc_mcontext.regs; 182 return (struct pt_regs *)&frame->uc.uc_mcontext;
181 } 183 }
182 return NULL; 184 return NULL;
183} 185}
@@ -209,11 +211,11 @@ static int KBacktraceIterator_next_item_inclusive(
209 for (;;) { 211 for (;;) {
210 do { 212 do {
211 if (!KBacktraceIterator_is_sigreturn(kbt)) 213 if (!KBacktraceIterator_is_sigreturn(kbt))
212 return 1; 214 return KBT_ONGOING;
213 } while (backtrace_next(&kbt->it)); 215 } while (backtrace_next(&kbt->it));
214 216
215 if (!KBacktraceIterator_restart(kbt)) 217 if (!KBacktraceIterator_restart(kbt))
216 return 0; 218 return KBT_DONE;
217 } 219 }
218} 220}
219 221
@@ -266,7 +268,7 @@ void KBacktraceIterator_init(struct KBacktraceIterator *kbt,
266 kbt->pgtable = NULL; 268 kbt->pgtable = NULL;
267 kbt->verbose = 0; /* override in caller if desired */ 269 kbt->verbose = 0; /* override in caller if desired */
268 kbt->profile = 0; /* override in caller if desired */ 270 kbt->profile = 0; /* override in caller if desired */
269 kbt->end = 0; 271 kbt->end = KBT_ONGOING;
270 kbt->new_context = 0; 272 kbt->new_context = 0;
271 if (is_current) { 273 if (is_current) {
272 HV_PhysAddr pgdir_pa = hv_inquire_context().page_table; 274 HV_PhysAddr pgdir_pa = hv_inquire_context().page_table;
@@ -292,7 +294,7 @@ void KBacktraceIterator_init(struct KBacktraceIterator *kbt,
292 if (regs == NULL) { 294 if (regs == NULL) {
293 if (is_current || t->state == TASK_RUNNING) { 295 if (is_current || t->state == TASK_RUNNING) {
294 /* Can't do this; we need registers */ 296 /* Can't do this; we need registers */
295 kbt->end = 1; 297 kbt->end = KBT_RUNNING;
296 return; 298 return;
297 } 299 }
298 pc = get_switch_to_pc(); 300 pc = get_switch_to_pc();
@@ -307,26 +309,29 @@ void KBacktraceIterator_init(struct KBacktraceIterator *kbt,
307 } 309 }
308 310
309 backtrace_init(&kbt->it, read_memory_func, kbt, pc, lr, sp, r52); 311 backtrace_init(&kbt->it, read_memory_func, kbt, pc, lr, sp, r52);
310 kbt->end = !KBacktraceIterator_next_item_inclusive(kbt); 312 kbt->end = KBacktraceIterator_next_item_inclusive(kbt);
311} 313}
312EXPORT_SYMBOL(KBacktraceIterator_init); 314EXPORT_SYMBOL(KBacktraceIterator_init);
313 315
314int KBacktraceIterator_end(struct KBacktraceIterator *kbt) 316int KBacktraceIterator_end(struct KBacktraceIterator *kbt)
315{ 317{
316 return kbt->end; 318 return kbt->end != KBT_ONGOING;
317} 319}
318EXPORT_SYMBOL(KBacktraceIterator_end); 320EXPORT_SYMBOL(KBacktraceIterator_end);
319 321
320void KBacktraceIterator_next(struct KBacktraceIterator *kbt) 322void KBacktraceIterator_next(struct KBacktraceIterator *kbt)
321{ 323{
324 VirtualAddress old_pc = kbt->it.pc, old_sp = kbt->it.sp;
322 kbt->new_context = 0; 325 kbt->new_context = 0;
323 if (!backtrace_next(&kbt->it) && 326 if (!backtrace_next(&kbt->it) && !KBacktraceIterator_restart(kbt)) {
324 !KBacktraceIterator_restart(kbt)) { 327 kbt->end = KBT_DONE;
325 kbt->end = 1; 328 return;
326 return; 329 }
327 } 330 kbt->end = KBacktraceIterator_next_item_inclusive(kbt);
328 331 if (old_pc == kbt->it.pc && old_sp == kbt->it.sp) {
329 kbt->end = !KBacktraceIterator_next_item_inclusive(kbt); 332 /* Trapped in a loop; give up. */
333 kbt->end = KBT_LOOP;
334 }
330} 335}
331EXPORT_SYMBOL(KBacktraceIterator_next); 336EXPORT_SYMBOL(KBacktraceIterator_next);
332 337
@@ -351,12 +356,6 @@ void tile_show_stack(struct KBacktraceIterator *kbt, int headers)
351 kbt->task->pid, kbt->task->tgid, kbt->task->comm, 356 kbt->task->pid, kbt->task->tgid, kbt->task->comm,
352 smp_processor_id(), get_cycles()); 357 smp_processor_id(), get_cycles());
353 } 358 }
354#ifdef __tilegx__
355 if (kbt->is_current) {
356 __insn_mtspr(SPR_SIM_CONTROL,
357 SIM_DUMP_SPR_ARG(SIM_DUMP_BACKTRACE));
358 }
359#endif
360 kbt->verbose = 1; 359 kbt->verbose = 1;
361 i = 0; 360 i = 0;
362 for (; !KBacktraceIterator_end(kbt); KBacktraceIterator_next(kbt)) { 361 for (; !KBacktraceIterator_end(kbt); KBacktraceIterator_next(kbt)) {
@@ -395,6 +394,8 @@ void tile_show_stack(struct KBacktraceIterator *kbt, int headers)
395 break; 394 break;
396 } 395 }
397 } 396 }
397 if (kbt->end == KBT_LOOP)
398 pr_err("Stack dump stopped; next frame identical to this one\n");
398 if (headers) 399 if (headers)
399 pr_err("Stack dump complete\n"); 400 pr_err("Stack dump complete\n");
400} 401}