PageRenderTime 34ms CodeModel.GetById 7ms app.highlight 22ms RepoModel.GetById 1ms app.codeStats 0ms

/arch/ppc64/kernel/kprobes.c

https://bitbucket.org/evzijst/gittest
C | 290 lines | 174 code | 36 blank | 80 comment | 31 complexity | a0ed6a0a8dfd72f57c44c06bf00897c0 MD5 | raw file
  1/*
  2 *  Kernel Probes (KProbes)
  3 *  arch/ppc64/kernel/kprobes.c
  4 *
  5 * This program is free software; you can redistribute it and/or modify
  6 * it under the terms of the GNU General Public License as published by
  7 * the Free Software Foundation; either version 2 of the License, or
  8 * (at your option) any later version.
  9 *
 10 * This program is distributed in the hope that it will be useful,
 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13 * GNU General Public License for more details.
 14 *
 15 * You should have received a copy of the GNU General Public License
 16 * along with this program; if not, write to the Free Software
 17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 18 *
 19 * Copyright (C) IBM Corporation, 2002, 2004
 20 *
 21 * 2002-Oct	Created by Vamsi Krishna S <vamsi_krishna@in.ibm.com> Kernel
 22 *		Probes initial implementation ( includes contributions from
 23 *		Rusty Russell).
 24 * 2004-July	Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes
 25 *		interface to access function arguments.
 26 * 2004-Nov	Ananth N Mavinakayanahalli <ananth@in.ibm.com> kprobes port
 27 *		for PPC64
 28 */
 29
 30#include <linux/config.h>
 31#include <linux/kprobes.h>
 32#include <linux/ptrace.h>
 33#include <linux/spinlock.h>
 34#include <linux/preempt.h>
 35#include <asm/kdebug.h>
 36#include <asm/sstep.h>
 37
 38/* kprobe_status settings */
 39#define KPROBE_HIT_ACTIVE	0x00000001
 40#define KPROBE_HIT_SS		0x00000002
 41
 42static struct kprobe *current_kprobe;
 43static unsigned long kprobe_status, kprobe_saved_msr;
 44static struct pt_regs jprobe_saved_regs;
 45
 46int arch_prepare_kprobe(struct kprobe *p)
 47{
 48	kprobe_opcode_t insn = *p->addr;
 49
 50	if (IS_MTMSRD(insn) || IS_RFID(insn))
 51		/* cannot put bp on RFID/MTMSRD */
 52		return 1;
 53	return 0;
 54}
 55
 56void arch_copy_kprobe(struct kprobe *p)
 57{
 58	memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
 59}
 60
 61void arch_remove_kprobe(struct kprobe *p)
 62{
 63}
 64
 65static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs)
 66{
 67	*p->addr = p->opcode;
 68	regs->nip = (unsigned long)p->addr;
 69}
 70
 71static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
 72{
 73	regs->msr |= MSR_SE;
 74	/*single step inline if it a breakpoint instruction*/
 75	if (p->opcode == BREAKPOINT_INSTRUCTION)
 76		regs->nip = (unsigned long)p->addr;
 77	else
 78		regs->nip = (unsigned long)&p->ainsn.insn;
 79}
 80
 81static inline int kprobe_handler(struct pt_regs *regs)
 82{
 83	struct kprobe *p;
 84	int ret = 0;
 85	unsigned int *addr = (unsigned int *)regs->nip;
 86
 87	/* Check we're not actually recursing */
 88	if (kprobe_running()) {
 89		/* We *are* holding lock here, so this is safe.
 90		   Disarm the probe we just hit, and ignore it. */
 91		p = get_kprobe(addr);
 92		if (p) {
 93			if (kprobe_status == KPROBE_HIT_SS) {
 94				regs->msr &= ~MSR_SE;
 95				regs->msr |= kprobe_saved_msr;
 96				unlock_kprobes();
 97				goto no_kprobe;
 98			}
 99			disarm_kprobe(p, regs);
100			ret = 1;
101		} else {
102			p = current_kprobe;
103			if (p->break_handler && p->break_handler(p, regs)) {
104				goto ss_probe;
105			}
106		}
107		/* If it's not ours, can't be delete race, (we hold lock). */
108		goto no_kprobe;
109	}
110
111	lock_kprobes();
112	p = get_kprobe(addr);
113	if (!p) {
114		unlock_kprobes();
115		if (*addr != BREAKPOINT_INSTRUCTION) {
116			/*
117			 * PowerPC has multiple variants of the "trap"
118			 * instruction. If the current instruction is a
119			 * trap variant, it could belong to someone else
120			 */
121			kprobe_opcode_t cur_insn = *addr;
122			if (IS_TW(cur_insn) || IS_TD(cur_insn) ||
123					IS_TWI(cur_insn) || IS_TDI(cur_insn))
124		       		goto no_kprobe;
125			/*
126			 * The breakpoint instruction was removed right
127			 * after we hit it.  Another cpu has removed
128			 * either a probepoint or a debugger breakpoint
129			 * at this address.  In either case, no further
130			 * handling of this interrupt is appropriate.
131			 */
132			ret = 1;
133		}
134		/* Not one of ours: let kernel handle it */
135		goto no_kprobe;
136	}
137
138	kprobe_status = KPROBE_HIT_ACTIVE;
139	current_kprobe = p;
140	kprobe_saved_msr = regs->msr;
141	if (p->pre_handler && p->pre_handler(p, regs))
142		/* handler has already set things up, so skip ss setup */
143		return 1;
144
145ss_probe:
146	prepare_singlestep(p, regs);
147	kprobe_status = KPROBE_HIT_SS;
148	/*
149	 * This preempt_disable() matches the preempt_enable_no_resched()
150	 * in post_kprobe_handler().
151	 */
152	preempt_disable();
153	return 1;
154
155no_kprobe:
156	return ret;
157}
158
159/*
160 * Called after single-stepping.  p->addr is the address of the
161 * instruction whose first byte has been replaced by the "breakpoint"
162 * instruction.  To avoid the SMP problems that can occur when we
163 * temporarily put back the original opcode to single-step, we
164 * single-stepped a copy of the instruction.  The address of this
165 * copy is p->ainsn.insn.
166 */
167static void resume_execution(struct kprobe *p, struct pt_regs *regs)
168{
169	int ret;
170
171	regs->nip = (unsigned long)p->addr;
172	ret = emulate_step(regs, p->ainsn.insn[0]);
173	if (ret == 0)
174		regs->nip = (unsigned long)p->addr + 4;
175
176	regs->msr &= ~MSR_SE;
177}
178
179static inline int post_kprobe_handler(struct pt_regs *regs)
180{
181	if (!kprobe_running())
182		return 0;
183
184	if (current_kprobe->post_handler)
185		current_kprobe->post_handler(current_kprobe, regs, 0);
186
187	resume_execution(current_kprobe, regs);
188	regs->msr |= kprobe_saved_msr;
189
190	unlock_kprobes();
191	preempt_enable_no_resched();
192
193	/*
194	 * if somebody else is singlestepping across a probe point, msr
195	 * will have SE set, in which case, continue the remaining processing
196	 * of do_debug, as if this is not a probe hit.
197	 */
198	if (regs->msr & MSR_SE)
199		return 0;
200
201	return 1;
202}
203
204/* Interrupts disabled, kprobe_lock held. */
205static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
206{
207	if (current_kprobe->fault_handler
208	    && current_kprobe->fault_handler(current_kprobe, regs, trapnr))
209		return 1;
210
211	if (kprobe_status & KPROBE_HIT_SS) {
212		resume_execution(current_kprobe, regs);
213		regs->msr |= kprobe_saved_msr;
214
215		unlock_kprobes();
216		preempt_enable_no_resched();
217	}
218	return 0;
219}
220
221/*
222 * Wrapper routine to for handling exceptions.
223 */
224int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
225			     void *data)
226{
227	struct die_args *args = (struct die_args *)data;
228	int ret = NOTIFY_DONE;
229
230	/*
231	 * Interrupts are not disabled here.  We need to disable
232	 * preemption, because kprobe_running() uses smp_processor_id().
233	 */
234	preempt_disable();
235	switch (val) {
236	case DIE_IABR_MATCH:
237	case DIE_DABR_MATCH:
238	case DIE_BPT:
239		if (kprobe_handler(args->regs))
240			ret = NOTIFY_STOP;
241		break;
242	case DIE_SSTEP:
243		if (post_kprobe_handler(args->regs))
244			ret = NOTIFY_STOP;
245		break;
246	case DIE_GPF:
247	case DIE_PAGE_FAULT:
248		if (kprobe_running() &&
249		    kprobe_fault_handler(args->regs, args->trapnr))
250			ret = NOTIFY_STOP;
251		break;
252	default:
253		break;
254	}
255	preempt_enable();
256	return ret;
257}
258
259int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
260{
261	struct jprobe *jp = container_of(p, struct jprobe, kp);
262
263	memcpy(&jprobe_saved_regs, regs, sizeof(struct pt_regs));
264
265	/* setup return addr to the jprobe handler routine */
266	regs->nip = (unsigned long)(((func_descr_t *)jp->entry)->entry);
267	regs->gpr[2] = (unsigned long)(((func_descr_t *)jp->entry)->toc);
268
269	return 1;
270}
271
272void jprobe_return(void)
273{
274	asm volatile("trap" ::: "memory");
275}
276
277void jprobe_return_end(void)
278{
279};
280
281int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
282{
283	/*
284	 * FIXME - we should ideally be validating that we got here 'cos
285	 * of the "trap" in jprobe_return() above, before restoring the
286	 * saved regs...
287	 */
288	memcpy(regs, &jprobe_saved_regs, sizeof(struct pt_regs));
289	return 1;
290}