1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2012 Rabin Vincent <rabin at rab.in>
6 #include <linux/kernel.h>
7 #include <linux/types.h>
8 #include <linux/stddef.h>
9 #include <linux/wait.h>
10 #include <linux/uprobes.h>
11 #include <linux/module.h>
13 #include "../decode.h"
14 #include "../decode-arm.h"
17 static int uprobes_substitute_pc(unsigned long *pinsn
, u32 oregs
)
19 probes_opcode_t insn
= __mem_to_opcode_arm(*pinsn
);
26 for (regs
= oregs
; regs
; regs
>>= 4, insn
>>= 4) {
27 if ((regs
& 0xf) == REG_TYPE_NONE
)
30 free
&= ~(1 << (insn
& 0xf));
33 /* No PC, no problem */
41 * fls instead of ffs ensures that for "ldrd r0, r1, [pc]" we would
42 * pick LR instead of R1.
44 freereg
= free
= fls(free
) - 1;
46 temp
= __mem_to_opcode_arm(*pinsn
);
51 for (; regs
; regs
>>= 4, mask
<<= 4, free
<<= 4, temp
>>= 4) {
52 if ((regs
& 0xf) == REG_TYPE_NONE
)
55 if ((temp
& 0xf) != 15)
62 *pinsn
= __opcode_to_mem_arm(insn
);
66 static void uprobe_set_pc(struct arch_uprobe
*auprobe
,
67 struct arch_uprobe_task
*autask
,
70 u32 pcreg
= auprobe
->pcreg
;
72 autask
->backup
= regs
->uregs
[pcreg
];
73 regs
->uregs
[pcreg
] = regs
->ARM_pc
+ 8;
76 static void uprobe_unset_pc(struct arch_uprobe
*auprobe
,
77 struct arch_uprobe_task
*autask
,
80 /* PC will be taken care of by common code */
81 regs
->uregs
[auprobe
->pcreg
] = autask
->backup
;
84 static void uprobe_aluwrite_pc(struct arch_uprobe
*auprobe
,
85 struct arch_uprobe_task
*autask
,
88 u32 pcreg
= auprobe
->pcreg
;
90 alu_write_pc(regs
->uregs
[pcreg
], regs
);
91 regs
->uregs
[pcreg
] = autask
->backup
;
94 static void uprobe_write_pc(struct arch_uprobe
*auprobe
,
95 struct arch_uprobe_task
*autask
,
98 u32 pcreg
= auprobe
->pcreg
;
100 load_write_pc(regs
->uregs
[pcreg
], regs
);
101 regs
->uregs
[pcreg
] = autask
->backup
;
105 decode_pc_ro(probes_opcode_t insn
, struct arch_probes_insn
*asi
,
106 const struct decode_header
*d
)
108 struct arch_uprobe
*auprobe
= container_of(asi
, struct arch_uprobe
,
110 struct decode_emulate
*decode
= (struct decode_emulate
*) d
;
111 u32 regs
= decode
->header
.type_regs
.bits
>> DECODE_TYPE_BITS
;
114 reg
= uprobes_substitute_pc(&auprobe
->ixol
[0], regs
);
119 return INSN_REJECTED
;
121 auprobe
->pcreg
= reg
;
122 auprobe
->prehandler
= uprobe_set_pc
;
123 auprobe
->posthandler
= uprobe_unset_pc
;
129 decode_wb_pc(probes_opcode_t insn
, struct arch_probes_insn
*asi
,
130 const struct decode_header
*d
, bool alu
)
132 struct arch_uprobe
*auprobe
= container_of(asi
, struct arch_uprobe
,
134 enum probes_insn ret
= decode_pc_ro(insn
, asi
, d
);
136 if (((insn
>> 12) & 0xf) == 15)
137 auprobe
->posthandler
= alu
? uprobe_aluwrite_pc
144 decode_rd12rn16rm0rs8_rwflags(probes_opcode_t insn
,
145 struct arch_probes_insn
*asi
,
146 const struct decode_header
*d
)
148 return decode_wb_pc(insn
, asi
, d
, true);
152 decode_ldr(probes_opcode_t insn
, struct arch_probes_insn
*asi
,
153 const struct decode_header
*d
)
155 return decode_wb_pc(insn
, asi
, d
, false);
159 uprobe_decode_ldmstm(probes_opcode_t insn
,
160 struct arch_probes_insn
*asi
,
161 const struct decode_header
*d
)
163 struct arch_uprobe
*auprobe
= container_of(asi
, struct arch_uprobe
,
165 unsigned reglist
= insn
& 0xffff;
166 int rn
= (insn
>> 16) & 0xf;
167 int lbit
= insn
& (1 << 20);
168 unsigned used
= reglist
| (1 << rn
);
171 return INSN_REJECTED
;
173 if (!(used
& (1 << 15)))
176 if (used
& (1 << 14))
177 return INSN_REJECTED
;
179 /* Use LR instead of PC */
183 auprobe
->ixol
[0] = __opcode_to_mem_arm(insn
);
185 auprobe
->prehandler
= uprobe_set_pc
;
187 auprobe
->posthandler
= uprobe_write_pc
;
189 auprobe
->posthandler
= uprobe_unset_pc
;
194 const union decode_action uprobes_probes_actions
[] = {
195 [PROBES_PRELOAD_IMM
] = {.handler
= probes_simulate_nop
},
196 [PROBES_PRELOAD_REG
] = {.handler
= probes_simulate_nop
},
197 [PROBES_BRANCH_IMM
] = {.handler
= simulate_blx1
},
198 [PROBES_MRS
] = {.handler
= simulate_mrs
},
199 [PROBES_BRANCH_REG
] = {.handler
= simulate_blx2bx
},
200 [PROBES_CLZ
] = {.handler
= probes_simulate_nop
},
201 [PROBES_SATURATING_ARITHMETIC
] = {.handler
= probes_simulate_nop
},
202 [PROBES_MUL1
] = {.handler
= probes_simulate_nop
},
203 [PROBES_MUL2
] = {.handler
= probes_simulate_nop
},
204 [PROBES_SWP
] = {.handler
= probes_simulate_nop
},
205 [PROBES_LDRSTRD
] = {.decoder
= decode_pc_ro
},
206 [PROBES_LOAD_EXTRA
] = {.decoder
= decode_pc_ro
},
207 [PROBES_LOAD
] = {.decoder
= decode_ldr
},
208 [PROBES_STORE_EXTRA
] = {.decoder
= decode_pc_ro
},
209 [PROBES_STORE
] = {.decoder
= decode_pc_ro
},
210 [PROBES_MOV_IP_SP
] = {.handler
= simulate_mov_ipsp
},
211 [PROBES_DATA_PROCESSING_REG
] = {
212 .decoder
= decode_rd12rn16rm0rs8_rwflags
},
213 [PROBES_DATA_PROCESSING_IMM
] = {
214 .decoder
= decode_rd12rn16rm0rs8_rwflags
},
215 [PROBES_MOV_HALFWORD
] = {.handler
= probes_simulate_nop
},
216 [PROBES_SEV
] = {.handler
= probes_simulate_nop
},
217 [PROBES_WFE
] = {.handler
= probes_simulate_nop
},
218 [PROBES_SATURATE
] = {.handler
= probes_simulate_nop
},
219 [PROBES_REV
] = {.handler
= probes_simulate_nop
},
220 [PROBES_MMI
] = {.handler
= probes_simulate_nop
},
221 [PROBES_PACK
] = {.handler
= probes_simulate_nop
},
222 [PROBES_EXTEND
] = {.handler
= probes_simulate_nop
},
223 [PROBES_EXTEND_ADD
] = {.handler
= probes_simulate_nop
},
224 [PROBES_MUL_ADD_LONG
] = {.handler
= probes_simulate_nop
},
225 [PROBES_MUL_ADD
] = {.handler
= probes_simulate_nop
},
226 [PROBES_BITFIELD
] = {.handler
= probes_simulate_nop
},
227 [PROBES_BRANCH
] = {.handler
= simulate_bbl
},
228 [PROBES_LDMSTM
] = {.decoder
= uprobe_decode_ldmstm
}