root/arch/s390/kernel/unwind_bc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. unwind_get_return_address
  2. outside_of_stack
  3. update_stack_info
  4. unwind_next_frame
  5. __unwind_start

   1 /* SPDX-License-Identifier: GPL-2.0 */
   2 #include <linux/sched.h>
   3 #include <linux/sched/task.h>
   4 #include <linux/sched/task_stack.h>
   5 #include <linux/interrupt.h>
   6 #include <asm/sections.h>
   7 #include <asm/ptrace.h>
   8 #include <asm/bitops.h>
   9 #include <asm/stacktrace.h>
  10 #include <asm/unwind.h>
  11 
  12 unsigned long unwind_get_return_address(struct unwind_state *state)
  13 {
  14         if (unwind_done(state))
  15                 return 0;
  16         return __kernel_text_address(state->ip) ? state->ip : 0;
  17 }
  18 EXPORT_SYMBOL_GPL(unwind_get_return_address);
  19 
  20 static bool outside_of_stack(struct unwind_state *state, unsigned long sp)
  21 {
  22         return (sp <= state->sp) ||
  23                 (sp > state->stack_info.end - sizeof(struct stack_frame));
  24 }
  25 
  26 static bool update_stack_info(struct unwind_state *state, unsigned long sp)
  27 {
  28         struct stack_info *info = &state->stack_info;
  29         unsigned long *mask = &state->stack_mask;
  30 
  31         /* New stack pointer leaves the current stack */
  32         if (get_stack_info(sp, state->task, info, mask) != 0 ||
  33             !on_stack(info, sp, sizeof(struct stack_frame)))
  34                 /* 'sp' does not point to a valid stack */
  35                 return false;
  36         return true;
  37 }
  38 
  39 bool unwind_next_frame(struct unwind_state *state)
  40 {
  41         struct stack_info *info = &state->stack_info;
  42         struct stack_frame *sf;
  43         struct pt_regs *regs;
  44         unsigned long sp, ip;
  45         bool reliable;
  46 
  47         regs = state->regs;
  48         if (unlikely(regs)) {
  49                 if (state->reuse_sp) {
  50                         sp = state->sp;
  51                         state->reuse_sp = false;
  52                 } else {
  53                         sp = READ_ONCE_NOCHECK(regs->gprs[15]);
  54                         if (unlikely(outside_of_stack(state, sp))) {
  55                                 if (!update_stack_info(state, sp))
  56                                         goto out_err;
  57                         }
  58                 }
  59                 sf = (struct stack_frame *) sp;
  60                 ip = READ_ONCE_NOCHECK(sf->gprs[8]);
  61                 reliable = false;
  62                 regs = NULL;
  63                 if (!__kernel_text_address(ip)) {
  64                         /* skip bogus %r14 */
  65                         state->regs = NULL;
  66                         return unwind_next_frame(state);
  67                 }
  68         } else {
  69                 sf = (struct stack_frame *) state->sp;
  70                 sp = READ_ONCE_NOCHECK(sf->back_chain);
  71                 if (likely(sp)) {
  72                         /* Non-zero back-chain points to the previous frame */
  73                         if (unlikely(outside_of_stack(state, sp))) {
  74                                 if (!update_stack_info(state, sp))
  75                                         goto out_err;
  76                         }
  77                         sf = (struct stack_frame *) sp;
  78                         ip = READ_ONCE_NOCHECK(sf->gprs[8]);
  79                         reliable = true;
  80                 } else {
  81                         /* No back-chain, look for a pt_regs structure */
  82                         sp = state->sp + STACK_FRAME_OVERHEAD;
  83                         if (!on_stack(info, sp, sizeof(struct pt_regs)))
  84                                 goto out_stop;
  85                         regs = (struct pt_regs *) sp;
  86                         if (READ_ONCE_NOCHECK(regs->psw.mask) & PSW_MASK_PSTATE)
  87                                 goto out_stop;
  88                         ip = READ_ONCE_NOCHECK(regs->psw.addr);
  89                         reliable = true;
  90                 }
  91         }
  92 
  93 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
  94         /* Decode any ftrace redirection */
  95         if (ip == (unsigned long) return_to_handler)
  96                 ip = ftrace_graph_ret_addr(state->task, &state->graph_idx,
  97                                            ip, (void *) sp);
  98 #endif
  99 
 100         /* Update unwind state */
 101         state->sp = sp;
 102         state->ip = ip;
 103         state->regs = regs;
 104         state->reliable = reliable;
 105         return true;
 106 
 107 out_err:
 108         state->error = true;
 109 out_stop:
 110         state->stack_info.type = STACK_TYPE_UNKNOWN;
 111         return false;
 112 }
 113 EXPORT_SYMBOL_GPL(unwind_next_frame);
 114 
 115 void __unwind_start(struct unwind_state *state, struct task_struct *task,
 116                     struct pt_regs *regs, unsigned long sp)
 117 {
 118         struct stack_info *info = &state->stack_info;
 119         unsigned long *mask = &state->stack_mask;
 120         bool reliable, reuse_sp;
 121         struct stack_frame *sf;
 122         unsigned long ip;
 123 
 124         memset(state, 0, sizeof(*state));
 125         state->task = task;
 126         state->regs = regs;
 127 
 128         /* Don't even attempt to start from user mode regs: */
 129         if (regs && user_mode(regs)) {
 130                 info->type = STACK_TYPE_UNKNOWN;
 131                 return;
 132         }
 133 
 134         /* Get current stack pointer and initialize stack info */
 135         if (get_stack_info(sp, task, info, mask) != 0 ||
 136             !on_stack(info, sp, sizeof(struct stack_frame))) {
 137                 /* Something is wrong with the stack pointer */
 138                 info->type = STACK_TYPE_UNKNOWN;
 139                 state->error = true;
 140                 return;
 141         }
 142 
 143         /* Get the instruction pointer from pt_regs or the stack frame */
 144         if (regs) {
 145                 ip = READ_ONCE_NOCHECK(regs->psw.addr);
 146                 reliable = true;
 147                 reuse_sp = true;
 148         } else {
 149                 sf = (struct stack_frame *) sp;
 150                 ip = READ_ONCE_NOCHECK(sf->gprs[8]);
 151                 reliable = false;
 152                 reuse_sp = false;
 153         }
 154 
 155 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 156         /* Decode any ftrace redirection */
 157         if (ip == (unsigned long) return_to_handler)
 158                 ip = ftrace_graph_ret_addr(state->task, &state->graph_idx,
 159                                            ip, NULL);
 160 #endif
 161 
 162         /* Update unwind state */
 163         state->sp = sp;
 164         state->ip = ip;
 165         state->reliable = reliable;
 166         state->reuse_sp = reuse_sp;
 167 }
 168 EXPORT_SYMBOL_GPL(__unwind_start);

/* [<][>][^][v][top][bottom][index][help] */