xref: /linux/arch/arc/kernel/kprobes.c (revision db70d9f9)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
24d86dfbbSVineet Gupta /*
34d86dfbbSVineet Gupta  * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
44d86dfbbSVineet Gupta  */
54d86dfbbSVineet Gupta 
64d86dfbbSVineet Gupta #include <linux/types.h>
74d86dfbbSVineet Gupta #include <linux/kprobes.h>
84d86dfbbSVineet Gupta #include <linux/slab.h>
94d86dfbbSVineet Gupta #include <linux/module.h>
104d86dfbbSVineet Gupta #include <linux/kdebug.h>
114d86dfbbSVineet Gupta #include <linux/sched.h>
124d86dfbbSVineet Gupta #include <linux/uaccess.h>
134d86dfbbSVineet Gupta #include <asm/cacheflush.h>
144d86dfbbSVineet Gupta #include <asm/current.h>
154d86dfbbSVineet Gupta #include <asm/disasm.h>
164d86dfbbSVineet Gupta 
174d86dfbbSVineet Gupta #define MIN_STACK_SIZE(addr)	min((unsigned long)MAX_STACK_SIZE, \
184d86dfbbSVineet Gupta 		(unsigned long)current_thread_info() + THREAD_SIZE - (addr))
194d86dfbbSVineet Gupta 
204d86dfbbSVineet Gupta DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
214d86dfbbSVineet Gupta DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
224d86dfbbSVineet Gupta 
arch_prepare_kprobe(struct kprobe * p)234d86dfbbSVineet Gupta int __kprobes arch_prepare_kprobe(struct kprobe *p)
244d86dfbbSVineet Gupta {
254d86dfbbSVineet Gupta 	/* Attempt to probe at unaligned address */
264d86dfbbSVineet Gupta 	if ((unsigned long)p->addr & 0x01)
274d86dfbbSVineet Gupta 		return -EINVAL;
284d86dfbbSVineet Gupta 
294d86dfbbSVineet Gupta 	/* Address should not be in exception handling code */
304d86dfbbSVineet Gupta 
314d86dfbbSVineet Gupta 	p->ainsn.is_short = is_short_instr((unsigned long)p->addr);
324d86dfbbSVineet Gupta 	p->opcode = *p->addr;
334d86dfbbSVineet Gupta 
344d86dfbbSVineet Gupta 	return 0;
354d86dfbbSVineet Gupta }
364d86dfbbSVineet Gupta 
arch_arm_kprobe(struct kprobe * p)374d86dfbbSVineet Gupta void __kprobes arch_arm_kprobe(struct kprobe *p)
384d86dfbbSVineet Gupta {
394d86dfbbSVineet Gupta 	*p->addr = UNIMP_S_INSTRUCTION;
404d86dfbbSVineet Gupta 
414d86dfbbSVineet Gupta 	flush_icache_range((unsigned long)p->addr,
424d86dfbbSVineet Gupta 			   (unsigned long)p->addr + sizeof(kprobe_opcode_t));
434d86dfbbSVineet Gupta }
444d86dfbbSVineet Gupta 
arch_disarm_kprobe(struct kprobe * p)454d86dfbbSVineet Gupta void __kprobes arch_disarm_kprobe(struct kprobe *p)
464d86dfbbSVineet Gupta {
474d86dfbbSVineet Gupta 	*p->addr = p->opcode;
484d86dfbbSVineet Gupta 
494d86dfbbSVineet Gupta 	flush_icache_range((unsigned long)p->addr,
504d86dfbbSVineet Gupta 			   (unsigned long)p->addr + sizeof(kprobe_opcode_t));
514d86dfbbSVineet Gupta }
524d86dfbbSVineet Gupta 
arch_remove_kprobe(struct kprobe * p)534d86dfbbSVineet Gupta void __kprobes arch_remove_kprobe(struct kprobe *p)
544d86dfbbSVineet Gupta {
554d86dfbbSVineet Gupta 	arch_disarm_kprobe(p);
564d86dfbbSVineet Gupta 
574d86dfbbSVineet Gupta 	/* Can we remove the kprobe in the middle of kprobe handling? */
584d86dfbbSVineet Gupta 	if (p->ainsn.t1_addr) {
594d86dfbbSVineet Gupta 		*(p->ainsn.t1_addr) = p->ainsn.t1_opcode;
604d86dfbbSVineet Gupta 
614d86dfbbSVineet Gupta 		flush_icache_range((unsigned long)p->ainsn.t1_addr,
624d86dfbbSVineet Gupta 				   (unsigned long)p->ainsn.t1_addr +
634d86dfbbSVineet Gupta 				   sizeof(kprobe_opcode_t));
644d86dfbbSVineet Gupta 
654d86dfbbSVineet Gupta 		p->ainsn.t1_addr = NULL;
664d86dfbbSVineet Gupta 	}
674d86dfbbSVineet Gupta 
684d86dfbbSVineet Gupta 	if (p->ainsn.t2_addr) {
694d86dfbbSVineet Gupta 		*(p->ainsn.t2_addr) = p->ainsn.t2_opcode;
704d86dfbbSVineet Gupta 
714d86dfbbSVineet Gupta 		flush_icache_range((unsigned long)p->ainsn.t2_addr,
724d86dfbbSVineet Gupta 				   (unsigned long)p->ainsn.t2_addr +
734d86dfbbSVineet Gupta 				   sizeof(kprobe_opcode_t));
744d86dfbbSVineet Gupta 
754d86dfbbSVineet Gupta 		p->ainsn.t2_addr = NULL;
764d86dfbbSVineet Gupta 	}
774d86dfbbSVineet Gupta }
784d86dfbbSVineet Gupta 
save_previous_kprobe(struct kprobe_ctlblk * kcb)794d86dfbbSVineet Gupta static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
804d86dfbbSVineet Gupta {
814d86dfbbSVineet Gupta 	kcb->prev_kprobe.kp = kprobe_running();
824d86dfbbSVineet Gupta 	kcb->prev_kprobe.status = kcb->kprobe_status;
834d86dfbbSVineet Gupta }
844d86dfbbSVineet Gupta 
restore_previous_kprobe(struct kprobe_ctlblk * kcb)854d86dfbbSVineet Gupta static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
864d86dfbbSVineet Gupta {
876855e95cSChristoph Lameter 	__this_cpu_write(current_kprobe, kcb->prev_kprobe.kp);
884d86dfbbSVineet Gupta 	kcb->kprobe_status = kcb->prev_kprobe.status;
894d86dfbbSVineet Gupta }
904d86dfbbSVineet Gupta 
set_current_kprobe(struct kprobe * p)914d86dfbbSVineet Gupta static inline void __kprobes set_current_kprobe(struct kprobe *p)
924d86dfbbSVineet Gupta {
936855e95cSChristoph Lameter 	__this_cpu_write(current_kprobe, p);
944d86dfbbSVineet Gupta }
954d86dfbbSVineet Gupta 
resume_execution(struct kprobe * p,unsigned long addr,struct pt_regs * regs)964d86dfbbSVineet Gupta static void __kprobes resume_execution(struct kprobe *p, unsigned long addr,
974d86dfbbSVineet Gupta 				       struct pt_regs *regs)
984d86dfbbSVineet Gupta {
994d86dfbbSVineet Gupta 	/* Remove the trap instructions inserted for single step and
1004d86dfbbSVineet Gupta 	 * restore the original instructions
1014d86dfbbSVineet Gupta 	 */
1024d86dfbbSVineet Gupta 	if (p->ainsn.t1_addr) {
1034d86dfbbSVineet Gupta 		*(p->ainsn.t1_addr) = p->ainsn.t1_opcode;
1044d86dfbbSVineet Gupta 
1054d86dfbbSVineet Gupta 		flush_icache_range((unsigned long)p->ainsn.t1_addr,
1064d86dfbbSVineet Gupta 				   (unsigned long)p->ainsn.t1_addr +
1074d86dfbbSVineet Gupta 				   sizeof(kprobe_opcode_t));
1084d86dfbbSVineet Gupta 
1094d86dfbbSVineet Gupta 		p->ainsn.t1_addr = NULL;
1104d86dfbbSVineet Gupta 	}
1114d86dfbbSVineet Gupta 
1124d86dfbbSVineet Gupta 	if (p->ainsn.t2_addr) {
1134d86dfbbSVineet Gupta 		*(p->ainsn.t2_addr) = p->ainsn.t2_opcode;
1144d86dfbbSVineet Gupta 
1154d86dfbbSVineet Gupta 		flush_icache_range((unsigned long)p->ainsn.t2_addr,
1164d86dfbbSVineet Gupta 				   (unsigned long)p->ainsn.t2_addr +
1174d86dfbbSVineet Gupta 				   sizeof(kprobe_opcode_t));
1184d86dfbbSVineet Gupta 
1194d86dfbbSVineet Gupta 		p->ainsn.t2_addr = NULL;
1204d86dfbbSVineet Gupta 	}
1214d86dfbbSVineet Gupta 
1224d86dfbbSVineet Gupta 	return;
1234d86dfbbSVineet Gupta }
1244d86dfbbSVineet Gupta 
setup_singlestep(struct kprobe * p,struct pt_regs * regs)1254d86dfbbSVineet Gupta static void __kprobes setup_singlestep(struct kprobe *p, struct pt_regs *regs)
1264d86dfbbSVineet Gupta {
1274d86dfbbSVineet Gupta 	unsigned long next_pc;
1284d86dfbbSVineet Gupta 	unsigned long tgt_if_br = 0;
1294d86dfbbSVineet Gupta 	int is_branch;
1304d86dfbbSVineet Gupta 	unsigned long bta;
1314d86dfbbSVineet Gupta 
1324d86dfbbSVineet Gupta 	/* Copy the opcode back to the kprobe location and execute the
1334d86dfbbSVineet Gupta 	 * instruction. Because of this we will not be able to get into the
1344d86dfbbSVineet Gupta 	 * same kprobe until this kprobe is done
1354d86dfbbSVineet Gupta 	 */
1364d86dfbbSVineet Gupta 	*(p->addr) = p->opcode;
1374d86dfbbSVineet Gupta 
1384d86dfbbSVineet Gupta 	flush_icache_range((unsigned long)p->addr,
1394d86dfbbSVineet Gupta 			   (unsigned long)p->addr + sizeof(kprobe_opcode_t));
1404d86dfbbSVineet Gupta 
1414d86dfbbSVineet Gupta 	/* Now we insert the trap at the next location after this instruction to
1424d86dfbbSVineet Gupta 	 * single step. If it is a branch we insert the trap at possible branch
1434d86dfbbSVineet Gupta 	 * targets
1444d86dfbbSVineet Gupta 	 */
1454d86dfbbSVineet Gupta 
1464d86dfbbSVineet Gupta 	bta = regs->bta;
1474d86dfbbSVineet Gupta 
1484d86dfbbSVineet Gupta 	if (regs->status32 & 0x40) {
1494d86dfbbSVineet Gupta 		/* We are in a delay slot with the branch taken */
1504d86dfbbSVineet Gupta 
1514d86dfbbSVineet Gupta 		next_pc = bta & ~0x01;
1524d86dfbbSVineet Gupta 
1534d86dfbbSVineet Gupta 		if (!p->ainsn.is_short) {
1544d86dfbbSVineet Gupta 			if (bta & 0x01)
1554d86dfbbSVineet Gupta 				regs->blink += 2;
1564d86dfbbSVineet Gupta 			else {
1574d86dfbbSVineet Gupta 				/* Branch not taken */
1584d86dfbbSVineet Gupta 				next_pc += 2;
1594d86dfbbSVineet Gupta 
1604d86dfbbSVineet Gupta 				/* next pc is taken from bta after executing the
1614d86dfbbSVineet Gupta 				 * delay slot instruction
1624d86dfbbSVineet Gupta 				 */
1634d86dfbbSVineet Gupta 				regs->bta += 2;
1644d86dfbbSVineet Gupta 			}
1654d86dfbbSVineet Gupta 		}
1664d86dfbbSVineet Gupta 
1674d86dfbbSVineet Gupta 		is_branch = 0;
1684d86dfbbSVineet Gupta 	} else
1694d86dfbbSVineet Gupta 		is_branch =
1704d86dfbbSVineet Gupta 		    disasm_next_pc((unsigned long)p->addr, regs,
1714d86dfbbSVineet Gupta 			(struct callee_regs *) current->thread.callee_reg,
1724d86dfbbSVineet Gupta 			&next_pc, &tgt_if_br);
1734d86dfbbSVineet Gupta 
1744d86dfbbSVineet Gupta 	p->ainsn.t1_addr = (kprobe_opcode_t *) next_pc;
1754d86dfbbSVineet Gupta 	p->ainsn.t1_opcode = *(p->ainsn.t1_addr);
1764d86dfbbSVineet Gupta 	*(p->ainsn.t1_addr) = TRAP_S_2_INSTRUCTION;
1774d86dfbbSVineet Gupta 
1784d86dfbbSVineet Gupta 	flush_icache_range((unsigned long)p->ainsn.t1_addr,
1794d86dfbbSVineet Gupta 			   (unsigned long)p->ainsn.t1_addr +
1804d86dfbbSVineet Gupta 			   sizeof(kprobe_opcode_t));
1814d86dfbbSVineet Gupta 
1824d86dfbbSVineet Gupta 	if (is_branch) {
1834d86dfbbSVineet Gupta 		p->ainsn.t2_addr = (kprobe_opcode_t *) tgt_if_br;
1844d86dfbbSVineet Gupta 		p->ainsn.t2_opcode = *(p->ainsn.t2_addr);
1854d86dfbbSVineet Gupta 		*(p->ainsn.t2_addr) = TRAP_S_2_INSTRUCTION;
1864d86dfbbSVineet Gupta 
1874d86dfbbSVineet Gupta 		flush_icache_range((unsigned long)p->ainsn.t2_addr,
1884d86dfbbSVineet Gupta 				   (unsigned long)p->ainsn.t2_addr +
1894d86dfbbSVineet Gupta 				   sizeof(kprobe_opcode_t));
1904d86dfbbSVineet Gupta 	}
1914d86dfbbSVineet Gupta }
1924d86dfbbSVineet Gupta 
193*db70d9f9SVineet Gupta static int
arc_kprobe_handler(unsigned long addr,struct pt_regs * regs)194*db70d9f9SVineet Gupta __kprobes arc_kprobe_handler(unsigned long addr, struct pt_regs *regs)
1954d86dfbbSVineet Gupta {
1964d86dfbbSVineet Gupta 	struct kprobe *p;
1974d86dfbbSVineet Gupta 	struct kprobe_ctlblk *kcb;
1984d86dfbbSVineet Gupta 
1994d86dfbbSVineet Gupta 	preempt_disable();
2004d86dfbbSVineet Gupta 
2014d86dfbbSVineet Gupta 	kcb = get_kprobe_ctlblk();
2024d86dfbbSVineet Gupta 	p = get_kprobe((unsigned long *)addr);
2034d86dfbbSVineet Gupta 
2044d86dfbbSVineet Gupta 	if (p) {
2054d86dfbbSVineet Gupta 		/*
2064d86dfbbSVineet Gupta 		 * We have reentered the kprobe_handler, since another kprobe
2074d86dfbbSVineet Gupta 		 * was hit while within the handler, we save the original
2084d86dfbbSVineet Gupta 		 * kprobes and single step on the instruction of the new probe
2094d86dfbbSVineet Gupta 		 * without calling any user handlers to avoid recursive
2104d86dfbbSVineet Gupta 		 * kprobes.
2114d86dfbbSVineet Gupta 		 */
2124d86dfbbSVineet Gupta 		if (kprobe_running()) {
2134d86dfbbSVineet Gupta 			save_previous_kprobe(kcb);
2144d86dfbbSVineet Gupta 			set_current_kprobe(p);
2154d86dfbbSVineet Gupta 			kprobes_inc_nmissed_count(p);
2164d86dfbbSVineet Gupta 			setup_singlestep(p, regs);
2174d86dfbbSVineet Gupta 			kcb->kprobe_status = KPROBE_REENTER;
2184d86dfbbSVineet Gupta 			return 1;
2194d86dfbbSVineet Gupta 		}
2204d86dfbbSVineet Gupta 
2214d86dfbbSVineet Gupta 		set_current_kprobe(p);
2224d86dfbbSVineet Gupta 		kcb->kprobe_status = KPROBE_HIT_ACTIVE;
2234d86dfbbSVineet Gupta 
2244d86dfbbSVineet Gupta 		/* If we have no pre-handler or it returned 0, we continue with
2254d86dfbbSVineet Gupta 		 * normal processing. If we have a pre-handler and it returned
226e00f1993SMasami Hiramatsu 		 * non-zero - which means user handler setup registers to exit
227e00f1993SMasami Hiramatsu 		 * to another instruction, we must skip the single stepping.
2284d86dfbbSVineet Gupta 		 */
2294d86dfbbSVineet Gupta 		if (!p->pre_handler || !p->pre_handler(p, regs)) {
2304d86dfbbSVineet Gupta 			setup_singlestep(p, regs);
2314d86dfbbSVineet Gupta 			kcb->kprobe_status = KPROBE_HIT_SS;
232cce188bdSMasami Hiramatsu 		} else {
233cce188bdSMasami Hiramatsu 			reset_current_kprobe();
234cce188bdSMasami Hiramatsu 			preempt_enable_no_resched();
2354d86dfbbSVineet Gupta 		}
2364d86dfbbSVineet Gupta 
2374d86dfbbSVineet Gupta 		return 1;
2384d86dfbbSVineet Gupta 	}
2394d86dfbbSVineet Gupta 
2404d86dfbbSVineet Gupta 	/* no_kprobe: */
2414d86dfbbSVineet Gupta 	preempt_enable_no_resched();
2424d86dfbbSVineet Gupta 	return 0;
2434d86dfbbSVineet Gupta }
2444d86dfbbSVineet Gupta 
245*db70d9f9SVineet Gupta static int
arc_post_kprobe_handler(unsigned long addr,struct pt_regs * regs)246*db70d9f9SVineet Gupta __kprobes arc_post_kprobe_handler(unsigned long addr, struct pt_regs *regs)
2474d86dfbbSVineet Gupta {
2484d86dfbbSVineet Gupta 	struct kprobe *cur = kprobe_running();
2494d86dfbbSVineet Gupta 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
2504d86dfbbSVineet Gupta 
2514d86dfbbSVineet Gupta 	if (!cur)
2524d86dfbbSVineet Gupta 		return 0;
2534d86dfbbSVineet Gupta 
2544d86dfbbSVineet Gupta 	resume_execution(cur, addr, regs);
2554d86dfbbSVineet Gupta 
2564d86dfbbSVineet Gupta 	/* Rearm the kprobe */
2574d86dfbbSVineet Gupta 	arch_arm_kprobe(cur);
2584d86dfbbSVineet Gupta 
2594d86dfbbSVineet Gupta 	/*
2604d86dfbbSVineet Gupta 	 * When we return from trap instruction we go to the next instruction
2614d86dfbbSVineet Gupta 	 * We restored the actual instruction in resume_exectuiont and we to
2624d86dfbbSVineet Gupta 	 * return to the same address and execute it
2634d86dfbbSVineet Gupta 	 */
2644d86dfbbSVineet Gupta 	regs->ret = addr;
2654d86dfbbSVineet Gupta 
2664d86dfbbSVineet Gupta 	if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
2674d86dfbbSVineet Gupta 		kcb->kprobe_status = KPROBE_HIT_SSDONE;
2684d86dfbbSVineet Gupta 		cur->post_handler(cur, regs, 0);
2694d86dfbbSVineet Gupta 	}
2704d86dfbbSVineet Gupta 
2714d86dfbbSVineet Gupta 	if (kcb->kprobe_status == KPROBE_REENTER) {
2724d86dfbbSVineet Gupta 		restore_previous_kprobe(kcb);
2734d86dfbbSVineet Gupta 		goto out;
2744d86dfbbSVineet Gupta 	}
2754d86dfbbSVineet Gupta 
2764d86dfbbSVineet Gupta 	reset_current_kprobe();
2774d86dfbbSVineet Gupta 
2784d86dfbbSVineet Gupta out:
2794d86dfbbSVineet Gupta 	preempt_enable_no_resched();
2804d86dfbbSVineet Gupta 	return 1;
2814d86dfbbSVineet Gupta }
2824d86dfbbSVineet Gupta 
2834d86dfbbSVineet Gupta /*
2844d86dfbbSVineet Gupta  * Fault can be for the instruction being single stepped or for the
2854d86dfbbSVineet Gupta  * pre/post handlers in the module.
2864d86dfbbSVineet Gupta  * This is applicable for applications like user probes, where we have the
2874d86dfbbSVineet Gupta  * probe in user space and the handlers in the kernel
2884d86dfbbSVineet Gupta  */
2894d86dfbbSVineet Gupta 
kprobe_fault_handler(struct pt_regs * regs,unsigned long trapnr)2904d86dfbbSVineet Gupta int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned long trapnr)
2914d86dfbbSVineet Gupta {
2924d86dfbbSVineet Gupta 	struct kprobe *cur = kprobe_running();
2934d86dfbbSVineet Gupta 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
2944d86dfbbSVineet Gupta 
2954d86dfbbSVineet Gupta 	switch (kcb->kprobe_status) {
2964d86dfbbSVineet Gupta 	case KPROBE_HIT_SS:
2974d86dfbbSVineet Gupta 	case KPROBE_REENTER:
2984d86dfbbSVineet Gupta 		/*
2994d86dfbbSVineet Gupta 		 * We are here because the instruction being single stepped
3004d86dfbbSVineet Gupta 		 * caused the fault. We reset the current kprobe and allow the
3014d86dfbbSVineet Gupta 		 * exception handler as if it is regular exception. In our
3024d86dfbbSVineet Gupta 		 * case it doesn't matter because the system will be halted
3034d86dfbbSVineet Gupta 		 */
3044d86dfbbSVineet Gupta 		resume_execution(cur, (unsigned long)cur->addr, regs);
3054d86dfbbSVineet Gupta 
3064d86dfbbSVineet Gupta 		if (kcb->kprobe_status == KPROBE_REENTER)
3074d86dfbbSVineet Gupta 			restore_previous_kprobe(kcb);
3084d86dfbbSVineet Gupta 		else
3094d86dfbbSVineet Gupta 			reset_current_kprobe();
3104d86dfbbSVineet Gupta 
3114d86dfbbSVineet Gupta 		preempt_enable_no_resched();
3124d86dfbbSVineet Gupta 		break;
3134d86dfbbSVineet Gupta 
3144d86dfbbSVineet Gupta 	case KPROBE_HIT_ACTIVE:
3154d86dfbbSVineet Gupta 	case KPROBE_HIT_SSDONE:
3164d86dfbbSVineet Gupta 		/*
3174d86dfbbSVineet Gupta 		 * We are here because the instructions in the pre/post handler
3184d86dfbbSVineet Gupta 		 * caused the fault.
3194d86dfbbSVineet Gupta 		 */
3204d86dfbbSVineet Gupta 
3214d86dfbbSVineet Gupta 		/*
3224d86dfbbSVineet Gupta 		 * In case the user-specified fault handler returned zero,
3234d86dfbbSVineet Gupta 		 * try to fix up.
3244d86dfbbSVineet Gupta 		 */
3254d86dfbbSVineet Gupta 		if (fixup_exception(regs))
3264d86dfbbSVineet Gupta 			return 1;
3274d86dfbbSVineet Gupta 
3284d86dfbbSVineet Gupta 		/*
3294d86dfbbSVineet Gupta 		 * fixup_exception() could not handle it,
3304d86dfbbSVineet Gupta 		 * Let do_page_fault() fix it.
3314d86dfbbSVineet Gupta 		 */
3324d86dfbbSVineet Gupta 		break;
3334d86dfbbSVineet Gupta 
3344d86dfbbSVineet Gupta 	default:
3354d86dfbbSVineet Gupta 		break;
3364d86dfbbSVineet Gupta 	}
3374d86dfbbSVineet Gupta 	return 0;
3384d86dfbbSVineet Gupta }
3394d86dfbbSVineet Gupta 
kprobe_exceptions_notify(struct notifier_block * self,unsigned long val,void * data)3404d86dfbbSVineet Gupta int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
3414d86dfbbSVineet Gupta 				       unsigned long val, void *data)
3424d86dfbbSVineet Gupta {
3434d86dfbbSVineet Gupta 	struct die_args *args = data;
3444d86dfbbSVineet Gupta 	unsigned long addr = args->err;
3454d86dfbbSVineet Gupta 	int ret = NOTIFY_DONE;
3464d86dfbbSVineet Gupta 
3474d86dfbbSVineet Gupta 	switch (val) {
3484d86dfbbSVineet Gupta 	case DIE_IERR:
3494d86dfbbSVineet Gupta 		if (arc_kprobe_handler(addr, args->regs))
3504d86dfbbSVineet Gupta 			return NOTIFY_STOP;
3514d86dfbbSVineet Gupta 		break;
3524d86dfbbSVineet Gupta 
3534d86dfbbSVineet Gupta 	case DIE_TRAP:
3544d86dfbbSVineet Gupta 		if (arc_post_kprobe_handler(addr, args->regs))
3554d86dfbbSVineet Gupta 			return NOTIFY_STOP;
3564d86dfbbSVineet Gupta 		break;
3574d86dfbbSVineet Gupta 
3584d86dfbbSVineet Gupta 	default:
3594d86dfbbSVineet Gupta 		break;
3604d86dfbbSVineet Gupta 	}
3614d86dfbbSVineet Gupta 
3624d86dfbbSVineet Gupta 	return ret;
3634d86dfbbSVineet Gupta }
3644d86dfbbSVineet Gupta 
kretprobe_trampoline_holder(void)3654d86dfbbSVineet Gupta static void __used kretprobe_trampoline_holder(void)
3664d86dfbbSVineet Gupta {
367adf8a61aSMasami Hiramatsu 	__asm__ __volatile__(".global __kretprobe_trampoline\n"
368adf8a61aSMasami Hiramatsu 			     "__kretprobe_trampoline:\n"
369adf8a61aSMasami Hiramatsu 			     "nop\n");
3704d86dfbbSVineet Gupta }
3714d86dfbbSVineet Gupta 
arch_prepare_kretprobe(struct kretprobe_instance * ri,struct pt_regs * regs)3724d86dfbbSVineet Gupta void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
3734d86dfbbSVineet Gupta 				      struct pt_regs *regs)
3744d86dfbbSVineet Gupta {
3754d86dfbbSVineet Gupta 
3764d86dfbbSVineet Gupta 	ri->ret_addr = (kprobe_opcode_t *) regs->blink;
377f75dd136SMasami Hiramatsu 	ri->fp = NULL;
3784d86dfbbSVineet Gupta 
3794d86dfbbSVineet Gupta 	/* Replace the return addr with trampoline addr */
380adf8a61aSMasami Hiramatsu 	regs->blink = (unsigned long)&__kretprobe_trampoline;
3814d86dfbbSVineet Gupta }
3824d86dfbbSVineet Gupta 
trampoline_probe_handler(struct kprobe * p,struct pt_regs * regs)3834d86dfbbSVineet Gupta static int __kprobes trampoline_probe_handler(struct kprobe *p,
3844d86dfbbSVineet Gupta 					      struct pt_regs *regs)
3854d86dfbbSVineet Gupta {
38696fed8acSMasami Hiramatsu 	regs->ret = __kretprobe_trampoline_handler(regs, NULL);
3874d86dfbbSVineet Gupta 
3884d86dfbbSVineet Gupta 	/* By returning a non zero value, we are telling the kprobe handler
3894d86dfbbSVineet Gupta 	 * that we don't want the post_handler to run
3904d86dfbbSVineet Gupta 	 */
3914d86dfbbSVineet Gupta 	return 1;
3924d86dfbbSVineet Gupta }
3934d86dfbbSVineet Gupta 
3944d86dfbbSVineet Gupta static struct kprobe trampoline_p = {
395adf8a61aSMasami Hiramatsu 	.addr = (kprobe_opcode_t *) &__kretprobe_trampoline,
3964d86dfbbSVineet Gupta 	.pre_handler = trampoline_probe_handler
3974d86dfbbSVineet Gupta };
3984d86dfbbSVineet Gupta 
arch_init_kprobes(void)3994d86dfbbSVineet Gupta int __init arch_init_kprobes(void)
4004d86dfbbSVineet Gupta {
4014d86dfbbSVineet Gupta 	/* Registering the trampoline code for the kret probe */
4024d86dfbbSVineet Gupta 	return register_kprobe(&trampoline_p);
4034d86dfbbSVineet Gupta }
4044d86dfbbSVineet Gupta 
arch_trampoline_kprobe(struct kprobe * p)4054d86dfbbSVineet Gupta int __kprobes arch_trampoline_kprobe(struct kprobe *p)
4064d86dfbbSVineet Gupta {
407adf8a61aSMasami Hiramatsu 	if (p->addr == (kprobe_opcode_t *) &__kretprobe_trampoline)
4084d86dfbbSVineet Gupta 		return 1;
4094d86dfbbSVineet Gupta 
4104d86dfbbSVineet Gupta 	return 0;
4114d86dfbbSVineet Gupta }
4124d86dfbbSVineet Gupta 
trap_is_kprobe(unsigned long address,struct pt_regs * regs)41338a9ff6dSVineet Gupta void trap_is_kprobe(unsigned long address, struct pt_regs *regs)
4144d86dfbbSVineet Gupta {
41538a9ff6dSVineet Gupta 	notify_die(DIE_TRAP, "kprobe_trap", regs, address, 0, SIGTRAP);
4164d86dfbbSVineet Gupta }
417