162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * arch/arm/probes/kprobes/actions-arm.c
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2006, 2007 Motorola Inc.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci/*
962306a36Sopenharmony_ci * We do not have hardware single-stepping on ARM, This
1062306a36Sopenharmony_ci * effort is further complicated by the ARM not having a
1162306a36Sopenharmony_ci * "next PC" register.  Instructions that change the PC
1262306a36Sopenharmony_ci * can't be safely single-stepped in a MP environment, so
1362306a36Sopenharmony_ci * we have a lot of work to do:
1462306a36Sopenharmony_ci *
1562306a36Sopenharmony_ci * In the prepare phase:
1662306a36Sopenharmony_ci *   *) If it is an instruction that does anything
1762306a36Sopenharmony_ci *      with the CPU mode, we reject it for a kprobe.
1862306a36Sopenharmony_ci *      (This is out of laziness rather than need.  The
1962306a36Sopenharmony_ci *      instructions could be simulated.)
2062306a36Sopenharmony_ci *
2162306a36Sopenharmony_ci *   *) Otherwise, decode the instruction rewriting its
2262306a36Sopenharmony_ci *      registers to take fixed, ordered registers and
2362306a36Sopenharmony_ci *      setting a handler for it to run the instruction.
2462306a36Sopenharmony_ci *
2562306a36Sopenharmony_ci * In the execution phase by an instruction's handler:
2662306a36Sopenharmony_ci *
2762306a36Sopenharmony_ci *   *) If the PC is written to by the instruction, the
2862306a36Sopenharmony_ci *      instruction must be fully simulated in software.
2962306a36Sopenharmony_ci *
3062306a36Sopenharmony_ci *   *) Otherwise, a modified form of the instruction is
3162306a36Sopenharmony_ci *      directly executed.  Its handler calls the
3262306a36Sopenharmony_ci *      instruction in insn[0].  In insn[1] is a
3362306a36Sopenharmony_ci *      "mov pc, lr" to return.
3462306a36Sopenharmony_ci *
3562306a36Sopenharmony_ci *      Before calling, load up the reordered registers
3662306a36Sopenharmony_ci *      from the original instruction's registers.  If one
3762306a36Sopenharmony_ci *      of the original input registers is the PC, compute
3862306a36Sopenharmony_ci *      and adjust the appropriate input register.
3962306a36Sopenharmony_ci *
4062306a36Sopenharmony_ci *	After call completes, copy the output registers to
4162306a36Sopenharmony_ci *      the original instruction's original registers.
4262306a36Sopenharmony_ci *
4362306a36Sopenharmony_ci * We don't use a real breakpoint instruction since that
4462306a36Sopenharmony_ci * would have us in the kernel go from SVC mode to SVC
4562306a36Sopenharmony_ci * mode losing the link register.  Instead we use an
4662306a36Sopenharmony_ci * undefined instruction.  To simplify processing, the
4762306a36Sopenharmony_ci * undefined instruction used for kprobes must be reserved
4862306a36Sopenharmony_ci * exclusively for kprobes use.
4962306a36Sopenharmony_ci *
5062306a36Sopenharmony_ci * TODO: ifdef out some instruction decoding based on architecture.
5162306a36Sopenharmony_ci */
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci#include <linux/kernel.h>
5462306a36Sopenharmony_ci#include <linux/kprobes.h>
5562306a36Sopenharmony_ci#include <linux/ptrace.h>
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci#include "../decode-arm.h"
5862306a36Sopenharmony_ci#include "core.h"
5962306a36Sopenharmony_ci#include "checkers.h"
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci#if  __LINUX_ARM_ARCH__ >= 6
6262306a36Sopenharmony_ci#define BLX(reg)	"blx	"reg"		\n\t"
6362306a36Sopenharmony_ci#else
6462306a36Sopenharmony_ci#define BLX(reg)	"mov	lr, pc		\n\t"	\
6562306a36Sopenharmony_ci			"mov	pc, "reg"	\n\t"
6662306a36Sopenharmony_ci#endif
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_cistatic void __kprobes
6962306a36Sopenharmony_ciemulate_ldrdstrd(probes_opcode_t insn,
7062306a36Sopenharmony_ci	struct arch_probes_insn *asi, struct pt_regs *regs)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	unsigned long pc = regs->ARM_pc + 4;
7362306a36Sopenharmony_ci	int rt = (insn >> 12) & 0xf;
7462306a36Sopenharmony_ci	int rn = (insn >> 16) & 0xf;
7562306a36Sopenharmony_ci	int rm = insn & 0xf;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	register unsigned long rtv asm("r0") = regs->uregs[rt];
7862306a36Sopenharmony_ci	register unsigned long rt2v asm("r1") = regs->uregs[rt+1];
7962306a36Sopenharmony_ci	register unsigned long rnv asm("r2") = (rn == 15) ? pc
8062306a36Sopenharmony_ci							  : regs->uregs[rn];
8162306a36Sopenharmony_ci	register unsigned long rmv asm("r3") = regs->uregs[rm];
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	__asm__ __volatile__ (
8462306a36Sopenharmony_ci		BLX("%[fn]")
8562306a36Sopenharmony_ci		: "=r" (rtv), "=r" (rt2v), "=r" (rnv)
8662306a36Sopenharmony_ci		: "0" (rtv), "1" (rt2v), "2" (rnv), "r" (rmv),
8762306a36Sopenharmony_ci		  [fn] "r" (asi->insn_fn)
8862306a36Sopenharmony_ci		: "lr", "memory", "cc"
8962306a36Sopenharmony_ci	);
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	regs->uregs[rt] = rtv;
9262306a36Sopenharmony_ci	regs->uregs[rt+1] = rt2v;
9362306a36Sopenharmony_ci	if (is_writeback(insn))
9462306a36Sopenharmony_ci		regs->uregs[rn] = rnv;
9562306a36Sopenharmony_ci}
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_cistatic void __kprobes
9862306a36Sopenharmony_ciemulate_ldr(probes_opcode_t insn,
9962306a36Sopenharmony_ci	struct arch_probes_insn *asi, struct pt_regs *regs)
10062306a36Sopenharmony_ci{
10162306a36Sopenharmony_ci	unsigned long pc = regs->ARM_pc + 4;
10262306a36Sopenharmony_ci	int rt = (insn >> 12) & 0xf;
10362306a36Sopenharmony_ci	int rn = (insn >> 16) & 0xf;
10462306a36Sopenharmony_ci	int rm = insn & 0xf;
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	register unsigned long rtv asm("r0");
10762306a36Sopenharmony_ci	register unsigned long rnv asm("r2") = (rn == 15) ? pc
10862306a36Sopenharmony_ci							  : regs->uregs[rn];
10962306a36Sopenharmony_ci	register unsigned long rmv asm("r3") = regs->uregs[rm];
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	__asm__ __volatile__ (
11262306a36Sopenharmony_ci		BLX("%[fn]")
11362306a36Sopenharmony_ci		: "=r" (rtv), "=r" (rnv)
11462306a36Sopenharmony_ci		: "1" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn)
11562306a36Sopenharmony_ci		: "lr", "memory", "cc"
11662306a36Sopenharmony_ci	);
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	if (rt == 15)
11962306a36Sopenharmony_ci		load_write_pc(rtv, regs);
12062306a36Sopenharmony_ci	else
12162306a36Sopenharmony_ci		regs->uregs[rt] = rtv;
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	if (is_writeback(insn))
12462306a36Sopenharmony_ci		regs->uregs[rn] = rnv;
12562306a36Sopenharmony_ci}
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_cistatic void __kprobes
12862306a36Sopenharmony_ciemulate_str(probes_opcode_t insn,
12962306a36Sopenharmony_ci	struct arch_probes_insn *asi, struct pt_regs *regs)
13062306a36Sopenharmony_ci{
13162306a36Sopenharmony_ci	unsigned long rtpc = regs->ARM_pc - 4 + str_pc_offset;
13262306a36Sopenharmony_ci	unsigned long rnpc = regs->ARM_pc + 4;
13362306a36Sopenharmony_ci	int rt = (insn >> 12) & 0xf;
13462306a36Sopenharmony_ci	int rn = (insn >> 16) & 0xf;
13562306a36Sopenharmony_ci	int rm = insn & 0xf;
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	register unsigned long rtv asm("r0") = (rt == 15) ? rtpc
13862306a36Sopenharmony_ci							  : regs->uregs[rt];
13962306a36Sopenharmony_ci	register unsigned long rnv asm("r2") = (rn == 15) ? rnpc
14062306a36Sopenharmony_ci							  : regs->uregs[rn];
14162306a36Sopenharmony_ci	register unsigned long rmv asm("r3") = regs->uregs[rm];
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	__asm__ __volatile__ (
14462306a36Sopenharmony_ci		BLX("%[fn]")
14562306a36Sopenharmony_ci		: "=r" (rnv)
14662306a36Sopenharmony_ci		: "r" (rtv), "0" (rnv), "r" (rmv), [fn] "r" (asi->insn_fn)
14762306a36Sopenharmony_ci		: "lr", "memory", "cc"
14862306a36Sopenharmony_ci	);
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	if (is_writeback(insn))
15162306a36Sopenharmony_ci		regs->uregs[rn] = rnv;
15262306a36Sopenharmony_ci}
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_cistatic void __kprobes
15562306a36Sopenharmony_ciemulate_rd12rn16rm0rs8_rwflags(probes_opcode_t insn,
15662306a36Sopenharmony_ci	struct arch_probes_insn *asi, struct pt_regs *regs)
15762306a36Sopenharmony_ci{
15862306a36Sopenharmony_ci	unsigned long pc = regs->ARM_pc + 4;
15962306a36Sopenharmony_ci	int rd = (insn >> 12) & 0xf;
16062306a36Sopenharmony_ci	int rn = (insn >> 16) & 0xf;
16162306a36Sopenharmony_ci	int rm = insn & 0xf;
16262306a36Sopenharmony_ci	int rs = (insn >> 8) & 0xf;
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	register unsigned long rdv asm("r0") = regs->uregs[rd];
16562306a36Sopenharmony_ci	register unsigned long rnv asm("r2") = (rn == 15) ? pc
16662306a36Sopenharmony_ci							  : regs->uregs[rn];
16762306a36Sopenharmony_ci	register unsigned long rmv asm("r3") = (rm == 15) ? pc
16862306a36Sopenharmony_ci							  : regs->uregs[rm];
16962306a36Sopenharmony_ci	register unsigned long rsv asm("r1") = regs->uregs[rs];
17062306a36Sopenharmony_ci	unsigned long cpsr = regs->ARM_cpsr;
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci	__asm__ __volatile__ (
17362306a36Sopenharmony_ci		"msr	cpsr_fs, %[cpsr]	\n\t"
17462306a36Sopenharmony_ci		BLX("%[fn]")
17562306a36Sopenharmony_ci		"mrs	%[cpsr], cpsr		\n\t"
17662306a36Sopenharmony_ci		: "=r" (rdv), [cpsr] "=r" (cpsr)
17762306a36Sopenharmony_ci		: "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv),
17862306a36Sopenharmony_ci		  "1" (cpsr), [fn] "r" (asi->insn_fn)
17962306a36Sopenharmony_ci		: "lr", "memory", "cc"
18062306a36Sopenharmony_ci	);
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	if (rd == 15)
18362306a36Sopenharmony_ci		alu_write_pc(rdv, regs);
18462306a36Sopenharmony_ci	else
18562306a36Sopenharmony_ci		regs->uregs[rd] = rdv;
18662306a36Sopenharmony_ci	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
18762306a36Sopenharmony_ci}
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_cistatic void __kprobes
19062306a36Sopenharmony_ciemulate_rd12rn16rm0_rwflags_nopc(probes_opcode_t insn,
19162306a36Sopenharmony_ci	struct arch_probes_insn *asi, struct pt_regs *regs)
19262306a36Sopenharmony_ci{
19362306a36Sopenharmony_ci	int rd = (insn >> 12) & 0xf;
19462306a36Sopenharmony_ci	int rn = (insn >> 16) & 0xf;
19562306a36Sopenharmony_ci	int rm = insn & 0xf;
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	register unsigned long rdv asm("r0") = regs->uregs[rd];
19862306a36Sopenharmony_ci	register unsigned long rnv asm("r2") = regs->uregs[rn];
19962306a36Sopenharmony_ci	register unsigned long rmv asm("r3") = regs->uregs[rm];
20062306a36Sopenharmony_ci	unsigned long cpsr = regs->ARM_cpsr;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	__asm__ __volatile__ (
20362306a36Sopenharmony_ci		"msr	cpsr_fs, %[cpsr]	\n\t"
20462306a36Sopenharmony_ci		BLX("%[fn]")
20562306a36Sopenharmony_ci		"mrs	%[cpsr], cpsr		\n\t"
20662306a36Sopenharmony_ci		: "=r" (rdv), [cpsr] "=r" (cpsr)
20762306a36Sopenharmony_ci		: "0" (rdv), "r" (rnv), "r" (rmv),
20862306a36Sopenharmony_ci		  "1" (cpsr), [fn] "r" (asi->insn_fn)
20962306a36Sopenharmony_ci		: "lr", "memory", "cc"
21062306a36Sopenharmony_ci	);
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	regs->uregs[rd] = rdv;
21362306a36Sopenharmony_ci	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
21462306a36Sopenharmony_ci}
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_cistatic void __kprobes
21762306a36Sopenharmony_ciemulate_rd16rn12rm0rs8_rwflags_nopc(probes_opcode_t insn,
21862306a36Sopenharmony_ci	struct arch_probes_insn *asi,
21962306a36Sopenharmony_ci	struct pt_regs *regs)
22062306a36Sopenharmony_ci{
22162306a36Sopenharmony_ci	int rd = (insn >> 16) & 0xf;
22262306a36Sopenharmony_ci	int rn = (insn >> 12) & 0xf;
22362306a36Sopenharmony_ci	int rm = insn & 0xf;
22462306a36Sopenharmony_ci	int rs = (insn >> 8) & 0xf;
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	register unsigned long rdv asm("r2") = regs->uregs[rd];
22762306a36Sopenharmony_ci	register unsigned long rnv asm("r0") = regs->uregs[rn];
22862306a36Sopenharmony_ci	register unsigned long rmv asm("r3") = regs->uregs[rm];
22962306a36Sopenharmony_ci	register unsigned long rsv asm("r1") = regs->uregs[rs];
23062306a36Sopenharmony_ci	unsigned long cpsr = regs->ARM_cpsr;
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci	__asm__ __volatile__ (
23362306a36Sopenharmony_ci		"msr	cpsr_fs, %[cpsr]	\n\t"
23462306a36Sopenharmony_ci		BLX("%[fn]")
23562306a36Sopenharmony_ci		"mrs	%[cpsr], cpsr		\n\t"
23662306a36Sopenharmony_ci		: "=r" (rdv), [cpsr] "=r" (cpsr)
23762306a36Sopenharmony_ci		: "0" (rdv), "r" (rnv), "r" (rmv), "r" (rsv),
23862306a36Sopenharmony_ci		  "1" (cpsr), [fn] "r" (asi->insn_fn)
23962306a36Sopenharmony_ci		: "lr", "memory", "cc"
24062306a36Sopenharmony_ci	);
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci	regs->uregs[rd] = rdv;
24362306a36Sopenharmony_ci	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
24462306a36Sopenharmony_ci}
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_cistatic void __kprobes
24762306a36Sopenharmony_ciemulate_rd12rm0_noflags_nopc(probes_opcode_t insn,
24862306a36Sopenharmony_ci	struct arch_probes_insn *asi, struct pt_regs *regs)
24962306a36Sopenharmony_ci{
25062306a36Sopenharmony_ci	int rd = (insn >> 12) & 0xf;
25162306a36Sopenharmony_ci	int rm = insn & 0xf;
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	register unsigned long rdv asm("r0") = regs->uregs[rd];
25462306a36Sopenharmony_ci	register unsigned long rmv asm("r3") = regs->uregs[rm];
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	__asm__ __volatile__ (
25762306a36Sopenharmony_ci		BLX("%[fn]")
25862306a36Sopenharmony_ci		: "=r" (rdv)
25962306a36Sopenharmony_ci		: "0" (rdv), "r" (rmv), [fn] "r" (asi->insn_fn)
26062306a36Sopenharmony_ci		: "lr", "memory", "cc"
26162306a36Sopenharmony_ci	);
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci	regs->uregs[rd] = rdv;
26462306a36Sopenharmony_ci}
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_cistatic void __kprobes
26762306a36Sopenharmony_ciemulate_rdlo12rdhi16rn0rm8_rwflags_nopc(probes_opcode_t insn,
26862306a36Sopenharmony_ci	struct arch_probes_insn *asi,
26962306a36Sopenharmony_ci	struct pt_regs *regs)
27062306a36Sopenharmony_ci{
27162306a36Sopenharmony_ci	int rdlo = (insn >> 12) & 0xf;
27262306a36Sopenharmony_ci	int rdhi = (insn >> 16) & 0xf;
27362306a36Sopenharmony_ci	int rn = insn & 0xf;
27462306a36Sopenharmony_ci	int rm = (insn >> 8) & 0xf;
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	register unsigned long rdlov asm("r0") = regs->uregs[rdlo];
27762306a36Sopenharmony_ci	register unsigned long rdhiv asm("r2") = regs->uregs[rdhi];
27862306a36Sopenharmony_ci	register unsigned long rnv asm("r3") = regs->uregs[rn];
27962306a36Sopenharmony_ci	register unsigned long rmv asm("r1") = regs->uregs[rm];
28062306a36Sopenharmony_ci	unsigned long cpsr = regs->ARM_cpsr;
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	__asm__ __volatile__ (
28362306a36Sopenharmony_ci		"msr	cpsr_fs, %[cpsr]	\n\t"
28462306a36Sopenharmony_ci		BLX("%[fn]")
28562306a36Sopenharmony_ci		"mrs	%[cpsr], cpsr		\n\t"
28662306a36Sopenharmony_ci		: "=r" (rdlov), "=r" (rdhiv), [cpsr] "=r" (cpsr)
28762306a36Sopenharmony_ci		: "0" (rdlov), "1" (rdhiv), "r" (rnv), "r" (rmv),
28862306a36Sopenharmony_ci		  "2" (cpsr), [fn] "r" (asi->insn_fn)
28962306a36Sopenharmony_ci		: "lr", "memory", "cc"
29062306a36Sopenharmony_ci	);
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci	regs->uregs[rdlo] = rdlov;
29362306a36Sopenharmony_ci	regs->uregs[rdhi] = rdhiv;
29462306a36Sopenharmony_ci	regs->ARM_cpsr = (regs->ARM_cpsr & ~APSR_MASK) | (cpsr & APSR_MASK);
29562306a36Sopenharmony_ci}
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ciconst union decode_action kprobes_arm_actions[NUM_PROBES_ARM_ACTIONS] = {
29862306a36Sopenharmony_ci	[PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop},
29962306a36Sopenharmony_ci	[PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop},
30062306a36Sopenharmony_ci	[PROBES_BRANCH_IMM] = {.handler = simulate_blx1},
30162306a36Sopenharmony_ci	[PROBES_MRS] = {.handler = simulate_mrs},
30262306a36Sopenharmony_ci	[PROBES_BRANCH_REG] = {.handler = simulate_blx2bx},
30362306a36Sopenharmony_ci	[PROBES_CLZ] = {.handler = emulate_rd12rm0_noflags_nopc},
30462306a36Sopenharmony_ci	[PROBES_SATURATING_ARITHMETIC] = {
30562306a36Sopenharmony_ci		.handler = emulate_rd12rn16rm0_rwflags_nopc},
30662306a36Sopenharmony_ci	[PROBES_MUL1] = {.handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc},
30762306a36Sopenharmony_ci	[PROBES_MUL2] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc},
30862306a36Sopenharmony_ci	[PROBES_SWP] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
30962306a36Sopenharmony_ci	[PROBES_LDRSTRD] = {.handler = emulate_ldrdstrd},
31062306a36Sopenharmony_ci	[PROBES_LOAD_EXTRA] = {.handler = emulate_ldr},
31162306a36Sopenharmony_ci	[PROBES_LOAD] = {.handler = emulate_ldr},
31262306a36Sopenharmony_ci	[PROBES_STORE_EXTRA] = {.handler = emulate_str},
31362306a36Sopenharmony_ci	[PROBES_STORE] = {.handler = emulate_str},
31462306a36Sopenharmony_ci	[PROBES_MOV_IP_SP] = {.handler = simulate_mov_ipsp},
31562306a36Sopenharmony_ci	[PROBES_DATA_PROCESSING_REG] = {
31662306a36Sopenharmony_ci		.handler = emulate_rd12rn16rm0rs8_rwflags},
31762306a36Sopenharmony_ci	[PROBES_DATA_PROCESSING_IMM] = {
31862306a36Sopenharmony_ci		.handler = emulate_rd12rn16rm0rs8_rwflags},
31962306a36Sopenharmony_ci	[PROBES_MOV_HALFWORD] = {.handler = emulate_rd12rm0_noflags_nopc},
32062306a36Sopenharmony_ci	[PROBES_SEV] = {.handler = probes_emulate_none},
32162306a36Sopenharmony_ci	[PROBES_WFE] = {.handler = probes_simulate_nop},
32262306a36Sopenharmony_ci	[PROBES_SATURATE] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
32362306a36Sopenharmony_ci	[PROBES_REV] = {.handler = emulate_rd12rm0_noflags_nopc},
32462306a36Sopenharmony_ci	[PROBES_MMI] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
32562306a36Sopenharmony_ci	[PROBES_PACK] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
32662306a36Sopenharmony_ci	[PROBES_EXTEND] = {.handler = emulate_rd12rm0_noflags_nopc},
32762306a36Sopenharmony_ci	[PROBES_EXTEND_ADD] = {.handler = emulate_rd12rn16rm0_rwflags_nopc},
32862306a36Sopenharmony_ci	[PROBES_MUL_ADD_LONG] = {
32962306a36Sopenharmony_ci		.handler = emulate_rdlo12rdhi16rn0rm8_rwflags_nopc},
33062306a36Sopenharmony_ci	[PROBES_MUL_ADD] = {.handler = emulate_rd16rn12rm0rs8_rwflags_nopc},
33162306a36Sopenharmony_ci	[PROBES_BITFIELD] = {.handler = emulate_rd12rm0_noflags_nopc},
33262306a36Sopenharmony_ci	[PROBES_BRANCH] = {.handler = simulate_bbl},
33362306a36Sopenharmony_ci	[PROBES_LDMSTM] = {.decoder = kprobe_decode_ldmstm}
33462306a36Sopenharmony_ci};
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ciconst struct decode_checker *kprobes_arm_checkers[] = {arm_stack_checker, arm_regs_checker, NULL};
337