aboutsummaryrefslogtreecommitdiffstats
path: root/arch/tile/kernel/stack.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/tile/kernel/stack.c')
-rw-r--r--arch/tile/kernel/stack.c35
1 files changed, 22 insertions, 13 deletions
diff --git a/arch/tile/kernel/stack.c b/arch/tile/kernel/stack.c
index ea2e0ce28380..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)
@@ -207,11 +211,11 @@ static int KBacktraceIterator_next_item_inclusive(
207 for (;;) { 211 for (;;) {
208 do { 212 do {
209 if (!KBacktraceIterator_is_sigreturn(kbt)) 213 if (!KBacktraceIterator_is_sigreturn(kbt))
210 return 1; 214 return KBT_ONGOING;
211 } while (backtrace_next(&kbt->it)); 215 } while (backtrace_next(&kbt->it));
212 216
213 if (!KBacktraceIterator_restart(kbt)) 217 if (!KBacktraceIterator_restart(kbt))
214 return 0; 218 return KBT_DONE;
215 } 219 }
216} 220}
217 221
@@ -264,7 +268,7 @@ void KBacktraceIterator_init(struct KBacktraceIterator *kbt,
264 kbt->pgtable = NULL; 268 kbt->pgtable = NULL;
265 kbt->verbose = 0; /* override in caller if desired */ 269 kbt->verbose = 0; /* override in caller if desired */
266 kbt->profile = 0; /* override in caller if desired */ 270 kbt->profile = 0; /* override in caller if desired */
267 kbt->end = 0; 271 kbt->end = KBT_ONGOING;
268 kbt->new_context = 0; 272 kbt->new_context = 0;
269 if (is_current) { 273 if (is_current) {
270 HV_PhysAddr pgdir_pa = hv_inquire_context().page_table; 274 HV_PhysAddr pgdir_pa = hv_inquire_context().page_table;
@@ -290,7 +294,7 @@ void KBacktraceIterator_init(struct KBacktraceIterator *kbt,
290 if (regs == NULL) { 294 if (regs == NULL) {
291 if (is_current || t->state == TASK_RUNNING) { 295 if (is_current || t->state == TASK_RUNNING) {
292 /* Can't do this; we need registers */ 296 /* Can't do this; we need registers */
293 kbt->end = 1; 297 kbt->end = KBT_RUNNING;
294 return; 298 return;
295 } 299 }
296 pc = get_switch_to_pc(); 300 pc = get_switch_to_pc();
@@ -305,26 +309,29 @@ void KBacktraceIterator_init(struct KBacktraceIterator *kbt,
305 } 309 }
306 310
307 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);
308 kbt->end = !KBacktraceIterator_next_item_inclusive(kbt); 312 kbt->end = KBacktraceIterator_next_item_inclusive(kbt);
309} 313}
310EXPORT_SYMBOL(KBacktraceIterator_init); 314EXPORT_SYMBOL(KBacktraceIterator_init);
311 315
312int KBacktraceIterator_end(struct KBacktraceIterator *kbt) 316int KBacktraceIterator_end(struct KBacktraceIterator *kbt)
313{ 317{
314 return kbt->end; 318 return kbt->end != KBT_ONGOING;
315} 319}
316EXPORT_SYMBOL(KBacktraceIterator_end); 320EXPORT_SYMBOL(KBacktraceIterator_end);
317 321
318void KBacktraceIterator_next(struct KBacktraceIterator *kbt) 322void KBacktraceIterator_next(struct KBacktraceIterator *kbt)
319{ 323{
324 VirtualAddress old_pc = kbt->it.pc, old_sp = kbt->it.sp;
320 kbt->new_context = 0; 325 kbt->new_context = 0;
321 if (!backtrace_next(&kbt->it) && 326 if (!backtrace_next(&kbt->it) && !KBacktraceIterator_restart(kbt)) {
322 !KBacktraceIterator_restart(kbt)) { 327 kbt->end = KBT_DONE;
323 kbt->end = 1; 328 return;
324 return; 329 }
325 } 330 kbt->end = KBacktraceIterator_next_item_inclusive(kbt);
326 331 if (old_pc == kbt->it.pc && old_sp == kbt->it.sp) {
327 kbt->end = !KBacktraceIterator_next_item_inclusive(kbt); 332 /* Trapped in a loop; give up. */
333 kbt->end = KBT_LOOP;
334 }
328} 335}
329EXPORT_SYMBOL(KBacktraceIterator_next); 336EXPORT_SYMBOL(KBacktraceIterator_next);
330 337
@@ -387,6 +394,8 @@ void tile_show_stack(struct KBacktraceIterator *kbt, int headers)
387 break; 394 break;
388 } 395 }
389 } 396 }
397 if (kbt->end == KBT_LOOP)
398 pr_err("Stack dump stopped; next frame identical to this one\n");
390 if (headers) 399 if (headers)
391 pr_err("Stack dump complete\n"); 400 pr_err("Stack dump complete\n");
392} 401}