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