Lines Matching +full:ctrl +full:- +full:a
1 // SPDX-License-Identifier: GPL-2.0-only
87 /* Convert a prel31 symbol to an absolute address */
90 /* sign-extend to 32 bits */ \
101 * stop - 1 = last entry
125 addr_prel31 = (addr - (unsigned long)start) & 0x7fffffff; in search_index()
127 while (start < stop - 1) { in search_index()
128 const struct unwind_idx *mid = start + ((stop - start) >> 1); in search_index()
134 if (addr_prel31 - ((unsigned long)mid - (unsigned long)start) < in search_index()
135 mid->addr_offset) in search_index()
139 addr_prel31 -= ((unsigned long)mid - in search_index()
145 if (likely(start->addr_offset <= addr_prel31)) in search_index()
158 const struct unwind_idx *mid = start + ((stop - start) >> 1); in unwind_find_origin()
160 if (mid->addr_offset >= 0x40000000) in unwind_find_origin()
167 pr_debug("%s -> %p\n", __func__, stop); in unwind_find_origin()
194 if (addr >= table->begin_addr && in unwind_find_idx()
195 addr < table->end_addr) { in unwind_find_idx()
196 idx = search_index(addr, table->start, in unwind_find_idx()
197 table->origin, in unwind_find_idx()
198 table->stop); in unwind_find_idx()
199 /* Move-to-front to exploit common traces */ in unwind_find_idx()
200 list_move(&table->list, &unwind_tables); in unwind_find_idx()
211 static unsigned long unwind_get_byte(struct unwind_ctrl_block *ctrl) in unwind_get_byte() argument
215 if (ctrl->entries <= 0) { in unwind_get_byte()
220 ret = (*ctrl->insn >> (ctrl->byte * 8)) & 0xff; in unwind_get_byte()
222 if (ctrl->byte == 0) { in unwind_get_byte()
223 ctrl->insn++; in unwind_get_byte()
224 ctrl->entries--; in unwind_get_byte()
225 ctrl->byte = 3; in unwind_get_byte()
227 ctrl->byte--; in unwind_get_byte()
232 /* Before poping a register check whether it is feasible or not */
233 static int unwind_pop_register(struct unwind_ctrl_block *ctrl, in unwind_pop_register() argument
236 if (unlikely(ctrl->check_each_pop)) in unwind_pop_register()
237 if (*vsp >= (unsigned long *)ctrl->sp_high) in unwind_pop_register()
238 return -URC_FAILURE; in unwind_pop_register()
243 ctrl->vrs[reg] = READ_ONCE_NOCHECK(*(*vsp)); in unwind_pop_register()
245 ctrl->lr_addr = *vsp; in unwind_pop_register()
251 static int unwind_exec_pop_subset_r4_to_r13(struct unwind_ctrl_block *ctrl, in unwind_exec_pop_subset_r4_to_r13() argument
254 unsigned long *vsp = (unsigned long *)ctrl->vrs[SP]; in unwind_exec_pop_subset_r4_to_r13()
257 load_sp = mask & (1 << (13 - 4)); in unwind_exec_pop_subset_r4_to_r13()
260 if (unwind_pop_register(ctrl, &vsp, reg)) in unwind_exec_pop_subset_r4_to_r13()
261 return -URC_FAILURE; in unwind_exec_pop_subset_r4_to_r13()
266 ctrl->vrs[SP] = (unsigned long)vsp; in unwind_exec_pop_subset_r4_to_r13()
272 static int unwind_exec_pop_r4_to_rN(struct unwind_ctrl_block *ctrl, in unwind_exec_pop_r4_to_rN() argument
275 unsigned long *vsp = (unsigned long *)ctrl->vrs[SP]; in unwind_exec_pop_r4_to_rN()
278 /* pop R4-R[4+bbb] */ in unwind_exec_pop_r4_to_rN()
280 if (unwind_pop_register(ctrl, &vsp, reg)) in unwind_exec_pop_r4_to_rN()
281 return -URC_FAILURE; in unwind_exec_pop_r4_to_rN()
284 if (unwind_pop_register(ctrl, &vsp, 14)) in unwind_exec_pop_r4_to_rN()
285 return -URC_FAILURE; in unwind_exec_pop_r4_to_rN()
287 ctrl->vrs[SP] = (unsigned long)vsp; in unwind_exec_pop_r4_to_rN()
292 static int unwind_exec_pop_subset_r0_to_r3(struct unwind_ctrl_block *ctrl, in unwind_exec_pop_subset_r0_to_r3() argument
295 unsigned long *vsp = (unsigned long *)ctrl->vrs[SP]; in unwind_exec_pop_subset_r0_to_r3()
298 /* pop R0-R3 according to mask */ in unwind_exec_pop_subset_r0_to_r3()
301 if (unwind_pop_register(ctrl, &vsp, reg)) in unwind_exec_pop_subset_r0_to_r3()
302 return -URC_FAILURE; in unwind_exec_pop_subset_r0_to_r3()
306 ctrl->vrs[SP] = (unsigned long)vsp; in unwind_exec_pop_subset_r0_to_r3()
311 static unsigned long unwind_decode_uleb128(struct unwind_ctrl_block *ctrl) in unwind_decode_uleb128() argument
318 * unwind_get_byte() will advance `ctrl` one instruction at a time, so in unwind_decode_uleb128()
321 * Note: This decodes a maximum of 4 bytes to output 28 bits data where in unwind_decode_uleb128()
322 * max is 0xfffffff: that will cover a vsp increment of 1073742336, hence in unwind_decode_uleb128()
326 insn = unwind_get_byte(ctrl); in unwind_decode_uleb128()
337 static int unwind_exec_insn(struct unwind_ctrl_block *ctrl) in unwind_exec_insn() argument
339 unsigned long insn = unwind_get_byte(ctrl); in unwind_exec_insn()
345 ctrl->vrs[SP] += ((insn & 0x3f) << 2) + 4; in unwind_exec_insn()
347 ctrl->vrs[SP] -= ((insn & 0x3f) << 2) + 4; in unwind_exec_insn()
351 insn = (insn << 8) | unwind_get_byte(ctrl); in unwind_exec_insn()
356 return -URC_FAILURE; in unwind_exec_insn()
359 ret = unwind_exec_pop_subset_r4_to_r13(ctrl, mask); in unwind_exec_insn()
364 ctrl->vrs[SP] = ctrl->vrs[insn & 0x0f]; in unwind_exec_insn()
366 ret = unwind_exec_pop_r4_to_rN(ctrl, insn); in unwind_exec_insn()
370 if (ctrl->vrs[PC] == 0) in unwind_exec_insn()
371 ctrl->vrs[PC] = ctrl->vrs[LR]; in unwind_exec_insn()
373 ctrl->entries = 0; in unwind_exec_insn()
375 unsigned long mask = unwind_get_byte(ctrl); in unwind_exec_insn()
380 return -URC_FAILURE; in unwind_exec_insn()
383 ret = unwind_exec_pop_subset_r0_to_r3(ctrl, mask); in unwind_exec_insn()
387 unsigned long uleb128 = unwind_decode_uleb128(ctrl); in unwind_exec_insn()
389 ctrl->vrs[SP] += 0x204 + (uleb128 << 2); in unwind_exec_insn()
392 return -URC_FAILURE; in unwind_exec_insn()
396 ctrl->vrs[FP], ctrl->vrs[SP], ctrl->vrs[LR], ctrl->vrs[PC]); in unwind_exec_insn()
403 * Unwind a single frame starting with *sp for the symbol at *pc. It
409 struct unwind_ctrl_block ctrl; in unwind_frame() local
413 sp_low = frame->sp; in unwind_frame()
414 ctrl.sp_high = ALIGN(sp_low - THREAD_SIZE, THREAD_ALIGN) in unwind_frame()
418 frame->pc, frame->lr, frame->sp); in unwind_frame()
420 idx = unwind_find_idx(frame->pc); in unwind_frame()
422 if (frame->pc && kernel_text_address(frame->pc)) { in unwind_frame()
423 if (in_module_plt(frame->pc) && frame->pc != frame->lr) { in unwind_frame()
425 * Quoting Ard: Veneers only set PC using a in unwind_frame()
429 frame->pc = frame->lr; in unwind_frame()
432 pr_warn("unwind: Index not found %08lx\n", frame->pc); in unwind_frame()
434 return -URC_FAILURE; in unwind_frame()
437 ctrl.vrs[FP] = frame->fp; in unwind_frame()
438 ctrl.vrs[SP] = frame->sp; in unwind_frame()
439 ctrl.vrs[LR] = frame->lr; in unwind_frame()
440 ctrl.vrs[PC] = 0; in unwind_frame()
442 if (idx->insn == 1) in unwind_frame()
444 return -URC_FAILURE; in unwind_frame()
445 else if (frame->pc == prel31_to_addr(&idx->addr_offset)) { in unwind_frame()
451 * a function, we are still effectively in the stack frame of in unwind_frame()
454 if (frame->pc == frame->lr) in unwind_frame()
455 return -URC_FAILURE; in unwind_frame()
456 frame->pc = frame->lr; in unwind_frame()
458 } else if ((idx->insn & 0x80000000) == 0) in unwind_frame()
460 ctrl.insn = (unsigned long *)prel31_to_addr(&idx->insn); in unwind_frame()
461 else if ((idx->insn & 0xff000000) == 0x80000000) in unwind_frame()
463 ctrl.insn = &idx->insn; in unwind_frame()
466 idx->insn, idx); in unwind_frame()
467 return -URC_FAILURE; in unwind_frame()
471 if ((*ctrl.insn & 0xff000000) == 0x80000000) { in unwind_frame()
472 ctrl.byte = 2; in unwind_frame()
473 ctrl.entries = 1; in unwind_frame()
474 } else if ((*ctrl.insn & 0xff000000) == 0x81000000) { in unwind_frame()
475 ctrl.byte = 1; in unwind_frame()
476 ctrl.entries = 1 + ((*ctrl.insn & 0x00ff0000) >> 16); in unwind_frame()
479 *ctrl.insn, ctrl.insn); in unwind_frame()
480 return -URC_FAILURE; in unwind_frame()
483 ctrl.check_each_pop = 0; in unwind_frame()
485 if (prel31_to_addr(&idx->addr_offset) == (u32)&call_with_stack) { in unwind_frame()
491 sp_low = frame->fp; in unwind_frame()
492 ctrl.sp_high = ALIGN(frame->fp, THREAD_SIZE); in unwind_frame()
495 while (ctrl.entries > 0) { in unwind_frame()
497 if ((ctrl.sp_high - ctrl.vrs[SP]) < sizeof(ctrl.vrs)) in unwind_frame()
498 ctrl.check_each_pop = 1; in unwind_frame()
499 urc = unwind_exec_insn(&ctrl); in unwind_frame()
502 if (ctrl.vrs[SP] < sp_low || ctrl.vrs[SP] > ctrl.sp_high) in unwind_frame()
503 return -URC_FAILURE; in unwind_frame()
506 if (ctrl.vrs[PC] == 0) in unwind_frame()
507 ctrl.vrs[PC] = ctrl.vrs[LR]; in unwind_frame()
510 if (frame->pc == ctrl.vrs[PC] && frame->sp == ctrl.vrs[SP]) in unwind_frame()
511 return -URC_FAILURE; in unwind_frame()
513 frame->fp = ctrl.vrs[FP]; in unwind_frame()
514 frame->sp = ctrl.vrs[SP]; in unwind_frame()
515 frame->lr = ctrl.vrs[LR]; in unwind_frame()
516 frame->pc = ctrl.vrs[PC]; in unwind_frame()
517 frame->lr_addr = ctrl.lr_addr; in unwind_frame()
537 if (!kernel_text_address(regs->ARM_pc)) in unwind_backtrace()
538 frame.pc = regs->ARM_lr; in unwind_backtrace()
554 * The function calling __switch_to cannot be a leaf function in unwind_backtrace()
568 dump_backtrace_entry(where, frame.pc, frame.sp - 4, loglvl); in unwind_backtrace()
585 tab->start = (const struct unwind_idx *)start; in unwind_table_add()
586 tab->stop = (const struct unwind_idx *)(start + size); in unwind_table_add()
587 tab->origin = unwind_find_origin(tab->start, tab->stop); in unwind_table_add()
588 tab->begin_addr = text_addr; in unwind_table_add()
589 tab->end_addr = text_addr + text_size; in unwind_table_add()
592 list_add_tail(&tab->list, &unwind_tables); in unwind_table_add()
606 list_del(&tab->list); in unwind_table_del()