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.


Lock bugfixes - missing lock deinits This also adds deinit calls in the linux_module...
[palacios.git] / palacios / src / devices / lnx_virtio_vnet.c
index 7746bcc..69c1836 100644 (file)
 #include <palacios/vmm_dev_mgr.h>
 #include <palacios/vm_guest_mem.h>
 #include <devices/lnx_virtio_pci.h>
-#include <palacios/vmm_vnet.h>
+#include <vnet/vnet.h>
 #include <palacios/vmm_sprintf.h>
 #include <devices/pci.h>
 
 
-#ifndef CONFIG_DEBUG_LINUX_VIRTIO_VNET
+#ifndef V3_CONFIG_DEBUG_LINUX_VIRTIO_VNET
 #undef PrintDebug
 #define PrintDebug(fmt, args...)
 #endif
@@ -75,7 +75,6 @@ struct virtio_vnet_state {
 #define VNET_ADD_LINK 21
 #define VNET_DEL_LINK 22
 
-// structure of the vnet command header
 struct vnet_ctrl_hdr {
     uint8_t cmd_type;
     uint32_t num_cmds;
@@ -123,13 +122,11 @@ static int get_desc_count(struct virtio_queue * q, int index) {
 }
 
 
-
-
 static int handle_cmd_kick(struct guest_info * core, 
                           struct virtio_vnet_state * vnet_state) {
     struct virtio_queue * q = &(vnet_state->queue[0]);
     
-    PrintDebug("VNET Bridge: Handling command  queue\n");
+    PrintDebug(core->vm_info, core, "VNET Bridge: Handling command  queue\n");
 
     while (q->cur_avail_idx != q->avail->index) {
        struct vring_desc * hdr_desc = NULL;
@@ -143,25 +140,23 @@ static int handle_cmd_kick(struct guest_info * core,
        uint8_t * status_ptr = NULL;
        uint8_t status = 0;
 
-
-       PrintDebug("VNET Bridge: CMD: Descriptor Count=%d, index=%d, desc_idx=%d\n", desc_cnt, q->cur_avail_idx % QUEUE_SIZE, desc_idx);
+       PrintDebug(core->vm_info, core, "VNET Bridge: CMD: Descriptor Count=%d, index=%d, desc_idx=%d\n", desc_cnt, q->cur_avail_idx % QUEUE_SIZE, desc_idx);
 
        if (desc_cnt < 3) {
-           PrintError("VNET Bridge cmd must include at least 3 descriptors (cnt=%d)\n", desc_cnt);
+           PrintError(core->vm_info, core, "VNET Bridge cmd must include at least 3 descriptors (cnt=%d)\n", desc_cnt);
            return -1;
        }
        
        hdr_desc = &(q->desc[desc_idx]);
 
        if (v3_gpa_to_hva(core, hdr_desc->addr_gpa, (addr_t *)&hdr) == -1) {
-           PrintError("Could not translate VirtioVNET header address\n");
+           PrintError(core->vm_info, core, "Could not translate VirtioVNET header address\n");
            return -1;
        }
 
        desc_idx = hdr_desc->next;
        
-       if (hdr->cmd_type == VNET_ADD_ROUTE) {
-           
+       if (hdr->cmd_type == VNET_ADD_ROUTE) {   
            for (i = 0; i < hdr->num_cmds; i++) {
                uint8_t tmp_status = 0;
                struct v3_vnet_route * route = NULL;
@@ -169,41 +164,36 @@ static int handle_cmd_kick(struct guest_info * core,
                buf_desc = &(q->desc[desc_idx]);
 
                if (v3_gpa_to_hva(core, buf_desc->addr_gpa, (addr_t *)&(route)) == -1) {
-                   PrintError("Could not translate route address\n");
+                   PrintError(core->vm_info, core, "Could not translate route address\n");
                    return -1;
                }
 
-               // add route
-               PrintDebug("VNET Bridge: Adding VNET Route\n");
-
                tmp_status = v3_vnet_add_route(*route);
-
-               PrintDebug("VNET Route Added\n");
-
                if (tmp_status != 0) {
-                   PrintError("Error adding VNET ROUTE\n");
+                   PrintError(core->vm_info, core, "Error adding VNET ROUTE\n");
+                       
                    status = tmp_status;
                }
 
+               PrintDebug(core->vm_info, core, "VNET Route Added\n");
+
                xfer_len += buf_desc->length;
                desc_idx = buf_desc->next;
            }
 
        } 
 
-
-
        status_desc = &(q->desc[desc_idx]);
 
        if (v3_gpa_to_hva(core, status_desc->addr_gpa, (addr_t *)&status_ptr) == -1) {
-           PrintError("VirtioVNET Error could not translate status address\n");
+           PrintError(core->vm_info, core, "VirtioVNET Error could not translate status address\n");
            return -1;
        }
 
        xfer_len += status_desc->length;
        *status_ptr = status;
 
-       PrintDebug("Transferred %d bytes (xfer_len)\n", xfer_len);
+       PrintDebug(core->vm_info, core, "Transferred %d bytes (xfer_len)\n", xfer_len);
        q->used->ring[q->used->index % QUEUE_SIZE].id = q->avail->ring[q->cur_avail_idx % QUEUE_SIZE];
        q->used->ring[q->used->index % QUEUE_SIZE].length = xfer_len; // set to total inbound xfer length
 
@@ -213,8 +203,8 @@ static int handle_cmd_kick(struct guest_info * core,
 
 
     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
-       PrintDebug("Raising IRQ %d\n",  vnet_state->pci_dev->config_header.intr_line);
-       v3_pci_raise_irq(vnet_state->pci_bus, 0, vnet_state->pci_dev);
+       PrintDebug(core->vm_info, core, "Raising IRQ %d\n",  vnet_state->pci_dev->config_header.intr_line);
+       v3_pci_raise_irq(vnet_state->pci_bus, vnet_state->pci_dev, 0);
        vnet_state->virtio_cfg.pci_isr = 1;
     }
 
@@ -234,7 +224,8 @@ static int vnet_pkt_input_cb(struct v3_vm_info * vm,
     flags = v3_lock_irqsave(vnet_state->lock);
        
     if (q->ring_avail_addr == 0) {
-       PrintError("Queue is not set\n");
+       PrintError(vm, VCORE_NONE, "Queue is not set\n");
+       
        goto exit;
     }
 
@@ -244,14 +235,13 @@ static int vnet_pkt_input_cb(struct v3_vm_info * vm,
        struct vnet_bridge_pkt * virtio_pkt = NULL;
 
        pkt_desc = &(q->desc[pkt_idx]);
-       PrintDebug("VNET Bridge RX: buffer desc len: %d\n", pkt_desc->length);
 
        if (v3_gpa_to_hva(&(vm->cores[0]), pkt_desc->addr_gpa, (addr_t *)&(virtio_pkt)) == -1) {
-           PrintError("Could not translate buffer address\n");
+           PrintError(vm, VCORE_NONE, "Could not translate buffer address\n");
            goto exit;
        }
 
-       PrintDebug("VNET Bridge: RX: pkt sent to guest pkt size: %d, dst link: %d\n", pkt->size, pkt->dst_id);
+       PrintDebug(vm, VCORE_NONE, "VNET Bridge: RX: pkt sent to guest pkt size: %d, dst link: %d\n", pkt->size, pkt->dst_id);
 
        // Fill in dst packet buffer
        virtio_pkt->link_id = pkt->dst_id;
@@ -268,9 +258,9 @@ static int vnet_pkt_input_cb(struct v3_vm_info * vm,
     }
 
     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
-       v3_pci_raise_irq(vnet_state->pci_bus, 0, vnet_state->pci_dev);
+       v3_pci_raise_irq(vnet_state->pci_bus, vnet_state->pci_dev, 0);
        vnet_state->virtio_cfg.pci_isr = 0x1;
-       PrintDebug("Raising IRQ %d\n",  vnet_state->pci_dev->config_header.intr_line);
+       PrintDebug(vm, VCORE_NONE, "Raising IRQ %d\n",  vnet_state->pci_dev->config_header.intr_line);
     }
 
     ret_val = 0;
@@ -282,7 +272,7 @@ exit:
     return ret_val;
 }
 
-static int handle_pkt_kick(struct guest_info * core, 
+static int do_tx_pkts(struct guest_info * core, 
                           struct virtio_vnet_state * vnet_state) 
 {
     struct virtio_queue * q = &(vnet_state->queue[XMIT_QUEUE]);
@@ -298,15 +288,13 @@ static int handle_pkt_kick(struct guest_info * core,
        struct vnet_bridge_pkt * virtio_pkt = NULL;
 
        pkt_desc = &(q->desc[desc_idx]);
-
-       PrintDebug("VNET Bridge: Handle TX desc buf_len: %d\n", pkt_desc->length);
        
        if (v3_gpa_to_hva(core, pkt_desc->addr_gpa, (addr_t *)&(virtio_pkt)) == -1) {
-           PrintError("Could not translate buffer address\n");
+           PrintError(core->vm_info, core, "Could not translate buffer address\n");
            return -1;
        }
 
-       //PrintDebug("VNET Bridge: TX: on cpu %d pkt size: %d, dst link: %d\n", cpu, virtio_pkt->pkt_size, virtio_pkt->link_id);
+       //PrintDebug(core->vm_info, core, "VNET Bridge: TX: on cpu %d pkt size: %d, dst link: %d\n", cpu, virtio_pkt->pkt_size, virtio_pkt->link_id);
 
        struct v3_vnet_pkt pkt;
        pkt.size = virtio_pkt->pkt_size;
@@ -332,8 +320,8 @@ static int handle_pkt_kick(struct guest_info * core,
     }
 
     if (!(q->avail->flags & VIRTIO_NO_IRQ_FLAG)) {
-           v3_pci_raise_irq(vnet_state->pci_bus, 0, vnet_state->pci_dev);
-           vnet_state->virtio_cfg.pci_isr = 0x1;
+       v3_pci_raise_irq(vnet_state->pci_bus,  vnet_state->pci_dev, 0);
+       vnet_state->virtio_cfg.pci_isr = 0x1;
     }
        
     return 0;
@@ -343,15 +331,13 @@ static void vnet_virtio_poll(struct v3_vm_info * vm, void * private_data){
     struct virtio_vnet_state * vnet_state = (struct virtio_vnet_state *)private_data;
 
     if(vm == vnet_state->vm){  
-       handle_pkt_kick(&(vm->cores[0]), vnet_state);
+       do_tx_pkts(&(vm->cores[0]), vnet_state);
     }
 }
 
-static int handle_rx_kick(struct guest_info *core, 
+static int handle_rx_queue_kick(struct guest_info *core, 
                          struct virtio_vnet_state * vnet_state) 
-{
-    //v3_vnet_enable_bridge();
-       
+{      
     return 0;
 }
 
@@ -361,14 +347,14 @@ static int vnet_virtio_io_write(struct guest_info * core,
     struct virtio_vnet_state * vnet_state = (struct virtio_vnet_state *)private_data;
     int port_idx = port % vnet_state->io_range_size;
 
-    PrintDebug("VNET Bridge: VIRTIO VNET Write for port %d len=%d, value=%x\n", 
+    PrintDebug(core->vm_info, core, "VNET Bridge: VIRTIO VNET Write for port %d len=%d, value=%x\n", 
               port, length, *(uint32_t *)src);
 
     vnet_state->total_exit ++;
     switch (port_idx) {
        case GUEST_FEATURES_PORT:
            if (length != 4) {
-               PrintError("Illegal write length for guest features\n");
+               PrintError(core->vm_info, core, "Illegal write length for guest features\n");
                return -1;
            }    
            vnet_state->virtio_cfg.guest_features = *(uint32_t *)src;
@@ -391,26 +377,26 @@ static int vnet_virtio_io_write(struct guest_info * core,
                vnet_state->cur_queue->ring_used_addr = (vnet_state->cur_queue->ring_used_addr + 0xfff) & ~0xfff;
 
                if (v3_gpa_to_hva(core, vnet_state->cur_queue->ring_desc_addr, (addr_t *)&(vnet_state->cur_queue->desc)) == -1) {
-                   PrintError("Could not translate ring descriptor address\n");
+                   PrintError(core->vm_info, core, "Could not translate ring descriptor address\n");
                    return -1;
                }
 
                if (v3_gpa_to_hva(core, vnet_state->cur_queue->ring_avail_addr, (addr_t *)&(vnet_state->cur_queue->avail)) == -1) {
-                   PrintError("Could not translate ring available address\n");
+                   PrintError(core->vm_info, core, "Could not translate ring available address\n");
                    return -1;
                }
 
                if (v3_gpa_to_hva(core, vnet_state->cur_queue->ring_used_addr, (addr_t *)&(vnet_state->cur_queue->used)) == -1) {
-                   PrintError("Could not translate ring used address\n");
+                   PrintError(core->vm_info, core, "Could not translate ring used address\n");
                    return -1;
                }
 
-               PrintDebug("VNET Bridge: RingDesc_addr=%p, Avail_addr=%p, Used_addr=%p\n",
+               PrintDebug(core->vm_info, core, "VNET Bridge: RingDesc_addr=%p, Avail_addr=%p, Used_addr=%p\n",
                           (void *)(vnet_state->cur_queue->ring_desc_addr),
                           (void *)(vnet_state->cur_queue->ring_avail_addr),
                           (void *)(vnet_state->cur_queue->ring_used_addr));
 
-               PrintDebug("VNET Bridge: RingDesc=%p, Avail=%p, Used=%p\n", 
+               PrintDebug(core->vm_info, core, "VNET Bridge: RingDesc=%p, Avail=%p, Used=%p\n", 
                           vnet_state->cur_queue->desc, vnet_state->cur_queue->avail, vnet_state->cur_queue->used);
 
                if(vnet_state->queue[RECV_QUEUE].avail != NULL){
@@ -424,7 +410,7 @@ static int vnet_virtio_io_write(struct guest_info * core,
                    vnet_state->queue[XMIT_QUEUE].used->flags |= VRING_NO_NOTIFY_FLAG;
                }
            } else {
-               PrintError("Illegal write length for page frame number\n");
+               PrintError(core->vm_info, core, "Illegal write length for page frame number\n");
                return -1;
            }
            break;
@@ -432,7 +418,7 @@ static int vnet_virtio_io_write(struct guest_info * core,
            vnet_state->virtio_cfg.vring_queue_selector = *(uint16_t *)src;
 
            if (vnet_state->virtio_cfg.vring_queue_selector > NUM_QUEUES) {
-               PrintError("VNET Bridge device has no qeueues. Selected %d\n", 
+               PrintError(core->vm_info, core, "VNET Bridge device has no qeueues. Selected %d\n", 
                           vnet_state->virtio_cfg.vring_queue_selector);
                return -1;
            }
@@ -443,27 +429,27 @@ static int vnet_virtio_io_write(struct guest_info * core,
        case VRING_Q_NOTIFY_PORT: {
            uint16_t queue_idx = *(uint16_t *)src;
 
-           PrintDebug("VNET Bridge: Handling Kick\n");
+           PrintDebug(core->vm_info, core, "VNET Bridge: Handling Kick\n");
 
            if (queue_idx == 0) {
                if (handle_cmd_kick(core, vnet_state) == -1) {
-                   PrintError("Could not handle Virtio VNET Control command\n");
+                   PrintError(core->vm_info, core, "Could not handle Virtio VNET Control command\n");
                    return -1;
                }
            } else if (queue_idx == 1) {
-               if (handle_pkt_kick(core, vnet_state) == -1){
-                   PrintError("Could not handle Virtio VNET TX\n");
+               if (do_tx_pkts(core, vnet_state) == -1){
+                   PrintError(core->vm_info, core, "Could not handle Virtio VNET TX\n");
                    return -1;
                }
-               PrintError("Notify on TX\n");
+               PrintError(core->vm_info, core, "Notify on TX\n");
            } else if (queue_idx == 2) {
-               if (handle_rx_kick(core, vnet_state) == -1){
-                   PrintError("Could not handle Virtio RX buffer refills Kick\n");
+               if (handle_rx_queue_kick(core, vnet_state) == -1){
+                   PrintError(core->vm_info, core, "Could not handle Virtio RX buffer refills Kick\n");
                    return -1;
                }
                vnet_state->rx_exit ++;
            } else {
-               PrintError("VNET Bridge: Kick on invalid queue (%d)\n", queue_idx);
+               PrintError(core->vm_info, core, "VNET Bridge: Kick on invalid queue (%d)\n", queue_idx);
                return -1;
            }
 
@@ -473,7 +459,7 @@ static int vnet_virtio_io_write(struct guest_info * core,
            vnet_state->virtio_cfg.status = *(uint8_t *)src;
 
            if (vnet_state->virtio_cfg.status == 0) {
-               PrintDebug("VNET Bridge: Resetting device\n");
+               PrintDebug(core->vm_info, core, "VNET Bridge: Resetting device\n");
                virtio_reset(vnet_state);
            }
 
@@ -501,7 +487,7 @@ static int vnet_virtio_io_read(struct guest_info * core,
     switch (port_idx) {
        case HOST_FEATURES_PORT:
            if (length != 4) {
-               PrintError("Illegal read length for host features\n");
+               PrintError(core->vm_info, core, "Illegal read length for host features\n");
                return -1;
            }
 
@@ -510,7 +496,7 @@ static int vnet_virtio_io_read(struct guest_info * core,
            break;
        case VRING_PG_NUM_PORT:
            if (length != 4) {
-               PrintError("Illegal read length for page frame number\n");
+               PrintError(core->vm_info, core, "Illegal read length for page frame number\n");
                return -1;
            }
 
@@ -519,7 +505,7 @@ static int vnet_virtio_io_read(struct guest_info * core,
            break;
        case VRING_SIZE_PORT:
            if (length != 2) {
-               PrintError("Illegal read length for vring size\n");
+               PrintError(core->vm_info, core, "Illegal read length for vring size\n");
                return -1;
            }
                
@@ -529,7 +515,7 @@ static int vnet_virtio_io_read(struct guest_info * core,
 
        case VIRTIO_STATUS_PORT:
            if (length != 1) {
-               PrintError("Illegal read length for status\n");
+               PrintError(core->vm_info, core, "Illegal read length for status\n");
                return -1;
            }
 
@@ -539,7 +525,7 @@ static int vnet_virtio_io_read(struct guest_info * core,
        case VIRTIO_ISR_PORT:
            *(uint8_t *)dst = vnet_state->virtio_cfg.pci_isr;
            vnet_state->virtio_cfg.pci_isr = 0;
-           v3_pci_lower_irq(vnet_state->pci_bus, 0, vnet_state->pci_dev);
+           v3_pci_lower_irq(vnet_state->pci_bus, vnet_state->pci_dev, 0);
            break;
 
        default:
@@ -551,7 +537,7 @@ static int vnet_virtio_io_read(struct guest_info * core,
                memcpy(dst, cfg_ptr + cfg_offset, length);
                
            } else {
-               PrintError("Read of Unhandled Virtio Read\n");
+               PrintError(core->vm_info, core, "Read of Unhandled Virtio Read\n");
                return -1;
            }
          
@@ -562,12 +548,20 @@ static int vnet_virtio_io_read(struct guest_info * core,
 }
 
 
+static int virtio_free(struct virtio_vnet_state * vnet_state) {
+
+    // unregister from PCI
+
+    v3_lock_deinit(&(vnet_state->lock));
+
+    V3_Free(vnet_state);
+
+    return 0;
+}
+
 
 static struct v3_device_ops dev_ops = {
-    .free = NULL,
-    .reset = NULL,
-    .start = NULL,
-    .stop = NULL,
+    .free = (int (*)(void *))virtio_free,
 };
 
 static int dev_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
@@ -576,14 +570,20 @@ static int dev_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     struct pci_device * pci_dev = NULL;
     char * name = v3_cfg_val(cfg, "name");
 
-    PrintDebug("VNET Bridge: Initializing VNET Bridge Control device: %s\n", name);
+    PrintDebug(vm, VCORE_NONE, "VNET Bridge: Initializing VNET Bridge Control device: %s\n", name);
 
     if (pci_bus == NULL) {
-       PrintError("VNET Bridge device require a PCI Bus");
+       PrintError(vm, VCORE_NONE, "VNET Bridge device require a PCI Bus");
        return -1;
     }
     
     vnet_state  = (struct virtio_vnet_state *)V3_Malloc(sizeof(struct virtio_vnet_state));
+
+    if (!vnet_state) {
+       PrintError(vm, VCORE_NONE, "Cannot allocate in init\n");
+       return -1;
+    }
+
     memset(vnet_state, 0, sizeof(struct virtio_vnet_state));
        
     vnet_state->vm = vm;
@@ -591,7 +591,7 @@ static int dev_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     struct vm_device * dev = v3_add_device(vm, name, &dev_ops, vnet_state);
 
     if (dev == NULL) {
-       PrintError("Could not attach device %s\n", name);
+       PrintError(vm, VCORE_NONE, "Could not attach device %s\n", name);
        V3_Free(vnet_state);
        return -1;
     }
@@ -632,10 +632,10 @@ static int dev_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
        pci_dev = v3_pci_register_device(pci_bus, PCI_STD_DEVICE, 
                                         0, 5 /*PCI_AUTO_DEV_NUM*/, 0,
                                         "LNX_VIRTIO_VNET", bars,
-                                        NULL, NULL, NULL, vnet_state);
+                                        NULL, NULL, NULL, NULL, vnet_state);
 
        if (!pci_dev) {
-           PrintError("Could not register PCI Device\n");
+           PrintError(vm, VCORE_NONE, "Could not register PCI Device\n");
            v3_remove_device(dev);
            return -1;
        }
@@ -660,7 +660,7 @@ static int dev_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     brg_ops.input = vnet_pkt_input_cb;
     brg_ops.poll = vnet_virtio_poll;
 
-    V3_Print("Registering Virtio device as vnet bridge\n");
+    V3_Print(vm, VCORE_NONE, "Registering Virtio device as vnet bridge\n");
 
     v3_vnet_add_bridge(vm, &brg_ops, CTL_VM_BRIDGE, (void *)vnet_state);