Lines Matching +full:early +full:- +full:to +full:- +full:mid

1 // SPDX-License-Identifier: GPL-2.0
5 * (c) 2002-2004 Randolph Chung <tausq@debian.org>
7 * Derived partially from the IA64 implementation. The PA-RISC
8 * Runtime Architecture Document is also a useful reference to
21 #include <asm/asm-offsets.h>
38 #define ALIGNMENT_OK(ptr, type) (((ptr) & (sizeof(type) - 1)) == 0)
46 * we can call unwind_init as early in the bootup process as
56 unsigned long lo, hi, mid; in find_unwind_entry_in_table() local
59 hi = table->length - 1; in find_unwind_entry_in_table()
62 mid = (hi - lo) / 2 + lo; in find_unwind_entry_in_table()
63 e = &table->table[mid]; in find_unwind_entry_in_table()
64 if (addr < e->region_start) in find_unwind_entry_in_table()
65 hi = mid - 1; in find_unwind_entry_in_table()
66 else if (addr > e->region_end) in find_unwind_entry_in_table()
67 lo = mid + 1; in find_unwind_entry_in_table()
89 if (addr >= table->start && in find_unwind_entry()
90 addr <= table->end) in find_unwind_entry()
93 /* Move-to-front to exploit common traces */ in find_unwind_entry()
94 list_move(&table->list, &unwind_tables); in find_unwind_entry()
111 (struct unwind_table_entry *)table_end - 1; in unwind_table_init()
113 table->name = name; in unwind_table_init()
114 table->base_addr = base_addr; in unwind_table_init()
115 table->gp = gp; in unwind_table_init()
116 table->start = base_addr + start->region_start; in unwind_table_init()
117 table->end = base_addr + end->region_end; in unwind_table_init()
118 table->table = (struct unwind_table_entry *)table_start; in unwind_table_init()
119 table->length = end - start + 1; in unwind_table_init()
120 INIT_LIST_HEAD(&table->list); in unwind_table_init()
124 start->region_end > (start+1)->region_start) { in unwind_table_init()
129 start->region_start += base_addr; in unwind_table_init()
130 start->region_end += base_addr; in unwind_table_init()
136 return ((const struct unwind_table_entry *)a)->region_start in cmp_unwind_table_entry()
137 - ((const struct unwind_table_entry *)b)->region_start; in cmp_unwind_table_entry()
144 sort(start, finish - start, sizeof(struct unwind_table_entry), in unwind_table_sort()
165 list_add_tail(&table->list, &unwind_tables); in unwind_table_add()
176 list_del(&table->list); in unwind_table_remove()
182 /* Called from setup_arch to import the kernel unwind info */
193 (stop - start) / sizeof(struct unwind_table_entry)); in unwind_init()
203 printk("region 0x%x-0x%x\n", in unwind_init()
220 * We have to use void * instead of a function pointer, because in unwind_special()
221 * function pointers aren't a pointer to the function on 64-bit. in unwind_special()
224 * instead but we want to keep it simple here. in unwind_special()
235 struct pt_regs *regs = (struct pt_regs *)(info->sp - frame_size - PT_SZ_ALGN); in unwind_special()
237 info->prev_sp = regs->gr[30]; in unwind_special()
238 info->prev_ip = regs->iaoq[0]; in unwind_special()
244 info->prev_sp = info->prev_ip = 0; in unwind_special()
252 regs = (struct pt_regs *)(info->sp - PT_SZ_ALGN); in unwind_special()
253 info->prev_sp = regs->gr[30]; in unwind_special()
254 info->prev_ip = regs->iaoq[0]; in unwind_special()
255 info->rp = regs->gr[2]; in unwind_special()
261 info->prev_sp = info->sp - CALLEE_SAVE_FRAME_SIZE; in unwind_special()
262 if (ALIGNMENT_OK(info->prev_sp, long)) in unwind_special()
263 info->prev_ip = *(unsigned long *)(info->prev_sp - RP_OFFSET); in unwind_special()
265 info->prev_ip = info->prev_sp = 0; in unwind_special()
270 if (pc == (unsigned long)&_call_on_stack && ALIGNMENT_OK(info->sp, long)) { in unwind_special()
271 info->prev_sp = *(unsigned long *)(info->sp - FRAME_SIZE - REG_SZ); in unwind_special()
272 info->prev_ip = *(unsigned long *)(info->sp - FRAME_SIZE - RP_OFFSET); in unwind_special()
287 e = find_unwind_entry(info->ip); in unwind_frame_regs()
292 (void *) info->ip); in unwind_frame_regs()
296 correctly. The rp is checked to see if it belongs to the in unwind_frame_regs()
298 correct stack frame and we continue to unwind the stack. in unwind_frame_regs()
301 sp = info->sp & ~63; in unwind_frame_regs()
305 info->prev_sp = sp - 64; in unwind_frame_regs()
306 info->prev_ip = 0; in unwind_frame_regs()
309 if ((info->prev_sp - (unsigned long) task_stack_page(info->t)) in unwind_frame_regs()
311 info->prev_sp = 0; in unwind_frame_regs()
316 (void *)info->prev_sp - RP_OFFSET, sizeof(tmp))) in unwind_frame_regs()
318 info->prev_ip = tmp; in unwind_frame_regs()
319 sp = info->prev_sp; in unwind_frame_regs()
320 } while (!kernel_text_address(info->prev_ip)); in unwind_frame_regs()
322 info->rp = 0; in unwind_frame_regs()
325 "prev_sp=%lx prev_ip=%lx\n", info->ip, in unwind_frame_regs()
326 info->prev_sp, info->prev_ip); in unwind_frame_regs()
328 dbg("e->start = 0x%x, e->end = 0x%x, Save_SP = %d, " in unwind_frame_regs()
330 e->region_start, e->region_end, e->Save_SP, e->Save_RP, in unwind_frame_regs()
331 e->Millicode, e->Total_frame_size); in unwind_frame_regs()
333 looking_for_rp = e->Save_RP; in unwind_frame_regs()
335 for (npc = e->region_start; in unwind_frame_regs()
336 (frame_size < (e->Total_frame_size << 3) || in unwind_frame_regs()
338 npc < info->ip; in unwind_frame_regs()
348 "%lx, frame_size = %ld\n", info->ip, in unwind_frame_regs()
354 "%lx, frame_size = %ld\n", info->ip, in unwind_frame_regs()
357 /* stw rp,-20(sp) */ in unwind_frame_regs()
361 "-20(sp) @ %lx\n", info->ip, npc); in unwind_frame_regs()
363 /* std rp,-16(sr0,sp) */ in unwind_frame_regs()
367 "-16(sp) @ %lx\n", info->ip, npc); in unwind_frame_regs()
371 if (frame_size > e->Total_frame_size << 3) in unwind_frame_regs()
372 frame_size = e->Total_frame_size << 3; in unwind_frame_regs()
374 if (!unwind_special(info, e->region_start, frame_size)) { in unwind_frame_regs()
375 info->prev_sp = info->sp - frame_size; in unwind_frame_regs()
376 if (e->Millicode) in unwind_frame_regs()
377 info->rp = info->r31; in unwind_frame_regs()
378 else if (rpoffset && ALIGNMENT_OK(info->prev_sp, long)) in unwind_frame_regs()
379 info->rp = *(unsigned long *)(info->prev_sp - rpoffset); in unwind_frame_regs()
381 info->rp = 0; in unwind_frame_regs()
382 info->prev_ip = info->rp; in unwind_frame_regs()
383 info->rp = 0; in unwind_frame_regs()
387 "prev_ip=%lx npc=%lx\n", info->ip, info->prev_sp, in unwind_frame_regs()
388 info->prev_ip, npc); in unwind_frame_regs()
396 info->t = t; in unwind_frame_init()
397 info->sp = regs->gr[30]; in unwind_frame_init()
398 info->ip = regs->iaoq[0]; in unwind_frame_init()
399 info->rp = regs->gr[2]; in unwind_frame_init()
400 info->r31 = regs->gr[31]; in unwind_frame_init()
403 t ? (int)t->pid : -1, info->sp, info->ip); in unwind_frame_init()
408 struct pt_regs *r = &t->thread.regs; in unwind_frame_init_from_blocked_task()
415 r2->gr[30] = r->ksp; in unwind_frame_init_from_blocked_task()
416 r2->iaoq[0] = r->kpc; in unwind_frame_init_from_blocked_task()
452 if (next_frame->prev_sp == 0 || in unwind_once()
453 next_frame->prev_ip == 0) in unwind_once()
454 return -1; in unwind_once()
456 next_frame->sp = next_frame->prev_sp; in unwind_once()
457 next_frame->ip = next_frame->prev_ip; in unwind_once()
458 next_frame->prev_sp = 0; in unwind_once()
459 next_frame->prev_ip = 0; in unwind_once()
461 dbg("(%d) Continue unwind to sp=%08lx ip=%08lx\n", in unwind_once()
462 next_frame->t ? (int)next_frame->t->pid : -1, in unwind_once()
463 next_frame->sp, next_frame->ip); in unwind_once()
474 } while (!ret && !(info->ip & 3)); in unwind_to_user()
493 } while (info.ip && level--); in return_address()