#ifndef ICC_BUS_H_
 #define ICC_BUS_H_
 
+
+struct v3_icc_ops {
+    int (*raise_intr)(struct guest_info * core, int intr_num, void * private_data);
+};
+
+
 /**
  *
  */
-int v3_icc_register_apic(struct v3_vm_info *info, struct vm_device *icc_bus, struct vm_device *apic, uint32_t apic_num);
+int v3_icc_register_apic(struct guest_info * vm, struct vm_device * icc_bus, uint8_t apic_phys_id, struct v3_icc_ops * ops, void * priv_data);
+
 
 /**
  * Send an inter-processor interrupt (IPI) from this local APIC to another local APIC.
  *
- * @param icc_bus The ICC bus that facilitates the communication.
- * @param apic_num The remote APIC number.
- * @param intr_num The interrupt number.
+ * @param icc_bus - The ICC bus that routes IPIs.
+ * @param apic_num - The remote APIC number.
+ * @param intr_num - The interrupt number.
  */
-int v3_icc_send_ipi(struct vm_device * icc_bus, uint32_t apic_num, uint32_t intr_num);
+int v3_icc_send_irq(struct vm_device * icc_bus, uint8_t apic_num, uint32_t irq_num);
+
+
+
 
 #endif /* ICC_BUS_H_ */
 
 menu "Virtual Devices"
 
 config APIC
-       bool "APIC"
+       bool "APIC" 
        default y
+       depends on ICC_BUS
        help 
          Includes the Virtual APIC device
 
          Enable debugging for the APIC
 
 
+
+config IO_APIC
+       bool "IOAPIC"
+       depends on ICC_BUS
+       default y
+       help 
+         Includes the Virtual IO APIC
+
+config DEBUG_IO_APIC
+       bool "IO APIC Debugging"
+       default n
+       depends on IO_APIC && DEBUG_ON 
+       help 
+         Enable debugging for the IO APIC
+
+
+config ICC_BUS
+       bool "ICC BUS"
+       default y
+       help 
+         The ICC Bus for APIC/IOAPIC communication
+
+
 config BOCHS_DEBUG
        bool "Bochs Debug Console Device"
        default y
          Enable debugging for the IDE Layer
 
 
-config IO_APIC
-       bool "IOAPIC"
-       depends on ICC_BUS
-       default y
-       help 
-         Includes the Virtual IO APIC
-
-config DEBUG_IO_APIC
-       bool "IO APIC Debugging"
-       default n
-       depends on IO_APIC && DEBUG_ON 
-       help 
-         Enable debugging for the IO APIC
-
 
 
 
 
 obj-$(CONFIG_APIC) += apic.o
+obj-$(CONFIG_IO_APIC) += io_apic.o
+obj-$(CONFIG_ICC_BUS) += icc_bus.o
 obj-$(CONFIG_PIT) += 8254.o
 obj-$(CONFIG_PIC) += 8259a.o
 obj-$(CONFIG_BOCHS_DEBUG) += bochs_debug.o
 obj-$(CONFIG_GENERIC) += generic.o
 obj-$(CONFIG_I440FX) += i440fx.o
 obj-$(CONFIG_IDE) += ide.o
-obj-$(CONFIG_IO_APIC) += io_apic.o
+
 obj-$(CONFIG_KEYBOARD) += keyboard.o
 obj-$(CONFIG_LINUX_VIRTIO_BALLOON) += lnx_virtio_balloon.o
 obj-$(CONFIG_LINUX_VIRTIO_BLOCK) += lnx_virtio_blk.o
 
 
 #include <devices/apic.h>
 #include <devices/apic_regs.h>
+#include <devices/icc_bus.h>
 #include <palacios/vmm.h>
 #include <palacios/vmm_msr.h>
 #include <palacios/vmm_sprintf.h>
 #include <palacios/vm_guest.h>
 
+
 #ifndef CONFIG_DEBUG_APIC
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
   
     uint32_t eoi;
 
-    uint32_t my_apic_id;
-    struct vm_device *icc_bus;
+    struct vm_device * icc_bus;
 
     v3_lock_t  lock;
 };
 
-static int apic_read(addr_t guest_addr, void * dst, uint_t length, void * priv_data);
-static int apic_write(addr_t guest_addr, void * src, uint_t length, void * priv_data);
+static int apic_read(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data);
+static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data);
 
 static void init_apic_state(struct apic_state * apic) {
     apic->base_addr = DEFAULT_BASE_ADDR;
 
 
 
-static int read_apic_msr(uint_t msr, v3_msr_t * dst, void * priv_data) {
+static int read_apic_msr(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
     struct vm_device * dev = (struct vm_device *)priv_data;
-    struct apic_state * apic = (struct apic_state *)dev->private_data;
+    struct apic_state * apics = (struct apic_state *)(dev->private_data);
+    struct apic_state * apic = &(apics[core->cpu_id]);
+
     v3_lock(apic->lock);
     dst->value = apic->base_addr;
     v3_unlock(apic->lock);
 }
 
 
-static int write_apic_msr(uint_t msr, v3_msr_t src, void * priv_data) {
+static int write_apic_msr(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
     struct vm_device * dev = (struct vm_device *)priv_data;
-    struct apic_state * apic = (struct apic_state *)dev->private_data;
-    struct v3_shadow_region * old_reg = v3_get_shadow_region(dev->vm, apic->base_addr);
+    struct apic_state * apics = (struct apic_state *)(dev->private_data);
+    struct apic_state * apic = &(apics[core->cpu_id]);
+    struct v3_shadow_region * old_reg = v3_get_shadow_region(dev->vm, core->cpu_id, apic->base_addr);
 
 
     if (old_reg == NULL) {
 
     apic->base_addr = src.value;
 
-    if (v3_hook_full_mem(dev->vm, apic->base_addr, apic->base_addr + PAGE_SIZE_4KB, apic_read, apic_write, dev) == -1) {
+    if (v3_hook_full_mem(dev->vm, core->cpu_id, apic->base_addr, apic->base_addr + PAGE_SIZE_4KB, apic_read, apic_write, dev) == -1) {
        PrintError("Could not hook new APIC Base address\n");
        v3_unlock(apic->lock);
        return -1;
 }
 
 
-static int apic_read(addr_t guest_addr, void * dst, uint_t length, void * priv_data) {
-    struct vm_device * dev = (struct vm_device *)priv_data;
-    struct apic_state * apic = (struct apic_state *)dev->private_data;
+static int apic_read(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data) {
+    struct apic_state * apic = (struct apic_state *)priv_data;
     addr_t reg_addr  = guest_addr - apic->base_addr;
     struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
     uint32_t val = 0;
 /**
  *
  */
-static int apic_write(addr_t guest_addr, void * src, uint_t length, void * priv_data) {
-    struct vm_device * dev = (struct vm_device *)priv_data;
-    struct apic_state * apic = (struct apic_state *)dev->private_data;
+static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data) {
+    struct apic_state * apic = (struct apic_state *)priv_data;
     addr_t reg_addr  = guest_addr - apic->base_addr;
     struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
     uint32_t op_val = *(uint32_t *)src;
 
        case INT_CMD_LO_OFFSET:
            apic->int_cmd.lo = op_val;
-        v3_icc_send_ipi(apic->icc_bus, apic->int_cmd.dst, apic->int_cmd.val);
+           // ICC???
+           v3_icc_send_irq(apic->icc_bus, apic->int_cmd.dst, apic->int_cmd.val);
            break;
        case INT_CMD_HI_OFFSET:
            apic->int_cmd.hi = op_val;
 
 // returns 1 if an interrupt is pending, 0 otherwise
 static int apic_intr_pending(struct guest_info * info, void * private_data) {
-    struct vm_device * dev = (struct vm_device *)private_data;
-    struct apic_state * apic = (struct apic_state *)dev->private_data;
+    struct apic_state * apic = (struct apic_state *)private_data;
     int req_irq = get_highest_irr(apic);
     int svc_irq = get_highest_isr(apic);
 
 }
 
 static int apic_get_intr_number(struct guest_info * info, void * private_data) {
-    struct vm_device * dev = (struct vm_device *)private_data;
-    struct apic_state * apic = (struct apic_state *)dev->private_data;
+    struct apic_state * apic = (struct apic_state *)private_data;
     int req_irq = get_highest_irr(apic);
     int svc_irq = get_highest_isr(apic);
 
     return -1;
 }
 
-#if 0
-static int apic_raise_intr(struct guest_info * info, void * private_data, int irq) {
-#ifdef CONFIG_CRAY_XT
-    // The Seastar is connected directly to the LAPIC via LINT0 on the ICC bus
-
-    if (irq == 238) {
-       struct vm_device * dev = (struct vm_device *)private_data;
-       struct apic_state * apic = (struct apic_state *)dev->private_data;
 
-       return activate_apic_irq(apic, irq);
-    }
-#endif
+static int apic_raise_intr(struct guest_info * info, int irq, void * private_data) {
+  struct apic_state * apic = (struct apic_state *)private_data;
 
-    return 0;
+  return activate_apic_irq(apic, irq);
 }
 
-static int apic_lower_intr(struct guest_info * info, void * private_data, int irq) {
-    return 0;
-}
-#endif
+
 
 static int apic_begin_irq(struct guest_info * info, void * private_data, int irq) {
-    struct vm_device * dev = (struct vm_device *)private_data;
-    struct apic_state * apic = (struct apic_state *)dev->private_data;
+    struct apic_state * apic = (struct apic_state *)private_data;
     int major_offset = (irq & ~0x00000007) >> 3;
     int minor_offset = irq & 0x00000007;
     uchar_t * req_location = apic->int_req_reg + major_offset;
     *svc_location |= flag;
     *req_location &= ~flag;
 
-#ifdef CONFIG_CRAY_XT
-    if ((irq == 238) || (irq == 239)) {
-       PrintError("APIC: Begin IRQ %d (ISR=%x), (IRR=%x)\n", irq, *svc_location, *req_location);
-    }
-#endif
-
-    return 0;
-}
-
-
-
-int v3_apic_raise_intr(struct guest_info * info, struct vm_device * apic_dev, int intr_num) {
-    struct apic_state * apic = (struct apic_state *)apic_dev->private_data;
-
-    // Special cases go here
-    // startup, etc
-
-    if (activate_apic_irq(apic, intr_num) == -1) {
-       PrintError("Error: Could not activate apic_irq\n");
-       return -1;
-    } 
 
-    // Don't need this since we'll have the IPI force an exit if
-    // This is called on a different core
-    /* v3_interrupt_cpu(info, 0); */
 
     return 0;
 }
 
 
 
+
 /* Timer Functions */
 static void apic_update_time(struct guest_info * info, ullong_t cpu_cycles, ullong_t cpu_freq, void * priv_data) {
-    struct vm_device * dev = (struct vm_device *)priv_data;
-    struct apic_state * apic = (struct apic_state *)dev->private_data;
+    struct apic_state * apic = (struct apic_state *)priv_data;
     // The 32 bit GCC runtime is a pile of shit
 #ifdef __V3_64BIT__
     uint64_t tmr_ticks = 0;
 
 
 
+static struct v3_icc_ops icc_ops = {
+    .raise_intr = apic_raise_intr,
+};
+
+
+
 static int apic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     PrintDebug("Creating APIC\n");
     char * name = v3_cfg_val(cfg, "name");
     char * icc_name = v3_cfg_val(cfg,"irq_bus");
-    int i;
     struct vm_device * icc = v3_find_dev(vm, icc_name);
+    int i;
 
     if (!icc) {
-        PrintError("Cannot find device %s\n", icc_name);
+        PrintError("Cannot find ICC Bus (%s)\n", icc_name);
         return -1;
     }
 
-    struct apic_state * apic = (struct apic_state *)V3_Malloc(sizeof(struct apic_state));
+    // We allocate one apic per core
+    // APICs are accessed via index which correlates with the core's cpu_id 
+    struct apic_state * apic = (struct apic_state *)V3_Malloc(sizeof(struct apic_state) * vm->num_cores);
 
     struct vm_device * dev = v3_allocate_device(name, &dev_ops, apic);
 
        return -1;
     }
 
-    for (i = 0; i < vm->num_cores; i++)
-    {
-       v3_register_intr_controller(&vm->cores[i], &intr_ops, dev);
-       v3_add_timer(&vm->cores[i], &timer_ops, dev);
+    
+    for (i = 0; i < vm->num_cores; i++) {
+       struct guest_info * core = &(vm->cores[i]);
+
+       v3_register_intr_controller(core, &intr_ops, &(apic[i]));
+       v3_add_timer(core, &timer_ops, &(apic[i]));
+       v3_hook_full_mem(vm, core->cpu_id, apic->base_addr, apic->base_addr + PAGE_SIZE_4KB, apic_read, apic_write, &(apic[i]));
+
+       v3_icc_register_apic(core, icc, i, &icc_ops, &(apic[i]));
+
+       init_apic_state(&(apic[i]));
     }
 
-    init_apic_state(apic);
 
-    v3_icc_register_apic(vm, icc, dev,apic->my_apic_id);
 
     v3_hook_msr(vm, BASE_ADDR_MSR, read_apic_msr, write_apic_msr, dev);
 
-    v3_hook_full_mem(vm, apic->base_addr, apic->base_addr + PAGE_SIZE_4KB, apic_read, apic_write, dev);
-
     return 0;
 }
 
 
 #include <palacios/vmm_dev_mgr.h>
 #include <palacios/vmm_sprintf.h>
 #include <palacios/vm_guest.h>
-#include <devices/apic_regs.h>
-#include <devices/apic.h>
+#include <devices/icc_bus.h>
 
-#define MAX_APIC 256
+#define MAX_APICS 256
 
-struct icc_bus_internal {
-    struct vm_device * apic[MAX_APIC];
+
+struct ipi_thunk_data {
+    struct vm_device * target;
+    uint64_t val;
+};
+
+struct int_cmd_reg {
+    union {
+        uint64_t val;
+
+        struct {
+            uint32_t lo;
+            uint32_t hi;
+        } __attribute__((packed));
+
+        struct {
+            uint_t vec           : 8;
+            uint_t msg_type      : 3;
+            uint_t dst_mode      : 1;
+            uint_t del_status    : 1;
+            uint_t rsvd1         : 1;
+            uint_t lvl           : 1;
+            uint_t trig_mode     : 1;
+            uint_t rem_rd_status : 2;
+            uint_t dst_shorthand : 2;
+            uint64_t rsvd2       : 36;
+            uint32_t dst         : 8;
+        } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+
+
+struct apic_data {
+    struct guest_info * core;
+    struct v3_icc_ops * ops;
+    
+    void * priv_data;
+    int present;
+};
+
+
+struct icc_bus_state {
+    struct apic_data apics[MAX_APICS];
 };
 
 static struct v3_device_ops dev_ops = {
     .stop = NULL,
 };
 
-int v3_icc_register_apic(struct v3_vm_info *info, struct vm_device *icc_bus, struct vm_device *apic, uint32_t apic_num)
-{
-    struct icc_bus_internal * icc = (struct icc_bus_internal *)icc_bus->private_data;
-
-    if (apic_num < MAX_APIC) {
-        if (icc->apic[apic_num]) {
-            PrintError("Attempt to re-register apic %u\n", apic_num);
-            return -1;
-        } else {
-            icc->apic[apic_num] = apic;
-            PrintDebug("Registered apic or ioapic %u\n", apic_num);
-            return 0;
-        }
-    } else {
-        PrintError("Too many apics for icc bus!");
-        return -1;
-    }
-}
 
-struct ipi_thunk_data {
-    struct vm_device *target;
-    uint64_t          val;
-} ;
 
-static void icc_force_exit(void *val)
-{
-     return;
-}
 
-int v3_icc_send_ipi(struct vm_device * icc_bus, uint32_t apic_num, uint32_t val) {
-    struct icc_bus_internal * internal = (struct icc_bus_internal *)icc_bus->private_data;
+int v3_icc_send_irq(struct vm_device * icc_bus, uint8_t apic_num, uint32_t irq_num) {
+    struct icc_bus_state * state = (struct icc_bus_state *)icc_bus->private_data;
+    struct apic_data * apic = &(state->apics[apic_num]);    
+
 
     struct int_cmd_reg icr;
-    icr.lo = val;
+    icr.lo = irq_num;
 
-    char *type = NULL, *dest = NULL;
+
+    char * type = NULL;
+    char * dest = NULL;
     char foo[8];
 
-    switch (icr.dst_shorthand)
-    {
-    case 0x0:
-        sprintf(foo, "%d", icr.dst);
-        dest = foo;
-        break;
-    case 0x1:
-        dest = "(self)";
-        break;
-    case 0x2:
-        dest = "(broadcast inclusive)";
-        break;
-    case 0x3:
-        dest = "(broadcast)";
-        break;
+    switch (icr.dst_shorthand) {
+       case 0x0:
+           sprintf(foo, "%d", icr.dst);
+           dest = foo;
+           break;
+       case 0x1:
+           dest = "(self)";
+           break;
+       case 0x2:
+           dest = "(broadcast inclusive)";
+           break;
+       case 0x3:
+           dest = "(broadcast)";
+           break;
     }
-    switch (icr.msg_type)
-    {
-    case 0x0:
-        type = "";
-        break;
-    case 0x4:
-        type = "(NMI)";
-        break;
-    case 0x5:
-        type = "(INIT)";
-        break;
-    case 0x6:
-        type = "(Startup)";
-        break;
+
+    switch (icr.msg_type) {
+       case 0x0:
+           type = "";
+           break;
+       case 0x4:
+           type = "(NMI)";
+           break;
+       case 0x5:
+           type = "(INIT)";
+           break;
+       case 0x6:
+           type = "(Startup)";
+           break;
     }
 
 
-    PrintDebug("Sending IPI of type %s and destination type %s from LAPIC %u to LAPIC %u.\n", type, dest, V3_Get_CPU(), apic_num);
+    PrintDebug("Sending IPI of type %s and destination type %s from LAPIC %u to LAPIC %u.\n", 
+              type, dest, V3_Get_CPU(), apic_num);
 
-    v3_apic_raise_intr(internal->apic[apic_num], val & 0xff);
+    apic->ops->raise_intr(apic->core, irq_num & 0xff, apic->priv_data);
 
-    V3_Call_On_CPU(apic_num,  icc_force_exit, (void *)(uint64_t)(val & 0xff));
+    //V3_Call_On_CPU(apic_num,  icc_force_exit, (void *)(uint64_t)(val & 0xff));
 
     return 0;
 }
 
 
-static int init_icc_bus_internal_state(struct icc_bus_internal* icc) {
-    int i;
-    for (i=0;i<MAX_APIC;i++) { icc->apic[i]=0; }
-    return  0;
+
+/* THIS IS A BIG ASSUMPTION: APIC PHYSID == LOGID == CORENUM */
+
+int v3_icc_register_apic(struct guest_info  * core, struct vm_device * icc_bus, 
+                        uint8_t apic_num, struct v3_icc_ops * ops, void * priv_data) {
+    struct icc_bus_state * icc = (struct icc_bus_state *)icc_bus->private_data;
+    struct apic_data * apic = &(icc->apics[apic_num]);
+
+    if (apic->present == 1) {
+       PrintError("Attempt to re-register apic %u\n", apic_num);
+       return -1;
+    }
+    
+    apic->present = 1;
+    apic->priv_data = priv_data;
+    apic->core = core;
+    apic->ops = ops;
+   
+    PrintDebug("Registered apic%u\n", apic_num);
+
+    return 0;
 }
 
+
+
+
 static int icc_bus_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     PrintDebug("Creating ICC_BUS\n");
+
     char * name = v3_cfg_val(cfg, "name");
 
-    struct icc_bus_internal * icc_bus = (struct icc_bus_internal *)V3_Malloc(sizeof(struct icc_bus_internal));
+    struct icc_bus_state * icc_bus = (struct icc_bus_state *)V3_Malloc(sizeof(struct icc_bus_state));
+    memset(icc_bus, 0, sizeof(struct icc_bus_state));
 
     struct vm_device * dev = v3_allocate_device(name, &dev_ops, icc_bus);
 
         return -1;
     }
 
-    init_icc_bus_internal_state(icc_bus);
-
     return 0;
 }
 
 
 
 #include <palacios/vmm.h>
 #include <palacios/vmm_dev_mgr.h>
-#include <devices/apic.h>
+#include <devices/icc_bus.h>
 #include <palacios/vm_guest.h>
 
 #ifndef CONFIG_DEBUG_IO_APIC
   
     struct redir_tbl_entry redir_tbl[24];
 
-    // This is a temporary method of communication between the IOAPIC and the LAPIC
-    struct vm_device * apic;
+    struct vm_device * icc_bus;
   
 };
 
 }
 
 
-static int ioapic_read(addr_t guest_addr, void * dst, uint_t length, void * priv_data) {
+static int ioapic_read(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data) {
     struct vm_device * dev = (struct vm_device *)priv_data;
     struct io_apic_state * ioapic = (struct io_apic_state *)(dev->private_data);
     uint32_t reg_tgt = guest_addr - ioapic->base_addr;
 }
 
 
-static int ioapic_write(addr_t guest_addr, void * src, uint_t length, void * priv_data) {
+static int ioapic_write(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data) {
     struct vm_device * dev = (struct vm_device *)priv_data;
     struct io_apic_state * ioapic = (struct io_apic_state *)(dev->private_data);
     uint32_t reg_tgt = guest_addr - ioapic->base_addr;
     return length;
 }
 
-/* Interrupt controller functions */
-static int ioapic_intr_pending(struct guest_info * info, void * private_data) {
-    return 0;
-}
-
-
-static int ioapic_get_intr_number(struct guest_info * info, void * private_data) {
-    return 0;
-}
-
-static int ioapic_begin_irq(struct guest_info * info, void * private_data, int irq) {
-    return 0;
-}
 
-static int ioapic_raise_irq(struct guest_info * info, void * private_data, int irq) {
+static int ioapic_raise_irq(struct v3_vm_info * vm, void * private_data, int irq) {
     struct vm_device * dev = (struct vm_device *)private_data;
     struct io_apic_state * ioapic = (struct io_apic_state *)(dev->private_data);  
     struct redir_tbl_entry * irq_entry = NULL;
 
     if (irq_entry->mask == 0) {
        PrintDebug("IOAPIC Signalling APIC to raise INTR %d\n", irq_entry->vec);
-       //v3_apic_raise_intr(info, ioapic->apic, irq_entry->vec);
-       v3_apic_raise_intr(ioapic->apic, irq_entry->vec);
+       v3_icc_send_irq(ioapic->icc_bus, irq_entry->dst_field, irq_entry->vec);
     }
 
     return 0;
 }
 
 /* I don't know if we can do anything here.... */
-static int ioapic_lower_irq(struct guest_info * info, void * private_data, int irq) {
+static int ioapic_lower_irq(struct v3_vm_info * vm, void * private_data, int irq) {
     return 0;
 }
 
-static struct intr_ctrl_ops intr_ops = {
-    .intr_pending = ioapic_intr_pending,
-    .get_intr_number = ioapic_get_intr_number,
+static struct intr_router_ops router_ops = {
     .raise_intr = ioapic_raise_irq,
-    .begin_irq = ioapic_begin_irq,
     .lower_intr = ioapic_lower_irq, 
 };
 
 
 
 
-static int ioapic_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
-    struct vm_device * apic = v3_find_dev(vm, v3_cfg_val(cfg, "irq_bus"));
+static int ioapic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
+    struct vm_device * icc_bus = v3_find_dev(vm, v3_cfg_val(cfg, "irq_bus"));
     char * name = v3_cfg_val(cfg, "name");
 
-    if (!apic) {
-       PrintError("Could not locate APIC device (%s)\n", v3_cfg_val(cfg, "irq_bus"));
+    if (!icc_bus) {
+       PrintError("Could not locate ICC BUS device (%s)\n", v3_cfg_val(cfg, "irq_bus"));
        return -1;
     }
 
 
     struct io_apic_state * ioapic = (struct io_apic_state *)V3_Malloc(sizeof(struct io_apic_state));
 
-    ioapic->apic = apic;
+    ioapic->icc_bus = icc_bus;
 
     struct vm_device * dev = v3_allocate_device(name, &dev_ops, ioapic);
 
     }
 
 
-    v3_register_intr_controller(vm, &intr_ops, dev);
+    v3_register_intr_router(vm, &router_ops, dev);
     init_ioapic_state(ioapic);
 
-    v3_hook_full_mem(vm, ioapic->base_addr, ioapic->base_addr + PAGE_SIZE_4KB, 
+    v3_hook_full_mem(vm, V3_MEM_CORE_ANY, ioapic->base_addr, ioapic->base_addr + PAGE_SIZE_4KB, 
                     ioapic_read, ioapic_write, dev);
   
     return 0;