^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2000, 2002-2003 Hewlett-Packard Co
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * David Mosberger-Tang <davidm@hpl.hp.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Kernel unwind support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #define UNW_VER(x) ((x) >> 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #define UNW_FLAG_MASK 0x0000ffff00000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #define UNW_FLAG_OSMASK 0x0000f00000000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #define UNW_FLAG_EHANDLER(x) ((x) & 0x0000000100000000L)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #define UNW_FLAG_UHANDLER(x) ((x) & 0x0000000200000000L)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define UNW_LENGTH(x) ((x) & 0x00000000ffffffffL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) enum unw_register_index {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) /* primary unat: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) UNW_REG_PRI_UNAT_GR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) UNW_REG_PRI_UNAT_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) /* register stack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) UNW_REG_BSP, /* register stack pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) UNW_REG_BSPSTORE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) UNW_REG_PFS, /* previous function state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) UNW_REG_RNAT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /* memory stack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) UNW_REG_PSP, /* previous memory stack pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /* return pointer: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) UNW_REG_RP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /* preserved registers: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) UNW_REG_R4, UNW_REG_R5, UNW_REG_R6, UNW_REG_R7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) UNW_REG_UNAT, UNW_REG_PR, UNW_REG_LC, UNW_REG_FPSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) UNW_REG_B1, UNW_REG_B2, UNW_REG_B3, UNW_REG_B4, UNW_REG_B5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) UNW_REG_F2, UNW_REG_F3, UNW_REG_F4, UNW_REG_F5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) UNW_REG_F16, UNW_REG_F17, UNW_REG_F18, UNW_REG_F19,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) UNW_REG_F20, UNW_REG_F21, UNW_REG_F22, UNW_REG_F23,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) UNW_REG_F24, UNW_REG_F25, UNW_REG_F26, UNW_REG_F27,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) UNW_REG_F28, UNW_REG_F29, UNW_REG_F30, UNW_REG_F31,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) UNW_NUM_REGS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct unw_info_block {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) u64 header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) u64 desc[]; /* unwind descriptors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /* personality routine and language-specific data follow behind descriptors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct unw_table {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct unw_table *next; /* must be first member! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) unsigned long gp; /* global pointer for this load-module */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) unsigned long segment_base; /* base for offsets in the unwind table entries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) unsigned long start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) unsigned long end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) const struct unw_table_entry *array;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) unsigned long length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) enum unw_where {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) UNW_WHERE_NONE, /* register isn't saved at all */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) UNW_WHERE_GR, /* register is saved in a general register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) UNW_WHERE_FR, /* register is saved in a floating-point register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) UNW_WHERE_BR, /* register is saved in a branch register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) UNW_WHERE_SPREL, /* register is saved on memstack (sp-relative) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) UNW_WHERE_PSPREL, /* register is saved on memstack (psp-relative) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * At the end of each prologue these locations get resolved to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * UNW_WHERE_PSPREL and UNW_WHERE_GR, respectively:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) UNW_WHERE_SPILL_HOME, /* register is saved in its spill home */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) UNW_WHERE_GR_SAVE /* register is saved in next general register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define UNW_WHEN_NEVER 0x7fffffff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct unw_reg_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) unsigned long val; /* save location: register number or offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) enum unw_where where; /* where the register gets saved */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) int when; /* when the register gets saved */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct unw_reg_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct unw_reg_state *next; /* next (outer) element on state stack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct unw_reg_info reg[UNW_NUM_REGS]; /* register save locations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) struct unw_labeled_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) struct unw_labeled_state *next; /* next labeled state (or NULL) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) unsigned long label; /* label for this state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct unw_reg_state saved_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct unw_state_record {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) unsigned int first_region : 1; /* is this the first region? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) unsigned int done : 1; /* are we done scanning descriptors? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) unsigned int any_spills : 1; /* got any register spills? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) unsigned int in_body : 1; /* are we inside a body (as opposed to a prologue)? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) unsigned long flags; /* see UNW_FLAG_* in unwind.h */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) u8 *imask; /* imask of spill_mask record or NULL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) unsigned long pr_val; /* predicate values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) unsigned long pr_mask; /* predicate mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) long spill_offset; /* psp-relative offset for spill base */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) int region_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) int region_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) int epilogue_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) int epilogue_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) int when_target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) u8 gr_save_loc; /* next general register to use for saving a register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) u8 return_link_reg; /* branch register in which the return link is passed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct unw_labeled_state *labeled_states; /* list of all labeled states */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct unw_reg_state curr; /* current state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) enum unw_nat_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) UNW_NAT_NONE, /* NaT not represented */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) UNW_NAT_VAL, /* NaT represented by NaT value (fp reg) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) UNW_NAT_MEMSTK, /* NaT value is in unat word at offset OFF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) UNW_NAT_REGSTK /* NaT is in rnat */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) enum unw_insn_opcode {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) UNW_INSN_ADD, /* s[dst] += val */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) UNW_INSN_ADD_PSP, /* s[dst] = (s.psp + val) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) UNW_INSN_ADD_SP, /* s[dst] = (s.sp + val) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) UNW_INSN_MOVE, /* s[dst] = s[val] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) UNW_INSN_MOVE2, /* s[dst] = s[val]; s[dst+1] = s[val+1] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) UNW_INSN_MOVE_STACKED, /* s[dst] = ia64_rse_skip(*s.bsp, val) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) UNW_INSN_SETNAT_MEMSTK, /* s[dst+1].nat.type = MEMSTK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) s[dst+1].nat.off = *s.pri_unat - s[dst] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) UNW_INSN_SETNAT_TYPE, /* s[dst+1].nat.type = val */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) UNW_INSN_LOAD, /* s[dst] = *s[val] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) UNW_INSN_MOVE_SCRATCH, /* s[dst] = scratch reg "val" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) UNW_INSN_MOVE_CONST, /* s[dst] = constant reg "val" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct unw_insn {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) unsigned int opc : 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) unsigned int dst : 9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) signed int val : 19;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * Preserved general static registers (r4-r7) give rise to two script
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * instructions; everything else yields at most one instruction; at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * the end of the script, the psp gets popped, accounting for one more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * instruction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #define UNW_MAX_SCRIPT_LEN (UNW_NUM_REGS + 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct unw_script {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) unsigned long ip; /* ip this script is for */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) unsigned long pr_mask; /* mask of predicates script depends on */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) unsigned long pr_val; /* predicate values this script is for */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) rwlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) unsigned int flags; /* see UNW_FLAG_* in unwind.h */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) unsigned short lru_chain; /* used for least-recently-used chain */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) unsigned short coll_chain; /* used for hash collisions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) unsigned short hint; /* hint for next script to try (or -1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) unsigned short count; /* number of instructions in script */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) struct unw_insn insn[UNW_MAX_SCRIPT_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) };