// SPDX-License-Identifier: GPL-2.0-only /* * several functions that help interpret ARC instructions * used for unaligned accesses, kprobes and kgdb * * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
*/
/* disasm_instr: Analyses instruction at addr, stores * findings in *state
*/ void __kprobes disasm_instr(unsignedlong addr, struct disasm_state *state, int userspace, struct pt_regs *regs, struct callee_regs *cregs)
{ int fieldA = 0; int fieldC = 0, fieldCisReg = 0;
uint16_t word1 = 0, word0 = 0; int subopcode, is_linked, op_format;
uint16_t *ins_ptr;
uint16_t ins_buf[4]; int bytes_not_copied = 0;
memset(state, 0, sizeof(struct disasm_state));
/* This fetches the upper part of the 32 bit instruction
* in both the cases of Little Endian or Big Endian configurations. */ if (userspace) {
bytes_not_copied = copy_from_user(ins_buf,
(constvoid __user *) addr, 8); if (bytes_not_copied > 6) goto fault;
ins_ptr = ins_buf;
} else {
ins_ptr = (uint16_t *) addr;
}
word1 = *((uint16_t *)addr);
state->major_opcode = (word1 >> 11) & 0x1F;
/* Check if the instruction is 32 bit or 16 bit instruction */ if (state->major_opcode < 0x0B) { if (bytes_not_copied > 4) goto fault;
state->instr_len = 4;
word0 = *((uint16_t *)(addr+2));
state->words[0] = (word1 << 16) | word0;
} else {
state->instr_len = 2;
state->words[0] = word1;
}
/* Read the second word in case of limm */
word1 = *((uint16_t *)(addr + state->instr_len));
word0 = *((uint16_t *)(addr + state->instr_len + 2));
state->words[1] = (word1 << 16) | word0;
switch (state->major_opcode) { case op_Bcc:
state->is_branch = 1;
fieldC = fieldC << 1;
fieldC += (addr & ~0x03);
state->is_branch = 1;
state->flow = direct_jump;
state->target = fieldC;
} /* For Unconditional lp, next pc is the fall through
* which is updated */ break;
case10: /* MOV */ /* still need to check for limm to extract instr len */ /* MOV is special case because it only takes 2 args */ switch (BITS(state->words[0], 22, 23)) { case0: /* OP a,b,c */ if (FIELD_C(state->words[0]) == REG_LIMM)
state->instr_len += 4; break; case1: /* OP a,b,u6 */ break; case2: /* OP b,b,s12 */ break; case3: /* OP.cc b,b,c/u6 */ if ((!IS_BIT(state->words[0], 5)) &&
(FIELD_C(state->words[0]) == REG_LIMM))
state->instr_len += 4; break;
} break;
default: /* Not a Load, Jump or Loop instruction */ /* still need to check for limm to extract instr len */ switch (BITS(state->words[0], 22, 23)) { case0: /* OP a,b,c */ if ((FIELD_B(state->words[0]) == REG_LIMM) ||
(FIELD_C(state->words[0]) == REG_LIMM))
state->instr_len += 4; break; case1: /* OP a,b,u6 */ break; case2: /* OP b,b,s12 */ break; case3: /* OP.cc b,b,c/u6 */ if ((!IS_BIT(state->words[0], 5)) &&
((FIELD_B(state->words[0]) == REG_LIMM) ||
(FIELD_C(state->words[0]) == REG_LIMM)))
state->instr_len += 4; break;
} break;
} break;
case op_LDB_S: case op_STB_S: /* no further handling required as byte accesses should not
* cause an unaligned access exception */
state->zz = 1; break;
/* * Disassembles the insn at @pc and sets @next_pc to next PC (which could be * @pc +2/4/6 (ARCompact ISA allows free intermixing of 16/32 bit insns). * * If @pc is a branch * -@tgt_if_br is set to branch target. * -If branch has delay slot, @next_pc updated with actual next PC.
*/ int __kprobes disasm_next_pc(unsignedlong pc, struct pt_regs *regs, struct callee_regs *cregs, unsignedlong *next_pc, unsignedlong *tgt_if_br)
{ struct disasm_state instr;
disasm_instr(pc, &instr, 0, regs, cregs);
*next_pc = pc + instr.instr_len;
/* Instruction with possible two targets branch, jump and loop */ if (instr.is_branch)
*tgt_if_br = instr.target;
/* For the instructions with delay slots, the fall through is the * instruction following the instruction in delay slot.
*/ if (instr.delay_slot) { struct disasm_state instr_d;
disasm_instr(*next_pc, &instr_d, 0, regs, cregs);
*next_pc += instr_d.instr_len;
}
/* Zero Overhead Loop - end of the loop */ if (!(regs->status32 & STATUS32_L) && (*next_pc == regs->lp_end)
&& (regs->lp_count > 1)) {
*next_pc = regs->lp_start;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.