linux/arch/s390/include/asm/unwind.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2#ifndef _ASM_S390_UNWIND_H
   3#define _ASM_S390_UNWIND_H
   4
   5#include <linux/sched.h>
   6#include <linux/ftrace.h>
   7#include <asm/ptrace.h>
   8#include <asm/stacktrace.h>
   9
  10/*
  11 * To use the stack unwinder it has to be initialized with unwind_start.
  12 * There four combinations for task and regs:
  13 * 1) task==NULL, regs==NULL: the unwind starts for the task that is currently
  14 *    running, sp/ip picked up from the CPU registers
  15 * 2) task==NULL, regs!=NULL: the unwind starts from the sp/ip found in
  16 *    the struct pt_regs of an interrupt frame for the current task
  17 * 3) task!=NULL, regs==NULL: the unwind starts for an inactive task with
  18 *    the sp picked up from task->thread.ksp and the ip picked up from the
  19 *    return address stored by __switch_to
  20 * 4) task!=NULL, regs!=NULL: the sp/ip are picked up from the interrupt
  21 *    frame 'regs' of a inactive task
  22 * If 'first_frame' is not zero unwind_start skips unwind frames until it
  23 * reaches the specified stack pointer.
  24 * The end of the unwinding is indicated with unwind_done, this can be true
  25 * right after unwind_start, e.g. with first_frame!=0 that can not be found.
  26 * unwind_next_frame skips to the next frame.
  27 * Once the unwind is completed unwind_error() can be used to check if there
  28 * has been a situation where the unwinder could not correctly understand
  29 * the tasks call chain.
  30 */
  31
  32struct unwind_state {
  33        struct stack_info stack_info;
  34        unsigned long stack_mask;
  35        struct task_struct *task;
  36        struct pt_regs *regs;
  37        unsigned long sp, ip;
  38        int graph_idx;
  39        bool reliable;
  40        bool error;
  41};
  42
  43void __unwind_start(struct unwind_state *state, struct task_struct *task,
  44                    struct pt_regs *regs, unsigned long first_frame);
  45bool unwind_next_frame(struct unwind_state *state);
  46unsigned long unwind_get_return_address(struct unwind_state *state);
  47
  48static inline bool unwind_done(struct unwind_state *state)
  49{
  50        return state->stack_info.type == STACK_TYPE_UNKNOWN;
  51}
  52
  53static inline bool unwind_error(struct unwind_state *state)
  54{
  55        return state->error;
  56}
  57
  58static __always_inline void unwind_start(struct unwind_state *state,
  59                                         struct task_struct *task,
  60                                         struct pt_regs *regs,
  61                                         unsigned long first_frame)
  62{
  63        task = task ?: current;
  64        first_frame = first_frame ?: get_stack_pointer(task, regs);
  65        __unwind_start(state, task, regs, first_frame);
  66}
  67
  68static inline struct pt_regs *unwind_get_entry_regs(struct unwind_state *state)
  69{
  70        return unwind_done(state) ? NULL : state->regs;
  71}
  72
  73#define unwind_for_each_frame(state, task, regs, first_frame)   \
  74        for (unwind_start(state, task, regs, first_frame);      \
  75             !unwind_done(state);                               \
  76             unwind_next_frame(state))
  77
  78static inline void unwind_init(void) {}
  79static inline void unwind_module_init(struct module *mod, void *orc_ip,
  80                                      size_t orc_ip_size, void *orc,
  81                                      size_t orc_size) {}
  82
  83#endif /* _ASM_S390_UNWIND_H */
  84