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

TOMOYO Linux Cross Reference
Linux/arch/csky/kernel/probes/simulate-insn.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ 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 ] ~

  1 // SPDX-License-Identifier: GPL-2.0+
  2 
  3 #include <linux/bitops.h>
  4 #include <linux/kernel.h>
  5 #include <linux/kprobes.h>
  6 
  7 #include "decode-insn.h"
  8 #include "simulate-insn.h"
  9 
 10 static inline bool csky_insn_reg_get_val(struct pt_regs *regs,
 11                                          unsigned long index,
 12                                          unsigned long *ptr)
 13 {
 14         if (index < 14)
 15                 *ptr = *(&regs->a0 + index);
 16 
 17         if (index > 15 && index < 31)
 18                 *ptr = *(&regs->exregs[0] + index - 16);
 19 
 20         switch (index) {
 21         case 14:
 22                 *ptr = regs->usp;
 23                 break;
 24         case 15:
 25                 *ptr = regs->lr;
 26                 break;
 27         case 31:
 28                 *ptr = regs->tls;
 29                 break;
 30         default:
 31                 goto fail;
 32         }
 33 
 34         return true;
 35 fail:
 36         return false;
 37 }
 38 
 39 static inline bool csky_insn_reg_set_val(struct pt_regs *regs,
 40                                          unsigned long index,
 41                                          unsigned long val)
 42 {
 43         if (index < 14)
 44                 *(&regs->a0 + index) = val;
 45 
 46         if (index > 15 && index < 31)
 47                 *(&regs->exregs[0] + index - 16) = val;
 48 
 49         switch (index) {
 50         case 14:
 51                 regs->usp = val;
 52                 break;
 53         case 15:
 54                 regs->lr = val;
 55                 break;
 56         case 31:
 57                 regs->tls = val;
 58                 break;
 59         default:
 60                 goto fail;
 61         }
 62 
 63         return true;
 64 fail:
 65         return false;
 66 }
 67 
 68 void __kprobes
 69 simulate_br16(u32 opcode, long addr, struct pt_regs *regs)
 70 {
 71         instruction_pointer_set(regs,
 72                 addr + sign_extend32((opcode & 0x3ff) << 1, 9));
 73 }
 74 
 75 void __kprobes
 76 simulate_br32(u32 opcode, long addr, struct pt_regs *regs)
 77 {
 78         instruction_pointer_set(regs,
 79                 addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
 80 }
 81 
 82 void __kprobes
 83 simulate_bt16(u32 opcode, long addr, struct pt_regs *regs)
 84 {
 85         if (regs->sr & 1)
 86                 instruction_pointer_set(regs,
 87                         addr + sign_extend32((opcode & 0x3ff) << 1, 9));
 88         else
 89                 instruction_pointer_set(regs, addr + 2);
 90 }
 91 
 92 void __kprobes
 93 simulate_bt32(u32 opcode, long addr, struct pt_regs *regs)
 94 {
 95         if (regs->sr & 1)
 96                 instruction_pointer_set(regs,
 97                         addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
 98         else
 99                 instruction_pointer_set(regs, addr + 4);
100 }
101 
102 void __kprobes
103 simulate_bf16(u32 opcode, long addr, struct pt_regs *regs)
104 {
105         if (!(regs->sr & 1))
106                 instruction_pointer_set(regs,
107                         addr + sign_extend32((opcode & 0x3ff) << 1, 9));
108         else
109                 instruction_pointer_set(regs, addr + 2);
110 }
111 
112 void __kprobes
113 simulate_bf32(u32 opcode, long addr, struct pt_regs *regs)
114 {
115         if (!(regs->sr & 1))
116                 instruction_pointer_set(regs,
117                         addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
118         else
119                 instruction_pointer_set(regs, addr + 4);
120 }
121 
122 void __kprobes
123 simulate_jmp16(u32 opcode, long addr, struct pt_regs *regs)
124 {
125         unsigned long tmp = (opcode >> 2) & 0xf;
126 
127         csky_insn_reg_get_val(regs, tmp, &tmp);
128 
129         instruction_pointer_set(regs, tmp & 0xfffffffe);
130 }
131 
132 void __kprobes
133 simulate_jmp32(u32 opcode, long addr, struct pt_regs *regs)
134 {
135         unsigned long tmp = opcode & 0x1f;
136 
137         csky_insn_reg_get_val(regs, tmp, &tmp);
138 
139         instruction_pointer_set(regs, tmp & 0xfffffffe);
140 }
141 
142 void __kprobes
143 simulate_jsr16(u32 opcode, long addr, struct pt_regs *regs)
144 {
145         unsigned long tmp = (opcode >> 2) & 0xf;
146 
147         csky_insn_reg_get_val(regs, tmp, &tmp);
148 
149         regs->lr = addr + 2;
150 
151         instruction_pointer_set(regs, tmp & 0xfffffffe);
152 }
153 
154 void __kprobes
155 simulate_jsr32(u32 opcode, long addr, struct pt_regs *regs)
156 {
157         unsigned long tmp = opcode & 0x1f;
158 
159         csky_insn_reg_get_val(regs, tmp, &tmp);
160 
161         regs->lr = addr + 4;
162 
163         instruction_pointer_set(regs, tmp & 0xfffffffe);
164 }
165 
166 void __kprobes
167 simulate_lrw16(u32 opcode, long addr, struct pt_regs *regs)
168 {
169         unsigned long val;
170         unsigned long tmp = (opcode & 0x300) >> 3;
171         unsigned long offset = ((opcode & 0x1f) | tmp) << 2;
172 
173         tmp = (opcode & 0xe0) >> 5;
174 
175         val = *(unsigned int *)(instruction_pointer(regs) + offset);
176 
177         csky_insn_reg_set_val(regs, tmp, val);
178 }
179 
180 void __kprobes
181 simulate_lrw32(u32 opcode, long addr, struct pt_regs *regs)
182 {
183         unsigned long val;
184         unsigned long offset = (opcode & 0xffff0000) >> 14;
185         unsigned long tmp = opcode & 0x0000001f;
186 
187         val = *(unsigned int *)
188                 ((instruction_pointer(regs) + offset) & 0xfffffffc);
189 
190         csky_insn_reg_set_val(regs, tmp, val);
191 }
192 
193 void __kprobes
194 simulate_pop16(u32 opcode, long addr, struct pt_regs *regs)
195 {
196         unsigned long *tmp = (unsigned long *)regs->usp;
197         int i;
198 
199         for (i = 0; i < (opcode & 0xf); i++) {
200                 csky_insn_reg_set_val(regs, i + 4, *tmp);
201                 tmp += 1;
202         }
203 
204         if (opcode & 0x10) {
205                 csky_insn_reg_set_val(regs, 15, *tmp);
206                 tmp += 1;
207         }
208 
209         regs->usp = (unsigned long)tmp;
210 
211         instruction_pointer_set(regs, regs->lr);
212 }
213 
214 void __kprobes
215 simulate_pop32(u32 opcode, long addr, struct pt_regs *regs)
216 {
217         unsigned long *tmp = (unsigned long *)regs->usp;
218         int i;
219 
220         for (i = 0; i < ((opcode & 0xf0000) >> 16); i++) {
221                 csky_insn_reg_set_val(regs, i + 4, *tmp);
222                 tmp += 1;
223         }
224 
225         if (opcode & 0x100000) {
226                 csky_insn_reg_set_val(regs, 15, *tmp);
227                 tmp += 1;
228         }
229 
230         for (i = 0; i < ((opcode & 0xe00000) >> 21); i++) {
231                 csky_insn_reg_set_val(regs, i + 16, *tmp);
232                 tmp += 1;
233         }
234 
235         if (opcode & 0x1000000) {
236                 csky_insn_reg_set_val(regs, 29, *tmp);
237                 tmp += 1;
238         }
239 
240         regs->usp = (unsigned long)tmp;
241 
242         instruction_pointer_set(regs, regs->lr);
243 }
244 
245 void __kprobes
246 simulate_bez32(u32 opcode, long addr, struct pt_regs *regs)
247 {
248         unsigned long tmp = opcode & 0x1f;
249 
250         csky_insn_reg_get_val(regs, tmp, &tmp);
251 
252         if (tmp == 0) {
253                 instruction_pointer_set(regs,
254                         addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
255         } else
256                 instruction_pointer_set(regs, addr + 4);
257 }
258 
259 void __kprobes
260 simulate_bnez32(u32 opcode, long addr, struct pt_regs *regs)
261 {
262         unsigned long tmp = opcode & 0x1f;
263 
264         csky_insn_reg_get_val(regs, tmp, &tmp);
265 
266         if (tmp != 0) {
267                 instruction_pointer_set(regs,
268                         addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
269         } else
270                 instruction_pointer_set(regs, addr + 4);
271 }
272 
273 void __kprobes
274 simulate_bnezad32(u32 opcode, long addr, struct pt_regs *regs)
275 {
276         unsigned long tmp = opcode & 0x1f;
277         long val;
278 
279         csky_insn_reg_get_val(regs, tmp, (unsigned long *)&val);
280 
281         val -= 1;
282 
283         if (val > 0) {
284                 instruction_pointer_set(regs,
285                         addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
286         } else
287                 instruction_pointer_set(regs, addr + 4);
288 
289         csky_insn_reg_set_val(regs, tmp, (unsigned long)val);
290 }
291 
292 void __kprobes
293 simulate_bhsz32(u32 opcode, long addr, struct pt_regs *regs)
294 {
295         unsigned long tmp = opcode & 0x1f;
296         unsigned long val;
297 
298         csky_insn_reg_get_val(regs, tmp, &val);
299 
300         if ((long) val >= 0) {
301                 instruction_pointer_set(regs,
302                         addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
303         } else
304                 instruction_pointer_set(regs, addr + 4);
305 }
306 
307 void __kprobes
308 simulate_bhz32(u32 opcode, long addr, struct pt_regs *regs)
309 {
310         unsigned long tmp = opcode & 0x1f;
311         unsigned long val;
312 
313         csky_insn_reg_get_val(regs, tmp, &val);
314 
315         if ((long) val > 0) {
316                 instruction_pointer_set(regs,
317                         addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
318         } else
319                 instruction_pointer_set(regs, addr + 4);
320 }
321 
322 void __kprobes
323 simulate_blsz32(u32 opcode, long addr, struct pt_regs *regs)
324 {
325         unsigned long tmp = opcode & 0x1f;
326         unsigned long val;
327 
328         csky_insn_reg_get_val(regs, tmp, &val);
329 
330         if ((long) val <= 0) {
331                 instruction_pointer_set(regs,
332                         addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
333         } else
334                 instruction_pointer_set(regs, addr + 4);
335 }
336 
337 void __kprobes
338 simulate_blz32(u32 opcode, long addr, struct pt_regs *regs)
339 {
340         unsigned long tmp = opcode & 0x1f;
341         unsigned long val;
342 
343         csky_insn_reg_get_val(regs, tmp, &val);
344 
345         if ((long) val < 0) {
346                 instruction_pointer_set(regs,
347                         addr + sign_extend32((opcode & 0xffff0000) >> 15, 15));
348         } else
349                 instruction_pointer_set(regs, addr + 4);
350 }
351 
352 void __kprobes
353 simulate_bsr32(u32 opcode, long addr, struct pt_regs *regs)
354 {
355         unsigned long tmp;
356 
357         tmp = (opcode & 0xffff) << 16;
358         tmp |= (opcode & 0xffff0000) >> 16;
359 
360         instruction_pointer_set(regs,
361                 addr + sign_extend32((tmp & 0x3ffffff) << 1, 15));
362 
363         regs->lr = addr + 4;
364 }
365 
366 void __kprobes
367 simulate_jmpi32(u32 opcode, long addr, struct pt_regs *regs)
368 {
369         unsigned long val;
370         unsigned long offset = ((opcode & 0xffff0000) >> 14);
371 
372         val = *(unsigned int *)
373                 ((instruction_pointer(regs) + offset) & 0xfffffffc);
374 
375         instruction_pointer_set(regs, val);
376 }
377 
378 void __kprobes
379 simulate_jsri32(u32 opcode, long addr, struct pt_regs *regs)
380 {
381         unsigned long val;
382         unsigned long offset = ((opcode & 0xffff0000) >> 14);
383 
384         val = *(unsigned int *)
385                 ((instruction_pointer(regs) + offset) & 0xfffffffc);
386 
387         regs->lr = addr + 4;
388 
389         instruction_pointer_set(regs, val);
390 }
391 

~ [ 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