Linux Audio

Check our new training course

Linux BSP development engineering services

Need help to port Linux and bootloaders to your hardware?
Loading...
v3.5.6
  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}
v3.1
  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}