xref: /OK3568_Linux_fs/kernel/arch/arm/probes/kprobes/checkers-common.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * arch/arm/probes/kprobes/checkers-common.c
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2014 Huawei Inc.
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/kernel.h>
9*4882a593Smuzhiyun #include "../decode.h"
10*4882a593Smuzhiyun #include "../decode-arm.h"
11*4882a593Smuzhiyun #include "checkers.h"
12*4882a593Smuzhiyun 
checker_stack_use_none(probes_opcode_t insn,struct arch_probes_insn * asi,const struct decode_header * h)13*4882a593Smuzhiyun enum probes_insn checker_stack_use_none(probes_opcode_t insn,
14*4882a593Smuzhiyun 		struct arch_probes_insn *asi,
15*4882a593Smuzhiyun 		const struct decode_header *h)
16*4882a593Smuzhiyun {
17*4882a593Smuzhiyun 	asi->stack_space = 0;
18*4882a593Smuzhiyun 	return INSN_GOOD_NO_SLOT;
19*4882a593Smuzhiyun }
20*4882a593Smuzhiyun 
checker_stack_use_unknown(probes_opcode_t insn,struct arch_probes_insn * asi,const struct decode_header * h)21*4882a593Smuzhiyun enum probes_insn checker_stack_use_unknown(probes_opcode_t insn,
22*4882a593Smuzhiyun 		struct arch_probes_insn *asi,
23*4882a593Smuzhiyun 		const struct decode_header *h)
24*4882a593Smuzhiyun {
25*4882a593Smuzhiyun 	asi->stack_space = -1;
26*4882a593Smuzhiyun 	return INSN_GOOD_NO_SLOT;
27*4882a593Smuzhiyun }
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #ifdef CONFIG_THUMB2_KERNEL
checker_stack_use_imm_0xx(probes_opcode_t insn,struct arch_probes_insn * asi,const struct decode_header * h)30*4882a593Smuzhiyun enum probes_insn checker_stack_use_imm_0xx(probes_opcode_t insn,
31*4882a593Smuzhiyun 		struct arch_probes_insn *asi,
32*4882a593Smuzhiyun 		const struct decode_header *h)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun 	int imm = insn & 0xff;
35*4882a593Smuzhiyun 	asi->stack_space = imm;
36*4882a593Smuzhiyun 	return INSN_GOOD_NO_SLOT;
37*4882a593Smuzhiyun }
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun /*
40*4882a593Smuzhiyun  * Different from other insn uses imm8, the real addressing offset of
41*4882a593Smuzhiyun  * STRD in T32 encoding should be imm8 * 4. See ARMARM description.
42*4882a593Smuzhiyun  */
checker_stack_use_t32strd(probes_opcode_t insn,struct arch_probes_insn * asi,const struct decode_header * h)43*4882a593Smuzhiyun enum probes_insn checker_stack_use_t32strd(probes_opcode_t insn,
44*4882a593Smuzhiyun 		struct arch_probes_insn *asi,
45*4882a593Smuzhiyun 		const struct decode_header *h)
46*4882a593Smuzhiyun {
47*4882a593Smuzhiyun 	int imm = insn & 0xff;
48*4882a593Smuzhiyun 	asi->stack_space = imm << 2;
49*4882a593Smuzhiyun 	return INSN_GOOD_NO_SLOT;
50*4882a593Smuzhiyun }
51*4882a593Smuzhiyun #else
checker_stack_use_imm_x0x(probes_opcode_t insn,struct arch_probes_insn * asi,const struct decode_header * h)52*4882a593Smuzhiyun enum probes_insn checker_stack_use_imm_x0x(probes_opcode_t insn,
53*4882a593Smuzhiyun 		struct arch_probes_insn *asi,
54*4882a593Smuzhiyun 		const struct decode_header *h)
55*4882a593Smuzhiyun {
56*4882a593Smuzhiyun 	int imm = ((insn & 0xf00) >> 4) + (insn & 0xf);
57*4882a593Smuzhiyun 	asi->stack_space = imm;
58*4882a593Smuzhiyun 	return INSN_GOOD_NO_SLOT;
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun #endif
61*4882a593Smuzhiyun 
checker_stack_use_imm_xxx(probes_opcode_t insn,struct arch_probes_insn * asi,const struct decode_header * h)62*4882a593Smuzhiyun enum probes_insn checker_stack_use_imm_xxx(probes_opcode_t insn,
63*4882a593Smuzhiyun 		struct arch_probes_insn *asi,
64*4882a593Smuzhiyun 		const struct decode_header *h)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun 	int imm = insn & 0xfff;
67*4882a593Smuzhiyun 	asi->stack_space = imm;
68*4882a593Smuzhiyun 	return INSN_GOOD_NO_SLOT;
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun 
checker_stack_use_stmdx(probes_opcode_t insn,struct arch_probes_insn * asi,const struct decode_header * h)71*4882a593Smuzhiyun enum probes_insn checker_stack_use_stmdx(probes_opcode_t insn,
72*4882a593Smuzhiyun 		struct arch_probes_insn *asi,
73*4882a593Smuzhiyun 		const struct decode_header *h)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun 	unsigned int reglist = insn & 0xffff;
76*4882a593Smuzhiyun 	int pbit = insn & (1 << 24);
77*4882a593Smuzhiyun 	asi->stack_space = (hweight32(reglist) - (!pbit ? 1 : 0)) * 4;
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	return INSN_GOOD_NO_SLOT;
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun const union decode_action stack_check_actions[] = {
83*4882a593Smuzhiyun 	[STACK_USE_NONE] = {.decoder = checker_stack_use_none},
84*4882a593Smuzhiyun 	[STACK_USE_UNKNOWN] = {.decoder = checker_stack_use_unknown},
85*4882a593Smuzhiyun #ifdef CONFIG_THUMB2_KERNEL
86*4882a593Smuzhiyun 	[STACK_USE_FIXED_0XX] = {.decoder = checker_stack_use_imm_0xx},
87*4882a593Smuzhiyun 	[STACK_USE_T32STRD] = {.decoder = checker_stack_use_t32strd},
88*4882a593Smuzhiyun #else
89*4882a593Smuzhiyun 	[STACK_USE_FIXED_X0X] = {.decoder = checker_stack_use_imm_x0x},
90*4882a593Smuzhiyun #endif
91*4882a593Smuzhiyun 	[STACK_USE_FIXED_XXX] = {.decoder = checker_stack_use_imm_xxx},
92*4882a593Smuzhiyun 	[STACK_USE_STMDX] = {.decoder = checker_stack_use_stmdx},
93*4882a593Smuzhiyun };
94