diff options
author | Grant Likely <grant.likely@secretlab.ca> | 2010-12-30 00:20:30 -0500 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2010-12-30 00:21:47 -0500 |
commit | d392da5207352f09030e95d9ea335a4225667ec0 (patch) | |
tree | 7d6cd1932afcad0a5619a5c504a6d93ca318187c /arch/tile/kernel/stack.c | |
parent | e39d5ef678045d61812c1401f04fe8edb14d6359 (diff) | |
parent | 387c31c7e5c9805b0aef8833d1731a5fe7bdea14 (diff) |
Merge v2.6.37-rc8 into powerpc/next
Diffstat (limited to 'arch/tile/kernel/stack.c')
-rw-r--r-- | arch/tile/kernel/stack.c | 45 |
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? */ |
35 | static int in_kernel_stack(struct KBacktraceIterator *kbt, VirtualAddress sp) | 39 | static 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 */ |
109 | static struct pt_regs *valid_fault_handler(struct KBacktraceIterator* kbt) | 113 | static 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 | } |
312 | EXPORT_SYMBOL(KBacktraceIterator_init); | 314 | EXPORT_SYMBOL(KBacktraceIterator_init); |
313 | 315 | ||
314 | int KBacktraceIterator_end(struct KBacktraceIterator *kbt) | 316 | int KBacktraceIterator_end(struct KBacktraceIterator *kbt) |
315 | { | 317 | { |
316 | return kbt->end; | 318 | return kbt->end != KBT_ONGOING; |
317 | } | 319 | } |
318 | EXPORT_SYMBOL(KBacktraceIterator_end); | 320 | EXPORT_SYMBOL(KBacktraceIterator_end); |
319 | 321 | ||
320 | void KBacktraceIterator_next(struct KBacktraceIterator *kbt) | 322 | void 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 | } |
331 | EXPORT_SYMBOL(KBacktraceIterator_next); | 336 | EXPORT_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 | } |