From: Jack Lange Date: Wed, 29 Jul 2009 20:35:27 +0000 (-0500) Subject: updates to virtio device framework X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=ec75f3ad6503e3c7996e7a445404b8813740804d updates to virtio device framework --- diff --git a/palacios/include/devices/lnx_virtio.h b/palacios/include/devices/lnx_virtio_pci.h similarity index 70% rename from palacios/include/devices/lnx_virtio.h rename to palacios/include/devices/lnx_virtio_pci.h index 9afa483..d60f05d 100644 --- a/palacios/include/devices/lnx_virtio.h +++ b/palacios/include/devices/lnx_virtio_pci.h @@ -18,13 +18,12 @@ */ -#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 @@ -38,6 +37,19 @@ #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)); + diff --git a/palacios/src/devices/lnx_virtio_blk.c b/palacios/src/devices/lnx_virtio_blk.c index f44d616..5b40144 100644 --- a/palacios/src/devices/lnx_virtio_blk.c +++ b/palacios/src/devices/lnx_virtio_blk.c @@ -19,9 +19,10 @@ #include -#include -#include +#include + +#include 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; } diff --git a/palacios/src/devices/pci.c b/palacios/src/devices/pci.c index 970d738..cce7aa8 100644 --- a/palacios/src/devices/pci.c +++ b/palacios/src/devices/pci.c @@ -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); diff --git a/palacios/src/devices/sym_swap.c b/palacios/src/devices/sym_swap.c index ea303e5..9bb795f 100644 --- a/palacios/src/devices/sym_swap.c +++ b/palacios/src/devices/sym_swap.c @@ -19,7 +19,7 @@ #include #include -#include + diff --git a/palacios/src/palacios/vmm_config.c b/palacios/src/palacios/vmm_config.c index f226ea5..73ad311 100644 --- a/palacios/src/palacios/vmm_config.c +++ b/palacios/src/palacios/vmm_config.c @@ -25,7 +25,7 @@ #include #include #include - +#include #include @@ -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; } diff --git a/palacios/src/palacios/vmm_dev_mgr.c b/palacios/src/palacios/vmm_dev_mgr.c index fcbd93c..3492f7c 100644 --- a/palacios/src/palacios/vmm_dev_mgr.c +++ b/palacios/src/palacios/vmm_dev_mgr.c @@ -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);