• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /* SPDX-License-Identifier: GPL-2.0 */
2  #ifndef _ASM_IA64_UNWIND_H
3  #define _ASM_IA64_UNWIND_H
4  
5  /*
6   * Copyright (C) 1999-2000, 2003 Hewlett-Packard Co
7   *	David Mosberger-Tang <davidm@hpl.hp.com>
8   *
9   * A simple API for unwinding kernel stacks.  This is used for
10   * debugging and error reporting purposes.  The kernel doesn't need
11   * full-blown stack unwinding with all the bells and whitles, so there
12   * is not much point in implementing the full IA-64 unwind API (though
13   * it would of course be possible to implement the kernel API on top
14   * of it).
15   */
16  
17  struct task_struct;	/* forward declaration */
18  struct switch_stack;	/* forward declaration */
19  
20  enum unw_application_register {
21  	UNW_AR_BSP,
22  	UNW_AR_BSPSTORE,
23  	UNW_AR_PFS,
24  	UNW_AR_RNAT,
25  	UNW_AR_UNAT,
26  	UNW_AR_LC,
27  	UNW_AR_EC,
28  	UNW_AR_FPSR,
29  	UNW_AR_RSC,
30  	UNW_AR_CCV,
31  	UNW_AR_CSD,
32  	UNW_AR_SSD
33  };
34  
35  /*
36   * The following declarations are private to the unwind
37   * implementation:
38   */
39  
40  struct unw_stack {
41  	unsigned long limit;
42  	unsigned long top;
43  };
44  
45  #define UNW_FLAG_INTERRUPT_FRAME	(1UL << 0)
46  
47  /*
48   * No user of this module should every access this structure directly
49   * as it is subject to change.  It is declared here solely so we can
50   * use automatic variables.
51   */
52  struct unw_frame_info {
53  	struct unw_stack regstk;
54  	struct unw_stack memstk;
55  	unsigned int flags;
56  	short hint;
57  	short prev_script;
58  
59  	/* current frame info: */
60  	unsigned long bsp;		/* backing store pointer value */
61  	unsigned long sp;		/* stack pointer value */
62  	unsigned long psp;		/* previous sp value */
63  	unsigned long ip;		/* instruction pointer value */
64  	unsigned long pr;		/* current predicate values */
65  	unsigned long *cfm_loc;		/* cfm save location (or NULL) */
66  	unsigned long pt;		/* struct pt_regs location */
67  
68  	struct task_struct *task;
69  	struct switch_stack *sw;
70  
71  	/* preserved state: */
72  	unsigned long *bsp_loc;		/* previous bsp save location */
73  	unsigned long *bspstore_loc;
74  	unsigned long *pfs_loc;
75  	unsigned long *rnat_loc;
76  	unsigned long *rp_loc;
77  	unsigned long *pri_unat_loc;
78  	unsigned long *unat_loc;
79  	unsigned long *pr_loc;
80  	unsigned long *lc_loc;
81  	unsigned long *fpsr_loc;
82  	struct unw_ireg {
83  		unsigned long *loc;
84  		struct unw_ireg_nat {
85  			unsigned long type : 3;		/* enum unw_nat_type */
86  			signed long off : 61;		/* NaT word is at loc+nat.off */
87  		} nat;
88  	} r4, r5, r6, r7;
89  	unsigned long *b1_loc, *b2_loc, *b3_loc, *b4_loc, *b5_loc;
90  	struct ia64_fpreg *f2_loc, *f3_loc, *f4_loc, *f5_loc, *fr_loc[16];
91  };
92  
93  /*
94   * The official API follows below:
95   */
96  
97  struct unw_table_entry {
98  	u64 start_offset;
99  	u64 end_offset;
100  	u64 info_offset;
101  };
102  
103  /*
104   * Initialize unwind support.
105   */
106  extern void unw_init (void);
107  
108  extern void *unw_add_unwind_table (const char *name, unsigned long segment_base, unsigned long gp,
109  				   const void *table_start, const void *table_end);
110  
111  extern void unw_remove_unwind_table (void *handle);
112  
113  /*
114   * Prepare to unwind blocked task t.
115   */
116  extern void unw_init_from_blocked_task (struct unw_frame_info *info, struct task_struct *t);
117  
118  extern void unw_init_frame_info (struct unw_frame_info *info, struct task_struct *t,
119  				 struct switch_stack *sw);
120  
121  /*
122   * Prepare to unwind the currently running thread.
123   */
124  extern void unw_init_running (void (*callback)(struct unw_frame_info *info, void *arg), void *arg);
125  
126  /*
127   * Unwind to previous to frame.  Returns 0 if successful, negative
128   * number in case of an error.
129   */
130  extern int unw_unwind (struct unw_frame_info *info);
131  
132  /*
133   * Unwind until the return pointer is in user-land (or until an error
134   * occurs).  Returns 0 if successful, negative number in case of
135   * error.
136   */
137  extern int unw_unwind_to_user (struct unw_frame_info *info);
138  
139  #define unw_is_intr_frame(info)	(((info)->flags & UNW_FLAG_INTERRUPT_FRAME) != 0)
140  
141  static inline int
unw_get_ip(struct unw_frame_info * info,unsigned long * valp)142  unw_get_ip (struct unw_frame_info *info, unsigned long *valp)
143  {
144  	*valp = (info)->ip;
145  	return 0;
146  }
147  
148  static inline int
unw_get_sp(struct unw_frame_info * info,unsigned long * valp)149  unw_get_sp (struct unw_frame_info *info, unsigned long *valp)
150  {
151  	*valp = (info)->sp;
152  	return 0;
153  }
154  
155  static inline int
unw_get_psp(struct unw_frame_info * info,unsigned long * valp)156  unw_get_psp (struct unw_frame_info *info, unsigned long *valp)
157  {
158  	*valp = (info)->psp;
159  	return 0;
160  }
161  
162  static inline int
unw_get_bsp(struct unw_frame_info * info,unsigned long * valp)163  unw_get_bsp (struct unw_frame_info *info, unsigned long *valp)
164  {
165  	*valp = (info)->bsp;
166  	return 0;
167  }
168  
169  static inline int
unw_get_cfm(struct unw_frame_info * info,unsigned long * valp)170  unw_get_cfm (struct unw_frame_info *info, unsigned long *valp)
171  {
172  	*valp = *(info)->cfm_loc;
173  	return 0;
174  }
175  
176  static inline int
unw_set_cfm(struct unw_frame_info * info,unsigned long val)177  unw_set_cfm (struct unw_frame_info *info, unsigned long val)
178  {
179  	*(info)->cfm_loc = val;
180  	return 0;
181  }
182  
183  static inline int
unw_get_rp(struct unw_frame_info * info,unsigned long * val)184  unw_get_rp (struct unw_frame_info *info, unsigned long *val)
185  {
186  	if (!info->rp_loc)
187  		return -1;
188  	*val = *info->rp_loc;
189  	return 0;
190  }
191  
192  extern int unw_access_gr (struct unw_frame_info *, int, unsigned long *, char *, int);
193  extern int unw_access_br (struct unw_frame_info *, int, unsigned long *, int);
194  extern int unw_access_fr (struct unw_frame_info *, int, struct ia64_fpreg *, int);
195  extern int unw_access_ar (struct unw_frame_info *, int, unsigned long *, int);
196  extern int unw_access_pr (struct unw_frame_info *, unsigned long *, int);
197  
198  static inline int
unw_set_gr(struct unw_frame_info * i,int n,unsigned long v,char nat)199  unw_set_gr (struct unw_frame_info *i, int n, unsigned long v, char nat)
200  {
201  	return unw_access_gr(i, n, &v, &nat, 1);
202  }
203  
204  static inline int
unw_set_br(struct unw_frame_info * i,int n,unsigned long v)205  unw_set_br (struct unw_frame_info *i, int n, unsigned long v)
206  {
207  	return unw_access_br(i, n, &v, 1);
208  }
209  
210  static inline int
unw_set_fr(struct unw_frame_info * i,int n,struct ia64_fpreg v)211  unw_set_fr (struct unw_frame_info *i, int n, struct ia64_fpreg v)
212  {
213  	return unw_access_fr(i, n, &v, 1);
214  }
215  
216  static inline int
unw_set_ar(struct unw_frame_info * i,int n,unsigned long v)217  unw_set_ar (struct unw_frame_info *i, int n, unsigned long v)
218  {
219  	return unw_access_ar(i, n, &v, 1);
220  }
221  
222  static inline int
unw_set_pr(struct unw_frame_info * i,unsigned long v)223  unw_set_pr (struct unw_frame_info *i, unsigned long v)
224  {
225  	return unw_access_pr(i, &v, 1);
226  }
227  
228  #define unw_get_gr(i,n,v,nat)	unw_access_gr(i,n,v,nat,0)
229  #define unw_get_br(i,n,v)	unw_access_br(i,n,v,0)
230  #define unw_get_fr(i,n,v)	unw_access_fr(i,n,v,0)
231  #define unw_get_ar(i,n,v)	unw_access_ar(i,n,v,0)
232  #define unw_get_pr(i,v)		unw_access_pr(i,v,0)
233  
234  #endif /* _ASM_UNWIND_H */
235