18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * arch/arm/probes/kprobes/checkers-common.c
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2014 Huawei Inc.
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/kernel.h>
98c2ecf20Sopenharmony_ci#include "../decode.h"
108c2ecf20Sopenharmony_ci#include "../decode-arm.h"
118c2ecf20Sopenharmony_ci#include "checkers.h"
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_cienum probes_insn checker_stack_use_none(probes_opcode_t insn,
148c2ecf20Sopenharmony_ci		struct arch_probes_insn *asi,
158c2ecf20Sopenharmony_ci		const struct decode_header *h)
168c2ecf20Sopenharmony_ci{
178c2ecf20Sopenharmony_ci	asi->stack_space = 0;
188c2ecf20Sopenharmony_ci	return INSN_GOOD_NO_SLOT;
198c2ecf20Sopenharmony_ci}
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_cienum probes_insn checker_stack_use_unknown(probes_opcode_t insn,
228c2ecf20Sopenharmony_ci		struct arch_probes_insn *asi,
238c2ecf20Sopenharmony_ci		const struct decode_header *h)
248c2ecf20Sopenharmony_ci{
258c2ecf20Sopenharmony_ci	asi->stack_space = -1;
268c2ecf20Sopenharmony_ci	return INSN_GOOD_NO_SLOT;
278c2ecf20Sopenharmony_ci}
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci#ifdef CONFIG_THUMB2_KERNEL
308c2ecf20Sopenharmony_cienum probes_insn checker_stack_use_imm_0xx(probes_opcode_t insn,
318c2ecf20Sopenharmony_ci		struct arch_probes_insn *asi,
328c2ecf20Sopenharmony_ci		const struct decode_header *h)
338c2ecf20Sopenharmony_ci{
348c2ecf20Sopenharmony_ci	int imm = insn & 0xff;
358c2ecf20Sopenharmony_ci	asi->stack_space = imm;
368c2ecf20Sopenharmony_ci	return INSN_GOOD_NO_SLOT;
378c2ecf20Sopenharmony_ci}
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci/*
408c2ecf20Sopenharmony_ci * Different from other insn uses imm8, the real addressing offset of
418c2ecf20Sopenharmony_ci * STRD in T32 encoding should be imm8 * 4. See ARMARM description.
428c2ecf20Sopenharmony_ci */
438c2ecf20Sopenharmony_cistatic enum probes_insn checker_stack_use_t32strd(probes_opcode_t insn,
448c2ecf20Sopenharmony_ci		struct arch_probes_insn *asi,
458c2ecf20Sopenharmony_ci		const struct decode_header *h)
468c2ecf20Sopenharmony_ci{
478c2ecf20Sopenharmony_ci	int imm = insn & 0xff;
488c2ecf20Sopenharmony_ci	asi->stack_space = imm << 2;
498c2ecf20Sopenharmony_ci	return INSN_GOOD_NO_SLOT;
508c2ecf20Sopenharmony_ci}
518c2ecf20Sopenharmony_ci#else
528c2ecf20Sopenharmony_cienum probes_insn checker_stack_use_imm_x0x(probes_opcode_t insn,
538c2ecf20Sopenharmony_ci		struct arch_probes_insn *asi,
548c2ecf20Sopenharmony_ci		const struct decode_header *h)
558c2ecf20Sopenharmony_ci{
568c2ecf20Sopenharmony_ci	int imm = ((insn & 0xf00) >> 4) + (insn & 0xf);
578c2ecf20Sopenharmony_ci	asi->stack_space = imm;
588c2ecf20Sopenharmony_ci	return INSN_GOOD_NO_SLOT;
598c2ecf20Sopenharmony_ci}
608c2ecf20Sopenharmony_ci#endif
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_cienum probes_insn checker_stack_use_imm_xxx(probes_opcode_t insn,
638c2ecf20Sopenharmony_ci		struct arch_probes_insn *asi,
648c2ecf20Sopenharmony_ci		const struct decode_header *h)
658c2ecf20Sopenharmony_ci{
668c2ecf20Sopenharmony_ci	int imm = insn & 0xfff;
678c2ecf20Sopenharmony_ci	asi->stack_space = imm;
688c2ecf20Sopenharmony_ci	return INSN_GOOD_NO_SLOT;
698c2ecf20Sopenharmony_ci}
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_cienum probes_insn checker_stack_use_stmdx(probes_opcode_t insn,
728c2ecf20Sopenharmony_ci		struct arch_probes_insn *asi,
738c2ecf20Sopenharmony_ci		const struct decode_header *h)
748c2ecf20Sopenharmony_ci{
758c2ecf20Sopenharmony_ci	unsigned int reglist = insn & 0xffff;
768c2ecf20Sopenharmony_ci	int pbit = insn & (1 << 24);
778c2ecf20Sopenharmony_ci	asi->stack_space = (hweight32(reglist) - (!pbit ? 1 : 0)) * 4;
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	return INSN_GOOD_NO_SLOT;
808c2ecf20Sopenharmony_ci}
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ciconst union decode_action stack_check_actions[] = {
838c2ecf20Sopenharmony_ci	[STACK_USE_NONE] = {.decoder = checker_stack_use_none},
848c2ecf20Sopenharmony_ci	[STACK_USE_UNKNOWN] = {.decoder = checker_stack_use_unknown},
858c2ecf20Sopenharmony_ci#ifdef CONFIG_THUMB2_KERNEL
868c2ecf20Sopenharmony_ci	[STACK_USE_FIXED_0XX] = {.decoder = checker_stack_use_imm_0xx},
878c2ecf20Sopenharmony_ci	[STACK_USE_T32STRD] = {.decoder = checker_stack_use_t32strd},
888c2ecf20Sopenharmony_ci#else
898c2ecf20Sopenharmony_ci	[STACK_USE_FIXED_X0X] = {.decoder = checker_stack_use_imm_x0x},
908c2ecf20Sopenharmony_ci#endif
918c2ecf20Sopenharmony_ci	[STACK_USE_FIXED_XXX] = {.decoder = checker_stack_use_imm_xxx},
928c2ecf20Sopenharmony_ci	[STACK_USE_STMDX] = {.decoder = checker_stack_use_stmdx},
938c2ecf20Sopenharmony_ci};
94