162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * arch/arm/probes/kprobes/checkers-common.c
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2014 Huawei Inc.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/kernel.h>
962306a36Sopenharmony_ci#include "../decode.h"
1062306a36Sopenharmony_ci#include "../decode-arm.h"
1162306a36Sopenharmony_ci#include "checkers.h"
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_cienum probes_insn checker_stack_use_none(probes_opcode_t insn,
1462306a36Sopenharmony_ci		struct arch_probes_insn *asi,
1562306a36Sopenharmony_ci		const struct decode_header *h)
1662306a36Sopenharmony_ci{
1762306a36Sopenharmony_ci	asi->stack_space = 0;
1862306a36Sopenharmony_ci	return INSN_GOOD_NO_SLOT;
1962306a36Sopenharmony_ci}
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_cienum probes_insn checker_stack_use_unknown(probes_opcode_t insn,
2262306a36Sopenharmony_ci		struct arch_probes_insn *asi,
2362306a36Sopenharmony_ci		const struct decode_header *h)
2462306a36Sopenharmony_ci{
2562306a36Sopenharmony_ci	asi->stack_space = -1;
2662306a36Sopenharmony_ci	return INSN_GOOD_NO_SLOT;
2762306a36Sopenharmony_ci}
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#ifdef CONFIG_THUMB2_KERNEL
3062306a36Sopenharmony_cienum probes_insn checker_stack_use_imm_0xx(probes_opcode_t insn,
3162306a36Sopenharmony_ci		struct arch_probes_insn *asi,
3262306a36Sopenharmony_ci		const struct decode_header *h)
3362306a36Sopenharmony_ci{
3462306a36Sopenharmony_ci	int imm = insn & 0xff;
3562306a36Sopenharmony_ci	asi->stack_space = imm;
3662306a36Sopenharmony_ci	return INSN_GOOD_NO_SLOT;
3762306a36Sopenharmony_ci}
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci/*
4062306a36Sopenharmony_ci * Different from other insn uses imm8, the real addressing offset of
4162306a36Sopenharmony_ci * STRD in T32 encoding should be imm8 * 4. See ARMARM description.
4262306a36Sopenharmony_ci */
4362306a36Sopenharmony_cistatic enum probes_insn checker_stack_use_t32strd(probes_opcode_t insn,
4462306a36Sopenharmony_ci		struct arch_probes_insn *asi,
4562306a36Sopenharmony_ci		const struct decode_header *h)
4662306a36Sopenharmony_ci{
4762306a36Sopenharmony_ci	int imm = insn & 0xff;
4862306a36Sopenharmony_ci	asi->stack_space = imm << 2;
4962306a36Sopenharmony_ci	return INSN_GOOD_NO_SLOT;
5062306a36Sopenharmony_ci}
5162306a36Sopenharmony_ci#else
5262306a36Sopenharmony_cienum probes_insn checker_stack_use_imm_x0x(probes_opcode_t insn,
5362306a36Sopenharmony_ci		struct arch_probes_insn *asi,
5462306a36Sopenharmony_ci		const struct decode_header *h)
5562306a36Sopenharmony_ci{
5662306a36Sopenharmony_ci	int imm = ((insn & 0xf00) >> 4) + (insn & 0xf);
5762306a36Sopenharmony_ci	asi->stack_space = imm;
5862306a36Sopenharmony_ci	return INSN_GOOD_NO_SLOT;
5962306a36Sopenharmony_ci}
6062306a36Sopenharmony_ci#endif
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_cienum probes_insn checker_stack_use_imm_xxx(probes_opcode_t insn,
6362306a36Sopenharmony_ci		struct arch_probes_insn *asi,
6462306a36Sopenharmony_ci		const struct decode_header *h)
6562306a36Sopenharmony_ci{
6662306a36Sopenharmony_ci	int imm = insn & 0xfff;
6762306a36Sopenharmony_ci	asi->stack_space = imm;
6862306a36Sopenharmony_ci	return INSN_GOOD_NO_SLOT;
6962306a36Sopenharmony_ci}
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_cienum probes_insn checker_stack_use_stmdx(probes_opcode_t insn,
7262306a36Sopenharmony_ci		struct arch_probes_insn *asi,
7362306a36Sopenharmony_ci		const struct decode_header *h)
7462306a36Sopenharmony_ci{
7562306a36Sopenharmony_ci	unsigned int reglist = insn & 0xffff;
7662306a36Sopenharmony_ci	int pbit = insn & (1 << 24);
7762306a36Sopenharmony_ci	asi->stack_space = (hweight32(reglist) - (!pbit ? 1 : 0)) * 4;
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	return INSN_GOOD_NO_SLOT;
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ciconst union decode_action stack_check_actions[] = {
8362306a36Sopenharmony_ci	[STACK_USE_NONE] = {.decoder = checker_stack_use_none},
8462306a36Sopenharmony_ci	[STACK_USE_UNKNOWN] = {.decoder = checker_stack_use_unknown},
8562306a36Sopenharmony_ci#ifdef CONFIG_THUMB2_KERNEL
8662306a36Sopenharmony_ci	[STACK_USE_FIXED_0XX] = {.decoder = checker_stack_use_imm_0xx},
8762306a36Sopenharmony_ci	[STACK_USE_T32STRD] = {.decoder = checker_stack_use_t32strd},
8862306a36Sopenharmony_ci#else
8962306a36Sopenharmony_ci	[STACK_USE_FIXED_X0X] = {.decoder = checker_stack_use_imm_x0x},
9062306a36Sopenharmony_ci#endif
9162306a36Sopenharmony_ci	[STACK_USE_FIXED_XXX] = {.decoder = checker_stack_use_imm_xxx},
9262306a36Sopenharmony_ci	[STACK_USE_STMDX] = {.decoder = checker_stack_use_stmdx},
9362306a36Sopenharmony_ci};
94