source: trunk/packages/xen-3.1/xen-3.1/xen/arch/ia64/linux-xen/unwind.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

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