Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Cleanup and sanity-checking of use of strncpy/strcpy (Coverity static analysis)
[palacios.git] / palacios / src / devices / pci.c
index 3eadbc5..ab14422 100644 (file)
@@ -170,19 +170,19 @@ static void pci_dump_state(struct pci_internal * pci_state) {
     struct rb_node * node = v3_rb_first(&(pci_state->bus_list[0].devices));
     struct pci_device * tmp_dev = NULL;
     
-    PrintDebug("===PCI: Dumping state Begin ==========\n");
+    PrintDebug(VM_NONE, VCORE_NONE, "===PCI: Dumping state Begin ==========\n");
     
     do {
        tmp_dev = rb_entry(node, struct pci_device, dev_tree_node);
 
-       PrintDebug("PCI Device Number: %d (%s):\n", tmp_dev->dev_num,  tmp_dev->name);
-       PrintDebug("irq = %d\n", tmp_dev->config_header.intr_line);
-       PrintDebug("Vend ID: 0x%x\n", tmp_dev->config_header.vendor_id);
-       PrintDebug("Device ID: 0x%x\n", tmp_dev->config_header.device_id);
+       PrintDebug(VM_NONE, VCORE_NONE, "PCI Device Number: %d (%s):\n", tmp_dev->dev_num,  tmp_dev->name);
+       PrintDebug(VM_NONE, VCORE_NONE, "irq = %d\n", tmp_dev->config_header.intr_line);
+       PrintDebug(VM_NONE, VCORE_NONE, "Vend ID: 0x%x\n", tmp_dev->config_header.vendor_id);
+       PrintDebug(VM_NONE, VCORE_NONE, "Device ID: 0x%x\n", tmp_dev->config_header.device_id);
 
     } while ((node = v3_rb_next(node)));
     
-    PrintDebug("====PCI: Dumping state End==========\n");
+    PrintDebug(VM_NONE, VCORE_NONE, "====PCI: Dumping state End==========\n");
 }
 
 #endif
@@ -195,11 +195,11 @@ static int get_free_dev_num(struct pci_bus * bus) {
     int i, j;
 
     for (i = 0; i < sizeof(bus->dev_map); i++) {
-       PrintDebug("i=%d\n", i);
+       PrintDebug(VM_NONE, VCORE_NONE, "i=%d\n", i);
        if (bus->dev_map[i] != 0xff) {
            // availability
            for (j = 0; j < 8; j++) {
-               PrintDebug("\tj=%d\n", j);
+               PrintDebug(VM_NONE, VCORE_NONE, "\tj=%d\n", j);
                if (!(bus->dev_map[i] & (0x1 << j))) {
                    return ((i * 8) + j);
                }
@@ -312,14 +312,14 @@ int v3_pci_hook_config_range(struct pci_device * pci,
     
 
     if (find_cfg_range_hook(pci, start, length)) {
-       PrintError("Tried to hook an already hooked config region\n");
+       PrintError(VM_NONE, VCORE_NONE, "Tried to hook an already hooked config region\n");
        return -1;
     }
     
     hook = V3_Malloc(sizeof(struct cfg_range_hook));
 
     if (!hook) {
-       PrintError("Could not allocate range hook\n");
+       PrintError(VM_NONE, VCORE_NONE, "Could not allocate range hook\n");
        return -1;
     }
 
@@ -427,7 +427,7 @@ int cap_write(struct pci_device * pci, uint32_t offset, void * src, uint_t lengt
     int msix_was_enabled = 0;
 
 
-    V3_Print("CAP write trapped (val=%x, cfg_offset=%d, write_offset=%d)\n", *(uint32_t *)src, offset, write_offset);
+    V3_Print(VM_NONE, VCORE_NONE, "CAP write trapped (val=%x, cfg_offset=%d, write_offset=%d)\n", *(uint32_t *)src, offset, write_offset);
 
     if (cap_type == PCI_CAP_MSI) {
        struct msi_msg_ctrl * msg_ctrl = cap_ptr;
@@ -449,10 +449,10 @@ int cap_write(struct pci_device * pci, uint32_t offset, void * src, uint_t lengt
        if (cap_type == PCI_CAP_MSI) {
            struct msi_msg_ctrl * msg_ctrl = cap_ptr;
 
-           V3_Print("MSI Cap Ctrl=%x\n", *(uint16_t *)pci->msi_cap);
-           V3_Print("MSI ADDR=%x\n", *(uint32_t *)(cap_ptr + 2));
-           V3_Print("MSI HI ADDR=%x\n", *(uint32_t *)(cap_ptr + 6));
-           V3_Print("MSI Data=%x\n", *(uint16_t *)(cap_ptr + 10));
+           V3_Print(VM_NONE, VCORE_NONE, "MSI Cap Ctrl=%x\n", *(uint16_t *)pci->msi_cap);
+           V3_Print(VM_NONE, VCORE_NONE, "MSI ADDR=%x\n", *(uint32_t *)(cap_ptr + 2));
+           V3_Print(VM_NONE, VCORE_NONE, "MSI HI ADDR=%x\n", *(uint32_t *)(cap_ptr + 6));
+           V3_Print(VM_NONE, VCORE_NONE, "MSI Data=%x\n", *(uint16_t *)(cap_ptr + 10));
 
            if (msg_ctrl->cap_64bit) {
                if (msg_ctrl->per_vect_mask) {
@@ -492,7 +492,7 @@ int cap_write(struct pci_device * pci, uint32_t offset, void * src, uint_t lengt
        if (cap_type == PCI_CAP_MSI) {
            struct msi_msg_ctrl * msg_ctrl = cap_ptr;
            
-           V3_Print("msi_was_enabled=%d, msi_is_enabled=%d\n", msi_was_enabled,  msg_ctrl->msi_enable);
+           V3_Print(VM_NONE, VCORE_NONE, "msi_was_enabled=%d, msi_is_enabled=%d\n", msi_was_enabled,  msg_ctrl->msi_enable);
 
            if ((msg_ctrl->msi_enable == 1) && (msi_was_enabled == 0)) {
                pci->irq_type = IRQ_MSI;
@@ -577,19 +577,19 @@ static int init_pci_cap(struct pci_device * pci, pci_cap_type_t cap_type, uint_t
 static int scan_pci_caps(struct pci_device * pci) {
     uint_t cap_offset = pci->config_header.cap_ptr;
         
-    V3_Print("Scanning for Capabilities (cap_offset=%d)\n", cap_offset);
+    V3_Print(VM_NONE, VCORE_NONE, "Scanning for Capabilities (cap_offset=%d)\n", cap_offset);
 
     while (cap_offset != 0) {
        uint8_t id = pci->config_space[cap_offset];
        uint8_t next = pci->config_space[cap_offset + 1];
 
-       V3_Print("Found Capability 0x%x at offset %d (0x%x)\n", 
+       V3_Print(VM_NONE, VCORE_NONE, "Found Capability 0x%x at offset %d (0x%x)\n", 
                 id, cap_offset, cap_offset);
 
        struct pci_cap * cap = V3_Malloc(sizeof(struct pci_cap));
 
        if (!cap) {
-           PrintError("Error allocating PCI CAP info\n");
+           PrintError(VM_NONE, VCORE_NONE, "Error allocating PCI CAP info\n");
            return -1;
        }
        memset(cap, 0, sizeof(struct pci_cap));
@@ -613,7 +613,7 @@ static int scan_pci_caps(struct pci_device * pci) {
     // Hook Cap pointer to return cached config space value
     if (v3_pci_hook_config_range(pci, 0x34, 1, 
                                 NULL, NULL, NULL) == -1) {
-       PrintError("Could not hook cap pointer\n");
+       PrintError(VM_NONE, VCORE_NONE, "Could not hook cap pointer\n");
        return -1;
     }
     
@@ -651,7 +651,7 @@ int v3_pci_enable_capability(struct pci_device * pci, pci_cap_type_t cap_type) {
     }
 
 
-    V3_Print("Found Capability %x at %x (%d)\n", cap_type, cap->offset, cap->offset);
+    V3_Print(VM_NONE, VCORE_NONE, "Found Capability %x at %x (%d)\n", cap_type, cap->offset, cap->offset);
 
     // found the capability
 
@@ -698,11 +698,11 @@ int v3_pci_enable_capability(struct pci_device * pci, pci_cap_type_t cap_type) {
     }
 
 
-    V3_Print("Hooking capability range (offset=%d, size=%d)\n", cap->offset, size);
+    V3_Print(VM_NONE, VCORE_NONE, "Hooking capability range (offset=%d, size=%d)\n", cap->offset, size);
 
     if (v3_pci_hook_config_range(pci, cap->offset, size + 2, 
                                 cap_write, NULL, cap) == -1) {
-       PrintError("Could not hook config range (start=%d, size=%d)\n", 
+       PrintError(VM_NONE, VCORE_NONE, "Could not hook config range (start=%d, size=%d)\n", 
                   cap->offset + 2, size);
        return -1;
     }
@@ -724,10 +724,10 @@ static int addr_port_read(struct guest_info * core, ushort_t port, void * dst, u
     int reg_offset = port & 0x3;
     uint8_t * reg_addr = ((uint8_t *)&(pci_state->addr_reg.val)) + reg_offset;
 
-    PrintDebug("Reading PCI Address Port (%x): %x len=%d\n", port, pci_state->addr_reg.val, length);
+    PrintDebug(core->vm_info, core, "Reading PCI Address Port (%x): %x len=%d\n", port, pci_state->addr_reg.val, length);
 
     if (reg_offset + length > 4) {
-       PrintError("Invalid Address port write\n");
+       PrintError(core->vm_info, core, "Invalid Address port write\n");
        return -1;
     }
 
@@ -743,14 +743,14 @@ static int addr_port_write(struct guest_info * core, ushort_t port, void * src,
     uint8_t * reg_addr = ((uint8_t *)&(pci_state->addr_reg.val)) + reg_offset;
 
     if (reg_offset + length > 4) {
-       PrintError("Invalid Address port write\n");
+       PrintError(core->vm_info, core, "Invalid Address port write\n");
        return -1;
     }
 
     // Set address register
     memcpy(reg_addr, src, length);
 
-    PrintDebug("Writing PCI Address Port(%x): AddrReg=%x (op_val = %x, len=%d) \n", port, pci_state->addr_reg.val, *(uint32_t *)src, length);
+    PrintDebug(core->vm_info, core, "Writing PCI Address Port(%x): AddrReg=%x (op_val = %x, len=%d) \n", port, pci_state->addr_reg.val, *(uint32_t *)src, length);
 
     return length;
 }
@@ -770,13 +770,14 @@ static int data_port_read(struct guest_info * core, uint16_t port, void * dst, u
 
 
     pci_dev = get_device(&(pci_state->bus_list[0]), pci_state->addr_reg.dev_num, pci_state->addr_reg.fn_num);
+
     
     if (pci_dev == NULL) {
        memset(dst, 0xff, length);
        return length;
     } 
 
-    PrintDebug("Reading PCI Data register. bus = %d, dev = %d, fn = %d, reg = %d (%x), cfg_reg = %x\n", 
+    PrintDebug(core->vm_info, core, "Reading PCI Data register. bus = %d, dev = %d, fn = %d, reg = %d (%x), cfg_reg = %x\n", 
               pci_state->addr_reg.bus_num, 
               pci_state->addr_reg.dev_num, 
               pci_state->addr_reg.fn_num,
@@ -794,15 +795,21 @@ static int data_port_read(struct guest_info * core, uint16_t port, void * dst, u
 
            if (cfg_hook->read) {
                cfg_hook->read(pci_dev, reg_num + i, cfg_dst, range_len, cfg_hook->private_data);
-           }
+           } else {
+            if (pci_dev->config_read) {
+                if (pci_dev->config_read(pci_dev, reg_num + i, cfg_dst, range_len, pci_dev->priv_data) != 0) {
+                    PrintError(core->vm_info, core, "Error in config_read from PCI device (%s)\n", pci_dev->name);
+                }
+            }
+        }
            
            bytes_left -= range_len;
            i += range_len;
        } else {
            if (pci_dev->config_read) {
-               if (pci_dev->config_read(pci_dev, reg_num + i, cfg_dst, 1, pci_dev->priv_data) != 0) {
-                   PrintError("Error in config_read from PCI device (%s)\n", pci_dev->name);
-               }
+            if (pci_dev->config_read(pci_dev, reg_num + i, cfg_dst, 1, pci_dev->priv_data) != 0) {
+                PrintError(core->vm_info, core, "Error in config_read from PCI device (%s)\n", pci_dev->name);
+            }
            }
 
            bytes_left--;
@@ -812,7 +819,7 @@ static int data_port_read(struct guest_info * core, uint16_t port, void * dst, u
 
     memcpy(dst, &(pci_dev->config_space[reg_num]), length);
            
-    PrintDebug("\tVal=%x, len=%d\n", *(uint32_t *)dst, length);
+    PrintDebug(core->vm_info, core, "\tVal=%x, len=%d\n", *(uint32_t *)dst, length);
 
     return length;
 }
@@ -826,15 +833,15 @@ static int bar_update(struct pci_device * pci_dev, uint32_t offset,
     int bar_num = (bar_offset - 0x10) / 4;
     uint32_t new_val = *(uint32_t *)src;
     
-    PrintDebug("Updating BAR Register  (Dev=%s) (bar=%d) (old_val=0x%x) (new_val=0x%x)\n", 
-              pci_dev->name, bar_num, bar->val, new_val);
+    PrintDebug(VM_NONE, VCORE_NONE, "Updating BAR Register  (Dev=%s) (bar=%d) (old_val=0x%x) (new_val=0x%x) (length=%d)\n", 
+              pci_dev->name, bar_num, bar->val, new_val, length);
 
     // Cache the changes locally
     memcpy(&(pci_dev->config_space[offset]), src, length);
 
     if (bar->type == PCI_BAR_PASSTHROUGH) {
         if (bar->bar_write(bar_num, (void *)(pci_dev->config_space + bar_offset), bar->private_data) == -1) {
-           PrintError("Error in Passthrough bar write operation\n");
+           PrintError(VM_NONE, VCORE_NONE, "Error in Passthrough bar write operation\n");
            return -1;
        }
        
@@ -845,22 +852,27 @@ static int bar_update(struct pci_device * pci_dev, uint32_t offset,
 
     *(uint32_t *)(pci_dev->config_space + offset) &= bar->mask;
 
+    // Handle buggy code that discards the freaking I/O bit...
+    if (bar->type == PCI_BAR_IO && !(new_val & 0x1) ) {
+       PrintError(VM_NONE,VCORE_NONE,"Buggy guest:  Updating BAR %d of device %s discards the I/O bit...\n", bar_num, pci_dev->name);
+       *(uint32_t *)(pci_dev->config_space + offset) |= 0x1;
+       new_val |= 0x1;
+    }
+
+
+    // V3_Print(VM_NONE, VCORE_NONE,"mask=%x written val=%x\n", bar->mask, *(uint32_t *)(pci_dev->config_space + offset));
+
     switch (bar->type) {
        case PCI_BAR_IO: {
            int i = 0;
 
-           PrintDebug("\tRehooking %d IO ports from base 0x%x to 0x%x for %d ports\n",
+           PrintDebug(VM_NONE, VCORE_NONE, "\tRehooking %d IO ports from base 0x%x to 0x%x for %d ports\n",
                       bar->num_ports, PCI_IO_BASE(bar->val), PCI_IO_BASE(new_val),
                       bar->num_ports);
-               
-           // only do this if pci device is enabled....
-           if (!(pci_dev->config_header.status & 0x1)) {
-               PrintError("PCI Device IO space not enabled\n");
-           }
 
            for (i = 0; i < bar->num_ports; i++) {
 
-               PrintDebug("Rehooking PCI IO port (old port=%u) (new port=%u)\n",  
+               PrintDebug(VM_NONE, VCORE_NONE, "Rehooking PCI IO port (old port=%u) (new port=%u)\n",  
                           PCI_IO_BASE(bar->val) + i, PCI_IO_BASE(new_val) + i);
 
                v3_unhook_io_port(pci_dev->vm, PCI_IO_BASE(bar->val) + i);
@@ -869,9 +881,9 @@ static int bar_update(struct pci_device * pci_dev, uint32_t offset,
                                    bar->io_read, bar->io_write, 
                                    bar->private_data) == -1) {
 
-                   PrintError("Could not hook PCI IO port (old port=%u) (new port=%u)\n",  
+                   PrintError(VM_NONE, VCORE_NONE, "Could not hook PCI IO port (old port=%u) (new port=%u)\n",  
                               PCI_IO_BASE(bar->val) + i, PCI_IO_BASE(new_val) + i);
-                   v3_print_io_map(pci_dev->vm);
+                   //v3_print_io_map(pci_dev->vm);
                    return -1;
                }
            }
@@ -888,7 +900,7 @@ static int bar_update(struct pci_device * pci_dev, uint32_t offset,
                                 PCI_MEM32_BASE(new_val) + (bar->num_pages * PAGE_SIZE_4KB),
                                 bar->mem_read, bar->mem_write, pci_dev->priv_data);
            } else {
-               PrintError("Write hooks not supported for PCI\n");
+               PrintError(VM_NONE, VCORE_NONE, "Write hooks not supported for PCI\n");
                return -1;
            }
 
@@ -897,12 +909,12 @@ static int bar_update(struct pci_device * pci_dev, uint32_t offset,
            break;
        }
        case PCI_BAR_NONE: {
-           PrintDebug("Reprogramming an unsupported BAR register (Dev=%s) (bar=%d) (val=%x)\n", 
+           PrintDebug(VM_NONE, VCORE_NONE, "Reprogramming an unsupported BAR register (Dev=%s) (bar=%d) (val=%x)\n", 
                       pci_dev->name, bar_num, new_val);
            break;
        }
        default:
-           PrintError("Invalid Bar Reg updated (bar=%d)\n", bar_num);
+           PrintError(VM_NONE, VCORE_NONE, "Invalid Bar Reg updated (bar=%d)\n", bar_num);
            return -1;
     }
 
@@ -921,7 +933,7 @@ static int data_port_write(struct guest_info * core, uint16_t port, void * src,
        return length;
     }
 
-    PrintDebug("Writing PCI Data register. bus = %d, dev = %d, fn = %d, reg = %d (0x%x) addr_reg = 0x%x (val=0x%x, len=%d)\n", 
+    PrintDebug(VM_NONE, VCORE_NONE, "Writing PCI Data register. bus = %d, dev = %d, fn = %d, reg = %d (0x%x) addr_reg = 0x%x (val=0x%x, len=%d)\n", 
               pci_state->addr_reg.bus_num, 
               pci_state->addr_reg.dev_num, 
               pci_state->addr_reg.fn_num,
@@ -933,7 +945,7 @@ static int data_port_write(struct guest_info * core, uint16_t port, void * src,
     pci_dev = get_device(&(pci_state->bus_list[0]), pci_state->addr_reg.dev_num, pci_state->addr_reg.fn_num);
     
     if (pci_dev == NULL) {
-       PrintError("Writing configuration space for non-present device (dev_num=%d)\n", 
+       PrintError(VM_NONE, VCORE_NONE, "Writing configuration space for non-present device (dev_num=%d)\n", 
                   pci_state->addr_reg.dev_num); 
        return -1;
     }
@@ -950,7 +962,7 @@ static int data_port_write(struct guest_info * core, uint16_t port, void * src,
            
            if (cfg_hook->write) {
                cfg_hook->write(pci_dev, reg_num + i, (void *)(src + i), range_len, cfg_hook->private_data);
-           }
+           } 
 
            length -= range_len;
            i += range_len;
@@ -987,13 +999,17 @@ static int exp_rom_write(struct pci_device * pci_dev, uint32_t offset,
                         void * src, uint_t length, void * private_data) {
     int bar_offset = offset & ~0x03;
 
+    if (pci_dev->config_write) {
+        pci_dev->config_write(pci_dev, offset, src, length, pci_dev->priv_data);
+    }
+
     if (pci_dev->exp_rom_update) {
        pci_dev->exp_rom_update(pci_dev, (void *)(pci_dev->config_space + bar_offset), pci_dev->priv_data);
        
        return 0;
     }
 
-    PrintError("Expansion ROM update not handled. Will appear to not Exist\n");
+    PrintError(VM_NONE, VCORE_NONE, "Expansion ROM update not handled. Will appear to not Exist\n");
 
     return 0;
 }
@@ -1002,10 +1018,15 @@ static int exp_rom_write(struct pci_device * pci_dev, uint32_t offset,
 static int cmd_write(struct pci_device * pci_dev, uint32_t offset, 
                     void * src, uint_t length, void * private_data) {
 
+    PrintDebug(VM_NONE, VCORE_NONE, "PCI command update!\n");
+
     int i = 0;
 
     struct pci_cmd_reg old_cmd;
     struct pci_cmd_reg new_cmd;
+    if (pci_dev->config_write) {
+        pci_dev->config_write(pci_dev, offset, src, length, pci_dev->priv_data);
+    }
     old_cmd.val = pci_dev->config_header.command;
 
     for (i = 0; i < length; i++) {
@@ -1018,22 +1039,21 @@ static int cmd_write(struct pci_device * pci_dev, uint32_t offset,
 
     new_cmd.val = pci_dev->config_header.command;
 
-
     if (pci_dev->cmd_update) {
-       if ((new_cmd.intx_disable == 1) && (old_cmd.intx_disable == 0)) {
-           pci_dev->irq_type = IRQ_NONE;
-           pci_dev->cmd_update(pci_dev, PCI_CMD_INTX_DISABLE, 0, pci_dev->priv_data);
-       } else if ((new_cmd.intx_disable == 0) && (old_cmd.intx_disable == 1)) {
-           pci_dev->irq_type = IRQ_INTX;
-           pci_dev->cmd_update(pci_dev, PCI_CMD_INTX_ENABLE, 0, pci_dev->priv_data);
-       }
-
-
-       if ((new_cmd.dma_enable == 1) && (old_cmd.dma_enable == 0)) {
-           pci_dev->cmd_update(pci_dev, PCI_CMD_DMA_ENABLE, 0, pci_dev->priv_data);
-       } else if ((new_cmd.dma_enable == 0) && (old_cmd.dma_enable == 1)) {
-           pci_dev->cmd_update(pci_dev, PCI_CMD_DMA_DISABLE, 0, pci_dev->priv_data);
-       }
+        if ((new_cmd.intx_disable == 1) && (old_cmd.intx_disable == 0)) {
+            pci_dev->irq_type = IRQ_NONE;
+            pci_dev->cmd_update(pci_dev, PCI_CMD_INTX_DISABLE, 0, pci_dev->priv_data);
+        } else if ((new_cmd.intx_disable == 0) && (old_cmd.intx_disable == 1)) {
+            pci_dev->irq_type = IRQ_INTX;
+            pci_dev->cmd_update(pci_dev, PCI_CMD_INTX_ENABLE, 0, pci_dev->priv_data);
+        }
+
+
+        if ((new_cmd.dma_enable == 1) && (old_cmd.dma_enable == 0)) {
+            pci_dev->cmd_update(pci_dev, PCI_CMD_DMA_ENABLE, 0, pci_dev->priv_data);
+        } else if ((new_cmd.dma_enable == 0) && (old_cmd.dma_enable == 1)) {
+            pci_dev->cmd_update(pci_dev, PCI_CMD_DMA_DISABLE, 0, pci_dev->priv_data);
+        }
     }
 
     return 0;
@@ -1100,87 +1120,150 @@ static int pci_free(struct pci_internal * pci_state) {
 
 #include <palacios/vmm_sprintf.h>
 
-static int pci_save(struct v3_chkpt_ctx * ctx, void * private_data) {
+static int pci_save_extended(struct v3_chkpt *chkpt, char *id, void * private_data) {
     struct pci_internal * pci = (struct pci_internal *)private_data;
+    struct v3_chkpt_ctx *ctx=0;
     char buf[128];
     int i = 0;    
-    
-    v3_chkpt_save_32(ctx, "ADDR_REG", &(pci->addr_reg.val));
-    v3_chkpt_save_16(ctx, "IO_BASE", &(pci->dev_io_base));
+
+    ctx = v3_chkpt_open_ctx(chkpt,id);
+
+    if (!ctx) { 
+      PrintError(VM_NONE, VCORE_NONE, "Unable to open base context on save\n");
+      goto savefailout;
+    }
+
+    V3_CHKPT_SAVE(ctx, "ADDR_REG", pci->addr_reg.val, savefailout);
+    V3_CHKPT_SAVE(ctx, "IO_BASE", pci->dev_io_base, savefailout);
+
+    v3_chkpt_close_ctx(ctx); ctx=0;
 
     for (i = 0; i < PCI_BUS_COUNT; i++) {
        struct pci_bus * bus = &(pci->bus_list[i]);
        struct rb_node * node = v3_rb_first(&(bus->devices));
        struct pci_device * dev = NULL;
-       struct v3_chkpt_ctx * bus_ctx = NULL;
 
-       snprintf(buf, 128, "pci-%d", i);
+       snprintf(buf, 128, "%s-%d", id, i);
+       
+       ctx = v3_chkpt_open_ctx(chkpt, buf);
        
-       bus_ctx = v3_chkpt_open_ctx(ctx->chkpt, ctx, buf);
+       if (!ctx) { 
+         PrintError(VM_NONE, VCORE_NONE, "Failed to open context for %s\n", buf);
+         goto savefailout;
+       }
+
+       // nothing actually saved on the bus context... (later expansion)
+
+       v3_chkpt_close_ctx(ctx); ctx=0;
 
        while (node) {
-           struct v3_chkpt_ctx * dev_ctx = NULL;
            int bar_idx = 0;
            dev = rb_entry(node, struct pci_device, dev_tree_node);
 
-           snprintf(buf, 128, "pci-%d.%d-%d", i, dev->dev_num, dev->fn_num);
-           dev_ctx = v3_chkpt_open_ctx(bus_ctx->chkpt, bus_ctx, buf);
+           snprintf(buf, 128, "%s-%d.%d-%d", id, i, dev->dev_num, dev->fn_num);
+
+           ctx = v3_chkpt_open_ctx(chkpt, buf);
+           
+           if (!ctx) { 
+             PrintError(VM_NONE, VCORE_NONE, "Failed to open context for device\n");
+             goto savefailout;
+           }
            
-           v3_chkpt_save(dev_ctx, "CONFIG_SPACE", 256, dev->config_space);
+           V3_CHKPT_SAVE(ctx, "CONFIG_SPACE", dev->config_space, savefailout);
 
            for (bar_idx = 0; bar_idx < 6; bar_idx++) {
                snprintf(buf, 128, "BAR-%d", bar_idx);
-               v3_chkpt_save_32(dev_ctx, buf, &(dev->bar[bar_idx].val));
+               V3_CHKPT_SAVE(ctx, buf, dev->bar[bar_idx].val, savefailout);
            }
+           
+           v3_chkpt_close_ctx(ctx); ctx=0;
 
            node = v3_rb_next(node);
        }
     }
 
+// goodout:
 
     return 0;
+    
+ savefailout:
+    PrintError(VM_NONE, VCORE_NONE, "Failed to save PCI\n");
+    if (ctx) { v3_chkpt_close_ctx(ctx); }
+    return -1;
+
 }
 
 
-static int pci_load(struct v3_chkpt_ctx * ctx, void * private_data) {
+static int pci_load_extended(struct v3_chkpt *chkpt, char *id, void * private_data) {
     struct pci_internal * pci = (struct pci_internal *)private_data;
+    struct v3_chkpt_ctx *ctx=0;
     char buf[128];
     int i = 0;    
     
-    v3_chkpt_load_32(ctx, "ADDR_REG", &(pci->addr_reg.val));
-    v3_chkpt_load_16(ctx, "IO_BASE", &(pci->dev_io_base));
+    ctx = v3_chkpt_open_ctx(chkpt,id);
+
+    if (!ctx) { 
+      PrintError(VM_NONE, VCORE_NONE, "Unable to open base context on load\n");
+      goto loadfailout;
+    }
+
+    V3_CHKPT_LOAD(ctx, "ADDR_REG", pci->addr_reg.val, loadfailout);
+    V3_CHKPT_LOAD(ctx, "IO_BASE", pci->dev_io_base, loadfailout);
+
+    v3_chkpt_close_ctx(ctx); ctx=0;
 
     for (i = 0; i < PCI_BUS_COUNT; i++) {
        struct pci_bus * bus = &(pci->bus_list[i]);
        struct rb_node * node = v3_rb_first(&(bus->devices));
        struct pci_device * dev = NULL;
-       struct v3_chkpt_ctx * bus_ctx = NULL;
 
        snprintf(buf, 128, "pci-%d", i);
        
-       bus_ctx = v3_chkpt_open_ctx(ctx->chkpt, ctx, buf);
+       ctx = v3_chkpt_open_ctx(chkpt, buf);
+       
+       if (!ctx) { 
+         PrintError(VM_NONE, VCORE_NONE, "Failed to open context for %s\n", buf);
+         goto loadfailout;
+       }
+
+       // nothing actually saved on the bus context... (later expansion)
+
+       v3_chkpt_close_ctx(ctx); ctx=0;
 
        while (node) {
-           struct v3_chkpt_ctx * dev_ctx = NULL;
            int bar_idx = 0;
            dev = rb_entry(node, struct pci_device, dev_tree_node);
 
            snprintf(buf, 128, "pci-%d.%d-%d", i, dev->dev_num, dev->fn_num);
-           dev_ctx = v3_chkpt_open_ctx(bus_ctx->chkpt, bus_ctx, buf);
+
+           ctx = v3_chkpt_open_ctx(chkpt, buf);
            
-           v3_chkpt_load(dev_ctx, "CONFIG_SPACE", 256, dev->config_space);
+           if (!ctx) { 
+             PrintError(VM_NONE, VCORE_NONE, "Failed to open context for device\n");
+             goto loadfailout;
+           }
+
+           V3_CHKPT_LOAD(ctx, "CONFIG_SPACE", dev->config_space, loadfailout);
 
            for (bar_idx = 0; bar_idx < 6; bar_idx++) {
                snprintf(buf, 128, "BAR-%d", bar_idx);
-               v3_chkpt_load_32(dev_ctx, buf, &(dev->bar[bar_idx].val));
+               V3_CHKPT_LOAD(ctx, buf, dev->bar[bar_idx].val, loadfailout);
            }
 
+           v3_chkpt_close_ctx(ctx); ctx=0;
+
            node = v3_rb_next(node);
        }
     }
 
-
+// goodout:
     return 0;
+
+ loadfailout:
+    PrintError(VM_NONE, VCORE_NONE, "Failed to load PCI\n");
+    if (ctx) { v3_chkpt_close_ctx(ctx); }
+    return -1;
+    
 }
 
 
@@ -1192,8 +1275,8 @@ static int pci_load(struct v3_chkpt_ctx * ctx, void * private_data) {
 static struct v3_device_ops dev_ops = {
     .free = (int (*)(void *))pci_free,
 #ifdef V3_CONFIG_CHECKPOINT
-    .save = pci_save,
-    .load = pci_load
+    .save_extended = pci_save_extended,
+    .load_extended = pci_load_extended
 #endif
 };
 
@@ -1202,16 +1285,22 @@ static struct v3_device_ops dev_ops = {
 
 static int pci_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     struct pci_internal * pci_state = V3_Malloc(sizeof(struct pci_internal));
+
+    if (!pci_state) {
+       PrintError(vm, VCORE_NONE, "Cannot allocate in init\n");
+       return -1;
+    }
+
     int i = 0;
     char * dev_id = v3_cfg_val(cfg, "ID");
     int ret = 0;
     
-    PrintDebug("PCI internal at %p\n",(void *)pci_state);
+    PrintDebug(vm, VCORE_NONE, "PCI internal at %p\n",(void *)pci_state);
     
     struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, pci_state);
     
     if (dev == NULL) {
-       PrintError("Could not attach device %s\n", dev_id);
+       PrintError(vm, VCORE_NONE, "Could not attach device %s\n", dev_id);
        V3_Free(pci_state);
        return -1;
     }
@@ -1222,7 +1311,7 @@ static int pci_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
 
     init_pci_busses(pci_state);
     
-    PrintDebug("Sizeof config header=%d\n", (int)sizeof(struct pci_config_header));
+    PrintDebug(vm, VCORE_NONE, "Sizeof config header=%d\n", (int)sizeof(struct pci_config_header));
     
     for (i = 0; i < 4; i++) {
        ret |= v3_dev_hook_io(dev, CONFIG_ADDR_PORT + i, &addr_port_read, &addr_port_write);
@@ -1230,7 +1319,7 @@ static int pci_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     }
     
     if (ret != 0) {
-       PrintError("Error hooking PCI IO ports\n");
+       PrintError(vm, VCORE_NONE, "Error hooking PCI IO ports\n");
        v3_remove_device(dev);
        return -1;
     }
@@ -1267,7 +1356,7 @@ static inline int init_bars(struct v3_vm_info * vm, struct pci_device * pci_dev)
                    if (v3_hook_io_port(vm, bar->default_base_port + j,
                                        bar->io_read, bar->io_write, 
                                        bar->private_data) == -1) {
-                       PrintError("Could not hook default io port %x\n", bar->default_base_port + j);
+                       PrintError(vm, VCORE_NONE, "Could not hook default io port %x\n", bar->default_base_port + j);
                        return -1;
                    }
                }
@@ -1279,6 +1368,7 @@ static inline int init_bars(struct v3_vm_info * vm, struct pci_device * pci_dev)
            bar->mask = ~((bar->num_pages << 12) - 1);
            bar->mask |= 0xf; // preserve the configuration flags
 
+
            if (bar->default_base_addr != 0xffffffff) {
                bar->val = bar->default_base_addr & bar->mask;
            } else {
@@ -1293,7 +1383,7 @@ static inline int init_bars(struct v3_vm_info * vm, struct pci_device * pci_dev)
                                 bar->mem_read, bar->mem_write, pci_dev->priv_data);
            } else if (bar->mem_write) {
                // write hook
-               PrintError("Write hooks not supported for PCI devices\n");
+               PrintError(vm, VCORE_NONE, "Write hooks not supported for PCI devices\n");
                return -1;
                /*
                  v3_hook_write_mem(pci_dev->vm_dev->vm, bar->default_base_addr, 
@@ -1309,7 +1399,7 @@ static inline int init_bars(struct v3_vm_info * vm, struct pci_device * pci_dev)
            *(uint32_t *)(pci_dev->config_space + bar_offset) = bar->val;
 
        } else if (bar->type == PCI_BAR_MEM24) {
-           PrintError("16 Bit memory ranges not supported (reg: %d)\n", i);
+           PrintError(vm, VCORE_NONE, "16 Bit memory ranges not supported (reg: %d)\n", i);
            return -1;
        } else if (bar->type == PCI_BAR_NONE) {
            bar->val = 0x00000000;
@@ -1320,8 +1410,11 @@ static inline int init_bars(struct v3_vm_info * vm, struct pci_device * pci_dev)
            // Call the bar init function to get the local cached value
            bar->bar_init(i, &(bar->val), bar->private_data);
 
+           // Copy back changes it made
+            *(uint32_t *)(pci_dev->config_space + bar_offset) = bar->val;
+
        } else {
-           PrintError("Invalid BAR type for bar #%d\n", i);
+           PrintError(vm, VCORE_NONE, "Invalid BAR type for bar #%d\n", i);
            return -1;
        }
 
@@ -1418,7 +1511,7 @@ int v3_pci_raise_acked_irq(struct vm_device * pci_bus, struct pci_device * dev,
        struct msi_data * data = NULL;   
        
        if (dev->bar[bar_idx].type != PCI_BAR_MEM32) {
-          PrintError("Non 32bit MSIX BAR registers are not supported\n");
+          PrintError(VM_NONE, VCORE_NONE, "Non 32bit MSIX BAR registers are not supported\n");
           return -1;
        }
 
@@ -1426,7 +1519,7 @@ int v3_pci_raise_acked_irq(struct vm_device * pci_bus, struct pci_device * dev,
        msix_table_gpa += dev->msix_cap->table_offset;
 
        if (v3_gpa_to_hva(&(dev->vm->cores[0]), msix_table_gpa, (void *)&(msix_table)) != 0) {
-          PrintError("Could not translate MSIX Table GPA (%p)\n", (void *)msix_table_gpa);
+          PrintError(VM_NONE, VCORE_NONE, "Could not translate MSIX Table GPA (%p)\n", (void *)msix_table_gpa);
           return -1;
        }
        
@@ -1445,7 +1538,7 @@ int v3_pci_raise_acked_irq(struct vm_device * pci_bus, struct pci_device * dev,
        
 
 
-       V3_Print("Decode MSIX\n");
+       V3_Print(VM_NONE, VCORE_NONE, "Decode MSIX\n");
 
        v3_apic_send_ipi(dev->vm, &ipi, dev->apic_dev);
 
@@ -1491,22 +1584,23 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci,
     int i;
 
     if (dev_num > MAX_BUS_DEVICES) {
-       PrintError("Requested Invalid device number (%d)\n", dev_num);
+       PrintError(VM_NONE, VCORE_NONE, "Requested Invalid device number (%d)\n", dev_num);
        return NULL;
     }
 
     if (dev_num == PCI_AUTO_DEV_NUM) {
-       PrintDebug("Searching for free device number\n");
+       PrintDebug(VM_NONE, VCORE_NONE, "Searching for free device number\n");
        if ((dev_num = get_free_dev_num(bus)) == -1) {
-           PrintError("No more available PCI slots on bus %d\n", bus->bus_num);
+           PrintError(VM_NONE, VCORE_NONE, "No more available PCI slots on bus %d\n", bus->bus_num);
            return NULL;
        }
+       V3_Print(VM_NONE, VCORE_NONE,"assigning dev num %d to device (%s, busnum=%d,fnnum=%d)\n", dev_num, name, bus->bus_num, fn_num);
     }
     
-    PrintDebug("Checking for PCI Device\n");
+    PrintDebug(VM_NONE, VCORE_NONE, "Checking for PCI Device\n");
 
     if (get_device(bus, dev_num, fn_num) != NULL) {
-       PrintError("PCI Device already registered at slot %d on bus %d\n", 
+       PrintError(VM_NONE, VCORE_NONE, "PCI Device already registered at slot %d on bus %d\n", 
                   dev_num, bus->bus_num);
        return NULL;
     }
@@ -1515,7 +1609,7 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci,
     pci_dev = (struct pci_device *)V3_Malloc(sizeof(struct pci_device));
 
     if (pci_dev == NULL) {
-       PrintError("Could not allocate pci device\n");
+       PrintError(VM_NONE, VCORE_NONE, "Could not allocate pci device\n");
        return NULL;
     }
 
@@ -1532,7 +1626,7 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci,
            pci_dev->config_header.header_type = 0x80;
            break;
        default:
-           PrintError("Unhandled PCI Device Type: %d\n", dev_type);
+           PrintError(VM_NONE, VCORE_NONE, "Unhandled PCI Device Type: %d\n", dev_type);
            return NULL;
     }
 
@@ -1543,6 +1637,7 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci,
     pci_dev->fn_num = fn_num;
 
     strncpy(pci_dev->name, name, sizeof(pci_dev->name));
+    pci_dev->name[sizeof(pci_dev->name)-1] = 0;
     pci_dev->vm = pci->vm;
     pci_dev->priv_data = priv_data;
 
@@ -1572,14 +1667,14 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci,
        }
     }
 
-    V3_Print("Scanning for Capabilities\n");
+    V3_Print(VM_NONE, VCORE_NONE, "Scanning for Capabilities\n");
 
     // scan for caps
     scan_pci_caps(pci_dev);
 
     pci_dev->irq_type = IRQ_INTX;
 
-    V3_Print("Caps scanned\n");
+    V3_Print(VM_NONE, VCORE_NONE, "Caps scanned\n");
 
     // hook important regions
     v3_pci_hook_config_range(pci_dev, 0x30, 4, exp_rom_write, NULL, NULL);  // ExpRom
@@ -1626,7 +1721,7 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci,
     }
 
     if (init_bars(pci->vm, pci_dev) == -1) {
-       PrintError("could not initialize bar registers\n");
+       PrintError(VM_NONE, VCORE_NONE, "could not initialize bar registers\n");
        return NULL;
     }