xref: /netbsd/sys/arch/ia64/unwind/stackframe.h (revision 6550d01e)
1 /*	$NetBSD: stackframe.h,v 1.2 2010/02/28 15:52:16 snj Exp $	*/
2 
3 /*
4  * Contributed to the NetBSD foundation by Cherry G. Mathew
5  */
6 
7 #define UNW_VER(x)           ((x) >> 48)
8 #define UNW_FLAG_MASK        0x0000ffff00000000L
9 #define UNW_FLAG_OSMASK      0x0000f00000000000L
10 #define UNW_FLAG_EHANDLER(x) ((x) & 0x0000000100000000L)
11 #define UNW_FLAG_UHANDLER(x) ((x) & 0x0000000200000000L)
12 #define UNW_LENGTH(x)        ((x) & 0x00000000ffffffffL)
13 
14 /* Unwind table entry. */
15 struct uwtable_ent {
16 	uint64_t start;
17 	uint64_t end;
18 	char *infoptr;
19 };
20 
21 
22 enum regrecord_type{
23 	UNSAVED,	/* Register contents live ( and therefore untouched ). */
24 	IMMED,		/* .offset field is the saved content. */
25 	BRREL,		/* Register saved in one of the Branch Registers. */
26 	GRREL,		/* Register saved in one of the Stacked GRs
27 			 * regstate.offset contains GR number (usually >= 32)
28 			 */
29 	SPREL,		/* Register saved on the memory stack frame.
30 			 * regstate.offset is in words; ie; location == (sp + 4 * spoff).
31 			 */
32 	PSPREL		/* Register saved on the memory stack frame but offseted via psp
33 			 * regstate.offset is in words; ie; location == (psp + 16 �– 4 * pspoff)
34 			 */
35 };
36 
37 
38 struct regstate {
39 	enum regrecord_type where;
40 	uint64_t when;
41 
42 #define INVALID -1UL	/* Indicates uninitialised offset value. */
43 	uint64_t offset;
44 };
45 
46 
47 /* A staterecord contains the net state of
48  * sequentially parsing unwind descriptors.
49  * The entry state of the current prologue region
50  * is the exit state of the previous region.
51  * We record info about registers we care about
52  * ie; just enough to re-construct an unwind frame,
53  * and ignore the rest.
54  * Initial state is where = UNSAVED for all .where fields.
55  */
56 
57 struct staterecord {
58 	struct regstate bsp;
59    	struct regstate psp;
60  	struct regstate rp;
61  	struct regstate pfs;
62 };
63 
64 /* The unwind frame is a simpler version of the trap frame
65  * and contains a subset of preserved registers, which are
66  * useful in unwinding an ia64 stack frame.
67  * Keep this in sync with the staterecord. See: stackframe.c:updateregs()
68  */
69 
70 struct unwind_frame {
71 	uint64_t		bsp;	/* Base of the RSE. !!! XXX: Stack Frame discontinuities */
72 	uint64_t		psp;	/* Mem stack (variable size) base. */
73 	uint64_t		rp;	/* Return Pointer */
74 	uint64_t		pfs;	/* Previous Frame size info */
75 
76 	/* Don't mirror anything below this line with struct staterecord */
77 	uint64_t		sp;
78 };
79 
80 
81 void buildrecordchain(uint64_t, struct recordchain *);
82 void initrecord(struct staterecord *);
83 void modifyrecord(struct staterecord *, struct recordchain *, uint64_t);
84 void pushrecord(struct staterecord *);
85 void poprecord(struct staterecord *, int);
86 void dump_staterecord(struct staterecord *);
87 void clonerecordstack(u_int);
88 void switchrecordstack(u_int);
89 
90 struct uwtable_ent *
91 get_unwind_table_entry(uint64_t);
92 void
93 patchunwindframe(struct unwind_frame *, uint64_t, uint64_t);
94 void
95 updateregs(struct unwind_frame *uwf, struct staterecord *, uint64_t) ;
96 struct uwtable_ent * get_unwind_table_entry(uint64_t ip);
97 
98 struct staterecord *
99 buildrecordstack(struct recordchain *, uint64_t);
100 void dump_recordchain(struct recordchain *);
101 
102 /* Convenience macros to decompose CFM & ar.pfs. */
103 #define	IA64_CFM_SOF(x)		((x) & 0x7f)
104 #define	IA64_CFM_SOL(x)		(((x) >> 7) & 0x7f)
105 #define	IA64_CFM_SOR(x)		(((x) >> 14) & 0x0f)
106 #define	IA64_CFM_RRB_GR(x)	(((x) >> 18) & 0x7f)
107 #define	IA64_CFM_RRB_FR(x)	(((x) >> 25) & 0x7f)
108 #define	IA64_CFM_RRB_PR(x)	(((x) >> 32) & 0x3f)
109 
110 #define IA64_RNATINDEX(x)	(((x) & 0x1f8) >> 3)
111 
112 /* Obeys Table 6:2 RSE Operation Instructions and State Modification */
113 
114 /* These functions adjust for RSE rnat saves to bsp in the forward and
115  * reverse directions respectively.
116  */
117 #define ia64_rnat_adjust ia64_bsp_adjust_call
118 
119 static __inline uint64_t
120 ia64_bsp_adjust_call(uint64_t bsp, int sol)
121 {
122 	bsp += ((sol + (IA64_RNATINDEX(bsp) + sol) / 63) << 3);
123 	return bsp;
124 }
125 
126 static __inline uint64_t
127 ia64_bsp_adjust_ret(uint64_t bsp, int sol)
128 {
129 	bsp -= ((sol + (62 - IA64_RNATINDEX(bsp) + sol) / 63) << 3);
130 	return bsp;
131 }
132 
133 static __inline uint64_t
134 ia64_getrse_gr(uint64_t bsp, uint64_t gr)
135 {
136 	bsp = ia64_bsp_adjust_call(bsp, gr);
137 	return *(uint64_t *) bsp;
138 }
139