Merge tag 'clk-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / arch / arm64 / kernel / return_address.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * arch/arm64/kernel/return_address.c
4  *
5  * Copyright (C) 2013 Linaro Limited
6  * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
7  */
8
9 #include <linux/export.h>
10 #include <linux/ftrace.h>
11 #include <linux/kprobes.h>
12
13 #include <asm/stack_pointer.h>
14 #include <asm/stacktrace.h>
15
16 struct return_address_data {
17         unsigned int level;
18         void *addr;
19 };
20
21 static int save_return_addr(struct stackframe *frame, void *d)
22 {
23         struct return_address_data *data = d;
24
25         if (!data->level) {
26                 data->addr = (void *)frame->pc;
27                 return 1;
28         } else {
29                 --data->level;
30                 return 0;
31         }
32 }
33 NOKPROBE_SYMBOL(save_return_addr);
34
35 void *return_address(unsigned int level)
36 {
37         struct return_address_data data;
38         struct stackframe frame;
39
40         data.level = level + 2;
41         data.addr = NULL;
42
43         start_backtrace(&frame,
44                         (unsigned long)__builtin_frame_address(0),
45                         (unsigned long)return_address);
46         walk_stackframe(current, &frame, save_return_addr, &data);
47
48         if (!data.level)
49                 return data.addr;
50         else
51                 return NULL;
52 }
53 EXPORT_SYMBOL_GPL(return_address);
54 NOKPROBE_SYMBOL(return_address);