0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/kernel.h>
0010 #include <linux/sched.h>
0011 #include <linux/ptrace.h>
0012 #include <linux/uprobes.h>
0013 #include <linux/uaccess.h>
0014 #include <linux/kdebug.h>
0015
0016 #include <asm/sstep.h>
0017 #include <asm/inst.h>
0018
0019 #define UPROBE_TRAP_NR UINT_MAX
0020
0021
0022
0023
0024
0025
0026 bool is_trap_insn(uprobe_opcode_t *insn)
0027 {
0028 return (is_trap(*insn));
0029 }
0030
0031
0032
0033
0034
0035
0036
0037
0038 int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe,
0039 struct mm_struct *mm, unsigned long addr)
0040 {
0041 if (addr & 0x03)
0042 return -EINVAL;
0043
0044 if (cpu_has_feature(CPU_FTR_ARCH_31) &&
0045 ppc_inst_prefixed(ppc_inst_read(auprobe->insn)) &&
0046 (addr & 0x3f) == 60) {
0047 pr_info_ratelimited("Cannot register a uprobe on 64 byte unaligned prefixed instruction\n");
0048 return -EINVAL;
0049 }
0050
0051 if (!can_single_step(ppc_inst_val(ppc_inst_read(auprobe->insn)))) {
0052 pr_info_ratelimited("Cannot register a uprobe on instructions that can't be single stepped\n");
0053 return -ENOTSUPP;
0054 }
0055
0056 return 0;
0057 }
0058
0059
0060
0061
0062
0063
0064 int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
0065 {
0066 struct arch_uprobe_task *autask = ¤t->utask->autask;
0067
0068 autask->saved_trap_nr = current->thread.trap_nr;
0069 current->thread.trap_nr = UPROBE_TRAP_NR;
0070 regs_set_return_ip(regs, current->utask->xol_vaddr);
0071
0072 user_enable_single_step(current);
0073 return 0;
0074 }
0075
0076
0077
0078
0079
0080
0081
0082 unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
0083 {
0084 return instruction_pointer(regs);
0085 }
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097 bool arch_uprobe_xol_was_trapped(struct task_struct *t)
0098 {
0099 if (t->thread.trap_nr != UPROBE_TRAP_NR)
0100 return true;
0101
0102 return false;
0103 }
0104
0105
0106
0107
0108
0109
0110
0111
0112 int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
0113 {
0114 struct uprobe_task *utask = current->utask;
0115
0116 WARN_ON_ONCE(current->thread.trap_nr != UPROBE_TRAP_NR);
0117
0118 current->thread.trap_nr = utask->autask.saved_trap_nr;
0119
0120
0121
0122
0123
0124
0125
0126
0127 regs_set_return_ip(regs, (unsigned long)ppc_inst_next((void *)utask->vaddr, auprobe->insn));
0128
0129 user_disable_single_step(current);
0130 return 0;
0131 }
0132
0133
0134 int arch_uprobe_exception_notify(struct notifier_block *self,
0135 unsigned long val, void *data)
0136 {
0137 struct die_args *args = data;
0138 struct pt_regs *regs = args->regs;
0139
0140
0141 if (WARN_ON(!regs))
0142 return NOTIFY_DONE;
0143
0144
0145 if (!user_mode(regs))
0146 return NOTIFY_DONE;
0147
0148 switch (val) {
0149 case DIE_BPT:
0150 if (uprobe_pre_sstep_notifier(regs))
0151 return NOTIFY_STOP;
0152 break;
0153 case DIE_SSTEP:
0154 if (uprobe_post_sstep_notifier(regs))
0155 return NOTIFY_STOP;
0156 break;
0157 default:
0158 break;
0159 }
0160 return NOTIFY_DONE;
0161 }
0162
0163
0164
0165
0166
0167
0168 void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
0169 {
0170 struct uprobe_task *utask = current->utask;
0171
0172 current->thread.trap_nr = utask->autask.saved_trap_nr;
0173 instruction_pointer_set(regs, utask->vaddr);
0174
0175 user_disable_single_step(current);
0176 }
0177
0178
0179
0180
0181
0182 bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
0183 {
0184 int ret;
0185
0186
0187
0188
0189
0190 ret = emulate_step(regs, ppc_inst_read(auprobe->insn));
0191 if (ret > 0)
0192 return true;
0193
0194 return false;
0195 }
0196
0197 unsigned long
0198 arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs)
0199 {
0200 unsigned long orig_ret_vaddr;
0201
0202 orig_ret_vaddr = regs->link;
0203
0204
0205 regs->link = trampoline_vaddr;
0206
0207 return orig_ret_vaddr;
0208 }
0209
0210 bool arch_uretprobe_is_alive(struct return_instance *ret, enum rp_check ctx,
0211 struct pt_regs *regs)
0212 {
0213 if (ctx == RP_CHECK_CHAIN_CALL)
0214 return regs->gpr[1] <= ret->stack;
0215 else
0216 return regs->gpr[1] < ret->stack;
0217 }