1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 24bf1fa5aSUwe Kleine-König /* 34bf1fa5aSUwe Kleine-König * arch/arm/kernel/return_address.c 44bf1fa5aSUwe Kleine-König * 54bf1fa5aSUwe Kleine-König * Copyright (C) 2009 Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de> 64bf1fa5aSUwe Kleine-König * for Pengutronix 74bf1fa5aSUwe Kleine-König */ 8ecea4ab6SPaul Gortmaker #include <linux/export.h> 92bbd7e9bSRussell King #include <linux/ftrace.h> 104bf1fa5aSUwe Kleine-König #include <linux/sched.h> 114bf1fa5aSUwe Kleine-König 124bf1fa5aSUwe Kleine-König #include <asm/stacktrace.h> 134bf1fa5aSUwe Kleine-König 144bf1fa5aSUwe Kleine-König struct return_address_data { 154bf1fa5aSUwe Kleine-König unsigned int level; 164bf1fa5aSUwe Kleine-König void *addr; 174bf1fa5aSUwe Kleine-König }; 184bf1fa5aSUwe Kleine-König save_return_addr(void * d,unsigned long pc)19*70ccc7c0SLi Huafeistatic bool save_return_addr(void *d, unsigned long pc) 204bf1fa5aSUwe Kleine-König { 214bf1fa5aSUwe Kleine-König struct return_address_data *data = d; 224bf1fa5aSUwe Kleine-König 234bf1fa5aSUwe Kleine-König if (!data->level) { 24*70ccc7c0SLi Huafei data->addr = (void *)pc; 254bf1fa5aSUwe Kleine-König 26*70ccc7c0SLi Huafei return false; 274bf1fa5aSUwe Kleine-König } else { 284bf1fa5aSUwe Kleine-König --data->level; 29*70ccc7c0SLi Huafei return true; 304bf1fa5aSUwe Kleine-König } 314bf1fa5aSUwe Kleine-König } 324bf1fa5aSUwe Kleine-König return_address(unsigned int level)334bf1fa5aSUwe Kleine-Königvoid *return_address(unsigned int level) 344bf1fa5aSUwe Kleine-König { 354bf1fa5aSUwe Kleine-König struct return_address_data data; 364bf1fa5aSUwe Kleine-König struct stackframe frame; 374bf1fa5aSUwe Kleine-König 3801223f36SKeun-O Park data.level = level + 2; 3901223f36SKeun-O Park data.addr = NULL; 404bf1fa5aSUwe Kleine-König 414bf1fa5aSUwe Kleine-König frame.fp = (unsigned long)__builtin_frame_address(0); 42a556ee12SBehan Webster frame.sp = current_stack_pointer; 434bf1fa5aSUwe Kleine-König frame.lr = (unsigned long)__builtin_return_address(0); 44c46c2c9bSRussell King (Oracle) here: 45c46c2c9bSRussell King (Oracle) frame.pc = (unsigned long)&&here; 46fed240d9SMasami Hiramatsu #ifdef CONFIG_KRETPROBES 47fed240d9SMasami Hiramatsu frame.kr_cur = NULL; 48fed240d9SMasami Hiramatsu frame.tsk = current; 49fed240d9SMasami Hiramatsu #endif 50752ec621SLi Huafei frame.ex_frame = false; 514bf1fa5aSUwe Kleine-König 524bf1fa5aSUwe Kleine-König walk_stackframe(&frame, save_return_addr, &data); 534bf1fa5aSUwe Kleine-König 544bf1fa5aSUwe Kleine-König if (!data.level) 554bf1fa5aSUwe Kleine-König return data.addr; 564bf1fa5aSUwe Kleine-König else 574bf1fa5aSUwe Kleine-König return NULL; 584bf1fa5aSUwe Kleine-König } 594bf1fa5aSUwe Kleine-König 604bf1fa5aSUwe Kleine-König EXPORT_SYMBOL_GPL(return_address); 61