--- linux-2.6.27/include/linux/kaho.h	1970-01-01 09:00:00.000000000 +0900
+++ linux-2.6.27.kaho/include/linux/kaho.h	2009-03-09 05:38:24.000000000 +0900
@@ -0,0 +1,104 @@
+#ifndef _kaho_mod_h
+#define _kaho_mod_h
+
+#include <asm/ioctl.h>
+
+#define KAHO_IOC_MAGIC 'k'
+
+struct kaho_make_patch {
+	pid_t target_pid;
+	int nr_sub_patch;		/* number of the patch */
+	int handle;
+};
+
+struct kaho_map_opt {
+	int handle;
+	const char *filename;
+	unsigned long addr;
+	unsigned long length;
+	unsigned long offset;
+	unsigned long prot;
+	unsigned long flag;
+	unsigned long act_addr;
+};
+
+struct kaho_load_patch {
+	int handle;
+	int sub_patch_id;
+	int patch_type;
+	unsigned long src_addr;	  /* address of the patch in kaho command */
+	unsigned long patch_addr; /* address to store the patch in the target */
+	unsigned long patch_size; /* size of the patch code */
+	unsigned long target_addr;/* address to be patched in the target */
+};
+
+struct kaho_std_opt {
+	int handle;
+	unsigned int flags;
+};
+
+struct kaho_get_info {
+	int handle;
+	int sub_patch_id;
+	pid_t pid;
+	int nr_sub_patch;
+	int state;
+	int patch_type;
+	unsigned long patch_addr;
+	unsigned long patch_size;
+	unsigned long target_addr;
+	int next_handle;
+};
+
+
+#define KAHOCTL_MAKE_PATCH	_IOWR(KAHO_IOC_MAGIC, 1, struct kaho_make_patch)
+#define KAHOCTL_MAP_PATCH	_IOWR(KAHO_IOC_MAGIC, 2, struct kaho_map_opt)
+#define KAHOCTL_LOAD_PATCH	_IOW (KAHO_IOC_MAGIC, 3, struct kaho_load_patch)
+#define KAHOCTL_ACTIVATE	_IOW (KAHO_IOC_MAGIC, 4, struct kaho_std_opt)
+#define KAHOCTL_ACTIVATE_RT	_IOW (KAHO_IOC_MAGIC, 5, struct kaho_std_opt)
+#define KAHOCTL_DEACTIVATE	_IOW (KAHO_IOC_MAGIC, 6, struct kaho_std_opt)
+#define KAHOCTL_UNMAP_PATCH	_IOWR(KAHO_IOC_MAGIC, 7, struct kaho_map_opt)
+#define KAHOCTL_DEL_PATCH	_IOW (KAHO_IOC_MAGIC, 8, struct kaho_std_opt)
+#define KAHOCTL_GET_INFO	_IOWR(KAHO_IOC_MAGIC, 9, struct kaho_get_info)
+#define KAHOCTL_CANCEL		_IOW (KAHO_IOC_MAGIC, 10, struct kaho_std_opt)
+
+#define KAHO_STATE_ENTRY		0
+#define KAHO_STATE_MAPPING		1
+#define KAHO_STATE_MAPPED		2
+#define KAHO_STATE_LOADING		3
+#define KAHO_STATE_LOADED		4
+#define KAHO_STATE_IN_ACT		5
+//#define KAHO_STATE_IN_ACT_RT		6
+#define KAHO_STATE_ACTIVE		7
+#define KAHO_STATE_IN_DEACT		8
+//#define KAHO_STATE_IN_DEACT_RT		9
+#define KAHO_STATE_DEACTIVE		10
+#define KAHO_STATE_UNMAPPING		11
+#define KAHO_STATE_UNMAPPED		12
+#define KAHO_STATE_IN_DEL_PATCH		13
+#define KAHO_STATE_IN_ACT_RT0		14
+#define KAHO_STATE_IN_ACT_RT1		15
+#define KAHO_STATE_IN_ACT_RT2		16
+#define KAHO_STATE_IN_DEACT_RT0		17
+#define KAHO_STATE_IN_DEACT_RT1		18
+#define KAHO_STATE_IN_DEACT_RT2		19
+
+#define KAHO_STATE_ERROR	-1
+
+#define KAHO_MAX_NR_PATCH	0x1000
+#define KAHO_MAX_NR_SUB		0x100
+
+
+/* definition of patch type */
+#define KAHO_PTYPE_UNKNOWN	0
+#define KAHO_PTYPE_FUNC		1
+#define KAHO_PTYPE_VAR		2
+#define KAHO_PTYPE_POINTER	3
+#define KAHO_PTYPE_NONE	4
+#define KAHO_PTYPE_MAX		5
+
+/* flags for kaho_patch_item */
+#define KAHO_X86_ABS_JMP	0x0001
+#define KAHO_RT_PATCH		0x0002
+
+#endif
--- linux-2.6.27/kernel/kaho_def.h	1970-01-01 09:00:00.000000000 +0900
+++ linux-2.6.27.kaho/kernel/kaho_def.h	2009-03-09 05:43:56.000000000 +0900
@@ -0,0 +1,197 @@
+#ifndef _kaho_def_h
+#define _kaho_def_h
+
+/* ------------------------------------------------------------------
+ * Definitions for x86_64 & i386
+ * ---------------------------------------------------------------- */
+#if defined(__x86_64__) || defined(__i386__)
+
+#ifdef CONFIG_KAHO_RT
+static const unsigned char trap_code = 0xcc;
+static const int trap_code_size = 1;
+#endif
+
+#endif
+
+/* ------------------------------------------------------------------
+ * Definitions for x86_64
+ * ---------------------------------------------------------------- */
+#if defined(__x86_64__)
+
+static const unsigned char jmp_code_abs[] = {
+	/* jmpq *0x0(%rip) */
+	0xff, 0x25, 0x00, 0x00, 0x00, 0x00,
+	/* absolute address */
+	0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
+};
+
+static const unsigned char jmp_code_rel[] = {
+	/* jmpq  $0x12345678 */
+	0xe9, 0x12, 0x34, 0x56, 0x78,
+};
+
+/* size of jump code */
+static const int jmp_code_size_abs = sizeof(jmp_code_abs);
+static const int jmp_code_size_rel = sizeof(jmp_code_rel);
+#define ARCH_JMP_CODE_SIZE	sizeof(jmp_code_abs)
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
+#define INST_PTR regs->ip
+#else
+#define INST_PTR regs->rip
+#endif
+
+inline void arch_set_pc(struct pt_regs* regs, unsigned long pc)
+{
+	INST_PTR = pc;
+}
+
+inline unsigned long arch_get_pc(struct pt_regs* regs)
+{
+	return INST_PTR;
+}
+
+#endif
+
+/* ------------------------------------------------------------------
+ * Definitions for i386
+ * ---------------------------------------------------------------- */
+#if defined(__i386__)
+static const unsigned char jmp_code_rel[] = {
+	/* jmpq  $0x12345678 */
+	0xe9, 0x12, 0x34, 0x56, 0x78,
+};
+static const int jmp_code_size_rel = sizeof(jmp_code_rel);
+#define ARCH_JMP_CODE_SIZE sizeof(jmp_code_rel)
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
+#define INST_PTR regs->ip
+#else
+#define INST_PTR regs->eip
+#endif
+
+inline void arch_set_pc(struct pt_regs* regs, unsigned long pc)
+{
+	INST_PTR = pc;
+}
+
+inline unsigned long arch_get_pc(struct pt_regs* regs)
+{
+	return INST_PTR;
+}
+#endif
+
+/* ----------------------------------------------------------------
+ *
+ * Definictions for all architecutres
+ *
+ * ---------------------------------------------------------------- */
+#define HANDLE_NOT_USED	0
+#define HANDLE_USED	1
+
+#define NO_PATCHER	-1
+
+#define OPE_MAP		0
+#define OPE_UNMAP	1
+
+#define REQ_ACT		0
+#define REQ_DEACT	1
+#define REQ_ACT_RT	2
+#define REQ_DEACT_RT	3
+
+#define NOT_CODE_BKUP	0
+#define CODE_BKUP	1
+#define CODE_RESTORE	2
+
+#define CANCELED	1
+
+#ifdef CONFIG_KAHO_RT
+#define THR_NO_MARK	0
+#define THR_MARKED	1
+#define THR_ESRCH	2
+#define THR_NEWFACE	3
+#define THR_CHK_ERR	-1
+
+#define MAX_RETRY_RT_ACT	10
+#endif
+
+struct kaho_patch_item {
+	int patch_type;
+	unsigned long patch_addr;  /* address to patch in the target */
+	unsigned long patch_size;  /* size of the patch */
+	unsigned long target_addr; /* address to be patched */
+	unsigned char backup[ARCH_JMP_CODE_SIZE];
+#ifdef CONFIG_KAHO_RT
+	atomic_t backup_done;
+#endif
+	int flags;
+};
+
+struct kaho_map_struct {
+	struct file* filp;
+	unsigned long addr;
+	unsigned long length;
+	unsigned long offset;
+	unsigned long prot;
+	unsigned long flag;
+	unsigned long act_addr;
+};
+
+#ifdef CONFIG_KAHO_RT
+struct kaho_patch_info;
+struct kaho_thr_list {
+	struct utrace_attached_engine* engine;
+	struct rcu_head rcu_head;
+	struct list_head chk_list; /* list of threads to be checked */
+	struct list_head thr_list; /* list of all threads in the process */
+	struct task_struct* task;
+	struct kaho_patch_info* kpi;
+	atomic_t checked;
+	atomic_t used;
+	int sem_upped;
+};
+#endif
+
+struct kaho_patch_info {
+	/* basic variables */
+	struct list_head list;
+
+	/* lock for the members of this structure */
+	struct semaphore sem;
+	atomic_t used; /* reference counter */
+
+	int handle;
+	atomic_t state;
+	struct task_struct* target_task;
+	struct utrace_attached_engine* engine;
+
+	/* patch item array */
+	struct kaho_map_struct* kms;
+	struct semaphore mem_ope_sem;
+	int nr_sub_patch;
+	struct kaho_patch_item* items;
+	int canceled;
+	u32 exec_id;
+
+	/* for delayed release */
+	struct timer_list timer;
+	unsigned long nvcsw, nivcsw;
+
+#ifdef CONFIG_KAHO_RT
+	/* list of kaho_patch_info that is waiting for realtime activation */
+	struct list_head trap_list;	/* it is linked from ... */
+	struct list_head chk_list;	/* List head for the */
+	struct list_head thr_list;	/* List head for the */
+	/*spinlock_t chk_list_lock;
+	spinlock_t thr_list_lock;*/
+	spinlock_t list_lock;
+	int jmp_code_size;
+	struct semaphore rt_sem;
+
+	/* list of thread information */
+#endif
+};
+
+#endif
+
--- linux-2.6.27/kernel/kaho.c	1970-01-01 09:00:00.000000000 +0900
+++ linux-2.6.27.kaho/kernel/kaho.c	2009-03-09 05:38:24.000000000 +0900
@@ -0,0 +1,2521 @@
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <asm/uaccess.h>
+#include <linux/mman.h>
+#include <linux/pagemap.h>
+#include <linux/ptrace.h>
+#include <linux/mm.h>
+#include <asm/tlbflush.h>
+#include <asm/kdebug.h>
+#include <asm/ptrace.h>
+#include <linux/utrace.h>
+#include <linux/kthread.h>
+#include <linux/list.h>
+#include <linux/version.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+#include <linux/kdebug.h>
+#endif
+
+//#define CONFIG_KAHO_RT
+
+#include <linux/kaho.h>
+#include "kaho_def.h"
+
+//#define DEBUG
+#define MSG_HEAD KERN_ERR "kaho: "
+#ifdef DEBUG
+#define DPRINT(format, args...) printk(MSG_HEAD format, ## args)
+#else
+#define DPRINT(format, args...)
+#endif
+
+/* Macros to use various kernel */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+#define NEW_UTRACE
+#endif
+
+#ifdef NEW_UTRACE
+#define utrace_attach utrace_attach_task
+#define utrace_set_flags utrace_set_events
+#define utrace_detach(a, b) utrace_control(a, b, UTRACE_DETACH)
+#define find_task_by_pid(a) find_task_by_pid_ns(a, &init_pid_ns);
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+#define list_for_each_safe_rcu(pos, b, head) \
+	pos = head; \
+        list_for_each_continue_rcu(pos, head)
+#define class_device_create device_create
+#define class_device_destroy device_destroy
+#endif
+
+
+/* ------------------------------------------------------------------
+ * Basic variables and structures
+ * ---------------------------------------------------------------- */
+#define KAHO_VER "1.6.0"
+static struct class *kaho_class;
+static int kaho_major = 0;
+static int kaho_minor = 0;
+static const char kaho_dev_name[] = "kaho";
+
+/* ------------------------------------------------------------------*/
+/* List of kaho_patch_info */
+LIST_HEAD(kaho_patch_list_head);
+DEFINE_SPINLOCK(kaho_patch_list_lock);
+
+#ifdef CONFIG_KAHO_RT
+/* List of kaho_patch_info that is waiting for realtime activation */
+LIST_HEAD(kaho_trap_list_head);
+DEFINE_SPINLOCK(kaho_trap_list_lock);
+#endif
+
+/* Number of patches included in kaho_patch_list_head */
+static atomic_t nr_patch;
+
+/* Array and spinlock for handle management */
+static char handle_tbl[KAHO_MAX_NR_PATCH];
+DEFINE_SPINLOCK(handle_tbl_lock);
+
+/* ------------------------------------------------------------------
+ * Architecture depend codes
+ * ---------------------------------------------------------------- */
+#if defined(__i386__) || defined(__x86_64__)
+#if 0
+#define __access_mem(tsk, dst, src, size, exec_id, err_msg, err_code, dir) \
+do { \
+	struct mm_struct *mm = get_task_mm(tsk); \
+	if (!mm) { \
+		printk(KERN_ERR MSG_HEAD \
+		       "Failed to access_proccess_vm: " \
+		       "get_task_mm() returned NULL: " err_msg); \
+		err_code; \
+	} \
+	down_read(&mm->mmap_sem); \
+	if (tsk->self_exec_id != exec_id) { \
+		printk(KERN_ERR MSG_HEAD \
+		       "Failed to access_proccess_vm: exec_id has changed " \
+		       "%d->%d " err_msg, exec_id, tsk->self_exec_id); \
+		up_read(&mm->mmap_sem); \
+		mmput(mm); \
+		err_code; \
+	} \
+	ret = _kaho_access_process_vm(tsk, dst, src, size, dir); \
+	up_read(&mm->mmap_sem); \
+	mmput(mm); \
+	if (ret != size) { \
+		printk(KERN_ERR MSG_HEAD \
+		       "Failed to access_proccess_vm ret: %d, size: %d" \
+		       err_msg, ret, (int)size); \
+		err_code; \
+	} \
+} while(0)
+#endif
+//#if 0
+#define __access_mem(tsk, dst, src, size, exec_id, err_msg, err_code, dir) \
+do { \
+	if (tsk->self_exec_id != exec_id) { \
+		printk(KERN_ERR MSG_HEAD \
+		       "Failed to access_proccess_vm: exec_id has changed " \
+		       "%d->%d " err_msg, exec_id, tsk->self_exec_id); \
+		err_code; \
+	} \
+	ret = access_process_vm(tsk, dst, src, size, dir); \
+	if (ret != size) { \
+		printk(KERN_ERR MSG_HEAD \
+		       "Failed to access_proccess_vm ret: %d, size: %d" \
+		       err_msg, ret, (int)size); \
+		err_code; \
+	} \
+} while(0)
+//#endif
+
+#define __WRITE_MEM(tsk, dst, src, size, exec_id, err_msg, err_code) \
+	__access_mem(tsk, dst, src, size, exec_id, err_msg, err_code, 1)
+
+#define __READ_MEM(tsk, dst, src, size, exec_id, err_msg, err_code) \
+	__access_mem(tsk, dst, src, size, exec_id, err_msg, err_code, 0)
+
+
+static int arch_overwrite_code(struct kaho_patch_info* kpi, int no,
+			       unsigned long target_addr,
+			       unsigned char* ovwr_code, int jmp_code_size)
+{
+	int ret;
+
+#ifdef CONFIG_KAHO_RT
+	if (kpi->items[no].flags & KAHO_RT_PATCH) {
+		__WRITE_MEM(kpi->target_task, target_addr+trap_code_size,
+			    (void*)&ovwr_code[trap_code_size],
+			    jmp_code_size-trap_code_size, kpi->exec_id,
+			    "(arch_overwrite_code 1)\n",
+			    ret = -EFAULT; return ret);
+		__WRITE_MEM(kpi->target_task, target_addr,
+			    (void*)&ovwr_code[0], trap_code_size, kpi->exec_id,
+			    "(arch_overwrite_code 0)\n",
+			    ret = -EFAULT; return ret);
+	} else {
+#endif
+		__WRITE_MEM(kpi->target_task, target_addr, (void*)ovwr_code,
+			    jmp_code_size, kpi->exec_id,
+			    "(arch_overwrite_code)\n",
+			    ret = -EFAULT; return ret);
+#ifdef CONFIG_KAHO_RT
+	}
+#endif
+	return 0;
+}
+
+static int arch_get_jump_code_size(struct kaho_patch_info* kpi, int no)
+{
+	int ret;
+#if defined(__x86_64__)
+	if (kpi->items[no].flags & KAHO_X86_ABS_JMP)
+		ret = jmp_code_size_abs;
+	else
+#endif
+		ret = jmp_code_size_rel;
+	return ret;
+}
+
+#if defined(__x86_64__)
+static int arch_func_patch_abs(struct kaho_patch_info* kpi, int no)
+{
+	unsigned long patch_addr = kpi->items[no].patch_addr;
+	unsigned long target_addr = kpi->items[no].target_addr;
+	unsigned char jmp_code[jmp_code_size_abs];
+
+	memcpy(jmp_code, jmp_code_abs, 6);
+	*((unsigned long*)&jmp_code[6]) = patch_addr;
+	return arch_overwrite_code(kpi, no, target_addr, jmp_code,
+				   jmp_code_size_abs);
+}
+#endif
+
+#ifdef CONFIG_KAHO_RT
+static int arch_trap_addr_check(
+	struct die_args* args, unsigned long target_addr)
+{
+	return arch_get_pc(args->regs) ==  (target_addr + trap_code_size);
+}
+
+static int arch_implant_trap(struct kaho_patch_info* kpi, int i, int bkup)
+{
+	int ret;
+	struct kaho_patch_item* pitem = &(kpi->items[i]);
+
+	/* backup */
+	DPRINT("arch_implant_trap(entry): target_addr: %lx\n",
+	       pitem->target_addr);
+
+	if (bkup == CODE_BKUP) {
+		__READ_MEM(kpi->target_task, pitem->target_addr,
+			   (void*)pitem->backup, trap_code_size, kpi->exec_id,
+			   "(backup trap)\n",
+			   return -EFAULT);
+		atomic_set(&pitem->backup_done, 1);
+	}
+
+	/* Implant */
+	if (bkup == CODE_RESTORE) {
+		__WRITE_MEM(kpi->target_task, pitem->target_addr,
+			    (void*)pitem->backup, trap_code_size,
+			    kpi->exec_id, "(implant trap)\n",
+			    return -EFAULT);
+		return 0;
+	}
+	__WRITE_MEM(kpi->target_task, pitem->target_addr, (void*)&trap_code,
+		    trap_code_size, kpi->exec_id, "(implant trap)\n",
+		    return -EFAULT);
+
+	DPRINT("arch_implant_trap(exit)\n");
+	return 0;
+}
+#endif
+
+static int arch_calc_rel_addr(unsigned long patch_addr,
+			      unsigned long target_addr, int32_t* prel)
+{
+#if defined(__x86_64__)
+	int64_t rel_addr_64;
+
+	rel_addr_64 = patch_addr - target_addr - jmp_code_size_rel;
+	if (rel_addr_64 > 0x7fffffffL || -rel_addr_64 > 0x80000000L)
+		return -EINVAL;
+
+	*prel =  (int32_t)rel_addr_64;
+#endif
+
+#if defined(__i386__)
+	*prel = patch_addr - target_addr - jmp_code_size_rel;
+#endif
+	return 0;
+}
+
+static int arch_func_patch_rel(struct kaho_patch_info* kpi, int no)
+{
+	int ret;
+	unsigned long patch_addr = kpi->items[no].patch_addr;
+	unsigned long target_addr = kpi->items[no].target_addr;
+	unsigned char jmp_code[jmp_code_size_rel];
+	int32_t rel_addr;
+
+	/* Calculation of the relative address */
+	ret = arch_calc_rel_addr(patch_addr, target_addr, &rel_addr);
+	if (ret < 0) {
+		printk(KERN_ERR MSG_HEAD "Cannot jump: patch_addr: %lx, "
+		                         "target_addr: %lx\n",
+					 patch_addr, target_addr);
+		return ret;
+	}
+
+	/* Overwirte jump code */
+	jmp_code[0] = jmp_code_rel[0];
+	*((int32_t*)&jmp_code[1]) = rel_addr;
+	return arch_overwrite_code(kpi, no, target_addr, (void*)jmp_code,
+				   jmp_code_size_rel);
+}
+
+static int arch_func_patch(struct kaho_patch_info* kpi, int no)
+{
+	int backup_len;
+	int ret;
+	unsigned long target;
+	void* backup;
+
+	/* Get length to backup orig data */
+	backup_len = arch_get_jump_code_size(kpi, no);
+
+	/* Set addresses */
+	target = (unsigned long) kpi->items[no].target_addr;
+	backup = (void*) kpi->items[no].backup;
+
+#ifdef CONFIG_KAHO_RT
+	/* Backup size and backup address are adjusted, because the region
+	   that was overwrited by trap code has already backuped */
+	if (kpi->items[no].flags & KAHO_RT_PATCH) {
+		target += trap_code_size;
+		backup = &(kpi->items[no].backup[trap_code_size]);
+		backup_len -= trap_code_size;
+	}
+#endif
+
+	__READ_MEM(kpi->target_task, target, backup, backup_len,
+		   kpi->exec_id, "(backup code)\n",
+		   ret = -EFAULT; return ret);
+
+	/* Write jump command */
+#if defined(__x86_64__)
+	if (kpi->items[no].flags & KAHO_X86_ABS_JMP)
+		ret = arch_func_patch_abs(kpi, no);
+	else
+#endif
+		ret = arch_func_patch_rel(kpi, no);
+
+	return ret;
+}
+
+static int arch_data_patch(struct kaho_patch_info* kpi, int no, int ptype)
+{
+	int ret;
+	int patch_size;
+	unsigned long target_addr = kpi->items[no].target_addr;
+	void* saddr;
+	void* backup_addr;
+
+	if (ptype == KAHO_PTYPE_VAR) {
+		patch_size = kpi->items[no].patch_size;
+		saddr = (void*)kpi->items[no].patch_addr;
+		backup_addr = &((char*)saddr)[patch_size];
+		DPRINT("KAHO_PTYPE_VAR: patch_size: %d, saddr: %p, "
+		       "target: %lx, pid: %d\n", patch_size, saddr,
+		       target_addr, current->pid);
+	}
+	else if (ptype == KAHO_PTYPE_POINTER) {
+		patch_size = sizeof(void *);
+		saddr = (void*)&(kpi->items[no].patch_addr);
+		backup_addr = (void*)kpi->items[no].backup;
+		DPRINT("KAHO_PTYPE_POINTER: patch_size: %d, saddr: %p, "
+		       "*saddr: %lx, target: %lx, pid: %d\n",
+		       patch_size, saddr, *((unsigned long*)saddr),
+		       target_addr, current->pid);
+	}
+	else{
+		printk(KERN_ERR MSG_HEAD
+		       "Unknown ptype: %d @arch_data_patch\n", ptype);
+		return -EFAULT;
+	}
+
+	/* Backup orignal data */
+	__READ_MEM(kpi->target_task, target_addr, backup_addr, patch_size,
+		   kpi->exec_id, "(backup data)\n",
+		   ret = -EFAULT; return ret);
+
+	/* Write new data */
+	__WRITE_MEM(kpi->target_task, target_addr, saddr, patch_size,
+		    kpi->exec_id, "(write data)\n",
+		    ret = -EFAULT; return ret);
+
+	return 0;
+}
+
+static int arch_activate(struct kaho_patch_info* kpi, int i)
+{
+	int ret = -EINVAL;
+	struct kaho_patch_item* pitem = &(kpi->items[i]);
+
+	if (pitem->patch_type == KAHO_PTYPE_FUNC)
+		ret = arch_func_patch(kpi, i);
+	else if (pitem->patch_type == KAHO_PTYPE_VAR ||
+		 pitem->patch_type == KAHO_PTYPE_POINTER)
+		ret = arch_data_patch(kpi, i, pitem->patch_type);
+
+	return ret;
+}
+
+static int arch_deactivate(struct kaho_patch_info* kpi,
+			   unsigned long dst, unsigned char* src, int len,
+			   int no)
+{
+	return arch_overwrite_code(kpi, no, dst, src, len);
+}
+#endif
+
+/* ------------------------------------------------------------------
+ * Functions for handle management
+ * ---------------------------------------------------------------- */
+static void init_handle_tbl(void)
+{
+	int i;
+	for (i = 0; i < KAHO_MAX_NR_PATCH; i++)
+		handle_tbl[i] = HANDLE_NOT_USED;
+}
+
+static int get_handle(void)
+{
+	static int prev_assign_handle = 0;
+	int i;
+	int handle = 0;
+
+	spin_lock(&handle_tbl_lock);
+	for (i = prev_assign_handle + 1; i <= KAHO_MAX_NR_PATCH; i++) {
+		if (handle_tbl[i-1] == HANDLE_NOT_USED) {
+			handle = i;
+			break;
+		}
+	}
+	if (handle <= 0) {
+		for (i = 1; i <= prev_assign_handle; i++) {
+			if (handle_tbl[i-1] == HANDLE_NOT_USED) {
+				handle = i;
+				break;
+			}
+		}
+	}
+
+	if (handle > 0) {
+		/* if available handle is detected */
+		prev_assign_handle = handle;
+		handle_tbl[handle-1] = HANDLE_USED;
+	}
+	spin_unlock(&handle_tbl_lock);
+
+	return handle;
+}
+
+static void put_handle(int handle)
+{
+	spin_lock(&handle_tbl_lock);
+	handle_tbl[handle-1] = HANDLE_NOT_USED;
+	spin_unlock(&handle_tbl_lock);
+}
+
+/* ------------------------------------------------------------------
+ * State check functions
+ * ---------------------------------------------------------------- */
+static int chk_stat_map_ope_alloc(int stat)
+{
+	if (stat == KAHO_STATE_ENTRY)
+		return 1;
+	if (stat == KAHO_STATE_MAPPED)
+		return 1;
+	if (stat == KAHO_STATE_UNMAPPED)
+		return 1;
+	return 0;
+}
+
+static int chk_stat_map_ope_free(int stat)
+{
+	if (stat == KAHO_STATE_MAPPED)
+		return 1;
+	if (stat == KAHO_STATE_UNMAPPED)
+		return 1;
+	if (stat == KAHO_STATE_LOADED)
+		return 1;
+	if (stat == KAHO_STATE_DEACTIVE)
+		return 1;
+	return 0;
+}
+
+static int chk_stat_load(int stat)
+{
+	if (stat == KAHO_STATE_MAPPED)
+		return 1;
+	if (stat == KAHO_STATE_UNMAPPED)
+		return 1;
+	if (stat == KAHO_STATE_LOADED)
+		return 1;
+	return 0;
+}
+
+static int chk_stat_quiesce_main_thr(int stat)
+{
+	if (stat == KAHO_STATE_MAPPING)
+		return 1;
+	if (stat == KAHO_STATE_UNMAPPING)
+		return 1;
+	return 0;
+}
+
+static int chk_stat_activate(int stat)
+{
+	if (stat == KAHO_STATE_LOADED)
+		return 1;
+	if (stat == KAHO_STATE_DEACTIVE)
+		return 1;
+	return 0;
+}
+
+static int chk_stat_deactivate(int stat)
+{
+	if (stat == KAHO_STATE_ACTIVE)
+		return 1;
+	return 0;
+}
+
+static int chk_stat_del_patch(int stat)
+{
+	if (stat == KAHO_STATE_ENTRY)
+		return 1;
+	if (stat == KAHO_STATE_MAPPED)
+		return 1;
+	if (stat == KAHO_STATE_UNMAPPED)
+		return 1;
+	if (stat == KAHO_STATE_LOADED)
+		return 1;
+	if (stat == KAHO_STATE_DEACTIVE)
+		return 1;
+	if (stat == KAHO_STATE_ERROR)
+		return 1;
+	return 0;
+}
+
+/* ------------------------------------------------------------------
+ * Utility functions
+ * ---------------------------------------------------------------- */
+static struct kaho_patch_info* get_kpi(int handle)
+{
+	struct kaho_patch_info* kpi;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(kpi, &kaho_patch_list_head, list) {
+		if (kpi->handle == handle) {
+			atomic_inc(&kpi->used);
+			rcu_read_unlock();
+			down(&kpi->sem);
+			return kpi;
+		}
+	}
+	rcu_read_unlock();
+
+	return NULL;
+}
+
+static void put_kpi(struct kaho_patch_info* kpi)
+{
+	up(&kpi->sem);
+	atomic_dec(&kpi->used);
+}
+
+#ifdef CONFIG_KAHO_RT
+static void free_ktl(struct rcu_head* head)
+{
+	struct kaho_thr_list* ktl;
+	ktl = container_of(head, struct kaho_thr_list, rcu_head);
+	kfree(ktl);
+}
+#endif
+
+static void kaho_timer(unsigned long arg)
+{
+	struct semaphore* sem = (struct semaphore*)arg;
+	up(sem);
+}
+
+static void kaho_sleep(unsigned int ms)
+{
+	struct semaphore sem;
+	struct timer_list timer;
+	init_MUTEX_LOCKED(&sem);
+	setup_timer(&timer, kaho_timer, (unsigned long)&sem);
+	timer.expires = jiffies+(ms*HZ/1000);
+	add_timer(&timer);
+	down(&sem);
+
+}
+
+static void free_kpi(struct kaho_patch_info* kpi, int thr, int skip_detach)
+{
+	int i;
+	DPRINT("free_kpi (entry)\n");
+	/*
+	 * kpi->used does not increase, because this function must be called
+	 * after the kpi was deleted from the list.
+	 */
+	synchronize_rcu();
+	while (atomic_read(&kpi->used) > thr) {
+		
+		/* up semaphore if necessary */
+		if (down_trylock(&kpi->mem_ope_sem) != 0) {
+			DPRINT("cancel: Mem allocation\n");
+			kpi->canceled = CANCELED;
+			up(&kpi->mem_ope_sem);
+		}
+#ifdef CONFIG_KAHO_RT
+		else if (down_trylock(&kpi->rt_sem) != 0) {
+			DPRINT("cancel: RT activation\n");
+			kpi->canceled = CANCELED;
+			up(&kpi->rt_sem);
+		}
+#endif
+		/* waiting for a while */
+		kaho_sleep(10);
+	}
+
+	if (!skip_detach) {
+		if (utrace_detach(kpi->target_task, kpi->engine) < 0)
+			printk(KERN_ERR MSG_HEAD "Failed to utrace_detach()\n");
+	}
+	put_handle(kpi->handle);
+	atomic_dec(&nr_patch);
+
+	/*
+	 * Free buffer for var. patch
+	 */
+	for (i = 0; i < kpi->nr_sub_patch; i++ ) {
+		if (kpi->items[i].patch_type == KAHO_PTYPE_VAR){
+			void* addr = (void*)kpi->items[i].patch_addr;
+			if (addr != NULL){
+				DPRINT("free buf for var. patch: %p\n", addr);
+				kfree(addr);
+			}
+		}
+	}
+
+	/*
+	 * Free buffer for descriptions of sub patches.
+	 */
+	kfree(kpi->items);
+
+#ifdef CONFIG_KAHO_RT
+	if (!list_empty(&kpi->chk_list))
+		panic("list_empty(&kpi->chk_list) is not empty");
+	if (!list_empty(&kpi->thr_list))
+		panic("list_empty(&kpi->thr_list) is not empty");
+#endif
+	kfree(kpi);
+	DPRINT("free_kpi (exit)\n");
+}
+
+static int valid_patch_type(int patch_type)
+{
+	if (patch_type == KAHO_PTYPE_FUNC)
+		return 0;
+	if (patch_type == KAHO_PTYPE_VAR)
+		return 0;
+	if (patch_type == KAHO_PTYPE_POINTER)
+		return 0;
+	if (patch_type == KAHO_PTYPE_NONE)
+		return 0;
+	return -1;
+}
+
+/* ------------------------------------------------------------------
+ * Handlers of UTRACE for target process
+ * ---------------------------------------------------------------- */
+static void kaho_prepare_exit(struct utrace_attached_engine *engine,
+			   struct task_struct *tsk, int skip_detach)
+{
+	struct kaho_patch_info* kpi;
+	struct list_head *pos, *next;
+
+	DPRINT("kaho_prepare_exit (entry)\n");
+	spin_lock(&kaho_patch_list_lock);
+	list_for_each_safe(pos, next, &kaho_patch_list_head) {
+		kpi = list_entry(pos, struct kaho_patch_info, list);
+		if (engine == kpi->engine) {
+			list_del_rcu(&kpi->list);
+			spin_unlock(&kaho_patch_list_lock);
+			free_kpi(kpi, 0, skip_detach);
+			DPRINT("kaho_prepare_exit (exit) w/ free_kpi\n");
+			return;
+		}
+	}
+	spin_unlock(&kaho_patch_list_lock);
+
+	panic("kaho_prepare_exit: kpi was not found, task: %p, engine: %p\n",
+	      tsk, engine);
+}
+
+static void kaho_report_reap(struct utrace_attached_engine *engine,
+			     struct task_struct *tsk)
+{
+	DPRINT("kaho_report_reap (entry)\n");
+	kaho_prepare_exit(engine, tsk, 1);
+	DPRINT("kaho_report_reap (exit)\n");
+}
+
+static u32 kaho_report_exec(
+#ifndef NEW_UTRACE
+			    struct utrace_attached_engine *engine,
+			    struct task_struct *tsk,
+#else
+			    enum utrace_resume_action action,
+			    struct utrace_attached_engine *engine,
+			    struct task_struct *tsk,
+			    const struct linux_binfmt *fmt,
+#endif
+			    const struct linux_binprm *bprm,
+			    struct pt_regs *regs)
+{
+
+	DPRINT("kaho_report_exec (entry)\n");
+	kaho_prepare_exit(engine, tsk, 0);
+	DPRINT("kaho_report_exec (exit)\n");
+	return 0;
+}
+
+static void kaho_mem_timer(unsigned long arg)
+{
+	struct kaho_patch_info* kpi = (struct kaho_patch_info*)arg;
+	if (kpi->canceled == CANCELED) {
+		atomic_dec(&kpi->used);
+		return;
+	}
+
+	if ((kpi->nvcsw != kpi->target_task->nvcsw) ||
+	    (kpi->nivcsw != kpi->target_task->nivcsw) ){
+		up(&kpi->mem_ope_sem);
+		atomic_dec(&kpi->used);
+	}
+	else {
+		setup_timer(&kpi->timer, kaho_mem_timer, (unsigned long)kpi);
+		kpi->timer.expires = jiffies+(50*HZ/1000);
+		add_timer(&kpi->timer);
+	}
+}
+
+static void kaho_report_quiesce_mem_ope(struct kaho_patch_info* kpi)
+{
+	struct kaho_map_struct* kms;
+
+	/* memory allocation or free */
+	kms = kpi->kms;
+	/*
+	DPRINT("current: %p\n", current);
+	DPRINT("current->mm: %p\n", current->mm);
+	DPRINT("&current->mm->mmap_sem: %p\n", &current->mm->mmap_sem);
+	*/
+	down_write(&current->mm->mmap_sem);
+	if (atomic_read(&kpi->state) == KAHO_STATE_MAPPING) {
+		kms->act_addr = do_mmap(kms->filp, kms->addr, kms->length,
+					kms->prot, kms->flag, kms->offset);
+	} else {
+		kms->act_addr = do_munmap(current->mm, kms->addr, kms->length);
+	}
+	up_write(&current->mm->mmap_sem);
+
+	/* wake up the mem alloc ioctl after switing of the current task*/
+	atomic_inc(&kpi->used);
+	kpi->nvcsw = current->nvcsw;
+	kpi->nivcsw = current->nivcsw;
+	setup_timer(&kpi->timer, kaho_mem_timer, (unsigned long)kpi);
+	kpi->timer.expires = jiffies+(10*HZ/1000);
+	add_timer(&kpi->timer);
+}
+
+#ifndef NEW_UTRACE
+static u32 kaho_report_quiesce(struct utrace_attached_engine *engine,
+			       struct task_struct *tsk)
+#else
+static u32 kaho_report_quiesce(enum utrace_resume_action action,
+			       struct utrace_attached_engine *engine,
+			       struct task_struct *tsk, unsigned long envet)
+#endif
+{
+	int stat;
+	unsigned long flags = 0;
+	struct kaho_patch_info* kpi;
+	DPRINT("kaho_report_quiesce (entry)\n");
+	//dump_stack();
+
+	/* engine and kpi should be exist because this routine must be
+	   called with kpi->used > 0 */
+	kpi = (struct kaho_patch_info*)engine->data;
+	stat = atomic_read(&kpi->state);
+	if (!chk_stat_quiesce_main_thr(stat))
+		panic("kaho_report_quiesce: unintened call: %d\n", stat);
+
+	kaho_report_quiesce_mem_ope(kpi);
+
+	flags = engine->flags;
+	flags &= ~UTRACE_EVENT(QUIESCE);
+#ifndef NEW_UTRACE
+	flags &= ~UTRACE_ACTION_QUIESCE;
+#endif
+	if (utrace_set_flags(kpi->target_task, kpi->engine, flags) < 0) {
+		printk(KERN_ERR MSG_HEAD
+		       "Failed to set utrace flags at kaho_report_quiesce\n");
+	}
+	DPRINT("kaho_report_quiesce (exit)\n");
+#ifndef NEW_UTRACE
+	return 0;
+#else
+	return UTRACE_RESUME;
+#endif
+}
+
+static const struct utrace_engine_ops kaho_utrace_ops =
+{
+	.report_exec = kaho_report_exec,
+	.report_quiesce = kaho_report_quiesce,
+	.report_reap = kaho_report_reap,
+};
+
+/* ------------------------------------------------------------------
+ * I/O control functions
+ * ---------------------------------------------------------------- */
+static int ioctl_make_patch(void __user *uaddr)
+{
+	int i, nr_used;
+	int handle = 0;
+	unsigned long flags = 0;
+	struct kaho_make_patch mp;
+	struct kaho_patch_info* kpi;
+	int ret = 0;
+
+	DPRINT("ioctl_make_patch (entry)\n");
+	/* Get the request data */
+	if (copy_from_user(&mp, uaddr, sizeof(mp)) != 0) {
+		printk(KERN_ERR MSG_HEAD "Failed to copy mp\n");
+		ret = -EFAULT;
+		goto out;
+	}
+
+	/* Parameter check */
+	if (mp.nr_sub_patch <= 0 || mp.nr_sub_patch > KAHO_MAX_NR_SUB) {
+		printk(KERN_INFO MSG_HEAD
+		       "sub patch id is illegal: %d\n", mp.nr_sub_patch);
+		ret =  -EINVAL;
+		goto out;
+	}
+
+	/* Check the number of available handle */
+	spin_lock(&kaho_patch_list_lock);
+	nr_used = atomic_read(&nr_patch);
+	if (nr_used >= KAHO_MAX_NR_PATCH) {
+		ret =  -ENOSPC;
+		spin_unlock(&kaho_patch_list_lock);
+		printk(KERN_INFO MSG_HEAD
+		       "The number of patches reaches maximum: %d\n", nr_used);
+		goto out;
+	}
+
+	/* Find the available handle
+		(Note: The number of handle beings from 1) */
+	handle = get_handle();
+	if (handle <= 0) {
+		ret =  -EFAULT;
+		spin_unlock(&kaho_patch_list_lock);
+		printk(KERN_ERR MSG_HEAD "Finding handle was failed\n");
+		goto out;
+	}
+	atomic_inc(&nr_patch);
+	spin_unlock(&kaho_patch_list_lock);
+
+	/* Allocate memory */
+	kpi = kmalloc(sizeof(struct kaho_patch_info), GFP_KERNEL);
+	if (kpi == NULL) {
+		printk(KERN_ERR MSG_HEAD
+		       "Failed to kmalloc() for kaho_patch_info \n");
+		ret =  -EFAULT;
+		goto err0;
+	}
+
+	/* Allocate memory for sub patches */
+	kpi->items = kmalloc(mp.nr_sub_patch*sizeof(struct kaho_patch_item),
+			     GFP_KERNEL);
+	if (kpi->items == NULL) {
+		printk(KERN_ERR MSG_HEAD
+		       "Failed to kmalloc() for kaho_patch_item\n");
+		ret =  -EFAULT;
+		goto err1;
+	}
+
+	/* Initialize members */
+	atomic_set(&kpi->state, KAHO_STATE_ENTRY);
+	atomic_set(&kpi->used, 0);
+	init_MUTEX(&kpi->sem);
+	kpi->handle = handle;
+	kpi->nr_sub_patch = mp.nr_sub_patch;
+	kpi->kms = NULL;
+	init_MUTEX(&kpi->mem_ope_sem);
+
+	for (i = 0; i < kpi->nr_sub_patch; i++) {
+		kpi->items[i].patch_type = KAHO_PTYPE_UNKNOWN;
+		kpi->items[i].patch_addr = (unsigned long)NULL;
+		kpi->items[i].flags = 0;
+	}
+	kpi->canceled = !CANCELED;
+
+#ifdef CONFIG_KAHO_RT
+	INIT_LIST_HEAD(&kpi->chk_list);
+	INIT_LIST_HEAD(&kpi->thr_list);
+	spin_lock_init(&kpi->list_lock);
+	kpi->jmp_code_size = -1;
+	init_MUTEX(&kpi->rt_sem);
+#endif
+
+	/* Get task_struct of the target */
+	read_lock(&tasklist_lock);
+	kpi->target_task = find_task_by_pid(mp.target_pid);
+	if (kpi->target_task == NULL) {
+		read_unlock(&tasklist_lock);
+		printk(KERN_INFO MSG_HEAD
+		       "Failed to get the target with pid %d\n", mp.target_pid);
+		ret = -ENOENT;
+		goto err1a;
+	}
+	get_task_struct(kpi->target_task);
+	read_unlock(&tasklist_lock);
+
+	/* init */
+	kpi->exec_id = kpi->target_task->self_exec_id;
+
+	/* check status of the target */
+	if (kpi->target_task->exit_state) {
+		printk(KERN_INFO MSG_HEAD
+		       "Target task is now exiting: %ld\n",
+		       (long)kpi->target_task->exit_state);
+		ret = -EINVAL;
+		goto err1b;
+	}
+
+	/* add list with confirmation again */
+	atomic_inc(&kpi->used);
+	down(&kpi->sem);
+	spin_lock(&kaho_patch_list_lock);
+	list_add(&kpi->list, &kaho_patch_list_head);
+	spin_unlock(&kaho_patch_list_lock);
+
+	/* Attach to the target */
+	kpi->engine = utrace_attach(kpi->target_task, UTRACE_ATTACH_CREATE,
+				    &kaho_utrace_ops,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
+				    (unsigned long)
+#endif
+				    kpi);
+
+
+	if (IS_ERR(kpi->engine) || kpi->engine == NULL){
+		printk(KERN_ERR MSG_HEAD "Failed to utrace_attach\n");
+		/* delete kpi from the list */
+		spin_lock(&kaho_patch_list_lock);
+		list_del(&kpi->list);
+		spin_unlock(&kaho_patch_list_lock);
+		ret = -EFAULT;
+		goto err2;
+	}
+
+	flags |= UTRACE_EVENT(EXEC);
+	flags |= UTRACE_EVENT(REAP);
+	if (utrace_set_flags(kpi->target_task, kpi->engine, flags) < 0) {
+		printk(KERN_ERR MSG_HEAD "Failed to set utrace flags\n");
+		if (utrace_detach(kpi->target_task, kpi->engine) < 0)
+			printk(KERN_ERR MSG_HEAD "Failed to utrace_detach()\n");
+
+		/* delete kpi from the list */
+		spin_lock(&kaho_patch_list_lock);
+		list_del(&kpi->list);
+		spin_unlock(&kaho_patch_list_lock);
+		ret = -EFAULT;
+		goto err2;
+	}
+
+	put_kpi(kpi);
+	put_task_struct(kpi->target_task);
+
+	/* return the handle to user application */
+	mp.handle = handle;
+	if (copy_to_user(uaddr, &mp, sizeof(mp)) != 0) {
+		printk(KERN_ERR MSG_HEAD "Failed to copy mp\n");
+		ret = -EFAULT;
+		goto err1a;
+	}
+
+	DPRINT("ioctl_make_patch (exit)\n");
+	return 0;
+
+err2:
+	put_kpi(kpi);
+err1b:
+	put_task_struct(kpi->target_task);
+err1a:
+	kfree(kpi->items);
+err1:
+	kfree(kpi);
+err0:
+	atomic_dec(&nr_patch);
+	put_handle(handle);
+out:
+	DPRINT("ioctl_make_patch (exit:out0)\n");
+	return ret;
+}
+
+static int ioctl_map_ope(void __user *uaddr, int ope)
+{
+	unsigned long flags = 0;
+	struct kaho_map_opt kmo;
+	struct kaho_patch_info* kpi = NULL;
+	int ret = 0;
+	int st;
+	struct file *filp = NULL;
+	struct kaho_map_struct* kms;
+
+	DPRINT("ioctl_map_patch (entry)\n");
+	/* Get the argument */
+	if (copy_from_user(&kmo, uaddr, sizeof(kmo)) != 0) {
+		printk(KERN_ERR MSG_HEAD "Failed to copy kmo\n");
+		ret = -EFAULT;
+		goto err0;
+	}
+
+	/* Get memory for memory allocation */
+	kms = kmalloc(sizeof(struct kaho_map_struct), GFP_KERNEL);
+	if (kms == NULL) {
+		printk(KERN_ERR MSG_HEAD
+		       "Failed to kmolloc() for kaho_map_patch_struct\n");
+		ret =  -EFAULT;
+		goto err0;
+	}
+
+	/* Open the patch file */
+	if (kmo.filename != NULL) {
+		filp = filp_open( kmo.filename, O_RDONLY, 0);
+		if (IS_ERR(filp)) {
+			ret = -ENOENT;
+			goto err1;
+		}
+	}
+
+	/* Search the patch descripter */
+	kpi = get_kpi(kmo.handle);
+	if (kpi == NULL) {
+		ret = -EINVAL;
+		goto err2;
+	}
+
+	/* State check and setting new state */
+	st = atomic_read(&kpi->state);
+	if (ope == OPE_MAP) {
+		if (!chk_stat_map_ope_alloc(st)) {
+			printk(KERN_INFO MSG_HEAD
+			       "received map request "
+			       "in the state: %d\n", st);
+			ret = -EPERM;
+			goto err3;
+		}
+		atomic_set(&kpi->state, KAHO_STATE_MAPPING);
+	} else {
+		if (!chk_stat_map_ope_free(st)) {
+			printk(KERN_INFO MSG_HEAD
+				"Unmap request received in the state: %d\n", st);
+			ret = -EPERM;
+			goto err3;
+		}
+		atomic_set(&kpi->state, KAHO_STATE_UNMAPPING);
+	}
+
+	/* Copy parameters */
+	kms->filp = filp;
+	kms->addr   = kmo.addr;
+	kms->length = kmo.length;
+	kms->offset = kmo.offset;
+	kms->prot   = kmo.prot;
+	kms->flag   = kmo.flag;
+	init_MUTEX_LOCKED(&kpi->mem_ope_sem);
+	kpi->kms = kms;
+	//printk(KERN_ERR "filp: %p, addr: %lx, len: %lx, off: %lx, prot: %lx, 
+
+	/* Prepare operation for on the application context */
+	flags = kpi->engine->flags;
+#ifndef NEW_UTRACE
+	flags |= UTRACE_ACTION_QUIESCE;
+#endif
+	flags |= UTRACE_EVENT(SIGNAL);
+	flags |= UTRACE_EVENT(QUIESCE);
+	if (utrace_set_flags(kpi->target_task, kpi->engine, flags) < 0) {
+		printk(KERN_ERR MSG_HEAD "Failed to set utrace flags\n");
+		ret = -EFAULT;
+		goto err3;
+	}
+#ifdef NEW_UTRACE
+	if (utrace_control(kpi->target_task, kpi->engine, UTRACE_INTERRUPT) < 0) {
+		printk(KERN_ERR MSG_HEAD "Failed to call UTRACE_REPORT\n");
+		ret = -EFAULT;
+		goto err3;
+	}
+#endif
+
+	/* Sleep until the memory be obtained */
+	down(&kpi->mem_ope_sem);
+	if( kpi->canceled == CANCELED ){
+		ret = -EINVAL;
+		goto err3;
+	}
+
+	/* check the result */
+	kmo.act_addr = kms->act_addr;
+	if (IS_ERR((void*)kmo.act_addr)) {
+		printk(KERN_ERR MSG_HEAD "Failed to mmap or unmmap\n");
+		ret = kmo.act_addr;
+		goto err3;
+	}
+
+	/* return the result to the user application */
+	if (copy_to_user(uaddr, &kmo, sizeof(kmo)) != 0) {
+		printk(KERN_ERR MSG_HEAD "Failed to copy kmo\n");
+		ret = -EFAULT;
+		goto err3;
+	}
+
+	/* release the memory */
+	kfree(kpi->kms);
+	kpi->kms = NULL;
+
+	/* set current patch state */
+	if (ope == OPE_MAP)
+		atomic_set(&kpi->state, KAHO_STATE_MAPPED);
+	else
+		atomic_set(&kpi->state, KAHO_STATE_UNMAPPED);
+
+	put_kpi(kpi);
+	if (filp)
+		filp_close(filp, current->files);
+
+	DPRINT("ioctl_map_patch (exit)\n");
+	return 0;
+	
+err3:
+	atomic_set(&kpi->state, KAHO_STATE_ERROR);
+	kpi->kms = NULL;
+	put_kpi(kpi);
+
+err2:
+	if (filp)
+		filp_close(filp, current->files);
+err1:
+	if (kpi)
+		kfree(kms);
+err0:
+	DPRINT("ioctl_mem_ope (exit:err0)\n");
+	return ret;
+}
+
+static int ioctl_load_patch(void __user *uaddr)
+{
+	int ret = 0;
+	struct kaho_load_patch klp;
+	struct kaho_patch_info* kpi = NULL;
+	struct kaho_patch_item* pitem;
+	struct kaho_patch_item pitem_none;
+	int st;
+
+	DPRINT("ioctl_load_patch (entry)\n");
+	/* Get the arguments */
+	if (copy_from_user(&klp, uaddr, sizeof(klp)) != 0) {
+		printk(KERN_ERR MSG_HEAD "Failed to copy klp\n");
+		ret = -EFAULT;
+		goto err0;
+	}
+
+	/* Search from the patch */
+	kpi = get_kpi(klp.handle);
+	if (kpi == NULL) {
+		ret = -EINVAL;
+		goto err0;
+	}
+
+	/* Check if arguments are valid */
+	if (valid_patch_type(klp.patch_type) < 0) {
+		printk(KERN_ERR MSG_HEAD
+		       "Unknown patch type: %d\n", klp.patch_type);
+		ret = -EINVAL;
+		goto err1;
+	}
+
+	/* Check if parameter is correct */
+	if (klp.patch_type != KAHO_PTYPE_NONE)  {
+		if (klp.sub_patch_id <= 0 ||
+		    klp.sub_patch_id > kpi->nr_sub_patch) {
+			printk(KERN_INFO MSG_HEAD
+			       "sub_patch_id id is illegal: %d\n",
+			       klp.sub_patch_id);
+			ret = -EINVAL;
+			goto err1;
+		}
+	}
+
+	/* State check and setting new state */
+	st = atomic_read(&kpi->state);
+	if (!chk_stat_load(st) &&
+	    !(klp.patch_type == KAHO_PTYPE_VAR && st == KAHO_STATE_ENTRY)){
+
+		printk(KERN_INFO MSG_HEAD
+		       "load patch request received in the state: %d\n", st);
+		ret = -EPERM;
+		if (st == KAHO_STATE_ACTIVE)
+			goto err0a;
+		goto err1;
+	}
+	atomic_set(&kpi->state, KAHO_STATE_LOADING);
+
+	/* Copy data except KAHO_PTYPE_NONE */
+	if (klp.patch_type != KAHO_PTYPE_NONE)
+		pitem = &(kpi->items[klp.sub_patch_id-1]);
+	else
+		pitem = &pitem_none;
+	pitem->patch_type  = klp.patch_type;
+	pitem->target_addr = klp.target_addr;
+	pitem->patch_size  = klp.patch_size;
+#ifdef CONFIG_KAHO_RT
+	atomic_set(&pitem->backup_done, 0);
+#endif
+	if (klp.patch_type == KAHO_PTYPE_VAR) {
+		/* We allocate buffer region which has twice the size of
+		   patched data to store original data */
+		pitem->patch_addr = (unsigned long)
+				    kmalloc(2*klp.patch_size, GFP_KERNEL);
+		if ((void*)pitem->patch_addr == NULL) {
+			printk(KERN_ERR MSG_HEAD
+			       "patch_addr is NULL, size: %ld\n",
+			       2*klp.patch_size);
+			ret = -EFAULT;
+			goto err1;
+		}
+		if (copy_from_user((void*)pitem->patch_addr,
+		                   (void*)klp.src_addr,
+				   pitem->patch_size) != 0) {
+			printk(KERN_ERR MSG_HEAD "Failed to copy form user\n");
+			kfree((void*)pitem->patch_addr);
+			ret = -EFAULT;
+			goto err1;
+		}
+	}
+	else
+		pitem->patch_addr = klp.patch_addr;
+
+	if (klp.patch_type != KAHO_PTYPE_VAR &&
+	    pitem->patch_size > 0 && klp.src_addr != 0)
+		__WRITE_MEM(kpi->target_task, pitem->patch_addr,
+			    (void*)klp.src_addr, pitem->patch_size,
+			    kpi->exec_id,
+			    "(ioctl_load_patch)\n", ret = -EINVAL; goto err1);
+
+	/* return */
+	if (klp.patch_type != KAHO_PTYPE_NONE)
+		atomic_set(&kpi->state, KAHO_STATE_LOADED);
+	else
+		atomic_set(&kpi->state, st);
+	put_kpi(kpi);
+	DPRINT("ioctl_load_patch (exit)\n");
+	return ret;
+
+err1:
+	atomic_set(&kpi->state, KAHO_STATE_ERROR);
+err0a:
+	put_kpi(kpi);
+err0:
+	DPRINT("ioctl_load_patch (err.exit)\n");
+	return ret;
+}
+
+#ifdef CONFIG_KAHO_RT
+static void kaho_report_reap_thr(struct utrace_attached_engine *engine,
+				 struct task_struct *tsk);
+
+#ifndef NEW_UTRACE
+static u32 kaho_report_quiesce_thr(struct utrace_attached_engine *engine,
+				   struct task_struct *tsk);
+
+static u32 kaho_report_clone_thr(struct utrace_attached_engine *engine,
+				 struct task_struct *parent,
+				 unsigned long clone_flags,
+				 struct task_struct *child);
+#else
+static u32 kaho_report_quiesce_thr(enum utrace_resume_action action,
+				   struct utrace_attached_engine *engine,
+				   struct task_struct *tsk,
+				   unsigned long event);
+
+static u32 kaho_report_clone_thr(enum utrace_resume_action action,
+				 struct utrace_attached_engine *engine,
+				 struct task_struct *parent,
+				 unsigned long clone_flags,
+				 struct task_struct *child);
+#endif
+
+static const struct utrace_engine_ops kaho_utrace_ops_chk_thr =
+{
+	.report_reap  = kaho_report_reap_thr,
+	.report_clone = kaho_report_clone_thr,
+	.report_quiesce = kaho_report_quiesce_thr,
+};
+
+static struct kaho_thr_list* alloc_ktl(struct kaho_patch_info* kpi,
+				       struct task_struct* task)
+{
+	struct kaho_thr_list* ktl;
+	int flags = 0;
+	int ret;
+
+	DPRINT("alloc_ktl (entry): kpi: %p\n", kpi);
+
+	ktl = kmalloc(sizeof(struct kaho_thr_list), GFP_KERNEL);
+	if (ktl == NULL)
+		return NULL;
+
+	/* Initialize */
+	ktl->task = task;
+	ktl->kpi = kpi;
+	atomic_set(&ktl->checked, THR_NO_MARK);
+	atomic_set(&ktl->used, 0);
+	ktl->sem_upped = -1;
+
+	/* attach the thread */
+	ktl->engine = utrace_attach(ktl->task, UTRACE_ATTACH_CREATE,
+				    &kaho_utrace_ops_chk_thr,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
+				    (unsigned long)
+#endif
+				    ktl);
+
+	if (ktl->engine == ERR_PTR(-ESRCH)) {
+		/* target thread is dead */
+		atomic_set(&ktl->checked, THR_CHK_ERR);
+		goto out;
+	}
+	else if (IS_ERR(ktl->engine) || ktl->engine == NULL){
+		printk(KERN_ERR MSG_HEAD "Failed to utrace_attach\n");
+		goto err;
+	}
+
+	/* set events */
+	flags |= UTRACE_EVENT(CLONE);
+	flags |= UTRACE_EVENT(REAP);
+	//DPRINT("ktl: %p, pid: %d\n", ktl, task->pid);
+	//DPRINT("task: %p, engine: %p, flags: %08x\n", ktl->task, ktl->engine, flags);
+	ret = utrace_set_flags(ktl->task, ktl->engine, flags);
+	if (ret == -EALREADY){
+		/* target thread is dead */
+		atomic_set(&ktl->checked, THR_CHK_ERR);
+		DPRINT("safety_check_each_thr: EALREADY\n");
+	}
+	else if (ret < 0) {
+		atomic_set(&ktl->checked, THR_CHK_ERR);
+		printk(KERN_ERR MSG_HEAD "Failed to set utrace flags "
+					 "(alloc_ktl)\n");
+		if (utrace_detach(ktl->task, ktl->engine) < 0) {
+			printk(KERN_ERR MSG_HEAD
+			       "Failed to utrace_detach (alloc_ktl)\n");
+		}
+		goto err;
+	}
+out:
+	DPRINT("alloc_ktl (exit)\n");
+	return ktl;
+
+err:
+	kfree(ktl);
+	return NULL;
+}
+
+#ifndef NEW_UTRACE
+static u32 kaho_report_clone_thr(struct utrace_attached_engine *engine,
+				 struct task_struct *parent,
+				 unsigned long clone_flags,
+				 struct task_struct *child)
+#else
+static u32 kaho_report_clone_thr(enum utrace_resume_action action,
+				 struct utrace_attached_engine *engine,
+				 struct task_struct *parent,
+				 unsigned long clone_flags,
+				 struct task_struct *child)
+#endif
+{
+	int found = 0;
+	struct kaho_thr_list* ktl = (struct kaho_thr_list*)engine->data;
+	struct kaho_patch_info* kpi = ktl->kpi;
+	struct list_head *pos, *next;
+	
+	DPRINT("kaho_report_clone_thr (entry)\n");
+	/* check if ktl is including in the thread list */
+	spin_lock(&kpi->list_lock);
+	list_for_each_safe(pos, next, &kpi->thr_list) {
+		struct kaho_thr_list* _ktl;
+		_ktl = list_entry(pos, struct kaho_thr_list, thr_list);
+		if (ktl == _ktl){
+			atomic_inc(&ktl->used);
+			found = 1;
+		}
+	}
+	if (found == 0) {
+		/* This condition may cause when another CPU runs
+		   delete_thread_list() at the same time */
+		spin_unlock(&kpi->list_lock);
+		return 0;
+	}
+	spin_unlock(&kpi->list_lock);
+
+	/* Thread: the new thread is added to thr_list */
+	if (clone_flags & CLONE_THREAD) {
+		struct kaho_thr_list* new_ktl = alloc_ktl(kpi, child);
+		if (new_ktl != NULL) {
+			if (atomic_read(&new_ktl->checked) == THR_CHK_ERR) {
+				kfree(new_ktl);
+			}
+			else {
+				spin_lock(&kpi->list_lock);
+				list_add(&new_ktl->thr_list, &kpi->thr_list);
+				spin_unlock(&kpi->list_lock);
+			}
+		}
+		else {
+			printk(KERN_ERR MSG_HEAD "Failed to alloc_ktl\n");
+		}
+	}
+	/* Process: check if code at target address has changed */
+	else {
+		int i, ret;
+		int diff = 0;
+		unsigned char buf[trap_code_size];
+		struct kaho_patch_item* pitem = &(kpi->items[0]);
+
+		/* If backup_done is 0, preparation of Copy-On-Write has
+		   completed before implant of int3. That is, the child
+		   process does not have code that includes int3. */
+		if (atomic_read(&pitem->backup_done) == 0)
+			goto out;
+		
+		/* check the code at target address */
+		__READ_MEM(child, pitem->target_addr, buf, trap_code_size,
+			   kpi->exec_id, "(kaho_report_clone_thr:read)\n",
+			   goto err);
+		for (i = 0; i < trap_code_size; i++) {
+			if (buf[i] != pitem->backup[i]) {
+				diff = 1;
+				break;
+			}
+		}
+		/* rewrite if the code has been changed */
+		if (diff) {
+			DPRINT("The code at target address is different\n");
+			__WRITE_MEM(child, pitem->target_addr, pitem->backup,
+				    trap_code_size, kpi->exec_id,
+				    "(kaho_report_clone_thr:write)\n",
+				    goto err);
+		}
+		else
+			DPRINT("The code at target address is the same\n");
+	}
+out:
+	atomic_dec(&ktl->used);
+	DPRINT("kaho_report_clone_thr (exit)\n");
+	return 0;
+err:
+	atomic_dec(&ktl->used);
+	return -EFAULT;
+}
+
+static void delete_chk_list(struct kaho_thr_list* ktl)
+{
+	struct list_head *pos;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+	struct list_head *next;
+#endif
+	struct kaho_thr_list* __ktl;
+	list_for_each_safe_rcu(pos, next, &ktl->kpi->chk_list) {
+		__ktl = list_entry(pos, struct kaho_thr_list, chk_list);
+		if (__ktl == ktl) {
+			list_del_rcu(&ktl->chk_list);
+			break;
+		}
+	}
+}
+
+static void __kaho_report_reap_thr(struct kaho_thr_list* ktl)
+{
+	int st = atomic_read(&ktl->kpi->state);
+	if (st == KAHO_STATE_IN_ACT_RT2 || st == KAHO_STATE_IN_DEACT_RT2) {
+		if (ktl->sem_upped == 0) {
+			up(&ktl->kpi->rt_sem);
+			ktl->sem_upped = 1;
+			DPRINT("rt_sem was upped in __kaho_report_reap_thr\n");
+		}
+		if (ktl->sem_upped >= 0)
+			delete_chk_list(ktl);
+	}
+	list_del(&ktl->thr_list);
+	call_rcu(&ktl->rcu_head, free_ktl);
+}
+
+static void kaho_report_reap_thr(struct utrace_attached_engine *engine,
+				 struct task_struct *tsk)
+{
+	struct list_head *pos;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+	struct list_head *next;
+#endif
+	struct kaho_thr_list* ktl = (struct kaho_thr_list*)engine->data;
+	struct kaho_patch_info* kpi = ktl->kpi;
+
+	DPRINT("kaho_report_reap_thr (entry)\n");
+
+	spin_lock(&kpi->list_lock);
+	list_for_each_safe_rcu(pos, next, &kpi->thr_list) {
+		struct kaho_thr_list* _ktl;
+		_ktl = list_entry(pos, struct kaho_thr_list, thr_list);
+		if (_ktl == ktl) {
+			__kaho_report_reap_thr(ktl);
+			spin_unlock(&kpi->list_lock);
+			return;
+		}
+	}
+	spin_unlock(&kpi->list_lock);
+	DPRINT("kaho_report_reap_thr (exit)\n");
+}
+
+static int ktl_contain(struct kaho_patch_info* kpi, struct task_struct* task)
+{
+	struct kaho_thr_list* ktl;
+	spin_lock(&kpi->list_lock);
+	list_for_each_entry(ktl, &kpi->thr_list, thr_list) {
+		if (ktl->task == task) {
+			spin_unlock(&kpi->list_lock);
+			return 1;
+		}
+	}
+	spin_unlock(&kpi->list_lock);
+	return 0;
+}
+
+static int make_thread_list(struct kaho_patch_info* kpi)
+{
+	struct task_struct* task;
+	struct kaho_thr_list *ktl, *n;
+	DPRINT("make_thread_list (entry)\n");
+loop:
+	/* loop for all threads in this process */
+	read_lock(&tasklist_lock);
+	task = next_thread(kpi->target_task);
+	do {
+		if (!ktl_contain(kpi, task)) {
+			DPRINT("pid: %d\n", task->pid);
+			get_task_struct(task);
+			read_unlock(&tasklist_lock);
+			/* get allocated ktl that has utrace engine that
+			   is attaching to the thread */
+			ktl = alloc_ktl(kpi, task);
+			put_task_struct(task);
+			if (ktl == NULL) 
+				return -EFAULT;
+			/* add ktl to thread list */
+			spin_lock(&kpi->list_lock);
+			list_add(&ktl->thr_list, &kpi->thr_list);
+			spin_unlock(&kpi->list_lock);
+			goto loop;
+		}
+		/* get next thread */
+		task = next_thread(task);
+	} while (task != next_thread(kpi->target_task));
+	read_unlock(&tasklist_lock);
+
+	/* delete dead tasks */
+	spin_lock(&kpi->list_lock);
+	list_for_each_entry_safe(ktl, n, &kpi->thr_list, thr_list) {
+		if (atomic_read(&ktl->checked) == THR_CHK_ERR) {
+			list_del(&ktl->thr_list);
+			kfree(ktl);
+		}
+	}
+	spin_unlock(&kpi->list_lock);
+
+	DPRINT("make_thread_list (exit)\n");
+	return 0;
+}
+
+static void delete_thread_list(struct kaho_patch_info* kpi)
+{
+	struct kaho_thr_list* ktl;
+	struct list_head *pos;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+	struct list_head *next;
+#endif
+	int used;
+top:
+	used = 0;
+	spin_lock(&kpi->list_lock);
+	list_for_each_safe_rcu(pos, next, &kpi->thr_list) {
+		ktl = list_entry(pos, struct kaho_thr_list, thr_list);
+		DPRINT("[del] ktl: %p, target: %p, utrace: %p\n", ktl, ktl->task, ktl->task->utrace);
+
+		/* If the ktl is using by kaho_report_clone_thr(),
+		   kaho_report_quiesce_thr(), or, kaho_report_reap_thr(),
+		   deletion of the ktl is put off */
+		if (atomic_read(&ktl->used) > 0){
+			used++;
+			continue;
+		}
+
+		/* detach, delete from list, and, free it */
+		if (utrace_detach(ktl->task, ktl->engine) < 0) {
+			printk(KERN_ERR MSG_HEAD
+			       "Failed to utrace_detach (delete_thread_list)\n");
+		}
+		delete_chk_list(ktl);
+		list_del_rcu(&ktl->thr_list);
+		call_rcu(&ktl->rcu_head, free_ktl);
+	}
+	spin_unlock(&kpi->list_lock);
+
+	if (used > 0) {
+		/* waiting for a while */
+		kaho_sleep(10);
+		goto top;
+	}
+}
+
+static int safety_check(struct kaho_patch_info* kpi);
+
+static int pre_proc_act_rt(struct kaho_patch_info* kpi,
+			   struct kaho_std_opt* kso, int op)
+{
+	int ret, bkup;
+	struct kaho_patch_item* pi;
+
+	DPRINT("pre_proc_act_rt (entry)\n");
+
+	/* Check parameters */
+	pi = &(kpi->items[0]);
+	if (op == REQ_ACT_RT) {
+		pi->flags |= KAHO_RT_PATCH;
+		if (kpi->nr_sub_patch != 1) {
+			printk(KERN_INFO MSG_HEAD
+			       "# of sub patches must be one in RT mode.\n");
+			ret = -EPERM;
+			goto err1;
+		}
+
+		if (pi->patch_type != KAHO_PTYPE_FUNC) {
+			printk(KERN_INFO MSG_HEAD
+			       "Only FUNC patch is supported in RT mode.\n");
+			ret = -EPERM;
+			goto err1;
+		}
+
+		/* Set jump code size for backup */
+		kpi->jmp_code_size = arch_get_jump_code_size(kpi, 0);
+	}
+
+	/* make check sheet */
+	ret = make_thread_list(kpi);
+	if (ret < 0) {
+		printk(KERN_ERR MSG_HEAD "Failed to make_thread_list\n");
+		ret = -EFAULT;
+		goto err1;
+	}
+
+	/* add to list */
+	spin_lock(&kaho_trap_list_lock);
+	list_add_rcu(&kpi->trap_list, &kaho_trap_list_head);
+	spin_unlock(&kaho_trap_list_lock);
+
+	if (op == REQ_ACT_RT){
+		bkup = CODE_BKUP;
+		atomic_set(&kpi->state, KAHO_STATE_IN_ACT_RT1);
+	}
+	else {
+		bkup = NOT_CODE_BKUP;
+		atomic_set(&kpi->state, KAHO_STATE_IN_DEACT_RT1);
+	}
+
+	/* Implant trap instruction */
+	ret = arch_implant_trap(kpi, 0, bkup);
+	if (ret < 0) {
+		printk(KERN_ERR MSG_HEAD "Failed to implant trap code\n");
+		ret = -EFAULT;
+		goto err2;
+	}
+	
+	/* Safety check */
+	ret = safety_check(kpi);
+	if (ret < 0) {
+		printk(KERN_ERR MSG_HEAD "Failed to safety check\n");
+		ret = -EFAULT;
+		goto err3;
+	}
+
+	DPRINT("pre_proc_act_rt (exit)\n");
+	return 0;
+
+err3:
+	/* Restore original instruction instead of trap */
+	if (arch_implant_trap(kpi, 0, CODE_RESTORE) < 0)
+		printk(KERN_ERR MSG_HEAD "Failed to restore original code\n");
+err2:
+	/* delete trap list */
+	spin_lock(&kaho_trap_list_lock);
+	list_del_rcu(&kpi->trap_list);
+	spin_unlock(&kaho_trap_list_lock);
+err1:
+	DPRINT("pre_proc_act_rt (exit:err0)\n");
+	return ret;
+}
+
+static int post_proc_act_rt(struct kaho_patch_info* kpi)
+{
+	/* delete this kpi from trap list */
+	spin_lock(&kaho_trap_list_lock);
+	list_del_rcu(&kpi->trap_list);
+	spin_unlock(&kaho_trap_list_lock);
+	return 0;
+}
+#endif
+
+static int __ioctl_activate(void __user *uaddr, int op)
+{
+	int i, ret, st;
+	struct kaho_std_opt kso;
+	struct kaho_patch_info* kpi;
+	struct kaho_patch_item* pitem;
+
+	DPRINT("__ioctl_activate (entry)\n");
+	/* Get the arguments */
+	if (copy_from_user(&kso, uaddr, sizeof(kso)) != 0) {
+		ret = -EFAULT;
+		printk(KERN_ERR MSG_HEAD "Failed to copy kso\n");
+		goto err0;
+	}
+
+	/* Search kpi */
+	kpi = get_kpi(kso.handle);
+	if (kpi == NULL) {
+		ret = -EINVAL;
+		goto err0;
+	}
+#ifdef CONFIG_KAHO_RT
+	if (op == REQ_DEACT && (kpi->items[0].flags & KAHO_RT_PATCH))
+		op = REQ_DEACT_RT;
+#endif
+	/* State check and setting new state */
+	st = atomic_read(&kpi->state);
+	do {
+		if (op == REQ_ACT) {
+			if (chk_stat_activate(st)) {
+				atomic_set(&kpi->state, KAHO_STATE_IN_ACT);
+				break;
+			}
+		}
+#ifdef CONFIG_KAHO_RT
+		else if (op == REQ_ACT_RT) {
+			if (chk_stat_activate(st)) {
+				atomic_set(&kpi->state, KAHO_STATE_IN_ACT_RT0);
+				break;
+			}
+		}
+		else if (op == REQ_DEACT_RT) {
+			if (chk_stat_deactivate(st)) {
+				atomic_set(&kpi->state,
+					   KAHO_STATE_IN_DEACT_RT0);
+				break;
+			}
+		}
+#endif
+		else if (op == REQ_DEACT) {
+			if (chk_stat_deactivate(st)) {
+				atomic_set(&kpi->state, KAHO_STATE_IN_DEACT);
+				break;
+			}
+		}
+		else
+			panic("ioctl_activate: unintended op: %d\n", op);
+
+		printk(KERN_INFO MSG_HEAD "invalid state: op: %d, st:%d\n",
+					  op, st);
+		ret = -EPERM;
+		if (st == KAHO_STATE_ACTIVE)
+			goto err0a;
+		goto err1;
+	} while (0);
+
+	/* check parameters */
+	for (i = 0; i < kpi->nr_sub_patch; i++) {
+		pitem = &(kpi->items[i]);
+		pitem->flags |= kso.flags;
+		if (valid_patch_type(pitem->patch_type) < 0) {
+			printk(KERN_ERR MSG_HEAD
+			       "Unknown patch type: %d\n", pitem->patch_type);
+			ret = -EFAULT;
+			goto err1;
+		}
+	}
+
+#ifdef CONFIG_KAHO_RT
+	if (op == REQ_ACT_RT || op == REQ_DEACT_RT) {
+		ret = pre_proc_act_rt(kpi, &kso, op);
+		if (ret < 0)
+			goto err1;
+	}
+#endif
+	/* Write code and data */
+	for (i = 0; i < kpi->nr_sub_patch; i++) {
+		pitem = &(kpi->items[i]);
+		if (op == REQ_ACT || op == REQ_ACT_RT) {
+			ret = arch_activate(kpi, i);
+		} else {
+			int backup_len = 0;
+			unsigned char* src = NULL;
+			unsigned long dst = pitem->target_addr;
+
+			if (pitem->patch_type == KAHO_PTYPE_FUNC) {
+				backup_len = arch_get_jump_code_size(kpi, i);
+				src = pitem->backup;
+			}
+			else if (pitem->patch_type == KAHO_PTYPE_VAR) {
+				backup_len = pitem->patch_size;
+				src = &((char*)pitem->patch_addr)[backup_len];
+			}
+			else if (pitem->patch_type == KAHO_PTYPE_POINTER) {
+				backup_len = sizeof(void*);
+				src = pitem->backup;
+			}
+			ret = arch_deactivate(kpi, dst, src, backup_len, i);
+		}
+		if (ret < 0)
+			goto err1;
+	}
+
+#ifdef CONFIG_KAHO_RT
+	if (op == REQ_ACT_RT || op == REQ_DEACT_RT)
+		post_proc_act_rt(kpi);
+#endif
+	/* set status and return */
+	if (op == REQ_ACT)
+		atomic_set(&kpi->state, KAHO_STATE_ACTIVE);
+#ifdef CONFIG_KAHO_RT
+	else if (op == REQ_ACT_RT)
+		atomic_set(&kpi->state, KAHO_STATE_ACTIVE);
+#endif
+	else
+		atomic_set(&kpi->state, KAHO_STATE_DEACTIVE);
+
+#ifdef CONFIG_KAHO_RT
+	delete_thread_list(kpi);
+#endif
+
+	put_kpi(kpi);
+	DPRINT("__ioctl_activate (exit)\n");
+	return 0;
+
+err1:
+	atomic_set(&kpi->state, KAHO_STATE_ERROR);
+#ifdef CONFIG_KAHO_RT
+	/* delete thread list */
+	delete_thread_list(kpi);
+#endif
+
+err0a:
+	put_kpi(kpi);
+err0:
+	DPRINT("__ioctl_activate (exit:err)\n");
+	return ret;
+}
+
+static int ioctl_del_patch(void __user *uaddr)
+{
+	int ret, st;
+	struct kaho_std_opt  kso;
+	struct kaho_patch_info* kpi = NULL;
+	struct kaho_patch_info* _kpi = NULL;
+	struct kaho_patch_info* n;
+
+	DPRINT("ioctl_del_patch (entry)\n");
+	/* Get the arguments */
+	if (copy_from_user(&kso, uaddr, sizeof(kso)) != 0) {
+		printk(KERN_ERR MSG_HEAD "Failed to copy kso\n");
+		ret = -EFAULT;
+		goto err0;
+	}
+
+	/* Search kpi */
+	kpi = get_kpi(kso.handle);
+	if (kpi == NULL) {
+		ret = -EINVAL;
+		goto err0;
+	}
+
+	/* State check and setting new state */
+	st = atomic_read(&kpi->state);
+	if (!chk_stat_del_patch(st)) {
+		printk(KERN_INFO MSG_HEAD
+		       "delete patch request received in the state: %d\n", st);
+		ret = -EPERM;
+		if (st == KAHO_STATE_ACTIVE)
+			goto err0a;
+		goto err1;
+	}
+	atomic_set(&kpi->state, KAHO_STATE_IN_DEL_PATCH);
+
+	/* Delete Data structure */
+	spin_lock(&kaho_patch_list_lock);
+	list_for_each_entry_safe(_kpi, n, &kaho_patch_list_head, list) {
+		if (kpi == _kpi) {
+			list_del_rcu(&kpi->list);
+			break;
+		}
+	}
+	spin_unlock(&kaho_patch_list_lock);
+	if (kpi != _kpi)
+		panic("Not found the requested kpi in the list.\n");
+
+	/* Deletion */
+	up(&kpi->sem);
+	free_kpi(kpi, 1, 0);
+
+	DPRINT("ioctl_del_patch (exit)\n");
+	return 0;
+
+err1:
+	atomic_set(&kpi->state, KAHO_STATE_ERROR);
+err0a:
+	put_kpi(kpi);
+err0:
+	return ret;
+}
+
+static int ioctl_get_info(void __user* uaddr)
+{
+	int ret;
+	struct kaho_get_info kgi;
+	struct kaho_patch_info* kpi = NULL;
+	struct kaho_patch_item* pitem;
+
+	DPRINT("ioctl_get_info (entry)\n");
+	/* Get the arguments */
+	if (copy_from_user(&kgi, uaddr, sizeof(kgi)) != 0) {
+		printk(KERN_ERR MSG_HEAD "Failed to copy kgi\n");
+		ret = -EFAULT;
+		goto err0;
+	}
+
+	/* Is request for the first target?  */
+	if (kgi.handle == 0) {
+		if (atomic_read(&nr_patch) == 0) {
+			/* There is no data */
+			kgi.pid = -1;
+			kgi.next_handle = 0;
+			goto ret;
+		}
+		rcu_read_lock();
+		kpi = list_entry(kaho_patch_list_head.next,
+		                 struct kaho_patch_info, list);
+		atomic_inc(&kpi->used);
+		rcu_read_unlock();
+		down(&kpi->sem);
+		kgi.sub_patch_id = 1;
+	}
+	else{
+		/* Search kpi */
+		kpi = get_kpi(kgi.handle);
+		if (kpi == NULL) {
+			ret = -EINVAL;
+			goto err0;
+		}
+	}
+
+	/* Check parameter */
+	if (kgi.sub_patch_id <= 0 || kgi.sub_patch_id > kpi->nr_sub_patch) {
+		printk(KERN_INFO MSG_HEAD "sub patch id is illegal: %d\n",
+					  kgi.sub_patch_id);
+		ret = -EINVAL;
+		goto err1;
+	}
+
+	/* copy data */
+	kgi.handle = kpi->handle;
+	kgi.pid = kpi->target_task->pid;
+	kgi.nr_sub_patch = kpi->nr_sub_patch;
+	kgi.state = atomic_read(&kpi->state);
+	pitem = &(kpi->items[kgi.sub_patch_id-1]);
+	kgi.patch_type = pitem->patch_type;
+	kgi.patch_addr = pitem->patch_addr;
+	kgi.patch_size = pitem->patch_size;
+	kgi.target_addr = pitem->target_addr;
+	if (kpi->list.next == &kaho_patch_list_head) {
+		/* The last info */
+		kgi.next_handle = 0;
+	}
+	else{
+		struct kaho_patch_info* __k;
+		__k = list_entry(kpi->list.next, struct kaho_patch_info, list);
+		kgi.next_handle = __k->handle;
+	}
+
+	put_kpi(kpi);
+ret:
+	/* return the results to user application */
+	if (copy_to_user(uaddr, &kgi, sizeof(kgi)) != 0) {
+		printk(KERN_ERR MSG_HEAD "Failed to copy kmo\n");
+		ret = -EFAULT;
+		goto err1;
+	}
+
+	DPRINT("ioctl_get_info (exit)\n");
+	return 0;
+
+err1:
+	put_kpi(kpi);
+
+err0:
+	DPRINT("ioctl_get_info (err0)\n");
+	return ret;
+}
+
+#if 0
+static int ioctl_cancel(void __user* uaddr)
+{
+	int ret;
+	struct kaho_patch_info* kpi = NULL;
+	struct kaho_std_opt  kso;
+
+	/* Get the arguments */
+	if (copy_from_user(&kso, uaddr, sizeof(kso)) != 0) {
+		printk(KERN_ERR MSG_HEAD "Failed to copy ka\n");
+		ret = -EFAULT;
+		goto err0;
+	}
+
+	/* Search kpi */
+	kpi = get_kpi(kso.handle);
+	if (kpi == NULL) {
+		ret = -EINVAL;
+		goto err0;
+	}
+
+	/* body */
+	/*cancel(kpi);*/
+
+	put_kpi(kpi);
+	return 0;
+
+err0:
+	return ret;
+}
+#endif
+
+/* ------------------------------------------------------------------
+ * I/O control entry
+ * ---------------------------------------------------------------- */
+static int kaho_ioctl(
+	struct inode *inode, struct file *file, u_int cmd, u_long arg)
+{
+	int ret = 0;
+	void __user *uaddr = (void __user*)arg;
+
+	switch(cmd) {
+	case KAHOCTL_MAKE_PATCH:
+		ret = ioctl_make_patch(uaddr);
+		break;
+	case KAHOCTL_MAP_PATCH:
+		ret = ioctl_map_ope(uaddr, OPE_MAP);
+		break;
+	case KAHOCTL_LOAD_PATCH:
+		ret = ioctl_load_patch(uaddr);
+		break;
+	case KAHOCTL_ACTIVATE:
+		ret = __ioctl_activate(uaddr, REQ_ACT);
+		break;
+#ifdef CONFIG_KAHO_RT
+	case KAHOCTL_ACTIVATE_RT:
+		ret = __ioctl_activate(uaddr, REQ_ACT_RT);
+		break;
+#endif
+	case KAHOCTL_DEACTIVATE:
+		ret = __ioctl_activate(uaddr, REQ_DEACT);
+		break;
+	case KAHOCTL_UNMAP_PATCH:
+		ret = ioctl_map_ope(uaddr, OPE_UNMAP);
+		break;
+	case KAHOCTL_DEL_PATCH:
+		ret = ioctl_del_patch(uaddr);
+		break;
+	case KAHOCTL_GET_INFO:
+		ret = ioctl_get_info(uaddr);
+		break;
+	/*case KAHOCTL_CANCEL:
+		ret = ioctl_cancel(uaddr);
+		break;*/
+	default:
+		printk(KERN_INFO MSG_HEAD "Unknown IOCTL: %x\n", (int)cmd);
+		ret = -ENOTTY;
+	}
+	return ret;
+}
+
+static struct file_operations kaho_fops = {
+	.owner		= THIS_MODULE,
+	.ioctl		= kaho_ioctl,
+};
+
+#ifdef CONFIG_KAHO_RT
+/* ------------------------------------------------------------------
+ * Safety check functions
+ * ---------------------------------------------------------------- */
+static int quiesce_chk_thr_valid_state(int st)
+{
+	if (st == KAHO_STATE_IN_ACT_RT2)
+		return 1;
+	if (st == KAHO_STATE_IN_DEACT_RT2)
+		return 1;
+	return 0;
+}
+
+#ifndef NEW_UTRACE
+static u32 kaho_report_quiesce_thr(struct utrace_attached_engine *engine,
+				   struct task_struct *tsk)
+#else
+static u32 kaho_report_quiesce_thr(enum utrace_resume_action action,
+				   struct utrace_attached_engine *engine,
+				   struct task_struct *tsk,
+				   unsigned long event)
+#endif
+{
+	int st, found;
+	unsigned long pc, target_addr;
+	unsigned long flags = 0;
+	struct kaho_patch_info* kpi;
+	struct kaho_thr_list* ktl;
+	struct list_head *pos;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+	struct list_head *next;
+#endif
+	DPRINT("kaho_report_quiesce_chk_thr (entry)\n");
+
+	/* engine and kpi should be exist because this routine must be
+	   called with kpi->used > 0 */
+	ktl = (struct kaho_thr_list*)engine->data;
+	kpi = ktl->kpi;
+
+	/* We check if ktl is including in the list. Because ktl may have been
+	   deleted by the kaho_report_reap_thr() or delete_thread_list() */
+	spin_lock(&kpi->list_lock);
+	list_for_each_safe_rcu(pos, next, &kpi->thr_list) {
+		struct kaho_thr_list* _ktl;
+		_ktl = list_entry(pos, struct kaho_thr_list, thr_list);
+		if (ktl == _ktl) {
+			atomic_inc(&ktl->used);
+			found = 1;
+		}
+	}
+	if (found == 0) {
+		/* This condition may cause when another CPU runs
+		   delete_thread_list() at the same time */
+		spin_unlock(&kpi->list_lock);
+		return 0;
+	}
+	spin_unlock(&kpi->list_lock);
+
+	/* If the thread has already executed trap code,
+	   we do not have to check safety by the following */
+	if (atomic_read(&ktl->checked) == THR_MARKED)
+		goto out;
+
+	st = atomic_read(&kpi->state);
+	if (!quiesce_chk_thr_valid_state(st))
+		panic("Unexpected state: %d (kaho_report_quiesce_chk_thr)\n",
+		      st);
+	if (kpi->jmp_code_size < 0)
+		panic("jmp_code_size: %d\n", kpi->jmp_code_size);
+
+	/* Check the value of program counter */
+	target_addr = kpi->items[0].target_addr;
+	pc = arch_get_pc(task_pt_regs(ktl->task));
+	DPRINT("pc[%d]: %lx\n", current->pid, pc);
+	if (pc <= target_addr || pc >= (target_addr + kpi->jmp_code_size))
+		atomic_set(&ktl->checked, THR_MARKED);
+	else
+		DPRINT("Safety check: failed\n");
+out:
+	flags = engine->flags;
+#ifndef NEW_UTRACE
+	flags &= ~UTRACE_ACTION_QUIESCE;
+#endif
+	flags &= ~UTRACE_EVENT(QUIESCE);
+	if (utrace_set_flags(ktl->task, engine, flags) < 0) {
+		printk(KERN_ERR MSG_HEAD
+		       "Failed to set utrace flags at kaho_report_quiesce\n");
+		atomic_set(&ktl->checked, THR_CHK_ERR);
+	}
+	up(&kpi->rt_sem);
+	ktl->sem_upped = 1;
+	atomic_dec(&ktl->used);
+	DPRINT("kaho_report_quiesce_chk_thr (exit)\n");
+#ifndef NEW_UTRACE
+	return 0;
+#else
+	return UTRACE_RESUME;
+#endif
+}
+
+static void safety_check_each_thr(struct kaho_patch_info* kpi,
+				  struct kaho_thr_list* ktl)
+{
+	int ret;
+	unsigned long flags;
+
+	DPRINT("safety_check_each_thr (entry)\n");
+
+	/* If the thread has already executed trap code,
+	   we do not have to check by the following */
+	if (atomic_read(&ktl->checked) == THR_MARKED)
+		goto out;
+
+	/* Request to quiescent trace */
+	flags = ktl->engine->flags;
+#ifndef NEW_UTRACE
+	flags |= UTRACE_ACTION_QUIESCE;
+#endif
+	flags |= UTRACE_EVENT(QUIESCE);
+	ret = utrace_set_flags(ktl->task, ktl->engine, flags);
+	if (ret == -EALREADY){
+		atomic_set(&ktl->checked, THR_MARKED);
+		DPRINT("safety_check_each_thr: EALREADY\n");
+		goto out;
+	}
+	else if (ret < 0) {
+		printk(KERN_ERR MSG_HEAD
+			"Failed to set utrace flags at check_thr_safety\n");
+		goto err;
+	}
+#ifdef NEW_UTRACE
+	if (utrace_control(ktl->task, ktl->engine, UTRACE_INTERRUPT) < 0) {
+		printk(KERN_ERR MSG_HEAD "Failed to call UTRACE_REPORT\n");
+		ret = -EFAULT;
+		goto err;
+	}
+#endif
+
+	DPRINT("safety_check_each_thr (exit): ret: %d\n", ret);
+	return;
+err:
+	atomic_set(&ktl->checked, THR_CHK_ERR);
+out:
+	spin_lock(&kpi->list_lock);
+	up(&kpi->rt_sem);
+	ktl->sem_upped = 1;
+	spin_unlock(&kpi->list_lock);
+	DPRINT("safety_check_each_thr (exit:out)\n");
+}
+
+static int safety_check(struct kaho_patch_info* kpi)
+{
+	struct kaho_thr_list* ktl;
+	struct list_head *pos;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+	struct list_head *next;
+#endif
+	int nthr, st;
+	int loop_count = 0;
+	int err = 0;
+
+	DPRINT("safety_check (entry)\n");
+
+	/* Copy thread list */
+	spin_lock(&kpi->list_lock);
+	list_for_each_entry(ktl, &kpi->thr_list, thr_list) {
+		list_add_rcu(&ktl->chk_list, &kpi->chk_list);
+		ktl->sem_upped = 0;
+	}
+	spin_unlock(&kpi->list_lock);
+
+loop:
+	/* Set quiescent request */
+	nthr = 0;
+	spin_lock(&kpi->list_lock);
+
+	/* Count the number of threads */
+	list_for_each_entry(ktl, &kpi->chk_list, chk_list)
+		nthr++;
+	/* Initialize the semaphore */
+	sema_init(&kpi->rt_sem, 1-nthr);
+
+	/* Set state */
+	if (loop_count == 0) {
+		st = atomic_read(&kpi->state);
+		if (st == KAHO_STATE_IN_ACT_RT1)
+			atomic_set(&kpi->state, KAHO_STATE_IN_ACT_RT2);
+		else if (st == KAHO_STATE_IN_DEACT_RT1)
+			atomic_set(&kpi->state, KAHO_STATE_IN_DEACT_RT2);
+		else
+			panic("Unexpected state: %d (safety_check)\n", st);
+	}
+
+	spin_unlock(&kpi->list_lock);
+
+	/* Request quiescent to check address at which the thread runs */
+	list_for_each_entry(ktl, &kpi->chk_list, chk_list)
+		safety_check_each_thr(kpi, ktl);
+
+	/* Wait for finish of the safety check */
+	down(&kpi->rt_sem);
+
+	/* Delete elements of noexistent threads */
+	nthr = 0;
+	spin_lock(&kpi->list_lock);
+	list_for_each_safe_rcu(pos, next, &kpi->chk_list) {
+		ktl = list_entry(pos, struct kaho_thr_list, chk_list);
+		if (atomic_read(&ktl->checked) == THR_NO_MARK) {
+			nthr++;
+		}
+		else if (atomic_read(&ktl->checked) == THR_MARKED ||
+		         atomic_read(&ktl->checked) == THR_ESRCH ) {
+			list_del_rcu(&ktl->chk_list);
+		}
+		else if (atomic_read(&ktl->checked) == THR_CHK_ERR) {
+			err = 1;
+		}
+		else {
+			panic("Unexpected ktl->checked: %d\n",
+			      atomic_read(&ktl->checked));
+		}
+	}
+	spin_unlock(&kpi->list_lock);
+
+	/* Check a canceled flag and an error flag */
+	if (err == 1)
+		goto err;
+
+	/* When threre are non-safety threads */
+	if (nthr != 0) {
+		/* check canceled flag and error flag */
+		if (kpi->canceled == CANCELED){
+			/* Wait until all the in-flight RCUs are complete. */
+			rcu_barrier();
+			goto err;
+		}
+
+		/* Retry check if element is remaining */
+		if (loop_count < MAX_RETRY_RT_ACT) {
+			loop_count++;
+			goto loop;
+		}
+		/* Give up */
+		printk(KERN_ERR MSG_HEAD
+		       "Loop count reached MAX_RETRY_RT_ACT\n");
+		goto err;
+	}
+
+	DPRINT("safety_check (exit)\n");
+	return 0;
+
+err:
+	spin_lock(&kpi->list_lock);
+	list_for_each_safe_rcu(pos, next, &kpi->chk_list)
+		ktl = list_entry(pos, struct kaho_thr_list, chk_list);
+		list_del_rcu(&ktl->chk_list);
+	spin_unlock(&kpi->list_lock);
+	DPRINT("safety_check (exit:err)\n");
+	return -EFAULT;
+}
+
+/* ------------------------------------------------------------------
+ * Trap Handlers and threads
+ * ---------------------------------------------------------------- */
+static void mark_check_list(struct kaho_patch_info *kpi)
+{
+	struct kaho_thr_list* ktl;
+
+	DPRINT("mark_check_list (entry)\n");
+	list_for_each_entry_rcu(ktl, &kpi->chk_list, chk_list) {
+		if (ktl->task == current) {
+			 atomic_set(&ktl->checked, THR_MARKED);
+			 break;
+		}
+	}
+	DPRINT("mark_check_list (exit)\n");
+}
+
+static int kaho_trap_handler(
+	struct notifier_block *nb, unsigned long val, void *data)
+{
+	struct kaho_patch_info* kpi;
+	struct die_args * args = (struct die_args *)data;
+	unsigned long target_addr;
+
+	DPRINT("kaho_trap_handler (entry)\n");
+	if (val != DIE_INT3)
+		return NOTIFY_DONE;
+
+	/* Serach tregistered trap */
+	rcu_read_lock();
+	list_for_each_entry_rcu(kpi, &kaho_trap_list_head, trap_list) {
+
+		DPRINT("[trap] current->group_leader: %p, target_task: %p\n",
+		        current->group_leader, kpi->target_task);
+		if (current->group_leader != kpi->target_task)
+			continue;
+
+		DPRINT("[trap] st: %d\n", atomic_read(&kpi->state));
+		if ((atomic_read(&kpi->state) != KAHO_STATE_IN_ACT_RT1) &&
+		    (atomic_read(&kpi->state) != KAHO_STATE_IN_ACT_RT2) &&
+		    (atomic_read(&kpi->state) != KAHO_STATE_ACTIVE) &&
+		    (atomic_read(&kpi->state) != KAHO_STATE_IN_DEACT_RT1) &&
+		    (atomic_read(&kpi->state) != KAHO_STATE_IN_DEACT_RT2) &&
+		    (atomic_read(&kpi->state) != KAHO_STATE_DEACTIVE))
+			continue;
+
+		target_addr = kpi->items[0].target_addr;
+		DPRINT("[trap] addr: %lx\n", target_addr);
+		if (!arch_trap_addr_check(args, target_addr))
+			continue;
+
+		/* assert checked flag */
+		mark_check_list(kpi);
+
+		/* jumpt to patch */
+		arch_set_pc(args->regs, kpi->items[0].patch_addr);
+
+		rcu_read_unlock();
+		DPRINT("kaho_trap_handler (exit:NOTFY_STOP)\n");
+		return NOTIFY_STOP;
+	}
+	rcu_read_unlock();
+	DPRINT("kaho_trap_handler (exit:NOTFY_DONE)\n");
+	return NOTIFY_DONE;
+}
+
+struct notifier_block kaho_trap_notif = {
+	.notifier_call = kaho_trap_handler,
+	.priority = 100
+};
+
+extern int register_die_notifier(struct notifier_block *nb);
+#endif
+
+
+static int __init init_kaho(void)
+{
+	int rv;
+	/* Register as a character device */
+	rv = register_chrdev(kaho_major, kaho_dev_name, &kaho_fops);
+	if (rv < 0) {
+		class_destroy(kaho_class);
+		printk(KERN_ERR MSG_HEAD "can't register device class\n");
+		return rv;
+	}
+	/* Register as a class device */
+	kaho_class = class_create(THIS_MODULE, (char*)kaho_dev_name);
+	if (IS_ERR(kaho_class)) {
+		printk(KERN_ERR MSG_HEAD "can't register device class\n");
+		goto err3;
+	}
+	if (kaho_major == 0)
+		kaho_major = rv;
+	/* add class device */
+	class_device_create(kaho_class, NULL, MKDEV(kaho_major, kaho_minor),
+			    NULL, "kaho");
+
+	/* init variables */
+	atomic_set(&nr_patch, 0);
+	init_handle_tbl();
+
+#ifdef CONFIG_KAHO_RT
+	/* Trap Handler */
+	if (register_die_notifier(&kaho_trap_notif) < 0) {
+		printk(KERN_ERR MSG_HEAD
+		       "Failed to register the trap handler\n");
+		goto err2;
+	}
+
+#endif
+
+#ifndef CONFIG_KAHO_RT
+	printk(KERN_INFO MSG_HEAD "%s initialized\n", KAHO_VER);
+#else
+	printk(KERN_INFO MSG_HEAD "%s initialized (RT)\n", KAHO_VER);
+#endif
+
+	return 0;
+
+#ifdef CONFIG_KAHO_RT
+err2:
+	class_device_destroy(kaho_class, MKDEV(kaho_major, kaho_minor));
+	class_destroy(kaho_class);
+#endif
+
+err3:
+	unregister_chrdev(kaho_major, kaho_dev_name);
+
+	return -EFAULT;
+}
+
+static void __exit cleanup_kaho(void)
+{
+	struct kaho_patch_info* kpi;
+	struct kaho_patch_info* n;
+
+	printk(KERN_INFO MSG_HEAD "start cleanup\n");
+
+loop:
+	spin_lock(&kaho_patch_list_lock);
+	list_for_each_entry_safe(kpi, n, &kaho_patch_list_head, list) {
+		list_del_rcu(&kpi->list);
+		spin_unlock(&kaho_patch_list_lock);
+		free_kpi(kpi, 0, 0);
+		goto loop;
+	}
+	spin_unlock(&kaho_patch_list_lock);
+
+#ifdef CONFIG_KAHO_RT
+	/* Unregister the trap handler */
+	if (unregister_die_notifier(&kaho_trap_notif) < 0)
+		printk(KERN_ERR MSG_HEAD "Failed to unregister int3 handler\n");
+#endif
+
+	class_device_destroy(kaho_class, MKDEV(kaho_major, kaho_minor));
+	class_destroy(kaho_class);
+	unregister_chrdev(kaho_major, kaho_dev_name);
+	printk(KERN_INFO MSG_HEAD "%s removed\n", KAHO_VER);
+	DPRINT("\n");
+}
+
+module_init(init_kaho);
+module_exit(cleanup_kaho);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("K. Yamato. <kyamato@miraclelinux.com>");
+MODULE_DESCRIPTION("KAHO (kernel Aided Hexadecimal code Operator");
--- linux-2.6.27/kernel/Makefile	2009-03-09 05:45:44.000000000 +0900
+++ linux-2.6.27.kaho/kernel/Makefile	2009-03-09 05:38:24.000000000 +0900
@@ -9,7 +9,7 @@
 	    rcupdate.o extable.o params.o posix-timers.o \
 	    kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
 	    hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \
-	    notifier.o ksysfs.o pm_qos_params.o sched_clock.o
+	    notifier.o ksysfs.o pm_qos_params.o sched_clock.o kaho.o
 
 ifdef CONFIG_FTRACE
 # Do not trace debug files and internal ftrace files
