struct v3_vm_info * v3_create_vm(void * cfg, void * priv_data, char * name);
 int v3_start_vm(struct v3_vm_info * vm, unsigned int cpu_mask);
 int v3_stop_vm(struct v3_vm_info * vm);
+int v3_free_vm(struct v3_vm_info * vm);
 
 int v3_deliver_irq(struct v3_vm_info * vm, struct v3_interrupt * intr);
 
 
 
 
 struct v3_device_ops {
-    int (*free)(struct vm_device * dev);
+    int (*free)(void * private_data);
 
     //int (*save)(struct vm_device *dev, struct *iostream);
     //int (*restore)(struct vm_device *dev, struct *iostream);
 
 
     struct v3_timer * timer;
 
+    struct v3_vm_info * vm;
+
     struct channel ch_0;
     struct channel ch_1;
     struct channel ch_2;
 
 
 
-static int pit_free(struct vm_device * dev) {
-    struct pit * state = (struct pit *)dev->private_data;
-    struct guest_info * info = &(dev->vm->cores[0]);
+static int pit_free(void * private_data) {
+    struct pit * state = (struct pit *)private_data;
+    struct guest_info * info = &(state->vm->cores[0]);
 
 
     if (state->timer) {
 
 
 static struct v3_device_ops dev_ops = {
-    .free = pit_free,
+    .free = (int (*)(void *))pit_free,
 
 
 };
 
 
 
 
-static int pic_free(struct vm_device * dev) {
+static int pic_free(struct pic_internal * state) {
 
+
+    // unregister intr_controller
+    // unregister intr router
+
+    V3_Free(state);
     return 0;
 }
 
 
 
 static struct v3_device_ops dev_ops = {
-    .free = pic_free,
+    .free = (int (*)(void *))pic_free,
 
 };
 
 
 
 
 
-static int apic_free(struct vm_device * dev) {
-    struct apic_dev_state * apic_dev = (struct apic_dev_state *)dev->private_data;
+static int apic_free(struct apic_dev_state * apic_dev) {
     int i = 0;
+    struct v3_vm_info * vm = NULL;
 
-    for (i = 0; i < dev->vm->num_cores; i++) {
+    for (i = 0; i < apic_dev->num_apics; i++) {
        struct apic_state * apic = &(apic_dev->apics[i]);
-       struct guest_info * core = &(dev->vm->cores[i]);
+       struct guest_info * core = apic->core;
        
+       vm = core->vm_info;
 
        // unregister intr controller
 
 
     }
 
-    v3_unhook_msr(dev->vm, BASE_ADDR_MSR);
+    v3_unhook_msr(vm, BASE_ADDR_MSR);
 
     V3_Free(apic_dev);
     return 0;
 
 
 static struct v3_device_ops dev_ops = {
-    .free = apic_free,
+    .free = (int (*)(void *))apic_free,
 };
 
 
 
 
 
 
-static int debug_free(struct vm_device * dev) {
-    struct debug_state * state = dev->private_data;
+static int debug_free(struct debug_state * state) {
 
     V3_Free(state);
-
     return 0;
 };
 
 
 
 static struct v3_device_ops dev_ops = {
-    .free = debug_free,
+    .free = (int (*)(void *))debug_free,
 
 };
 
 
     // so we need a temp variable to hold the partial update
     uint16_t tmp_screen_offset; 
     
+    struct vm_device * dev;
+
 
     uint8_t passthrough;
 
 
 
 
-static int free_device(struct vm_device * dev) {
-    struct video_internal * video_state = (struct video_internal *)dev->private_data;
+static int free_device(struct video_internal * video_state) {
 
     if (video_state->framebuf_pa) {
        V3_FreePages((void *)(video_state->framebuf_pa), (FRAMEBUF_SIZE / 4096));
     }
 
-    v3_unhook_mem(dev->vm, V3_MEM_CORE_ANY, START_ADDR);
+    v3_unhook_mem(video_state->dev->vm, V3_MEM_CORE_ANY, START_ADDR);
 
 
     V3_Free(video_state);
 
 
 static struct v3_device_ops dev_ops = {
-    .free = free_device,
+    .free = (int (*)(void *))free_device,
 };
 
 static int cga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
        V3_Free(video_state);
        return -1;
     }
+  
+    video_state->dev = dev;
 
     video_state->framebuf_pa = (addr_t)V3_AllocPages(FRAMEBUF_SIZE / 4096);
     video_state->framebuf = V3_VAddr((void *)(video_state->framebuf_pa));
 
     return v3_stream_write(state->stream, buf, length);
 }
 
-static int stream_free(struct vm_device * dev) {
-    struct stream_state * state = (struct stream_state *)(dev->private_data);
-
+static int stream_free(struct stream_state * state) {
     v3_stream_close(state->stream);
 
     // detach host event
 
 
 static struct v3_device_ops dev_ops = {
-    .free = stream_free,
+    .free = (int (*)(void *))stream_free,
 };
 
 static int stream_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
 
 }
 
 
-static int cons_free(struct vm_device * dev) {
-    struct cons_state * state = (struct cons_state *)dev->private_data;
-
+static int cons_free(struct cons_state * state) {
     v3_console_close(state->cons);
 
     // remove host event
 };
 
 static struct v3_device_ops dev_ops = {
-    .free = cons_free,
+    .free = (int (*)(void *))cons_free,
 };
 
 static int cons_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) 
 
     return model->ops->get_capacity(model->private_data);
 }
 
-static int model_free(struct vm_device * dev) {
-    return -1;
+static int model_free(struct disk_state * model) {
+
+    // unhook from frontend
+
+    V3_Free(model);
+    return 0;
 }
 
 
 
 
 static struct v3_device_ops dev_ops = {
-    .free = model_free,
+    .free = (int (*)(void *))model_free,
 };
 
 
 
 
 
 
-static int disk_free(struct vm_device * dev) {
-    struct disk_state * disk = dev->private_data;
-
+static int disk_free(struct disk_state * disk) {
     v3_file_close(disk->fd);
     
     V3_Free(disk);
 }
 
 static struct v3_device_ops dev_ops = {
-    .free = disk_free,
+    .free = (int (*)(void *))disk_free,
 };
 
 
 
 
 
 
-static int generic_free(struct vm_device * dev) {
-    struct generic_internal * state = (struct generic_internal *)(dev->private_data);
-
+static int generic_free(struct generic_internal * state) {
     PrintDebug("generic: deinit_device\n");
 
     V3_Free(state);
 
 
 static struct v3_device_ops dev_ops = { 
-    .free = generic_free, 
+    .free = (int (*)(void *))generic_free, 
 };
 
 
 
 
 
 
-static int i440_free(struct vm_device * dev) {
-    struct i440_state * state = dev->private_data;
+static int i440_free(struct i440_state * state) {
 
     // unregister from PCI
 
 }
 
 static struct v3_device_ops dev_ops = {
-    .free = i440_free,
+    .free = (int (*)(void *))i440_free,
 
 };
 
 
 
 
 
-static int ide_free(struct vm_device * dev) {
-    // unhook io ports....
-
+static int ide_free(struct ide_internal * ide) {
 
     // deregister from PCI?
 
-
+    V3_Free(ide);
 
     return 0;
 }
 
 
 static struct v3_device_ops dev_ops = {
-    .free = ide_free,
+    .free = (int (*)(void *))ide_free,
 
 };
 
 
 
 
 
-static int io_apic_free(struct vm_device * dev) {
-    //  struct guest_info * info = dev->vm;
+static int io_apic_free(struct io_apic_state * ioapic) {
+
+    // unregister intr router
+
+    // unhook memory
+
+    V3_Free(ioapic);
 
     return 0;
 }
 
 
 static struct v3_device_ops dev_ops = {
-    .free = io_apic_free,
+    .free = (int (*)(void *))io_apic_free,
 
 };
 
 
 
 
 
-static int keyboard_free(struct vm_device * dev) {
+static int keyboard_free(struct keyboard_internal * kbd) {
     
+
+    // unhook host events
+
+    V3_Free(kbd);
     return 0;
 }
 
 }
 
 static struct v3_device_ops dev_ops = { 
-    .free = keyboard_free,
+    .free = (int (*)(void *))keyboard_free,
 
 };
 
 
 };
 
 
-static int virtio_free(struct vm_device * dev) {
-    return -1;
-}
+
 
 static int virtio_reset(struct virtio_balloon_state * virtio) {
 
 }
 
 
+static int virtio_free(struct virtio_balloon_state * virtio) {
+
+    // unregister from PCI
+
+    V3_Free(virtio);
+    return 0;
+}
 
 
 static struct v3_device_ops dev_ops = {
-    .free = virtio_free,
+    .free = (int (*)(void *))virtio_free,
 
 };
 
 
 };
 
 
-static int virtio_free(struct vm_device * dev) {
-    return -1;
-}
+
 
 static int blk_reset(struct virtio_blk_state * virtio) {
 
 }
 
 
+static int virtio_free(struct virtio_dev_state * virtio) {
+    
+    V3_Free(virtio);
+
+    return 0;
+}
+
 
 
 static struct v3_device_ops dev_ops = {
-    .free = virtio_free,
+    .free = (int (*)(void *))virtio_free,
 
 };
 
 
 #define ERR_VIRTIO_TXQ_DISABLED 6
 
 
-static int virtio_free(struct vm_device * dev) 
-{
-       
-    return 0;
-}
+
 
 static int virtio_init_state(struct virtio_net_state * virtio) 
 {
     return ret_val;
 }
 
+static int virtio_free(struct virtio_net_state * virtio) {
+       
+    // unregister from PCI
+
+    V3_Free(virtio);
+    return 0;
+}
+
 
 static struct v3_device_ops dev_ops = {
-    .free = virtio_free,
+    .free = (int (*)(void *))virtio_free,
 };
 
 
 
 }
 
 
+int virtio_free(struct virtio_sym_state * virtio_state) {
+
+    // unregister from PCI
+
+    V3_Free(virtio_state);
+    return 0;
+}
 
    
 
 static struct v3_device_ops dev_ops = {
-    .free = NULL,
+    .free = (int (*)(void *))virtio_free,
 };
 
 
     memset(virtio_state, 0, sizeof(struct virtio_sym_state));
 
 
-    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, virtio_state);
-    if (v3_attach_device(vm, dev) == -1) {
+    struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, virtio_state);
+
+    if (dev == NULL) {
        PrintError("Could not attach device %s\n", dev_id);
+       V3_Free(virtio_state);
        return -1;
     }
 
 
        if (!pci_dev) {
            PrintError("Could not register PCI Device\n");
+           v3_remove_device(dev);
            return -1;
        }
        
 
 }
 
 
-static int virtio_free(struct vm_device * dev) 
-{
-       
+static int virtio_free(struct virtio_sym_state * virtio_state) {
+    // unregister from PCI
+
+    V3_Free(virtio_state);
     return 0;
 }
 
 
 static struct v3_device_ops dev_ops = {
-    .free = virtio_free,
+    .free = (int (*)(void *))virtio_free,
 };
 
 
 
 }
 
 
+static int virtio_free(struct virtio_vnet_state * vnet_state) {
+
+    // unregister from PCI
+
+    V3_Free(vnet_state);
+    return 0;
+}
+
 
 static struct v3_device_ops dev_ops = {
-    .free = NULL,
-    .reset = NULL,
-    .start = NULL,
-    .stop = NULL,
+    .free = (int (*)(void *))virtio_free,
 };
 
 static int dev_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
 
 
 
 
-static int disk_free(struct vm_device * dev) {
+static int disk_free(struct disk_state * disk) {
+
+    v3_socket_close(disk->socket);
+
+    V3_Free(disk);
     return 0;
 }
 
 static struct v3_device_ops dev_ops = {
-    .free = disk_free,
+    .free = (int (*)(void *))disk_free,
 };
 
 
 
 }
 
 
-static int vnet_nic_free(struct vm_device * dev) {
-    struct nic_bridge_state * bridge = dev->private_data;
+static int vnet_nic_free(struct nic_bridge_state * bridge) {
 
     /*detach from front device */
 
 }
 
 static struct v3_device_ops dev_ops = {
-    .free = vnet_nic_free,
+    .free = (int (*)(void *))vnet_nic_free,
 
 };
 
 
 
 
 
-static int nvram_free(struct vm_device * dev) {
+static int nvram_free(struct nvram_internal * nvram_state) {
+
+    // unregister host events
+
+    V3_Free(nvram_state);
     return 0;
 }
 
 
 
 static struct v3_device_ops dev_ops = {  
-    .free = nvram_free,
+    .free = (int (*)(void *))nvram_free,
 };
 
 
 
 
 
 
-static int debug_free(struct vm_device * dev) {
+static int debug_free(struct debug_state * state) {
 
+    // unregister hypercall
+
+    V3_Free(state);
     return 0;
 };
 
 
 
 static struct v3_device_ops dev_ops = {
-    .free = debug_free,
+    .free = (int (*)(void *))debug_free,
 };
 
 
 
 
 
 
-static int pci_free(struct vm_device * dev) {
-    
-    return 0;
-}
-
 
 
 static void init_pci_busses(struct pci_internal * pci_state) {
 }
 
 
+static int pci_free(struct pci_internal * pci_state) {
+
+    // cleanup devices (?)
+    
+    V3_Free(pci_state);
+    return 0;
+}
 
 
 static struct v3_device_ops dev_ops = {
-    .free = pci_free,
+    .free = (int (*)(void *))pci_free,
 
 };
 
 
 
 
 
-static int piix_free(struct vm_device * dev) {
+static int piix_free(struct v3_southbridge * piix3) {
+
+    // unregister pci
+
+    V3_Free(piix3);
     return 0;
 }
 
 
 static struct v3_device_ops dev_ops = {
-    .free = piix_free,
+    .free = (int (*)(void *))piix_free,
 };
 
 
 
 
 
 
-static int disk_free(struct vm_device * dev) {
+static int disk_free(struct disk_state * state) {
+
+    V3_Free(state);
     return 0;
 }
 
 static struct v3_device_ops dev_ops = {
-    .free = disk_free,
+    .free = (int (*)(void *))disk_free,
 };
 
 
 
     return length;
 }
 
-static int serial_free(struct vm_device * dev) {
+static int serial_free(struct serial_state * state) {
+
+    V3_Free(state);
     return 0;
 }
 
 
 
 static struct v3_device_ops dev_ops = {
-    .free = serial_free,
+    .free = (int (*)(void *))serial_free,
 };
 
 
 
     .scroll = scroll,
 };
 
-static int cons_free(struct vm_device * dev) {
-    return -1;
+static int cons_free(struct cons_state * state) {
+
+    // kill thread... ?
+
+    V3_Free(state);
+    return 0;
 }
 
 
 static struct v3_device_ops dev_ops = {
-    .free = cons_free,
+    .free = (int (*)(void *))cons_free,
 };
 
 
 
 }
 
 
-static int blk_free(struct vm_device * dev) {
-    return -1;
+static int blk_free(struct blk_state * blk) {
+    V3_FreePages((void *)blk->blk_base_addr, blk->capacity / 4096);
+
+    V3_Free(blk);
+    return 0;
 }
 
 
 
 
 static struct v3_device_ops dev_ops = {
-    .free = blk_free,
+    .free = (int (*)(void *))blk_free,
 
 };
 
 
 }
 
 
-static int vnet_nic_free(struct vm_device * dev) {
+static int vnet_nic_free(struct vnet_nic_state * vnetnic) {
+    
+
+    V3_Free(vnetnic);
     return 0;
 }
 
 static struct v3_device_ops dev_ops = {
-    .free = vnet_nic_free,
+    .free = (int (*)(void *))vnet_nic_free,
 
 };
 
 
 
     // Wait for all cores to enter CORE_STOPPED state
 
+
+
+    return 0;
+}
+
+
+int v3_free_vm(struct v3_vm_info * vm) {
     // deinitialize guest (free memory, etc...)
 
+    v3_dev_mgr_deinit(vm);
+
     return 0;
 }
 
 
     }
 
     if (dev->ops->free) {
-       dev->ops->free(dev);
+       dev->ops->free(dev->private_data);
     } else {
        PrintError("Error: %s free() not implemented\n",  dev->name);
     }