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.


updates to virtio device framework
Jack Lange [Wed, 29 Jul 2009 20:35:27 +0000 (15:35 -0500)]
palacios/include/devices/lnx_virtio_pci.h [moved from palacios/include/devices/lnx_virtio.h with 70% similarity]
palacios/src/devices/lnx_virtio_blk.c
palacios/src/devices/pci.c
palacios/src/devices/sym_swap.c
palacios/src/palacios/vmm_config.c
palacios/src/palacios/vmm_dev_mgr.c

similarity index 70%
rename from palacios/include/devices/lnx_virtio.h
rename to palacios/include/devices/lnx_virtio_pci.h
index 9afa483..d60f05d 100644 (file)
  */
 
 
-#ifndef __DEVICES_LNX_VIRTIO_H__
-#define __DEVICES_LNX_VIRTIO_H__
+#ifndef __DEVICES_LNX_VIRTIO_PCI_H__
+#define __DEVICES_LNX_VIRTIO_PCI_H__
 
 #ifdef __V3VEE__
 
 
-
 /* PCI Vendor IDs (from Qemu) */
 #define VIRTIO_VENDOR_ID    0x1af4 // Redhat/Qumranet
 #define VIRTIO_SUBVENDOR_ID 0x1af4 // Redhat/Qumranet
 
 #define VIRTIO_BLOCK_SUBDEVICE_ID 2
 
+
+
+#define HOST_FEATURES_PORT 0
+#define GUEST_FEATURES_PORT 4
+#define VRING_PG_NUM_PORT 8
+#define VRING_SIZE_PORT 12
+#define VRING_Q_SEL_PORT 14
+#define VRING_Q_NOTIFY_PORT 16
+#define VIRTIO_STATUS_PORT 18
+#define VIRTIO_ISR_PORT 19
+
+
+
 /* The virtio configuration space is a hybrid io/memory mapped model 
  * All IO is done via IO port accesses
  * The IO ports access fields in a virtio data structure, and the base io port 
@@ -58,6 +70,31 @@ struct virtio_config {
 } __attribute__((packed));
 
 
+struct vring_desc {
+    uint64_t addr_gpa;
+    uint32_t length;
+    uint16_t flags;
+    uint16_t next;
+} __attribute__((packed));
+
+struct vring_avail {
+    uint16_t flags;
+    uint16_t index;
+    uint16_t ring[0];
+} __attribute__((packed));
+
+
+struct vring_used_elem {
+    uint32_t id;
+    uint32_t length;
+} __attribute__((packed));
+
+struct vring_used {
+    uint16_t flags;
+    uint16_t index;
+    struct vring_used_elem ring[0];
+} __attribute__((packed));
+
 
 
 
index f44d616..5b40144 100644 (file)
 
 #include <palacios/vmm.h>
 
-#include <devices/lnx_virtio.h>
-#include <devices/pci.h>
+#include <devices/lnx_virtio_pci.h>
+
 
+#include <devices/pci.h>
 
 
 struct blk_config {
@@ -33,23 +34,32 @@ struct blk_config {
     uint8_t sectors;
 } __attribute__((packed));
 
-struct blk_state {
 
-    struct blk_config cfg;
+
+
+/* Host Feature flags */
+#define VIRTIO_BARRIER       0x01       /* Does host support barriers? */
+#define VIRTIO_SIZE_MAX      0x02       /* Indicates maximum segment size */
+#define VIRTIO_SEG_MAX       0x04       /* Indicates maximum # of segments */
+#define VIRTIO_LEGACY_GEOM   0x10       /* Indicates support of legacy geometry */
+
+
+
+struct virtio_blk_state {
+    struct blk_config block_cfg;
+    struct virtio_config virtio_cfg;
 
     struct vm_device * pci_bus;
-};
+    struct pci_device * pci_dev;
 
+    struct virtio_device * virtio_dev; // the virtio device struction for _this_ device
+    
 
+    int io_range_size;
+};
 
-static int virtio_pci_write(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
-    return -1;
-}
 
 
-static int virtio_pci_read(uint16_t port, void * dst, uint_t length, struct vm_device * dev) {
-    return -1;
-}
 
 
 
@@ -59,6 +69,7 @@ static int virtio_free(struct vm_device * dev) {
 
 
 
+
 static struct v3_device_ops dev_ops = {
     .free = virtio_free,
     .reset = NULL,
@@ -70,86 +81,98 @@ static struct v3_device_ops dev_ops = {
 
 
 
-static int virtio_init(struct guest_info * vm, void * cfg_data) {
-    struct blk_state * virtio = NULL;
-    struct vm_device * pci_bus = (struct vm_device *)cfg_data;
 
+static int virtio_init(struct guest_info * vm, void * cfg_data) {
+    struct vm_device * pci_bus = v3_find_dev(vm, (char *)cfg_data);
+    struct virtio_blk_state * virtio_state = NULL;
+    struct pci_device * pci_dev = NULL;
 
     PrintDebug("Initializing VIRTIO Block device\n");
 
     if (pci_bus == NULL) {
-       PrintError("VirtIO requires a PCI bus\n");
+       PrintError("VirtIO devices require a PCI Bus");
        return -1;
     }
 
-    virtio = (struct blk_state *)V3_Malloc(sizeof(struct blk_state));
+    
+    virtio_state  = (struct virtio_blk_state *)V3_Malloc(sizeof(struct virtio_blk_state));
+    memset(virtio_state, 0, sizeof(struct virtio_blk_state));
 
-    virtio->pci_bus = pci_bus;
 
-    struct vm_device * dev = v3_allocate_device("VIRTIO_BLK", &dev_ops, virtio);
+
+
+    struct vm_device * dev = v3_allocate_device("LNX_VIRTIO_BLK", &dev_ops, virtio_state);
     if (v3_attach_device(vm, dev) == -1) {
        PrintError("Could not attach device %s\n", "LNX_VIRTIO_BLK");
        return -1;
     }
 
+    struct v3_pci_bar bars[6];
+    int num_ports = sizeof(struct virtio_config) + sizeof(struct blk_config);
+    int tmp_ports = num_ports;
+    int i;
 
 
-    if (virtio->pci_bus != NULL) {
-       struct v3_pci_bar bars[6];
-       struct pci_device * pci_dev = NULL;
-       int i;
-       int num_ports_pow2 = 1;
-       int num_ports = sizeof(struct virtio_config) + sizeof(struct blk_config);
-       
 
-       // This gets the number of ports, rounded up to a power of 2
-       while (num_ports > 0) {
-           num_ports >>= 1;
-           num_ports_pow2 <<= 1;
-       }
-       
-       // reset num_ports 
-       num_ports = sizeof(struct virtio_config) + sizeof(struct blk_config);
+    // This gets the number of ports, rounded up to a power of 2
+    virtio_state->io_range_size = 1; // must be a power of 2
 
-       if (num_ports  & ((num_ports_pow2 >> 1) - 1)) {
-           num_ports_pow2 >>= 1;
-       }
+    while (tmp_ports > 0) {
+       tmp_ports >>= 1;
+       virtio_state->io_range_size <<= 1;
+    }
+       
+    // this is to account for any low order bits being set in num_ports
+    // if there are none, then num_ports was already a power of 2 so we shift right to reset it
+    if ((num_ports & ((virtio_state->io_range_size >> 1) - 1)) == 0) {
+       virtio_state->io_range_size >>= 1;
+    }
 
 
-       for (i = 0; i < 6; i++) {
-           bars[i].type = PCI_BAR_NONE;
-       }
+    for (i = 0; i < 6; i++) {
+       bars[i].type = PCI_BAR_NONE;
+    }
 
-       bars[0].type = PCI_BAR_IO;
-       bars[0].default_base_port = -1;
-       bars[0].num_ports = num_ports_pow2;
+    bars[0].type = PCI_BAR_IO;
+    bars[0].default_base_port = -1;
+    bars[0].num_ports = virtio_state->io_range_size;
 
-       bars[0].io_read = virtio_pci_read;
-       bars[0].io_write = virtio_pci_write;
+    //    bars[0].io_read = virtio_io_read;
+    //  bars[0].io_write = virtio_io_write;
 
-       pci_dev = v3_pci_register_device(virtio->pci_bus, PCI_STD_DEVICE, 
-                                        0, PCI_AUTO_DEV_NUM, 0,
-                                        "VIRTIO-BLK", bars,
-                                        NULL, NULL, NULL, dev);
+    pci_dev = v3_pci_register_device(pci_bus, PCI_STD_DEVICE, 
+                                    0, PCI_AUTO_DEV_NUM, 0,
+                                    "LNX_VIRTIO_BLK", bars,
+                                    NULL, NULL, NULL, dev);
 
-       if (!pci_dev) {
-           PrintError("Could not register PCI Device\n");
-           return -1;
-       }
+    if (!pci_dev) {
+       PrintError("Could not register PCI Device\n");
+       return -1;
+    }
+       
+    pci_dev->config_header.vendor_id = VIRTIO_VENDOR_ID;
+    pci_dev->config_header.subsystem_vendor_id = VIRTIO_SUBVENDOR_ID;
        
-       pci_dev->config_header.vendor_id = VIRTIO_VENDOR_ID;
-       pci_dev->config_header.device_id = VIRTIO_BLOCK_DEV_ID;
-       pci_dev->config_header.class = PCI_CLASS_STORAGE;
-       pci_dev->config_header.subclass = PCI_STORAGE_SUBCLASS_OTHER;
 
-       pci_dev->config_header.subsystem_vendor_id = VIRTIO_SUBVENDOR_ID;
-       pci_dev->config_header.subsystem_id = VIRTIO_BLOCK_SUBDEVICE_ID;
+    pci_dev->config_header.device_id = VIRTIO_BLOCK_DEV_ID;
+    pci_dev->config_header.class = PCI_CLASS_STORAGE;
+    pci_dev->config_header.subclass = PCI_STORAGE_SUBCLASS_OTHER;
+    
+    pci_dev->config_header.subsystem_id = VIRTIO_BLOCK_SUBDEVICE_ID;
 
-       pci_dev->config_header.max_latency = 1; // ?? (qemu does it...)
-    }
 
+    pci_dev->config_header.intr_pin = 1;
+
+    pci_dev->config_header.max_latency = 1; // ?? (qemu does it...)
+
+
+    virtio_state->pci_dev = pci_dev;
+    virtio_state->pci_bus = pci_bus;
+
+    /* Block configuration */
 
 
+    
     return -1;
 }
 
index 970d738..cce7aa8 100644 (file)
@@ -121,9 +121,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);
        if (bus->dev_map[i] != 0xff) {
            // availability
            for (j = 0; j < 8; j++) {
+               PrintDebug("\tj=%d\n", j);
                if (!(bus->dev_map[i] & (0x1 << j))) {
                    return ((i * 8) + j);
                }
@@ -639,10 +641,12 @@ static inline int init_bars(struct pci_device * pci_dev) {
 
            for (j = 0; j < pci_dev->bar[i].num_ports; j++) {
                // hook IO
-               if (v3_dev_hook_io(pci_dev->vm_dev, pci_dev->bar[i].default_base_port + j,
-                                  pci_dev->bar[i].io_read, pci_dev->bar[i].io_write) == -1) {
-                   PrintError("Could not hook default io port %x\n", pci_dev->bar[i].default_base_port + j);
-                   return -1;
+               if (pci_dev->bar[i].default_base_port != 0xffff) {
+                   if (v3_dev_hook_io(pci_dev->vm_dev, pci_dev->bar[i].default_base_port + j,
+                                      pci_dev->bar[i].io_read, pci_dev->bar[i].io_write) == -1) {
+                       PrintError("Could not hook default io port %x\n", pci_dev->bar[i].default_base_port + j);
+                       return -1;
+                   }
                }
            }
 
@@ -717,13 +721,16 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci,
        return NULL;
     }
 
-    if (dev_num == -1) {
+    if (dev_num == PCI_AUTO_DEV_NUM) {
+       PrintDebug("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);
            return NULL;
        }
     }
     
+    PrintDebug("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", 
                   dev_num, bus->bus_num);
index ea303e5..9bb795f 100644 (file)
@@ -19,7 +19,7 @@
 
 #include <palacios/vmm.h>
 #include <palacios/vmm_dev_mgr.h>
-#include <devices/lnx_virtio.h>
+
 
 
 
index f226ea5..73ad311 100644 (file)
@@ -25,7 +25,7 @@
 #include <palacios/vmm_profiler.h>
 #include <palacios/vmm_mem.h>
 #include <palacios/vmm_hypercall.h>
-
+#include <palacios/vmm_dev_mgr.h>
 
 
 #include <devices/generic.h>
@@ -161,7 +161,7 @@ static int setup_memory_map(struct guest_info * info, struct v3_vm_config * conf
        }
     } else {
        v3_hook_write_mem(info, 0xa0000, 0xc0000, 0xa0000,  passthrough_mem_write, NULL);
-    }  
+    }
 
 #define VGABIOS_START 0x000c0000
 #define ROMBIOS_START 0x000f0000
@@ -188,7 +188,7 @@ static int setup_memory_map(struct guest_info * info, struct v3_vm_config * conf
            return -1;
        }
     }
-#endif    
+#endif
 
     print_shadow_map(info);
 
@@ -199,7 +199,6 @@ static int setup_memory_map(struct guest_info * info, struct v3_vm_config * conf
 
 static int setup_devices(struct guest_info * info, struct v3_vm_config * config_ptr) {
 
-
     v3_create_device(info, "8259A", NULL);
     v3_create_device(info, "KEYBOARD", NULL);
     v3_create_device(info, "8254_PIT", NULL); 
@@ -207,28 +206,25 @@ static int setup_devices(struct guest_info * info, struct v3_vm_config * config_
     v3_create_device(info, "OS_DEBUG", NULL);
     v3_create_device(info, "LAPIC", NULL);
     v3_create_device(info, "IOAPIC", "LAPIC");
-    v3_create_device(info, "PARANET", NULL);
+    v3_create_device(info, "VMNET", NULL);
     
     int use_generic = USE_GENERIC;
 
-
     if (config_ptr->enable_pci == 1) {
-       struct ide_cfg ide_config = {"PCI", "PIIX3"};   
+       struct ide_cfg ide_config = {"PCI", "PIIX3"};
        
        v3_create_device(info, "PCI", NULL);
        v3_create_device(info, "i440FX", "PCI");
        v3_create_device(info, "PIIX3", "PCI");
        
+
+       //      v3_create_device(info, "LNX_VIRTIO_BLK", "PCI");
        v3_create_device(info, "IDE", &ide_config);
     } else {
        v3_create_device(info, "IDE", NULL);
-
     }
 
 
-
-
-
     if (config_ptr->pri_disk_type != NONE) {
        if (config_ptr->pri_disk_type == CDROM) {
            if (config_ptr->pri_disk_con == RAM) {
@@ -246,7 +242,7 @@ static int setup_devices(struct guest_info * info, struct v3_vm_config * config_
                                         config_ptr->pri_disk_info.net.disk_name};
                PrintDebug("Creating NET CD\n");
 
-               v3_create_device(info, "NET-CD", &cfg);    
+               v3_create_device(info, "NET-CD", &cfg);
            }
        } else if (config_ptr->pri_disk_type == HARDDRIVE) {
            if (config_ptr->pri_disk_con == RAM) {
@@ -434,10 +430,7 @@ static int configure_generic(struct guest_info * info, struct v3_vm_config * con
     v3_generic_add_port_range(generic, 0xc100, 0xc1ff, GENERIC_PRINT_AND_PASSTHROUGH);
 #endif
 
-
-
     //  v3_generic_add_port_range(generic, 0x378, 0x400, GENERIC_PRINT_AND_IGNORE);
     
-
     return 0;
 }
index fcbd93c..3492f7c 100644 (file)
@@ -48,11 +48,15 @@ int v3_init_devices() {
     extern struct v3_device_info __start__v3_devices[];
     extern struct v3_device_info __stop__v3_devices[];
     struct v3_device_info * tmp_dev =  __start__v3_devices;
-    int num_devices = (__stop__v3_devices - __start__v3_devices) / sizeof(struct v3_device_info);
     int i = 0;
 
+#ifdef DEBUG_DEV_MGR
+    {
+       int num_devices = (__stop__v3_devices - __start__v3_devices) / sizeof(struct v3_device_info);
+       PrintDebug("%d Virtual devices registered with Palacios\n", num_devices);
+    }
+#endif
 
-    PrintDebug("%d Virtual devices registered with Palacios\n", num_devices);
     PrintDebug("Start addres=%p, Stop address=%p\n", __start__v3_devices, __stop__v3_devices);
 
     master_dev_table = v3_create_htable(0, dev_hash_fn, dev_eq_fn);