^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) 1999-2004 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) * Copyright (C) 2003 Fenghua Yu <fenghua.yu@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * - Change pt_regs_off() to make it less dependent on pt_regs structure.
^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) * This file implements call frame unwind support for the Linux
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * kernel. Parsing and processing the unwind information is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * time-consuming, so this implementation translates the unwind
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * descriptors into unwind scripts. These scripts are very simple
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * (basically a sequence of assignments) and efficient to execute.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * They are cached for later re-use. Each script is specific for a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * given instruction pointer address and the set of predicate values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * that the script depends on (most unwind descriptors are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * unconditional and scripts often do not depend on predicates at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * all). This code is based on the unwind conventions described in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * the "IA-64 Software Conventions and Runtime Architecture" manual.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * SMP conventions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * o updates to the global unwind data (in structure "unw") are serialized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * by the unw.lock spinlock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * o each unwind script has its own read-write lock; a thread must acquire
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * a read lock before executing a script and must acquire a write lock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * before modifying a script
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * o if both the unw.lock spinlock and a script's read-write lock must be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * acquired, then the read-write lock must be acquired first.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/memblock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/elf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <asm/unwind.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <asm/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <asm/page.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <asm/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <asm/ptrace_offsets.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <asm/rse.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <asm/sections.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include "entry.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include "unwind_i.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define UNW_LOG_CACHE_SIZE 7 /* each unw_script is ~256 bytes in size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define UNW_CACHE_SIZE (1 << UNW_LOG_CACHE_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define UNW_LOG_HASH_SIZE (UNW_LOG_CACHE_SIZE + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define UNW_HASH_SIZE (1 << UNW_LOG_HASH_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define UNW_STATS 0 /* WARNING: this disabled interrupts for long time-spans!! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #ifdef UNW_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static unsigned int unw_debug_level = UNW_DEBUG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) # define UNW_DEBUG_ON(n) unw_debug_level >= n
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /* Do not code a printk level, not all debug lines end in newline */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) # define UNW_DPRINT(n, ...) if (UNW_DEBUG_ON(n)) printk(__VA_ARGS__)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) # undef inline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) # define inline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #else /* !UNW_DEBUG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) # define UNW_DEBUG_ON(n) 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) # define UNW_DPRINT(n, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #endif /* UNW_DEBUG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #if UNW_STATS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) # define STAT(x...) x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) # define STAT(x...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define alloc_reg_state() kmalloc(sizeof(struct unw_reg_state), GFP_ATOMIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define free_reg_state(usr) kfree(usr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define alloc_labeled_state() kmalloc(sizeof(struct unw_labeled_state), GFP_ATOMIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define free_labeled_state(usr) kfree(usr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) typedef unsigned long unw_word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) typedef unsigned char unw_hash_index_t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) spinlock_t lock; /* spinlock for unwind data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /* list of unwind tables (one per load-module) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) struct unw_table *tables;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) unsigned long r0; /* constant 0 for r0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* table of registers that prologues can save (and order in which they're saved): */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) const unsigned char save_order[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /* maps a preserved register index (preg_index) to corresponding switch_stack offset: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) unsigned short sw_off[sizeof(struct unw_frame_info) / 8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) unsigned short lru_head; /* index of lead-recently used script */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) unsigned short lru_tail; /* index of most-recently used script */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) /* index into unw_frame_info for preserved register i */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) unsigned short preg_index[UNW_NUM_REGS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) short pt_regs_offsets[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /* unwind table for the kernel: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct unw_table kernel_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /* unwind table describing the gate page (kernel code that is mapped into user space): */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) size_t gate_table_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) unsigned long *gate_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /* hash table that maps instruction pointer to script index: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) unsigned short hash[UNW_HASH_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /* script cache: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct unw_script cache[UNW_CACHE_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) # ifdef UNW_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) const char *preg_name[UNW_NUM_REGS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) # endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) # if UNW_STATS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) int lookups;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) int hinted_hits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) int normal_hits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) int collision_chain_traversals;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) } cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) unsigned long build_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) unsigned long run_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) unsigned long parse_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) int builds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) int news;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) int collisions;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) int runs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) } script;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) unsigned long init_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) unsigned long unwind_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) int inits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) int unwinds;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) } api;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) } stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) # endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) } unw = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) .tables = &unw.kernel_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) .lock = __SPIN_LOCK_UNLOCKED(unw.lock),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) .save_order = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) UNW_REG_RP, UNW_REG_PFS, UNW_REG_PSP, UNW_REG_PR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) UNW_REG_UNAT, UNW_REG_LC, UNW_REG_FPSR, UNW_REG_PRI_UNAT_GR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) .preg_index = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) offsetof(struct unw_frame_info, pri_unat_loc)/8, /* PRI_UNAT_GR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) offsetof(struct unw_frame_info, pri_unat_loc)/8, /* PRI_UNAT_MEM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) offsetof(struct unw_frame_info, bsp_loc)/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) offsetof(struct unw_frame_info, bspstore_loc)/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) offsetof(struct unw_frame_info, pfs_loc)/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) offsetof(struct unw_frame_info, rnat_loc)/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) offsetof(struct unw_frame_info, psp)/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) offsetof(struct unw_frame_info, rp_loc)/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) offsetof(struct unw_frame_info, r4)/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) offsetof(struct unw_frame_info, r5)/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) offsetof(struct unw_frame_info, r6)/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) offsetof(struct unw_frame_info, r7)/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) offsetof(struct unw_frame_info, unat_loc)/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) offsetof(struct unw_frame_info, pr_loc)/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) offsetof(struct unw_frame_info, lc_loc)/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) offsetof(struct unw_frame_info, fpsr_loc)/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) offsetof(struct unw_frame_info, b1_loc)/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) offsetof(struct unw_frame_info, b2_loc)/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) offsetof(struct unw_frame_info, b3_loc)/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) offsetof(struct unw_frame_info, b4_loc)/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) offsetof(struct unw_frame_info, b5_loc)/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) offsetof(struct unw_frame_info, f2_loc)/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) offsetof(struct unw_frame_info, f3_loc)/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) offsetof(struct unw_frame_info, f4_loc)/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) offsetof(struct unw_frame_info, f5_loc)/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) offsetof(struct unw_frame_info, fr_loc[16 - 16])/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) offsetof(struct unw_frame_info, fr_loc[17 - 16])/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) offsetof(struct unw_frame_info, fr_loc[18 - 16])/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) offsetof(struct unw_frame_info, fr_loc[19 - 16])/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) offsetof(struct unw_frame_info, fr_loc[20 - 16])/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) offsetof(struct unw_frame_info, fr_loc[21 - 16])/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) offsetof(struct unw_frame_info, fr_loc[22 - 16])/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) offsetof(struct unw_frame_info, fr_loc[23 - 16])/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) offsetof(struct unw_frame_info, fr_loc[24 - 16])/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) offsetof(struct unw_frame_info, fr_loc[25 - 16])/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) offsetof(struct unw_frame_info, fr_loc[26 - 16])/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) offsetof(struct unw_frame_info, fr_loc[27 - 16])/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) offsetof(struct unw_frame_info, fr_loc[28 - 16])/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) offsetof(struct unw_frame_info, fr_loc[29 - 16])/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) offsetof(struct unw_frame_info, fr_loc[30 - 16])/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) offsetof(struct unw_frame_info, fr_loc[31 - 16])/8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) .pt_regs_offsets = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) [0] = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) offsetof(struct pt_regs, r1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) offsetof(struct pt_regs, r2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) offsetof(struct pt_regs, r3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) [4] = -1, [5] = -1, [6] = -1, [7] = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) offsetof(struct pt_regs, r8),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) offsetof(struct pt_regs, r9),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) offsetof(struct pt_regs, r10),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) offsetof(struct pt_regs, r11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) offsetof(struct pt_regs, r12),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) offsetof(struct pt_regs, r13),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) offsetof(struct pt_regs, r14),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) offsetof(struct pt_regs, r15),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) offsetof(struct pt_regs, r16),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) offsetof(struct pt_regs, r17),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) offsetof(struct pt_regs, r18),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) offsetof(struct pt_regs, r19),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) offsetof(struct pt_regs, r20),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) offsetof(struct pt_regs, r21),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) offsetof(struct pt_regs, r22),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) offsetof(struct pt_regs, r23),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) offsetof(struct pt_regs, r24),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) offsetof(struct pt_regs, r25),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) offsetof(struct pt_regs, r26),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) offsetof(struct pt_regs, r27),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) offsetof(struct pt_regs, r28),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) offsetof(struct pt_regs, r29),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) offsetof(struct pt_regs, r30),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) offsetof(struct pt_regs, r31),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) .hash = { [0 ... UNW_HASH_SIZE - 1] = -1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) #ifdef UNW_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) .preg_name = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) "pri_unat_gr", "pri_unat_mem", "bsp", "bspstore", "ar.pfs", "ar.rnat", "psp", "rp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) "r4", "r5", "r6", "r7",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) "ar.unat", "pr", "ar.lc", "ar.fpsr",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) "b1", "b2", "b3", "b4", "b5",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) "f2", "f3", "f4", "f5",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) read_only (void *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) return (unsigned long) ((char *) addr - (char *) &unw.r0) < sizeof(unw.r0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) * Returns offset of rREG in struct pt_regs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static inline unsigned long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) pt_regs_off (unsigned long reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) short off = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (reg < ARRAY_SIZE(unw.pt_regs_offsets))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) off = unw.pt_regs_offsets[reg];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (off < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) UNW_DPRINT(0, "unwind.%s: bad scratch reg r%lu\n", __func__, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) off = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return (unsigned long) off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) static inline struct pt_regs *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) get_scratch_regs (struct unw_frame_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (!info->pt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /* This should not happen with valid unwind info. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) UNW_DPRINT(0, "unwind.%s: bad unwind info: resetting info->pt\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (info->flags & UNW_FLAG_INTERRUPT_FRAME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) info->pt = (unsigned long) ((struct pt_regs *) info->psp - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) info->pt = info->sp - 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) UNW_DPRINT(3, "unwind.%s: sp 0x%lx pt 0x%lx\n", __func__, info->sp, info->pt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return (struct pt_regs *) info->pt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) /* Unwind accessors. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) unw_access_gr (struct unw_frame_info *info, int regnum, unsigned long *val, char *nat, int write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) unsigned long *addr, *nat_addr, nat_mask = 0, dummy_nat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) struct unw_ireg *ireg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) struct pt_regs *pt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if ((unsigned) regnum - 1 >= 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (regnum == 0 && !write) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) *val = 0; /* read r0 always returns 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) *nat = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) UNW_DPRINT(0, "unwind.%s: trying to access non-existent r%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) __func__, regnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (regnum < 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (regnum >= 4 && regnum <= 7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) /* access a preserved register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) ireg = &info->r4 + (regnum - 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) addr = ireg->loc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) nat_addr = addr + ireg->nat.off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) switch (ireg->nat.type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) case UNW_NAT_VAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) /* simulate getf.sig/setf.sig */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (write) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (*nat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) /* write NaTVal and be done with it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) addr[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) addr[1] = 0x1fffe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) addr[1] = 0x1003e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (addr[0] == 0 && addr[1] == 0x1ffe) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) /* return NaT and be done with it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) *val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) *nat = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) case UNW_NAT_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) dummy_nat = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) nat_addr = &dummy_nat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) case UNW_NAT_MEMSTK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) nat_mask = (1UL << ((long) addr & 0x1f8)/8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) case UNW_NAT_REGSTK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) nat_addr = ia64_rse_rnat_addr(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) if ((unsigned long) addr < info->regstk.limit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) || (unsigned long) addr >= info->regstk.top)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) UNW_DPRINT(0, "unwind.%s: %p outside of regstk "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) "[0x%lx-0x%lx)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) __func__, (void *) addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) info->regstk.limit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) info->regstk.top);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if ((unsigned long) nat_addr >= info->regstk.top)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) nat_addr = &info->sw->ar_rnat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) nat_mask = (1UL << ia64_rse_slot_num(addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) addr = &info->sw->r4 + (regnum - 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) nat_addr = &info->sw->ar_unat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) nat_mask = (1UL << ((long) addr & 0x1f8)/8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) /* access a scratch register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) pt = get_scratch_regs(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) addr = (unsigned long *) ((unsigned long)pt + pt_regs_off(regnum));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (info->pri_unat_loc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) nat_addr = info->pri_unat_loc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) nat_addr = &info->sw->caller_unat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) nat_mask = (1UL << ((long) addr & 0x1f8)/8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) /* access a stacked register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) addr = ia64_rse_skip_regs((unsigned long *) info->bsp, regnum - 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) nat_addr = ia64_rse_rnat_addr(addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if ((unsigned long) addr < info->regstk.limit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) || (unsigned long) addr >= info->regstk.top)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) UNW_DPRINT(0, "unwind.%s: ignoring attempt to access register outside "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) "of rbs\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if ((unsigned long) nat_addr >= info->regstk.top)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) nat_addr = &info->sw->ar_rnat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) nat_mask = (1UL << ia64_rse_slot_num(addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (write) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (read_only(addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) *addr = *val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (*nat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) *nat_addr |= nat_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) *nat_addr &= ~nat_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if ((*nat_addr & nat_mask) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) *val = *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) *nat = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) *val = 0; /* if register is a NaT, *addr may contain kernel data! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) *nat = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) EXPORT_SYMBOL(unw_access_gr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) unw_access_br (struct unw_frame_info *info, int regnum, unsigned long *val, int write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) unsigned long *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) struct pt_regs *pt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) switch (regnum) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) /* scratch: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) case 0: pt = get_scratch_regs(info); addr = &pt->b0; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) case 6: pt = get_scratch_regs(info); addr = &pt->b6; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) case 7: pt = get_scratch_regs(info); addr = &pt->b7; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) /* preserved: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) case 1: case 2: case 3: case 4: case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) addr = *(&info->b1_loc + (regnum - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (!addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) addr = &info->sw->b1 + (regnum - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) UNW_DPRINT(0, "unwind.%s: trying to access non-existent b%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) __func__, regnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (read_only(addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) *addr = *val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) *val = *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) EXPORT_SYMBOL(unw_access_br);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) unw_access_fr (struct unw_frame_info *info, int regnum, struct ia64_fpreg *val, int write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) struct ia64_fpreg *addr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) struct pt_regs *pt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if ((unsigned) (regnum - 2) >= 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) UNW_DPRINT(0, "unwind.%s: trying to access non-existent f%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) __func__, regnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (regnum <= 5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) addr = *(&info->f2_loc + (regnum - 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (!addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) addr = &info->sw->f2 + (regnum - 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) } else if (regnum <= 15) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) if (regnum <= 11) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) pt = get_scratch_regs(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) addr = &pt->f6 + (regnum - 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) addr = &info->sw->f12 + (regnum - 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) } else if (regnum <= 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) addr = info->fr_loc[regnum - 16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (!addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) addr = &info->sw->f16 + (regnum - 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) struct task_struct *t = info->task;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) ia64_sync_fph(t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) ia64_flush_fph(t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) addr = t->thread.fph + (regnum - 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) if (write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (read_only(addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) *addr = *val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) *val = *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) EXPORT_SYMBOL(unw_access_fr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) unw_access_ar (struct unw_frame_info *info, int regnum, unsigned long *val, int write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) unsigned long *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) struct pt_regs *pt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) switch (regnum) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) case UNW_AR_BSP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) addr = info->bsp_loc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (!addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) addr = &info->sw->ar_bspstore;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) case UNW_AR_BSPSTORE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) addr = info->bspstore_loc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) if (!addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) addr = &info->sw->ar_bspstore;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) case UNW_AR_PFS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) addr = info->pfs_loc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (!addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) addr = &info->sw->ar_pfs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) case UNW_AR_RNAT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) addr = info->rnat_loc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (!addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) addr = &info->sw->ar_rnat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) case UNW_AR_UNAT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) addr = info->unat_loc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (!addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) addr = &info->sw->caller_unat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) case UNW_AR_LC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) addr = info->lc_loc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) if (!addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) addr = &info->sw->ar_lc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) case UNW_AR_EC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (!info->cfm_loc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) if (write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) *info->cfm_loc =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) (*info->cfm_loc & ~(0x3fUL << 52)) | ((*val & 0x3f) << 52);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) *val = (*info->cfm_loc >> 52) & 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) case UNW_AR_FPSR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) addr = info->fpsr_loc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (!addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) addr = &info->sw->ar_fpsr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) case UNW_AR_RSC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) pt = get_scratch_regs(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) addr = &pt->ar_rsc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) case UNW_AR_CCV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) pt = get_scratch_regs(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) addr = &pt->ar_ccv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) case UNW_AR_CSD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) pt = get_scratch_regs(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) addr = &pt->ar_csd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) case UNW_AR_SSD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) pt = get_scratch_regs(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) addr = &pt->ar_ssd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) UNW_DPRINT(0, "unwind.%s: trying to access non-existent ar%u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) __func__, regnum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (write) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if (read_only(addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) *addr = *val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) *val = *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) EXPORT_SYMBOL(unw_access_ar);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) unw_access_pr (struct unw_frame_info *info, unsigned long *val, int write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) unsigned long *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) addr = info->pr_loc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (!addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) addr = &info->sw->pr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (write) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (read_only(addr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) UNW_DPRINT(0, "unwind.%s: ignoring attempt to write read-only location\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) *addr = *val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) *val = *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) EXPORT_SYMBOL(unw_access_pr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) /* Routines to manipulate the state stack. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) push (struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) struct unw_reg_state *rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) rs = alloc_reg_state();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (!rs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) printk(KERN_ERR "unwind: cannot stack reg state!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) memcpy(rs, &sr->curr, sizeof(*rs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) sr->curr.next = rs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) pop (struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) struct unw_reg_state *rs = sr->curr.next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (!rs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) printk(KERN_ERR "unwind: stack underflow!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) memcpy(&sr->curr, rs, sizeof(*rs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) free_reg_state(rs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) /* Make a copy of the state stack. Non-recursive to avoid stack overflows. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) static struct unw_reg_state *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) dup_state_stack (struct unw_reg_state *rs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) struct unw_reg_state *copy, *prev = NULL, *first = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) while (rs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) copy = alloc_reg_state();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (!copy) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) printk(KERN_ERR "unwind.dup_state_stack: out of memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) memcpy(copy, rs, sizeof(*copy));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) prev->next = copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) first = copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) rs = rs->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) prev = copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) return first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) /* Free all stacked register states (but not RS itself). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) free_state_stack (struct unw_reg_state *rs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) struct unw_reg_state *p, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) for (p = rs->next; p != NULL; p = next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) next = p->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) free_reg_state(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) rs->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) /* Unwind decoder routines */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) static enum unw_register_index __attribute_const__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) decode_abreg (unsigned char abreg, int memory)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) switch (abreg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) case 0x04 ... 0x07: return UNW_REG_R4 + (abreg - 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) case 0x22 ... 0x25: return UNW_REG_F2 + (abreg - 0x22);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) case 0x30 ... 0x3f: return UNW_REG_F16 + (abreg - 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) case 0x41 ... 0x45: return UNW_REG_B1 + (abreg - 0x41);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) case 0x60: return UNW_REG_PR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) case 0x61: return UNW_REG_PSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) case 0x62: return memory ? UNW_REG_PRI_UNAT_MEM : UNW_REG_PRI_UNAT_GR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) case 0x63: return UNW_REG_RP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) case 0x64: return UNW_REG_BSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) case 0x65: return UNW_REG_BSPSTORE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) case 0x66: return UNW_REG_RNAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) case 0x67: return UNW_REG_UNAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) case 0x68: return UNW_REG_FPSR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) case 0x69: return UNW_REG_PFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) case 0x6a: return UNW_REG_LC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) UNW_DPRINT(0, "unwind.%s: bad abreg=0x%x\n", __func__, abreg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) return UNW_REG_LC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) set_reg (struct unw_reg_info *reg, enum unw_where where, int when, unsigned long val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) reg->val = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) reg->where = where;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) if (reg->when == UNW_WHEN_NEVER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) reg->when = when;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) alloc_spill_area (unsigned long *offp, unsigned long regsize,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) struct unw_reg_info *lo, struct unw_reg_info *hi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) struct unw_reg_info *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) for (reg = hi; reg >= lo; --reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) if (reg->where == UNW_WHERE_SPILL_HOME) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) reg->where = UNW_WHERE_PSPREL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) *offp -= regsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) reg->val = *offp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) spill_next_when (struct unw_reg_info **regp, struct unw_reg_info *lim, unw_word t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) struct unw_reg_info *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) for (reg = *regp; reg <= lim; ++reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) if (reg->where == UNW_WHERE_SPILL_HOME) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) reg->when = t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) *regp = reg + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) UNW_DPRINT(0, "unwind.%s: excess spill!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) finish_prologue (struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) struct unw_reg_info *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) unsigned long off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) * First, resolve implicit register save locations (see Section "11.4.2.3 Rules
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) * for Using Unwind Descriptors", rule 3):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) for (i = 0; i < (int) ARRAY_SIZE(unw.save_order); ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) reg = sr->curr.reg + unw.save_order[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) if (reg->where == UNW_WHERE_GR_SAVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) reg->where = UNW_WHERE_GR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) reg->val = sr->gr_save_loc++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) * Next, compute when the fp, general, and branch registers get
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) * saved. This must come before alloc_spill_area() because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) * we need to know which registers are spilled to their home
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) * locations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) if (sr->imask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) unsigned char kind, mask = 0, *cp = sr->imask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) int t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) static const unsigned char limit[3] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) UNW_REG_F31, UNW_REG_R7, UNW_REG_B5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) struct unw_reg_info *(regs[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) regs[0] = sr->curr.reg + UNW_REG_F2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) regs[1] = sr->curr.reg + UNW_REG_R4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) regs[2] = sr->curr.reg + UNW_REG_B1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) for (t = 0; t < sr->region_len; ++t) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if ((t & 3) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) mask = *cp++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) kind = (mask >> 2*(3-(t & 3))) & 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) if (kind > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) spill_next_when(®s[kind - 1], sr->curr.reg + limit[kind - 1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) sr->region_start + t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) * Next, lay out the memory stack spill area:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) if (sr->any_spills) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) off = sr->spill_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) alloc_spill_area(&off, 16, sr->curr.reg + UNW_REG_F2, sr->curr.reg + UNW_REG_F31);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) alloc_spill_area(&off, 8, sr->curr.reg + UNW_REG_B1, sr->curr.reg + UNW_REG_B5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) alloc_spill_area(&off, 8, sr->curr.reg + UNW_REG_R4, sr->curr.reg + UNW_REG_R7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) * Region header descriptors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) desc_prologue (int body, unw_word rlen, unsigned char mask, unsigned char grsave,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) int i, region_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) if (!(sr->in_body || sr->first_region))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) finish_prologue(sr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) sr->first_region = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) /* check if we're done: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) if (sr->when_target < sr->region_start + sr->region_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) sr->done = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) region_start = sr->region_start + sr->region_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) for (i = 0; i < sr->epilogue_count; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) pop(sr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) sr->epilogue_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) sr->epilogue_start = UNW_WHEN_NEVER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) sr->region_start = region_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) sr->region_len = rlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) sr->in_body = body;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) if (!body) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) push(sr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) for (i = 0; i < 4; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (mask & 0x8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) set_reg(sr->curr.reg + unw.save_order[i], UNW_WHERE_GR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) sr->region_start + sr->region_len - 1, grsave++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) mask <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) sr->gr_save_loc = grsave;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) sr->any_spills = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) sr->imask = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) sr->spill_offset = 0x10; /* default to psp+16 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) * Prologue descriptors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) desc_abi (unsigned char abi, unsigned char context, struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) if (abi == 3 && context == 'i') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) sr->flags |= UNW_FLAG_INTERRUPT_FRAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) UNW_DPRINT(3, "unwind.%s: interrupt frame\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) UNW_DPRINT(0, "unwind%s: ignoring unwabi(abi=0x%x,context=0x%x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) __func__, abi, context);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) desc_br_gr (unsigned char brmask, unsigned char gr, struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) for (i = 0; i < 5; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) if (brmask & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) set_reg(sr->curr.reg + UNW_REG_B1 + i, UNW_WHERE_GR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) sr->region_start + sr->region_len - 1, gr++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) brmask >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) desc_br_mem (unsigned char brmask, struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) for (i = 0; i < 5; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) if (brmask & 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) set_reg(sr->curr.reg + UNW_REG_B1 + i, UNW_WHERE_SPILL_HOME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) sr->region_start + sr->region_len - 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) sr->any_spills = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) brmask >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) desc_frgr_mem (unsigned char grmask, unw_word frmask, struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) for (i = 0; i < 4; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) if ((grmask & 1) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) set_reg(sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_SPILL_HOME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) sr->region_start + sr->region_len - 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) sr->any_spills = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) grmask >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) for (i = 0; i < 20; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) if ((frmask & 1) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) int base = (i < 4) ? UNW_REG_F2 : UNW_REG_F16 - 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) set_reg(sr->curr.reg + base + i, UNW_WHERE_SPILL_HOME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) sr->region_start + sr->region_len - 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) sr->any_spills = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) frmask >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) desc_fr_mem (unsigned char frmask, struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) for (i = 0; i < 4; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) if ((frmask & 1) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) set_reg(sr->curr.reg + UNW_REG_F2 + i, UNW_WHERE_SPILL_HOME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) sr->region_start + sr->region_len - 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) sr->any_spills = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) frmask >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) desc_gr_gr (unsigned char grmask, unsigned char gr, struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) for (i = 0; i < 4; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) if ((grmask & 1) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) set_reg(sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_GR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) sr->region_start + sr->region_len - 1, gr++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) grmask >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) desc_gr_mem (unsigned char grmask, struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) for (i = 0; i < 4; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) if ((grmask & 1) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) set_reg(sr->curr.reg + UNW_REG_R4 + i, UNW_WHERE_SPILL_HOME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) sr->region_start + sr->region_len - 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) sr->any_spills = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) grmask >>= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) desc_mem_stack_f (unw_word t, unw_word size, struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) set_reg(sr->curr.reg + UNW_REG_PSP, UNW_WHERE_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) sr->region_start + min_t(int, t, sr->region_len - 1), 16*size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) desc_mem_stack_v (unw_word t, struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) sr->curr.reg[UNW_REG_PSP].when = sr->region_start + min_t(int, t, sr->region_len - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) desc_reg_gr (unsigned char reg, unsigned char dst, struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) set_reg(sr->curr.reg + reg, UNW_WHERE_GR, sr->region_start + sr->region_len - 1, dst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) desc_reg_psprel (unsigned char reg, unw_word pspoff, struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) set_reg(sr->curr.reg + reg, UNW_WHERE_PSPREL, sr->region_start + sr->region_len - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) 0x10 - 4*pspoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) desc_reg_sprel (unsigned char reg, unw_word spoff, struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) set_reg(sr->curr.reg + reg, UNW_WHERE_SPREL, sr->region_start + sr->region_len - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) 4*spoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) desc_rp_br (unsigned char dst, struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) sr->return_link_reg = dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) desc_reg_when (unsigned char regnum, unw_word t, struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) struct unw_reg_info *reg = sr->curr.reg + regnum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) if (reg->where == UNW_WHERE_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) reg->where = UNW_WHERE_GR_SAVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) reg->when = sr->region_start + min_t(int, t, sr->region_len - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) desc_spill_base (unw_word pspoff, struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) sr->spill_offset = 0x10 - 4*pspoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) static inline unsigned char *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) desc_spill_mask (unsigned char *imaskp, struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) sr->imask = imaskp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) return imaskp + (2*sr->region_len + 7)/8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) * Body descriptors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) desc_epilogue (unw_word t, unw_word ecount, struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) sr->epilogue_start = sr->region_start + sr->region_len - 1 - t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) sr->epilogue_count = ecount + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) desc_copy_state (unw_word label, struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) struct unw_labeled_state *ls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) for (ls = sr->labeled_states; ls; ls = ls->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) if (ls->label == label) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) free_state_stack(&sr->curr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) memcpy(&sr->curr, &ls->saved_state, sizeof(sr->curr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) sr->curr.next = dup_state_stack(ls->saved_state.next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) printk(KERN_ERR "unwind: failed to find state labeled 0x%lx\n", label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) desc_label_state (unw_word label, struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) struct unw_labeled_state *ls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) ls = alloc_labeled_state();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) if (!ls) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) printk(KERN_ERR "unwind.desc_label_state(): out of memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) ls->label = label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) memcpy(&ls->saved_state, &sr->curr, sizeof(ls->saved_state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) ls->saved_state.next = dup_state_stack(sr->curr.next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) /* insert into list of labeled states: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) ls->next = sr->labeled_states;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) sr->labeled_states = ls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) * General descriptors.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) desc_is_active (unsigned char qp, unw_word t, struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) if (sr->when_target <= sr->region_start + min_t(int, t, sr->region_len - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) if (qp > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) if ((sr->pr_val & (1UL << qp)) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) sr->pr_mask |= (1UL << qp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) desc_restore_p (unsigned char qp, unw_word t, unsigned char abreg, struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) struct unw_reg_info *r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) if (!desc_is_active(qp, t, sr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) r = sr->curr.reg + decode_abreg(abreg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) r->where = UNW_WHERE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) r->when = UNW_WHEN_NEVER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) r->val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) desc_spill_reg_p (unsigned char qp, unw_word t, unsigned char abreg, unsigned char x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) unsigned char ytreg, struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) enum unw_where where = UNW_WHERE_GR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) struct unw_reg_info *r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) if (!desc_is_active(qp, t, sr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) if (x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) where = UNW_WHERE_BR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) else if (ytreg & 0x80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) where = UNW_WHERE_FR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) r = sr->curr.reg + decode_abreg(abreg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) r->where = where;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) r->when = sr->region_start + min_t(int, t, sr->region_len - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) r->val = (ytreg & 0x7f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) desc_spill_psprel_p (unsigned char qp, unw_word t, unsigned char abreg, unw_word pspoff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) struct unw_reg_info *r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) if (!desc_is_active(qp, t, sr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) r = sr->curr.reg + decode_abreg(abreg, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) r->where = UNW_WHERE_PSPREL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) r->when = sr->region_start + min_t(int, t, sr->region_len - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) r->val = 0x10 - 4*pspoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) desc_spill_sprel_p (unsigned char qp, unw_word t, unsigned char abreg, unw_word spoff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) struct unw_reg_info *r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) if (!desc_is_active(qp, t, sr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) r = sr->curr.reg + decode_abreg(abreg, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) r->where = UNW_WHERE_SPREL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) r->when = sr->region_start + min_t(int, t, sr->region_len - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) r->val = 4*spoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) #define UNW_DEC_BAD_CODE(code) printk(KERN_ERR "unwind: unknown code 0x%02x\n", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) * region headers:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) #define UNW_DEC_PROLOGUE_GR(fmt,r,m,gr,arg) desc_prologue(0,r,m,gr,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) #define UNW_DEC_PROLOGUE(fmt,b,r,arg) desc_prologue(b,r,0,32,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) * prologue descriptors:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) #define UNW_DEC_ABI(fmt,a,c,arg) desc_abi(a,c,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) #define UNW_DEC_BR_GR(fmt,b,g,arg) desc_br_gr(b,g,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) #define UNW_DEC_BR_MEM(fmt,b,arg) desc_br_mem(b,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) #define UNW_DEC_FRGR_MEM(fmt,g,f,arg) desc_frgr_mem(g,f,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) #define UNW_DEC_FR_MEM(fmt,f,arg) desc_fr_mem(f,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) #define UNW_DEC_GR_GR(fmt,m,g,arg) desc_gr_gr(m,g,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) #define UNW_DEC_GR_MEM(fmt,m,arg) desc_gr_mem(m,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) #define UNW_DEC_MEM_STACK_F(fmt,t,s,arg) desc_mem_stack_f(t,s,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) #define UNW_DEC_MEM_STACK_V(fmt,t,arg) desc_mem_stack_v(t,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) #define UNW_DEC_REG_GR(fmt,r,d,arg) desc_reg_gr(r,d,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) #define UNW_DEC_REG_PSPREL(fmt,r,o,arg) desc_reg_psprel(r,o,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) #define UNW_DEC_REG_SPREL(fmt,r,o,arg) desc_reg_sprel(r,o,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) #define UNW_DEC_REG_WHEN(fmt,r,t,arg) desc_reg_when(r,t,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) #define UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg) desc_reg_when(UNW_REG_PRI_UNAT_GR,t,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) #define UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg) desc_reg_when(UNW_REG_PRI_UNAT_MEM,t,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) #define UNW_DEC_PRIUNAT_GR(fmt,r,arg) desc_reg_gr(UNW_REG_PRI_UNAT_GR,r,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) #define UNW_DEC_PRIUNAT_PSPREL(fmt,o,arg) desc_reg_psprel(UNW_REG_PRI_UNAT_MEM,o,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) #define UNW_DEC_PRIUNAT_SPREL(fmt,o,arg) desc_reg_sprel(UNW_REG_PRI_UNAT_MEM,o,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) #define UNW_DEC_RP_BR(fmt,d,arg) desc_rp_br(d,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) #define UNW_DEC_SPILL_BASE(fmt,o,arg) desc_spill_base(o,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) #define UNW_DEC_SPILL_MASK(fmt,m,arg) (m = desc_spill_mask(m,arg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) * body descriptors:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) #define UNW_DEC_EPILOGUE(fmt,t,c,arg) desc_epilogue(t,c,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) #define UNW_DEC_COPY_STATE(fmt,l,arg) desc_copy_state(l,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) #define UNW_DEC_LABEL_STATE(fmt,l,arg) desc_label_state(l,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) * general unwind descriptors:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) #define UNW_DEC_SPILL_REG_P(f,p,t,a,x,y,arg) desc_spill_reg_p(p,t,a,x,y,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) #define UNW_DEC_SPILL_REG(f,t,a,x,y,arg) desc_spill_reg_p(0,t,a,x,y,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) #define UNW_DEC_SPILL_PSPREL_P(f,p,t,a,o,arg) desc_spill_psprel_p(p,t,a,o,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) #define UNW_DEC_SPILL_PSPREL(f,t,a,o,arg) desc_spill_psprel_p(0,t,a,o,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) #define UNW_DEC_SPILL_SPREL_P(f,p,t,a,o,arg) desc_spill_sprel_p(p,t,a,o,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) #define UNW_DEC_SPILL_SPREL(f,t,a,o,arg) desc_spill_sprel_p(0,t,a,o,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) #define UNW_DEC_RESTORE_P(f,p,t,a,arg) desc_restore_p(p,t,a,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) #define UNW_DEC_RESTORE(f,t,a,arg) desc_restore_p(0,t,a,arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) #include "unwind_decoder.c"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) /* Unwind scripts. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) static inline unw_hash_index_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) hash (unsigned long ip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) /* magic number = ((sqrt(5)-1)/2)*2^64 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) static const unsigned long hashmagic = 0x9e3779b97f4a7c16UL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) return (ip >> 4) * hashmagic >> (64 - UNW_LOG_HASH_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) static inline long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) cache_match (struct unw_script *script, unsigned long ip, unsigned long pr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) read_lock(&script->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) if (ip == script->ip && ((pr ^ script->pr_val) & script->pr_mask) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) /* keep the read lock... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) read_unlock(&script->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) static inline struct unw_script *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) script_lookup (struct unw_frame_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) struct unw_script *script = unw.cache + info->hint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) unsigned short index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) unsigned long ip, pr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) if (UNW_DEBUG_ON(0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) return NULL; /* Always regenerate scripts in debug mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) STAT(++unw.stat.cache.lookups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) ip = info->ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) pr = info->pr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) if (cache_match(script, ip, pr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) STAT(++unw.stat.cache.hinted_hits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) return script;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) index = unw.hash[hash(ip)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) if (index >= UNW_CACHE_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) script = unw.cache + index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) if (cache_match(script, ip, pr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) /* update hint; no locking required as single-word writes are atomic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) STAT(++unw.stat.cache.normal_hits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) unw.cache[info->prev_script].hint = script - unw.cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) return script;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) if (script->coll_chain >= UNW_HASH_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) script = unw.cache + script->coll_chain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) STAT(++unw.stat.cache.collision_chain_traversals);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) * On returning, a write lock for the SCRIPT is still being held.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) static inline struct unw_script *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) script_new (unsigned long ip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) struct unw_script *script, *prev, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) unw_hash_index_t index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) unsigned short head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) STAT(++unw.stat.script.news);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) * Can't (easily) use cmpxchg() here because of ABA problem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) * that is intrinsic in cmpxchg()...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) head = unw.lru_head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) script = unw.cache + head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) unw.lru_head = script->lru_chain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) * We'd deadlock here if we interrupted a thread that is holding a read lock on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) * script->lock. Thus, if the write_trylock() fails, we simply bail out. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) * alternative would be to disable interrupts whenever we hold a read-lock, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) * that seems silly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) if (!write_trylock(&script->lock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) /* re-insert script at the tail of the LRU chain: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) unw.cache[unw.lru_tail].lru_chain = head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) unw.lru_tail = head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) /* remove the old script from the hash table (if it's there): */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) if (script->ip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) index = hash(script->ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) tmp = unw.cache + unw.hash[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) prev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) if (tmp == script) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) if (prev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) prev->coll_chain = tmp->coll_chain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) unw.hash[index] = tmp->coll_chain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) prev = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) if (tmp->coll_chain >= UNW_CACHE_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) /* old script wasn't in the hash-table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) tmp = unw.cache + tmp->coll_chain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) /* enter new script in the hash table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) index = hash(ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) script->coll_chain = unw.hash[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) unw.hash[index] = script - unw.cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) script->ip = ip; /* set new IP while we're holding the locks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) STAT(if (script->coll_chain < UNW_CACHE_SIZE) ++unw.stat.script.collisions);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) script->flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) script->hint = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) script->count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) return script;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) script_finalize (struct unw_script *script, struct unw_state_record *sr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) script->pr_mask = sr->pr_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) script->pr_val = sr->pr_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) * We could down-grade our write-lock on script->lock here but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) * the rwlock API doesn't offer atomic lock downgrading, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) * we'll just keep the write-lock and release it later when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) * we're done using the script.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) script_emit (struct unw_script *script, struct unw_insn insn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) if (script->count >= UNW_MAX_SCRIPT_LEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) UNW_DPRINT(0, "unwind.%s: script exceeds maximum size of %u instructions!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) __func__, UNW_MAX_SCRIPT_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) script->insn[script->count++] = insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) emit_nat_info (struct unw_state_record *sr, int i, struct unw_script *script)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) struct unw_reg_info *r = sr->curr.reg + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) enum unw_insn_opcode opc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) struct unw_insn insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) unsigned long val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) switch (r->where) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) case UNW_WHERE_GR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) if (r->val >= 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) /* register got spilled to a stacked register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) opc = UNW_INSN_SETNAT_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) val = UNW_NAT_REGSTK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) /* register got spilled to a scratch register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) opc = UNW_INSN_SETNAT_MEMSTK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) case UNW_WHERE_FR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) opc = UNW_INSN_SETNAT_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) val = UNW_NAT_VAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) case UNW_WHERE_BR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) opc = UNW_INSN_SETNAT_TYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) val = UNW_NAT_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) case UNW_WHERE_PSPREL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) case UNW_WHERE_SPREL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) opc = UNW_INSN_SETNAT_MEMSTK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) UNW_DPRINT(0, "unwind.%s: don't know how to emit nat info for where = %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) __func__, r->where);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) insn.opc = opc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) insn.dst = unw.preg_index[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) insn.val = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) script_emit(script, insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) compile_reg (struct unw_state_record *sr, int i, struct unw_script *script)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) struct unw_reg_info *r = sr->curr.reg + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) enum unw_insn_opcode opc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) unsigned long val, rval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) struct unw_insn insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) long need_nat_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) if (r->where == UNW_WHERE_NONE || r->when >= sr->when_target)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) opc = UNW_INSN_MOVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) val = rval = r->val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) need_nat_info = (i >= UNW_REG_R4 && i <= UNW_REG_R7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) switch (r->where) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) case UNW_WHERE_GR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) if (rval >= 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) opc = UNW_INSN_MOVE_STACKED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) val = rval - 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) } else if (rval >= 4 && rval <= 7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) if (need_nat_info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) opc = UNW_INSN_MOVE2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) need_nat_info = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) val = unw.preg_index[UNW_REG_R4 + (rval - 4)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) } else if (rval == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) opc = UNW_INSN_MOVE_CONST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) /* register got spilled to a scratch register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) opc = UNW_INSN_MOVE_SCRATCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) val = pt_regs_off(rval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) case UNW_WHERE_FR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) if (rval <= 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) val = unw.preg_index[UNW_REG_F2 + (rval - 2)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) else if (rval >= 16 && rval <= 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) val = unw.preg_index[UNW_REG_F16 + (rval - 16)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) opc = UNW_INSN_MOVE_SCRATCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) if (rval <= 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) val = offsetof(struct pt_regs, f6) + 16*(rval - 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) UNW_DPRINT(0, "unwind.%s: kernel may not touch f%lu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) __func__, rval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) case UNW_WHERE_BR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) if (rval >= 1 && rval <= 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) val = unw.preg_index[UNW_REG_B1 + (rval - 1)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) opc = UNW_INSN_MOVE_SCRATCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) if (rval == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) val = offsetof(struct pt_regs, b0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) else if (rval == 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) val = offsetof(struct pt_regs, b6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) val = offsetof(struct pt_regs, b7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) case UNW_WHERE_SPREL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) opc = UNW_INSN_ADD_SP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) case UNW_WHERE_PSPREL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) opc = UNW_INSN_ADD_PSP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) UNW_DPRINT(0, "unwind%s: register %u has unexpected `where' value of %u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) __func__, i, r->where);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) insn.opc = opc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) insn.dst = unw.preg_index[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) insn.val = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) script_emit(script, insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) if (need_nat_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) emit_nat_info(sr, i, script);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) if (i == UNW_REG_PSP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) * info->psp must contain the _value_ of the previous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) * sp, not it's save location. We get this by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) * dereferencing the value we just stored in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) * info->psp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) insn.opc = UNW_INSN_LOAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) insn.dst = insn.val = unw.preg_index[UNW_REG_PSP];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) script_emit(script, insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) static inline const struct unw_table_entry *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) lookup (struct unw_table *table, unsigned long rel_ip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) const struct unw_table_entry *e = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) unsigned long lo, hi, mid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) /* do a binary search for right entry: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) for (lo = 0, hi = table->length; lo < hi; ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) mid = (lo + hi) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) e = &table->array[mid];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) if (rel_ip < e->start_offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) hi = mid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) else if (rel_ip >= e->end_offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) lo = mid + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) if (rel_ip < e->start_offset || rel_ip >= e->end_offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) return e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) * Build an unwind script that unwinds from state OLD_STATE to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) * entrypoint of the function that called OLD_STATE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) static inline struct unw_script *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) build_script (struct unw_frame_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) const struct unw_table_entry *e = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) struct unw_script *script = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) struct unw_labeled_state *ls, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) unsigned long ip = info->ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) struct unw_state_record sr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) struct unw_table *table, *prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) struct unw_reg_info *r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) struct unw_insn insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) u8 *dp, *desc_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) u64 hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) STAT(unsigned long start, parse_start;)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) STAT(++unw.stat.script.builds; start = ia64_get_itc());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) /* build state record */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) memset(&sr, 0, sizeof(sr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) for (r = sr.curr.reg; r < sr.curr.reg + UNW_NUM_REGS; ++r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) r->when = UNW_WHEN_NEVER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) sr.pr_val = info->pr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) UNW_DPRINT(3, "unwind.%s: ip 0x%lx\n", __func__, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) script = script_new(ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) if (!script) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) UNW_DPRINT(0, "unwind.%s: failed to create unwind script\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) STAT(unw.stat.script.build_time += ia64_get_itc() - start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) unw.cache[info->prev_script].hint = script - unw.cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) /* search the kernels and the modules' unwind tables for IP: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) STAT(parse_start = ia64_get_itc());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) prev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) for (table = unw.tables; table; table = table->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) if (ip >= table->start && ip < table->end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) * Leave the kernel unwind table at the very front,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) * lest moving it breaks some assumption elsewhere.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) * Otherwise, move the matching table to the second
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) * position in the list so that traversals can benefit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) * from commonality in backtrace paths.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) if (prev && prev != unw.tables) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) /* unw is safe - we're already spinlocked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) prev->next = table->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) table->next = unw.tables->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) unw.tables->next = table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) e = lookup(table, ip - table->segment_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) prev = table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) if (!e) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) /* no info, return default unwinder (leaf proc, no mem stack, no saved regs) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) UNW_DPRINT(1, "unwind.%s: no unwind info for ip=0x%lx (prev ip=0x%lx)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) __func__, ip, unw.cache[info->prev_script].ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) sr.curr.reg[UNW_REG_RP].where = UNW_WHERE_BR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) sr.curr.reg[UNW_REG_RP].when = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) sr.curr.reg[UNW_REG_RP].val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) compile_reg(&sr, UNW_REG_RP, script);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) script_finalize(script, &sr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) STAT(unw.stat.script.parse_time += ia64_get_itc() - parse_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) STAT(unw.stat.script.build_time += ia64_get_itc() - start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) return script;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) sr.when_target = (3*((ip & ~0xfUL) - (table->segment_base + e->start_offset))/16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) + (ip & 0xfUL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) hdr = *(u64 *) (table->segment_base + e->info_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) dp = (u8 *) (table->segment_base + e->info_offset + 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) desc_end = dp + 8*UNW_LENGTH(hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) while (!sr.done && dp < desc_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) dp = unw_decode(dp, sr.in_body, &sr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) if (sr.when_target > sr.epilogue_start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) * sp has been restored and all values on the memory stack below
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) * psp also have been restored.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) sr.curr.reg[UNW_REG_PSP].val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) sr.curr.reg[UNW_REG_PSP].where = UNW_WHERE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) sr.curr.reg[UNW_REG_PSP].when = UNW_WHEN_NEVER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) for (r = sr.curr.reg; r < sr.curr.reg + UNW_NUM_REGS; ++r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) if ((r->where == UNW_WHERE_PSPREL && r->val <= 0x10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) || r->where == UNW_WHERE_SPREL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) r->val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) r->where = UNW_WHERE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) r->when = UNW_WHEN_NEVER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) script->flags = sr.flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) * If RP did't get saved, generate entry for the return link
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) * register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) if (sr.curr.reg[UNW_REG_RP].when >= sr.when_target) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) sr.curr.reg[UNW_REG_RP].where = UNW_WHERE_BR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) sr.curr.reg[UNW_REG_RP].when = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) sr.curr.reg[UNW_REG_RP].val = sr.return_link_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) UNW_DPRINT(1, "unwind.%s: using default for rp at ip=0x%lx where=%d val=0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) __func__, ip, sr.curr.reg[UNW_REG_RP].where,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) sr.curr.reg[UNW_REG_RP].val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) #ifdef UNW_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) UNW_DPRINT(1, "unwind.%s: state record for func 0x%lx, t=%u:\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) __func__, table->segment_base + e->start_offset, sr.when_target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) for (r = sr.curr.reg; r < sr.curr.reg + UNW_NUM_REGS; ++r) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) if (r->where != UNW_WHERE_NONE || r->when != UNW_WHEN_NEVER) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) UNW_DPRINT(1, " %s <- ", unw.preg_name[r - sr.curr.reg]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) switch (r->where) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) case UNW_WHERE_GR: UNW_DPRINT(1, "r%lu", r->val); break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) case UNW_WHERE_FR: UNW_DPRINT(1, "f%lu", r->val); break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) case UNW_WHERE_BR: UNW_DPRINT(1, "b%lu", r->val); break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) case UNW_WHERE_SPREL: UNW_DPRINT(1, "[sp+0x%lx]", r->val); break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) case UNW_WHERE_PSPREL: UNW_DPRINT(1, "[psp+0x%lx]", r->val); break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) case UNW_WHERE_NONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) UNW_DPRINT(1, "%s+0x%lx", unw.preg_name[r - sr.curr.reg], r->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) UNW_DPRINT(1, "BADWHERE(%d)", r->where);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) UNW_DPRINT(1, "\t\t%d\n", r->when);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) STAT(unw.stat.script.parse_time += ia64_get_itc() - parse_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) /* translate state record into unwinder instructions: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) * First, set psp if we're dealing with a fixed-size frame;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) * subsequent instructions may depend on this value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) if (sr.when_target > sr.curr.reg[UNW_REG_PSP].when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) && (sr.curr.reg[UNW_REG_PSP].where == UNW_WHERE_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) && sr.curr.reg[UNW_REG_PSP].val != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) /* new psp is sp plus frame size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) insn.opc = UNW_INSN_ADD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) insn.dst = offsetof(struct unw_frame_info, psp)/8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) insn.val = sr.curr.reg[UNW_REG_PSP].val; /* frame size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) script_emit(script, insn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) /* determine where the primary UNaT is: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) if (sr.when_target < sr.curr.reg[UNW_REG_PRI_UNAT_GR].when)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) i = UNW_REG_PRI_UNAT_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) else if (sr.when_target < sr.curr.reg[UNW_REG_PRI_UNAT_MEM].when)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) i = UNW_REG_PRI_UNAT_GR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) else if (sr.curr.reg[UNW_REG_PRI_UNAT_MEM].when > sr.curr.reg[UNW_REG_PRI_UNAT_GR].when)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) i = UNW_REG_PRI_UNAT_MEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) i = UNW_REG_PRI_UNAT_GR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) compile_reg(&sr, i, script);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) for (i = UNW_REG_BSP; i < UNW_NUM_REGS; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) compile_reg(&sr, i, script);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) /* free labeled register states & stack: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) STAT(parse_start = ia64_get_itc());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) for (ls = sr.labeled_states; ls; ls = next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) next = ls->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) free_state_stack(&ls->saved_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) free_labeled_state(ls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) free_state_stack(&sr.curr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) STAT(unw.stat.script.parse_time += ia64_get_itc() - parse_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) script_finalize(script, &sr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) STAT(unw.stat.script.build_time += ia64_get_itc() - start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) return script;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) * Apply the unwinding actions represented by OPS and update SR to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) * reflect the state that existed upon entry to the function that this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) * unwinder represents.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) run_script (struct unw_script *script, struct unw_frame_info *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) struct unw_insn *ip, *limit, next_insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) unsigned long opc, dst, val, off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) unsigned long *s = (unsigned long *) state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) STAT(unsigned long start;)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) STAT(++unw.stat.script.runs; start = ia64_get_itc());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) state->flags = script->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) ip = script->insn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) limit = script->insn + script->count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) next_insn = *ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) while (ip++ < limit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) opc = next_insn.opc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) dst = next_insn.dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) val = next_insn.val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) next_insn = *ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) redo:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) switch (opc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) case UNW_INSN_ADD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) s[dst] += val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) case UNW_INSN_MOVE2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) if (!s[val])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) goto lazy_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) s[dst+1] = s[val+1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) s[dst] = s[val];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) case UNW_INSN_MOVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) if (!s[val])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) goto lazy_init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) s[dst] = s[val];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) case UNW_INSN_MOVE_SCRATCH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) if (state->pt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) s[dst] = (unsigned long) get_scratch_regs(state) + val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) s[dst] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) UNW_DPRINT(0, "unwind.%s: no state->pt, dst=%ld, val=%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) __func__, dst, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) case UNW_INSN_MOVE_CONST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) if (val == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) s[dst] = (unsigned long) &unw.r0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) s[dst] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) UNW_DPRINT(0, "unwind.%s: UNW_INSN_MOVE_CONST bad val=%ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) __func__, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) case UNW_INSN_MOVE_STACKED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) s[dst] = (unsigned long) ia64_rse_skip_regs((unsigned long *)state->bsp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) case UNW_INSN_ADD_PSP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) s[dst] = state->psp + val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) case UNW_INSN_ADD_SP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) s[dst] = state->sp + val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) case UNW_INSN_SETNAT_MEMSTK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) if (!state->pri_unat_loc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) state->pri_unat_loc = &state->sw->caller_unat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) /* register off. is a multiple of 8, so the least 3 bits (type) are 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) s[dst+1] = ((unsigned long) state->pri_unat_loc - s[dst]) | UNW_NAT_MEMSTK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) case UNW_INSN_SETNAT_TYPE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) s[dst+1] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) case UNW_INSN_LOAD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) #ifdef UNW_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) if ((s[val] & (local_cpu_data->unimpl_va_mask | 0x7)) != 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) || s[val] < TASK_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) UNW_DPRINT(0, "unwind.%s: rejecting bad psp=0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) __func__, s[val]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) s[dst] = *(unsigned long *) s[val];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) STAT(unw.stat.script.run_time += ia64_get_itc() - start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) lazy_init:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) off = unw.sw_off[val];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) s[val] = (unsigned long) state->sw + off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) if (off >= offsetof(struct switch_stack, r4) && off <= offsetof(struct switch_stack, r7))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) * We're initializing a general register: init NaT info, too. Note that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) * the offset is a multiple of 8 which gives us the 3 bits needed for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) * the type field.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) s[val+1] = (offsetof(struct switch_stack, ar_unat) - off) | UNW_NAT_MEMSTK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) goto redo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) find_save_locs (struct unw_frame_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) int have_write_lock = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) struct unw_script *scr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) unsigned long flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) if ((info->ip & (local_cpu_data->unimpl_va_mask | 0xf)) || info->ip < TASK_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) /* don't let obviously bad addresses pollute the cache */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) /* FIXME: should really be level 0 but it occurs too often. KAO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) UNW_DPRINT(1, "unwind.%s: rejecting bad ip=0x%lx\n", __func__, info->ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) info->rp_loc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) scr = script_lookup(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) if (!scr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) spin_lock_irqsave(&unw.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) scr = build_script(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) if (!scr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) spin_unlock_irqrestore(&unw.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) UNW_DPRINT(0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) "unwind.%s: failed to locate/build unwind script for ip %lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) __func__, info->ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) have_write_lock = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) info->hint = scr->hint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) info->prev_script = scr - unw.cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) run_script(scr, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) if (have_write_lock) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) write_unlock(&scr->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) spin_unlock_irqrestore(&unw.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) read_unlock(&scr->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) unw_valid(const struct unw_frame_info *info, unsigned long* p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) unsigned long loc = (unsigned long)p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) return (loc >= info->regstk.limit && loc < info->regstk.top) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) (loc >= info->memstk.top && loc < info->memstk.limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) unw_unwind (struct unw_frame_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) unsigned long prev_ip, prev_sp, prev_bsp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) unsigned long ip, pr, num_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) STAT(unsigned long start, flags;)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) STAT(local_irq_save(flags); ++unw.stat.api.unwinds; start = ia64_get_itc());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) prev_ip = info->ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) prev_sp = info->sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) prev_bsp = info->bsp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) /* validate the return IP pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) if (!unw_valid(info, info->rp_loc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) /* FIXME: should really be level 0 but it occurs too often. KAO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) UNW_DPRINT(1, "unwind.%s: failed to locate return link (ip=0x%lx)!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) __func__, info->ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) /* restore the ip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) ip = info->ip = *info->rp_loc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) if (ip < GATE_ADDR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) UNW_DPRINT(2, "unwind.%s: reached user-space (ip=0x%lx)\n", __func__, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) /* validate the previous stack frame pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) if (!unw_valid(info, info->pfs_loc)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) UNW_DPRINT(0, "unwind.%s: failed to locate ar.pfs!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) /* restore the cfm: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) info->cfm_loc = info->pfs_loc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) /* restore the bsp: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) pr = info->pr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) num_regs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) if ((info->flags & UNW_FLAG_INTERRUPT_FRAME)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) info->pt = info->sp + 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) if ((pr & (1UL << PRED_NON_SYSCALL)) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) num_regs = *info->cfm_loc & 0x7f; /* size of frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) info->pfs_loc =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) (unsigned long *) (info->pt + offsetof(struct pt_regs, ar_pfs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) UNW_DPRINT(3, "unwind.%s: interrupt_frame pt 0x%lx\n", __func__, info->pt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) num_regs = (*info->cfm_loc >> 7) & 0x7f; /* size of locals */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->bsp, -num_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) if (info->bsp < info->regstk.limit || info->bsp > info->regstk.top) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) UNW_DPRINT(0, "unwind.%s: bsp (0x%lx) out of range [0x%lx-0x%lx]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) __func__, info->bsp, info->regstk.limit, info->regstk.top);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) /* restore the sp: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) info->sp = info->psp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) if (info->sp < info->memstk.top || info->sp > info->memstk.limit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) UNW_DPRINT(0, "unwind.%s: sp (0x%lx) out of range [0x%lx-0x%lx]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) __func__, info->sp, info->memstk.top, info->memstk.limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) if (info->ip == prev_ip && info->sp == prev_sp && info->bsp == prev_bsp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) UNW_DPRINT(0, "unwind.%s: ip, sp, bsp unchanged; stopping here (ip=0x%lx)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) __func__, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) /* as we unwind, the saved ar.unat becomes the primary unat: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) info->pri_unat_loc = info->unat_loc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) /* finally, restore the predicates: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) unw_get_pr(info, &info->pr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) retval = find_save_locs(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) EXPORT_SYMBOL(unw_unwind);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) unw_unwind_to_user (struct unw_frame_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) unsigned long ip, sp, pr = info->pr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) unw_get_sp(info, &sp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) if ((long)((unsigned long)info->task + IA64_STK_OFFSET - sp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) < IA64_PT_REGS_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) UNW_DPRINT(0, "unwind.%s: ran off the top of the kernel stack\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) if (unw_is_intr_frame(info) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) (pr & (1UL << PRED_USER_STACK)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) if (unw_get_pr (info, &pr) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) unw_get_rp(info, &ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) UNW_DPRINT(0, "unwind.%s: failed to read "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) "predicate register (ip=0x%lx)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) __func__, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) } while (unw_unwind(info) >= 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) unw_get_ip(info, &ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) __func__, ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) EXPORT_SYMBOL(unw_unwind_to_user);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) init_frame_info (struct unw_frame_info *info, struct task_struct *t,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) struct switch_stack *sw, unsigned long stktop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) unsigned long rbslimit, rbstop, stklimit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) STAT(unsigned long start, flags;)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) STAT(local_irq_save(flags); ++unw.stat.api.inits; start = ia64_get_itc());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) * Subtle stuff here: we _could_ unwind through the switch_stack frame but we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) * don't want to do that because it would be slow as each preserved register would
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) * have to be processed. Instead, what we do here is zero out the frame info and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) * start the unwind process at the function that created the switch_stack frame.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) * When a preserved value in switch_stack needs to be accessed, run_script() will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) * initialize the appropriate pointer on demand.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) memset(info, 0, sizeof(*info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) rbslimit = (unsigned long) t + IA64_RBS_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) stklimit = (unsigned long) t + IA64_STK_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) rbstop = sw->ar_bspstore;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) if (rbstop > stklimit || rbstop < rbslimit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) rbstop = rbslimit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) if (stktop <= rbstop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) stktop = rbstop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) if (stktop > stklimit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) stktop = stklimit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) info->regstk.limit = rbslimit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) info->regstk.top = rbstop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) info->memstk.limit = stklimit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) info->memstk.top = stktop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) info->task = t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) info->sw = sw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) info->sp = info->psp = stktop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) info->pr = sw->pr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) UNW_DPRINT(3, "unwind.%s:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) " task 0x%lx\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) " rbs = [0x%lx-0x%lx)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) " stk = [0x%lx-0x%lx)\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) " pr 0x%lx\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) " sw 0x%lx\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) " sp 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) __func__, (unsigned long) t, rbslimit, rbstop, stktop, stklimit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) info->pr, (unsigned long) info->sw, info->sp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) STAT(unw.stat.api.init_time += ia64_get_itc() - start; local_irq_restore(flags));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) unw_init_frame_info (struct unw_frame_info *info, struct task_struct *t, struct switch_stack *sw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) unsigned long sol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) init_frame_info(info, t, sw, (unsigned long) (sw + 1) - 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) info->cfm_loc = &sw->ar_pfs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) sol = (*info->cfm_loc >> 7) & 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->regstk.top, -sol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) info->ip = sw->b0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) UNW_DPRINT(3, "unwind.%s:\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) " bsp 0x%lx\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) " sol 0x%lx\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) " ip 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) __func__, info->bsp, sol, info->ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) find_save_locs(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) EXPORT_SYMBOL(unw_init_frame_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) unw_init_from_blocked_task (struct unw_frame_info *info, struct task_struct *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) struct switch_stack *sw = (struct switch_stack *) (t->thread.ksp + 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) UNW_DPRINT(1, "unwind.%s\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) unw_init_frame_info(info, t, sw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) EXPORT_SYMBOL(unw_init_from_blocked_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) init_unwind_table (struct unw_table *table, const char *name, unsigned long segment_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) unsigned long gp, const void *table_start, const void *table_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) const struct unw_table_entry *start = table_start, *end = table_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) table->name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) table->segment_base = segment_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) table->gp = gp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) table->start = segment_base + start[0].start_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) table->end = segment_base + end[-1].end_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) table->array = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) table->length = end - start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) void *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) unw_add_unwind_table (const char *name, unsigned long segment_base, unsigned long gp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) const void *table_start, const void *table_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) const struct unw_table_entry *start = table_start, *end = table_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) struct unw_table *table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) if (end - start <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) UNW_DPRINT(0, "unwind.%s: ignoring attempt to insert empty unwind table\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) table = kmalloc(sizeof(*table), GFP_USER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) if (!table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) init_unwind_table(table, name, segment_base, gp, table_start, table_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) spin_lock_irqsave(&unw.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) /* keep kernel unwind table at the front (it's searched most commonly): */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) table->next = unw.tables->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) unw.tables->next = table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) spin_unlock_irqrestore(&unw.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) return table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) unw_remove_unwind_table (void *handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) struct unw_table *table, *prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) struct unw_script *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) long index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) if (!handle) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) UNW_DPRINT(0, "unwind.%s: ignoring attempt to remove non-existent unwind table\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) table = handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) if (table == &unw.kernel_table) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) UNW_DPRINT(0, "unwind.%s: sorry, freeing the kernel's unwind table is a "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) "no-can-do!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) spin_lock_irqsave(&unw.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) /* first, delete the table: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) for (prev = (struct unw_table *) &unw.tables; prev; prev = prev->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) if (prev->next == table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) if (!prev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) UNW_DPRINT(0, "unwind.%s: failed to find unwind table %p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) __func__, (void *) table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) spin_unlock_irqrestore(&unw.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) prev->next = table->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) spin_unlock_irqrestore(&unw.lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) /* next, remove hash table entries for this table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) for (index = 0; index < UNW_HASH_SIZE; ++index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) tmp = unw.cache + unw.hash[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) if (unw.hash[index] >= UNW_CACHE_SIZE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) || tmp->ip < table->start || tmp->ip >= table->end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) write_lock(&tmp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) if (tmp->ip >= table->start && tmp->ip < table->end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) unw.hash[index] = tmp->coll_chain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) tmp->ip = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) write_unlock(&tmp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) kfree(table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) static int __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) create_gate_table (void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) const struct unw_table_entry *entry, *start, *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) unsigned long *lp, segbase = GATE_ADDR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) size_t info_size, size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) char *info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) Elf64_Phdr *punw = NULL, *phdr = (Elf64_Phdr *) (GATE_ADDR + GATE_EHDR->e_phoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) for (i = 0; i < GATE_EHDR->e_phnum; ++i, ++phdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) if (phdr->p_type == PT_IA_64_UNWIND) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) punw = phdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) if (!punw) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) printk("%s: failed to find gate DSO's unwind table!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) start = (const struct unw_table_entry *) punw->p_vaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) end = (struct unw_table_entry *) ((char *) start + punw->p_memsz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) unw_add_unwind_table("linux-gate.so", segbase, 0, start, end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) for (entry = start; entry < end; ++entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) size += 3*8 + 8 + 8*UNW_LENGTH(*(u64 *) (segbase + entry->info_offset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) size += 8; /* reserve space for "end of table" marker */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) unw.gate_table = kmalloc(size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) if (!unw.gate_table) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) unw.gate_table_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) printk(KERN_ERR "%s: unable to create unwind data for gate page!\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) unw.gate_table_size = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) lp = unw.gate_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) info = (char *) unw.gate_table + size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) for (entry = start; entry < end; ++entry, lp += 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) info_size = 8 + 8*UNW_LENGTH(*(u64 *) (segbase + entry->info_offset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) info -= info_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) memcpy(info, (char *) segbase + entry->info_offset, info_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233) lp[0] = segbase + entry->start_offset; /* start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) lp[1] = segbase + entry->end_offset; /* end */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) lp[2] = info - (char *) unw.gate_table; /* info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) *lp = 0; /* end-of-table marker */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) __initcall(create_gate_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) void __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) unw_init (void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) extern char __gp[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) extern void unw_hash_index_t_is_too_narrow (void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) long i, off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) if (8*sizeof(unw_hash_index_t) < UNW_LOG_HASH_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) unw_hash_index_t_is_too_narrow();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) unw.sw_off[unw.preg_index[UNW_REG_PRI_UNAT_GR]] = SW(CALLER_UNAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) unw.sw_off[unw.preg_index[UNW_REG_BSPSTORE]] = SW(AR_BSPSTORE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) unw.sw_off[unw.preg_index[UNW_REG_PFS]] = SW(AR_PFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) unw.sw_off[unw.preg_index[UNW_REG_RP]] = SW(B0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) unw.sw_off[unw.preg_index[UNW_REG_UNAT]] = SW(CALLER_UNAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) unw.sw_off[unw.preg_index[UNW_REG_PR]] = SW(PR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) unw.sw_off[unw.preg_index[UNW_REG_LC]] = SW(AR_LC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) unw.sw_off[unw.preg_index[UNW_REG_FPSR]] = SW(AR_FPSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) for (i = UNW_REG_R4, off = SW(R4); i <= UNW_REG_R7; ++i, off += 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) unw.sw_off[unw.preg_index[i]] = off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) for (i = UNW_REG_B1, off = SW(B1); i <= UNW_REG_B5; ++i, off += 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) unw.sw_off[unw.preg_index[i]] = off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) for (i = UNW_REG_F2, off = SW(F2); i <= UNW_REG_F5; ++i, off += 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) unw.sw_off[unw.preg_index[i]] = off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) for (i = UNW_REG_F16, off = SW(F16); i <= UNW_REG_F31; ++i, off += 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) unw.sw_off[unw.preg_index[i]] = off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) for (i = 0; i < UNW_CACHE_SIZE; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) if (i > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) unw.cache[i].lru_chain = (i - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) unw.cache[i].coll_chain = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) rwlock_init(&unw.cache[i].lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) unw.lru_head = UNW_CACHE_SIZE - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) unw.lru_tail = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) init_unwind_table(&unw.kernel_table, "kernel", KERNEL_START, (unsigned long) __gp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) __start_unwind, __end_unwind);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) * DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) * This system call has been deprecated. The new and improved way to get
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) * at the kernel's unwind info is via the gate DSO. The address of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) * ELF header for this DSO is passed to user-level via AT_SYSINFO_EHDR.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) * DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292) * This system call copies the unwind data into the buffer pointed to by BUF and returns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) * the size of the unwind data. If BUF_SIZE is smaller than the size of the unwind data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) * or if BUF is NULL, nothing is copied, but the system call still returns the size of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) * unwind data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) * The first portion of the unwind data contains an unwind table and rest contains the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) * associated unwind info (in no particular order). The unwind table consists of a table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) * of entries of the form:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) * u64 start; (64-bit address of start of function)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) * u64 end; (64-bit address of start of function)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) * u64 info; (BUF-relative offset to unwind info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) * The end of the unwind table is indicated by an entry with a START address of zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) * Please see the IA-64 Software Conventions and Runtime Architecture manual for details
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) * on the format of the unwind info.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) * ERRORS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) * EFAULT BUF points outside your accessible address space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) asmlinkage long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) sys_getunwind (void __user *buf, size_t buf_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) if (buf && buf_size >= unw.gate_table_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) if (copy_to_user(buf, unw.gate_table, unw.gate_table_size) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) return unw.gate_table_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) }