162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  Kernel Probes Jump Optimization (Optprobes)
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) IBM Corporation, 2002, 2004
662306a36Sopenharmony_ci * Copyright (C) Hitachi Ltd., 2012
762306a36Sopenharmony_ci * Copyright (C) Huawei Inc., 2014
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/kprobes.h>
1162306a36Sopenharmony_ci#include <linux/jump_label.h>
1262306a36Sopenharmony_ci#include <asm/kprobes.h>
1362306a36Sopenharmony_ci#include <asm/cacheflush.h>
1462306a36Sopenharmony_ci/* for arm_gen_branch */
1562306a36Sopenharmony_ci#include <asm/insn.h>
1662306a36Sopenharmony_ci/* for patch_text */
1762306a36Sopenharmony_ci#include <asm/patch.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#include "core.h"
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci/*
2262306a36Sopenharmony_ci * See register_usage_flags. If the probed instruction doesn't use PC,
2362306a36Sopenharmony_ci * we can copy it into template and have it executed directly without
2462306a36Sopenharmony_ci * simulation or emulation.
2562306a36Sopenharmony_ci */
2662306a36Sopenharmony_ci#define ARM_REG_PC	15
2762306a36Sopenharmony_ci#define can_kprobe_direct_exec(m)	(!test_bit(ARM_REG_PC, &(m)))
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci/*
3062306a36Sopenharmony_ci * NOTE: the first sub and add instruction will be modified according
3162306a36Sopenharmony_ci * to the stack cost of the instruction.
3262306a36Sopenharmony_ci */
3362306a36Sopenharmony_ciasm (
3462306a36Sopenharmony_ci			".global optprobe_template_entry\n"
3562306a36Sopenharmony_ci			"optprobe_template_entry:\n"
3662306a36Sopenharmony_ci			".global optprobe_template_sub_sp\n"
3762306a36Sopenharmony_ci			"optprobe_template_sub_sp:"
3862306a36Sopenharmony_ci			"	sub	sp, sp, #0xff\n"
3962306a36Sopenharmony_ci			"	stmia	sp, {r0 - r14} \n"
4062306a36Sopenharmony_ci			".global optprobe_template_add_sp\n"
4162306a36Sopenharmony_ci			"optprobe_template_add_sp:"
4262306a36Sopenharmony_ci			"	add	r3, sp, #0xff\n"
4362306a36Sopenharmony_ci			"	str	r3, [sp, #52]\n"
4462306a36Sopenharmony_ci			"	mrs	r4, cpsr\n"
4562306a36Sopenharmony_ci			"	str	r4, [sp, #64]\n"
4662306a36Sopenharmony_ci			"	mov	r1, sp\n"
4762306a36Sopenharmony_ci			"	ldr	r0, 1f\n"
4862306a36Sopenharmony_ci			"	ldr	r2, 2f\n"
4962306a36Sopenharmony_ci			/*
5062306a36Sopenharmony_ci			 * AEABI requires an 8-bytes alignment stack. If
5162306a36Sopenharmony_ci			 * SP % 8 != 0 (SP % 4 == 0 should be ensured),
5262306a36Sopenharmony_ci			 * alloc more bytes here.
5362306a36Sopenharmony_ci			 */
5462306a36Sopenharmony_ci			"	and	r4, sp, #4\n"
5562306a36Sopenharmony_ci			"	sub	sp, sp, r4\n"
5662306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 5
5762306a36Sopenharmony_ci			"	blx	r2\n"
5862306a36Sopenharmony_ci#else
5962306a36Sopenharmony_ci			"	mov     lr, pc\n"
6062306a36Sopenharmony_ci			"	mov	pc, r2\n"
6162306a36Sopenharmony_ci#endif
6262306a36Sopenharmony_ci			"	add	sp, sp, r4\n"
6362306a36Sopenharmony_ci			"	ldr	r1, [sp, #64]\n"
6462306a36Sopenharmony_ci			"	tst	r1, #"__stringify(PSR_T_BIT)"\n"
6562306a36Sopenharmony_ci			"	ldrne	r2, [sp, #60]\n"
6662306a36Sopenharmony_ci			"	orrne	r2, #1\n"
6762306a36Sopenharmony_ci			"	strne	r2, [sp, #60] @ set bit0 of PC for thumb\n"
6862306a36Sopenharmony_ci			"	msr	cpsr_cxsf, r1\n"
6962306a36Sopenharmony_ci			".global optprobe_template_restore_begin\n"
7062306a36Sopenharmony_ci			"optprobe_template_restore_begin:\n"
7162306a36Sopenharmony_ci			"	ldmia	sp, {r0 - r15}\n"
7262306a36Sopenharmony_ci			".global optprobe_template_restore_orig_insn\n"
7362306a36Sopenharmony_ci			"optprobe_template_restore_orig_insn:\n"
7462306a36Sopenharmony_ci			"	nop\n"
7562306a36Sopenharmony_ci			".global optprobe_template_restore_end\n"
7662306a36Sopenharmony_ci			"optprobe_template_restore_end:\n"
7762306a36Sopenharmony_ci			"	nop\n"
7862306a36Sopenharmony_ci			".global optprobe_template_val\n"
7962306a36Sopenharmony_ci			"optprobe_template_val:\n"
8062306a36Sopenharmony_ci			"1:	.long 0\n"
8162306a36Sopenharmony_ci			".global optprobe_template_call\n"
8262306a36Sopenharmony_ci			"optprobe_template_call:\n"
8362306a36Sopenharmony_ci			"2:	.long 0\n"
8462306a36Sopenharmony_ci			".global optprobe_template_end\n"
8562306a36Sopenharmony_ci			"optprobe_template_end:\n");
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci#define TMPL_VAL_IDX \
8862306a36Sopenharmony_ci	((unsigned long *)optprobe_template_val - (unsigned long *)optprobe_template_entry)
8962306a36Sopenharmony_ci#define TMPL_CALL_IDX \
9062306a36Sopenharmony_ci	((unsigned long *)optprobe_template_call - (unsigned long *)optprobe_template_entry)
9162306a36Sopenharmony_ci#define TMPL_END_IDX \
9262306a36Sopenharmony_ci	((unsigned long *)optprobe_template_end - (unsigned long *)optprobe_template_entry)
9362306a36Sopenharmony_ci#define TMPL_ADD_SP \
9462306a36Sopenharmony_ci	((unsigned long *)optprobe_template_add_sp - (unsigned long *)optprobe_template_entry)
9562306a36Sopenharmony_ci#define TMPL_SUB_SP \
9662306a36Sopenharmony_ci	((unsigned long *)optprobe_template_sub_sp - (unsigned long *)optprobe_template_entry)
9762306a36Sopenharmony_ci#define TMPL_RESTORE_BEGIN \
9862306a36Sopenharmony_ci	((unsigned long *)optprobe_template_restore_begin - (unsigned long *)optprobe_template_entry)
9962306a36Sopenharmony_ci#define TMPL_RESTORE_ORIGN_INSN \
10062306a36Sopenharmony_ci	((unsigned long *)optprobe_template_restore_orig_insn - (unsigned long *)optprobe_template_entry)
10162306a36Sopenharmony_ci#define TMPL_RESTORE_END \
10262306a36Sopenharmony_ci	((unsigned long *)optprobe_template_restore_end - (unsigned long *)optprobe_template_entry)
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci/*
10562306a36Sopenharmony_ci * ARM can always optimize an instruction when using ARM ISA, except
10662306a36Sopenharmony_ci * instructions like 'str r0, [sp, r1]' which store to stack and unable
10762306a36Sopenharmony_ci * to determine stack space consumption statically.
10862306a36Sopenharmony_ci */
10962306a36Sopenharmony_ciint arch_prepared_optinsn(struct arch_optimized_insn *optinsn)
11062306a36Sopenharmony_ci{
11162306a36Sopenharmony_ci	return optinsn->insn != NULL;
11262306a36Sopenharmony_ci}
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci/*
11562306a36Sopenharmony_ci * In ARM ISA, kprobe opt always replace one instruction (4 bytes
11662306a36Sopenharmony_ci * aligned and 4 bytes long). It is impossible to encounter another
11762306a36Sopenharmony_ci * kprobe in the address range. So always return 0.
11862306a36Sopenharmony_ci */
11962306a36Sopenharmony_ciint arch_check_optimized_kprobe(struct optimized_kprobe *op)
12062306a36Sopenharmony_ci{
12162306a36Sopenharmony_ci	return 0;
12262306a36Sopenharmony_ci}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci/* Caller must ensure addr & 3 == 0 */
12562306a36Sopenharmony_cistatic int can_optimize(struct kprobe *kp)
12662306a36Sopenharmony_ci{
12762306a36Sopenharmony_ci	if (kp->ainsn.stack_space < 0)
12862306a36Sopenharmony_ci		return 0;
12962306a36Sopenharmony_ci	/*
13062306a36Sopenharmony_ci	 * 255 is the biggest imm can be used in 'sub r0, r0, #<imm>'.
13162306a36Sopenharmony_ci	 * Number larger than 255 needs special encoding.
13262306a36Sopenharmony_ci	 */
13362306a36Sopenharmony_ci	if (kp->ainsn.stack_space > 255 - sizeof(struct pt_regs))
13462306a36Sopenharmony_ci		return 0;
13562306a36Sopenharmony_ci	return 1;
13662306a36Sopenharmony_ci}
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci/* Free optimized instruction slot */
13962306a36Sopenharmony_cistatic void
14062306a36Sopenharmony_ci__arch_remove_optimized_kprobe(struct optimized_kprobe *op, int dirty)
14162306a36Sopenharmony_ci{
14262306a36Sopenharmony_ci	if (op->optinsn.insn) {
14362306a36Sopenharmony_ci		free_optinsn_slot(op->optinsn.insn, dirty);
14462306a36Sopenharmony_ci		op->optinsn.insn = NULL;
14562306a36Sopenharmony_ci	}
14662306a36Sopenharmony_ci}
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_cistatic void
14962306a36Sopenharmony_cioptimized_callback(struct optimized_kprobe *op, struct pt_regs *regs)
15062306a36Sopenharmony_ci{
15162306a36Sopenharmony_ci	unsigned long flags;
15262306a36Sopenharmony_ci	struct kprobe *p = &op->kp;
15362306a36Sopenharmony_ci	struct kprobe_ctlblk *kcb;
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	/* Save skipped registers */
15662306a36Sopenharmony_ci	regs->ARM_pc = (unsigned long)op->kp.addr;
15762306a36Sopenharmony_ci	regs->ARM_ORIG_r0 = ~0UL;
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	local_irq_save(flags);
16062306a36Sopenharmony_ci	kcb = get_kprobe_ctlblk();
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	if (kprobe_running()) {
16362306a36Sopenharmony_ci		kprobes_inc_nmissed_count(&op->kp);
16462306a36Sopenharmony_ci	} else {
16562306a36Sopenharmony_ci		__this_cpu_write(current_kprobe, &op->kp);
16662306a36Sopenharmony_ci		kcb->kprobe_status = KPROBE_HIT_ACTIVE;
16762306a36Sopenharmony_ci		opt_pre_handler(&op->kp, regs);
16862306a36Sopenharmony_ci		__this_cpu_write(current_kprobe, NULL);
16962306a36Sopenharmony_ci	}
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	/*
17262306a36Sopenharmony_ci	 * We singlestep the replaced instruction only when it can't be
17362306a36Sopenharmony_ci	 * executed directly during restore.
17462306a36Sopenharmony_ci	 */
17562306a36Sopenharmony_ci	if (!p->ainsn.kprobe_direct_exec)
17662306a36Sopenharmony_ci		op->kp.ainsn.insn_singlestep(p->opcode, &p->ainsn, regs);
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	local_irq_restore(flags);
17962306a36Sopenharmony_ci}
18062306a36Sopenharmony_ciNOKPROBE_SYMBOL(optimized_callback)
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ciint arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *orig)
18362306a36Sopenharmony_ci{
18462306a36Sopenharmony_ci	kprobe_opcode_t *code;
18562306a36Sopenharmony_ci	unsigned long rel_chk;
18662306a36Sopenharmony_ci	unsigned long val;
18762306a36Sopenharmony_ci	unsigned long stack_protect = sizeof(struct pt_regs);
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci	if (!can_optimize(orig))
19062306a36Sopenharmony_ci		return -EILSEQ;
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	code = get_optinsn_slot();
19362306a36Sopenharmony_ci	if (!code)
19462306a36Sopenharmony_ci		return -ENOMEM;
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	/*
19762306a36Sopenharmony_ci	 * Verify if the address gap is in 32MiB range, because this uses
19862306a36Sopenharmony_ci	 * a relative jump.
19962306a36Sopenharmony_ci	 *
20062306a36Sopenharmony_ci	 * kprobe opt use a 'b' instruction to branch to optinsn.insn.
20162306a36Sopenharmony_ci	 * According to ARM manual, branch instruction is:
20262306a36Sopenharmony_ci	 *
20362306a36Sopenharmony_ci	 *   31  28 27           24 23             0
20462306a36Sopenharmony_ci	 *  +------+---+---+---+---+----------------+
20562306a36Sopenharmony_ci	 *  | cond | 1 | 0 | 1 | 0 |      imm24     |
20662306a36Sopenharmony_ci	 *  +------+---+---+---+---+----------------+
20762306a36Sopenharmony_ci	 *
20862306a36Sopenharmony_ci	 * imm24 is a signed 24 bits integer. The real branch offset is computed
20962306a36Sopenharmony_ci	 * by: imm32 = SignExtend(imm24:'00', 32);
21062306a36Sopenharmony_ci	 *
21162306a36Sopenharmony_ci	 * So the maximum forward branch should be:
21262306a36Sopenharmony_ci	 *   (0x007fffff << 2) = 0x01fffffc =  0x1fffffc
21362306a36Sopenharmony_ci	 * The maximum backword branch should be:
21462306a36Sopenharmony_ci	 *   (0xff800000 << 2) = 0xfe000000 = -0x2000000
21562306a36Sopenharmony_ci	 *
21662306a36Sopenharmony_ci	 * We can simply check (rel & 0xfe000003):
21762306a36Sopenharmony_ci	 *  if rel is positive, (rel & 0xfe000000) shoule be 0
21862306a36Sopenharmony_ci	 *  if rel is negitive, (rel & 0xfe000000) should be 0xfe000000
21962306a36Sopenharmony_ci	 *  the last '3' is used for alignment checking.
22062306a36Sopenharmony_ci	 */
22162306a36Sopenharmony_ci	rel_chk = (unsigned long)((long)code -
22262306a36Sopenharmony_ci			(long)orig->addr + 8) & 0xfe000003;
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	if ((rel_chk != 0) && (rel_chk != 0xfe000000)) {
22562306a36Sopenharmony_ci		/*
22662306a36Sopenharmony_ci		 * Different from x86, we free code buf directly instead of
22762306a36Sopenharmony_ci		 * calling __arch_remove_optimized_kprobe() because
22862306a36Sopenharmony_ci		 * we have not fill any field in op.
22962306a36Sopenharmony_ci		 */
23062306a36Sopenharmony_ci		free_optinsn_slot(code, 0);
23162306a36Sopenharmony_ci		return -ERANGE;
23262306a36Sopenharmony_ci	}
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci	/* Copy arch-dep-instance from template. */
23562306a36Sopenharmony_ci	memcpy(code, (unsigned long *)optprobe_template_entry,
23662306a36Sopenharmony_ci			TMPL_END_IDX * sizeof(kprobe_opcode_t));
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci	/* Adjust buffer according to instruction. */
23962306a36Sopenharmony_ci	BUG_ON(orig->ainsn.stack_space < 0);
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	stack_protect += orig->ainsn.stack_space;
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	/* Should have been filtered by can_optimize(). */
24462306a36Sopenharmony_ci	BUG_ON(stack_protect > 255);
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	/* Create a 'sub sp, sp, #<stack_protect>' */
24762306a36Sopenharmony_ci	code[TMPL_SUB_SP] = __opcode_to_mem_arm(0xe24dd000 | stack_protect);
24862306a36Sopenharmony_ci	/* Create a 'add r3, sp, #<stack_protect>' */
24962306a36Sopenharmony_ci	code[TMPL_ADD_SP] = __opcode_to_mem_arm(0xe28d3000 | stack_protect);
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	/* Set probe information */
25262306a36Sopenharmony_ci	val = (unsigned long)op;
25362306a36Sopenharmony_ci	code[TMPL_VAL_IDX] = val;
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	/* Set probe function call */
25662306a36Sopenharmony_ci	val = (unsigned long)optimized_callback;
25762306a36Sopenharmony_ci	code[TMPL_CALL_IDX] = val;
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	/* If possible, copy insn and have it executed during restore */
26062306a36Sopenharmony_ci	orig->ainsn.kprobe_direct_exec = false;
26162306a36Sopenharmony_ci	if (can_kprobe_direct_exec(orig->ainsn.register_usage_flags)) {
26262306a36Sopenharmony_ci		kprobe_opcode_t final_branch = arm_gen_branch(
26362306a36Sopenharmony_ci				(unsigned long)(&code[TMPL_RESTORE_END]),
26462306a36Sopenharmony_ci				(unsigned long)(op->kp.addr) + 4);
26562306a36Sopenharmony_ci		if (final_branch != 0) {
26662306a36Sopenharmony_ci			/*
26762306a36Sopenharmony_ci			 * Replace original 'ldmia sp, {r0 - r15}' with
26862306a36Sopenharmony_ci			 * 'ldmia {r0 - r14}', restore all registers except pc.
26962306a36Sopenharmony_ci			 */
27062306a36Sopenharmony_ci			code[TMPL_RESTORE_BEGIN] = __opcode_to_mem_arm(0xe89d7fff);
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci			/* The original probed instruction */
27362306a36Sopenharmony_ci			code[TMPL_RESTORE_ORIGN_INSN] = __opcode_to_mem_arm(orig->opcode);
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci			/* Jump back to next instruction */
27662306a36Sopenharmony_ci			code[TMPL_RESTORE_END] = __opcode_to_mem_arm(final_branch);
27762306a36Sopenharmony_ci			orig->ainsn.kprobe_direct_exec = true;
27862306a36Sopenharmony_ci		}
27962306a36Sopenharmony_ci	}
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	flush_icache_range((unsigned long)code,
28262306a36Sopenharmony_ci			   (unsigned long)(&code[TMPL_END_IDX]));
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	/* Set op->optinsn.insn means prepared. */
28562306a36Sopenharmony_ci	op->optinsn.insn = code;
28662306a36Sopenharmony_ci	return 0;
28762306a36Sopenharmony_ci}
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_civoid __kprobes arch_optimize_kprobes(struct list_head *oplist)
29062306a36Sopenharmony_ci{
29162306a36Sopenharmony_ci	struct optimized_kprobe *op, *tmp;
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	list_for_each_entry_safe(op, tmp, oplist, list) {
29462306a36Sopenharmony_ci		unsigned long insn;
29562306a36Sopenharmony_ci		WARN_ON(kprobe_disabled(&op->kp));
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci		/*
29862306a36Sopenharmony_ci		 * Backup instructions which will be replaced
29962306a36Sopenharmony_ci		 * by jump address
30062306a36Sopenharmony_ci		 */
30162306a36Sopenharmony_ci		memcpy(op->optinsn.copied_insn, op->kp.addr,
30262306a36Sopenharmony_ci				RELATIVEJUMP_SIZE);
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci		insn = arm_gen_branch((unsigned long)op->kp.addr,
30562306a36Sopenharmony_ci				(unsigned long)op->optinsn.insn);
30662306a36Sopenharmony_ci		BUG_ON(insn == 0);
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci		/*
30962306a36Sopenharmony_ci		 * Make it a conditional branch if replaced insn
31062306a36Sopenharmony_ci		 * is consitional
31162306a36Sopenharmony_ci		 */
31262306a36Sopenharmony_ci		insn = (__mem_to_opcode_arm(
31362306a36Sopenharmony_ci			  op->optinsn.copied_insn[0]) & 0xf0000000) |
31462306a36Sopenharmony_ci			(insn & 0x0fffffff);
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci		/*
31762306a36Sopenharmony_ci		 * Similar to __arch_disarm_kprobe, operations which
31862306a36Sopenharmony_ci		 * removing breakpoints must be wrapped by stop_machine
31962306a36Sopenharmony_ci		 * to avoid racing.
32062306a36Sopenharmony_ci		 */
32162306a36Sopenharmony_ci		kprobes_remove_breakpoint(op->kp.addr, insn);
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci		list_del_init(&op->list);
32462306a36Sopenharmony_ci	}
32562306a36Sopenharmony_ci}
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_civoid arch_unoptimize_kprobe(struct optimized_kprobe *op)
32862306a36Sopenharmony_ci{
32962306a36Sopenharmony_ci	arch_arm_kprobe(&op->kp);
33062306a36Sopenharmony_ci}
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci/*
33362306a36Sopenharmony_ci * Recover original instructions and breakpoints from relative jumps.
33462306a36Sopenharmony_ci * Caller must call with locking kprobe_mutex.
33562306a36Sopenharmony_ci */
33662306a36Sopenharmony_civoid arch_unoptimize_kprobes(struct list_head *oplist,
33762306a36Sopenharmony_ci			    struct list_head *done_list)
33862306a36Sopenharmony_ci{
33962306a36Sopenharmony_ci	struct optimized_kprobe *op, *tmp;
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	list_for_each_entry_safe(op, tmp, oplist, list) {
34262306a36Sopenharmony_ci		arch_unoptimize_kprobe(op);
34362306a36Sopenharmony_ci		list_move(&op->list, done_list);
34462306a36Sopenharmony_ci	}
34562306a36Sopenharmony_ci}
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ciint arch_within_optimized_kprobe(struct optimized_kprobe *op,
34862306a36Sopenharmony_ci				 kprobe_opcode_t *addr)
34962306a36Sopenharmony_ci{
35062306a36Sopenharmony_ci	return (op->kp.addr <= addr &&
35162306a36Sopenharmony_ci		op->kp.addr + (RELATIVEJUMP_SIZE / sizeof(kprobe_opcode_t)) > addr);
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci}
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_civoid arch_remove_optimized_kprobe(struct optimized_kprobe *op)
35662306a36Sopenharmony_ci{
35762306a36Sopenharmony_ci	__arch_remove_optimized_kprobe(op, 1);
35862306a36Sopenharmony_ci}
359