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