1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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
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
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;
85
86
87 struct unw_table *tables;
88
89
90 const unsigned char save_order[8];
91
92
93 unsigned short sw_off[sizeof(struct unw_frame_info) / 8];
94
95 unsigned short lru_head;
96 unsigned short lru_tail;
97
98
99 unsigned short preg_index[UNW_NUM_REGS];
100
101
102 struct unw_table kernel_table;
103
104
105 size_t gate_table_size;
106 unsigned long *gate_table;
107
108
109 unsigned short hash[UNW_HASH_SIZE];
110
111
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,
151 struct_offset(struct unw_frame_info, pri_unat_loc)/8,
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
208
209
210
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
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
252 if (write) {
253 if (*nat) {
254
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
263 *val = 0;
264 *nat = 1;
265 return 0;
266 }
267 }
268
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
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
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;
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
357 case 0: addr = &pt->b0; break;
358 case 6: addr = &pt->b6; break;
359 case 7: addr = &pt->b7; break;
360
361
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
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
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
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
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
667
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
679
680
681
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(®s[kind - 1], sr->curr.reg + limit[kind - 1],
701 sr->region_start + t);
702 }
703 }
704
705
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
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
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;
758 }
759}
760
761
762
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
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
971 ls->next = sr->labeled_states;
972 sr->labeled_states = ls;
973}
974
975
976
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
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
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
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
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
1110
1111static inline unw_hash_index_t
1112hash (unsigned long ip)
1113{
1114# define magic 0x9e3779b97f4a7c16
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
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
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
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
1181
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
1193
1194
1195
1196
1197
1198 write_lock(&script->lock);
1199
1200 spin_lock(&unw.lock);
1201 {
1202
1203 unw.cache[unw.lru_tail].lru_chain = head;
1204 unw.lru_tail = head;
1205
1206
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
1222 break;
1223 tmp = unw.cache + tmp->coll_chain;
1224 }
1225 }
1226
1227
1228 index = hash(ip);
1229 script->coll_chain = unw.hash[index];
1230 unw.hash[index] = script - unw.cache;
1231
1232 script->ip = ip;
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
1251
1252
1253
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
1280 opc = UNW_INSN_SETNAT_TYPE;
1281 val = UNW_NAT_REGSTK;
1282 } else
1283
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
1397
1398
1399
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
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
1431
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
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
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
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
1501
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
1520
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
1553
1554
1555
1556
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
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;
1565 script_emit(script, insn);
1566 }
1567
1568
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
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
1601
1602
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
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
1690
1691
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
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
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
1756
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
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
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;
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;
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
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
1805 info->pri_unat_loc = info->unat_loc;
1806
1807
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
1828
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
1848
1849
1850
1851
1852
1853
1854
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
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
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
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;
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;
2029 lp[1] = entry->end_offset - start + GATE_ADDR;
2030 lp[2] = info - (char *) unw.gate_table;
2031 }
2032 *lp = 0;
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
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
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