190075Sobrien/* SPDX-License-Identifier: GPL-2.0 */ 2132718Skan#ifndef _ASM_S390_UNWIND_H 3169689Skan#define _ASM_S390_UNWIND_H 418334Speter 518334Speter#include <linux/sched.h> 690075Sobrien#include <linux/ftrace.h> 718334Speter#include <linux/rethook.h> 890075Sobrien#include <linux/llist.h> 990075Sobrien#include <asm/ptrace.h> 1090075Sobrien#include <asm/stacktrace.h> 1190075Sobrien 1218334Speter/* 1390075Sobrien * To use the stack unwinder it has to be initialized with unwind_start. 1490075Sobrien * There four combinations for task and regs: 1590075Sobrien * 1) task==NULL, regs==NULL: the unwind starts for the task that is currently 1690075Sobrien * running, sp/ip picked up from the CPU registers 1718334Speter * 2) task==NULL, regs!=NULL: the unwind starts from the sp/ip found in 1818334Speter * the struct pt_regs of an interrupt frame for the current task 1990075Sobrien * 3) task!=NULL, regs==NULL: the unwind starts for an inactive task with 20169689Skan * the sp picked up from task->thread.ksp and the ip picked up from the 21169689Skan * return address stored by __switch_to 2218334Speter * 4) task!=NULL, regs!=NULL: the sp/ip are picked up from the interrupt 2350397Sobrien * frame 'regs' of a inactive task 2450397Sobrien * If 'first_frame' is not zero unwind_start skips unwind frames until it 25132718Skan * reaches the specified stack pointer. 26132718Skan * The end of the unwinding is indicated with unwind_done, this can be true 2718334Speter * right after unwind_start, e.g. with first_frame!=0 that can not be found. 2818334Speter * unwind_next_frame skips to the next frame. 2918334Speter * Once the unwind is completed unwind_error() can be used to check if there 3090075Sobrien * has been a situation where the unwinder could not correctly understand 3150397Sobrien * the tasks call chain. 3218334Speter */ 3390075Sobrien 3418334Speterstruct unwind_state { 3518334Speter struct stack_info stack_info; 3618334Speter unsigned long stack_mask; 3750397Sobrien struct task_struct *task; 3818334Speter struct pt_regs *regs; 3918334Speter unsigned long sp, ip; 4050397Sobrien int graph_idx; 4118334Speter struct llist_node *kr_cur; 4250397Sobrien bool reliable; 4352284Sobrien bool error; 4490075Sobrien}; 4590075Sobrien 4690075Sobrien/* Recover the return address modified by rethook and ftrace_graph. */ 47117395Skanstatic inline unsigned long unwind_recover_ret_addr(struct unwind_state *state, 48169689Skan unsigned long ip) 4918334Speter{ 50169689Skan ip = ftrace_graph_ret_addr(state->task, &state->graph_idx, ip, (void *)state->sp); 5118334Speter#ifdef CONFIG_RETHOOK 5218334Speter if (is_rethook_trampoline(ip)) 5318334Speter ip = rethook_find_ret_addr(state->task, state->sp, &state->kr_cur); 54169689Skan#endif 55117395Skan return ip; 5690075Sobrien} 5790075Sobrien 5890075Sobrienvoid __unwind_start(struct unwind_state *state, struct task_struct *task, 59117395Skan struct pt_regs *regs, unsigned long first_frame); 6090075Sobrienbool unwind_next_frame(struct unwind_state *state); 6190075Sobrienunsigned long unwind_get_return_address(struct unwind_state *state); 62117395Skan 6390075Sobrienstatic inline bool unwind_done(struct unwind_state *state) 6452284Sobrien{ 65132718Skan return state->stack_info.type == STACK_TYPE_UNKNOWN; 66132718Skan} 6718334Speter 6850397Sobrienstatic inline bool unwind_error(struct unwind_state *state) 6990075Sobrien{ 7090075Sobrien return state->error; 7190075Sobrien} 72132718Skan 7390075Sobrienstatic __always_inline void unwind_start(struct unwind_state *state, 74117395Skan struct task_struct *task, 7590075Sobrien struct pt_regs *regs, 76117395Skan unsigned long first_frame) 7790075Sobrien{ 78117395Skan task = task ?: current; 7990075Sobrien first_frame = first_frame ?: get_stack_pointer(task, regs); 80117395Skan __unwind_start(state, task, regs, first_frame); 81117395Skan} 82117395Skan 83117395Skanstatic inline struct pt_regs *unwind_get_entry_regs(struct unwind_state *state) 84117395Skan{ 85169689Skan return unwind_done(state) ? NULL : state->regs; 8690075Sobrien} 8790075Sobrien 8890075Sobrien#define unwind_for_each_frame(state, task, regs, first_frame) \ 89117395Skan for (unwind_start(state, task, regs, first_frame); \ 9090075Sobrien !unwind_done(state); \ 9118334Speter unwind_next_frame(state)) 9218334Speter 9318334Speterstatic inline void unwind_init(void) {} 9418334Speterstatic inline void unwind_module_init(struct module *mod, void *orc_ip, 9518334Speter size_t orc_ip_size, void *orc, 9618334Speter size_t orc_size) {} 9718334Speter 9818334Speter#endif /* _ASM_S390_UNWIND_H */ 9918334Speter