diff -Naru linux-2.6.7/arch/i386/Kconfig linux-hooks-base/arch/i386/Kconfig
--- linux-2.6.7/arch/i386/Kconfig	2004-06-17 10:00:40.808632264 +0900
+++ linux-hooks-base/arch/i386/Kconfig	2004-06-17 10:01:25.260874496 +0900
@@ -1307,6 +1307,20 @@
 	depends on X86_LOCAL_APIC && !X86_VISWS
 	default y
 
+config HOOK
+	tristate "Kernel Hook support"
+	depends on DEBUG_KERNEL 
+	help
+	 The Kernel Hooks Interface is a generalised facility for placing hooks in
+	 arbitrary kernel locations. A hook is a location in the kernel that
+	 calls out of the kernel to a kernel module routine - a hook exit routine.
+	 Read Documentation/hook/HOWTO for more details.
+
+config ASM_HOOK
+	bool
+	default y
+	depends on DEBUG_KERNEL && HOOK
+
 endmenu
 
 source "security/Kconfig"
diff -Naru linux-2.6.7/arch/sparc64/Kconfig linux-hooks-base/arch/sparc64/Kconfig
--- linux-2.6.7/arch/sparc64/Kconfig	2004-06-17 10:00:44.139125952 +0900
+++ linux-hooks-base/arch/sparc64/Kconfig	2004-06-17 10:01:25.293869480 +0900
@@ -705,6 +705,20 @@
 	depends on MCOUNT
 	default y
 
+config HOOK
+	tristate "Kernel Hook support"
+	depends on DEBUG_KERNEL 
+	help
+	 The Kernel Hooks Interface is a generalised facility for placing hooks in
+	 arbitrary kernel locations. A hook is a location in the kernel that
+	 calls out of the kernel to a kernel module routine - a hook exit routine.
+	 Read Documentation/hook/HOWTO for more details.
+
+config ASM_HOOK
+	bool
+	default y
+	depends on DEBUG_KERNEL && HOOK
+	
 endmenu
 
 source "security/Kconfig"
diff -Naru linux-2.6.7/arch/sparc/Kconfig linux-hooks-base/arch/sparc/Kconfig
--- linux-2.6.7/arch/sparc/Kconfig	2004-04-16 19:06:12.000000000 +0900
+++ linux-hooks-base/arch/sparc/Kconfig	2004-06-17 10:01:25.293869480 +0900
@@ -448,6 +448,19 @@
 	  of the BUG call as well as the EIP and oops trace.  This aids
 	  debugging but costs about 70-100K of memory.
 
+config HOOK
+	tristate "Kernel Hook support"
+	help
+	 The Kernel Hooks Interface is a generalised facility for placing hooks in
+	 arbitrary kernel locations. A hook is a location in the kernel that
+	 calls out of the kernel to a kernel module routine - a hook exit routine.
+	 Read Documentation/hook/HOWTO for more details.
+
+config ASM_HOOK
+	bool
+	default y
+	depends on HOOK
+	
 endmenu
 
 source "security/Kconfig"
diff -Naru linux-2.6.7/arch/ppc/Kconfig linux-hooks-base/arch/ppc/Kconfig
--- linux-2.6.7/arch/ppc/Kconfig	2004-06-17 10:00:43.017296496 +0900
+++ linux-hooks-base/arch/ppc/Kconfig	2004-06-17 10:01:25.264873888 +0900
@@ -1276,6 +1276,20 @@
 	depends on IBM_OCP
 	default y
 
+config HOOK
+	tristate "Kernel Hook support"
+	depends on DEBUG_KERNEL 
+	help
+	 The Kernel Hooks Interface is a generalised facility for placing hooks in
+	 arbitrary kernel locations. A hook is a location in the kernel that
+	 calls out of the kernel to a kernel module routine - a hook exit routine.
+	 Read Documentation/hook/HOWTO for more details.
+
+config ASM_HOOK
+	bool
+	default y
+	depends on DEBUG_KERNEL && HOOK
+
 endmenu
 
 source "security/Kconfig"
diff -Naru linux-2.6.7/arch/mips/Kconfig linux-hooks-base/arch/mips/Kconfig
--- linux-2.6.7/arch/mips/Kconfig	2004-06-17 10:00:42.394391192 +0900
+++ linux-hooks-base/arch/mips/Kconfig	2004-06-17 10:01:25.263874040 +0900
@@ -1644,6 +1644,20 @@
 	bool "Highmem debugging"
 	depends on DEBUG_KERNEL && HIGHMEM
 
+config HOOK
+	tristate "Kernel Hook support"
+	depends on DEBUG_KERNEL 
+	help
+	 The Kernel Hooks Interface is a generalised facility for placing hooks in
+	 arbitrary kernel locations. A hook is a location in the kernel that
+	 calls out of the kernel to a kernel module routine - a hook exit routine.
+	 Read Documentation/hook/HOWTO for more details.
+
+config ASM_HOOK
+	bool
+	default y
+	depends on DEBUG_KERNEL && HOOK
+	
 endmenu
 
 source "security/Kconfig"
diff -Naru linux-2.6.7/arch/cris/Kconfig linux-hooks-base/arch/cris/Kconfig
--- linux-2.6.7/arch/cris/Kconfig	2004-06-17 10:00:40.390695800 +0900
+++ linux-hooks-base/arch/cris/Kconfig	2004-06-17 10:01:25.259874648 +0900
@@ -208,6 +208,19 @@
           If you don't debug the kernel, you can say N, but we may not be able
           to solve problems without frame pointers.
 
+config HOOK
+	tristate "Kernel Hook support"
+	help
+	 The Kernel Hooks Interface is a generalised facility for placing hooks in
+	 arbitrary kernel locations. A hook is a location in the kernel that
+	 calls out of the kernel to a kernel module routine - a hook exit routine.
+	 Read Documentation/hook/HOWTO for more details.
+
+config ASM_HOOK
+	bool
+	default y
+	depends on HOOK
+	
 endmenu
 
 source "security/Kconfig"
diff -Naru linux-2.6.7/arch/sh/Kconfig linux-hooks-base/arch/sh/Kconfig
--- linux-2.6.7/arch/sh/Kconfig	2004-04-16 19:06:12.000000000 +0900
+++ linux-hooks-base/arch/sh/Kconfig	2004-06-17 10:01:25.283871000 +0900
@@ -790,6 +790,19 @@
 	  If you don't debug the kernel, you can say N, but we may not be able
 	  to solve problems without frame pointers.
 
+config HOOK
+	tristate "Kernel Hook support"
+	help
+	 The Kernel Hooks Interface is a generalised facility for placing hooks in
+	 arbitrary kernel locations. A hook is a location in the kernel that
+	 calls out of the kernel to a kernel module routine - a hook exit routine.
+	 Read Documentation/hook/HOWTO for more details.
+
+config ASM_HOOK
+	bool
+	default y
+	depends on HOOK
+	
 endmenu
 
 source "security/Kconfig"
diff -Naru linux-2.6.7/arch/m68k/Kconfig linux-hooks-base/arch/m68k/Kconfig
--- linux-2.6.7/arch/m68k/Kconfig	2004-06-17 10:00:41.839475552 +0900
+++ linux-hooks-base/arch/m68k/Kconfig	2004-06-17 10:02:16.937018528 +0900
@@ -688,6 +688,20 @@
 	  Say Y here only if you plan to use gdb to debug the kernel.
 	  If you don't debug the kernel, you can say N.
 
+config HOOK
+	tristate "Kernel Hook support"
+	depends on DEBUG_KERNEL 
+	help
+	 The Kernel Hooks Interface is a generalised facility for placing hooks in
+	 arbitrary kernel locations. A hook is a location in the kernel that
+	 calls out of the kernel to a kernel module routine - a hook exit routine.
+	 Read Documentation/hook/HOWTO for more details.
+
+config ASM_HOOK
+	bool
+	default y
+	depends on DEBUG_KERNEL && HOOK
+
 endmenu
 
 source "security/Kconfig"
diff -Naru linux-2.6.7/arch/ia64/Kconfig linux-hooks-base/arch/ia64/Kconfig
--- linux-2.6.7/arch/ia64/Kconfig	2004-06-17 10:00:41.342551096 +0900
+++ linux-hooks-base/arch/ia64/Kconfig	2004-06-17 10:01:25.260874496 +0900
@@ -498,6 +498,21 @@
 	bool
 	depends on COMPAT && SYSVIPC
 	default y
+
+config HOOK
+	tristate "Kernel Hook support"
+	depends on DEBUG_KERNEL 
+	help
+	 The Kernel Hooks Interface is a generalised facility for placing hooks in
+	 arbitrary kernel locations. A hook is a location in the kernel that
+	 calls out of the kernel to a kernel module routine - a hook exit routine.
+	 Read Documentation/hook/HOWTO for more details.
+
+config ASM_HOOK
+	bool
+	default y
+	depends on DEBUG_KERNEL && HOOK
+	
 endmenu
 
 source "security/Kconfig"
diff -Naru linux-2.6.7/arch/alpha/Kconfig linux-hooks-base/arch/alpha/Kconfig
--- linux-2.6.7/arch/alpha/Kconfig	2004-06-17 10:00:39.558822264 +0900
+++ linux-hooks-base/arch/alpha/Kconfig	2004-06-17 10:01:25.257874952 +0900
@@ -690,6 +690,20 @@
 	  Say Y here only if you plan to use gdb to debug the kernel.
 	  If you don't debug the kernel, you can say N.
 
+config HOOK
+	tristate "Kernel Hook support"
+	depends on DEBUG_KERNEL 
+	help
+	 The Kernel Hooks Interface is a generalised facility for placing hooks in
+	 arbitrary kernel locations. A hook is a location in the kernel that
+	 calls out of the kernel to a kernel module routine - a hook exit routine.
+	 Read Documentation/hook/HOWTO for more details.
+
+config ASM_HOOK
+	bool
+	default y
+	depends on DEBUG_KERNEL && HOOK
+	
 endmenu
 
 source "security/Kconfig"
diff -Naru linux-2.6.7/arch/ppc64/Kconfig linux-hooks-base/arch/ppc64/Kconfig
--- linux-2.6.7/arch/ppc64/Kconfig	2004-06-17 10:00:43.421235088 +0900
+++ linux-hooks-base/arch/ppc64/Kconfig	2004-06-17 10:03:25.701564728 +0900
@@ -424,7 +424,20 @@
 	  If you say Y here the kernel will use separate kernel stacks
 	  for handling hard and soft interrupts.  This can help avoid
 	  overflowing the process kernel stacks.
-	  
+
+config HOOK
+	tristate "Kernel Hook support"
+	depends on DEBUG_KERNEL 
+	help
+	 The Kernel Hooks Interface is a generalised facility for placing hooks in
+	 arbitrary kernel locations. A hook is a location in the kernel that
+	 calls out of the kernel to a kernel module routine - a hook exit routine.
+	 Read Documentation/hook/HOWTO for more details.
+
+config ASM_HOOK
+	bool
+	default y
+	depends on DEBUG_KERNEL && HOOK
 endmenu
 
 config SPINLINE
diff -Naru linux-2.6.7/arch/arm/Kconfig linux-hooks-base/arch/arm/Kconfig
--- linux-2.6.7/arch/arm/Kconfig	2004-06-17 10:00:39.724797032 +0900
+++ linux-hooks-base/arch/arm/Kconfig	2004-06-17 10:01:25.258874800 +0900
@@ -806,6 +806,20 @@
 	  should be between zero and two. The port must have been
 	  initalised by the boot-loader before use.
 
+config HOOK
+	tristate "Kernel Hook support"
+	depends on DEBUG_KERNEL 
+	help
+	 The Kernel Hooks Interface is a generalised facility for placing hooks in
+	 arbitrary kernel locations. A hook is a location in the kernel that
+	 calls out of the kernel to a kernel module routine - a hook exit routine.
+	 Read Documentation/hook/HOWTO for more details.
+
+config ASM_HOOK
+	bool
+	default y
+	depends on DEBUG_KERNEL && HOOK
+	
 endmenu
 
 source "security/Kconfig"
diff -Naru linux-2.6.7/arch/parisc/Kconfig linux-hooks-base/arch/parisc/Kconfig
--- linux-2.6.7/arch/parisc/Kconfig	2004-06-17 10:00:42.795330240 +0900
+++ linux-hooks-base/arch/parisc/Kconfig	2004-06-17 10:01:25.263874040 +0900
@@ -221,6 +221,20 @@
 	  Say Y here only if you plan to use gdb to debug the kernel.
 	  If you don't debug the kernel, you can say N.
 	  
+config HOOK
+	tristate "Kernel Hook support"
+	depends on DEBUG_KERNEL 
+	help
+	 The Kernel Hooks Interface is a generalised facility for placing hooks in
+	 arbitrary kernel locations. A hook is a location in the kernel that
+	 calls out of the kernel to a kernel module routine - a hook exit routine.
+	 Read Documentation/hook/HOWTO for more details.
+
+config ASM_HOOK
+	bool
+	default y
+	depends on DEBUG_KERNEL && HOOK
+	
 endmenu
 
 source "security/Kconfig"
diff -Naru linux-2.6.7/arch/x86_64/Kconfig linux-hooks-base/arch/x86_64/Kconfig
--- linux-2.6.7/arch/x86_64/Kconfig	2004-06-17 10:00:44.350093880 +0900
+++ linux-hooks-base/arch/x86_64/Kconfig	2004-06-17 10:01:25.294869328 +0900
@@ -497,6 +497,20 @@
 #config X86_REMOTE_DEBUG
 #       bool "kgdb debugging stub"
 
+config HOOK
+	tristate "Kernel Hook support"
+	depends on DEBUG_KERNEL 
+	help
+	 The Kernel Hooks Interface is a generalised facility for placing hooks in
+	 arbitrary kernel locations. A hook is a location in the kernel that
+	 calls out of the kernel to a kernel module routine - a hook exit routine.
+	 Read Documentation/hook/HOWTO for more details.
+
+config ASM_HOOK
+	bool
+	default y
+	depends on DEBUG_KERNEL && HOOK
+	
 endmenu
 
 source "security/Kconfig"
diff -Naru linux-2.6.7/arch/s390/Kconfig linux-hooks-base/arch/s390/Kconfig
--- linux-2.6.7/arch/s390/Kconfig	2004-05-27 15:31:43.000000000 +0900
+++ linux-hooks-base/arch/s390/Kconfig	2004-06-17 10:01:25.273872520 +0900
@@ -423,6 +423,20 @@
 	  If you say Y here, various routines which may sleep will become very
 	  noisy if they are called with a spinlock held.	
 
+config HOOK
+	tristate "Kernel Hook support"
+	depends on DEBUG_KERNEL 
+	help
+	 The Kernel Hooks Interface is a generalised facility for placing hooks in
+	 arbitrary kernel locations. A hook is a location in the kernel that
+	 calls out of the kernel to a kernel module routine - a hook exit routine.
+	 Read Documentation/hook/HOWTO for more details.
+
+config ASM_HOOK
+	bool
+	default y
+	depends on DEBUG_KERNEL && HOOK
+	
 endmenu
 
 source "security/Kconfig"
diff -Naru linux-2.6.7/include/linux/hook.h linux-hooks-base/include/linux/hook.h
--- linux-2.6.7/include/linux/hook.h	1970-01-01 09:00:00.000000000 +0900
+++ linux-hooks-base/include/linux/hook.h	2004-06-17 10:01:25.298868720 +0900
@@ -0,0 +1,205 @@
+#ifndef __LINUX_HOOK_H
+#define __LINUX_HOOK_H
+/*
+ * Kernel Hooks Interface.
+ * 
+ * Authors: Richard J Moore <richardj_moore@uk.ibm.com>
+ *	    Vamsi Krishna S. <vamsi_krishna@in.ibm.com>
+ */
+#include <linux/compiler.h>
+#include <linux/module.h>
+#include <linux/list.h>
+
+/* define the user (kernel module) hook structure */
+struct hook_rec;
+struct hook;
+
+struct hook_rec {
+	void *hook_exit;
+	struct list_head exit_list;
+	unsigned int hook_flags;
+	struct hook *hook_head;
+};
+
+struct hook {
+	struct list_head exit_list;
+	unsigned int hook_flags;
+	void *hook_addr;
+	void *hook_ex_exit;
+};
+
+/* hook flags */
+#define HOOK_ARMED		0x00000001
+#define HOOK_REGISTERED		0x00000002
+#define HOOK_EXCLUSIVE		0x0000000c
+
+/*
+ * Use the DECLARE_HOOK macro to define the hook structure in global 
+ * memory of a kernel module that is implementing a hook.
+ */
+#if defined(CONFIG_HOOK) || defined(CONFIG_HOOK_MODULE)
+
+#define HOOK_SYM(h) _HOOK_SYM(h)
+#define _HOOK_SYM(h) h##_hook
+
+#define DECLARE_HOOK(name) _DECLARE_HOOK(name, HOOK_SYM(name))
+#define _DECLARE_HOOK(name, hk) \
+extern void hk; \
+struct hook name = { \
+	.hook_addr 	= &(hk), 			  \
+	.exit_list	= LIST_HEAD_INIT(name.exit_list), \
+}; \
+EXPORT_SYMBOL(name);
+
+#define DECLARE_EXCLUSIVE_HOOK(name) _DECLARE_EXCLUSIVE_HOOK(name, HOOK_SYM(name))
+#define _DECLARE_EXCLUSIVE_HOOK(name, hk) \
+extern void hk; \
+struct hook name = { \
+	.hook_addr 	= &(hk), 			  \
+	.exit_list	= LIST_HEAD_INIT(name.exit_list), \
+	.hook_flags	= HOOK_EXCLUSIVE,		  \
+}; \
+EXPORT_SYMBOL(name);
+
+/*
+ * Generic hooks are the same in all architectures and may be used to
+ * place hooks even in inline functions. They don't define a symbol at hook
+ * location.
+ */ 
+#define DECLARE_GENERIC_HOOK(name) _DECLARE_GENERIC_HOOK(name)
+#define _DECLARE_GENERIC_HOOK(name) \
+struct hook name; \
+EXPORT_SYMBOL(name);
+
+#define USE_HOOK(name) _USE_HOOK(name)
+#define _USE_HOOK(name) extern struct hook name
+
+/* define head record only flags */
+#define HOOK_ACTIVE	0x80000000
+#define HOOK_ASM_HOOK	0x40000000
+#define HOOK_EXCLUSIVE	0x20000000
+
+typedef int (*hook_fn_t)(struct hook *, ...);
+
+#ifdef CONFIG_ASM_HOOK
+#include <asm/hook.h>
+#else
+static inline int is_asm_hook(unsigned char *addr) {return 0;}
+static inline void activate_asm_hook(struct hook *hook) { }
+static inline void deactivate_asm_hook(struct hook *hook) { }
+#endif
+
+#ifndef IF_HOOK_ENABLED
+#define IF_HOOK_ENABLED(h, hk) _IF_HOOK_ENABLED(h, #hk)
+#define _IF_HOOK_ENABLED(h, hk) \
+	__asm__ __volatile__ (".global "hk"; "hk":"); \
+	if (unlikely(h.hook_flags & HOOK_ACTIVE))
+#endif
+
+#define HOOK_TEST(h) \
+	extern struct hook h; \
+	IF_HOOK_ENABLED(h, h##_hook)
+
+#define CALL_EXIT(fn, parm, args...) (((hook_fn_t)(fn))(parm , ##args))
+
+#define DISPATCH_NORMAL(fn, parm, dsprc, args...) \
+	dsprc = CALL_EXIT(fn, parm , ##args);
+
+#define DISPATCH_RET(fn, parm, dsprc, args...) { \
+	int rc; \
+	dsprc = CALL_EXIT(fn, parm, &rc , ##args); \
+	if (dsprc == HOOK_RETURN) \
+		return rc; \
+}
+
+#define DISPATCH_RET_NORC(fn, parm, dsprc, args...) { \
+	dsprc = CALL_EXIT(fn, parm , ##args); \
+	if (dsprc == HOOK_RETURN) \
+		return; \
+}
+
+#define HOOK_DISP_LOOP(h, dispatch, args...) { \
+	register struct hook_rec *rec; \
+	list_for_each_entry(rec, &h.exit_list, exit_list) { \
+		register int dsprc; \
+		if (rec->hook_flags & HOOK_ARMED) { \
+			dispatch(rec->hook_exit, rec->hook_head, dsprc , ##args) \
+			if (dsprc == HOOK_TERMINATE) \
+				break; \
+		} \
+	} \
+}
+
+#define HOOK_DISP_EXCLUSIVE(h, dispatch, args...) { \
+	register int dsprc; \
+	if (h.hook_flags & HOOK_ACTIVE) { \
+		dispatch(h.hook_ex_exit, &h, dsprc , ##args) \
+	} \
+}
+
+#define HOOK(h, args...) { \
+	HOOK_TEST(h) \
+	HOOK_DISP_LOOP(h, DISPATCH_NORMAL , ##args); \
+}
+
+#define HOOK_RET(h, args...) { \
+	HOOK_TEST(h) \
+	HOOK_DISP_LOOP(h, DISPATCH_RET , ##args); \
+}
+
+#define HOOK_RET_NORC(h, args...) { \
+	HOOK_TEST(h) \
+	HOOK_DISP_LOOP(h, DISPATCH_RET_NORC , ##args); \
+}
+
+#define EXCLUSIVE_HOOK(h, args...) { \
+	HOOK_TEST(h) \
+	HOOK_DISP_EXCLUSIVE(h, DISPATCH_NORMAL , ##args); \
+}
+
+#define EXCLUSIVE_HOOK_RET(h, args...) { \
+	HOOK_TEST(h) \
+	HOOK_DISP_EXCLUSIVE(h, DISPATCH_RET , ##args); \
+}
+
+#define EXCLUSIVE_HOOK_RET_NORC(h, args...) { \
+	HOOK_TEST(h) \
+	HOOK_DISP_EXCLUSIVE(h, DISPATCH_RET_NORC , ##args); \
+}
+
+#define GENERIC_HOOK(h, args...) { \
+	extern struct hook h; \
+	if (unlikely(h.hook_flags & HOOK_ACTIVE)) { \
+		HOOK_DISP_LOOP(h, DISPATCH_NORMAL , ##args); \
+	} \
+}
+
+/* exported function prototypes */
+extern int hook_exit_register(struct hook *, struct hook_rec *);
+extern void hook_exit_deregister(struct hook_rec *);
+extern void hook_exit_arm(struct hook_rec *);
+extern void hook_exit_disarm(struct hook_rec *);
+
+/* exported functions error codes */
+#define EPRIORITY	1	/* reqd. priority not possible */
+
+/* Return values from Hook Exit routines */
+#define HOOK_CONTINUE 	0
+#define HOOK_TERMINATE 	1
+#define HOOK_RETURN 	-1
+
+#else
+/* dummy macros when hooks are not compiled in */
+#define DECLARE_HOOK(x)
+#define DECLARE_GENERIC_HOOK(x)
+#define USE_HOOK(x)
+#define HOOK(h, args...)
+#define HOOK_RET(h, args...)
+#define HOOK_RET_NORC(h, args...)
+#define EXCLUSIVE_HOOK(h, args...)
+#define EXCLUSIVE_HOOK_RET(h, args...)
+#define EXCLUSIVE_HOOK_RET_NORC(h, args...)
+#define GENERIC_HOOK(h, args...)
+#endif /* !(CONFIG_HOOK || CONFIG_HOOK_MODULE) */
+
+#endif /* __LINUX_HOOK_H */
diff -Naru linux-2.6.7/include/asm-ppc64/hook.h linux-hooks-base/include/asm-ppc64/hook.h
--- linux-2.6.7/include/asm-ppc64/hook.h	1970-01-01 09:00:00.000000000 +0900
+++ linux-hooks-base/include/asm-ppc64/hook.h	2004-06-17 10:01:25.296869024 +0900
@@ -0,0 +1,47 @@
+#ifndef __ASM_PPC_HOOK_H
+#define __ASM_PPC_HOOK_H
+/*
+ * Kernel Hooks optimized for PPC64.
+ * 
+ * Authors: Mike Grundy <grundym@us.ibm.com> PPC64
+ */
+#include <asm-generic/hook.h>
+
+#if defined(CONFIG_HOOK) || defined(CONFIG_HOOK_MODULE)
+
+#define IF_HOOK_ENABLED(h, hk) _IF_HOOK_ENABLED(h, #hk)
+#define _IF_HOOK_ENABLED(h, hk) \
+	register int tmp; \
+	__asm__ __volatile__ (".global "hk"; "hk":li %0, 0x00":"=r"(tmp)); \
+	if (unlikely(tmp))
+
+#endif /* CONFIG_HOOK || CONFIG_HOOK_MODULE */
+
+
+/*
+ * Sanity check the hook location for valid instructions at hook location.
+ * At hook location, we should find these instructions:
+ *	38 00 00 00       	li    	r0,0
+ *	2c 00 00 00            	cmpwi	r0,0
+ *	
+ * We can check for li and cmpwi instructions. As these instructions encode
+ * the register name in the second byte and the register cannot be predicted, 
+ * we mask out the bits corresponding to registers in the opcode before comparing.
+ * PPC opcodes are six bits, hence mask of 0xFC
+ */
+#define OPCODE_MOV1			0x38 /* LI (really an extended mnemonic for addi */   
+#define OPCODE_MOV1_MASK		0xFC
+/* Compiler generates 2c 00 00 00     cmpwi   r0,0 */
+		
+static inline int is_asm_hook(unsigned char * addr)
+{
+	if (!addr)
+		return 0;
+	
+	if((addr[0] & OPCODE_MOV1_MASK) == OPCODE_MOV1) {
+		if (*((unsigned short *)(addr+1)) == 0)
+			return 1;
+	}
+	return 0;
+}
+#endif /* __ASM_PPC_HOOK_H */
diff -Naru linux-2.6.7/include/asm-generic/hook.h linux-hooks-base/include/asm-generic/hook.h
--- linux-2.6.7/include/asm-generic/hook.h	1970-01-01 09:00:00.000000000 +0900
+++ linux-hooks-base/include/asm-generic/hook.h	2004-06-17 10:01:25.294869328 +0900
@@ -0,0 +1,25 @@
+#ifndef __ASM_GENERIC_HOOK_H
+#define __ASM_GENERIC_HOOK_H
+/*
+ * Kernel Hooks common code for many archs.
+ * 
+ * Authors: Vamsi Krishna S. <vamsi_krishna@in.ibm.com>
+ */
+#include <asm/cacheflush.h>
+
+static inline void deactivate_asm_hook(struct hook *hook)
+{
+	unsigned char *addr = (unsigned char *) (hook->hook_addr);
+	addr[2] = 0;
+	flush_icache_range(addr + 2, addr + 2);
+	return;
+}
+
+static inline void activate_asm_hook(struct hook *hook)
+{
+	unsigned char *addr = (unsigned char *) (hook->hook_addr);
+	addr[2] = 1;
+	flush_icache_range(addr + 2, addr + 2);
+	return;
+}
+#endif /* __ASM_GENERIC_HOOK_H */
diff -Naru linux-2.6.7/include/asm-ppc/hook.h linux-hooks-base/include/asm-ppc/hook.h
--- linux-2.6.7/include/asm-ppc/hook.h	1970-01-01 09:00:00.000000000 +0900
+++ linux-hooks-base/include/asm-ppc/hook.h	2004-06-17 10:01:25.295869176 +0900
@@ -0,0 +1,47 @@
+#ifndef __ASM_PPC_HOOK_H
+#define __ASM_PPC_HOOK_H
+/*
+ * Kernel Hooks optimized for PPC.
+ * 
+ * Authors: Mike Grundy <grundym@us.ibm.com> s390x
+ */
+#include <asm-generic/hook.h>
+
+#if defined(CONFIG_HOOK) || defined(CONFIG_HOOK_MODULE)
+
+#define IF_HOOK_ENABLED(h, hk) _IF_HOOK_ENABLED(h, #hk)
+#define _IF_HOOK_ENABLED(h, hk) \
+	register int tmp; \
+	__asm__ __volatile__ (".global "hk"; "hk":li %0, 0x00":"=r"(tmp)); \
+	if (unlikely(tmp))
+
+#endif /* CONFIG_HOOK || CONFIG_HOOK_MODULE */
+
+
+/*
+ * Sanity check the hook location for valid instructions at hook location.
+ * At hook location, we should find these instructions:
+ *	38 00 00 00       	li    	r0,0
+ *	2c 00 00 00            	cmpwi	r0,0
+ *	
+ * We can check for li and cmpwi instructions. As these instructions encode
+ * the register name in the second byte and the register cannot be predicted, 
+ * we mask out the bits corresponding to registers in the opcode before comparing.
+ * PPC opcodes are six bits, hence mask of 0xFC
+ */
+#define OPCODE_MOV1			0x38 /* LI (really an extended mnemonic for addi */   
+#define OPCODE_MOV1_MASK		0xFC
+/* Compiler generates 2c 00 00 00     cmpwi   r0,0 */
+		
+static inline int is_asm_hook(unsigned char * addr)
+{
+	if (!addr)
+		return 0;
+	
+	if((addr[0] & OPCODE_MOV1_MASK) == OPCODE_MOV1) {
+		if (*((unsigned short *)(addr+1)) == 0)
+			return 1;
+	}
+	return 0;
+}
+#endif /* __ASM_PPC_HOOK_H */
diff -Naru linux-2.6.7/include/asm-s390/hook.h linux-hooks-base/include/asm-s390/hook.h
--- linux-2.6.7/include/asm-s390/hook.h	1970-01-01 09:00:00.000000000 +0900
+++ linux-hooks-base/include/asm-s390/hook.h	2004-06-17 10:01:25.296869024 +0900
@@ -0,0 +1,49 @@
+#ifndef __ASM_S390_HOOK_H
+#define __ASM_S390_HOOK_H
+/*
+ * Kernel Hooks optimized for s390.
+ * 
+ * Authors: Mike Grundy <grundym@us.ibm.com> s390
+ */
+#include <asm-generic/hook.h>
+
+#if defined(CONFIG_HOOK) || defined(CONFIG_HOOK_MODULE)
+
+#define IF_HOOK_ENABLED(h, hk) _IF_HOOK_ENABLED(h, #hk)
+#define _IF_HOOK_ENABLED(h, hk) \
+	register int tmp; \
+	__asm__ __volatile__ (".global "hk"; "hk":lhi %0, 0x00":"=r"(tmp)); \
+	if (unlikely(tmp))
+
+#endif /* CONFIG_HOOK || CONFIG_HOOK_MODULE */
+
+/*
+ * Sanity check the hook location for valid instructions at hook location.
+ * At hook location, we should find these instructions:
+ *  a7 18 00 00             lhi     %r1,0
+ *  12 11                   ltr     %r1,%r1
+ * We can check for the lhi and ltr instructions. As the lhi instruction encodes
+ * the register name in it, and we can't guarantee which register will be used,
+ * we'll mask out the bits corresponding to the target register.
+ */
+#define OPCODE_MOV2_1			0xa7 /* LHI first byte */
+#define OPCODE_MOV2_2			0x08 /* LHI second byte */
+#define OPCODE_MOV2_1_MASK		0xff
+#define OPCODE_MOV2_2_MASK		0x0f
+/* Compiler generates LTR opcode 12, but second op not tested */
+		
+static inline int is_asm_hook(unsigned char * addr)
+{
+	if (!addr){
+		return 0;
+	}
+	if (((addr[0] & OPCODE_MOV2_1_MASK) == OPCODE_MOV2_1) && 
+		    ((addr[1] & OPCODE_MOV2_2_MASK) == OPCODE_MOV2_2)) {
+		/* was checking a 32bit val, need to check 16, cheated with 8+8 */
+		if (addr[2]== 0 && addr[3]== 0){
+			return 1;
+		}
+	}
+	return 0;
+}
+#endif /* __ASM_S390_HOOK_H */
diff -Naru linux-2.6.7/include/asm-i386/hook.h linux-hooks-base/include/asm-i386/hook.h
--- linux-2.6.7/include/asm-i386/hook.h	1970-01-01 09:00:00.000000000 +0900
+++ linux-hooks-base/include/asm-i386/hook.h	2004-06-17 10:01:25.295869176 +0900
@@ -0,0 +1,48 @@
+#ifndef __ASM_I386_HOOK_H
+#define __ASM_I386_HOOK_H
+/*
+ * Kernel Hooks optimized for ia32.
+ * 
+ * Authors: Richard J Moore <richardj_moore@uk.ibm.com>
+ *	    Vamsi Krishna S. <vamsi_krishna@in.ibm.com>
+ */
+#include <asm-generic/hook.h>
+
+#if defined(CONFIG_HOOK) || defined(CONFIG_HOOK_MODULE)
+
+#define IF_HOOK_ENABLED(h, hk) _IF_HOOK_ENABLED(h, #hk)
+#define _IF_HOOK_ENABLED(h, hk) \
+	register int tmp; \
+	__asm__ __volatile__ (".global "hk"; "hk":movl $0, %0":"=r"(tmp)); \
+	if (unlikely(tmp))
+
+#endif /* CONFIG_HOOK || CONFIG_HOOK_MODULE */
+
+/*
+ * Sanity check the hook location for expected instructions at hook location.
+ * movl $0, %reg, testl %reg, %reg
+ * test doesn't have to follow movl, so don't test for that.
+ */
+#define OPCODE_MOV1			0xb0
+#define OPCODE_MOV1_MASK		0xf0
+#define OPCODE_MOV2_1			0xc6 /* first byte */
+#define OPCODE_MOV2_2			0xc0 /* second byte */
+#define OPCODE_MOV2_1_MASK		0xfe
+#define OPCODE_MOV2_2_MASK		0xf8
+		
+static inline int is_asm_hook(unsigned char *addr)
+{
+	if (!addr)
+		return 0;
+	if((addr[0] & OPCODE_MOV1_MASK) == OPCODE_MOV1) {
+		if (*((unsigned long *)(addr+1)) == 0)
+			return 1;
+	} else if (((addr[0] & OPCODE_MOV2_1_MASK) == OPCODE_MOV2_1) && 
+		    ((addr[1] & OPCODE_MOV2_2_MASK) == OPCODE_MOV2_2)) {
+		if (*((unsigned long *)(addr+2)) == 0)
+			return 1;
+	}
+	return 0;
+}
+
+#endif /* __ASM_I386_HOOK_H */
diff -Naru linux-2.6.7/include/asm-s390x/hook.h linux-hooks-base/include/asm-s390x/hook.h
--- linux-2.6.7/include/asm-s390x/hook.h	1970-01-01 09:00:00.000000000 +0900
+++ linux-hooks-base/include/asm-s390x/hook.h	2004-06-17 10:01:25.297868872 +0900
@@ -0,0 +1,49 @@
+#ifndef __ASM_S390X_HOOK_H
+#define __ASM_S390X_HOOK_H
+/*
+ * Kernel Hooks optimized for s390x(64bit).
+ * 
+ * Authors: Mike Grundy <grundym@us.ibm.com> s390x
+ */
+#include <asm-generic/hook.h>
+
+#if defined(CONFIG_HOOK) || defined(CONFIG_HOOK_MODULE)
+
+#define IF_HOOK_ENABLED(h, hk) _IF_HOOK_ENABLED(h, #hk)
+#define _IF_HOOK_ENABLED(h, hk) \
+	register int tmp; \
+	__asm__ __volatile__ (".global "hk"; "hk":lhi %0, 0x00":"=r"(tmp)); \
+	if (unlikely(tmp))
+
+#endif /* CONFIG_HOOK || CONFIG_HOOK_MODULE */
+
+/*
+ * Sanity check the hook location for valid instructions at hook location.
+ * At hook location, we should find these instructions:
+ *  a7 18 00 00             lhi     %r1,0
+ *  12 11                   ltr     %r1,%r1
+ * We can check for the lhi and ltr instructions. As the lhi instruction encodes
+ * the register name in it, and we can't guarantee which register will be used,
+ * we'll mask out the bits corresponding to the target register.
+ */
+#define OPCODE_MOV2_1			0xa7 /* LHI first byte */
+#define OPCODE_MOV2_2			0x08 /* LHI second byte */
+#define OPCODE_MOV2_1_MASK		0xff
+#define OPCODE_MOV2_2_MASK		0x0f
+/* Compiler generates LTR opcode 12, but second op not tested */
+		
+static inline int is_asm_hook(unsigned char * addr)
+{
+	if (!addr){
+		return 0;
+	}
+	if (((addr[0] & OPCODE_MOV2_1_MASK) == OPCODE_MOV2_1) && 
+		    ((addr[1] & OPCODE_MOV2_2_MASK) == OPCODE_MOV2_2)) {
+		/* was checking a 32bit val, need to check 16, cheated with 8+8 */
+		if (addr[2]== 0 && addr[3]== 0){
+			return 1;
+		}
+	}
+	return 0;
+}
+#endif /* __ASM_S390X_HOOK_H */
diff -Naru linux-2.6.7/kernel/Makefile linux-hooks-base/kernel/Makefile
--- linux-2.6.7/kernel/Makefile	2004-05-27 15:31:49.000000000 +0900
+++ linux-hooks-base/kernel/Makefile	2004-06-17 10:01:25.304867808 +0900
@@ -7,7 +7,7 @@
 	    sysctl.o capability.o ptrace.o timer.o user.o \
 	    signal.o sys.o kmod.o workqueue.o pid.o \
 	    rcupdate.o intermodule.o extable.o params.o posix-timers.o \
-	    kthread.o
+	    kthread.o hook.o
 
 obj-$(CONFIG_FUTEX) += futex.o
 obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
@@ -23,6 +23,7 @@
 obj-$(CONFIG_STOP_MACHINE) += stop_machine.o
 obj-$(CONFIG_AUDIT) += audit.o
 obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
+obj-$(CONFIG_HOOK) += hook.o
 
 ifneq ($(CONFIG_IA64),y)
 # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
diff -Naru linux-2.6.7/kernel/hook.c linux-hooks-base/kernel/hook.c
--- linux-2.6.7/kernel/hook.c	1970-01-01 09:00:00.000000000 +0900
+++ linux-hooks-base/kernel/hook.c	2004-06-17 10:01:25.304867808 +0900
@@ -0,0 +1,123 @@
+/*
+ * Kernel Hooks Interface.
+ * 
+ * Authors: Richard J Moore <richardj_moore@uk.ibm.com>
+ *	    Vamsi Krishna S. <vamsi_krishna@in.ibm.com>
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/hook.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+static spinlock_t hook_lock = SPIN_LOCK_UNLOCKED;
+
+static inline void deactivate_hook(struct hook *hook)
+{
+	hook->hook_flags &= ~HOOK_ACTIVE;
+	if(hook->hook_flags & HOOK_ASM_HOOK)
+		deactivate_asm_hook(hook);
+}
+
+static inline void activate_hook(struct hook *hook)
+{
+	hook->hook_flags |= HOOK_ACTIVE;
+	if(hook->hook_flags & HOOK_ASM_HOOK)
+		activate_asm_hook(hook);
+}
+
+static void disarm_one_hook_exit(struct hook_rec *hook_rec)
+{
+	struct hook_rec *rec;
+
+	hook_rec->hook_flags &= ~HOOK_ARMED;
+	list_for_each_entry(rec, &hook_rec->hook_head->exit_list, exit_list) {
+		if(rec->hook_flags & HOOK_ARMED) {
+			return;
+		}
+	}
+	deactivate_hook(hook_rec->hook_head);
+}
+
+int hook_exit_register(struct hook *hook, struct hook_rec *hook_rec)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hook_lock, flags);
+	if(hook->hook_flags & HOOK_EXCLUSIVE) {
+		if (!list_empty(&hook->exit_list)) {
+			spin_unlock_irqrestore(&hook_lock, flags);
+			return -EPRIORITY;
+		}
+		hook->hook_ex_exit = hook_rec->hook_exit;
+	}
+	list_add(&hook_rec->exit_list, &hook->exit_list);
+	
+	hook_rec->hook_head = hook;
+	if(is_asm_hook(hook->hook_addr))
+		hook->hook_flags |= HOOK_ASM_HOOK;
+
+	MOD_INC_USE_COUNT;
+	spin_unlock_irqrestore(&hook_lock, flags);
+	return 0;
+}
+
+void hook_exit_deregister(struct hook_rec *rec)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hook_lock, flags);
+	if(rec->hook_flags & HOOK_ARMED)
+		disarm_one_hook_exit(rec);
+	if(rec->hook_head->hook_flags & HOOK_EXCLUSIVE)
+		rec->hook_head->hook_ex_exit = NULL;
+	list_del(&rec->exit_list);
+
+	MOD_DEC_USE_COUNT;
+	spin_unlock_irqrestore(&hook_lock, flags);
+}
+
+void hook_exit_arm(struct hook_rec *rec)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hook_lock, flags);
+	rec->hook_flags |= HOOK_ARMED;
+	if(!(rec->hook_head->hook_flags & HOOK_ACTIVE))
+		activate_hook(rec->hook_head);
+	spin_unlock_irqrestore(&hook_lock, flags);
+}
+
+void hook_exit_disarm(struct hook_rec *rec)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hook_lock, flags);
+	disarm_one_hook_exit(rec);
+	spin_unlock_irqrestore(&hook_lock, flags);
+}
+
+static int __init hook_init_module(void)
+{
+	printk(KERN_INFO "Kernel Hooks Interface installed.\n");
+	return 0;
+}
+
+static void __exit hook_cleanup_module(void)
+{
+	printk(KERN_INFO "Kernel Hooks Interface terminated.\n");
+}
+
+module_init(hook_init_module);
+module_exit(hook_cleanup_module);
+
+EXPORT_SYMBOL(hook_exit_deregister);
+EXPORT_SYMBOL(hook_exit_arm);
+EXPORT_SYMBOL(hook_exit_disarm);
+EXPORT_SYMBOL(hook_exit_register);
+
+MODULE_LICENSE("GPL");
