~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/powerpc/kernel/uprobes.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /arch/powerpc/kernel/uprobes.c (Architecture i386) and /arch/mips/kernel/uprobes.c (Architecture mips)


  1 // SPDX-License-Identifier: GPL-2.0-or-later   !!   1 // SPDX-License-Identifier: GPL-2.0
  2 /*                                             !!   2 #include <linux/highmem.h>
  3  * User-space Probes (UProbes) for powerpc     !!   3 #include <linux/kdebug.h>
  4  *                                             !!   4 #include <linux/types.h>
  5  * Copyright IBM Corporation, 2007-2012        !!   5 #include <linux/notifier.h>
  6  *                                             << 
  7  * Adapted from the x86 port by Ananth N Mavin << 
  8  */                                            << 
  9 #include <linux/kernel.h>                      << 
 10 #include <linux/sched.h>                            6 #include <linux/sched.h>
 11 #include <linux/ptrace.h>                      << 
 12 #include <linux/uprobes.h>                          7 #include <linux/uprobes.h>
 13 #include <linux/uaccess.h>                     << 
 14 #include <linux/kdebug.h>                      << 
 15                                                     8 
 16 #include <asm/sstep.h>                         !!   9 #include <asm/branch.h>
 17 #include <asm/inst.h>                          !!  10 #include <asm/cpu-features.h>
                                                   >>  11 #include <asm/ptrace.h>
 18                                                    12 
 19 #define UPROBE_TRAP_NR  UINT_MAX               !!  13 #include "probes-common.h"
 20                                                    14 
 21 /**                                            !!  15 static inline int insn_has_delay_slot(const union mips_instruction insn)
 22  * is_trap_insn - check if the instruction is  << 
 23  * @insn: instruction to be checked.           << 
 24  * Returns true if @insn is a trap variant.    << 
 25  */                                            << 
 26 bool is_trap_insn(uprobe_opcode_t *insn)       << 
 27 {                                                  16 {
 28         return (is_trap(*insn));               !!  17         return __insn_has_delay_slot(insn);
 29 }                                                  18 }
 30                                                    19 
 31 /**                                                20 /**
 32  * arch_uprobe_analyze_insn                    !!  21  * arch_uprobe_analyze_insn - instruction analysis including validity and fixups.
 33  * @mm: the probed address space.                  22  * @mm: the probed address space.
 34  * @arch_uprobe: the probepoint information.       23  * @arch_uprobe: the probepoint information.
 35  * @addr: vaddr to probe.                      !!  24  * @addr: virtual address at which to install the probepoint
 36  * Return 0 on success or a -ve number on erro     25  * Return 0 on success or a -ve number on error.
 37  */                                                26  */
 38 int arch_uprobe_analyze_insn(struct arch_uprob !!  27 int arch_uprobe_analyze_insn(struct arch_uprobe *aup,
 39                 struct mm_struct *mm, unsigned !!  28         struct mm_struct *mm, unsigned long addr)
 40 {                                                  29 {
                                                   >>  30         union mips_instruction inst;
                                                   >>  31 
                                                   >>  32         /*
                                                   >>  33          * For the time being this also blocks attempts to use uprobes with
                                                   >>  34          * MIPS16 and microMIPS.
                                                   >>  35          */
 41         if (addr & 0x03)                           36         if (addr & 0x03)
 42                 return -EINVAL;                    37                 return -EINVAL;
 43                                                    38 
 44         if (cpu_has_feature(CPU_FTR_ARCH_31) & !!  39         inst.word = aup->insn[0];
 45             ppc_inst_prefixed(ppc_inst_read(au !!  40 
 46             (addr & 0x3f) == 60) {             !!  41         if (__insn_is_compact_branch(inst)) {
 47                 pr_info_ratelimited("Cannot re !!  42                 pr_notice("Uprobes for compact branches are not supported\n");
 48                 return -EINVAL;                    43                 return -EINVAL;
 49         }                                          44         }
 50                                                    45 
 51         if (!can_single_step(ppc_inst_val(ppc_ !!  46         aup->ixol[0] = aup->insn[insn_has_delay_slot(inst)];
 52                 pr_info_ratelimited("Cannot re !!  47         aup->ixol[1] = UPROBE_BRK_UPROBE_XOL;           /* NOP  */
 53                 return -ENOTSUPP;              << 
 54         }                                      << 
 55                                                    48 
 56         return 0;                                  49         return 0;
 57 }                                                  50 }
 58                                                    51 
                                                   >>  52 /**
                                                   >>  53  * is_trap_insn - check if the instruction is a trap variant
                                                   >>  54  * @insn: instruction to be checked.
                                                   >>  55  * Returns true if @insn is a trap variant.
                                                   >>  56  *
                                                   >>  57  * This definition overrides the weak definition in kernel/events/uprobes.c.
                                                   >>  58  * and is needed for the case where an architecture has multiple trap
                                                   >>  59  * instructions (like PowerPC or MIPS).  We treat BREAK just like the more
                                                   >>  60  * modern conditional trap instructions.
                                                   >>  61  */
                                                   >>  62 bool is_trap_insn(uprobe_opcode_t *insn)
                                                   >>  63 {
                                                   >>  64         union mips_instruction inst;
                                                   >>  65 
                                                   >>  66         inst.word = *insn;
                                                   >>  67 
                                                   >>  68         switch (inst.i_format.opcode) {
                                                   >>  69         case spec_op:
                                                   >>  70                 switch (inst.r_format.func) {
                                                   >>  71                 case break_op:
                                                   >>  72                 case teq_op:
                                                   >>  73                 case tge_op:
                                                   >>  74                 case tgeu_op:
                                                   >>  75                 case tlt_op:
                                                   >>  76                 case tltu_op:
                                                   >>  77                 case tne_op:
                                                   >>  78                         return true;
                                                   >>  79                 }
                                                   >>  80                 break;
                                                   >>  81 
                                                   >>  82         case bcond_op:  /* Yes, really ...  */
                                                   >>  83                 switch (inst.u_format.rt) {
                                                   >>  84                 case teqi_op:
                                                   >>  85                 case tgei_op:
                                                   >>  86                 case tgeiu_op:
                                                   >>  87                 case tlti_op:
                                                   >>  88                 case tltiu_op:
                                                   >>  89                 case tnei_op:
                                                   >>  90                         return true;
                                                   >>  91                 }
                                                   >>  92                 break;
                                                   >>  93         }
                                                   >>  94 
                                                   >>  95         return false;
                                                   >>  96 }
                                                   >>  97 
                                                   >>  98 #define UPROBE_TRAP_NR  ULONG_MAX
                                                   >>  99 
 59 /*                                                100 /*
 60  * arch_uprobe_pre_xol - prepare to execute ou    101  * arch_uprobe_pre_xol - prepare to execute out of line.
 61  * @auprobe: the probepoint information.          102  * @auprobe: the probepoint information.
 62  * @regs: reflects the saved user state of cur    103  * @regs: reflects the saved user state of current task.
 63  */                                               104  */
 64 int arch_uprobe_pre_xol(struct arch_uprobe *au !! 105 int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs)
 65 {                                                 106 {
 66         struct arch_uprobe_task *autask = &cur !! 107         struct uprobe_task *utask = current->utask;
 67                                                   108 
 68         autask->saved_trap_nr = current->threa !! 109         /*
                                                   >> 110          * Now find the EPC where to resume after the breakpoint has been
                                                   >> 111          * dealt with.  This may require emulation of a branch.
                                                   >> 112          */
                                                   >> 113         aup->resume_epc = regs->cp0_epc + 4;
                                                   >> 114         if (insn_has_delay_slot((union mips_instruction) aup->insn[0])) {
                                                   >> 115                 __compute_return_epc_for_insn(regs,
                                                   >> 116                         (union mips_instruction) aup->insn[0]);
                                                   >> 117                 aup->resume_epc = regs->cp0_epc;
                                                   >> 118         }
                                                   >> 119         utask->autask.saved_trap_nr = current->thread.trap_nr;
 69         current->thread.trap_nr = UPROBE_TRAP_    120         current->thread.trap_nr = UPROBE_TRAP_NR;
 70         regs_set_return_ip(regs, current->utas !! 121         regs->cp0_epc = current->utask->xol_vaddr;
 71                                                   122 
 72         user_enable_single_step(current);      << 
 73         return 0;                                 123         return 0;
 74 }                                                 124 }
 75                                                   125 
 76 /**                                            !! 126 int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs)
 77  * uprobe_get_swbp_addr - compute address of s << 
 78  * @regs: Reflects the saved state of the task << 
 79  * instruction.                                << 
 80  * Return the address of the breakpoint instru << 
 81  */                                            << 
 82 unsigned long uprobe_get_swbp_addr(struct pt_r << 
 83 {                                                 127 {
 84         return instruction_pointer(regs);      !! 128         struct uprobe_task *utask = current->utask;
                                                   >> 129 
                                                   >> 130         current->thread.trap_nr = utask->autask.saved_trap_nr;
                                                   >> 131         regs->cp0_epc = aup->resume_epc;
                                                   >> 132 
                                                   >> 133         return 0;
 85 }                                                 134 }
 86                                                   135 
 87 /*                                                136 /*
 88  * If xol insn itself traps and generates a si !! 137  * If xol insn itself traps and generates a signal(Say,
 89  * then detect the case where a singlestepped  !! 138  * SIGILL/SIGSEGV/etc), then detect the case where a singlestepped
 90  * own address. It is assumed that anything li !! 139  * instruction jumps back to its own address. It is assumed that anything
 91  * sets thread.trap_nr != UINT_MAX.            !! 140  * like do_page_fault/do_trap/etc sets thread.trap_nr != -1.
 92  *                                                141  *
 93  * arch_uprobe_pre_xol/arch_uprobe_post_xol sa    142  * arch_uprobe_pre_xol/arch_uprobe_post_xol save/restore thread.trap_nr,
 94  * arch_uprobe_xol_was_trapped() simply checks    143  * arch_uprobe_xol_was_trapped() simply checks that ->trap_nr is not equal to
 95  * UPROBE_TRAP_NR == UINT_MAX set by arch_upro !! 144  * UPROBE_TRAP_NR == -1 set by arch_uprobe_pre_xol().
 96  */                                               145  */
 97 bool arch_uprobe_xol_was_trapped(struct task_s !! 146 bool arch_uprobe_xol_was_trapped(struct task_struct *tsk)
 98 {                                                 147 {
 99         if (t->thread.trap_nr != UPROBE_TRAP_N !! 148         if (tsk->thread.trap_nr != UPROBE_TRAP_NR)
100                 return true;                      149                 return true;
101                                                   150 
102         return false;                             151         return false;
103 }                                                 152 }
104                                                   153 
105 /*                                             << 
106  * Called after single-stepping. To avoid the  << 
107  * occur when we temporarily put back the orig << 
108  * single-step, we single-stepped a copy of th << 
109  *                                             << 
110  * This function prepares to resume execution  << 
111  */                                            << 
112 int arch_uprobe_post_xol(struct arch_uprobe *a << 
113 {                                              << 
114         struct uprobe_task *utask = current->u << 
115                                                << 
116         WARN_ON_ONCE(current->thread.trap_nr ! << 
117                                                << 
118         current->thread.trap_nr = utask->autas << 
119                                                << 
120         /*                                     << 
121          * On powerpc, except for loads and st << 
122          * including ones that alter code flow << 
123          * are emulated in the kernel. We get  << 
124          * support doesn't exist and have to f << 
125          * to be executed.                     << 
126          */                                    << 
127         regs_set_return_ip(regs, (unsigned lon << 
128                                                << 
129         user_disable_single_step(current);     << 
130         return 0;                              << 
131 }                                              << 
132                                                << 
133 /* callback routine for handling exceptions. * << 
134 int arch_uprobe_exception_notify(struct notifi    154 int arch_uprobe_exception_notify(struct notifier_block *self,
135                                 unsigned long  !! 155         unsigned long val, void *data)
136 {                                                 156 {
137         struct die_args *args = data;             157         struct die_args *args = data;
138         struct pt_regs *regs = args->regs;        158         struct pt_regs *regs = args->regs;
139                                                   159 
140         /* regs == NULL is a kernel bug */        160         /* regs == NULL is a kernel bug */
141         if (WARN_ON(!regs))                       161         if (WARN_ON(!regs))
142                 return NOTIFY_DONE;               162                 return NOTIFY_DONE;
143                                                   163 
144         /* We are only interested in userspace    164         /* We are only interested in userspace traps */
145         if (!user_mode(regs))                     165         if (!user_mode(regs))
146                 return NOTIFY_DONE;               166                 return NOTIFY_DONE;
147                                                   167 
148         switch (val) {                            168         switch (val) {
149         case DIE_BPT:                          !! 169         case DIE_UPROBE:
150                 if (uprobe_pre_sstep_notifier(    170                 if (uprobe_pre_sstep_notifier(regs))
151                         return NOTIFY_STOP;       171                         return NOTIFY_STOP;
152                 break;                            172                 break;
153         case DIE_SSTEP:                        !! 173         case DIE_UPROBE_XOL:
154                 if (uprobe_post_sstep_notifier    174                 if (uprobe_post_sstep_notifier(regs))
155                         return NOTIFY_STOP;       175                         return NOTIFY_STOP;
156                 break;                            176                 break;
157         default:                                  177         default:
158                 break;                            178                 break;
159         }                                         179         }
160         return NOTIFY_DONE;                    !! 180 
                                                   >> 181         return 0;
161 }                                                 182 }
162                                                   183 
163 /*                                                184 /*
164  * This function gets called when XOL instruct    185  * This function gets called when XOL instruction either gets trapped or
165  * the thread has a fatal signal, so reset the !! 186  * the thread has a fatal signal. Reset the instruction pointer to its
166  * probed address.                             !! 187  * probed address for the potential restart or for post mortem analysis.
167  */                                               188  */
168 void arch_uprobe_abort_xol(struct arch_uprobe  !! 189 void arch_uprobe_abort_xol(struct arch_uprobe *aup,
                                                   >> 190         struct pt_regs *regs)
169 {                                                 191 {
170         struct uprobe_task *utask = current->u    192         struct uprobe_task *utask = current->utask;
171                                                   193 
172         current->thread.trap_nr = utask->autas    194         current->thread.trap_nr = utask->autask.saved_trap_nr;
173         instruction_pointer_set(regs, utask->v    195         instruction_pointer_set(regs, utask->vaddr);
174                                                << 
175         user_disable_single_step(current);     << 
176 }                                                 196 }
177                                                   197 
178 /*                                             !! 198 unsigned long arch_uretprobe_hijack_return_addr(
179  * See if the instruction can be emulated.     !! 199         unsigned long trampoline_vaddr, struct pt_regs *regs)
180  * Returns true if instruction was emulated, f << 
181  */                                            << 
182 bool arch_uprobe_skip_sstep(struct arch_uprobe << 
183 {                                                 200 {
184         int ret;                               !! 201         unsigned long ra;
185                                                   202 
186         /*                                     !! 203         ra = regs->regs[31];
187          * emulate_step() returns 1 if the ins << 
188          * For all other cases, we need to sin << 
189          */                                    << 
190         ret = emulate_step(regs, ppc_inst_read << 
191         if (ret > 0)                           << 
192                 return true;                   << 
193                                                   204 
194         return false;                          !! 205         /* Replace the return address with the trampoline address */
                                                   >> 206         regs->regs[31] = trampoline_vaddr;
                                                   >> 207 
                                                   >> 208         return ra;
195 }                                                 209 }
196                                                   210 
197 unsigned long                                  !! 211 void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
198 arch_uretprobe_hijack_return_addr(unsigned lon !! 212                                   void *src, unsigned long len)
199 {                                                 213 {
200         unsigned long orig_ret_vaddr;          !! 214         unsigned long kaddr, kstart;
201                                                << 
202         orig_ret_vaddr = regs->link;           << 
203                                                   215 
204         /* Replace the return addr with trampo !! 216         /* Initialize the slot */
205         regs->link = trampoline_vaddr;         !! 217         kaddr = (unsigned long)kmap_atomic(page);
                                                   >> 218         kstart = kaddr + (vaddr & ~PAGE_MASK);
                                                   >> 219         memcpy((void *)kstart, src, len);
                                                   >> 220         flush_icache_range(kstart, kstart + len);
                                                   >> 221         kunmap_atomic((void *)kaddr);
                                                   >> 222 }
206                                                   223 
207         return orig_ret_vaddr;                 !! 224 /**
                                                   >> 225  * uprobe_get_swbp_addr - compute address of swbp given post-swbp regs
                                                   >> 226  * @regs: Reflects the saved state of the task after it has hit a breakpoint
                                                   >> 227  * instruction.
                                                   >> 228  * Return the address of the breakpoint instruction.
                                                   >> 229  *
                                                   >> 230  * This overrides the weak version in kernel/events/uprobes.c.
                                                   >> 231  */
                                                   >> 232 unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
                                                   >> 233 {
                                                   >> 234         return instruction_pointer(regs);
208 }                                                 235 }
209                                                   236 
210 bool arch_uretprobe_is_alive(struct return_ins !! 237 /*
211                                 struct pt_regs !! 238  * See if the instruction can be emulated.
                                                   >> 239  * Returns true if instruction was emulated, false otherwise.
                                                   >> 240  *
                                                   >> 241  * For now we always emulate so this function just returns false.
                                                   >> 242  */
                                                   >> 243 bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
212 {                                                 244 {
213         if (ctx == RP_CHECK_CHAIN_CALL)        !! 245         return false;
214                 return regs->gpr[1] <= ret->st << 
215         else                                   << 
216                 return regs->gpr[1] < ret->sta << 
217 }                                                 246 }
218                                                   247 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php