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