1/*
2 *  Kernel Probes (KProbes)
3 *
4 * Copyright (C) 2005-2006 Atmel Corporation
5 *
6 * Based on arch/ppc64/kernel/kprobes.c
7 *  Copyright (C) IBM Corporation, 2002, 2004
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/kprobes.h>
15#include <linux/ptrace.h>
16
17#include <asm/cacheflush.h>
18#include <linux/kdebug.h>
19#include <asm/ocd.h>
20
21DEFINE_PER_CPU(struct kprobe *, current_kprobe);
22static unsigned long kprobe_status;
23static struct pt_regs jprobe_saved_regs;
24
25struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}};
26
27int __kprobes arch_prepare_kprobe(struct kprobe *p)
28{
29	int ret = 0;
30
31	if ((unsigned long)p->addr & 0x01) {
32		printk("Attempt to register kprobe at an unaligned address\n");
33		ret = -EINVAL;
34	}
35
36	/* XXX: Might be a good idea to check if p->addr is a valid
37	 * kernel address as well... */
38
39	if (!ret) {
40		pr_debug("copy kprobe at %p\n", p->addr);
41		memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
42		p->opcode = *p->addr;
43	}
44
45	return ret;
46}
47
48void __kprobes arch_arm_kprobe(struct kprobe *p)
49{
50	pr_debug("arming kprobe at %p\n", p->addr);
51	ocd_enable(NULL);
52	*p->addr = BREAKPOINT_INSTRUCTION;
53	flush_icache_range((unsigned long)p->addr,
54			   (unsigned long)p->addr + sizeof(kprobe_opcode_t));
55}
56
57void __kprobes arch_disarm_kprobe(struct kprobe *p)
58{
59	pr_debug("disarming kprobe at %p\n", p->addr);
60	ocd_disable(NULL);
61	*p->addr = p->opcode;
62	flush_icache_range((unsigned long)p->addr,
63			   (unsigned long)p->addr + sizeof(kprobe_opcode_t));
64}
65
66static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
67{
68	unsigned long dc;
69
70	pr_debug("preparing to singlestep over %p (PC=%08lx)\n",
71		 p->addr, regs->pc);
72
73	BUG_ON(!(sysreg_read(SR) & SYSREG_BIT(SR_D)));
74
75	dc = ocd_read(DC);
76	dc |= 1 << OCD_DC_SS_BIT;
77	ocd_write(DC, dc);
78
79	/*
80	 * We must run the instruction from its original location
81	 * since it may actually reference PC.
82	 *
83	 * TODO: Do the instruction replacement directly in icache.
84	 */
85	*p->addr = p->opcode;
86	flush_icache_range((unsigned long)p->addr,
87			   (unsigned long)p->addr + sizeof(kprobe_opcode_t));
88}
89
90static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
91{
92	unsigned long dc;
93
94	pr_debug("resuming execution at PC=%08lx\n", regs->pc);
95
96	dc = ocd_read(DC);
97	dc &= ~(1 << OCD_DC_SS_BIT);
98	ocd_write(DC, dc);
99
100	*p->addr = BREAKPOINT_INSTRUCTION;
101	flush_icache_range((unsigned long)p->addr,
102			   (unsigned long)p->addr + sizeof(kprobe_opcode_t));
103}
104
105static void __kprobes set_current_kprobe(struct kprobe *p)
106{
107	__get_cpu_var(current_kprobe) = p;
108}
109
110static int __kprobes kprobe_handler(struct pt_regs *regs)
111{
112	struct kprobe *p;
113	void *addr = (void *)regs->pc;
114	int ret = 0;
115
116	pr_debug("kprobe_handler: kprobe_running=%p\n",
117		 kprobe_running());
118
119	/*
120	 * We don't want to be preempted for the entire
121	 * duration of kprobe processing
122	 */
123	preempt_disable();
124
125	/* Check that we're not recursing */
126	if (kprobe_running()) {
127		p = get_kprobe(addr);
128		if (p) {
129			if (kprobe_status == KPROBE_HIT_SS) {
130				printk("FIXME: kprobe hit while single-stepping!\n");
131				goto no_kprobe;
132			}
133
134			printk("FIXME: kprobe hit while handling another kprobe\n");
135			goto no_kprobe;
136		} else {
137			p = kprobe_running();
138			if (p->break_handler && p->break_handler(p, regs))
139				goto ss_probe;
140		}
141		/* If it's not ours, can't be delete race, (we hold lock). */
142		goto no_kprobe;
143	}
144
145	p = get_kprobe(addr);
146	if (!p)
147		goto no_kprobe;
148
149	kprobe_status = KPROBE_HIT_ACTIVE;
150	set_current_kprobe(p);
151	if (p->pre_handler && p->pre_handler(p, regs))
152		/* handler has already set things up, so skip ss setup */
153		return 1;
154
155ss_probe:
156	prepare_singlestep(p, regs);
157	kprobe_status = KPROBE_HIT_SS;
158	return 1;
159
160no_kprobe:
161	preempt_enable_no_resched();
162	return ret;
163}
164
165static int __kprobes post_kprobe_handler(struct pt_regs *regs)
166{
167	struct kprobe *cur = kprobe_running();
168
169	pr_debug("post_kprobe_handler, cur=%p\n", cur);
170
171	if (!cur)
172		return 0;
173
174	if (cur->post_handler) {
175		kprobe_status = KPROBE_HIT_SSDONE;
176		cur->post_handler(cur, regs, 0);
177	}
178
179	resume_execution(cur, regs);
180	reset_current_kprobe();
181	preempt_enable_no_resched();
182
183	return 1;
184}
185
186int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
187{
188	struct kprobe *cur = kprobe_running();
189
190	pr_debug("kprobe_fault_handler: trapnr=%d\n", trapnr);
191
192	if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
193		return 1;
194
195	if (kprobe_status & KPROBE_HIT_SS) {
196		resume_execution(cur, regs);
197		preempt_enable_no_resched();
198	}
199	return 0;
200}
201
202/*
203 * Wrapper routine to for handling exceptions.
204 */
205int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
206				       unsigned long val, void *data)
207{
208	struct die_args *args = (struct die_args *)data;
209	int ret = NOTIFY_DONE;
210
211	pr_debug("kprobe_exceptions_notify: val=%lu, data=%p\n",
212		 val, data);
213
214	switch (val) {
215	case DIE_BREAKPOINT:
216		if (kprobe_handler(args->regs))
217			ret = NOTIFY_STOP;
218		break;
219	case DIE_SSTEP:
220		if (post_kprobe_handler(args->regs))
221			ret = NOTIFY_STOP;
222		break;
223	default:
224		break;
225	}
226
227	return ret;
228}
229
230int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
231{
232	struct jprobe *jp = container_of(p, struct jprobe, kp);
233
234	memcpy(&jprobe_saved_regs, regs, sizeof(struct pt_regs));
235
236	/*
237	 * TODO: We should probably save some of the stack here as
238	 * well, since gcc may pass arguments on the stack for certain
239	 * functions (lots of arguments, large aggregates, varargs)
240	 */
241
242	/* setup return addr to the jprobe handler routine */
243	regs->pc = (unsigned long)jp->entry;
244	return 1;
245}
246
247void __kprobes jprobe_return(void)
248{
249	asm volatile("breakpoint" ::: "memory");
250}
251
252int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
253{
254	/*
255	 * FIXME - we should ideally be validating that we got here 'cos
256	 * of the "trap" in jprobe_return() above, before restoring the
257	 * saved regs...
258	 */
259	memcpy(regs, &jprobe_saved_regs, sizeof(struct pt_regs));
260	return 1;
261}
262
263int __init arch_init_kprobes(void)
264{
265	/* TODO: Register kretprobe trampoline */
266	return 0;
267}
268