~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/ia64/kernel/unwind.c

Version: ~ [ linux-5.1-rc1 ] ~ [ linux-5.0.3 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.30 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.107 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.164 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.176 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.136 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.63 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.39.4 ] ~ [ linux-2.6.38.8 ] ~ [ linux-2.6.37.6 ] ~ [ linux-2.6.36.4 ] ~ [ linux-2.6.35.14 ] ~ [ linux-2.6.34.15 ] ~ [ linux-2.6.33.20 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp