Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARC: disassembly (needed by kprobes/kgdb/unaligned-access-emul)

In-kernel disassembler

Due Credits
* Orig written by Rajeshwar Ranga
* Consolidation/cleanups by Mischa Jonker

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Cc: Rajeshwar Ranga <rajeshwar.ranga@gmail.com>
Cc: Mischa Jonker <mjonker@synopsys.com>

+656 -1
+116
arch/arc/include/asm/disasm.h
··· 1 + /* 2 + * several functions that help interpret ARC instructions 3 + * used for unaligned accesses, kprobes and kgdb 4 + * 5 + * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License version 2 as 9 + * published by the Free Software Foundation. 10 + */ 11 + 12 + #ifndef __ARC_DISASM_H__ 13 + #define __ARC_DISASM_H__ 14 + 15 + enum { 16 + op_Bcc = 0, op_BLcc = 1, op_LD = 2, op_ST = 3, op_MAJOR_4 = 4, 17 + op_MAJOR_5 = 5, op_LD_ADD = 12, op_ADD_SUB_SHIFT = 13, 18 + op_ADD_MOV_CMP = 14, op_S = 15, op_LD_S = 16, op_LDB_S = 17, 19 + op_LDW_S = 18, op_LDWX_S = 19, op_ST_S = 20, op_STB_S = 21, 20 + op_STW_S = 22, op_Su5 = 23, op_SP = 24, op_GP = 25, 21 + op_Pcl = 26, op_MOV_S = 27, op_ADD_CMP = 28, op_BR_S = 29, 22 + op_B_S = 30, op_BL_S = 31 23 + }; 24 + 25 + enum flow { 26 + noflow, 27 + direct_jump, 28 + direct_call, 29 + indirect_jump, 30 + indirect_call, 31 + invalid_instr 32 + }; 33 + 34 + #define IS_BIT(word, n) ((word) & (1<<n)) 35 + #define BITS(word, s, e) (((word) >> (s)) & (~((-2) << ((e) - (s))))) 36 + 37 + #define MAJOR_OPCODE(word) (BITS((word), 27, 31)) 38 + #define MINOR_OPCODE(word) (BITS((word), 16, 21)) 39 + #define FIELD_A(word) (BITS((word), 0, 5)) 40 + #define FIELD_B(word) ((BITS((word), 12, 14)<<3) | \ 41 + (BITS((word), 24, 26))) 42 + #define FIELD_C(word) (BITS((word), 6, 11)) 43 + #define FIELD_u6(word) FIELDC(word) 44 + #define FIELD_s12(word) sign_extend(((BITS((word), 0, 5) << 6) | \ 45 + BITS((word), 6, 11)), 12) 46 + 47 + /* note that for BL/BRcc these two macro's need another AND statement to mask 48 + * out bit 1 (make the result a multiple of 4) */ 49 + #define FIELD_s9(word) sign_extend(((BITS(word, 15, 15) << 8) | \ 50 + BITS(word, 16, 23)), 9) 51 + #define FIELD_s21(word) sign_extend(((BITS(word, 6, 15) << 11) | \ 52 + (BITS(word, 17, 26) << 1)), 12) 53 + #define FIELD_s25(word) sign_extend(((BITS(word, 0, 3) << 21) | \ 54 + (BITS(word, 6, 15) << 11) | \ 55 + (BITS(word, 17, 26) << 1)), 12) 56 + 57 + /* note: these operate on 16 bits! */ 58 + #define FIELD_S_A(word) ((BITS((word), 2, 2)<<3) | BITS((word), 0, 2)) 59 + #define FIELD_S_B(word) ((BITS((word), 10, 10)<<3) | \ 60 + BITS((word), 8, 10)) 61 + #define FIELD_S_C(word) ((BITS((word), 7, 7)<<3) | BITS((word), 5, 7)) 62 + #define FIELD_S_H(word) ((BITS((word), 0, 2)<<3) | BITS((word), 5, 8)) 63 + #define FIELD_S_u5(word) (BITS((word), 0, 4)) 64 + #define FIELD_S_u6(word) (BITS((word), 0, 4) << 1) 65 + #define FIELD_S_u7(word) (BITS((word), 0, 4) << 2) 66 + #define FIELD_S_u10(word) (BITS((word), 0, 7) << 2) 67 + #define FIELD_S_s7(word) sign_extend(BITS((word), 0, 5) << 1, 9) 68 + #define FIELD_S_s8(word) sign_extend(BITS((word), 0, 7) << 1, 9) 69 + #define FIELD_S_s9(word) sign_extend(BITS((word), 0, 8), 9) 70 + #define FIELD_S_s10(word) sign_extend(BITS((word), 0, 8) << 1, 10) 71 + #define FIELD_S_s11(word) sign_extend(BITS((word), 0, 8) << 2, 11) 72 + #define FIELD_S_s13(word) sign_extend(BITS((word), 0, 10) << 2, 13) 73 + 74 + #define STATUS32_L 0x00000100 75 + #define REG_LIMM 62 76 + 77 + struct disasm_state { 78 + /* generic info */ 79 + unsigned long words[2]; 80 + int instr_len; 81 + int major_opcode; 82 + /* info for branch/jump */ 83 + int is_branch; 84 + int target; 85 + int delay_slot; 86 + enum flow flow; 87 + /* info for load/store */ 88 + int src1, src2, src3, dest, wb_reg; 89 + int zz, aa, x, pref, di; 90 + int fault, write; 91 + }; 92 + 93 + static inline int sign_extend(int value, int bits) 94 + { 95 + if (IS_BIT(value, (bits - 1))) 96 + value |= (0xffffffff << bits); 97 + 98 + return value; 99 + } 100 + 101 + static inline int is_short_instr(unsigned long addr) 102 + { 103 + uint16_t word = *((uint16_t *)addr); 104 + int opcode = (word >> 11) & 0x1F; 105 + return (opcode >= 0x0B); 106 + } 107 + 108 + void disasm_instr(unsigned long addr, struct disasm_state *state, 109 + int userspace, struct pt_regs *regs, struct callee_regs *cregs); 110 + int disasm_next_pc(unsigned long pc, struct pt_regs *regs, struct callee_regs 111 + *cregs, unsigned long *fall_thru, unsigned long *target); 112 + long get_reg(int reg, struct pt_regs *regs, struct callee_regs *cregs); 113 + void set_reg(int reg, long val, struct pt_regs *regs, 114 + struct callee_regs *cregs); 115 + 116 + #endif /* __ARC_DISASM_H__ */
+1 -1
arch/arc/kernel/Makefile
··· 9 9 CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"' 10 10 11 11 obj-y := arcksyms.o setup.o irq.o time.o reset.o ptrace.o entry.o process.o 12 - obj-y += signal.o traps.o sys.o troubleshoot.o stacktrace.o clk.o 12 + obj-y += signal.o traps.o sys.o troubleshoot.o stacktrace.o disasm.o clk.o 13 13 obj-y += devtree.o 14 14 15 15 obj-$(CONFIG_MODULES) += arcksyms.o module.o
+539
arch/arc/kernel/disasm.c
··· 1 + /* 2 + * several functions that help interpret ARC instructions 3 + * used for unaligned accesses, kprobes and kgdb 4 + * 5 + * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) 6 + * 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU General Public License version 2 as 9 + * published by the Free Software Foundation. 10 + */ 11 + 12 + #include <linux/types.h> 13 + #include <linux/kprobes.h> 14 + #include <linux/slab.h> 15 + #include <asm/disasm.h> 16 + #include <asm/uaccess.h> 17 + 18 + #if defined(CONFIG_KGDB) || defined(CONFIG_MISALIGN_ACCESS) || \ 19 + defined(CONFIG_KPROBES) 20 + 21 + /* disasm_instr: Analyses instruction at addr, stores 22 + * findings in *state 23 + */ 24 + void __kprobes disasm_instr(unsigned long addr, struct disasm_state *state, 25 + int userspace, struct pt_regs *regs, struct callee_regs *cregs) 26 + { 27 + int fieldA = 0; 28 + int fieldC = 0, fieldCisReg = 0; 29 + uint16_t word1 = 0, word0 = 0; 30 + int subopcode, is_linked, op_format; 31 + uint16_t *ins_ptr; 32 + uint16_t ins_buf[4]; 33 + int bytes_not_copied = 0; 34 + 35 + memset(state, 0, sizeof(struct disasm_state)); 36 + 37 + /* This fetches the upper part of the 32 bit instruction 38 + * in both the cases of Little Endian or Big Endian configurations. */ 39 + if (userspace) { 40 + bytes_not_copied = copy_from_user(ins_buf, 41 + (const void __user *) addr, 8); 42 + if (bytes_not_copied > 6) 43 + goto fault; 44 + ins_ptr = ins_buf; 45 + } else { 46 + ins_ptr = (uint16_t *) addr; 47 + } 48 + 49 + word1 = *((uint16_t *)addr); 50 + 51 + state->major_opcode = (word1 >> 11) & 0x1F; 52 + 53 + /* Check if the instruction is 32 bit or 16 bit instruction */ 54 + if (state->major_opcode < 0x0B) { 55 + if (bytes_not_copied > 4) 56 + goto fault; 57 + state->instr_len = 4; 58 + word0 = *((uint16_t *)(addr+2)); 59 + state->words[0] = (word1 << 16) | word0; 60 + } else { 61 + state->instr_len = 2; 62 + state->words[0] = word1; 63 + } 64 + 65 + /* Read the second word in case of limm */ 66 + word1 = *((uint16_t *)(addr + state->instr_len)); 67 + word0 = *((uint16_t *)(addr + state->instr_len + 2)); 68 + state->words[1] = (word1 << 16) | word0; 69 + 70 + switch (state->major_opcode) { 71 + case op_Bcc: 72 + state->is_branch = 1; 73 + 74 + /* unconditional branch s25, conditional branch s21 */ 75 + fieldA = (IS_BIT(state->words[0], 16)) ? 76 + FIELD_s25(state->words[0]) : 77 + FIELD_s21(state->words[0]); 78 + 79 + state->delay_slot = IS_BIT(state->words[0], 5); 80 + state->target = fieldA + (addr & ~0x3); 81 + state->flow = direct_jump; 82 + break; 83 + 84 + case op_BLcc: 85 + if (IS_BIT(state->words[0], 16)) { 86 + /* Branch and Link*/ 87 + /* unconditional branch s25, conditional branch s21 */ 88 + fieldA = (IS_BIT(state->words[0], 17)) ? 89 + (FIELD_s25(state->words[0]) & ~0x3) : 90 + FIELD_s21(state->words[0]); 91 + 92 + state->flow = direct_call; 93 + } else { 94 + /*Branch On Compare */ 95 + fieldA = FIELD_s9(state->words[0]) & ~0x3; 96 + state->flow = direct_jump; 97 + } 98 + 99 + state->delay_slot = IS_BIT(state->words[0], 5); 100 + state->target = fieldA + (addr & ~0x3); 101 + state->is_branch = 1; 102 + break; 103 + 104 + case op_LD: /* LD<zz> a,[b,s9] */ 105 + state->write = 0; 106 + state->di = BITS(state->words[0], 11, 11); 107 + if (state->di) 108 + break; 109 + state->x = BITS(state->words[0], 6, 6); 110 + state->zz = BITS(state->words[0], 7, 8); 111 + state->aa = BITS(state->words[0], 9, 10); 112 + state->wb_reg = FIELD_B(state->words[0]); 113 + if (state->wb_reg == REG_LIMM) { 114 + state->instr_len += 4; 115 + state->aa = 0; 116 + state->src1 = state->words[1]; 117 + } else { 118 + state->src1 = get_reg(state->wb_reg, regs, cregs); 119 + } 120 + state->src2 = FIELD_s9(state->words[0]); 121 + state->dest = FIELD_A(state->words[0]); 122 + state->pref = (state->dest == REG_LIMM); 123 + break; 124 + 125 + case op_ST: 126 + state->write = 1; 127 + state->di = BITS(state->words[0], 5, 5); 128 + if (state->di) 129 + break; 130 + state->aa = BITS(state->words[0], 3, 4); 131 + state->zz = BITS(state->words[0], 1, 2); 132 + state->src1 = FIELD_C(state->words[0]); 133 + if (state->src1 == REG_LIMM) { 134 + state->instr_len += 4; 135 + state->src1 = state->words[1]; 136 + } else { 137 + state->src1 = get_reg(state->src1, regs, cregs); 138 + } 139 + state->wb_reg = FIELD_B(state->words[0]); 140 + if (state->wb_reg == REG_LIMM) { 141 + state->aa = 0; 142 + state->instr_len += 4; 143 + state->src2 = state->words[1]; 144 + } else { 145 + state->src2 = get_reg(state->wb_reg, regs, cregs); 146 + } 147 + state->src3 = FIELD_s9(state->words[0]); 148 + break; 149 + 150 + case op_MAJOR_4: 151 + subopcode = MINOR_OPCODE(state->words[0]); 152 + switch (subopcode) { 153 + case 32: /* Jcc */ 154 + case 33: /* Jcc.D */ 155 + case 34: /* JLcc */ 156 + case 35: /* JLcc.D */ 157 + is_linked = 0; 158 + 159 + if (subopcode == 33 || subopcode == 35) 160 + state->delay_slot = 1; 161 + 162 + if (subopcode == 34 || subopcode == 35) 163 + is_linked = 1; 164 + 165 + fieldCisReg = 0; 166 + op_format = BITS(state->words[0], 22, 23); 167 + if (op_format == 0 || ((op_format == 3) && 168 + (!IS_BIT(state->words[0], 5)))) { 169 + fieldC = FIELD_C(state->words[0]); 170 + 171 + if (fieldC == REG_LIMM) { 172 + fieldC = state->words[1]; 173 + state->instr_len += 4; 174 + } else { 175 + fieldCisReg = 1; 176 + } 177 + } else if (op_format == 1 || ((op_format == 3) 178 + && (IS_BIT(state->words[0], 5)))) { 179 + fieldC = FIELD_C(state->words[0]); 180 + } else { 181 + /* op_format == 2 */ 182 + fieldC = FIELD_s12(state->words[0]); 183 + } 184 + 185 + if (!fieldCisReg) { 186 + state->target = fieldC; 187 + state->flow = is_linked ? 188 + direct_call : direct_jump; 189 + } else { 190 + state->target = get_reg(fieldC, regs, cregs); 191 + state->flow = is_linked ? 192 + indirect_call : indirect_jump; 193 + } 194 + state->is_branch = 1; 195 + break; 196 + 197 + case 40: /* LPcc */ 198 + if (BITS(state->words[0], 22, 23) == 3) { 199 + /* Conditional LPcc u7 */ 200 + fieldC = FIELD_C(state->words[0]); 201 + 202 + fieldC = fieldC << 1; 203 + fieldC += (addr & ~0x03); 204 + state->is_branch = 1; 205 + state->flow = direct_jump; 206 + state->target = fieldC; 207 + } 208 + /* For Unconditional lp, next pc is the fall through 209 + * which is updated */ 210 + break; 211 + 212 + case 48 ... 55: /* LD a,[b,c] */ 213 + state->di = BITS(state->words[0], 15, 15); 214 + if (state->di) 215 + break; 216 + state->x = BITS(state->words[0], 16, 16); 217 + state->zz = BITS(state->words[0], 17, 18); 218 + state->aa = BITS(state->words[0], 22, 23); 219 + state->wb_reg = FIELD_B(state->words[0]); 220 + if (state->wb_reg == REG_LIMM) { 221 + state->instr_len += 4; 222 + state->src1 = state->words[1]; 223 + } else { 224 + state->src1 = get_reg(state->wb_reg, regs, 225 + cregs); 226 + } 227 + state->src2 = FIELD_C(state->words[0]); 228 + if (state->src2 == REG_LIMM) { 229 + state->instr_len += 4; 230 + state->src2 = state->words[1]; 231 + } else { 232 + state->src2 = get_reg(state->src2, regs, 233 + cregs); 234 + } 235 + state->dest = FIELD_A(state->words[0]); 236 + if (state->dest == REG_LIMM) 237 + state->pref = 1; 238 + break; 239 + 240 + case 10: /* MOV */ 241 + /* still need to check for limm to extract instr len */ 242 + /* MOV is special case because it only takes 2 args */ 243 + switch (BITS(state->words[0], 22, 23)) { 244 + case 0: /* OP a,b,c */ 245 + if (FIELD_C(state->words[0]) == REG_LIMM) 246 + state->instr_len += 4; 247 + break; 248 + case 1: /* OP a,b,u6 */ 249 + break; 250 + case 2: /* OP b,b,s12 */ 251 + break; 252 + case 3: /* OP.cc b,b,c/u6 */ 253 + if ((!IS_BIT(state->words[0], 5)) && 254 + (FIELD_C(state->words[0]) == REG_LIMM)) 255 + state->instr_len += 4; 256 + break; 257 + } 258 + break; 259 + 260 + 261 + default: 262 + /* Not a Load, Jump or Loop instruction */ 263 + /* still need to check for limm to extract instr len */ 264 + switch (BITS(state->words[0], 22, 23)) { 265 + case 0: /* OP a,b,c */ 266 + if ((FIELD_B(state->words[0]) == REG_LIMM) || 267 + (FIELD_C(state->words[0]) == REG_LIMM)) 268 + state->instr_len += 4; 269 + break; 270 + case 1: /* OP a,b,u6 */ 271 + break; 272 + case 2: /* OP b,b,s12 */ 273 + break; 274 + case 3: /* OP.cc b,b,c/u6 */ 275 + if ((!IS_BIT(state->words[0], 5)) && 276 + ((FIELD_B(state->words[0]) == REG_LIMM) || 277 + (FIELD_C(state->words[0]) == REG_LIMM))) 278 + state->instr_len += 4; 279 + break; 280 + } 281 + break; 282 + } 283 + break; 284 + 285 + /* 16 Bit Instructions */ 286 + case op_LD_ADD: /* LD_S|LDB_S|LDW_S a,[b,c] */ 287 + state->zz = BITS(state->words[0], 3, 4); 288 + state->src1 = get_reg(FIELD_S_B(state->words[0]), regs, cregs); 289 + state->src2 = get_reg(FIELD_S_C(state->words[0]), regs, cregs); 290 + state->dest = FIELD_S_A(state->words[0]); 291 + break; 292 + 293 + case op_ADD_MOV_CMP: 294 + /* check for limm, ignore mov_s h,b (== mov_s 0,b) */ 295 + if ((BITS(state->words[0], 3, 4) < 3) && 296 + (FIELD_S_H(state->words[0]) == REG_LIMM)) 297 + state->instr_len += 4; 298 + break; 299 + 300 + case op_S: 301 + subopcode = BITS(state->words[0], 5, 7); 302 + switch (subopcode) { 303 + case 0: /* j_s */ 304 + case 1: /* j_s.d */ 305 + case 2: /* jl_s */ 306 + case 3: /* jl_s.d */ 307 + state->target = get_reg(FIELD_S_B(state->words[0]), 308 + regs, cregs); 309 + state->delay_slot = subopcode & 1; 310 + state->flow = (subopcode >= 2) ? 311 + direct_call : indirect_jump; 312 + break; 313 + case 7: 314 + switch (BITS(state->words[0], 8, 10)) { 315 + case 4: /* jeq_s [blink] */ 316 + case 5: /* jne_s [blink] */ 317 + case 6: /* j_s [blink] */ 318 + case 7: /* j_s.d [blink] */ 319 + state->delay_slot = (subopcode == 7); 320 + state->flow = indirect_jump; 321 + state->target = get_reg(31, regs, cregs); 322 + default: 323 + break; 324 + } 325 + default: 326 + break; 327 + } 328 + break; 329 + 330 + case op_LD_S: /* LD_S c, [b, u7] */ 331 + state->src1 = get_reg(FIELD_S_B(state->words[0]), regs, cregs); 332 + state->src2 = FIELD_S_u7(state->words[0]); 333 + state->dest = FIELD_S_C(state->words[0]); 334 + break; 335 + 336 + case op_LDB_S: 337 + case op_STB_S: 338 + /* no further handling required as byte accesses should not 339 + * cause an unaligned access exception */ 340 + state->zz = 1; 341 + break; 342 + 343 + case op_LDWX_S: /* LDWX_S c, [b, u6] */ 344 + state->x = 1; 345 + /* intentional fall-through */ 346 + 347 + case op_LDW_S: /* LDW_S c, [b, u6] */ 348 + state->zz = 2; 349 + state->src1 = get_reg(FIELD_S_B(state->words[0]), regs, cregs); 350 + state->src2 = FIELD_S_u6(state->words[0]); 351 + state->dest = FIELD_S_C(state->words[0]); 352 + break; 353 + 354 + case op_ST_S: /* ST_S c, [b, u7] */ 355 + state->write = 1; 356 + state->src1 = get_reg(FIELD_S_C(state->words[0]), regs, cregs); 357 + state->src2 = get_reg(FIELD_S_B(state->words[0]), regs, cregs); 358 + state->src3 = FIELD_S_u7(state->words[0]); 359 + break; 360 + 361 + case op_STW_S: /* STW_S c,[b,u6] */ 362 + state->write = 1; 363 + state->zz = 2; 364 + state->src1 = get_reg(FIELD_S_C(state->words[0]), regs, cregs); 365 + state->src2 = get_reg(FIELD_S_B(state->words[0]), regs, cregs); 366 + state->src3 = FIELD_S_u6(state->words[0]); 367 + break; 368 + 369 + case op_SP: /* LD_S|LDB_S b,[sp,u7], ST_S|STB_S b,[sp,u7] */ 370 + /* note: we are ignoring possibility of: 371 + * ADD_S, SUB_S, PUSH_S, POP_S as these should not 372 + * cause unaliged exception anyway */ 373 + state->write = BITS(state->words[0], 6, 6); 374 + state->zz = BITS(state->words[0], 5, 5); 375 + if (state->zz) 376 + break; /* byte accesses should not come here */ 377 + if (!state->write) { 378 + state->src1 = get_reg(28, regs, cregs); 379 + state->src2 = FIELD_S_u7(state->words[0]); 380 + state->dest = FIELD_S_B(state->words[0]); 381 + } else { 382 + state->src1 = get_reg(FIELD_S_B(state->words[0]), regs, 383 + cregs); 384 + state->src2 = get_reg(28, regs, cregs); 385 + state->src3 = FIELD_S_u7(state->words[0]); 386 + } 387 + break; 388 + 389 + case op_GP: /* LD_S|LDB_S|LDW_S r0,[gp,s11/s9/s10] */ 390 + /* note: ADD_S r0, gp, s11 is ignored */ 391 + state->zz = BITS(state->words[0], 9, 10); 392 + state->src1 = get_reg(26, regs, cregs); 393 + state->src2 = state->zz ? FIELD_S_s10(state->words[0]) : 394 + FIELD_S_s11(state->words[0]); 395 + state->dest = 0; 396 + break; 397 + 398 + case op_Pcl: /* LD_S b,[pcl,u10] */ 399 + state->src1 = regs->ret & ~3; 400 + state->src2 = FIELD_S_u10(state->words[0]); 401 + state->dest = FIELD_S_B(state->words[0]); 402 + break; 403 + 404 + case op_BR_S: 405 + state->target = FIELD_S_s8(state->words[0]) + (addr & ~0x03); 406 + state->flow = direct_jump; 407 + state->is_branch = 1; 408 + break; 409 + 410 + case op_B_S: 411 + fieldA = (BITS(state->words[0], 9, 10) == 3) ? 412 + FIELD_S_s7(state->words[0]) : 413 + FIELD_S_s10(state->words[0]); 414 + state->target = fieldA + (addr & ~0x03); 415 + state->flow = direct_jump; 416 + state->is_branch = 1; 417 + break; 418 + 419 + case op_BL_S: 420 + state->target = FIELD_S_s13(state->words[0]) + (addr & ~0x03); 421 + state->flow = direct_call; 422 + state->is_branch = 1; 423 + break; 424 + 425 + default: 426 + break; 427 + } 428 + 429 + if (bytes_not_copied <= (8 - state->instr_len)) 430 + return; 431 + 432 + fault: state->fault = 1; 433 + } 434 + 435 + long __kprobes get_reg(int reg, struct pt_regs *regs, 436 + struct callee_regs *cregs) 437 + { 438 + long *p; 439 + 440 + if (reg <= 12) { 441 + p = &regs->r0; 442 + return p[-reg]; 443 + } 444 + 445 + if (cregs && (reg <= 25)) { 446 + p = &cregs->r13; 447 + return p[13-reg]; 448 + } 449 + 450 + if (reg == 26) 451 + return regs->r26; 452 + if (reg == 27) 453 + return regs->fp; 454 + if (reg == 28) 455 + return regs->sp; 456 + if (reg == 31) 457 + return regs->blink; 458 + 459 + return 0; 460 + } 461 + 462 + void __kprobes set_reg(int reg, long val, struct pt_regs *regs, 463 + struct callee_regs *cregs) 464 + { 465 + long *p; 466 + 467 + switch (reg) { 468 + case 0 ... 12: 469 + p = &regs->r0; 470 + p[-reg] = val; 471 + break; 472 + case 13 ... 25: 473 + if (cregs) { 474 + p = &cregs->r13; 475 + p[13-reg] = val; 476 + } 477 + break; 478 + case 26: 479 + regs->r26 = val; 480 + break; 481 + case 27: 482 + regs->fp = val; 483 + break; 484 + case 28: 485 + regs->sp = val; 486 + break; 487 + case 31: 488 + regs->blink = val; 489 + break; 490 + default: 491 + break; 492 + } 493 + } 494 + 495 + /* 496 + * Disassembles the insn at @pc and sets @next_pc to next PC (which could be 497 + * @pc +2/4/6 (ARCompact ISA allows free intermixing of 16/32 bit insns). 498 + * 499 + * If @pc is a branch 500 + * -@tgt_if_br is set to branch target. 501 + * -If branch has delay slot, @next_pc updated with actual next PC. 502 + * 503 + */ 504 + int __kprobes disasm_next_pc(unsigned long pc, struct pt_regs *regs, 505 + struct callee_regs *cregs, 506 + unsigned long *next_pc, unsigned long *tgt_if_br) 507 + { 508 + struct disasm_state instr; 509 + 510 + memset(&instr, 0, sizeof(struct disasm_state)); 511 + disasm_instr(pc, &instr, 0, regs, cregs); 512 + 513 + *next_pc = pc + instr.instr_len; 514 + 515 + /* Instruction with possible two targets branch, jump and loop */ 516 + if (instr.is_branch) 517 + *tgt_if_br = instr.target; 518 + 519 + /* For the instructions with delay slots, the fall through is the 520 + * instruction following the instruction in delay slot. 521 + */ 522 + if (instr.delay_slot) { 523 + struct disasm_state instr_d; 524 + 525 + disasm_instr(*next_pc, &instr_d, 0, regs, cregs); 526 + 527 + *next_pc += instr_d.instr_len; 528 + } 529 + 530 + /* Zero Overhead Loop - end of the loop */ 531 + if (!(regs->status32 & STATUS32_L) && (*next_pc == regs->lp_end) 532 + && (regs->lp_count > 1)) { 533 + *next_pc = regs->lp_start; 534 + } 535 + 536 + return instr.is_branch; 537 + } 538 + 539 + #endif /* CONFIG_KGDB || CONFIG_MISALIGN_ACCESS || CONFIG_KPROBES */