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.


checkpoint changes to get "reset to BIOS" working.
[palacios.git] / palacios / src / devices / pci.c
index 5a12909..05272a8 100644 (file)
@@ -37,7 +37,7 @@
 
 
 
-#ifndef CONFIG_DEBUG_PCI
+#ifndef V3_CONFIG_DEBUG_PCI
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
@@ -104,7 +104,7 @@ struct pci_internal {
 
 
 
-#ifdef CONFIG_DEBUG_PCI
+#ifdef V3_CONFIG_DEBUG_PCI
 
 static void pci_dump_state(struct pci_internal * pci_state) {
     struct rb_node * node = v3_rb_first(&(pci_state->bus_list[0].devices));
@@ -597,11 +597,6 @@ static int data_port_write(struct guest_info * core, ushort_t port, void * src,
 
 
 
-static int pci_free(struct vm_device * dev) {
-    
-    return 0;
-}
-
 
 
 static void init_pci_busses(struct pci_internal * pci_state) {
@@ -615,11 +610,129 @@ static void init_pci_busses(struct pci_internal * pci_state) {
 }
 
 
+static int pci_free(struct pci_internal * pci_state) {
+    int i;
 
 
-static struct v3_device_ops dev_ops = {
-    .free = pci_free,
+    // cleanup devices
+    for (i = 0; i < PCI_BUS_COUNT; i++) {
+       struct pci_bus * bus = &(pci_state->bus_list[i]);
+       struct rb_node * node = v3_rb_first(&(bus->devices));
+       struct pci_device * dev = NULL;
+
+       while (node) {
+           dev = rb_entry(node, struct pci_device, dev_tree_node);
+           node = v3_rb_next(node);
+           
+           v3_rb_erase(&(dev->dev_tree_node), &(bus->devices));
+           V3_Free(dev);
+       }
+
+    }
+    
+    V3_Free(pci_state);
+    return 0;
+}
+
+#ifdef V3_CONFIG_CHECKPOINT
+
+#include <palacios/vmm_sprintf.h>
+
+static int pci_save(struct v3_chkpt_ctx * ctx, void * private_data) {
+    struct pci_internal * pci = (struct pci_internal *)private_data;
+    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));
+
+    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\n", i);
+       
+       bus_ctx = v3_chkpt_open_ctx(ctx->chkpt, ctx, buf);
+
+       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);
+           
+           v3_chkpt_save(dev_ctx, "CONFIG_SPACE", 256, dev->config_space);
+
+           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));
+           }
+
+           node = v3_rb_next(node);
+       }
+    }
 
+
+    return 0;
+}
+
+
+static int pci_load(struct v3_chkpt_ctx * ctx, void * private_data) {
+    struct pci_internal * pci = (struct pci_internal *)private_data;
+    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));
+
+    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\n", i);
+       
+       bus_ctx = v3_chkpt_open_ctx(ctx->chkpt, ctx, buf);
+
+       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);
+           
+           v3_chkpt_load(dev_ctx, "CONFIG_SPACE", 256, dev->config_space);
+
+           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));
+           }
+
+           node = v3_rb_next(node);
+       }
+    }
+
+
+    return 0;
+}
+
+
+#endif
+
+
+
+
+static struct v3_device_ops dev_ops = {
+    .free = (int (*)(void *))pci_free,
+#ifdef V3_CONFIG_CHECKPOINT
+    .save = pci_save,
+    .load = pci_load
+#endif
 };
 
 
@@ -904,7 +1017,7 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci,
     // add the device
     add_device_to_bus(bus, pci_dev);
 
-#ifdef CONFIG_DEBUG_PCI
+#ifdef V3_CONFIG_DEBUG_PCI
     pci_dump_state(pci_state);
 #endif
 
@@ -972,7 +1085,7 @@ struct pci_device * v3_pci_register_passthrough_device(struct vm_device * pci,
     // add the device
     add_device_to_bus(bus, pci_dev);
 
-#ifdef CONFIG_DEBUG_PCI
+#ifdef V3_CONFIG_DEBUG_PCI
     pci_dump_state(pci_state);
 #endif