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 #include <linux/stacktrace.h>
13 
14 #include <asm/stack_pointer.h>
15 
16 struct return_address_data {
17 	unsigned int level;
18 	void *addr;
19 };
20 
save_return_addr(void * d,unsigned long pc)21 static bool save_return_addr(void *d, unsigned long pc)
22 {
23 	struct return_address_data *data = d;
24 
25 	if (!data->level) {
26 		data->addr = (void *)pc;
27 		return false;
28 	} else {
29 		--data->level;
30 		return true;
31 	}
32 }
33 NOKPROBE_SYMBOL(save_return_addr);
34 
return_address(unsigned int level)35 void *return_address(unsigned int level)
36 {
37 	struct return_address_data data;
38 
39 	data.level = level + 2;
40 	data.addr = NULL;
41 
42 	arch_stack_walk(save_return_addr, &data, current, NULL);
43 
44 	if (!data.level)
45 		return data.addr;
46 	else
47 		return NULL;
48 }
49 EXPORT_SYMBOL_GPL(return_address);
50 NOKPROBE_SYMBOL(return_address);
51