*/
-#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
} __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));
+
#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 {
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;
-}
+
static struct v3_device_ops dev_ops = {
.free = virtio_free,
.reset = NULL,
-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;
}
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);
}
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;
+ }
}
}
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);
#include <palacios/vmm.h>
#include <palacios/vmm_dev_mgr.h>
-#include <devices/lnx_virtio.h>
+
#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>
}
} else {
v3_hook_write_mem(info, 0xa0000, 0xc0000, 0xa0000, passthrough_mem_write, NULL);
- }
+ }
#define VGABIOS_START 0x000c0000
#define ROMBIOS_START 0x000f0000
return -1;
}
}
-#endif
+#endif
print_shadow_map(info);
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);
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) {
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) {
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;
}
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);