int v3_create_device(struct v3_vm_info * vm, const char * dev_name, v3_cfg_tree_t * cfg);
 
-
-void v3_free_device(struct vm_device * dev);
-
-
 struct vm_device * v3_find_dev(struct v3_vm_info * info, const char * dev_name);
 
 
                     ushort_t            port);
 
 
+
+struct vm_device * v3_add_device(struct v3_vm_info * vm, char * name, 
+                                struct v3_device_ops * ops, void * private_data);
+int v3_remove_device(struct vm_device * dev);
+
+
 int v3_attach_device(struct v3_vm_info * vm, struct vm_device * dev);
 int v3_detach_device(struct vm_device * dev);
-
 struct vm_device * v3_allocate_device(char * name, struct v3_device_ops * ops, void * private_data);
 
 
 
     V3_ASSERT(pit_state != NULL);
     pit_state->speaker = 0;
 
-    dev = v3_allocate_device(dev_id, &dev_ops, pit_state);
+    dev = v3_add_device(vm, dev_id, &dev_ops, pit_state);
 
-    if (v3_attach_device(vm, dev) == -1) {
+    if (dev == NULL) {
        PrintError("Could not attach device %s\n", dev_id);
        V3_Free(pit_state);
        return -1;
 
     if (ret != 0) {
        PrintError("8254 PIT: Failed to hook IO ports\n");
-       v3_detach_device(dev);
+       v3_remove_device(dev);
        return -1;
     }
 
     pit_state->timer = v3_add_timer(info, &timer_ops, pit_state);
 
     if (pit_state->timer == NULL) {
-       v3_detach_device(dev);
+       v3_remove_device(dev);
        return -1;
     }
 
 
 
 static int pic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     struct pic_internal * state = NULL;
-    state = (struct pic_internal *)V3_Malloc(sizeof(struct pic_internal));
     char * dev_id = v3_cfg_val(cfg, "ID");
+    int ret = 0;
 
     // PIC is only usable in non-multicore environments
     // just hardcode the core context
     struct guest_info * core = &(vm->cores[0]);
 
     V3_ASSERT(state != NULL);
+    
+    state = (struct pic_internal *)V3_Malloc(sizeof(struct pic_internal));
+ 
 
-    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, state);
+    struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, state);
 
-    if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", dev_id);
+    if (dev == NULL) {
+       PrintError("Could not add device %s\n", dev_id);
+       V3_Free(state);
        return -1;
     }
 
     state->slave_state = ICW1;
 
 
-    v3_dev_hook_io(dev, MASTER_PORT1, &read_master_port1, &write_master_port1);
-    v3_dev_hook_io(dev, MASTER_PORT2, &read_master_port2, &write_master_port2);
-    v3_dev_hook_io(dev, SLAVE_PORT1, &read_slave_port1, &write_slave_port1);
-    v3_dev_hook_io(dev, SLAVE_PORT2, &read_slave_port2, &write_slave_port2);
+    ret |= v3_dev_hook_io(dev, MASTER_PORT1, &read_master_port1, &write_master_port1);
+    ret |= v3_dev_hook_io(dev, MASTER_PORT2, &read_master_port2, &write_master_port2);
+    ret |= v3_dev_hook_io(dev, SLAVE_PORT1, &read_slave_port1, &write_slave_port1);
+    ret |= v3_dev_hook_io(dev, SLAVE_PORT2, &read_slave_port2, &write_slave_port2);
 
 
-    v3_dev_hook_io(dev, ELCR1_PORT, &read_elcr_port, &write_elcr_port);
-    v3_dev_hook_io(dev, ELCR2_PORT, &read_elcr_port, &write_elcr_port);
+    ret |= v3_dev_hook_io(dev, ELCR1_PORT, &read_elcr_port, &write_elcr_port);
+    ret |= v3_dev_hook_io(dev, ELCR2_PORT, &read_elcr_port, &write_elcr_port);
+
+    if (ret != 0) {
+       PrintError("Error hooking io ports\n");
+       v3_remove_device(dev);
+       return -1;
+    }
 
     return 0;
 }
 
 
     apic_dev->num_apics = vm->num_cores;
 
-    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, apic_dev);
+    struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, apic_dev);
 
-    if (v3_attach_device(vm, dev) == -1) {
+    if (dev == NULL) {
        PrintError("apic: Could not attach device %s\n", dev_id);
        V3_Free(apic_dev);
        return -1;
 
        if (apic->timer == NULL) {
            PrintError("APIC: Failed to attach timer to core %d\n", i);
-           v3_detach_device(dev);
+           v3_remove_device(dev);
            return -1;
        }
 
 
 
     state = (struct debug_state *)V3_Malloc(sizeof(struct debug_state));
 
-    V3_ASSERT(state != NULL);
+    if (state == NULL) {
+       PrintError("Could not allocate bochs debug state\n");
+       return -1;
+    }
 
     PrintDebug("Creating Bochs Debug Device\n");
-    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, state);
+    struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, state);
 
-    if (v3_attach_device(vm, dev) == -1) {
+    if (dev == NULL) {
        PrintError("Could not attach device %s\n", dev_id);
        V3_Free(state);
        return -1;
     
     if (ret != 0) {
        PrintError("Could not hook Bochs Debug IO Ports\n");
-       v3_detach_device(dev);
+       v3_remove_device(dev);
        return -1;
     }
   
 
     struct video_internal * video_state = NULL;
     char * dev_id = v3_cfg_val(cfg, "ID");
     char * passthrough_str = v3_cfg_val(cfg, "passthrough");
+    int ret = 0;
     
     PrintDebug("video: init_device\n");
 
     video_state = (struct video_internal *)V3_Malloc(sizeof(struct video_internal));
     memset(video_state, 0, sizeof(struct video_internal));
 
-    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, video_state);
+    struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, video_state);
 
-    if (v3_attach_device(vm, dev) == -1) {
+    if (dev == NULL) {
        PrintError("Could not attach device %s\n", dev_id);
        V3_Free(video_state);
        return -1;
     }
 
 
-    v3_dev_hook_io(dev, 0x3b0, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3b1, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3b2, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3b3, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3b4, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3b5, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3b6, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3b7, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3b8, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3b9, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3ba, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3bb, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3c0, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3c1, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3c2, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3c3, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3c4, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3c5, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3c6, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3c7, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3c8, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3c9, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3ca, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3cb, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3cc, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3cd, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3ce, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3cf, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3d0, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3d1, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3d2, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3d3, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3d4, &video_read_port, &crtc_index_write);
-    v3_dev_hook_io(dev, 0x3d5, &video_read_port, &crtc_data_write);
-    v3_dev_hook_io(dev, 0x3d6, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3d7, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3d8, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3d9, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3da, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3db, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3dc, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3dd, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3de, &video_read_port, &video_write_port);
-    v3_dev_hook_io(dev, 0x3df, &video_read_port, &video_write_port);
-
+    ret |= v3_dev_hook_io(dev, 0x3b0, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3b1, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3b2, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3b3, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3b4, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3b5, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3b6, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3b7, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3b8, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3b9, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3ba, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3bb, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3c0, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3c1, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3c2, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3c3, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3c4, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3c5, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3c6, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3c7, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3c8, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3c9, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3ca, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3cb, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3cc, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3cd, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3ce, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3cf, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3d0, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3d1, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3d2, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3d3, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3d4, &video_read_port, &crtc_index_write);
+    ret |= v3_dev_hook_io(dev, 0x3d5, &video_read_port, &crtc_data_write);
+    ret |= v3_dev_hook_io(dev, 0x3d6, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3d7, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3d8, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3d9, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3da, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3db, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3dc, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3dd, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3de, &video_read_port, &video_write_port);
+    ret |= v3_dev_hook_io(dev, 0x3df, &video_read_port, &video_write_port);
+
+    if (ret != 0) {
+       PrintError("Error allocating cga io port\n");
+       v3_remove_device(dev);
+       return -1;
+    }
 
     return 0;
 }
 
 
     memset(state, 0, sizeof(struct stream_state));
 
-    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, state);
+    struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, state);
 
     if (dev == NULL) {
        PrintError("Could not allocate device %s\n", dev_id);
        return -1;
     }
 
-    if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", dev_id);
-       V3_Free(state);
-       return -1;
-    }
+
 
     state->stream = v3_stream_open(vm, stream_name);
 
     if (state->stream == NULL) {
        PrintError("Could not open stream %s\n", stream_name);
-       v3_detach_device(dev);
+       v3_remove_device(dev);
        return -1;
     }
 
                            state, &(state->push_fn_arg)) == -1) {
        PrintError("Could not connect %s to frontend %s\n", 
                   dev_id, v3_cfg_val(frontend_cfg, "tag"));
-       v3_detach_device(dev);
+       v3_remove_device(dev);
        return -1;
     }
 
 
     }
 
     /* allocate device */
-    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, state);
-    V3_ASSERT(dev);
-
-    /* attach device to virtual machine */
-    if (v3_attach_device(vm, dev) == -1) {
+    struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, state);
+ 
+    if (dev == NULL) {
        PrintError("Could not attach device %s\n", dev_id);
        V3_Free(state);
        return -1;
 
 
     char * dev_id = v3_cfg_val(cfg, "ID");
 
-    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, NULL);
+    struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, NULL);
 
-    if (v3_attach_device(vm, dev) == -1) {
+    if (dev == NULL) {
        PrintError("Could not attach device %s\n", dev_id);
        return -1;
     }
 
     if (v3_dev_add_blk_frontend(vm, dev_id, connect_fn, NULL) == -1) {
        PrintError("Could not register %s as block frontend\n", dev_id);
+       v3_remove_device(dev);
        return -1;
     }
 
 
 
     memset(disk, 0, sizeof(struct disk_state));
 
+    struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, disk);
+
+    if (dev == NULL) {
+       PrintError("Could not attach device %s\n", dev_id);
+       V3_Free(disk);
+       return -1;
+    }
+
+
     disk->fd = v3_file_open(vm, path, flags);
 
     if (disk->fd == NULL) {
        PrintError("Could not open file disk:%s\n", path);
-       V3_Free(disk);
+       v3_remove_device(dev);
        return -1;
     }
 
     PrintDebug("Registering FILEDISK %s (path=%s, fd=%lu, size=%lu)\n",
               dev_id, path, file->fd, file->capacity);
 
-    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, disk);
-
-    if (v3_attach_device(vm, dev) == -1) {
-       PrintError("Could not attach device %s\n", dev_id);
-       v3_file_close(disk->fd);
-       V3_Free(disk);
-       return -1;
-    }
 
     if (v3_dev_connect_blk(vm, v3_cfg_val(frontend_cfg, "tag"), 
                           &blk_ops, frontend_cfg, disk) == -1) {
        PrintError("Could not connect %s to frontend %s\n", 
                   dev_id, v3_cfg_val(frontend_cfg, "tag"));
-       v3_file_close(disk->fd);
-       V3_Free(disk);
+       v3_remove_device(dev);
        return -1;
     }
     
 
     
     memset(state, 0, sizeof(struct generic_internal));
     
-    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, state);
+    struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, state);
 
-    if (v3_attach_device(vm, dev) == -1) {
+    if (dev == NULL) {
        PrintError("Could not attach device %s\n", dev_id);
        V3_Free(state);
        return -1;
            mode = GENERIC_PRINT_AND_PASSTHROUGH;
        } else {
            PrintError("Invalid Mode %s\n", mode_str);
-           v3_detach_device(dev);
+           v3_remove_device(dev);
            return -1;
        }
        
        if (add_port_range(dev, start, end, mode) == -1) {
            PrintError("Could not add port range %d-%d\n", start, end);
-           v3_detach_device(dev);
+           v3_remove_device(dev);
            return -1;
        }
 
 
     struct i440_state * state = NULL;
     struct vm_device * pci = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
     char * dev_id = v3_cfg_val(cfg, "ID");
+    int ret = 0;
 
     if (!pci) {
        PrintError("could not find PCI Device\n");
 
     state->pci = pci;
        
-    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, state);
+    struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, state);
 
-    if (v3_attach_device(vm, dev) == -1) {
+    if (dev == NULL) {
        PrintError("Could not attach device %s\n", dev_id);
        V3_Free(state);
        return -1;
     }
 
     for (i = 0; i < 4; i++) {
-       v3_dev_hook_io(dev, 0x0cf8 + i, &io_read, &io_write);
-       v3_dev_hook_io(dev, 0x0cfc + i, &io_read, &io_write);
+       ret |= v3_dev_hook_io(dev, 0x0cf8 + i, &io_read, &io_write);
+       ret |= v3_dev_hook_io(dev, 0x0cfc + i, &io_read, &io_write);
+    }
+
+    if (ret != 0) {
+       PrintError("Error hooking i440FX io ports\n");
+       v3_remove_device(dev);
+       return -1;
     }
 
     for (i = 0; i < 6; i++) {
                                     NULL, NULL, NULL, state);
 
     if (!pci_dev) {
-       v3_detach_device(dev);
+       v3_remove_device(dev);
        return -1;
     }
 
 
 static int ide_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     struct ide_internal * ide  = NULL;
     char * dev_id = v3_cfg_val(cfg, "ID");
+    int ret = 0;
 
     PrintDebug("IDE: Initializing IDE\n");
 
     memset(ide, 0, sizeof(struct ide_internal));
 
     ide->vm = vm;
-
     ide->pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus"));
 
     if (ide->pci_bus != NULL) {
 
     PrintDebug("IDE: Creating IDE bus x 2\n");
 
-    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, ide);
+    struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, ide);
 
-    if (v3_attach_device(vm, dev) == -1) {
+    if (dev == NULL) {
        PrintError("Could not attach device %s\n", dev_id);
-       v3_free_device(dev);
        V3_Free(ide);
        return -1;
     }
 
     if (init_ide_state(ide) == -1) {
        PrintError("Failed to initialize IDE state\n");
-       v3_detach_device(dev);
+       v3_remove_device(dev);
        return -1;
     }
 
     PrintDebug("Connecting to IDE IO ports\n");
 
-    v3_dev_hook_io(dev, PRI_DATA_PORT, 
-                  &ide_read_data_port, &write_data_port);
-    v3_dev_hook_io(dev, PRI_FEATURES_PORT, 
-                  &read_port_std, &write_port_std);
-    v3_dev_hook_io(dev, PRI_SECT_CNT_PORT, 
-                  &read_port_std, &write_port_std);
-    v3_dev_hook_io(dev, PRI_SECT_NUM_PORT, 
-                  &read_port_std, &write_port_std);
-    v3_dev_hook_io(dev, PRI_CYL_LOW_PORT, 
-                  &read_port_std, &write_port_std);
-    v3_dev_hook_io(dev, PRI_CYL_HIGH_PORT, 
-                  &read_port_std, &write_port_std);
-    v3_dev_hook_io(dev, PRI_DRV_SEL_PORT, 
-                  &read_port_std, &write_port_std);
-    v3_dev_hook_io(dev, PRI_CMD_PORT, 
-                  &read_port_std, &write_cmd_port);
-
-    v3_dev_hook_io(dev, SEC_DATA_PORT, 
-                  &ide_read_data_port, &write_data_port);
-    v3_dev_hook_io(dev, SEC_FEATURES_PORT, 
-                  &read_port_std, &write_port_std);
-    v3_dev_hook_io(dev, SEC_SECT_CNT_PORT, 
-                  &read_port_std, &write_port_std);
-    v3_dev_hook_io(dev, SEC_SECT_NUM_PORT, 
-                  &read_port_std, &write_port_std);
-    v3_dev_hook_io(dev, SEC_CYL_LOW_PORT, 
-                  &read_port_std, &write_port_std);
-    v3_dev_hook_io(dev, SEC_CYL_HIGH_PORT, 
-                  &read_port_std, &write_port_std);
-    v3_dev_hook_io(dev, SEC_DRV_SEL_PORT, 
-                  &read_port_std, &write_port_std);
-    v3_dev_hook_io(dev, SEC_CMD_PORT, 
-                  &read_port_std, &write_cmd_port);
+    ret |= v3_dev_hook_io(dev, PRI_DATA_PORT, 
+                         &ide_read_data_port, &write_data_port);
+    ret |= v3_dev_hook_io(dev, PRI_FEATURES_PORT, 
+                         &read_port_std, &write_port_std);
+    ret |= v3_dev_hook_io(dev, PRI_SECT_CNT_PORT, 
+                         &read_port_std, &write_port_std);
+    ret |= v3_dev_hook_io(dev, PRI_SECT_NUM_PORT, 
+                         &read_port_std, &write_port_std);
+    ret |= v3_dev_hook_io(dev, PRI_CYL_LOW_PORT, 
+                         &read_port_std, &write_port_std);
+    ret |= v3_dev_hook_io(dev, PRI_CYL_HIGH_PORT, 
+                         &read_port_std, &write_port_std);
+    ret |= v3_dev_hook_io(dev, PRI_DRV_SEL_PORT, 
+                         &read_port_std, &write_port_std);
+    ret |= v3_dev_hook_io(dev, PRI_CMD_PORT, 
+                         &read_port_std, &write_cmd_port);
+
+    ret |= v3_dev_hook_io(dev, SEC_DATA_PORT, 
+                         &ide_read_data_port, &write_data_port);
+    ret |= v3_dev_hook_io(dev, SEC_FEATURES_PORT, 
+                         &read_port_std, &write_port_std);
+    ret |= v3_dev_hook_io(dev, SEC_SECT_CNT_PORT, 
+                         &read_port_std, &write_port_std);
+    ret |= v3_dev_hook_io(dev, SEC_SECT_NUM_PORT, 
+                         &read_port_std, &write_port_std);
+    ret |= v3_dev_hook_io(dev, SEC_CYL_LOW_PORT, 
+                         &read_port_std, &write_port_std);
+    ret |= v3_dev_hook_io(dev, SEC_CYL_HIGH_PORT, 
+                         &read_port_std, &write_port_std);
+    ret |= v3_dev_hook_io(dev, SEC_DRV_SEL_PORT, 
+                         &read_port_std, &write_port_std);
+    ret |= v3_dev_hook_io(dev, SEC_CMD_PORT, 
+                         &read_port_std, &write_cmd_port);
   
 
-    v3_dev_hook_io(dev, PRI_CTRL_PORT, 
-                  &read_port_std, &write_port_std);
+    ret |= v3_dev_hook_io(dev, PRI_CTRL_PORT, 
+                         &read_port_std, &write_port_std);
 
-    v3_dev_hook_io(dev, SEC_CTRL_PORT, 
-                  &read_port_std, &write_port_std);
+    ret |= v3_dev_hook_io(dev, SEC_CTRL_PORT, 
+                         &read_port_std, &write_port_std);
   
 
-    v3_dev_hook_io(dev, SEC_ADDR_REG_PORT, 
-                  &read_port_std, &write_port_std);
+    ret |= v3_dev_hook_io(dev, SEC_ADDR_REG_PORT, 
+                         &read_port_std, &write_port_std);
 
-    v3_dev_hook_io(dev, PRI_ADDR_REG_PORT, 
-                  &read_port_std, &write_port_std);
+    ret |= v3_dev_hook_io(dev, PRI_ADDR_REG_PORT, 
+                         &read_port_std, &write_port_std);
 
 
+    if (ret != 0) {
+       PrintError("Error hooking IDE IO port\n");
+       v3_remove_device(dev);
+       return -1;
+    }
 
 
     if (ide->pci_bus) {
 
        if (pci_dev == NULL) {
            PrintError("Failed to register IDE BUS %d with PCI\n", i); 
+           v3_remove_device(dev);
            return -1;
        }
 
 
     if (v3_dev_add_blk_frontend(vm, dev_id, connect_fn, (void *)ide) == -1) {
        PrintError("Could not register %s as frontend\n", dev_id);
-       v3_detach_device(dev);
+       v3_remove_device(dev);
        return -1;
     }
     
 
 
     ioapic->apic_dev_data = apic_dev;
 
-    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, ioapic);
+    struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, ioapic);
 
-
-    if (v3_attach_device(vm, dev) == -1) {
+    if (dev == NULL) {
        PrintError("ioapic: Could not attach device %s\n", dev_id);
+       V3_Free(ioapic);
        return -1;
     }
 
-
     v3_register_intr_router(vm, &router_ops, ioapic);
 
     init_ioapic_state(ioapic, vm->num_cores);
 
 static int keyboard_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     struct keyboard_internal * kbd = NULL;
     char * dev_id = v3_cfg_val(cfg, "ID");
+    int ret = 0;
 
     PrintDebug("keyboard: init_device\n");
 
 
     kbd->vm = vm;
 
-    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, kbd);
+    struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, kbd);
 
-    if (v3_attach_device(vm, dev) == -1) {
+    if (dev == NULL) {
        PrintError("Could not attach device %s\n", dev_id);
+       V3_Free(kbd);
        return -1;
     }
 
 
 
     // hook ports
-    v3_dev_hook_io(dev, KEYBOARD_64H, &keyboard_read_status, &keyboard_write_command);
-    v3_dev_hook_io(dev, KEYBOARD_60H, &keyboard_read_input, &keyboard_write_output);
+    ret |= v3_dev_hook_io(dev, KEYBOARD_64H, &keyboard_read_status, &keyboard_write_command);
+    ret |= v3_dev_hook_io(dev, KEYBOARD_60H, &keyboard_read_input, &keyboard_write_output);
+
+    if (ret != 0) {
+       PrintError("Error hooking keyboard IO ports\n");
+       v3_remove_device(dev);
+       return -1;
+    }
 
     v3_hook_host_event(vm, HOST_KEYBOARD_EVT, V3_HOST_EVENT_HANDLER(key_event_handler), kbd);
     v3_hook_host_event(vm, HOST_MOUSE_EVT, V3_HOST_EVENT_HANDLER(mouse_event_handler), kbd);
 
     }
 
     
-    virtio_state  = (struct virtio_balloon_state *)V3_Malloc(sizeof(struct virtio_balloon_state));
+    virtio_state = (struct virtio_balloon_state *)V3_Malloc(sizeof(struct virtio_balloon_state));
     memset(virtio_state, 0, sizeof(struct virtio_balloon_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;
     }
 
-
-
-
     // PCI initialization
     {
        struct v3_pci_bar bars[6];
 
        if (!pci_dev) {
            PrintError("Could not register PCI Device\n");
+           v3_remove_device(dev);
            return -1;
        }
        
 
     virtio_state->pci_bus = pci_bus;
 
 
-    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 (v3_dev_add_blk_frontend(vm, dev_id, connect_fn, (void *)virtio_state) == -1) {
        PrintError("Could not register %s as block frontend\n", dev_id);
+       v3_remove_device(dev);
        return -1;
     }
 
 
     virtio_state->pci_bus = pci_bus;
     virtio_state->vm = vm;
 
-    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("Virtio NIC: Could not attach device %s\n", dev_id);
+       V3_Free(virtio_state);
        return -1;
     }
 
     if (v3_dev_add_net_frontend(vm, dev_id, connect_fn, (void *)virtio_state) == -1) {
        PrintError("Virtio NIC: Could not register %s as net frontend\n", dev_id);
+       v3_remove_device(dev);
        return -1;
     }
        
 
 
 
 
-    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, virtio_state);
+    struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, virtio_state);
 
-    if (v3_attach_device(vm, dev) == -1) {
+    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;
        }
        
     }
     
 
-
     V3_Print("SYMMOD: %d available sym modules\n", virtio_state->sym_cfg.avail_mods);
 
     virtio_reset(virtio_state);
 
        
     vnet_state->vm = vm;
 
-    struct vm_device * dev = v3_allocate_device(name, &dev_ops, vnet_state);
+    struct vm_device * dev = v3_add_device(vm, name, &dev_ops, vnet_state);
 
-    if (v3_attach_device(vm, dev) == -1) {
+    if (dev == NULL) {
        PrintError("Could not attach device %s\n", name);
+       V3_Free(vnet_state);
        return -1;
     }
 
 
        if (!pci_dev) {
            PrintError("Could not register PCI Device\n");
+           v3_remove_device(dev);
            return -1;
        }
        
     brg_ops.poll = vnet_virtio_poll;
 
     V3_Print("Registering Virtio device as vnet bridge\n");
+
     v3_vnet_add_bridge(vm, &brg_ops, CTL_VM_BRIDGE, (void *)vnet_state);
 
     return 0;
 
     disk->port = atoi(port_str);
     disk->vm = vm;
 
-    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, disk);
+    struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, disk);
 
-    if (v3_attach_device(vm, dev) == -1) {
+    if (dev == NULL) {
        PrintError("Could not attach device %s\n", dev_id);
+       V3_Free(disk);
        return -1;
     }
 
     if (socket_init(disk) == -1) {
        PrintError("could not initialize network connection\n");
+       v3_remove_device(dev);
        return -1;
     }
 
     if (v3_dev_connect_blk(vm, v3_cfg_val(frontend_cfg, "tag"), 
                           &blk_ops, frontend_cfg, disk) == -1) {
        PrintError("Could not connect %s to frontend\n", dev_id);
+       v3_remove_device(dev);
        return -1;
     }
 
 
     bridge = (struct nic_bridge_state *)V3_Malloc(sizeof(struct nic_bridge_state));
     memset(bridge, 0, sizeof(struct nic_bridge_state));
 
-    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, bridge);
+    struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, bridge);
 
-    if (v3_attach_device(vm, dev) == -1) {
+    if (dev == NULL) {
        PrintError("Could not attach device %s\n", dev_id);
+       V3_Free(bridge);
        return -1;
     }
 
                           &(bridge->net_ops), frontend_cfg, bridge) == -1) {
        PrintError("Could not connect %s to frontend %s\n", 
                   dev_id, v3_cfg_val(frontend_cfg, "tag"));
+       v3_remove_device(dev);
        return -1;
     }
 
 
     struct nvram_internal * nvram_state = NULL;
     struct vm_device * ide = v3_find_dev(vm, v3_cfg_val(cfg, "storage"));
     char * dev_id = v3_cfg_val(cfg, "ID");
+    int ret = 0;
 
     if (!ide) {
        PrintError("Could not find IDE device\n");
     nvram_state->ide = ide;
     nvram_state->vm = vm;
 
-    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, nvram_state);
+    struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, nvram_state);
 
-
-    if (v3_attach_device(vm, dev) == -1) {
+    if (dev == NULL) {
        PrintError("Could not attach device %s\n", dev_id);
+       V3_Free(nvram_state);
        return -1;
     }
 
     init_nvram_state(vm, nvram_state);
 
     // hook ports
-    v3_dev_hook_io(dev, NVRAM_REG_PORT, NULL, &nvram_write_reg_port);
-    v3_dev_hook_io(dev, NVRAM_DATA_PORT, &nvram_read_data_port, &nvram_write_data_port);
+    ret |= v3_dev_hook_io(dev, NVRAM_REG_PORT, NULL, &nvram_write_reg_port);
+    ret |= v3_dev_hook_io(dev, NVRAM_DATA_PORT, &nvram_read_data_port, &nvram_write_data_port);
   
+    if (ret != 0) {
+       PrintError("Error hooking NVRAM IO ports\n");
+       v3_remove_device(dev);
+       return -1;
+    }
+
     v3_hook_host_event(vm, HOST_TIMER_EVT, V3_HOST_EVENT_HANDLER(handle_timer_event), nvram_state);
 
     return 0;
 
 
     PrintDebug("Creating OS Debug Device\n");
 
-    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, state);
+    struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, state);
 
-
-    if (v3_attach_device(vm, dev) == -1) {
+    if (dev == NULL) {
        PrintError("Could not attach device %s\n", dev_id);
+       V3_Free(state);
+       return -1;
+    }
+
+    if (v3_dev_hook_io(dev, DEBUG_PORT1,  NULL, &handle_gen_write) == -1) {
+       PrintError("Error hooking OS debug IO port\n");
+       v3_remove_device(dev);
        return -1;
     }
 
-    v3_dev_hook_io(dev, DEBUG_PORT1,  NULL, &handle_gen_write);
     v3_register_hypercall(vm, OS_DEBUG_HCALL, handle_hcall, state);
 
     state->debug_offset = 0;
 
     struct pci_internal * pci_state = V3_Malloc(sizeof(struct pci_internal));
     int i = 0;
     char * dev_id = v3_cfg_val(cfg, "ID");
+    int ret = 0;
     
     PrintDebug("PCI internal at %p\n",(void *)pci_state);
     
-    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, pci_state);
+    struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, pci_state);
     
-    if (v3_attach_device(vm, dev) == -1) {
+    if (dev == NULL) {
        PrintError("Could not attach device %s\n", dev_id);
+       V3_Free(pci_state);
        return -1;
     }
 
     PrintDebug("Sizeof config header=%d\n", (int)sizeof(struct pci_config_header));
     
     for (i = 0; i < 4; i++) {
-       v3_dev_hook_io(dev, CONFIG_ADDR_PORT + i, &addr_port_read, &addr_port_write);
-       v3_dev_hook_io(dev, CONFIG_DATA_PORT + i, &data_port_read, &data_port_write);
+       ret |= v3_dev_hook_io(dev, CONFIG_ADDR_PORT + i, &addr_port_read, &addr_port_write);
+       ret |= v3_dev_hook_io(dev, CONFIG_DATA_PORT + i, &data_port_read, &data_port_write);
+    }
+    
+    if (ret != 0) {
+       PrintError("Error hooking PCI IO ports\n");
+       v3_remove_device(dev);
+       return -1;
     }
 
     return 0;
    struct pci_internal * pci_state = (struct pci_internal *)pci_bus->private_data;
    struct pci_bus * bus = &(pci_state->bus_list[bus_num]);
 
-   return bus->raise_pci_irq(bus->irq_dev_data, dev);
+   return bus->raise_pci_irq(dev, bus->irq_dev_data);
 }
 
 int v3_pci_lower_irq(struct vm_device * pci_bus, int bus_num, struct pci_device * dev) {
    struct pci_internal * pci_state = (struct pci_internal *)pci_bus->private_data;
    struct pci_bus * bus = &(pci_state->bus_list[bus_num]);
 
-   return bus->lower_pci_irq(bus->irq_dev_data, dev);
+   return bus->lower_pci_irq(dev, bus->irq_dev_data);
 }
 
 // if dev_num == -1, auto assign 
 
     strncpy(state->name, dev_id, 32);
 
 
-    dev = v3_allocate_device(dev_id, &dev_ops, state);
+    dev = v3_add_device(vm, dev_id, &dev_ops, state);
 
-    if (v3_attach_device(vm, dev) == -1) {
+    if (dev == NULL) {
        PrintError("Could not attach device %s\n", dev_id);
+       V3_Free(state);
        return -1;
     }
 
        PrintError("Could not find PCI Device %s:%s\n", 
                   v3_cfg_val(cfg, "vendor_id"), 
                   v3_cfg_val(cfg, "device_id"));
+       v3_remove_device(dev);
        return 0;
     }
 
 
     piix3->pci_bus = pci;
     piix3->type = V3_SB_PIIX3;
     
-    dev = v3_allocate_device(dev_id, &dev_ops, piix3);
+    dev = v3_add_device(vm, dev_id, &dev_ops, piix3);
 
-    if (v3_attach_device(vm, dev) == -1) {
+    if (dev == NULL) {
        PrintError("Could not attach device %s\n", dev_id);
+       V3_Free(piix3);
        return -1;
     }
 
     PrintDebug("Created PIIX3\n");
 
-    return setup_pci(piix3);
+    if (setup_pci(piix3) == -1) {
+       v3_remove_device(dev);
+       return -1;
+    }
+
+    return 0;
 }
 
 
 
 
     v3_cfg_tree_t * frontend_cfg = v3_cfg_subtree(cfg, "frontend");
 
-    disk = (struct disk_state *)V3_Malloc(sizeof(struct disk_state));
-    memset(disk, 0, sizeof(struct disk_state));
-
-
     if (!filename) {
        PrintError("Missing filename (%s) for %s\n", filename, dev_id);
        return -1;
        return -1;
     }
 
+
+    disk = (struct disk_state *)V3_Malloc(sizeof(struct disk_state));
+    memset(disk, 0, sizeof(struct disk_state));
+
     disk->disk_image = file->data;
     disk->capacity = file->size;
     PrintDebug("Registering RAMDISK at %p (size=%d)\n", 
               (void *)file->data, (uint32_t)file->size);
 
-    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, disk);
 
-    if (v3_attach_device(vm, dev) == -1) {
+    struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, disk);
+
+    if (dev == NULL) {
        PrintError("Could not attach device %s\n", dev_id);
+       V3_Free(disk);
        return -1;
     }
 
+
     if (v3_dev_connect_blk(vm, v3_cfg_val(frontend_cfg, "tag"), 
                           &blk_ops, frontend_cfg, disk) == -1) {
        PrintError("Could not connect %s to frontend %s\n", 
                   dev_id, v3_cfg_val(frontend_cfg, "tag"));
+       v3_remove_device(dev);
        return -1;
     }
     
 
 static int serial_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     struct serial_state * state = NULL;
     char * dev_id = v3_cfg_val(cfg, "ID");
+    int ret = 0;
 
     state = (struct serial_state *)V3_Malloc(sizeof(struct serial_state));
     
     
     memset(state, 0, sizeof(struct serial_state));
 
-
-
     init_serial_port(&(state->coms[0]));
     init_serial_port(&(state->coms[1]));
     init_serial_port(&(state->coms[2]));
     state->coms[3].irq_number = COM4_IRQ;
 
 
-    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, state);
+    struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, state);
 
-    if (v3_attach_device(vm, dev) == -1) {
+    if (dev == NULL) {
        PrintError("Could not attach device %s\n", dev_id);
+       V3_Free(state);
        return -1;
     }
 
     PrintDebug("Serial device attached\n");
 
-    v3_dev_hook_io(dev, COM1_DATA_PORT, &read_data_port, &write_data_port);
-    v3_dev_hook_io(dev, COM1_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
-    v3_dev_hook_io(dev, COM1_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
-    v3_dev_hook_io(dev, COM1_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
-    v3_dev_hook_io(dev, COM1_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
-    v3_dev_hook_io(dev, COM1_LINE_STATUS_PORT, &read_status_port, &write_status_port);
-    v3_dev_hook_io(dev, COM1_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
-    v3_dev_hook_io(dev, COM1_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
-
-    v3_dev_hook_io(dev, COM2_DATA_PORT, &read_data_port, &write_data_port);
-    v3_dev_hook_io(dev, COM2_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
-    v3_dev_hook_io(dev, COM2_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
-    v3_dev_hook_io(dev, COM2_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
-    v3_dev_hook_io(dev, COM2_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
-    v3_dev_hook_io(dev, COM2_LINE_STATUS_PORT, &read_status_port, &write_status_port);
-    v3_dev_hook_io(dev, COM2_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
-    v3_dev_hook_io(dev, COM2_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
-
-    v3_dev_hook_io(dev, COM3_DATA_PORT, &read_data_port, &write_data_port);
-    v3_dev_hook_io(dev, COM3_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
-    v3_dev_hook_io(dev, COM3_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
-    v3_dev_hook_io(dev, COM3_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
-    v3_dev_hook_io(dev, COM3_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
-    v3_dev_hook_io(dev, COM3_LINE_STATUS_PORT, &read_status_port, &write_status_port);
-    v3_dev_hook_io(dev, COM3_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
-    v3_dev_hook_io(dev, COM3_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
-
-    v3_dev_hook_io(dev, COM4_DATA_PORT, &read_data_port, &write_data_port);
-    v3_dev_hook_io(dev, COM4_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
-    v3_dev_hook_io(dev, COM4_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
-    v3_dev_hook_io(dev, COM4_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
-    v3_dev_hook_io(dev, COM4_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
-    v3_dev_hook_io(dev, COM4_LINE_STATUS_PORT, &read_status_port, &write_status_port);
-    v3_dev_hook_io(dev, COM4_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
-    v3_dev_hook_io(dev, COM4_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
+    ret |= v3_dev_hook_io(dev, COM1_DATA_PORT, &read_data_port, &write_data_port);
+    ret |= v3_dev_hook_io(dev, COM1_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
+    ret |= v3_dev_hook_io(dev, COM1_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+    ret |= v3_dev_hook_io(dev, COM1_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+    ret |= v3_dev_hook_io(dev, COM1_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+    ret |= v3_dev_hook_io(dev, COM1_LINE_STATUS_PORT, &read_status_port, &write_status_port);
+    ret |= v3_dev_hook_io(dev, COM1_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
+    ret |= v3_dev_hook_io(dev, COM1_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
+
+    ret |= v3_dev_hook_io(dev, COM2_DATA_PORT, &read_data_port, &write_data_port);
+    ret |= v3_dev_hook_io(dev, COM2_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
+    ret |= v3_dev_hook_io(dev, COM2_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+    ret |= v3_dev_hook_io(dev, COM2_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+    ret |= v3_dev_hook_io(dev, COM2_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+    ret |= v3_dev_hook_io(dev, COM2_LINE_STATUS_PORT, &read_status_port, &write_status_port);
+    ret |= v3_dev_hook_io(dev, COM2_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
+    ret |= v3_dev_hook_io(dev, COM2_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
+
+    ret |= v3_dev_hook_io(dev, COM3_DATA_PORT, &read_data_port, &write_data_port);
+    ret |= v3_dev_hook_io(dev, COM3_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
+    ret |= v3_dev_hook_io(dev, COM3_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+    ret |= v3_dev_hook_io(dev, COM3_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+    ret |= v3_dev_hook_io(dev, COM3_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+    ret |= v3_dev_hook_io(dev, COM3_LINE_STATUS_PORT, &read_status_port, &write_status_port);
+    ret |= v3_dev_hook_io(dev, COM3_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
+    ret |= v3_dev_hook_io(dev, COM3_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
+
+    ret |= v3_dev_hook_io(dev, COM4_DATA_PORT, &read_data_port, &write_data_port);
+    ret |= v3_dev_hook_io(dev, COM4_IRQ_ENABLE_PORT, &read_ctrl_port, &write_ctrl_port);
+    ret |= v3_dev_hook_io(dev, COM4_FIFO_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+    ret |= v3_dev_hook_io(dev, COM4_LINE_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+    ret |= v3_dev_hook_io(dev, COM4_MODEM_CTRL_PORT, &read_ctrl_port, &write_ctrl_port);
+    ret |= v3_dev_hook_io(dev, COM4_LINE_STATUS_PORT, &read_status_port, &write_status_port);
+    ret |= v3_dev_hook_io(dev, COM4_MODEM_STATUS_PORT, &read_status_port, &write_status_port);
+    ret |= v3_dev_hook_io(dev, COM4_SCRATCH_PORT, &read_ctrl_port, &write_ctrl_port);
+
+    if (ret != 0) {
+       PrintError("Error hooking Serial IO ports\n");
+       v3_remove_device(dev);
+       return -1;
+    }
 
     PrintDebug("Serial ports hooked\n");
 
 
     if (v3_dev_add_char_frontend(vm, dev_id, connect_fn, (void *)state) == -1) {
        PrintError("Could not register %s as frontend\n", dev_id);
+       v3_remove_device(dev);
        return -1;
     }
 
 
     v3_lock_init(&(state->cons_lock));
 
 
-    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, state);
+    struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, state);
 
-    if (v3_attach_device(vm, dev) == -1) {
+    if (dev == NULL) {
        PrintError("Could not attach device %s\n", dev_id);
+       V3_Free(state);
        return -1;
     }
 
 
     memset(blk->blk_space, 0, capacity);
 
 
-    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, blk);
+    struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, blk);
 
-    if (v3_attach_device(vm, dev) == -1) {
+    if (dev == NULL) {
        PrintError("Could not attach device %s\n", dev_id);
+       V3_Free(blk);
        return -1;
     }
 
                           &blk_ops, frontend_cfg, blk) == -1) {
        PrintError("Could not connect %s to frontend %s\n", 
                   dev_id, v3_cfg_val(frontend_cfg, "tag"));
+       v3_remove_device(dev);
        return -1;
     }
 
 
     vnetnic = (struct vnet_nic_state *)V3_Malloc(sizeof(struct vnet_nic_state));
     memset(vnetnic, 0, sizeof(struct vnet_nic_state));
 
-    struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, vnetnic);
+    struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, vnetnic);
 
-    if (v3_attach_device(vm, dev) == -1) {
+    if (dev == NULL) {
        PrintError("Could not attach device %s\n", dev_id);
+       V3_Free(vnetnic);
        return -1;
     }
 
                           &(vnetnic->net_ops), frontend_cfg, vnetnic) == -1) {
        PrintError("Could not connect %s to frontend %s\n", 
                   dev_id, v3_cfg_val(frontend_cfg, "tag"));
+       v3_remove_device(vnetnic);
        return -1;
     }
 
 
     if ((vnet_dev_id = register_to_vnet(vm, vnetnic, dev_id, vnetnic->mac)) == -1) {
        PrintError("Vnet-nic device %s (mac: %s) fails to registered to VNET\n", dev_id, macstr);
+       v3_remove_device(vnetnic);
+       return 0;
     }
+
     vnetnic->vnet_dev_id = vnet_dev_id;
 
     PrintDebug("Vnet-nic device %s (mac: %s, %ld) registered to VNET\n", 
 
     struct vm_device * tmp;
 
     list_for_each_entry_safe(dev, tmp, &(mgr->dev_list), dev_link) {
-       v3_detach_device(dev);
+       v3_remove_device(dev);
     }
 
     v3_free_htable(mgr->blk_table, 0, 0);
 }
 
 
-void v3_free_device(struct vm_device * dev) {
-    V3_Free(dev);
-}
-
 
 
 struct vm_device * v3_find_dev(struct v3_vm_info * vm, const char * dev_name) {
 
 
 
-int v3_detach_device(struct vm_device * dev) {
+int v3_remove_device(struct vm_device * dev) {
     struct vmm_dev_mgr * mgr = &(dev->vm->dev_mgr);
+    struct dev_io_hook * io_hook = NULL;
+    struct dev_io_hook * tmp;
+
+    list_for_each_entry_safe(io_hook, tmp, &(dev->io_hooks), node) {
+       v3_unhook_io_port(dev->vm, io_hook->port);          
+       list_del(&(io_hook->node));
+       V3_Free(io_hook);    
+    }
 
     if (dev->ops->free) {
        dev->ops->free(dev);
 
     dev->vm = NULL;
 
-    v3_free_device(dev);
+    V3_Free(dev);
     return -1;
 }
 
 
-struct vm_device * v3_allocate_device(char * name, 
-                                     struct v3_device_ops * ops, 
-                                     void * private_data) {
+struct vm_device * v3_add_device(struct v3_vm_info * vm,
+                                char * name, 
+                                struct v3_device_ops * ops, 
+                                void * private_data) {
+    struct vmm_dev_mgr * mgr = &(vm->dev_mgr);
     struct vm_device * dev = NULL;
 
-    dev = (struct vm_device*)V3_Malloc(sizeof(struct vm_device));
+    dev = (struct vm_device *)V3_Malloc(sizeof(struct vm_device));
+
+    if (dev == NULL) {
+       return NULL;
+    }
 
     INIT_LIST_HEAD(&(dev->io_hooks));
 
     dev->ops = ops;
     dev->private_data = private_data;
 
-    dev->vm = NULL;
-
-    return dev;
-}
-
-
-int v3_attach_device(struct v3_vm_info * vm, struct vm_device * dev ) {
-    struct vmm_dev_mgr * mgr = &(vm->dev_mgr);
-
     dev->vm = vm;
 
     list_add(&(dev->dev_link), &(mgr->dev_list));
     mgr->num_devs++;
 
-
     v3_htable_insert(mgr->dev_table, (addr_t)(dev->name), (addr_t)dev);
 
-    return 0;
+    return dev;
 }
 
 
-
 void v3_print_dev_mgr(struct v3_vm_info * vm) {
     struct vmm_dev_mgr * mgr = &(vm->dev_mgr);
     struct vm_device * dev;