X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fdevices%2Flnx_virtio_blk.c;h=fd9ec6191842c5dd41e5cbf89262484a0fc73444;hb=8a3dbb70c29175bad79764a0b2f3961b98138bb2;hp=989459a6abe7e176b8d32ef6703e7703565be856;hpb=18ff442f1ddb03f4371550ca74a96f834e13457c;p=palacios.git diff --git a/palacios/src/devices/lnx_virtio_blk.c b/palacios/src/devices/lnx_virtio_blk.c index 989459a..fd9ec61 100644 --- a/palacios/src/devices/lnx_virtio_blk.c +++ b/palacios/src/devices/lnx_virtio_blk.c @@ -26,7 +26,7 @@ -#ifndef CONFIG_DEBUG_VIRTIO_BLK +#ifndef V3_CONFIG_DEBUG_VIRTIO_BLK #undef PrintDebug #define PrintDebug(fmt, args...) #endif @@ -104,9 +104,7 @@ struct virtio_blk_state { }; -static int virtio_free(struct vm_device * dev) { - return -1; -} + static int blk_reset(struct virtio_blk_state * virtio) { @@ -122,16 +120,7 @@ static int blk_reset(struct virtio_blk_state * virtio) { } -static int virtio_reset(struct vm_device * dev) { - struct virtio_dev_state * dev_state = (struct virtio_dev_state *)(dev->private_data); - struct virtio_blk_state * blk_state = NULL; - - list_for_each_entry(blk_state, &(dev_state->dev_list), dev_link) { - blk_reset(blk_state); - } - return 0; -} static int handle_read_op(struct virtio_blk_state * blk_state, uint8_t * buf, uint64_t * sector, uint64_t len) { int ret = -1; @@ -163,7 +152,7 @@ static int handle_block_op(struct guest_info * core, struct virtio_blk_state * b uint8_t * buf = NULL; PrintDebug("Handling Block op\n"); - if (guest_pa_to_host_va(core, buf_desc->addr_gpa, (addr_t *)&(buf)) == -1) { + if (v3_gpa_to_hva(core, buf_desc->addr_gpa, (addr_t *)&(buf)) == -1) { PrintError("Could not translate buffer address\n"); return -1; } @@ -241,7 +230,7 @@ static int handle_kick(struct guest_info * core, struct virtio_blk_state * blk_s PrintDebug("Header Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d\n", hdr_desc, (void *)(hdr_desc->addr_gpa), hdr_desc->length, hdr_desc->flags, hdr_desc->next); - if (guest_pa_to_host_va(core, hdr_desc->addr_gpa, &(hdr_addr)) == -1) { + if (v3_gpa_to_hva(core, hdr_desc->addr_gpa, &(hdr_addr)) == -1) { PrintError("Could not translate block header address\n"); return -1; } @@ -279,7 +268,7 @@ static int handle_kick(struct guest_info * core, struct virtio_blk_state * blk_s PrintDebug("Status Descriptor (ptr=%p) gpa=%p, len=%d, flags=%x, next=%d\n", status_desc, (void *)(status_desc->addr_gpa), status_desc->length, status_desc->flags, status_desc->next); - if (guest_pa_to_host_va(core, status_desc->addr_gpa, (addr_t *)&(status_ptr)) == -1) { + if (v3_gpa_to_hva(core, status_desc->addr_gpa, (addr_t *)&(status_ptr)) == -1) { PrintError("Could not translate status address\n"); return -1; } @@ -341,19 +330,19 @@ static int virtio_io_write(struct guest_info * core, uint16_t port, void * src, // round up to next page boundary. blk_state->queue.ring_used_addr = (blk_state->queue.ring_used_addr + 0xfff) & ~0xfff; - if (guest_pa_to_host_va(core, blk_state->queue.ring_desc_addr, (addr_t *)&(blk_state->queue.desc)) == -1) { + if (v3_gpa_to_hva(core, blk_state->queue.ring_desc_addr, (addr_t *)&(blk_state->queue.desc)) == -1) { PrintError("Could not translate ring descriptor address\n"); return -1; } - if (guest_pa_to_host_va(core, blk_state->queue.ring_avail_addr, (addr_t *)&(blk_state->queue.avail)) == -1) { + if (v3_gpa_to_hva(core, blk_state->queue.ring_avail_addr, (addr_t *)&(blk_state->queue.avail)) == -1) { PrintError("Could not translate ring available address\n"); return -1; } - if (guest_pa_to_host_va(core, blk_state->queue.ring_used_addr, (addr_t *)&(blk_state->queue.used)) == -1) { + if (v3_gpa_to_hva(core, blk_state->queue.ring_used_addr, (addr_t *)&(blk_state->queue.used)) == -1) { PrintError("Could not translate ring used address\n"); return -1; } @@ -418,38 +407,44 @@ static int virtio_io_read(struct guest_info * core, uint16_t port, void * dst, u PrintDebug("VIRTIO BLOCK Read for port %d (index =%d), length=%d\n", port, port_idx, length); + switch (port_idx) { case HOST_FEATURES_PORT: - if (length != 4) { - PrintError("Illegal read length for host features\n"); + case HOST_FEATURES_PORT + 1: + case HOST_FEATURES_PORT + 2: + case HOST_FEATURES_PORT + 3: + if (port_idx + length > HOST_FEATURES_PORT + 4) { + PrintError("Illegal read length for host features (len=%d)\n", length); return -1; } - *(uint32_t *)dst = blk_state->virtio_cfg.host_features; - + memcpy(dst, &(blk_state->virtio_cfg.host_features), length); break; case VRING_PG_NUM_PORT: - if (length != 4) { - PrintError("Illegal read length for page frame number\n"); + case VRING_PG_NUM_PORT + 1: + case VRING_PG_NUM_PORT + 2: + case VRING_PG_NUM_PORT + 3: + if (port_idx + length > VRING_PG_NUM_PORT + 4) { + PrintError("Illegal read length for vring pg num (len=%d)\n", length); return -1; } - *(uint32_t *)dst = blk_state->queue.pfn; - + memcpy(dst, &(blk_state->queue.pfn), length); break; case VRING_SIZE_PORT: - if (length != 2) { - PrintError("Illegal read length for vring size\n"); + case VRING_SIZE_PORT + 1: + if (length > 2) { + PrintError("Illegal read length for vring size (len=%d)\n", length); return -1; } - - *(uint16_t *)dst = blk_state->queue.queue_size; + + memcpy(dst, &(blk_state->queue.queue_size), length); break; case VIRTIO_STATUS_PORT: if (length != 1) { - PrintError("Illegal read length for status\n"); + PrintError("Illegal read length for status (len=%d)\n", length); return -1; } @@ -482,13 +477,29 @@ static int virtio_io_read(struct guest_info * core, uint16_t port, void * dst, u } +static int virtio_free(struct virtio_dev_state * virtio) { + struct virtio_blk_state * blk_state = NULL; + struct virtio_blk_state * tmp = NULL; + + list_for_each_entry_safe(blk_state, tmp, &(virtio->dev_list), dev_link) { + + // unregister from PCI + + list_del(&(blk_state->dev_link)); + V3_Free(blk_state); + } + + + V3_Free(virtio); + + return 0; +} + static struct v3_device_ops dev_ops = { - .free = virtio_free, - .reset = virtio_reset, - .start = NULL, - .stop = NULL, + .free = (int (*)(void *))virtio_free, + }; @@ -561,6 +572,10 @@ static int register_dev(struct virtio_dev_state * virtio, struct virtio_blk_stat blk_state->pci_dev = pci_dev; + + + /* Add backend to list of devices */ + list_add(&(blk_state->dev_link), &(virtio->dev_list)); /* Block configuration */ blk_state->virtio_cfg.host_features = VIRTIO_SEG_MAX; @@ -606,7 +621,7 @@ static int connect_fn(struct v3_vm_info * vm, static int virtio_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { struct vm_device * pci_bus = v3_find_dev(vm, v3_cfg_val(cfg, "bus")); struct virtio_dev_state * virtio_state = NULL; - char * name = v3_cfg_val(cfg, "name"); + char * dev_id = v3_cfg_val(cfg, "ID"); PrintDebug("Initializing VIRTIO Block device\n"); @@ -623,14 +638,17 @@ static int virtio_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { virtio_state->pci_bus = pci_bus; - struct vm_device * dev = v3_allocate_device(name, &dev_ops, virtio_state); - if (v3_attach_device(vm, dev) == -1) { - PrintError("Could not attach device %s\n", name); + struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, virtio_state); + + if (dev == NULL) { + PrintError("Could not attach device %s\n", dev_id); + V3_Free(virtio_state); return -1; } - if (v3_dev_add_blk_frontend(vm, name, connect_fn, (void *)virtio_state) == -1) { - PrintError("Could not register %s as block frontend\n", name); + if (v3_dev_add_blk_frontend(vm, dev_id, connect_fn, (void *)virtio_state) == -1) { + PrintError("Could not register %s as block frontend\n", dev_id); + v3_remove_device(dev); return -1; }