aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/uprobes.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/uprobes.c')
-rw-r--r--arch/mips/kernel/uprobes.c88
1 files changed, 15 insertions, 73 deletions
diff --git a/arch/mips/kernel/uprobes.c b/arch/mips/kernel/uprobes.c
index 4c7c1558944a..dbb917403131 100644
--- a/arch/mips/kernel/uprobes.c
+++ b/arch/mips/kernel/uprobes.c
@@ -8,71 +8,12 @@
8#include <asm/branch.h> 8#include <asm/branch.h>
9#include <asm/cpu-features.h> 9#include <asm/cpu-features.h>
10#include <asm/ptrace.h> 10#include <asm/ptrace.h>
11#include <asm/inst.h> 11
12#include "probes-common.h"
12 13
13static inline int insn_has_delay_slot(const union mips_instruction insn) 14static inline int insn_has_delay_slot(const union mips_instruction insn)
14{ 15{
15 switch (insn.i_format.opcode) { 16 return __insn_has_delay_slot(insn);
16 /*
17 * jr and jalr are in r_format format.
18 */
19 case spec_op:
20 switch (insn.r_format.func) {
21 case jalr_op:
22 case jr_op:
23 return 1;
24 }
25 break;
26
27 /*
28 * This group contains:
29 * bltz_op, bgez_op, bltzl_op, bgezl_op,
30 * bltzal_op, bgezal_op, bltzall_op, bgezall_op.
31 */
32 case bcond_op:
33 switch (insn.i_format.rt) {
34 case bltz_op:
35 case bltzl_op:
36 case bgez_op:
37 case bgezl_op:
38 case bltzal_op:
39 case bltzall_op:
40 case bgezal_op:
41 case bgezall_op:
42 case bposge32_op:
43 return 1;
44 }
45 break;
46
47 /*
48 * These are unconditional and in j_format.
49 */
50 case jal_op:
51 case j_op:
52 case beq_op:
53 case beql_op:
54 case bne_op:
55 case bnel_op:
56 case blez_op: /* not really i_format */
57 case blezl_op:
58 case bgtz_op:
59 case bgtzl_op:
60 return 1;
61
62 /*
63 * And now the FPA/cp1 branch instructions.
64 */
65 case cop1_op:
66#ifdef CONFIG_CPU_CAVIUM_OCTEON
67 case lwc2_op: /* This is bbit0 on Octeon */
68 case ldc2_op: /* This is bbit032 on Octeon */
69 case swc2_op: /* This is bbit1 on Octeon */
70 case sdc2_op: /* This is bbit132 on Octeon */
71#endif
72 return 1;
73 }
74
75 return 0;
76} 17}
77 18
78/** 19/**
@@ -95,6 +36,12 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *aup,
95 return -EINVAL; 36 return -EINVAL;
96 37
97 inst.word = aup->insn[0]; 38 inst.word = aup->insn[0];
39
40 if (__insn_is_compact_branch(inst)) {
41 pr_notice("Uprobes for compact branches are not supported\n");
42 return -EINVAL;
43 }
44
98 aup->ixol[0] = aup->insn[insn_has_delay_slot(inst)]; 45 aup->ixol[0] = aup->insn[insn_has_delay_slot(inst)];
99 aup->ixol[1] = UPROBE_BRK_UPROBE_XOL; /* NOP */ 46 aup->ixol[1] = UPROBE_BRK_UPROBE_XOL; /* NOP */
100 47
@@ -282,19 +229,14 @@ int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm,
282void __weak arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr, 229void __weak arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
283 void *src, unsigned long len) 230 void *src, unsigned long len)
284{ 231{
285 void *kaddr; 232 unsigned long kaddr, kstart;
286 233
287 /* Initialize the slot */ 234 /* Initialize the slot */
288 kaddr = kmap_atomic(page); 235 kaddr = (unsigned long)kmap_atomic(page);
289 memcpy(kaddr + (vaddr & ~PAGE_MASK), src, len); 236 kstart = kaddr + (vaddr & ~PAGE_MASK);
290 kunmap_atomic(kaddr); 237 memcpy((void *)kstart, src, len);
291 238 flush_icache_range(kstart, kstart + len);
292 /* 239 kunmap_atomic((void *)kaddr);
293 * The MIPS version of flush_icache_range will operate safely on
294 * user space addresses and more importantly, it doesn't require a
295 * VMA argument.
296 */
297 flush_icache_range(vaddr, vaddr + len);
298} 240}
299 241
300/** 242/**