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.


virtio updates
[palacios.git] / palacios / src / devices / lnx_virtio_blk.c
index 4e0c14c..5eefbf8 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,48 +34,159 @@ 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_io_write(uint16_t port, void * src, uint_t length, struct vm_device * dev) {
+    struct virtio_device * virtio_dev = find_virtio_dev(dev);
+    int port_idx = port % virtio->io_range_size;
+    uint8_t * cfg_ptr = (uint8_t *)cfg;
+
+    PrintDebug("VIRTIO BLOCK Write for port %d (index=%d) len=%d, value=%x\n", 
+              port, port_idx,  length, *(uint32_t *)src);
+
+
+
+    switch (port_index) {
+       case VRING_Q_NOTIFY_PORT:
+           // handle output
+           PrintError("Notification\n");
+           return -1;
+           break;
+       case VRING_STATUS_PORT:
+           if (cfg->status == 0) {
+               PrintDebug("Resetting device\n");
+               return -1;
+               //reset
+           }
+           break;
+       default:
+           return -1;
+           break;
+    }
+
+
+
+
+    return length;
 }
 
 
-static int virtio_pci_read(uint16_t port, void * dst, uint_t length, struct vm_device * dev) {
+static int virtio_io_read(uint16_t port, void * dst, uint_t length, struct vm_device * dev) {
+    struct blk_state * virtio = (struct blk_state *)dev->private_data;
+    int port_idx = port % virtio->io_range_size;
+    uint8_t * cfg_ptr = (uint8_t *)cfg;
+
+    PrintDebug("VIRTIO BLOCK Read  for port %d (index =%d), length=%d\n", 
+              port, port_idx, length);
+
+    switch (port_idx) {
+       // search for device....
+       // call and return dev config read
+       default:
+       return -1;
+    }
+
+
+    return length;
+}
+
+struct v3_dev_ops  = {
+    .free = virtio_free,
+    .reset = NULL,
+    .stop = NULL,
+    .start = NULL
+};
+
+
+static int virtio_free(struct vm_device * dev) {
     return -1;
 }
 
-static int virtio_init(struct vm_device * dev) {
-    struct blk_state * virtio = (struct blk_state *)(dev->private_data);
+
+
+
+static struct v3_device_ops dev_ops = {
+    .free = virtio_free,
+    .reset = NULL,
+    .start = NULL,
+    .stop = NULL,
+};
+
+
+
+
+
+
+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 (virtio->pci_bus != NULL) {
+    if (pci_bus == NULL) {
+       PrintError("VirtIO devices require a PCI Bus");
+       return -1;
+    }
+
+    
+    virtio_state  = (struct virtio_blk_state *)V3_Malloc(sizeof(struct virtio_blk_state));
+    memset(virtio_state, 0, sizeof(struct virtio_blk_state));
+
+
+    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;
+    }
+
+
+    // PCI initialization
+    {
        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);
-       
+       int tmp_ports = num_ports;
+       int i;
+
+
 
        // This gets the number of ports, rounded up to a power of 2
-       while (num_ports > 0) {
-           num_ports >>= 1;
-           num_ports_pow2 <<= 1;
+       virtio_state->io_range_size = 1; // must be a power of 2
+
+       while (tmp_ports > 0) {
+           tmp_ports >>= 1;
+           virtio_state->io_range_size <<= 1;
        }
        
-       // reset num_ports 
-       num_ports = sizeof(struct virtio_config) + sizeof(struct blk_config);
-
-       if (num_ports  & ((num_ports_pow2 >> 1) - 1)) {
-           num_ports_pow2 >>= 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;
        }
 
 
@@ -84,14 +196,14 @@ static int virtio_init(struct vm_device * dev) {
 
        bars[0].type = PCI_BAR_IO;
        bars[0].default_base_port = -1;
-       bars[0].num_ports = num_ports_pow2;
+       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, 
+       pci_dev = v3_pci_register_device(pci_bus, PCI_STD_DEVICE, 
                                         0, PCI_AUTO_DEV_NUM, 0,
-                                        "VIRTIO-BLK", bars,
+                                        "LNX_VIRTIO_BLK", bars,
                                         NULL, NULL, NULL, dev);
 
        if (!pci_dev) {
@@ -100,51 +212,29 @@ static int virtio_init(struct vm_device * dev) {
        }
        
        pci_dev->config_header.vendor_id = VIRTIO_VENDOR_ID;
+       pci_dev->config_header.subsystem_vendor_id = VIRTIO_SUBVENDOR_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.max_latency = 1; // ?? (qemu does it...)
-    }
-
-
-
-    return -1;
-}
-
-static int virtio_deinit(struct vm_device * dev) {
-    return -1;
-}
-
-
-
-static struct vm_device_ops dev_ops = {
-    .init = virtio_init, 
-    .deinit = virtio_deinit,
-    .reset = NULL,
-    .start = NULL,
-    .stop = NULL,
-};
 
+       pci_dev->config_header.intr_pin = 1;
 
+       pci_dev->config_header.max_latency = 1; // ?? (qemu does it...)
 
-struct vm_device * v3_create_virtio(struct vm_device * pci_bus) {
-    struct blk_state * virtio = NULL;
 
-    PrintDebug("Creating VirtIO Block device\n");
+       virtio_state->pci_dev = pci_dev;
+       virtio_state->pci_bus = pci_bus;
 
-    if (pci_bus == NULL) {
-       PrintError("VirtIO requires a PCI bus\n");
-       return NULL;
+       /* Block configuration */
     }
+    
+    return 0;
+}
 
 
-    virtio = (struct blk_state *)V3_Malloc(sizeof(struct blk_state));
-
-    virtio->pci_bus = pci_bus;
-
-    return v3_create_device("VIRTIO_BLK", &dev_ops, virtio);
-}
+device_register("LNX_VIRTIO_BLK", virtio_init)