1*b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
27f30491cSTony Luck #ifndef _ASM_IA64_UNWIND_H
37f30491cSTony Luck #define _ASM_IA64_UNWIND_H
47f30491cSTony Luck
57f30491cSTony Luck /*
67f30491cSTony Luck * Copyright (C) 1999-2000, 2003 Hewlett-Packard Co
77f30491cSTony Luck * David Mosberger-Tang <davidm@hpl.hp.com>
87f30491cSTony Luck *
97f30491cSTony Luck * A simple API for unwinding kernel stacks. This is used for
107f30491cSTony Luck * debugging and error reporting purposes. The kernel doesn't need
117f30491cSTony Luck * full-blown stack unwinding with all the bells and whitles, so there
127f30491cSTony Luck * is not much point in implementing the full IA-64 unwind API (though
137f30491cSTony Luck * it would of course be possible to implement the kernel API on top
147f30491cSTony Luck * of it).
157f30491cSTony Luck */
167f30491cSTony Luck
177f30491cSTony Luck struct task_struct; /* forward declaration */
187f30491cSTony Luck struct switch_stack; /* forward declaration */
197f30491cSTony Luck
207f30491cSTony Luck enum unw_application_register {
217f30491cSTony Luck UNW_AR_BSP,
227f30491cSTony Luck UNW_AR_BSPSTORE,
237f30491cSTony Luck UNW_AR_PFS,
247f30491cSTony Luck UNW_AR_RNAT,
257f30491cSTony Luck UNW_AR_UNAT,
267f30491cSTony Luck UNW_AR_LC,
277f30491cSTony Luck UNW_AR_EC,
287f30491cSTony Luck UNW_AR_FPSR,
297f30491cSTony Luck UNW_AR_RSC,
307f30491cSTony Luck UNW_AR_CCV,
317f30491cSTony Luck UNW_AR_CSD,
327f30491cSTony Luck UNW_AR_SSD
337f30491cSTony Luck };
347f30491cSTony Luck
357f30491cSTony Luck /*
367f30491cSTony Luck * The following declarations are private to the unwind
377f30491cSTony Luck * implementation:
387f30491cSTony Luck */
397f30491cSTony Luck
407f30491cSTony Luck struct unw_stack {
417f30491cSTony Luck unsigned long limit;
427f30491cSTony Luck unsigned long top;
437f30491cSTony Luck };
447f30491cSTony Luck
457f30491cSTony Luck #define UNW_FLAG_INTERRUPT_FRAME (1UL << 0)
467f30491cSTony Luck
477f30491cSTony Luck /*
487f30491cSTony Luck * No user of this module should every access this structure directly
497f30491cSTony Luck * as it is subject to change. It is declared here solely so we can
507f30491cSTony Luck * use automatic variables.
517f30491cSTony Luck */
527f30491cSTony Luck struct unw_frame_info {
537f30491cSTony Luck struct unw_stack regstk;
547f30491cSTony Luck struct unw_stack memstk;
557f30491cSTony Luck unsigned int flags;
567f30491cSTony Luck short hint;
577f30491cSTony Luck short prev_script;
587f30491cSTony Luck
597f30491cSTony Luck /* current frame info: */
607f30491cSTony Luck unsigned long bsp; /* backing store pointer value */
617f30491cSTony Luck unsigned long sp; /* stack pointer value */
627f30491cSTony Luck unsigned long psp; /* previous sp value */
637f30491cSTony Luck unsigned long ip; /* instruction pointer value */
647f30491cSTony Luck unsigned long pr; /* current predicate values */
657f30491cSTony Luck unsigned long *cfm_loc; /* cfm save location (or NULL) */
667f30491cSTony Luck unsigned long pt; /* struct pt_regs location */
677f30491cSTony Luck
687f30491cSTony Luck struct task_struct *task;
697f30491cSTony Luck struct switch_stack *sw;
707f30491cSTony Luck
717f30491cSTony Luck /* preserved state: */
727f30491cSTony Luck unsigned long *bsp_loc; /* previous bsp save location */
737f30491cSTony Luck unsigned long *bspstore_loc;
747f30491cSTony Luck unsigned long *pfs_loc;
757f30491cSTony Luck unsigned long *rnat_loc;
767f30491cSTony Luck unsigned long *rp_loc;
777f30491cSTony Luck unsigned long *pri_unat_loc;
787f30491cSTony Luck unsigned long *unat_loc;
797f30491cSTony Luck unsigned long *pr_loc;
807f30491cSTony Luck unsigned long *lc_loc;
817f30491cSTony Luck unsigned long *fpsr_loc;
827f30491cSTony Luck struct unw_ireg {
837f30491cSTony Luck unsigned long *loc;
847f30491cSTony Luck struct unw_ireg_nat {
857f30491cSTony Luck unsigned long type : 3; /* enum unw_nat_type */
867f30491cSTony Luck signed long off : 61; /* NaT word is at loc+nat.off */
877f30491cSTony Luck } nat;
887f30491cSTony Luck } r4, r5, r6, r7;
897f30491cSTony Luck unsigned long *b1_loc, *b2_loc, *b3_loc, *b4_loc, *b5_loc;
907f30491cSTony Luck struct ia64_fpreg *f2_loc, *f3_loc, *f4_loc, *f5_loc, *fr_loc[16];
917f30491cSTony Luck };
927f30491cSTony Luck
937f30491cSTony Luck /*
947f30491cSTony Luck * The official API follows below:
957f30491cSTony Luck */
967f30491cSTony Luck
977f30491cSTony Luck struct unw_table_entry {
987f30491cSTony Luck u64 start_offset;
997f30491cSTony Luck u64 end_offset;
1007f30491cSTony Luck u64 info_offset;
1017f30491cSTony Luck };
1027f30491cSTony Luck
1037f30491cSTony Luck /*
1047f30491cSTony Luck * Initialize unwind support.
1057f30491cSTony Luck */
1067f30491cSTony Luck extern void unw_init (void);
1077f30491cSTony Luck
1087f30491cSTony Luck extern void *unw_add_unwind_table (const char *name, unsigned long segment_base, unsigned long gp,
1097f30491cSTony Luck const void *table_start, const void *table_end);
1107f30491cSTony Luck
1117f30491cSTony Luck extern void unw_remove_unwind_table (void *handle);
1127f30491cSTony Luck
1137f30491cSTony Luck /*
1147f30491cSTony Luck * Prepare to unwind blocked task t.
1157f30491cSTony Luck */
1167f30491cSTony Luck extern void unw_init_from_blocked_task (struct unw_frame_info *info, struct task_struct *t);
1177f30491cSTony Luck
1187f30491cSTony Luck extern void unw_init_frame_info (struct unw_frame_info *info, struct task_struct *t,
1197f30491cSTony Luck struct switch_stack *sw);
1207f30491cSTony Luck
1217f30491cSTony Luck /*
1227f30491cSTony Luck * Prepare to unwind the currently running thread.
1237f30491cSTony Luck */
1247f30491cSTony Luck extern void unw_init_running (void (*callback)(struct unw_frame_info *info, void *arg), void *arg);
1257f30491cSTony Luck
1267f30491cSTony Luck /*
1277f30491cSTony Luck * Unwind to previous to frame. Returns 0 if successful, negative
1287f30491cSTony Luck * number in case of an error.
1297f30491cSTony Luck */
1307f30491cSTony Luck extern int unw_unwind (struct unw_frame_info *info);
1317f30491cSTony Luck
1327f30491cSTony Luck /*
1337f30491cSTony Luck * Unwind until the return pointer is in user-land (or until an error
1347f30491cSTony Luck * occurs). Returns 0 if successful, negative number in case of
1357f30491cSTony Luck * error.
1367f30491cSTony Luck */
1377f30491cSTony Luck extern int unw_unwind_to_user (struct unw_frame_info *info);
1387f30491cSTony Luck
1397f30491cSTony Luck #define unw_is_intr_frame(info) (((info)->flags & UNW_FLAG_INTERRUPT_FRAME) != 0)
1407f30491cSTony Luck
1417f30491cSTony Luck static inline int
unw_get_ip(struct unw_frame_info * info,unsigned long * valp)1427f30491cSTony Luck unw_get_ip (struct unw_frame_info *info, unsigned long *valp)
1437f30491cSTony Luck {
1447f30491cSTony Luck *valp = (info)->ip;
1457f30491cSTony Luck return 0;
1467f30491cSTony Luck }
1477f30491cSTony Luck
1487f30491cSTony Luck static inline int
unw_get_sp(struct unw_frame_info * info,unsigned long * valp)1497f30491cSTony Luck unw_get_sp (struct unw_frame_info *info, unsigned long *valp)
1507f30491cSTony Luck {
1517f30491cSTony Luck *valp = (info)->sp;
1527f30491cSTony Luck return 0;
1537f30491cSTony Luck }
1547f30491cSTony Luck
1557f30491cSTony Luck static inline int
unw_get_psp(struct unw_frame_info * info,unsigned long * valp)1567f30491cSTony Luck unw_get_psp (struct unw_frame_info *info, unsigned long *valp)
1577f30491cSTony Luck {
1587f30491cSTony Luck *valp = (info)->psp;
1597f30491cSTony Luck return 0;
1607f30491cSTony Luck }
1617f30491cSTony Luck
1627f30491cSTony Luck static inline int
unw_get_bsp(struct unw_frame_info * info,unsigned long * valp)1637f30491cSTony Luck unw_get_bsp (struct unw_frame_info *info, unsigned long *valp)
1647f30491cSTony Luck {
1657f30491cSTony Luck *valp = (info)->bsp;
1667f30491cSTony Luck return 0;
1677f30491cSTony Luck }
1687f30491cSTony Luck
1697f30491cSTony Luck static inline int
unw_get_cfm(struct unw_frame_info * info,unsigned long * valp)1707f30491cSTony Luck unw_get_cfm (struct unw_frame_info *info, unsigned long *valp)
1717f30491cSTony Luck {
1727f30491cSTony Luck *valp = *(info)->cfm_loc;
1737f30491cSTony Luck return 0;
1747f30491cSTony Luck }
1757f30491cSTony Luck
1767f30491cSTony Luck static inline int
unw_set_cfm(struct unw_frame_info * info,unsigned long val)1777f30491cSTony Luck unw_set_cfm (struct unw_frame_info *info, unsigned long val)
1787f30491cSTony Luck {
1797f30491cSTony Luck *(info)->cfm_loc = val;
1807f30491cSTony Luck return 0;
1817f30491cSTony Luck }
1827f30491cSTony Luck
1837f30491cSTony Luck static inline int
unw_get_rp(struct unw_frame_info * info,unsigned long * val)1847f30491cSTony Luck unw_get_rp (struct unw_frame_info *info, unsigned long *val)
1857f30491cSTony Luck {
1867f30491cSTony Luck if (!info->rp_loc)
1877f30491cSTony Luck return -1;
1887f30491cSTony Luck *val = *info->rp_loc;
1897f30491cSTony Luck return 0;
1907f30491cSTony Luck }
1917f30491cSTony Luck
1927f30491cSTony Luck extern int unw_access_gr (struct unw_frame_info *, int, unsigned long *, char *, int);
1937f30491cSTony Luck extern int unw_access_br (struct unw_frame_info *, int, unsigned long *, int);
1947f30491cSTony Luck extern int unw_access_fr (struct unw_frame_info *, int, struct ia64_fpreg *, int);
1957f30491cSTony Luck extern int unw_access_ar (struct unw_frame_info *, int, unsigned long *, int);
1967f30491cSTony Luck extern int unw_access_pr (struct unw_frame_info *, unsigned long *, int);
1977f30491cSTony Luck
1987f30491cSTony Luck static inline int
unw_set_gr(struct unw_frame_info * i,int n,unsigned long v,char nat)1997f30491cSTony Luck unw_set_gr (struct unw_frame_info *i, int n, unsigned long v, char nat)
2007f30491cSTony Luck {
2017f30491cSTony Luck return unw_access_gr(i, n, &v, &nat, 1);
2027f30491cSTony Luck }
2037f30491cSTony Luck
2047f30491cSTony Luck static inline int
unw_set_br(struct unw_frame_info * i,int n,unsigned long v)2057f30491cSTony Luck unw_set_br (struct unw_frame_info *i, int n, unsigned long v)
2067f30491cSTony Luck {
2077f30491cSTony Luck return unw_access_br(i, n, &v, 1);
2087f30491cSTony Luck }
2097f30491cSTony Luck
2107f30491cSTony Luck static inline int
unw_set_fr(struct unw_frame_info * i,int n,struct ia64_fpreg v)2117f30491cSTony Luck unw_set_fr (struct unw_frame_info *i, int n, struct ia64_fpreg v)
2127f30491cSTony Luck {
2137f30491cSTony Luck return unw_access_fr(i, n, &v, 1);
2147f30491cSTony Luck }
2157f30491cSTony Luck
2167f30491cSTony Luck static inline int
unw_set_ar(struct unw_frame_info * i,int n,unsigned long v)2177f30491cSTony Luck unw_set_ar (struct unw_frame_info *i, int n, unsigned long v)
2187f30491cSTony Luck {
2197f30491cSTony Luck return unw_access_ar(i, n, &v, 1);
2207f30491cSTony Luck }
2217f30491cSTony Luck
2227f30491cSTony Luck static inline int
unw_set_pr(struct unw_frame_info * i,unsigned long v)2237f30491cSTony Luck unw_set_pr (struct unw_frame_info *i, unsigned long v)
2247f30491cSTony Luck {
2257f30491cSTony Luck return unw_access_pr(i, &v, 1);
2267f30491cSTony Luck }
2277f30491cSTony Luck
2287f30491cSTony Luck #define unw_get_gr(i,n,v,nat) unw_access_gr(i,n,v,nat,0)
2297f30491cSTony Luck #define unw_get_br(i,n,v) unw_access_br(i,n,v,0)
2307f30491cSTony Luck #define unw_get_fr(i,n,v) unw_access_fr(i,n,v,0)
2317f30491cSTony Luck #define unw_get_ar(i,n,v) unw_access_ar(i,n,v,0)
2327f30491cSTony Luck #define unw_get_pr(i,v) unw_access_pr(i,v,0)
2337f30491cSTony Luck
2347f30491cSTony Luck #endif /* _ASM_UNWIND_H */
235