static int __kprobes unsupported_inst(uint template, uint  slot,
                                      uint major_opcode,
                                      unsigned long kprobe_inst,
-                                     struct kprobe *p)
+                                     unsigned long addr)
 {
-       unsigned long addr = (unsigned long)p->addr;
-
        if (bundle_encoding[template][slot] == I) {
                switch (major_opcode) {
                        case 0x0: //I_UNIT_MISC_OPCODE:
                                         struct kprobe *p)
 {
        unsigned long break_inst = BREAK_INST;
-       bundle_t *bundle = &p->ainsn.insn.bundle;
+       bundle_t *bundle = &p->opcode.bundle;
 
        /*
         * Copy the original kprobe_inst qualifying predicate(qp)
        unsigned long *kprobe_addr = (unsigned long *)(addr & ~0xFULL);
        unsigned long kprobe_inst=0;
        unsigned int slot = addr & 0xf, template, major_opcode = 0;
-       bundle_t *bundle = &p->ainsn.insn.bundle;
-
-       memcpy(&p->opcode.bundle, kprobe_addr, sizeof(bundle_t));
-       memcpy(&p->ainsn.insn.bundle, kprobe_addr, sizeof(bundle_t));
+       bundle_t *bundle;
 
+       bundle = &((kprobe_opcode_t *)kprobe_addr)->bundle;
        template = bundle->quad0.template;
 
        if(valid_kprobe_addr(template, slot, addr))
        /* Get kprobe_inst and major_opcode from the bundle */
        get_kprobe_inst(bundle, slot, &kprobe_inst, &major_opcode);
 
-       if (unsupported_inst(template, slot, major_opcode, kprobe_inst, p))
+       if (unsupported_inst(template, slot, major_opcode, kprobe_inst, addr))
                        return -EINVAL;
 
-       prepare_break_inst(template, slot, major_opcode, kprobe_inst, p);
 
-       return 0;
-}
+       p->ainsn.insn = get_insn_slot();
+       if (!p->ainsn.insn)
+               return -ENOMEM;
+       memcpy(&p->opcode, kprobe_addr, sizeof(kprobe_opcode_t));
+       memcpy(p->ainsn.insn, kprobe_addr, sizeof(kprobe_opcode_t));
 
-void __kprobes flush_insn_slot(struct kprobe *p)
-{
-       unsigned long arm_addr;
+       prepare_break_inst(template, slot, major_opcode, kprobe_inst, p);
 
-       arm_addr = ((unsigned long)&p->opcode.bundle) & ~0xFULL;
-       flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
+       return 0;
 }
 
 void __kprobes arch_arm_kprobe(struct kprobe *p)
        unsigned long addr = (unsigned long)p->addr;
        unsigned long arm_addr = addr & ~0xFULL;
 
-       flush_insn_slot(p);
-       memcpy((char *)arm_addr, &p->ainsn.insn.bundle, sizeof(bundle_t));
-       flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
+       flush_icache_range((unsigned long)p->ainsn.insn,
+                       (unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t));
+       memcpy((char *)arm_addr, &p->opcode, sizeof(kprobe_opcode_t));
+       flush_icache_range(arm_addr, arm_addr + sizeof(kprobe_opcode_t));
 }
 
 void __kprobes arch_disarm_kprobe(struct kprobe *p)
        unsigned long addr = (unsigned long)p->addr;
        unsigned long arm_addr = addr & ~0xFULL;
 
-       /* p->opcode contains the original unaltered bundle */
-       memcpy((char *) arm_addr, (char *) &p->opcode.bundle, sizeof(bundle_t));
-       flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
+       /* p->ainsn.insn contains the original unaltered kprobe_opcode_t */
+       memcpy((char *) arm_addr, (char *) p->ainsn.insn,
+                                        sizeof(kprobe_opcode_t));
+       flush_icache_range(arm_addr, arm_addr + sizeof(kprobe_opcode_t));
 }
 
+void __kprobes arch_remove_kprobe(struct kprobe *p)
+{
+       mutex_lock(&kprobe_mutex);
+       free_insn_slot(p->ainsn.insn);
+       mutex_unlock(&kprobe_mutex);
+}
 /*
  * We are resuming execution after a single step fault, so the pt_regs
  * structure reflects the register state after we executed the instruction
  */
 static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
 {
-       unsigned long bundle_addr = ((unsigned long) (&p->opcode.bundle)) & ~0xFULL;
+       unsigned long bundle_addr = (unsigned long) (&p->ainsn.insn->bundle);
        unsigned long resume_addr = (unsigned long)p->addr & ~0xFULL;
        unsigned long template;
        int slot = ((unsigned long)p->addr & 0xf);
 
-       template = p->opcode.bundle.quad0.template;
+       template = p->ainsn.insn->bundle.quad0.template;
 
        if (slot == 1 && bundle_encoding[template][1] == L)
                slot = 2;
 
 static void __kprobes prepare_ss(struct kprobe *p, struct pt_regs *regs)
 {
-       unsigned long bundle_addr = (unsigned long) &p->opcode.bundle;
+       unsigned long bundle_addr = (unsigned long) &p->ainsn.insn->bundle;
        unsigned long slot = (unsigned long)p->addr & 0xf;
 
        /* single step inline if break instruction */
 
 #include <linux/percpu.h>
 #include <asm/break.h>
 
-#define MAX_INSN_SIZE   16
+#define __ARCH_WANT_KPROBES_INSN_SLOT
+#define MAX_INSN_SIZE   1
 #define BREAK_INST     (long)(__IA64_BREAK_KPROBE << 6)
 
 typedef union cmp_inst {
 #define IP_RELATIVE_PREDICT_OPCODE     (7)
 #define LONG_BRANCH_OPCODE             (0xC)
 #define LONG_CALL_OPCODE               (0xD)
-#define arch_remove_kprobe(p)          do {} while (0)
+#define flush_insn_slot(p)             do { } while (0)
 
 typedef struct kprobe_opcode {
        bundle_t bundle;
 /* Architecture specific copy of original instruction*/
 struct arch_specific_insn {
        /* copy of the instruction to be emulated */
-       kprobe_opcode_t insn;
+       kprobe_opcode_t *insn;
  #define INST_FLAG_FIX_RELATIVE_IP_ADDR                1
  #define INST_FLAG_FIX_BRANCH_REG              2
  #define INST_FLAG_BREAK_INST                  4
 }
 extern void invalidate_stacked_regs(void);
 extern void flush_register_stack(void);
-extern void flush_insn_slot(struct kprobe *p);
+extern void arch_remove_kprobe(struct kprobe *p);
 
 #endif                         /* _ASM_KPROBES_H */