Linux Audio

Check our new training course

Loading...
v5.9
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Kernel unwinding support
  4 *
  5 * (c) 2002-2004 Randolph Chung <tausq@debian.org>
  6 *
  7 * Derived partially from the IA64 implementation. The PA-RISC
  8 * Runtime Architecture Document is also a useful reference to
  9 * understand what is happening here
 10 */
 11
 12#include <linux/kernel.h>
 13#include <linux/init.h>
 14#include <linux/sched.h>
 15#include <linux/slab.h>
 16#include <linux/sort.h>
 17
 18#include <linux/uaccess.h>
 19#include <asm/assembly.h>
 20#include <asm/asm-offsets.h>
 21#include <asm/ptrace.h>
 22
 23#include <asm/unwind.h>
 24
 25/* #define DEBUG 1 */
 26#ifdef DEBUG
 27#define dbg(x...) pr_debug(x)
 28#else
 29#define dbg(x...)
 30#endif
 31
 32#define KERNEL_START (KERNEL_BINARY_TEXT_START)
 33
 34extern struct unwind_table_entry __start___unwind[];
 35extern struct unwind_table_entry __stop___unwind[];
 36
 37static DEFINE_SPINLOCK(unwind_lock);
 38/*
 39 * the kernel unwind block is not dynamically allocated so that
 40 * we can call unwind_init as early in the bootup process as 
 41 * possible (before the slab allocator is initialized)
 42 */
 43static struct unwind_table kernel_unwind_table __ro_after_init;
 44static LIST_HEAD(unwind_tables);
 45
 46static inline const struct unwind_table_entry *
 47find_unwind_entry_in_table(const struct unwind_table *table, unsigned long addr)
 48{
 49	const struct unwind_table_entry *e = NULL;
 50	unsigned long lo, hi, mid;
 51
 52	lo = 0; 
 53	hi = table->length - 1; 
 54	
 55	while (lo <= hi) {
 56		mid = (hi - lo) / 2 + lo;
 57		e = &table->table[mid];
 58		if (addr < e->region_start)
 59			hi = mid - 1;
 60		else if (addr > e->region_end)
 61			lo = mid + 1;
 62		else
 63			return e;
 64	}
 65
 66	return NULL;
 67}
 68
 69static const struct unwind_table_entry *
 70find_unwind_entry(unsigned long addr)
 71{
 72	struct unwind_table *table;
 73	const struct unwind_table_entry *e = NULL;
 74
 75	if (addr >= kernel_unwind_table.start && 
 76	    addr <= kernel_unwind_table.end)
 77		e = find_unwind_entry_in_table(&kernel_unwind_table, addr);
 78	else {
 79		unsigned long flags;
 80
 81		spin_lock_irqsave(&unwind_lock, flags);
 82		list_for_each_entry(table, &unwind_tables, list) {
 83			if (addr >= table->start && 
 84			    addr <= table->end)
 85				e = find_unwind_entry_in_table(table, addr);
 86			if (e) {
 87				/* Move-to-front to exploit common traces */
 88				list_move(&table->list, &unwind_tables);
 89				break;
 90			}
 91		}
 92		spin_unlock_irqrestore(&unwind_lock, flags);
 93	}
 94
 95	return e;
 96}
 97
 98static void
 99unwind_table_init(struct unwind_table *table, const char *name,
100		  unsigned long base_addr, unsigned long gp,
101		  void *table_start, void *table_end)
102{
103	struct unwind_table_entry *start = table_start;
104	struct unwind_table_entry *end = 
105		(struct unwind_table_entry *)table_end - 1;
106
107	table->name = name;
108	table->base_addr = base_addr;
109	table->gp = gp;
110	table->start = base_addr + start->region_start;
111	table->end = base_addr + end->region_end;
112	table->table = (struct unwind_table_entry *)table_start;
113	table->length = end - start + 1;
114	INIT_LIST_HEAD(&table->list);
115
116	for (; start <= end; start++) {
117		if (start < end && 
118		    start->region_end > (start+1)->region_start) {
119			pr_warn("Out of order unwind entry! %px and %px\n",
120				start, start+1);
121		}
122
123		start->region_start += base_addr;
124		start->region_end += base_addr;
125	}
126}
127
128static int cmp_unwind_table_entry(const void *a, const void *b)
129{
130	return ((const struct unwind_table_entry *)a)->region_start
131	     - ((const struct unwind_table_entry *)b)->region_start;
132}
133
134static void
135unwind_table_sort(struct unwind_table_entry *start,
136		  struct unwind_table_entry *finish)
137{
138	sort(start, finish - start, sizeof(struct unwind_table_entry),
139	     cmp_unwind_table_entry, NULL);
140}
141
142struct unwind_table *
143unwind_table_add(const char *name, unsigned long base_addr, 
144		 unsigned long gp,
145                 void *start, void *end)
146{
147	struct unwind_table *table;
148	unsigned long flags;
149	struct unwind_table_entry *s = (struct unwind_table_entry *)start;
150	struct unwind_table_entry *e = (struct unwind_table_entry *)end;
151
152	unwind_table_sort(s, e);
153
154	table = kmalloc(sizeof(struct unwind_table), GFP_USER);
155	if (table == NULL)
156		return NULL;
157	unwind_table_init(table, name, base_addr, gp, start, end);
158	spin_lock_irqsave(&unwind_lock, flags);
159	list_add_tail(&table->list, &unwind_tables);
160	spin_unlock_irqrestore(&unwind_lock, flags);
161
162	return table;
163}
164
165void unwind_table_remove(struct unwind_table *table)
166{
167	unsigned long flags;
168
169	spin_lock_irqsave(&unwind_lock, flags);
170	list_del(&table->list);
171	spin_unlock_irqrestore(&unwind_lock, flags);
172
173	kfree(table);
174}
175
176/* Called from setup_arch to import the kernel unwind info */
177int __init unwind_init(void)
178{
179	long start, stop;
180	register unsigned long gp __asm__ ("r27");
181
182	start = (long)&__start___unwind[0];
183	stop = (long)&__stop___unwind[0];
184
185	dbg("unwind_init: start = 0x%lx, end = 0x%lx, entries = %lu\n",
186	    start, stop,
187	    (stop - start) / sizeof(struct unwind_table_entry));
188
189	unwind_table_init(&kernel_unwind_table, "kernel", KERNEL_START,
190			  gp, 
191			  &__start___unwind[0], &__stop___unwind[0]);
192#if 0
193	{
194		int i;
195		for (i = 0; i < 10; i++)
196		{
197			printk("region 0x%x-0x%x\n", 
198				__start___unwind[i].region_start, 
199				__start___unwind[i].region_end);
200		}
201	}
202#endif
203	return 0;
204}
205
206static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int frame_size)
207{
208	/*
209	 * We have to use void * instead of a function pointer, because
210	 * function pointers aren't a pointer to the function on 64-bit.
211	 * Make them const so the compiler knows they live in .text
212	 * Note: We could use dereference_kernel_function_descriptor()
213	 * instead but we want to keep it simple here.
214	 */
215	extern void * const handle_interruption;
216	extern void * const ret_from_kernel_thread;
217	extern void * const syscall_exit;
218	extern void * const intr_return;
219	extern void * const _switch_to_ret;
220#ifdef CONFIG_IRQSTACKS
221	extern void * const _call_on_stack;
222#endif /* CONFIG_IRQSTACKS */
223
224	if (pc == (unsigned long) &handle_interruption) {
225		struct pt_regs *regs = (struct pt_regs *)(info->sp - frame_size - PT_SZ_ALGN);
226		dbg("Unwinding through handle_interruption()\n");
227		info->prev_sp = regs->gr[30];
228		info->prev_ip = regs->iaoq[0];
229		return 1;
230	}
231
232	if (pc == (unsigned long) &ret_from_kernel_thread ||
233	    pc == (unsigned long) &syscall_exit) {
234		info->prev_sp = info->prev_ip = 0;
235		return 1;
236	}
237
238	if (pc == (unsigned long) &intr_return) {
239		struct pt_regs *regs;
240
241		dbg("Found intr_return()\n");
242		regs = (struct pt_regs *)(info->sp - PT_SZ_ALGN);
243		info->prev_sp = regs->gr[30];
244		info->prev_ip = regs->iaoq[0];
245		info->rp = regs->gr[2];
246		return 1;
247	}
248
249	if (pc == (unsigned long) &_switch_to_ret) {
250		info->prev_sp = info->sp - CALLEE_SAVE_FRAME_SIZE;
251		info->prev_ip = *(unsigned long *)(info->prev_sp - RP_OFFSET);
252		return 1;
253	}
254
255#ifdef CONFIG_IRQSTACKS
256	if (pc == (unsigned long) &_call_on_stack) {
257		info->prev_sp = *(unsigned long *)(info->sp - FRAME_SIZE - REG_SZ);
258		info->prev_ip = *(unsigned long *)(info->sp - FRAME_SIZE - RP_OFFSET);
259		return 1;
260	}
261#endif
262
263	return 0;
264}
265
266static void unwind_frame_regs(struct unwind_frame_info *info)
267{
268	const struct unwind_table_entry *e;
269	unsigned long npc;
270	unsigned int insn;
271	long frame_size = 0;
272	int looking_for_rp, rpoffset = 0;
273
274	e = find_unwind_entry(info->ip);
275	if (e == NULL) {
276		unsigned long sp;
277
278		dbg("Cannot find unwind entry for %pS; forced unwinding\n",
279			(void *) info->ip);
280
281		/* Since we are doing the unwinding blind, we don't know if
282		   we are adjusting the stack correctly or extracting the rp
283		   correctly. The rp is checked to see if it belongs to the
284		   kernel text section, if not we assume we don't have a 
285		   correct stack frame and we continue to unwind the stack.
286		   This is not quite correct, and will fail for loadable
287		   modules. */
288		sp = info->sp & ~63;
289		do {
290			unsigned long tmp;
291
292			info->prev_sp = sp - 64;
293			info->prev_ip = 0;
294
295			/* The stack is at the end inside the thread_union
296			 * struct. If we reach data, we have reached the
297			 * beginning of the stack and should stop unwinding. */
298			if (info->prev_sp >= (unsigned long) task_thread_info(info->t) &&
299			    info->prev_sp < ((unsigned long) task_thread_info(info->t)
300						+ THREAD_SZ_ALGN)) {
301				info->prev_sp = 0;
302				break;
303			}
304
305			if (get_user(tmp, (unsigned long *)(info->prev_sp - RP_OFFSET))) 
306				break;
307			info->prev_ip = tmp;
308			sp = info->prev_sp;
309		} while (!kernel_text_address(info->prev_ip));
310
311		info->rp = 0;
312
313		dbg("analyzing func @ %lx with no unwind info, setting "
314		    "prev_sp=%lx prev_ip=%lx\n", info->ip, 
315		    info->prev_sp, info->prev_ip);
316	} else {
317		dbg("e->start = 0x%x, e->end = 0x%x, Save_SP = %d, "
318		    "Save_RP = %d, Millicode = %d size = %u\n", 
319		    e->region_start, e->region_end, e->Save_SP, e->Save_RP, 
320		    e->Millicode, e->Total_frame_size);
321
322		looking_for_rp = e->Save_RP;
323
324		for (npc = e->region_start; 
325		     (frame_size < (e->Total_frame_size << 3) || 
326		      looking_for_rp) && 
327		     npc < info->ip; 
328		     npc += 4) {
329
330			insn = *(unsigned int *)npc;
331
332			if ((insn & 0xffffc001) == 0x37de0000 ||
333			    (insn & 0xffe00001) == 0x6fc00000) {
334				/* ldo X(sp), sp, or stwm X,D(sp) */
335				frame_size += (insn & 0x3fff) >> 1;
336				dbg("analyzing func @ %lx, insn=%08x @ "
337				    "%lx, frame_size = %ld\n", info->ip,
338				    insn, npc, frame_size);
339			} else if ((insn & 0xffe00009) == 0x73c00008) {
340				/* std,ma X,D(sp) */
341				frame_size += ((insn >> 4) & 0x3ff) << 3;
342				dbg("analyzing func @ %lx, insn=%08x @ "
343				    "%lx, frame_size = %ld\n", info->ip,
344				    insn, npc, frame_size);
345			} else if (insn == 0x6bc23fd9) { 
346				/* stw rp,-20(sp) */
347				rpoffset = 20;
348				looking_for_rp = 0;
349				dbg("analyzing func @ %lx, insn=stw rp,"
350				    "-20(sp) @ %lx\n", info->ip, npc);
351			} else if (insn == 0x0fc212c1) {
352				/* std rp,-16(sr0,sp) */
353				rpoffset = 16;
354				looking_for_rp = 0;
355				dbg("analyzing func @ %lx, insn=std rp,"
356				    "-16(sp) @ %lx\n", info->ip, npc);
357			}
358		}
359
360		if (frame_size > e->Total_frame_size << 3)
361			frame_size = e->Total_frame_size << 3;
362
363		if (!unwind_special(info, e->region_start, frame_size)) {
364			info->prev_sp = info->sp - frame_size;
365			if (e->Millicode)
366				info->rp = info->r31;
367			else if (rpoffset)
368				info->rp = *(unsigned long *)(info->prev_sp - rpoffset);
369			info->prev_ip = info->rp;
370			info->rp = 0;
371		}
372
373		dbg("analyzing func @ %lx, setting prev_sp=%lx "
374		    "prev_ip=%lx npc=%lx\n", info->ip, info->prev_sp, 
375		    info->prev_ip, npc);
376	}
377}
378
379void unwind_frame_init(struct unwind_frame_info *info, struct task_struct *t, 
380		       struct pt_regs *regs)
381{
382	memset(info, 0, sizeof(struct unwind_frame_info));
383	info->t = t;
384	info->sp = regs->gr[30];
385	info->ip = regs->iaoq[0];
386	info->rp = regs->gr[2];
387	info->r31 = regs->gr[31];
388
389	dbg("(%d) Start unwind from sp=%08lx ip=%08lx\n", 
390	    t ? (int)t->pid : -1, info->sp, info->ip);
391}
392
393void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct task_struct *t)
394{
395	struct pt_regs *r = &t->thread.regs;
396	struct pt_regs *r2;
397
398	r2 = kmalloc(sizeof(struct pt_regs), GFP_ATOMIC);
399	if (!r2)
400		return;
401	*r2 = *r;
402	r2->gr[30] = r->ksp;
403	r2->iaoq[0] = r->kpc;
404	unwind_frame_init(info, t, r2);
405	kfree(r2);
406}
407
408#define get_parisc_stackpointer() ({ \
409	unsigned long sp; \
410	__asm__("copy %%r30, %0" : "=r"(sp)); \
411	(sp); \
412})
413
414void unwind_frame_init_task(struct unwind_frame_info *info,
415	struct task_struct *task, struct pt_regs *regs)
416{
417	task = task ? task : current;
418
419	if (task == current) {
420		struct pt_regs r;
421
422		if (!regs) {
423			memset(&r, 0, sizeof(r));
424			r.iaoq[0] =  _THIS_IP_;
425			r.gr[2] = _RET_IP_;
426			r.gr[30] = get_parisc_stackpointer();
427			regs = &r;
428		}
429		unwind_frame_init(info, task, regs);
430	} else {
431		unwind_frame_init_from_blocked_task(info, task);
432	}
433}
434
435int unwind_once(struct unwind_frame_info *next_frame)
436{
437	unwind_frame_regs(next_frame);
438
439	if (next_frame->prev_sp == 0 ||
440	    next_frame->prev_ip == 0)
441		return -1;
442
443	next_frame->sp = next_frame->prev_sp;
444	next_frame->ip = next_frame->prev_ip;
445	next_frame->prev_sp = 0;
446	next_frame->prev_ip = 0;
447
448	dbg("(%d) Continue unwind to sp=%08lx ip=%08lx\n", 
449	    next_frame->t ? (int)next_frame->t->pid : -1, 
450	    next_frame->sp, next_frame->ip);
451
452	return 0;
453}
454
455int unwind_to_user(struct unwind_frame_info *info)
456{
457	int ret;
458	
459	do {
460		ret = unwind_once(info);
461	} while (!ret && !(info->ip & 3));
462
463	return ret;
464}
465
466unsigned long return_address(unsigned int level)
467{
468	struct unwind_frame_info info;
469
470	/* initialize unwind info */
471	unwind_frame_init_task(&info, current, NULL);
472
473	/* unwind stack */
474	level += 2;
475	do {
476		if (unwind_once(&info) < 0 || info.ip == 0)
477			return 0;
478		if (!kernel_text_address(info.ip))
479			return 0;
480	} while (info.ip && level--);
481
482	return info.ip;
483}
v5.4
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Kernel unwinding support
  4 *
  5 * (c) 2002-2004 Randolph Chung <tausq@debian.org>
  6 *
  7 * Derived partially from the IA64 implementation. The PA-RISC
  8 * Runtime Architecture Document is also a useful reference to
  9 * understand what is happening here
 10 */
 11
 12#include <linux/kernel.h>
 13#include <linux/init.h>
 14#include <linux/sched.h>
 15#include <linux/slab.h>
 16#include <linux/sort.h>
 17
 18#include <linux/uaccess.h>
 19#include <asm/assembly.h>
 20#include <asm/asm-offsets.h>
 21#include <asm/ptrace.h>
 22
 23#include <asm/unwind.h>
 24
 25/* #define DEBUG 1 */
 26#ifdef DEBUG
 27#define dbg(x...) pr_debug(x)
 28#else
 29#define dbg(x...)
 30#endif
 31
 32#define KERNEL_START (KERNEL_BINARY_TEXT_START)
 33
 34extern struct unwind_table_entry __start___unwind[];
 35extern struct unwind_table_entry __stop___unwind[];
 36
 37static DEFINE_SPINLOCK(unwind_lock);
 38/*
 39 * the kernel unwind block is not dynamically allocated so that
 40 * we can call unwind_init as early in the bootup process as 
 41 * possible (before the slab allocator is initialized)
 42 */
 43static struct unwind_table kernel_unwind_table __ro_after_init;
 44static LIST_HEAD(unwind_tables);
 45
 46static inline const struct unwind_table_entry *
 47find_unwind_entry_in_table(const struct unwind_table *table, unsigned long addr)
 48{
 49	const struct unwind_table_entry *e = NULL;
 50	unsigned long lo, hi, mid;
 51
 52	lo = 0; 
 53	hi = table->length - 1; 
 54	
 55	while (lo <= hi) {
 56		mid = (hi - lo) / 2 + lo;
 57		e = &table->table[mid];
 58		if (addr < e->region_start)
 59			hi = mid - 1;
 60		else if (addr > e->region_end)
 61			lo = mid + 1;
 62		else
 63			return e;
 64	}
 65
 66	return NULL;
 67}
 68
 69static const struct unwind_table_entry *
 70find_unwind_entry(unsigned long addr)
 71{
 72	struct unwind_table *table;
 73	const struct unwind_table_entry *e = NULL;
 74
 75	if (addr >= kernel_unwind_table.start && 
 76	    addr <= kernel_unwind_table.end)
 77		e = find_unwind_entry_in_table(&kernel_unwind_table, addr);
 78	else {
 79		unsigned long flags;
 80
 81		spin_lock_irqsave(&unwind_lock, flags);
 82		list_for_each_entry(table, &unwind_tables, list) {
 83			if (addr >= table->start && 
 84			    addr <= table->end)
 85				e = find_unwind_entry_in_table(table, addr);
 86			if (e) {
 87				/* Move-to-front to exploit common traces */
 88				list_move(&table->list, &unwind_tables);
 89				break;
 90			}
 91		}
 92		spin_unlock_irqrestore(&unwind_lock, flags);
 93	}
 94
 95	return e;
 96}
 97
 98static void
 99unwind_table_init(struct unwind_table *table, const char *name,
100		  unsigned long base_addr, unsigned long gp,
101		  void *table_start, void *table_end)
102{
103	struct unwind_table_entry *start = table_start;
104	struct unwind_table_entry *end = 
105		(struct unwind_table_entry *)table_end - 1;
106
107	table->name = name;
108	table->base_addr = base_addr;
109	table->gp = gp;
110	table->start = base_addr + start->region_start;
111	table->end = base_addr + end->region_end;
112	table->table = (struct unwind_table_entry *)table_start;
113	table->length = end - start + 1;
114	INIT_LIST_HEAD(&table->list);
115
116	for (; start <= end; start++) {
117		if (start < end && 
118		    start->region_end > (start+1)->region_start) {
119			pr_warn("Out of order unwind entry! %px and %px\n",
120				start, start+1);
121		}
122
123		start->region_start += base_addr;
124		start->region_end += base_addr;
125	}
126}
127
128static int cmp_unwind_table_entry(const void *a, const void *b)
129{
130	return ((const struct unwind_table_entry *)a)->region_start
131	     - ((const struct unwind_table_entry *)b)->region_start;
132}
133
134static void
135unwind_table_sort(struct unwind_table_entry *start,
136		  struct unwind_table_entry *finish)
137{
138	sort(start, finish - start, sizeof(struct unwind_table_entry),
139	     cmp_unwind_table_entry, NULL);
140}
141
142struct unwind_table *
143unwind_table_add(const char *name, unsigned long base_addr, 
144		 unsigned long gp,
145                 void *start, void *end)
146{
147	struct unwind_table *table;
148	unsigned long flags;
149	struct unwind_table_entry *s = (struct unwind_table_entry *)start;
150	struct unwind_table_entry *e = (struct unwind_table_entry *)end;
151
152	unwind_table_sort(s, e);
153
154	table = kmalloc(sizeof(struct unwind_table), GFP_USER);
155	if (table == NULL)
156		return NULL;
157	unwind_table_init(table, name, base_addr, gp, start, end);
158	spin_lock_irqsave(&unwind_lock, flags);
159	list_add_tail(&table->list, &unwind_tables);
160	spin_unlock_irqrestore(&unwind_lock, flags);
161
162	return table;
163}
164
165void unwind_table_remove(struct unwind_table *table)
166{
167	unsigned long flags;
168
169	spin_lock_irqsave(&unwind_lock, flags);
170	list_del(&table->list);
171	spin_unlock_irqrestore(&unwind_lock, flags);
172
173	kfree(table);
174}
175
176/* Called from setup_arch to import the kernel unwind info */
177int __init unwind_init(void)
178{
179	long start, stop;
180	register unsigned long gp __asm__ ("r27");
181
182	start = (long)&__start___unwind[0];
183	stop = (long)&__stop___unwind[0];
184
185	dbg("unwind_init: start = 0x%lx, end = 0x%lx, entries = %lu\n",
186	    start, stop,
187	    (stop - start) / sizeof(struct unwind_table_entry));
188
189	unwind_table_init(&kernel_unwind_table, "kernel", KERNEL_START,
190			  gp, 
191			  &__start___unwind[0], &__stop___unwind[0]);
192#if 0
193	{
194		int i;
195		for (i = 0; i < 10; i++)
196		{
197			printk("region 0x%x-0x%x\n", 
198				__start___unwind[i].region_start, 
199				__start___unwind[i].region_end);
200		}
201	}
202#endif
203	return 0;
204}
205
206static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int frame_size)
207{
208	/*
209	 * We have to use void * instead of a function pointer, because
210	 * function pointers aren't a pointer to the function on 64-bit.
211	 * Make them const so the compiler knows they live in .text
212	 * Note: We could use dereference_kernel_function_descriptor()
213	 * instead but we want to keep it simple here.
214	 */
215	extern void * const handle_interruption;
216	extern void * const ret_from_kernel_thread;
217	extern void * const syscall_exit;
218	extern void * const intr_return;
219	extern void * const _switch_to_ret;
220#ifdef CONFIG_IRQSTACKS
221	extern void * const _call_on_stack;
222#endif /* CONFIG_IRQSTACKS */
223
224	if (pc == (unsigned long) &handle_interruption) {
225		struct pt_regs *regs = (struct pt_regs *)(info->sp - frame_size - PT_SZ_ALGN);
226		dbg("Unwinding through handle_interruption()\n");
227		info->prev_sp = regs->gr[30];
228		info->prev_ip = regs->iaoq[0];
229		return 1;
230	}
231
232	if (pc == (unsigned long) &ret_from_kernel_thread ||
233	    pc == (unsigned long) &syscall_exit) {
234		info->prev_sp = info->prev_ip = 0;
235		return 1;
236	}
237
238	if (pc == (unsigned long) &intr_return) {
239		struct pt_regs *regs;
240
241		dbg("Found intr_return()\n");
242		regs = (struct pt_regs *)(info->sp - PT_SZ_ALGN);
243		info->prev_sp = regs->gr[30];
244		info->prev_ip = regs->iaoq[0];
245		info->rp = regs->gr[2];
246		return 1;
247	}
248
249	if (pc == (unsigned long) &_switch_to_ret) {
250		info->prev_sp = info->sp - CALLEE_SAVE_FRAME_SIZE;
251		info->prev_ip = *(unsigned long *)(info->prev_sp - RP_OFFSET);
252		return 1;
253	}
254
255#ifdef CONFIG_IRQSTACKS
256	if (pc == (unsigned long) &_call_on_stack) {
257		info->prev_sp = *(unsigned long *)(info->sp - FRAME_SIZE - REG_SZ);
258		info->prev_ip = *(unsigned long *)(info->sp - FRAME_SIZE - RP_OFFSET);
259		return 1;
260	}
261#endif
262
263	return 0;
264}
265
266static void unwind_frame_regs(struct unwind_frame_info *info)
267{
268	const struct unwind_table_entry *e;
269	unsigned long npc;
270	unsigned int insn;
271	long frame_size = 0;
272	int looking_for_rp, rpoffset = 0;
273
274	e = find_unwind_entry(info->ip);
275	if (e == NULL) {
276		unsigned long sp;
277
278		dbg("Cannot find unwind entry for %pS; forced unwinding\n",
279			(void *) info->ip);
280
281		/* Since we are doing the unwinding blind, we don't know if
282		   we are adjusting the stack correctly or extracting the rp
283		   correctly. The rp is checked to see if it belongs to the
284		   kernel text section, if not we assume we don't have a 
285		   correct stack frame and we continue to unwind the stack.
286		   This is not quite correct, and will fail for loadable
287		   modules. */
288		sp = info->sp & ~63;
289		do {
290			unsigned long tmp;
291
292			info->prev_sp = sp - 64;
293			info->prev_ip = 0;
294
295			/* The stack is at the end inside the thread_union
296			 * struct. If we reach data, we have reached the
297			 * beginning of the stack and should stop unwinding. */
298			if (info->prev_sp >= (unsigned long) task_thread_info(info->t) &&
299			    info->prev_sp < ((unsigned long) task_thread_info(info->t)
300						+ THREAD_SZ_ALGN)) {
301				info->prev_sp = 0;
302				break;
303			}
304
305			if (get_user(tmp, (unsigned long *)(info->prev_sp - RP_OFFSET))) 
306				break;
307			info->prev_ip = tmp;
308			sp = info->prev_sp;
309		} while (!kernel_text_address(info->prev_ip));
310
311		info->rp = 0;
312
313		dbg("analyzing func @ %lx with no unwind info, setting "
314		    "prev_sp=%lx prev_ip=%lx\n", info->ip, 
315		    info->prev_sp, info->prev_ip);
316	} else {
317		dbg("e->start = 0x%x, e->end = 0x%x, Save_SP = %d, "
318		    "Save_RP = %d, Millicode = %d size = %u\n", 
319		    e->region_start, e->region_end, e->Save_SP, e->Save_RP, 
320		    e->Millicode, e->Total_frame_size);
321
322		looking_for_rp = e->Save_RP;
323
324		for (npc = e->region_start; 
325		     (frame_size < (e->Total_frame_size << 3) || 
326		      looking_for_rp) && 
327		     npc < info->ip; 
328		     npc += 4) {
329
330			insn = *(unsigned int *)npc;
331
332			if ((insn & 0xffffc001) == 0x37de0000 ||
333			    (insn & 0xffe00001) == 0x6fc00000) {
334				/* ldo X(sp), sp, or stwm X,D(sp) */
335				frame_size += (insn & 0x3fff) >> 1;
336				dbg("analyzing func @ %lx, insn=%08x @ "
337				    "%lx, frame_size = %ld\n", info->ip,
338				    insn, npc, frame_size);
339			} else if ((insn & 0xffe00009) == 0x73c00008) {
340				/* std,ma X,D(sp) */
341				frame_size += ((insn >> 4) & 0x3ff) << 3;
342				dbg("analyzing func @ %lx, insn=%08x @ "
343				    "%lx, frame_size = %ld\n", info->ip,
344				    insn, npc, frame_size);
345			} else if (insn == 0x6bc23fd9) { 
346				/* stw rp,-20(sp) */
347				rpoffset = 20;
348				looking_for_rp = 0;
349				dbg("analyzing func @ %lx, insn=stw rp,"
350				    "-20(sp) @ %lx\n", info->ip, npc);
351			} else if (insn == 0x0fc212c1) {
352				/* std rp,-16(sr0,sp) */
353				rpoffset = 16;
354				looking_for_rp = 0;
355				dbg("analyzing func @ %lx, insn=std rp,"
356				    "-16(sp) @ %lx\n", info->ip, npc);
357			}
358		}
359
360		if (frame_size > e->Total_frame_size << 3)
361			frame_size = e->Total_frame_size << 3;
362
363		if (!unwind_special(info, e->region_start, frame_size)) {
364			info->prev_sp = info->sp - frame_size;
365			if (e->Millicode)
366				info->rp = info->r31;
367			else if (rpoffset)
368				info->rp = *(unsigned long *)(info->prev_sp - rpoffset);
369			info->prev_ip = info->rp;
370			info->rp = 0;
371		}
372
373		dbg("analyzing func @ %lx, setting prev_sp=%lx "
374		    "prev_ip=%lx npc=%lx\n", info->ip, info->prev_sp, 
375		    info->prev_ip, npc);
376	}
377}
378
379void unwind_frame_init(struct unwind_frame_info *info, struct task_struct *t, 
380		       struct pt_regs *regs)
381{
382	memset(info, 0, sizeof(struct unwind_frame_info));
383	info->t = t;
384	info->sp = regs->gr[30];
385	info->ip = regs->iaoq[0];
386	info->rp = regs->gr[2];
387	info->r31 = regs->gr[31];
388
389	dbg("(%d) Start unwind from sp=%08lx ip=%08lx\n", 
390	    t ? (int)t->pid : -1, info->sp, info->ip);
391}
392
393void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct task_struct *t)
394{
395	struct pt_regs *r = &t->thread.regs;
396	struct pt_regs *r2;
397
398	r2 = kmalloc(sizeof(struct pt_regs), GFP_ATOMIC);
399	if (!r2)
400		return;
401	*r2 = *r;
402	r2->gr[30] = r->ksp;
403	r2->iaoq[0] = r->kpc;
404	unwind_frame_init(info, t, r2);
405	kfree(r2);
406}
407
408#define get_parisc_stackpointer() ({ \
409	unsigned long sp; \
410	__asm__("copy %%r30, %0" : "=r"(sp)); \
411	(sp); \
412})
413
414void unwind_frame_init_task(struct unwind_frame_info *info,
415	struct task_struct *task, struct pt_regs *regs)
416{
417	task = task ? task : current;
418
419	if (task == current) {
420		struct pt_regs r;
421
422		if (!regs) {
423			memset(&r, 0, sizeof(r));
424			r.iaoq[0] =  _THIS_IP_;
425			r.gr[2] = _RET_IP_;
426			r.gr[30] = get_parisc_stackpointer();
427			regs = &r;
428		}
429		unwind_frame_init(info, task, regs);
430	} else {
431		unwind_frame_init_from_blocked_task(info, task);
432	}
433}
434
435int unwind_once(struct unwind_frame_info *next_frame)
436{
437	unwind_frame_regs(next_frame);
438
439	if (next_frame->prev_sp == 0 ||
440	    next_frame->prev_ip == 0)
441		return -1;
442
443	next_frame->sp = next_frame->prev_sp;
444	next_frame->ip = next_frame->prev_ip;
445	next_frame->prev_sp = 0;
446	next_frame->prev_ip = 0;
447
448	dbg("(%d) Continue unwind to sp=%08lx ip=%08lx\n", 
449	    next_frame->t ? (int)next_frame->t->pid : -1, 
450	    next_frame->sp, next_frame->ip);
451
452	return 0;
453}
454
455int unwind_to_user(struct unwind_frame_info *info)
456{
457	int ret;
458	
459	do {
460		ret = unwind_once(info);
461	} while (!ret && !(info->ip & 3));
462
463	return ret;
464}
465
466unsigned long return_address(unsigned int level)
467{
468	struct unwind_frame_info info;
469
470	/* initialize unwind info */
471	unwind_frame_init_task(&info, current, NULL);
472
473	/* unwind stack */
474	level += 2;
475	do {
476		if (unwind_once(&info) < 0 || info.ip == 0)
477			return 0;
478		if (!kernel_text_address(info.ip))
479			return 0;
480	} while (info.ip && level--);
481
482	return info.ip;
483}