linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* Kprobes for PPC32[Booke]
@ 2007-03-15 15:41 rsmadhvesh
  0 siblings, 0 replies; only message in thread
From: rsmadhvesh @ 2007-03-15 15:41 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: madhvesh.s

[-- Attachment #1: Type: text/plain, Size: 3443 bytes --]

Hi,

This is regarding the kprobes support for ppc32 with
BOOKE versions. The attached patch contains this code 
and there is seperate patch which includes some kernel 
modules to test the same. This is tested for ebony 
platform(ppc440_gp).

Kernel Version: 2.6.16.39
Platform: Ebony

But there are some issues which i have noticed while
handling debug exception used for single step operation. 

1. The single step operation in PPC32 is implemented using
debug control register (DBCR) which can be used to generate
single step debug exception. This mechanism is used in handling
post handler execution of kprobes (see code prepare_single_step)

2. It was noticed that having preempt_disable() at the beginning of
kprobe_handler, generates OOPS and kprobes doesnot work. But this is 
against the original kprobes design implemented in other already working 
archs (that is, preemption is disabled for the entire duration of pre and post
handlers execution). The basic problem noticed is, change in the preempt
count after generating single step exception. Even though the preemption
is disabled at the beginning of kprobe_handler(), after generating the
single step exception, preempt count gets printed as zero in DebugException() 
handler of traps.c. This causes the problem and system generates OOPS!!

To resolve this problem, we have introduced the preempt_disable 
and preempt_enable_no_resched blocks in pre and post handlers
exceptions switch case of kprobe_exceptions_notify(), and by this way 
we found that the preempt count is consistent and pre and post handlers 
get executed. So why in PPC32 arch, preempt count gets changed between the
debug exceptions? Is this problem already noticed or is it because of some other
bug in the kprobes code of the attached patch?

3. In PPC32 it is noticed that interrupts are enabled by default and 
initially i had suspected this as the cause for problem stated in <2>.
But it is found that by disabling interrupts, uncommenting the #if 0 blocks
in the attached patch, the same problem appears. But this code is still
not tested for kprobes reentrancy (by having interrupts enabled). Does 
anybody see a issue of enabling interrupts while processing kprobes?

4. While executing the fault handler using the test k-004.c in the 
attached patch, we noticed the following message being printed
repeatedly for every pre handler execution where put_user() gets
called to generate fault exception.

Debug: sleeping function called from invalid context at /..../k-004.c:39
in_atomic():1, irqs_disabled():1

Even though interrupts are enabled in the code(MSR bits show it as 
enabled), why the above debug message shows it as disabled? 
It appears that put_user() will  internally call might_sleep() which 
turns out to be a sleeping function. But this same test didnot report 
any kind of above message while testing with ARM and MIPS arch 
even though all interrupts were disabled explicitly. So is it a failure
message ? or wrongly printed only in ppc32? After getting this message,
the test completes and the system is stable!!! 

Since this code is implemented with limited ppc32 arch knowledge,
some key things may be missing in this. Can somebody review this
and provide some inputs for this code?

(Note:After porting the above patches to 2.6.20, the same above results
are noticed!)


Best Regards
Madhvesh

==================
Madhvesh. R. Sulibhavi
Sony India Software Centre
Bangalore



[-- Attachment #2: kprobes-ppc-2.6.16.39-20070313.patch --]
[-- Type: application/octet-stream, Size: 22227 bytes --]

Index: linux-2.6.16.39/arch/powerpc/lib/Makefile
===================================================================
--- linux-2.6.16.39.orig/arch/powerpc/lib/Makefile	2007-03-13 20:37:13.157699240 +0530
+++ linux-2.6.16.39/arch/powerpc/lib/Makefile	2007-03-13 20:39:04.531767808 +0530
@@ -13,8 +13,8 @@
 			   strcase.o
 obj-$(CONFIG_PPC_ISERIES) += e2a.o
 obj-$(CONFIG_XMON)	+= sstep.o
+obj-$(CONFIG_KPROBES)	+= sstep.o
 
 ifeq ($(CONFIG_PPC64),y)
 obj-$(CONFIG_SMP)	+= locks.o
-obj-$(CONFIG_DEBUG_KERNEL) += sstep.o
 endif
Index: linux-2.6.16.39/arch/ppc/Kconfig
===================================================================
--- linux-2.6.16.39.orig/arch/ppc/Kconfig	2007-03-13 20:37:13.157699240 +0530
+++ linux-2.6.16.39/arch/ppc/Kconfig	2007-03-13 20:39:04.533767504 +0530
@@ -1397,3 +1397,17 @@
 source "security/Kconfig"
 
 source "crypto/Kconfig"
+
+menu "Instrumentation Support"
+
+config KPROBES
+	bool "Kprobes"
+	depends on DEBUG_KERNEL
+	help
+	  Kprobes allows you to trap at almost any kernel address and
+	  execute a callback function.  register_kprobe() establishes
+	  a probepoint and specifies the callback.  Kprobes is useful
+	  for kernel debugging, non-intrusive instrumentation and testing.
+	  If in doubt, say "N".
+
+endmenu
Index: linux-2.6.16.39/arch/ppc/kernel/Makefile
===================================================================
--- linux-2.6.16.39.orig/arch/ppc/kernel/Makefile	2007-03-13 20:37:13.158699088 +0530
+++ linux-2.6.16.39/arch/ppc/kernel/Makefile	2007-03-13 20:39:04.534767352 +0530
@@ -21,6 +21,7 @@
 obj-$(CONFIG_PCI)		+= pci.o
 obj-$(CONFIG_RAPIDIO)		+= rio.o
 obj-$(CONFIG_KGDB)		+= ppc-stub.o
+obj-$(CONFIG_KPROBES)		+= kprobes.o
 obj-$(CONFIG_SMP)		+= smp.o smp-tbsync.o
 obj-$(CONFIG_TAU)		+= temp.o
 ifndef CONFIG_E200
Index: linux-2.6.16.39/arch/ppc/kernel/kprobes.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/arch/ppc/kernel/kprobes.c	2007-03-13 20:40:40.425189792 +0530
@@ -0,0 +1,387 @@
+/*
+ *  Kernel Probes (KProbes)
+ *  arch/ppc/kernel/kprobes.c
+ *
+ *  Copyright 2007 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/kprobes.h>
+#include <linux/ptrace.h>
+#include <linux/preempt.h>
+#include <asm/cacheflush.h>
+#include <asm/kdebug.h>
+#include <asm/sstep.h>
+
+DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
+DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
+
+int __kprobes arch_prepare_kprobe(struct kprobe *p)
+{
+	int ret = 0;
+	kprobe_opcode_t insn = *p->addr;
+
+	if ((unsigned long)p->addr & 0x03) {
+		printk("Attempt to register kprobe at an unaligned address\n");
+		ret = -EINVAL;
+	} else if (IS_MTMSRD(insn) || IS_RFID(insn) || IS_RFI(insn)) {
+		printk("Cannot register a kprobe on rfi/rfid or mtmsr[d]\n");
+		ret = -EINVAL;
+	}
+
+	/* insn must be on a special executable page on ppc32 */
+	if (!ret) {
+		p->ainsn.insn = get_insn_slot();
+		if (!p->ainsn.insn)
+			ret = -ENOMEM;
+	}
+
+	if (!ret) {
+		memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
+		p->opcode = *p->addr;
+		flush_icache_range((unsigned long) p->ainsn.insn,
+			(unsigned long) p->ainsn.insn + sizeof(kprobe_opcode_t));
+	}
+
+	return ret;
+}
+
+void __kprobes arch_arm_kprobe(struct kprobe *p)
+{
+	*p->addr = BREAKPOINT_INSTRUCTION;
+	flush_icache_range((unsigned long) p->addr,
+			   (unsigned long) p->addr + sizeof(kprobe_opcode_t));
+}
+
+void __kprobes arch_disarm_kprobe(struct kprobe *p)
+{
+	*p->addr = p->opcode;
+	flush_icache_range((unsigned long) p->addr,
+			   (unsigned long) p->addr + sizeof(kprobe_opcode_t));
+}
+
+void __kprobes arch_remove_kprobe(struct kprobe *p)
+{
+	down(&kprobe_mutex);
+	free_insn_slot(p->ainsn.insn);
+	up(&kprobe_mutex);
+}
+
+static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = *p->ainsn.insn;
+
+#if 0
+	regs->msr &= ~(MSR_EE); /* Turn off 'Externel Intrerrupt' bits */
+	regs->msr &= ~(MSR_CE); /* Turn off 'Critical Intrerrupt' bits */
+#endif
+	regs->msr |= MSR_DE;
+
+	mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM);
+	regs->nip = (unsigned long)p->ainsn.insn;
+}
+
+static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+{
+	kcb->prev_kprobe.kp = kprobe_running();
+	kcb->prev_kprobe.status = kcb->kprobe_status;
+	kcb->prev_kprobe.saved_msr = kcb->kprobe_saved_msr;
+}
+
+static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+{
+	__get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
+	kcb->kprobe_status = kcb->prev_kprobe.status;
+	kcb->kprobe_saved_msr = kcb->prev_kprobe.saved_msr;
+}
+
+static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+				struct kprobe_ctlblk *kcb)
+{
+	__get_cpu_var(current_kprobe) = p;
+	kcb->kprobe_saved_msr = regs->msr;
+}
+
+/* Called with kretprobe_lock held */
+void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
+				      struct pt_regs *regs)
+{
+}
+
+static inline int kprobe_handler(struct pt_regs *regs)
+{
+	struct kprobe *p;
+	int ret = 0;
+	unsigned int *addr = (unsigned int *)regs->nip;
+	struct kprobe_ctlblk *kcb;
+
+
+	/*
+	 * We don't want to be preempted for the entire
+	 * duration of kprobe processing
+	 */
+
+	//preempt_disable();
+	kcb = get_kprobe_ctlblk();
+
+	/* Check we're not actually recursing */
+	if (kprobe_running()) {
+		p = get_kprobe(addr);
+		if (p) {
+			kprobe_opcode_t insn = *p->ainsn.insn;
+			if (kcb->kprobe_status == KPROBE_HIT_SS &&
+					is_trap(insn)) {
+				regs->msr &= ~MSR_DE; /* Turn off 'trace' bits */
+				regs->msr |= kcb->kprobe_saved_msr;
+				goto no_kprobe;
+			}
+			/* We have reentered the kprobe_handler(), since
+			 * another probe was hit while within the handler.
+			 * We here save the original kprobes variables and
+			 * just single step on the instruction of the new probe
+			 * without calling any user handlers.
+			 */
+			save_previous_kprobe(kcb);
+			set_current_kprobe(p, regs, kcb);
+			kcb->kprobe_saved_msr = regs->msr;
+			kprobes_inc_nmissed_count(p);
+			prepare_singlestep(p, regs);
+			kcb->kprobe_status = KPROBE_REENTER;
+			return 1;
+		} else {
+			if (*addr != BREAKPOINT_INSTRUCTION) {
+				/* If trap variant, then it belongs not to us */
+				kprobe_opcode_t cur_insn = *addr;
+				if (is_trap(cur_insn))
+		       			goto no_kprobe;
+				/* The breakpoint instruction was removed by
+				 * another cpu right after we hit, no further
+				 * handling of this interrupt is appropriate
+				 */
+				ret = 1;
+				goto no_kprobe;
+			}
+			p = __get_cpu_var(current_kprobe);
+			if (p->break_handler && p->break_handler(p, regs)) {
+				goto ss_probe;
+			}
+		}
+		goto no_kprobe;
+	}
+
+	p = get_kprobe(addr);
+	if (!p) {
+		if (*addr != BREAKPOINT_INSTRUCTION) {
+			/*
+			 * PowerPC has multiple variants of the "trap"
+			 * instruction. If the current instruction is a
+			 * trap variant, it could belong to someone else
+			 */
+			kprobe_opcode_t cur_insn = *addr;
+			if (is_trap(cur_insn))
+		       		goto no_kprobe;
+			/*
+			 * The breakpoint instruction was removed right
+			 * after we hit it.  Another cpu has removed
+			 * either a probepoint or a debugger breakpoint
+			 * at this address.  In either case, no further
+			 * handling of this interrupt is appropriate.
+			 */
+			ret = 1;
+		}
+		/* Not one of ours: let kernel handle it */
+		goto no_kprobe;
+	}
+
+	kcb->kprobe_status = KPROBE_HIT_ACTIVE;
+	set_current_kprobe(p, regs, kcb);
+	if (p->pre_handler && p->pre_handler(p, regs))
+		/* handler has already set things up, so skip ss setup */
+		return 1;
+
+ss_probe:
+	prepare_singlestep(p, regs);
+	kcb->kprobe_status = KPROBE_HIT_SS;
+	return 1;
+
+no_kprobe:
+	//preempt_enable_no_resched();
+	return ret;
+}
+
+/*
+ * Function return probe trampoline:
+ * 	- init_kprobes() establishes a probepoint here
+ * 	- When the probed function returns, this probe
+ * 		causes the handlers to fire
+ */
+void kretprobe_trampoline_holder(void)
+{
+}
+
+/*
+ * Called when the probe at kretprobe trampoline is hit
+ */
+int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
+{
+        return 1;
+}
+
+/*
+ * Called after single-stepping.  p->addr is the address of the
+ * instruction whose first byte has been replaced by the "breakpoint"
+ * instruction.  To avoid the SMP problems that can occur when we
+ * temporarily put back the original opcode to single-step, we
+ * single-stepped a copy of the instruction.  The address of this
+ * copy is p->ainsn.insn.
+ */
+static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
+{
+	int ret;
+	unsigned int insn = *p->ainsn.insn;
+
+	regs->nip = (unsigned long)p->addr;
+	ret = emulate_step(regs, insn);
+	if (ret == 0)
+		regs->nip = (unsigned long)p->addr + 4;
+}
+
+static inline int post_kprobe_handler(struct pt_regs *regs)
+{
+	struct kprobe *cur = kprobe_running();
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+	if (!cur)
+		return 0;
+
+	if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
+		kcb->kprobe_status = KPROBE_HIT_SSDONE;
+		cur->post_handler(cur, regs, 0);
+	}
+
+	resume_execution(cur, regs);
+	regs->msr |= kcb->kprobe_saved_msr;
+
+	/*Restore back the original saved kprobes variables and continue. */
+	if (kcb->kprobe_status == KPROBE_REENTER) {
+		restore_previous_kprobe(kcb);
+		goto out;
+	}
+	reset_current_kprobe();
+out:
+	//preempt_enable_no_resched();
+
+	/*
+	 * if somebody else is singlestepping across a probe point, msr
+	 * will have DE set, in which case, continue the remaining processing
+	 * of do_debug, as if this is not a probe hit.
+	 */
+	if (regs->msr & MSR_DE)
+		return 0;
+#if 0
+	regs->msr |= (MSR_EE); /* Turn on 'External Intrerrupt' bits */
+	regs->msr |= (MSR_CE); /* Turn on 'Critical Intrerrupt' bits */
+#endif
+
+	return 1;
+}
+
+static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+{
+	struct kprobe *cur = kprobe_running();
+	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+	if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
+		return 1;
+
+	if (kcb->kprobe_status & KPROBE_HIT_SS) {
+		resume_execution(cur, regs);
+		regs->msr &= ~MSR_DE; /* Turn off 'trace' bits */
+		regs->msr |= kcb->kprobe_saved_msr;
+
+		reset_current_kprobe();
+		//preempt_enable_no_resched();
+	}
+
+#if 0
+	regs->msr |= (MSR_EE); /* Turn on 'External Intrerrupt' bits */
+	regs->msr |= (MSR_CE); /* Turn on 'Critical Intrerrupt' bits */
+#endif
+
+	return 0;
+}
+
+/*
+ * Wrapper routine to for handling exceptions.
+ */
+int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
+				       unsigned long val, void *data)
+{
+	struct die_args *args = (struct die_args *)data;
+	int ret = NOTIFY_DONE;
+
+	switch (val) {
+	case DIE_BPT:
+		preempt_disable();
+		if (kprobe_handler(args->regs))
+			ret = NOTIFY_STOP;
+		preempt_enable_no_resched();
+		break;
+	case DIE_SSTEP:
+		preempt_disable();
+		if (post_kprobe_handler(args->regs))
+			ret = NOTIFY_STOP;
+		preempt_enable_no_resched();
+		break;
+	case DIE_PAGE_FAULT:
+		/* kprobe_running() needs smp_processor_id() */
+		preempt_disable();
+		if (kprobe_running() &&
+		    kprobe_fault_handler(args->regs, args->trapnr))
+			ret = NOTIFY_STOP;
+		preempt_enable();
+		break;
+	case DIE_IABR_MATCH:
+		printk("\nDIE_IABR_MATCH is found\n");
+		break;
+	default:
+		break;
+	}
+	return ret;
+}
+
+int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	return 1;
+}
+
+void __kprobes jprobe_return(void)
+{
+}
+
+void __kprobes jprobe_return_end(void)
+{
+};
+
+int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	return 1;
+}
+
+int __init arch_init_kprobes(void)
+{
+	return 0;
+}
Index: linux-2.6.16.39/arch/ppc/kernel/misc.S
===================================================================
--- linux-2.6.16.39.orig/arch/ppc/kernel/misc.S	2007-03-13 20:37:13.158699088 +0530
+++ linux-2.6.16.39/arch/ppc/kernel/misc.S	2007-03-13 20:39:04.537766896 +0530
@@ -427,7 +427,7 @@
  *
  * __flush_icache_range(unsigned long start, unsigned long stop)
  */
-_GLOBAL(__flush_icache_range)
+_KPROBE(__flush_icache_range)
 BEGIN_FTR_SECTION
 	blr				/* for 601, do nothing */
 END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
Index: linux-2.6.16.39/arch/ppc/kernel/traps.c
===================================================================
--- linux-2.6.16.39.orig/arch/ppc/kernel/traps.c	2007-03-13 20:37:13.158699088 +0530
+++ linux-2.6.16.39/arch/ppc/kernel/traps.c	2007-03-13 20:39:04.539766592 +0530
@@ -31,6 +31,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/prctl.h>
+#include <linux/kprobes.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -39,6 +40,7 @@
 #include <asm/reg.h>
 #include <asm/xmon.h>
 #include <asm/pmc.h>
+#include <asm/kdebug.h>
 
 #ifdef CONFIG_XMON
 extern int xmon_bpt(struct pt_regs *regs);
@@ -70,6 +72,23 @@
 #endif
 #endif
 
+#ifdef CONFIG_KPROBES
+struct notifier_block *ppc_die_chain;
+static DEFINE_SPINLOCK(die_notifier_lock);
+
+int register_die_notifier(struct notifier_block *nb)
+{
+	int err = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&die_notifier_lock, flags);
+	err = notifier_chain_register(&ppc_die_chain, nb);
+	spin_unlock_irqrestore(&die_notifier_lock, flags);
+	return err;
+}
+
+#endif
+
 /*
  * Trap & Exception support
  */
@@ -402,6 +421,11 @@
 
 void instruction_breakpoint_exception(struct pt_regs *regs)
 {
+#ifdef CONFIG_KPROBES
+	if (notify_die(DIE_IABR_MATCH, "iabr_match", regs, 5,
+					5, SIGTRAP) == NOTIFY_STOP)
+		return;
+#endif
 	if (debugger_iabr_match(regs))
 		return;
 	_exception(SIGTRAP, regs, TRAP_BRKPT, 0);
@@ -622,7 +646,7 @@
 	return 0;
 }
 
-void program_check_exception(struct pt_regs *regs)
+void __kprobes program_check_exception(struct pt_regs *regs)
 {
 	unsigned int reason = get_reason(regs);
 	extern int do_mathemu(struct pt_regs *regs);
@@ -671,6 +695,11 @@
 	}
 
 	if (reason & REASON_TRAP) {
+#ifdef CONFIG_KPROBES
+		if (notify_die(DIE_BPT, "breakpoint", regs, 5, 5, SIGTRAP)
+				== NOTIFY_STOP)
+			return;
+#endif
 		/* trap exception */
 		if (debugger_bpt(regs))
 			return;
@@ -793,6 +822,20 @@
 {
 	if (debug_status & DBSR_IC) {	/* instruction completion */
 		regs->msr &= ~MSR_DE;
+
+#ifdef CONFIG_KPROBES
+
+	/* Disable instruction completion */
+	mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) & ~DBCR0_IC);
+
+	/* Clear the instruction completion event */
+	mtspr(SPRN_DBSR, DBSR_IC);
+
+	if (notify_die(DIE_SSTEP, "single_step", regs, 5,
+			5, SIGTRAP) == NOTIFY_STOP)
+		return;
+#endif
+
 		if (user_mode(regs)) {
 			current->thread.dbcr0 &= ~DBCR0_IC;
 		} else {
Index: linux-2.6.16.39/arch/ppc/kernel/vmlinux.lds.S
===================================================================
--- linux-2.6.16.39.orig/arch/ppc/kernel/vmlinux.lds.S	2007-03-13 20:37:13.159698936 +0530
+++ linux-2.6.16.39/arch/ppc/kernel/vmlinux.lds.S	2007-03-13 20:39:04.539766592 +0530
@@ -33,6 +33,7 @@
     *(.text)
     SCHED_TEXT
     LOCK_TEXT
+    KPROBES_TEXT
     *(.fixup)
     *(.got1)
     __got2_start = .;
Index: linux-2.6.16.39/arch/ppc/mm/fault.c
===================================================================
--- linux-2.6.16.39.orig/arch/ppc/mm/fault.c	2007-03-13 20:37:13.159698936 +0530
+++ linux-2.6.16.39/arch/ppc/mm/fault.c	2007-03-13 20:39:04.541766288 +0530
@@ -28,6 +28,7 @@
 #include <linux/interrupt.h>
 #include <linux/highmem.h>
 #include <linux/module.h>
+#include <linux/kprobes.h>
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -36,6 +37,7 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/tlbflush.h>
+#include <asm/kdebug.h>
 
 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
 extern void (*debugger)(struct pt_regs *);
@@ -92,7 +94,7 @@
  * the error_code parameter is ESR for a data fault, 0 for an instruction
  * fault.
  */
-int do_page_fault(struct pt_regs *regs, unsigned long address,
+int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
 		  unsigned long error_code)
 {
 	struct vm_area_struct * vma;
@@ -116,6 +118,13 @@
 		is_write = error_code & 0x02000000;
 #endif /* CONFIG_4xx || CONFIG_BOOKE */
 
+#ifdef CONFIG_KPROBES
+	if (notify_die(DIE_PAGE_FAULT, "page_fault", regs, error_code,
+				11, SIGSEGV) == NOTIFY_STOP) {
+		return 0;
+	}
+#endif
+
 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
 	if (debugger_fault_handler && TRAP(regs) == 0x300) {
 		debugger_fault_handler(regs);
Index: linux-2.6.16.39/include/asm-powerpc/sstep.h
===================================================================
--- linux-2.6.16.39.orig/include/asm-powerpc/sstep.h	2007-03-13 20:37:13.160698784 +0530
+++ linux-2.6.16.39/include/asm-powerpc/sstep.h	2007-03-13 20:39:04.542766136 +0530
@@ -21,6 +21,7 @@
  */
 #define IS_MTMSRD(instr)	(((instr) & 0xfc0007be) == 0x7c000124)
 #define IS_RFID(instr)		(((instr) & 0xfc0007fe) == 0x4c000024)
+#define IS_RFI(instr)		(((instr) & 0xfc0007fe) == 0x4c000064)
 
 /* Emulate instructions that cause a transfer of control. */
 extern int emulate_step(struct pt_regs *regs, unsigned int instr);
Index: linux-2.6.16.39/include/asm-ppc/kdebug.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/include/asm-ppc/kdebug.h	2007-03-13 20:39:04.542766136 +0530
@@ -0,0 +1,60 @@
+#ifndef __PPC_KDEBUG_H
+#define __PPC_KDEBUG_H
+#ifdef __KERNEL__
+/*
+ *  Kernel Probes (KProbes)
+ *  include/asm-ppc/kdebug.h
+ *
+ *  Copyright 2007 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/notifier.h>
+
+struct pt_regs;
+
+struct die_args {
+	struct pt_regs *regs;
+	const char *str;
+	long err;
+	int trapnr;
+	int signr;
+};
+
+/*
+   Note - you should never unregister because that can race with NMIs.
+   If you really want to do it first unregister - then synchronize_sched -
+   then free.
+ */
+int register_die_notifier(struct notifier_block *nb);
+extern struct notifier_block *ppc_die_chain;
+
+/* Grossly misnamed. */
+enum die_val {
+	DIE_OOPS = 1,
+	DIE_IABR_MATCH,
+	DIE_BPT,
+	DIE_SSTEP,
+	DIE_PAGE_FAULT,
+};
+
+static inline int notify_die(enum die_val val,char *str,struct pt_regs *regs,long err,int trap, int sig)
+{
+	struct die_args args = { .regs=regs, .str=str, .err=err, .trapnr=trap,.signr=sig };
+	return notifier_call_chain(&ppc_die_chain, val, &args);
+}
+
+#endif /* __KERNEL__ */
+#endif /* __PPC_KDEBUG_H */
Index: linux-2.6.16.39/include/asm-ppc/kprobes.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/include/asm-ppc/kprobes.h	2007-03-13 20:39:04.543765984 +0530
@@ -0,0 +1,71 @@
+#ifndef __PPC_KPROBES_H
+#define __PPC_KPROBES_H
+#ifdef __KERNEL__
+/*
+ *  Kernel Probes (KProbes)
+ *  include/asm-ppc/kprobes.h
+ *
+ *  Copyright 2007 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/percpu.h>
+
+#define  __ARCH_WANT_KPROBES_INSN_SLOT
+
+struct pt_regs;
+struct kprobe;
+
+typedef unsigned int kprobe_opcode_t;
+#define BREAKPOINT_INSTRUCTION	0x7fe00008	/* trap */
+#define MAX_INSN_SIZE 1
+
+#define IS_TW(instr)		(((instr) & 0xfc0007fe) == 0x7c000008)
+#define IS_TWI(instr)		(((instr) & 0xfc000000) == 0x0c000000)
+
+#define JPROBE_ENTRY(pentry)	(kprobe_opcode_t *)((func_descr_t *)pentry)
+
+#define is_trap(instr)	(IS_TW(instr) || IS_TWI(instr))
+
+#define ARCH_SUPPORTS_KRETPROBES
+void kretprobe_trampoline(void);
+extern void arch_remove_kprobe(struct kprobe *p);
+
+/* Architecture specific copy of original instruction */
+struct arch_specific_insn {
+	/* copy of original instruction */
+	kprobe_opcode_t *insn;
+};
+
+struct prev_kprobe {
+	struct kprobe *kp;
+	unsigned long status;
+	unsigned long saved_msr;
+};
+
+/* per-cpu kprobe control block */
+struct kprobe_ctlblk {
+	unsigned long kprobe_status;
+	unsigned long kprobe_saved_msr;
+	struct pt_regs jprobe_saved_regs;
+	struct prev_kprobe prev_kprobe;
+};
+
+extern int kprobe_exceptions_notify(struct notifier_block *self,
+					unsigned long val, void *data);
+#endif /* __KERNEL__ */
+#endif	/* __PPC_KPROBES_H */

[-- Attachment #3: kprobes-kernel-test-module-20070313.patch --]
[-- Type: application/octet-stream, Size: 41816 bytes --]

Index: linux-2.6.16.39/Makefile
===================================================================
--- linux-2.6.16.39.orig/Makefile	2007-03-13 20:37:12.074863856 +0530
+++ linux-2.6.16.39/Makefile	2007-03-13 20:39:06.244507432 +0530
@@ -559,7 +559,7 @@
 
 
 ifeq ($(KBUILD_EXTMOD),)
-core-y		+= kernel/ mm/ fs/ ipc/ security/ crypto/ block/
+core-y		+= kernel/ mm/ fs/ ipc/ security/ crypto/ block/ kprobe-tests/
 
 vmlinux-dirs	:= $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
 		     $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
Index: linux-2.6.16.39/kprobe-tests/Kconfig
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/kprobe-tests/Kconfig	2007-03-13 20:39:06.245507280 +0530
@@ -0,0 +1,13 @@
+#
+# Kprobes test modules configuration
+#
+config KPROBESTEST
+	tristate "Kprobes test modules"
+	depends on KPROBES
+	default m if KPROBES=y
+	help
+	  This support if enabled, will be used to test the kprobes support.
+
+	  To compile this kprobe test support as a module, choose M here: the
+	  module will be called k-00x(x will be any number in 1,2,....9).
+	  If in doubt, say "N"
Index: linux-2.6.16.39/kprobe-tests/Makefile
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/kprobe-tests/Makefile	2007-03-13 20:39:06.245507280 +0530
@@ -0,0 +1,5 @@
+#
+# Makefile for the Kprobes test modules kernel.
+#
+obj-$(CONFIG_KPROBESTEST) += k-001.o k-002.o k-003.o k-004.o k-005.o k-006.o \
+				k-007.o k-008.o k-009.o
Index: linux-2.6.16.39/kprobe-tests/k-001.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/kprobe-tests/k-001.c	2007-03-13 20:39:06.246507128 +0530
@@ -0,0 +1,91 @@
+/*
+ *  k-001.c - A Kprobe with probe point to the kernel function 'do_fork'.
+ *
+ *  Copyright 2007 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
+#include "kprobes-test.h"
+
+#if defined(CONFIG_PPC32)
+extern void show_allregs(struct pt_regs *regs);
+#endif
+static struct kprobe k_001_kpr;
+
+static void __exit k_001_exit_probe(void)
+{
+	printk("\nModule exiting from do_fork \n");
+	unregister_kprobe(&k_001_kpr);
+}
+
+static int k_001_before_hook(struct kprobe *k_001_kpr, struct pt_regs *p)
+{
+	printk("\nBefore hook in do_fork");
+	printk("\nThis is the Kprobe pre \n"
+	       "handler for instruction at %p\n", k_001_kpr->addr);
+	printk("Stack Dump :\n");
+	dump_stack();
+	printk("The Registers are:\n");
+#if defined(CONFIG_PPC32)
+	show_allregs(p);
+#endif
+	return 0;
+}
+
+static int k_001_after_hook(struct kprobe *k_001_kpr,
+			    struct pt_regs *p, unsigned long flags)
+{
+	printk("\nAfter hook in do_fork");
+	printk("\nThis is the Kprobe post \n"
+	       "handler for instruction at" " %p\n", k_001_kpr->addr);
+	printk("Stack Dump :\n");
+	dump_stack();
+	printk("The Registers are:\n");
+#if defined(CONFIG_PPC32)
+	show_allregs(p);
+#endif
+	return 0;
+}
+
+static int __init k_001_init_probe(void)
+{
+	printk("\nInserting the kprobe for do_fork\n");
+
+	/* Registering a kprobe */
+	k_001_kpr.pre_handler = (kprobe_pre_handler_t) k_001_before_hook;
+	k_001_kpr.post_handler = (kprobe_post_handler_t) k_001_after_hook;
+	k_001_kpr.addr = (kprobe_opcode_t *) kallsyms_lookup_name("do_fork");
+	if (k_001_kpr.addr == NULL) {
+		printk("kallsyms_lookup_name could not find address "
+		       "for the specified symbol name\n");
+		return 1;
+	}
+
+	printk("\nAddress where the kprobe is \n"
+	       "going to be inserted - %p\n", k_001_kpr.addr);
+	register_kprobe(&k_001_kpr);
+	return 0;
+}
+
+module_init(k_001_init_probe);
+module_exit(k_001_exit_probe);
+
+MODULE_DESCRIPTION("Kprobes test module");
+MODULE_LICENSE("GPL");
Index: linux-2.6.16.39/kprobe-tests/k-002.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/kprobe-tests/k-002.c	2007-03-13 20:39:06.247506976 +0530
@@ -0,0 +1,95 @@
+/*
+ * k-002.c - Multiple Kprobes with the same probe point for the kernel
+ * function 'do_fork'.
+ *
+ *  Copyright 2007 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
+
+static struct kprobe k_002_kp1;
+static struct kprobe k_002_kp2;
+
+static void __exit k_002_exit_probe(void)
+{
+	printk("\nModule exiting");
+	printk("2 kprobes from do-fork\n");
+	unregister_kprobe(&k_002_kp2);
+	unregister_kprobe(&k_002_kp1);
+}
+
+static int k_002_before_hook(struct kprobe *k_002_kp1, struct pt_regs *p)
+{
+	printk("\nBefore hook 1st do_fork\n");
+	return 0;
+}
+
+static int k_002_after_hook(struct kprobe *k_002_kp1,
+			    struct pt_regs *p, unsigned long flags)
+{
+	printk("\nAfter hook 1st do_fork\n");
+	return 0;
+}
+
+static int k_002_pre_handler(struct kprobe *k_002_kp2, struct pt_regs *p)
+{
+	printk("\nBefore hook 2nd do_fork\n");
+	return 0;
+}
+
+static int k_002_post_handler(struct kprobe *k_002_kp2,
+			      struct pt_regs *p, unsigned long flags)
+{
+	printk("\nAfter hook 2nd do_fork\n");
+	return 0;
+}
+
+static int __init k_002_init_probe(void)
+{
+	printk("\nInserting two kprobes at the same probe point\n");
+
+	/* Registering a kprobe */
+	k_002_kp1.pre_handler = (kprobe_pre_handler_t) k_002_before_hook;
+	k_002_kp1.post_handler = (kprobe_post_handler_t) k_002_after_hook;
+
+	k_002_kp2.pre_handler = (kprobe_pre_handler_t) k_002_pre_handler;
+	k_002_kp2.post_handler = (kprobe_post_handler_t) k_002_post_handler;
+	k_002_kp2.addr = k_002_kp1.addr =
+	    (kprobe_opcode_t *) kallsyms_lookup_name("do_fork");
+	if ((k_002_kp1.addr == NULL) || (k_002_kp2.addr == NULL)) {
+		printk("kallsyms_lookup_name could not find address "
+		       "for the specified symbol name\n");
+		return 1;
+	}
+
+	printk("\nAddress where the two kprobes are \n"
+	       "going to be inserted - %p and %p\n", k_002_kp1.addr,
+	       k_002_kp2.addr);
+	register_kprobe(&k_002_kp1);
+	register_kprobe(&k_002_kp2);
+
+	return 0;
+}
+
+module_init(k_002_init_probe);
+module_exit(k_002_exit_probe);
+
+MODULE_DESCRIPTION("Kprobes test module");
+MODULE_LICENSE("GPL");
Index: linux-2.6.16.39/kprobe-tests/k-003.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/kprobe-tests/k-003.c	2007-03-13 20:39:06.248506824 +0530
@@ -0,0 +1,97 @@
+/*
+ *  k-003.c - Multiple kprobes with the different probe point for the kernel
+ *  function 'do_fork' and 'sys_gettimeofday'.
+ *
+ *  Copyright 2007 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
+
+static struct kprobe k_003_kp1;
+static struct kprobe k_003_kp2;
+
+static void __exit k_003_exit_probe(void)
+{
+	printk("\nModule exiting");
+	printk("\n2 kprobes from do-fork and sys_gettimeofday\n");
+	unregister_kprobe(&k_003_kp2);
+	unregister_kprobe(&k_003_kp1);
+}
+
+static int k_003_before_hook(struct kprobe *k_003_kp1, struct pt_regs *p)
+{
+	printk("\nBefore hook in do_fork\n");
+	return 0;
+}
+
+static int k_003_after_hook(struct kprobe *k_003_kp1,
+			    struct pt_regs *p, unsigned long flags)
+{
+	printk("\nAfter hook in do_fork\n");
+	return 0;
+}
+
+static int k_003_pre_handler(struct kprobe *k_003_kp2, struct pt_regs *p)
+{
+	printk("\nBefore hook in sys_gettimeofday\n");
+	return 0;
+}
+
+static int k_003_post_handler(struct kprobe *k_003_kp2,
+			      struct pt_regs *p, unsigned long flags)
+{
+	printk("\nAfter hook in sys_gettimeofday\n");
+	return 0;
+}
+
+static int __init k_003_init_probe(void)
+{
+	printk("\nInserting two kprobes at differnt probe point\n");
+
+	/* Registering a kprobe */
+	k_003_kp1.pre_handler = (kprobe_pre_handler_t) k_003_before_hook;
+	k_003_kp1.post_handler = (kprobe_post_handler_t) k_003_after_hook;
+
+	k_003_kp2.pre_handler = (kprobe_pre_handler_t) k_003_pre_handler;
+	k_003_kp2.post_handler = (kprobe_post_handler_t) k_003_post_handler;
+	k_003_kp1.addr = (kprobe_opcode_t *) kallsyms_lookup_name("do_fork");
+	k_003_kp2.addr =
+	    (kprobe_opcode_t *) kallsyms_lookup_name("sys_gettimeofday");
+
+	if ((k_003_kp1.addr == NULL) | (k_003_kp2.addr == NULL)) {
+		printk("kallsyms_lookup_name could not find address "
+		       "for the specified symbol name\n");
+		return 1;
+	}
+
+	printk("\nAddress where the kprobes are \n"
+	       "going to be inserted - %p  and  %p\n", k_003_kp1.addr,
+	       k_003_kp2.addr);
+	register_kprobe(&k_003_kp1);
+	register_kprobe(&k_003_kp2);
+
+	return 0;
+}
+
+module_init(k_003_init_probe);
+module_exit(k_003_exit_probe);
+
+MODULE_DESCRIPTION("Kprobes test module");
+MODULE_LICENSE("GPL");
Index: linux-2.6.16.39/kprobe-tests/k-004.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/kprobe-tests/k-004.c	2007-03-13 20:39:06.249506672 +0530
@@ -0,0 +1,124 @@
+/*
+ *  k-004.c - Kprobes with the fault handler for the kernel function
+ *  'sys_gettimeofday'.
+ *
+ *  Copyright 2007 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
+#include "kprobes-test.h"
+
+#if defined(CONFIG_PPC32)
+extern void show_allregs(struct pt_regs *regs);
+#endif
+static struct kprobe k_004_kpr;
+
+void k_004_CPY_FROM_USER(struct file *file, char *buf, int len)
+{
+
+	char x = 'a';
+
+	if (put_user(x, buf)) {
+		printk("put_user : -EFAULT\n");
+	}
+
+	printk("CPY_FROM_USER\n");
+}
+
+static void __exit k_004_exit_probe(void)
+{
+	printk("\nModule exiting from sys_gettimeofday \n");
+	unregister_kprobe(&k_004_kpr);
+}
+
+static int k_004_before_hook(struct kprobe *k_004_kpr, struct pt_regs *p)
+{
+	int len = 500;
+	struct file *file;
+
+	printk("\nBefore hook in sys_gettimeofday");
+	printk("\nThis is the Kprobe pre \n"
+	       "handler for instruction at" "%p\n", k_004_kpr->addr);
+	printk("Stack Dump:\n");
+	dump_stack();
+	printk("The Registers are:\n");
+#if defined(CONFIG_PPC32)
+	show_allregs(p);
+#endif
+	k_004_CPY_FROM_USER(file, NULL, len);
+	return 0;
+}
+
+static int k_004_after_hook(struct kprobe *k_004_kpr,
+			    struct pt_regs *p, unsigned long flags)
+{
+	printk("\nAfter hook in sys_gettimeofday");
+	printk("\nThis is the Kprobe post \n"
+	       "handler for instruction at" " %p\n", k_004_kpr->addr);
+	printk("Stack Dump:\n");
+	dump_stack();
+	printk("The Registers are:\n");
+#if defined(CONFIG_PPC32)
+	show_allregs(p);
+#endif
+	return 0;
+}
+
+int k_004_fault_probe(struct kprobe *p, struct pt_regs *regs, int trapnr)
+{
+	printk("\nThis is the Kprobe fault \n"
+	       "handler for sys_gettimeodday\n");
+	printk("fault_handler:p->addr=0x%p\n", p->addr);
+	printk("Stack Dump:\n");
+	dump_stack();
+	printk("The Registers are:\n");
+#if defined(CONFIG_PPC32)
+	show_allregs(regs);
+#endif
+	return 0;
+}
+
+static int __init k_004_init_probe(void)
+{
+	printk("\nInserting the kprobes  for sys_gettimeofday\n");
+
+	/* Registering a kprobe */
+	k_004_kpr.pre_handler = (kprobe_pre_handler_t) k_004_before_hook;
+	k_004_kpr.post_handler = (kprobe_post_handler_t) k_004_after_hook;
+	k_004_kpr.fault_handler = (kprobe_fault_handler_t) k_004_fault_probe;
+	k_004_kpr.addr =
+	    (kprobe_opcode_t *) kallsyms_lookup_name("sys_gettimeofday");
+	if (k_004_kpr.addr == NULL) {
+		printk("kallsyms_lookup_name could not find address "
+		       "for the specified symbol name\n");
+		return 1;
+	}
+
+	printk("\nAddress where the kprobe is \n"
+	       "going to be inserted - %p\n", k_004_kpr.addr);
+	register_kprobe(&k_004_kpr);
+	return 0;
+}
+
+module_init(k_004_init_probe);
+module_exit(k_004_exit_probe);
+
+MODULE_DESCRIPTION("Kprobes test module");
+MODULE_LICENSE("GPL");
Index: linux-2.6.16.39/kprobe-tests/k-005.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/kprobe-tests/k-005.c	2007-03-13 20:39:06.249506672 +0530
@@ -0,0 +1,72 @@
+/*
+ *  k-005.c - A Kprobe with probe point to the kernel function sys_read.
+ *
+ *  Copyright 2007 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
+
+static struct kprobe k_005_kpr;
+static int k_005_kr_kprobe_read_cnt;
+
+static void __exit k_005_exit_probe(void)
+{
+	printk("kernel kprobe_read_cnt is %d \n", k_005_kr_kprobe_read_cnt);
+	printk("\nModule exiting from sys_read \n");
+	unregister_kprobe(&k_005_kpr);
+}
+
+static int k_005_before_hook(struct kprobe *kpr, struct pt_regs *p)
+{
+	return 0;
+}
+
+static int k_005_after_hook(struct kprobe *kpr,
+			    struct pt_regs *p, unsigned long flags)
+{
+	k_005_kr_kprobe_read_cnt++;
+	return 0;
+}
+
+static int __init k_005_init_probe(void)
+{
+	printk("\nInserting the kprobe for sys_read\n");
+
+	/* Registering a kprobe */
+	k_005_kpr.pre_handler = (kprobe_pre_handler_t) k_005_before_hook;
+	k_005_kpr.post_handler = (kprobe_post_handler_t) k_005_after_hook;
+	k_005_kpr.addr = (kprobe_opcode_t *) kallsyms_lookup_name("sys_read");
+	if (k_005_kpr.addr == NULL) {
+		printk("kallsyms_lookup_name could not find address "
+		       "for the specified symbol name\n");
+		return 1;
+	}
+
+	printk("\nAddress where the kprobe is \n"
+	       "going to be inserted - %p\n", k_005_kpr.addr);
+	register_kprobe(&k_005_kpr);
+	return 0;
+}
+
+module_init(k_005_init_probe);
+module_exit(k_005_exit_probe);
+
+MODULE_DESCRIPTION("Kprobes test module");
+MODULE_LICENSE("GPL");
Index: linux-2.6.16.39/kprobe-tests/k-006.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/kprobe-tests/k-006.c	2007-03-13 20:39:06.250506520 +0530
@@ -0,0 +1,72 @@
+/*
+ *  k-006.c - A Kprobe with probe point to the kernel function sys_write.
+ *
+ *  Copyright 2007 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
+
+static struct kprobe k_006_kpr;
+static int k_006_kr_kprobe_write_cnt;
+
+static void __exit k_006_exit_probe(void)
+{
+	printk("kernel kprobe_write_cnt is %d \n", k_006_kr_kprobe_write_cnt);
+	printk("\nModule exiting from sys_write \n");
+	unregister_kprobe(&k_006_kpr);
+}
+
+static int k_006_before_hook(struct kprobe *kpr, struct pt_regs *p)
+{
+	return 0;
+}
+
+static int k_006_after_hook(struct kprobe *kpr,
+			    struct pt_regs *p, unsigned long flags)
+{
+	k_006_kr_kprobe_write_cnt++;
+	return 0;
+}
+
+static int __init k_006_init_probe(void)
+{
+	printk("\nInserting the kprobe for sys_write\n");
+
+	/* Registering a kprobe */
+	k_006_kpr.pre_handler = (kprobe_pre_handler_t) k_006_before_hook;
+	k_006_kpr.post_handler = (kprobe_post_handler_t) k_006_after_hook;
+	k_006_kpr.addr = (kprobe_opcode_t *) kallsyms_lookup_name("sys_write");
+	if (k_006_kpr.addr == NULL) {
+		printk("kallsyms_lookup_name could not find address "
+		       "for the specified symbol name\n");
+		return 1;
+	}
+
+	printk("\nAddress where the kprobe is \n"
+	       "going to be inserted - %p\n", k_006_kpr.addr);
+	register_kprobe(&k_006_kpr);
+	return 0;
+}
+
+module_init(k_006_init_probe);
+module_exit(k_006_exit_probe);
+
+MODULE_DESCRIPTION("Kprobes test module");
+MODULE_LICENSE("GPL");
Index: linux-2.6.16.39/kprobe-tests/k-007.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/kprobe-tests/k-007.c	2007-03-13 20:39:06.251506368 +0530
@@ -0,0 +1,80 @@
+/*
+ *  k-007.c - Kprobes with probe points to the kernel functions __kmalloc and
+ *  kfree.
+ *
+ *  Copyright 2007 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
+
+static struct kprobe k_007_kp, k_007_kp1;
+int k_007_kmalloc_count = 0;
+int k_007_kfree_count = 0;
+
+static int k_007_kmalloc_hndlr(struct kprobe *kpr, struct pt_regs *p)
+{
+	k_007_kmalloc_count++;
+	return 0;
+}
+
+static int k_007_kfree_hndlr(struct kprobe *kpr, struct pt_regs *p)
+{
+	k_007_kfree_count++;
+	return 0;
+}
+
+static int __init k_007_kmf_init(void)
+{
+	int ret;
+	k_007_kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("__kmalloc");
+	k_007_kp.pre_handler = k_007_kmalloc_hndlr;
+	k_007_kp1.addr = (kprobe_opcode_t *) kallsyms_lookup_name("kfree");
+	k_007_kp1.pre_handler = k_007_kfree_hndlr;
+	ret = register_kprobe(&k_007_kp);
+	if (ret != 0) {
+		printk(KERN_ERR "register_kprobe returns %d %d \n", ret,
+		       __LINE__);
+		return -1;
+	}
+
+	ret = register_kprobe(&k_007_kp1);
+	if (ret != 0) {
+		printk(KERN_ERR "register_kprobe returns %d %d \n", ret,
+		       __LINE__);
+		return -1;
+	}
+
+	return 0;
+}
+
+static void __exit k_007_kmf_exit(void)
+{
+	printk("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n\n\n\n");
+	printk("kmalloc count is %d \n", k_007_kmalloc_count);
+	printk("kfree count is %d \n", k_007_kfree_count);
+	printk("\n\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n");
+	unregister_kprobe(&k_007_kp);
+	unregister_kprobe(&k_007_kp1);
+	printk(KERN_INFO "ktime: exiting...\n");
+}
+
+module_init(k_007_kmf_init);
+module_exit(k_007_kmf_exit);
+MODULE_LICENSE("GPL");
Index: linux-2.6.16.39/kprobe-tests/k-008.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/kprobe-tests/k-008.c	2007-03-13 20:39:06.252506216 +0530
@@ -0,0 +1,68 @@
+/*
+ *  k-008.c - A Kprobe with a probe point to the kernel function
+ *  do_gettimeofday, with an empty pre-handler which can be used
+ *  to measure the Kprobes overhead.
+ *
+ *  Copyright 2007 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
+
+static struct kprobe k_008_kp1;
+
+static void __exit k_008_exit_probe(void)
+{
+	printk("\nModule exiting ");
+	printk("from gettimeofday\n");
+	unregister_kprobe(&k_008_kp1);
+}
+
+static int k_008_pre_handler(struct kprobe *k_008_kp1, struct pt_regs *p)
+{
+	return 0;
+}
+
+static int __init k_008_init_probe(void)
+{
+	printk("\nInserting the kprobe at do_gettimeofday\n");
+
+	/* Registering a kprobe */
+	k_008_kp1.pre_handler = (kprobe_pre_handler_t) k_008_pre_handler;
+	k_008_kp1.addr =
+	    (kprobe_opcode_t *) kallsyms_lookup_name("do_gettimeofday");
+
+	if (k_008_kp1.addr == NULL) {
+		printk("kallsyms_lookup_name could not find address "
+		       "for the specified symbol name\n");
+		return 1;
+	}
+
+	printk("\nAddress where the kprobes are \n"
+	       "going to be inserted - %p \n", k_008_kp1.addr);
+	register_kprobe(&k_008_kp1);
+
+	return 0;
+}
+
+module_init(k_008_init_probe);
+module_exit(k_008_exit_probe);
+
+MODULE_DESCRIPTION("Kprobes test module");
+MODULE_LICENSE("GPL");
Index: linux-2.6.16.39/kprobe-tests/k-009.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/kprobe-tests/k-009.c	2007-03-13 20:39:06.253506064 +0530
@@ -0,0 +1,74 @@
+/*
+ *  k-009.c - A Kprobe with a probe point to the kernel function
+ *  do_gettimeofday, with the empty pre-handler and post-handler
+ *  which can be used to measure the Kprobes overhead.
+ *
+ *  Copyright 2007 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
+
+static struct kprobe k_009_kp1;
+
+static void __exit k_009_exit_probe(void)
+{
+	printk("\nModule exiting ");
+	printk("from gettimeofday\n");
+	unregister_kprobe(&k_009_kp1);
+}
+
+static int k_009_pre_handler(struct kprobe *k_009_kp1, struct pt_regs *p)
+{
+	return 0;
+}
+
+static int k_009_post_handler(struct kprobe *k_009_kp1,
+			      struct pt_regs *p, unsigned long flags)
+{
+	return 0;
+}
+
+static int __init k_009_init_probe(void)
+{
+	printk("\nInserting the kprobe at do_gettimeofday\n");
+
+	/* Registering a kprobe */
+	k_009_kp1.pre_handler = (kprobe_pre_handler_t) k_009_pre_handler;
+	k_009_kp1.post_handler = (kprobe_post_handler_t) k_009_post_handler;
+	k_009_kp1.addr =
+	    (kprobe_opcode_t *) kallsyms_lookup_name("do_gettimeofday");
+
+	if (k_009_kp1.addr == NULL) {
+		printk("kallsyms_lookup_name could not find address "
+		       "for the specified symbol name\n");
+		return 1;
+	}
+
+	printk("\nAddress where the kprobes are \n"
+	       "going to be inserted - %p \n", k_009_kp1.addr);
+	register_kprobe(&k_009_kp1);
+
+	return 0;
+}
+
+module_init(k_009_init_probe);
+module_exit(k_009_exit_probe);
+
+MODULE_DESCRIPTION("Kprobes test module");
+MODULE_LICENSE("GPL");
Index: linux-2.6.16.39/Documentation/kprobe-tests.txt
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/Documentation/kprobe-tests.txt	2007-03-13 20:39:06.254505912 +0530
@@ -0,0 +1,299 @@
+Title	: Kernel Probes test modules
+
+Kprobes is a kernel debugging technique. This can be tested using kernel
+modules. These kernel module will hook the user defined pre handler, post
+handler and fault handler to the probed point.
+
+When configuring the kernel using make menuconfig/xconfig/oldconfig,
+ensure that CONFIG_KPROBES is set to "y".  Under "Instrumentation
+Support", look for "Kprobes".
+
+And also ensure that CONFIG_KPROBESTEST is set to "m", only if
+CONFIG_KPROBES is set to "y"
+
+To load and unload Kprobes-based instrumentation modules, make sure
+"Loadable module support" (CONFIG_MODULES) and "Module unloading"
+(CONFIG_MODULE_UNLOAD) are set to "y".
+
+You may also want to ensure that CONFIG_KALLSYMS and perhaps even
+CONFIG_KALLSYMS_ALL are set to "y", since kallsyms_lookup_name()
+is a handy, version-independent way to find a function's address.
+
+The Kprobes modules are:
+
+- kprobe-tests/k-00x.c ( x = 0,1,2....9 )
+
+
+1. k-001.c
+
+A Kprobe with probe point to the kernel function 'do_fork'.
+This will test the working of KPROBES support.
+
+DESCRIPTION:
+It has a kernel probe 'k_001_kpr' of the type `struct kprobe`.
+
+This module has user defined handlers as follows:
+1. Kprobe's pre-handler    : k_001_before_hook
+2. Kprobe's post-handler   : k_001_after_hook
+
+And the probed adddress is : kallsyms_lookup_name("do_fork").
+
+When this module is inserted using insmod, it registers the k_001_kpr
+using 'register_kprobe(&k_001_kpr)'.
+
+When the adress of a kernel routine 'do_fork' is hit, Kprobes calls
+user defined pre handler 'k_001_before_hook()'. As part of the this
+function call it dumps the stack using dump_stack() and also shows
+the register content at that point using k_001_show_allregs().
+
+After the probed instruction single-stepped, Kprobes calls the post
+handler 'k_001_after_hook()'. This also does the same dump_stack and
+shows the register content at that point using k_001_show_allregs().
+
+While unloading the module using rmmod(), it deregisters the k_001_kpr
+using 'unregister_kprobe()'.
+
+
+2. k-002.c
+
+OBJECTIVE   :
+Multiple Kprobes with the same probe point for the kernel function
+'do_fork'.
+
+DESCRIPTION :
+	It has two kernel probes 'k_002_kp1 and k_002_kp2' of the type
+`struct kprobe`.
+
+This module has user defined handlers as follows:
+1. Kprobe's pre-handler for k_002_kp1	: k_002_before_hook
+2  Kprobe's post-handler for k_002_kp1	: k_002_after_hook
+3. Kprobe's pre-handler for k_002_kp2	: k_002_pre_handler
+4. Kprobe's post-handler for k_002_kp2	: k_002_post_handler
+
+And the probed adddress for k_002_kp1 is : kallsyms_lookup_name("do_fork").
+And the probed adddress for k_002_kp2 is : kallsyms_lookup_name("do_fork").
+
+When this module is inserted using insmod, it registers the k_002_kp1 and
+k_002_kp2 using 'register_kprobe()'.
+
+When the adress of a kernel routine 'do_fork' is hit, Kprobes calls
+user defined pre handlers 'k_002_pre_handler' and 'k_002_before_hook'.
+
+After the probed instruction single-stepped, Kprobes calls the post
+handlers 'k_002_post_handler' and 'k_002_after_hook()'.
+
+While unloading the module using rmmod(), it deregisters the k_002_kp1
+and k_002_kp2 using 'unregister_kprobe()'.
+
+
+3. k-003.c
+
+OBJECTIVE   :
+Multiple kprobes with the different probe point for the kernel function
+'do_fork' and 'sys_gettimeofday'.
+
+DESCRIPTION :
+It has two kernel probes 'k_003_kp1 and k_003_kp2' of the type
+`struct kprobe`.
+
+This module has user defined handlers as follows:
+1. Kprobe's pre-handler for k_003_kp1	: k_003_before_hook
+2  Kprobe's post-handler for k_003_kp1	: k_003_after_hook
+3. Kprobe's pre-handler for k_003_kp2	: k_003_pre_handler
+4. kprobe's post-handler for k_003_kp2	: k_003_post_handler
+
+And the probed adddress for k_003_kp1 is : kallsyms_lookup_name("do_fork").
+And for k_003_kp2 is : kallsyms_lookup_name("sys_gettimeofday").
+
+When this module is inserted using insmod, it registers the k_003_kp1 and
+k_003_kp2 using 'register_kprobe()'.
+
+When the adress of a kernel routine 'do_fork' is hit, Kprobes calls
+user defined pre handlers 'k_003_before_hook'.
+
+When the adress of a kernel routine 'sys_gettimeofday' is hit, Kprobes
+calls user defined pre handlers 'k_003_pre_handler'.
+
+After the probed instruction single-stepped, Kprobes calls the post
+handlers 'k_003_post_handler' and 'k_003_after_hook()' for each probed
+address.
+
+While unloading the module using rmmod(), it deregisters the k_003_kp1
+and k_003_kp2 using 'unregister_kprobe()'.
+
+
+4. k-004.c
+
+Kprobes with the fault handler for the kernel function 'sys_gettimeofday'.
+
+DESCRIPTION:
+It has a kernel probe 'k_004_kpr' of the type `struct kprobe`.
+
+This module has user defined handlers as follows:
+1. Kprobe's pre-handler    : k_004_before_hook
+2. Kprobe's post-handler   : k_004_after_hook
+3. Kprobe's fault-handler  : k_004_fault_probe
+
+And the probed adddress is : kallsyms_lookup_name("sys_gettimeofday").
+
+When this module is inserted using insmod, it registers the k_004_kpr
+using 'register_kprobe(&k_004_kpr)'.
+
+When the adress of a kernel routine 'sys_gettimeofday' is hit, Kprobes
+calls user defined pre handler 'k_004_before_hook()'. As part of the this
+function call it dumps the stack using dump_stack() and also shows the
+register content at that point using k_004_show_allregs().
+And also pre handler k_004_before_hook() tries to genearate a fault by
+doing put_user() for a null buffer.
+
+When this fault is hit, Kprobe calls kprobe's fault handler 'k_004_fault_probe'.
+After the probed instruction single-stepped, Kprobes calls the post handler
+'k_004_after_hook()'. This also does the same dump_stack and shows the
+register content at that point using k_004_show_allregs().
+
+While unloading the module using rmmod(), it deregisters the k_004_kpr using
+'unregister_kprobe()'.
+
+
+5. k-005.c
+
+A Kprobe with probe point to the kernel function sys_read.
+
+DESCRIPTION:
+It has a kernel probe 'k_005_kpr' of the type `struct kprobe`.
+
+This module has user defined handlers as follows:
+1. Kprobe's pre-handler    : k_005_before_hook
+2. Kprobe's post-handler   : k_005_after_hook
+
+And the probed adddress is : kallsyms_lookup_name("sys_read").
+
+When this module is inserted using insmod, it registers the k_005_kpr
+using 'register_kprobe(&k_005_kpr)'.
+
+When the adress of a kernel routine 'sys_read' is hit, Kprobes
+calls user defined pre handler 'k_005_before_hook()'.
+
+After the probed instruction single-stepped, Kprobes calls the post
+handler 'k_005_after_hook()'. This will increases the count variable
+'k_005_kr_kprobe_read_cnt' by one.
+
+While unloading the module using rmmod(), it deregisters the k_005_kpr
+using 'unregister_kprobe()' and also prints the total number of read count.
+
+
+6. k-006.c
+
+A Kprobe with probe point to the kernel function sys_write.
+
+DESCRIPTION:
+It has a kernel probe 'k_006_kpr' of the type `struct kprobe`.
+
+This module has user defined handlers as follows:
+1. Kprobe's pre-handler    : k_006_before_hook
+2. Kprobe's post-handler   : k_006_after_hook
+
+And the probed adddress is : kallsyms_lookup_name("sys_write").
+
+When this module is inserted using insmod, it registers the k_006_kpr
+using 'register_kprobe(&k_006_kpr)'.
+
+When the adress of a kernel routine 'sys_read' is hit, Kprobes calls
+user defined pre handler 'k_006_before_hook()'.
+
+After the probed instruction single-stepped, Kprobes calls the post
+handler 'k_006_after_hook()'. This will increases the count variable
+'k_006_kr_kprobe_write_cnt' by one.
+
+While unloading the module using rmmod(), it deregisters the k_006_kpr
+using 'unregister_kprobe()' and also prints the total number of write
+count.
+
+
+7. k-007.c
+
+Kprobes with probe points to the kernel functions __kmalloc and kfree.
+
+DESCRIPTION :
+It has two kernel probes 'k_007_kp and k_007_kp1' of the type
+`struct kprobe`.
+
+This module has user defined handlers as follows:
+1. Kprobe's pre-handler for k_007_kp	: k_007_kmalloc_hndlr
+2. Kprobe's pre-handler for k_007_kp1	: k_007_kfree_hndlr
+
+And the probed adddress for k_007_kp is : kallsyms_lookup_name("__kmalloc").
+And the probed adddress for k_007_kp1 is: kallsyms_lookup_name("kfree").
+
+When this module is inserted using insmod, it registers the k_007_kp and
+k_007_kp1 using 'register_kprobe()'.
+
+When the adress of a kernel routine '__kmalloc' is hit, Kprobes calls
+user defined pre handlers 'k_007_kmalloc_hndlr'. This will increases
+the count variable 'k_007_kmalloc_count' by one.
+
+When the adress of a kernel routine 'free' is hit, Kprobes calls user
+defined pre handlers 'k_007_kfree_hndlr'. This will increases the
+count variable 'k_007_kfree_count' by one.
+
+After the pre handler excution it does the single-stepping of the
+probed instruction.
+
+While unloading the module using rmmod(), it deregisters the k_003_kp
+and k_003_kp1 using 'unregister_kprobe()' and also prints the total
+number of __kmalloc and kfree counts.
+
+
+8. k-008.c
+
+A Kprobe with a probe point to the kernel function do_gettimeofday,
+with an empty pre-handler which can be used to measure the Kprobes
+overhead.
+
+DESCRIPTION:
+It has a kernel probe 'k_008_kp1' of the type `struct kprobe`.
+
+This module has user defined handlers as follows:
+1. Kprobe's pre-handler    : k_008_pre_handler
+
+And the probed adddress is : kallsyms_lookup_name("do_gettimeofday").
+
+When this module is inserted using insmod, it registers the k_008_kp1
+using 'register_kprobe(&k_008_kp1)'.
+
+When the adress of a kernel routine 'do_gettimeofday' is hit, Kprobes
+calls user defined empty pre handler 'k_008_pre_handler()'.
+
+After the pre handler excution it does the single-stepping of the probed
+instruction.
+
+While unloading the module using rmmod(), it deregisters the k_008_kp1
+using 'unregister_kprobe()'.
+
+
+9. k-009.c
+
+A Kprobe with a probe point to the kernel function do_gettimeofday,
+with the empty pre-handler and post-handler which can be used to
+measure the Kprobes overhead.
+
+DESCRIPTION:
+It has a kernel probe 'k_009_kp1' of the type `struct kprobe`.
+
+This module has user defined handlers as follows:
+1. Kprobe's pre-handler    : k_009_pre_handler
+2. Kprobe's post-handler   : k_009_post_handler
+
+And the probed adddress is : kallsyms_lookup_name("do_gettimeofday").
+
+When this module is inserted using insmod, it registers the k_009_kp1
+using 'register_kprobe(&k_009_kp1)'.
+
+When the adress of a kernel routine 'do_gettimeofday' is hit, Kprobes
+calls user defined empty pre handler 'k_009_pre_handler()'.
+
+After the probed instruction single-stepped, Kprobes calls the empty post
+handler 'k_009_post_handler'.
+
+While unloading the module using rmmod(), it deregisters the k_009_kp1
+using 'unregister_kprobe()'.
Index: linux-2.6.16.39/kprobe-tests/kprobes-test.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16.39/kprobe-tests/kprobes-test.h	2007-03-13 20:39:06.255505760 +0530
@@ -0,0 +1,101 @@
+#ifndef _KPROBES_TEST_H
+#define _KPROBES_TEST_H
+/*
+ *  kprobes-test.h - Architecture specific kprobes test functions.
+ *
+ *  Copyright 2007 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifdef CONFIG_PPC32
+#include<linux/utsname.h>
+#include <asm/uaccess.h>
+
+#define REG		"%08lX"
+#define REGS_PER_LINE	8
+#define LAST_VOLATILE	12
+
+static struct regbit {
+	unsigned long bit;
+	const char *name;
+} msr_bits[] = {
+	{MSR_WE,	"WE"},
+	{MSR_CE,	"CE"},
+	{MSR_EE,	"EE"},
+	{MSR_PR,	"PR"},
+	{MSR_ME,	"ME"},
+	{MSR_DWE,	"DWE"},
+	{MSR_DE,	"DE"},
+	{MSR_IS,	"IS"},
+	{MSR_DS,	"DS"},
+	{0,		NULL}
+};
+
+static void printbits(unsigned long val, struct regbit *bits)
+{
+	const char *sep = "";
+
+	printk("<");
+	for (; bits->bit; ++bits)
+		if (val & bits->bit) {
+			printk("%s%s", sep, bits->name);
+			sep = ",";
+		}
+	printk(">");
+}
+void show_allregs(struct pt_regs * regs)
+{
+	int i, trap;
+
+	printk("NIP: "REG" LR: "REG" CTR: "REG"\n",
+	       regs->nip, regs->link, regs->ctr);
+	printk("REGS: %p TRAP: %04lx   (%s)\n",
+	       regs, regs->trap, system_utsname.release);
+	printk("MSR: "REG" ", regs->msr);
+	printbits(regs->msr, msr_bits);
+	printk("  CR: %08lX  XER: %08lX\n", regs->ccr, regs->xer);
+	trap = TRAP(regs);
+	if (trap == 0x300 || trap == 0x600)
+		printk("DAR: "REG", DSISR: "REG"\n", regs->dar, regs->dsisr);
+	printk("TASK = %p[%d] '%s' THREAD: %p",
+	       current, current->pid, current->comm, task_thread_info(current));
+
+#ifdef CONFIG_SMP
+	printk(" CPU: %d", smp_processor_id());
+#endif /* CONFIG_SMP */
+
+	for (i = 0;  i < 32;  i++) {
+		if ((i % REGS_PER_LINE) == 0)
+			printk("\n" KERN_INFO "GPR%02d: ", i);
+		printk(REG " ", regs->gpr[i]);
+		if (i == LAST_VOLATILE && !FULL_REGS(regs))
+			break;
+	}
+	printk("\n");
+#ifdef CONFIG_KALLSYMS
+	/*
+	 * Lookup NIP late so we have the best change of getting the
+	 * above info out without failing
+	 */
+	printk("NIP ["REG"] ", regs->nip);
+	print_symbol("%s\n", regs->nip);
+	printk("LR ["REG"] ", regs->link);
+	print_symbol("%s\n", regs->link);
+#endif
+}
+#endif
+
+
+#endif
Index: linux-2.6.16.39/arch/ppc/Kconfig
===================================================================
--- linux-2.6.16.39.orig/arch/ppc/Kconfig	2007-03-13 20:39:04.533767504 +0530
+++ linux-2.6.16.39/arch/ppc/Kconfig	2007-03-13 20:39:06.257505456 +0530
@@ -1410,4 +1410,5 @@
 	  for kernel debugging, non-intrusive instrumentation and testing.
 	  If in doubt, say "N".
 
+source "kprobe-tests/Kconfig"
 endmenu

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2007-03-15 16:49 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-03-15 15:41 Kprobes for PPC32[Booke] rsmadhvesh

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).