1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * arch/arm/probes/kprobes/checkers-thumb.c 4 * 5 * Copyright (C) 2014 Huawei Inc. 6 */ 7 8 #include <linux/kernel.h> 9 #include "../decode.h" 10 #include "../decode-thumb.h" 11 #include "checkers.h" 12 13 static enum probes_insn __kprobes t32_check_stack(probes_opcode_t insn, 14 struct arch_probes_insn *asi, 15 const struct decode_header *h) 16 { 17 /* 18 * PROBES_T32_LDMSTM, PROBES_T32_LDRDSTRD and PROBES_T32_LDRSTR 19 * may get here. Simply mark all normal insns as STACK_USE_NONE. 20 */ 21 static const union decode_item table[] = { 22 23 /* 24 * First, filter out all ldr insns to make our life easier. 25 * Following load insns may come here: 26 * LDM, LDRD, LDR. 27 * In T32 encoding, bit 20 is enough for distinguishing 28 * load and store. All load insns have this bit set, when 29 * all store insns have this bit clear. 30 */ 31 DECODE_CUSTOM (0x00100000, 0x00100000, STACK_USE_NONE), 32 33 /* 34 * Mark all 'STR{,B,H}, Rt, [Rn, Rm]' as STACK_USE_UNKNOWN 35 * if Rn or Rm is SP. T32 doesn't encode STRD. 36 */ 37 /* xx | Rn | Rt | | Rm |*/ 38 /* STR (register) 1111 1000 0100 xxxx xxxx 0000 00xx xxxx */ 39 /* STRB (register) 1111 1000 0000 xxxx xxxx 0000 00xx xxxx */ 40 /* STRH (register) 1111 1000 0010 xxxx xxxx 0000 00xx xxxx */ 41 /* INVALID INSN 1111 1000 0110 xxxx xxxx 0000 00xx xxxx */ 42 /* By Introducing INVALID INSN, bit 21 and 22 can be ignored. */ 43 DECODE_OR (0xff9f0fc0, 0xf80d0000), 44 DECODE_CUSTOM (0xff900fcf, 0xf800000d, STACK_USE_UNKNOWN), 45 46 47 /* xx | Rn | Rt | PUW| imm8 |*/ 48 /* STR (imm 8) 1111 1000 0100 1101 xxxx 110x xxxx xxxx */ 49 /* STRB (imm 8) 1111 1000 0000 1101 xxxx 110x xxxx xxxx */ 50 /* STRH (imm 8) 1111 1000 0010 1101 xxxx 110x xxxx xxxx */ 51 /* INVALID INSN 1111 1000 0110 1101 xxxx 110x xxxx xxxx */ 52 /* Only consider U == 0 and P == 1: strx rx, [sp, #-<imm>] */ 53 DECODE_CUSTOM (0xff9f0e00, 0xf80d0c00, STACK_USE_FIXED_0XX), 54 55 /* For STR{,B,H} (imm 12), offset is always positive, so ignore them. */ 56 57 /* P U W | Rn | Rt | Rt2| imm8 |*/ 58 /* STRD (immediate) 1110 1001 01x0 1101 xxxx xxxx xxxx xxxx */ 59 /* 60 * Only consider U == 0 and P == 1. 61 * Also note that STRD in T32 encoding is special: 62 * imm = ZeroExtend(imm8:'00', 32) 63 */ 64 DECODE_CUSTOM (0xffdf0000, 0xe94d0000, STACK_USE_T32STRD), 65 66 /* | Rn | */ 67 /* STMDB 1110 1001 00x0 1101 xxxx xxxx xxxx xxxx */ 68 DECODE_CUSTOM (0xffdf0000, 0xe90d0000, STACK_USE_STMDX), 69 70 /* fall through */ 71 DECODE_CUSTOM (0, 0, STACK_USE_NONE), 72 DECODE_END 73 }; 74 75 return probes_decode_insn(insn, asi, table, false, false, stack_check_actions, NULL); 76 } 77 78 const struct decode_checker t32_stack_checker[NUM_PROBES_T32_ACTIONS] = { 79 [PROBES_T32_LDMSTM] = {.checker = t32_check_stack}, 80 [PROBES_T32_LDRDSTRD] = {.checker = t32_check_stack}, 81 [PROBES_T32_LDRSTR] = {.checker = t32_check_stack}, 82 }; 83 84 /* 85 * See following comments. This insn must be 'push'. 86 */ 87 static enum probes_insn __kprobes t16_check_stack(probes_opcode_t insn, 88 struct arch_probes_insn *asi, 89 const struct decode_header *h) 90 { 91 unsigned int reglist = insn & 0x1ff; 92 asi->stack_space = hweight32(reglist) * 4; 93 return INSN_GOOD; 94 } 95 96 /* 97 * T16 encoding is simple: only the 'push' insn can need extra stack space. 98 * Other insns, like str, can only use r0-r7 as Rn. 99 */ 100 const struct decode_checker t16_stack_checker[NUM_PROBES_T16_ACTIONS] = { 101 [PROBES_T16_PUSH] = {.checker = t16_check_stack}, 102 };