linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [RFC][PATCH]Kprobes for PPC32(BOOKE)
@ 2007-04-20  7:24 rsmadhvesh
  2007-04-20 19:33 ` Kumar Gala
  0 siblings, 1 reply; 3+ messages in thread
From: rsmadhvesh @ 2007-04-20  7:24 UTC (permalink / raw)
  To: galak; +Cc: linuxppc-dev, madhvesh.s

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

Hi Kumar,

This is regarding the kprobes patches for
PPC32 BOOKE version. The attached patches
contain the implementation for this version.

I saw your earlier postings and commits to 2.6.21
regarding kprobes for PPC32. Since the single 
step mechanism in BookE is quite different, I
thought i can share some of the issues faced 
in this implementation and get your review 
feedback for those patches.

Last month, i had posted the patches for 
PPC32(BookE) version in the below thread.

http://ozlabs.org/pipermail/linuxppc-dev/2007-March/033058.html

Kernel Version:- 2.6.16.39
Target: Ebony (ppc440_gp processor)

I had mentioned some issues regarding the preempt count
in the above thread with some issues. In today released patches,
these issues are fixed with some additional patches to 
head_booke.h and traps.c. With these changes, there are no 
issues noticed and kprobes behavior is same as other 
architetcures. 

Regarding the below issue mentioned in my earlier mail...
> 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!!
> 

The core issue was the way debug exception was getting handled
in PPC32 BookE versions. The debug exception gets executed
using exception stack which doesnot contain the original stack
preempt count status. This exact sequence can be explained 
as below

After executing pre handler, the DEBUG_EXCEPTION gets called 
because of setting DE bit in MSR and IC, IDM bits of DBCR0. 
As part of  DEBUG_EXCEPTION in head_booke.h, the exception 
stack is prepared by storing current registers and original sp. But the 
current preempt count value is not set in exception stack. Because of 
this, preempt_count=ZERO. This will enable preemption and at any point,
it can be rescheduled because of higher priority interrupts. Also as part
of post_kprobe_handler(), preempt_enable_no_resched() gets called,
which will try to decrement the preempt_count value by 1. But since
exception stack contains the preempt_count as ZERO, this operation
will make its value as NEGATIVE and that results in OOPS. Execution  
stops after this point and system reboots

Two solutions are incorporated to solve this fix
1. The head_booke.h is modified before setting the exception stack. This
patch takes care of copying the original stack preempt_count value to 
exception stack before Stack Pointer gets changed 
2. Also as part of traps.c within DebugException(), the original stack 
thread_info contents are copied to exception stack since other contents 
of current thread_info is also required.

With the above 2 fixes, the system is stable and the kprobes behavior 
is same as other architectures.

I am porting these patches to 2.6.21-rc7 and will resubmit these 
patches after testing.

Originally i thought of combining the 2nd patch contents as part of 1st 
patch in the form of assembly, but i could not do it because of my 
limited PPC assembly knowledge. 
If you have any comments regarding the above patches or better 
solution, please let me know and i shall try it in 2.6.21.rc7..

Regards
Madhvesh




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

kprobes-ppc-1.patch:

This patch is to add Kprobes support for BOOKE version of PPC32

Signed-off-by: Madhvesh Sulibhavi <madhvesh.s@ap.sony.com>
Signed-off-by: Lubna Badkar <lubna@ap.sony.com>

Index: linux-2.6.16.39/arch/powerpc/lib/Makefile
===================================================================
--- linux-2.6.16.39.orig/arch/powerpc/lib/Makefile	2007-04-11 11:28:47.000000000 +0530
+++ linux-2.6.16.39/arch/powerpc/lib/Makefile	2007-04-11 11:28:50.386269112 +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-04-11 11:28:47.000000000 +0530
+++ linux-2.6.16.39/arch/ppc/Kconfig	2007-04-11 11:33:10.666700472 +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-04-11 11:28:47.000000000 +0530
+++ linux-2.6.16.39/arch/ppc/kernel/Makefile	2007-04-11 11:28:50.389268656 +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-04-11 11:41:53.335242776 +0530
@@ -0,0 +1,371 @@
+/*
+ *  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)
+{
+	regs->msr &= ~(MSR_EE); /* Turn off 'Externel Interrupt' bits */
+	regs->msr &= ~(MSR_CE); /* Turn off 'Critical Interrupt' bits */
+	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;
+	regs->msr |= (MSR_EE); /* Turn on 'External Interrupt' bits */
+	regs->msr |= (MSR_CE); /* Turn on 'Critical Interrupt' bits */
+	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;
+
+	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();
+	}
+
+	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:
+		if (kprobe_handler(args->regs))
+			ret = NOTIFY_STOP;
+		break;
+	case DIE_SSTEP:
+		if (post_kprobe_handler(args->regs))
+			ret = NOTIFY_STOP;
+		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("\nIABR Match 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-04-11 11:28:47.000000000 +0530
+++ linux-2.6.16.39/arch/ppc/kernel/misc.S	2007-04-11 11:28:50.392268200 +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-04-11 11:28:47.000000000 +0530
+++ linux-2.6.16.39/arch/ppc/kernel/traps.c	2007-04-11 11:42:42.129824872 +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;
@@ -791,8 +820,43 @@
 
 void DebugException(struct pt_regs *regs, unsigned long debug_status)
 {
+	struct thread_info *thread_info, *exception_thread_info;
+
 	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);
+		/*
+		 * On Book E and perhaps other processsors, singlestep is
+		 * handled on the critical exception stack.  This causes
+		 * current_thread_info() to fail, since it locates the
+		 * thread_info by masking off the low bits of the current
+		 * stack pointer.  We work around this issue by copying
+		 * the thread_info from the kernel stack before calling
+		 * kprobe_post_handler, and copying it back afterwards.
+		 * On most processors the copy is avoided since
+		 * exception_thread_info == thread_info.
+		 */
+		thread_info = (struct thread_info *)
+		    (regs->gpr[1] & ~(THREAD_SIZE - 1));
+		exception_thread_info = current_thread_info();
+
+		if (thread_info != exception_thread_info)
+			memcpy(exception_thread_info, thread_info,
+			       sizeof *thread_info);
+
+		if (notify_die(DIE_SSTEP, "single_step", regs, 5,
+			       5, SIGTRAP) == NOTIFY_STOP) {
+			if (thread_info != exception_thread_info)
+				memcpy(thread_info, exception_thread_info,
+				       sizeof *thread_info);
+			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-04-11 11:28:47.000000000 +0530
+++ linux-2.6.16.39/arch/ppc/kernel/vmlinux.lds.S	2007-04-11 11:28:50.395267744 +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-04-11 11:28:47.000000000 +0530
+++ linux-2.6.16.39/arch/ppc/mm/fault.c	2007-04-11 11:38:35.298348960 +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-04-11 11:28:47.000000000 +0530
+++ linux-2.6.16.39/include/asm-powerpc/sstep.h	2007-04-11 11:28:50.397267440 +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-04-11 11:28:50.398267288 +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-04-11 11:28:50.399267136 +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 */
Index: linux-2.6.16.39/arch/ppc/kernel/head_booke.h
===================================================================
--- linux-2.6.16.39.orig/arch/ppc/kernel/head_booke.h	2007-04-11 11:28:47.000000000 +0530
+++ linux-2.6.16.39/arch/ppc/kernel/head_booke.h	2007-04-11 11:34:34.031027168 +0530
@@ -85,6 +85,35 @@
 #endif
 
 /*
+ * The below macro is specific to kprobes support which addresses copying
+ * preempt count value from current stack to exception stack. This is
+ * required because kprobes has to be processed by disabling preemption.
+ * Even though it is disabled in kprobe_handler, since exception stack
+ * gets used for debug exception, this copy is taken care explicitly.
+ * Other fields of thread information is copied as part of DebugException
+ * before jumping to kprobe post handler.
+ */
+#ifdef CONFIG_KPROBES
+#define COPY_PREEMPT_STATUS						     \
+	SAVE_4GPRS(3, r11);						     \
+	SAVE_2GPRS(7, r11);						     \
+	rlwinm  r6,r1,0,0,18;						     \
+	lwz     r6,TI_PREEMPT(r6);					     \
+	rlwinm  r7,r11,0,0,18;						     \
+	stw     r6,TI_PREEMPT(r7);					     \
+	mr      r1,r11;							     \
+	rlwinm	r9,r9,0,14,12;		/* clear MSR_WE (necessary?)	   */\
+	stw     r0,GPR0(r11)
+#else
+#define COPY_PREEMPT_STATUS						     \
+	mr      r1,r11;							     \
+	rlwinm	r9,r9,0,14,12;		/* clear MSR_WE (necessary?)	   */\
+	stw     r0,GPR0(r11);						     \
+	SAVE_4GPRS(3, r11);						     \
+	SAVE_2GPRS(7, r11)
+#endif
+
+/*
  * Exception prolog for critical/machine check exceptions.  This is a
  * little different from the normal exception prolog above since a
  * critical/machine check exception can potentially occur at any point
@@ -121,11 +150,7 @@
 	stw	r1,GPR1(r11);						     \
 	mfspr	r9,exc_level_srr1;					     \
 	stw	r1,0(r11);						     \
-	mr	r1,r11;							     \
-	rlwinm	r9,r9,0,14,12;		/* clear MSR_WE (necessary?)	   */\
-	stw	r0,GPR0(r11);						     \
-	SAVE_4GPRS(3, r11);						     \
-	SAVE_2GPRS(7, r11)
+	COPY_PREEMPT_STATUS
 
 #define CRITICAL_EXCEPTION_PROLOG \
 		EXC_LEVEL_EXCEPTION_PROLOG(CRIT, SPRN_CSRR0, SPRN_CSRR1)

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

kprobes-kernel-test-module.patch :

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.

Signed-off-by: Madhvesh Sulibhavi <madhvesh.s@ap.sony.com>
Signed-off-by: Lubna Badkar <lubna@ap.sony.com>

Index: linux-2.6.16.39/Makefile
===================================================================
--- linux-2.6.16.39.orig/Makefile	2007-03-12 18:26:59.470356760 +0530
+++ linux-2.6.16.39/Makefile	2007-03-12 18:29:57.976219744 +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-12 18:29:57.976219744 +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-12 18:29:57.977219592 +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-12 18:31:52.266844928 +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-12 18:31:59.940678328 +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-12 18:32:09.980152096 +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-12 18:32:17.532004040 +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-12 18:32:26.889581472 +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-12 18:32:34.632404384 +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-12 18:32:41.485362576 +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-12 18:32:48.248334448 +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-12 18:32:55.554223784 +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-12 18:29:57.986218224 +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-12 18:30:54.164677800 +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-12 18:26:59.476355848 +0530
+++ linux-2.6.16.39/arch/ppc/Kconfig	2007-03-12 18:29:57.989217768 +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] 3+ messages in thread

* Re: [RFC][PATCH]Kprobes for PPC32(BOOKE)
  2007-04-20  7:24 [RFC][PATCH]Kprobes for PPC32(BOOKE) rsmadhvesh
@ 2007-04-20 19:33 ` Kumar Gala
  2007-04-23 14:36   ` rsmadhvesh
  0 siblings, 1 reply; 3+ messages in thread
From: Kumar Gala @ 2007-04-20 19:33 UTC (permalink / raw)
  To: rsmadhvesh; +Cc: linuxppc-dev, madhvesh.s


On Apr 20, 2007, at 2:24 AM, rsmadhvesh@vsnl.net wrote:

> Hi Kumar,
>
> This is regarding the kprobes patches for
> PPC32 BOOKE version. The attached patches
> contain the implementation for this version.
>
> I saw your earlier postings and commits to 2.6.21
> regarding kprobes for PPC32. Since the single
> step mechanism in BookE is quite different, I
> thought i can share some of the issues faced
> in this implementation and get your review
> feedback for those patches.

I'd love to review these patches.  Is there any possibility that I  
could get you to build them for arch/powerpc on top of David Gibson's  
port of ebony to arch/powerpc.

http://ozlabs.org/pipermail/linuxppc-dev/2007-April/034483.html

I dont see much value in adding kprobes into arch/ppc and have been  
trying to push any 'new' functionality get added to arch/powerpc and  
only bug fixes to arch/ppc.

- k

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [RFC][PATCH]Kprobes for PPC32(BOOKE)
  2007-04-20 19:33 ` Kumar Gala
@ 2007-04-23 14:36   ` rsmadhvesh
  0 siblings, 0 replies; 3+ messages in thread
From: rsmadhvesh @ 2007-04-23 14:36 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev, madhvesh.s

Hi Kumar,

Kumar Gala <galak@kernel.crashing.org> wrote on Saturday, April 21, 2007 1:04 am
> 
> On Apr 20, 2007, at 2:24 AM, rsmadhvesh@vsnl.net wrote:
> 
> > Hi Kumar,
> >
> > This is regarding the kprobes patches for
> > PPC32 BOOKE version. The attached patches
> > contain the implementation for this version.
> >
> > I saw your earlier postings and commits to 2.6.21
> > regarding kprobes for PPC32. Since the single
> > step mechanism in BookE is quite different, I
> > thought i can share some of the issues faced
> > in this implementation and get your review
> > feedback for those patches.
> 
> I'd love to review these patches.  Is there any possibility that I  
> could get you to build them for arch/powerpc on top of David 
> Gibson's  
> port of ebony to arch/powerpc.
> 
> http://ozlabs.org/pipermail/linuxppc-dev/2007-April/034483.html
> 
> I dont see much value in adding kprobes into arch/ppc and have been 
> 
> trying to push any 'new' functionality get added to arch/powerpc 
> and  
> only bug fixes to arch/ppc.
Thanks for taking interest in reviewing my patches.
I understand the recent discussions in merging ppc to
powerpc and now i can as well start merging my patches
to powerpc.  I will repost my patches after this, but if you find
any bugs in my code, please let me know.

-Madhvesh

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2007-04-23 14:40 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-04-20  7:24 [RFC][PATCH]Kprobes for PPC32(BOOKE) rsmadhvesh
2007-04-20 19:33 ` Kumar Gala
2007-04-23 14:36   ` 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).