diff options
Diffstat (limited to 'arch/mips/kernel/uprobes.c')
-rw-r--r-- | arch/mips/kernel/uprobes.c | 88 |
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 | ||
13 | static inline int insn_has_delay_slot(const union mips_instruction insn) | 14 | static 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, | |||
282 | void __weak arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr, | 229 | void __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 | /** |