18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
28c2ecf20Sopenharmony_ci#ifndef _ASM_X86_KPROBES_H
38c2ecf20Sopenharmony_ci#define _ASM_X86_KPROBES_H
48c2ecf20Sopenharmony_ci/*
58c2ecf20Sopenharmony_ci *  Kernel Probes (KProbes)
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Copyright (C) IBM Corporation, 2002, 2004
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * See arch/x86/kernel/kprobes.c for x86 kprobes history.
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <asm-generic/kprobes.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#ifdef CONFIG_KPROBES
158c2ecf20Sopenharmony_ci#include <linux/types.h>
168c2ecf20Sopenharmony_ci#include <linux/ptrace.h>
178c2ecf20Sopenharmony_ci#include <linux/percpu.h>
188c2ecf20Sopenharmony_ci#include <asm/text-patching.h>
198c2ecf20Sopenharmony_ci#include <asm/insn.h>
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#define  __ARCH_WANT_KPROBES_INSN_SLOT
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_cistruct pt_regs;
248c2ecf20Sopenharmony_cistruct kprobe;
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_citypedef u8 kprobe_opcode_t;
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci#define MAX_STACK_SIZE 64
298c2ecf20Sopenharmony_ci#define CUR_STACK_SIZE(ADDR) \
308c2ecf20Sopenharmony_ci	(current_top_of_stack() - (unsigned long)(ADDR))
318c2ecf20Sopenharmony_ci#define MIN_STACK_SIZE(ADDR)				\
328c2ecf20Sopenharmony_ci	(MAX_STACK_SIZE < CUR_STACK_SIZE(ADDR) ?	\
338c2ecf20Sopenharmony_ci	 MAX_STACK_SIZE : CUR_STACK_SIZE(ADDR))
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#define flush_insn_slot(p)	do { } while (0)
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci/* optinsn template addresses */
388c2ecf20Sopenharmony_ciextern __visible kprobe_opcode_t optprobe_template_entry[];
398c2ecf20Sopenharmony_ciextern __visible kprobe_opcode_t optprobe_template_clac[];
408c2ecf20Sopenharmony_ciextern __visible kprobe_opcode_t optprobe_template_val[];
418c2ecf20Sopenharmony_ciextern __visible kprobe_opcode_t optprobe_template_call[];
428c2ecf20Sopenharmony_ciextern __visible kprobe_opcode_t optprobe_template_end[];
438c2ecf20Sopenharmony_ci#define MAX_OPTIMIZED_LENGTH (MAX_INSN_SIZE + DISP32_SIZE)
448c2ecf20Sopenharmony_ci#define MAX_OPTINSN_SIZE 				\
458c2ecf20Sopenharmony_ci	(((unsigned long)optprobe_template_end -	\
468c2ecf20Sopenharmony_ci	  (unsigned long)optprobe_template_entry) +	\
478c2ecf20Sopenharmony_ci	 MAX_OPTIMIZED_LENGTH + JMP32_INSN_SIZE)
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ciextern const int kretprobe_blacklist_size;
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_civoid arch_remove_kprobe(struct kprobe *p);
528c2ecf20Sopenharmony_ciasmlinkage void kretprobe_trampoline(void);
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ciextern void arch_kprobe_override_function(struct pt_regs *regs);
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci/* Architecture specific copy of original instruction*/
578c2ecf20Sopenharmony_cistruct arch_specific_insn {
588c2ecf20Sopenharmony_ci	/* copy of the original instruction */
598c2ecf20Sopenharmony_ci	kprobe_opcode_t *insn;
608c2ecf20Sopenharmony_ci	/*
618c2ecf20Sopenharmony_ci	 * boostable = 0: This instruction type is not boostable.
628c2ecf20Sopenharmony_ci	 * boostable = 1: This instruction has been boosted: we have
638c2ecf20Sopenharmony_ci	 * added a relative jump after the instruction copy in insn,
648c2ecf20Sopenharmony_ci	 * so no single-step and fixup are needed (unless there's
658c2ecf20Sopenharmony_ci	 * a post_handler).
668c2ecf20Sopenharmony_ci	 */
678c2ecf20Sopenharmony_ci	unsigned boostable:1;
688c2ecf20Sopenharmony_ci	unsigned char size;	/* The size of insn */
698c2ecf20Sopenharmony_ci	union {
708c2ecf20Sopenharmony_ci		unsigned char opcode;
718c2ecf20Sopenharmony_ci		struct {
728c2ecf20Sopenharmony_ci			unsigned char type;
738c2ecf20Sopenharmony_ci		} jcc;
748c2ecf20Sopenharmony_ci		struct {
758c2ecf20Sopenharmony_ci			unsigned char type;
768c2ecf20Sopenharmony_ci			unsigned char asize;
778c2ecf20Sopenharmony_ci		} loop;
788c2ecf20Sopenharmony_ci		struct {
798c2ecf20Sopenharmony_ci			unsigned char reg;
808c2ecf20Sopenharmony_ci		} indirect;
818c2ecf20Sopenharmony_ci	};
828c2ecf20Sopenharmony_ci	s32 rel32;	/* relative offset must be s32, s16, or s8 */
838c2ecf20Sopenharmony_ci	void (*emulate_op)(struct kprobe *p, struct pt_regs *regs);
848c2ecf20Sopenharmony_ci	/* Number of bytes of text poked */
858c2ecf20Sopenharmony_ci	int tp_len;
868c2ecf20Sopenharmony_ci};
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_cistruct arch_optimized_insn {
898c2ecf20Sopenharmony_ci	/* copy of the original instructions */
908c2ecf20Sopenharmony_ci	kprobe_opcode_t copied_insn[DISP32_SIZE];
918c2ecf20Sopenharmony_ci	/* detour code buffer */
928c2ecf20Sopenharmony_ci	kprobe_opcode_t *insn;
938c2ecf20Sopenharmony_ci	/* the size of instructions copied to detour code buffer */
948c2ecf20Sopenharmony_ci	size_t size;
958c2ecf20Sopenharmony_ci};
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci/* Return true (!0) if optinsn is prepared for optimization. */
988c2ecf20Sopenharmony_cistatic inline int arch_prepared_optinsn(struct arch_optimized_insn *optinsn)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	return optinsn->size;
1018c2ecf20Sopenharmony_ci}
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_cistruct prev_kprobe {
1048c2ecf20Sopenharmony_ci	struct kprobe *kp;
1058c2ecf20Sopenharmony_ci	unsigned long status;
1068c2ecf20Sopenharmony_ci	unsigned long old_flags;
1078c2ecf20Sopenharmony_ci	unsigned long saved_flags;
1088c2ecf20Sopenharmony_ci};
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci/* per-cpu kprobe control block */
1118c2ecf20Sopenharmony_cistruct kprobe_ctlblk {
1128c2ecf20Sopenharmony_ci	unsigned long kprobe_status;
1138c2ecf20Sopenharmony_ci	unsigned long kprobe_old_flags;
1148c2ecf20Sopenharmony_ci	unsigned long kprobe_saved_flags;
1158c2ecf20Sopenharmony_ci	struct prev_kprobe prev_kprobe;
1168c2ecf20Sopenharmony_ci};
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ciextern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
1198c2ecf20Sopenharmony_ciextern int kprobe_exceptions_notify(struct notifier_block *self,
1208c2ecf20Sopenharmony_ci				    unsigned long val, void *data);
1218c2ecf20Sopenharmony_ciextern int kprobe_int3_handler(struct pt_regs *regs);
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci#else
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_cistatic inline int kprobe_debug_handler(struct pt_regs *regs) { return 0; }
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci#endif /* CONFIG_KPROBES */
1288c2ecf20Sopenharmony_ci#endif /* _ASM_X86_KPROBES_H */
129