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.


Cleanup and sanity-checking of OOB accesses and pointer-to-local issues (Coverity...
[palacios.git] / palacios / src / devices / ne2k.c
index 46594c3..f94b966 100644 (file)
@@ -28,7 +28,7 @@
 #include <palacios/vm_guest.h>
 #include <palacios/vmm_sprintf.h>
 
-#ifndef CONFIG_DEBUG_NE2K
+#ifndef V3_CONFIG_DEBUG_NE2K
 #undef PrintDebug
 #define PrintDebug(fmts, args...)
 #endif
 #define NE2K_MEM_SIZE           NE2K_PMEM_END
 
 #define NIC_REG_BASE_PORT       0xc100         /* Command register (for all pages) */
-#define NIC_DATA_PORT          0xc110          /* Data read/write port */
-#define NIC_RESET_PORT                 0xc11f          /* Reset port */
+
+#define NE2K_CMD_OFFSET        0x00
+#define NE2K_DATA_OFFSET       0x10
+#define NE2K_RESET_OFFSET      0x1f
 
 /* Page 0 registers */
 #define EN0_CLDALO             0x01    /* Low byte of current local dma addr  RD */
@@ -319,6 +321,8 @@ struct ne2k_state {
     uint8_t mcast_addr[8];
     uint8_t mac[ETH_ALEN];
 
+    struct nic_statistics statistics;
+
     struct v3_dev_net_ops *net_ops;
     void * backend_data;
 };
@@ -330,23 +334,34 @@ static int ne2k_update_irq(struct ne2k_state * nic_state) {
        if (pci_dev == NULL){
            v3_raise_virq(&(nic_state->vm->cores[0]), NE2K_DEFAULT_IRQ);
        } else {            
-           v3_pci_raise_irq(nic_state->pci_bus, 0, nic_state->pci_dev);
+          v3_pci_raise_irq(nic_state->pci_bus, nic_state->pci_dev, 0);
        }
 
-       PrintDebug("NE2000: Raise IRQ\n");
+       nic_state->statistics.rx_interrupts ++;
+
+       PrintDebug(VM_NONE, VCORE_NONE, "NE2000: Raise IRQ\n");
     }
 
     return 0;
 }
 
-static int ne2k_send_packet(struct ne2k_state * nic_state, uchar_t *pkt, uint32_t length) {
+static int tx_one_pkt(struct ne2k_state * nic_state, uchar_t *pkt, uint32_t length) {
        
-#ifdef CONFIG_DEBUG_NE2K
-    PrintDebug("NE2000: Send Packet:\n");
+#ifdef V3_CONFIG_DEBUG_NE2K
+    PrintDebug(VM_NONE, VCORE_NONE, "NE2000: Send Packet:\n");
     v3_hexdump(pkt, length, NULL, 0);
 #endif    
 
-    return nic_state->net_ops->send(pkt, length, nic_state->backend_data);
+    if(nic_state->net_ops->send(pkt, length, nic_state->backend_data) >= 0){
+       nic_state->statistics.tx_pkts ++;
+       nic_state->statistics.tx_bytes += length;
+
+       return 0;
+    }
+       
+    nic_state->statistics.tx_dropped ++;
+
+    return -1;
 }
 
 static int ne2k_rxbuf_full(struct ne2k_registers * regs) {
@@ -376,6 +391,7 @@ static int ne2k_rxbuf_full(struct ne2k_registers * regs) {
 // This needs to be completely redone...
 static int rx_one_pkt(struct ne2k_state * nic_state, const uchar_t * pkt,  uint32_t length) {
     struct ne2k_registers * regs = (struct ne2k_registers *)&(nic_state->context);
+    uchar_t buf[MIN_BUF_SIZE];
     uchar_t * p;
     uint32_t total_len;
     uint32_t next;
@@ -393,14 +409,12 @@ static int rx_one_pkt(struct ne2k_state * nic_state, const uchar_t * pkt,  uint3
     }
 
     if (ne2k_rxbuf_full(regs)) {
-       PrintError("Ne2k: received buffer overflow\n");
+       PrintError(VM_NONE, VCORE_NONE, "Ne2k: received buffer overflow\n");
        return -1;
     }
 
     //packet too small, expand it
     if (length < MIN_BUF_SIZE) {
-        uchar_t buf[MIN_BUF_SIZE];
-
         memcpy(buf, pkt, length);
         memset(buf + length, 0, MIN_BUF_SIZE - length);
         pkt = buf;
@@ -469,15 +483,20 @@ static int rx_one_pkt(struct ne2k_state * nic_state, const uchar_t * pkt,  uint3
 static int ne2k_rx(uint8_t * buf, uint32_t size, void * private_data){
     struct ne2k_state * nic_state = (struct ne2k_state *)private_data;
   
-#ifdef CONFIG_DEBUG_NE2K
-    PrintDebug("\nNe2k: Packet Received:\n");
+#ifdef V3_CONFIG_DEBUG_NE2K
+    PrintDebug(VM_NONE, VCORE_NONE, "\nNe2k: Packet Received:\n");
     v3_hexdump(buf, size, NULL, 0);
 #endif    
 
     if(!rx_one_pkt(nic_state, buf, size)){
+       nic_state->statistics.rx_pkts ++;
+       nic_state->statistics.rx_bytes += size;
+       
        return 0;
     }
-    
+
+    nic_state->statistics.rx_dropped ++;
+       
     return -1;
 }
 
@@ -584,14 +603,14 @@ static int ne2k_data_read(struct guest_info * core,
            val = mem_readl(nic_state, addr);
            break;
        default:
-           PrintError("ne2k_data_read error: invalid length %d\n", length);
+           PrintError(VM_NONE, VCORE_NONE, "ne2k_data_read error: invalid length %d\n", length);
            val = 0x0;
     }
     
     dma_update(nic_state, length);
     memcpy(dst, &val, length);
 
-    PrintDebug("NE2000 read: port:0x%x (%u bytes): 0x%x", port & 0x1f, length, val);
+    PrintDebug(VM_NONE, VCORE_NONE, "NE2000 read: port:0x%x (%u bytes): 0x%x", port & 0x1f, length, val);
 
     return length;
 }
@@ -624,12 +643,12 @@ static int ne2k_data_write(struct guest_info * core,
            mem_writel(nic_state, addr, val);
            break;
        default:
-           PrintError("NE2000 port write error: invalid length %d\n", length);
+           PrintError(VM_NONE, VCORE_NONE, "NE2000 port write error: invalid length %d\n", length);
     }
     
     dma_update(nic_state, length);
 
-    PrintDebug("NE2000: Write port:0x%x (%u bytes): 0x%x\n", port & 0x1f, length, val);
+    PrintDebug(VM_NONE, VCORE_NONE, "NE2000: Write port:0x%x (%u bytes): 0x%x\n", port & 0x1f, length, val);
     
     return length;
 }
@@ -655,7 +674,7 @@ static void ne2k_init_state(struct ne2k_state * nic_state) {
 static int reset_device(struct ne2k_state * nic_state) {  
     ne2k_init_state(nic_state);
 
-    PrintDebug("NE2000: Reset device\n");
+    PrintDebug(VM_NONE, VCORE_NONE, "NE2000: Reset device\n");
 
     return 0;
 }
@@ -694,7 +713,7 @@ static int ne2k_cmd_write(struct guest_info * core,
     struct ne2k_registers * regs = (struct ne2k_registers *)&(nic_state->context);
 
     if (length != 1) {
-       PrintError("Invalid write length to NE2000 Command register\n");
+       PrintError(core->vm_info, core, "Invalid write length to NE2000 Command register\n");
        return -1;
     }
 
@@ -717,7 +736,7 @@ static int ne2k_cmd_write(struct guest_info * core,
            }
 
            if (offset + regs->tbcr <= NE2K_PMEM_END) {
-               ne2k_send_packet(nic_state, nic_state->mem + offset, regs->tbcr);
+               tx_one_pkt(nic_state, nic_state->mem + offset, regs->tbcr);
            }
 
            regs->tsr.val = 0;        /* clear the tx status reg */
@@ -743,13 +762,13 @@ static int ne2k_cmd_read(struct guest_info * core,
     struct ne2k_state * nic_state = (struct ne2k_state *)private_data;
 
     if (length != 1) {
-       PrintError("Invalid read length to NE2000 Command register\n");
+       PrintError(core->vm_info, core, "Invalid read length to NE2000 Command register\n");
        return -1;
     }
 
     *(uint8_t *)dst = nic_state->context.cmd.val;
 
-    PrintDebug("ne2k_read: port:0x%x  val: 0x%x\n", port, *(uint8_t *)dst);
+    PrintDebug(core->vm_info, core, "ne2k_read: port:0x%x  val: 0x%x\n", port, *(uint8_t *)dst);
     return length;
 }
 
@@ -764,13 +783,13 @@ static int ne2k_std_write(struct guest_info * core,
     uint8_t page = regs->cmd.pg_sel;
 
     if (length != 1){
-       PrintError("NE2000 port write error: length %d port 0x%xnot equal to 1\n", length, port);  
+       PrintError(core->vm_info, core, "NE2000 port write error: length %d port 0x%xnot equal to 1\n", length, port);  
        return -1;
     }
 
     uint8_t val = *(uint8_t *)src;
        
-    PrintDebug("NE2000: write port:0x%x val: 0x%x\n", port, (uint8_t)val);
+    PrintDebug(core->vm_info, core, "NE2000: write port:0x%x val: 0x%x\n", port, (uint8_t)val);
     
     if (page == 0) {
        switch (idx) {
@@ -823,7 +842,7 @@ static int ne2k_std_write(struct guest_info * core,
                break;
 
            default:
-               PrintError("NE2000 port write error: invalid port:0x%x\n", port);
+               PrintError(core->vm_info, core, "NE2000 port write error: invalid port:0x%x\n", port);
                return -1;
        }
     } else if (page == 1) {
@@ -839,7 +858,7 @@ static int ne2k_std_write(struct guest_info * core,
                break;
                
            default:
-               PrintError("NE2000 write port error: invalid port:0x%x\n", port);
+               PrintError(core->vm_info, core, "NE2000 write port error: invalid port:0x%x\n", port);
                return -1;
        }
     } else if (page == 2) {
@@ -864,11 +883,11 @@ static int ne2k_std_write(struct guest_info * core,
                break;
                
            default:
-               PrintError("NE2000 write port error: invalid port:0x%x\n", port);
+               PrintError(core->vm_info, core, "NE2000 write port error: invalid port:0x%x\n", port);
                return -1;
        }
     } else {
-       PrintError("NE2000: Invalid Register Page Value\n");
+       PrintError(core->vm_info, core, "NE2000: Invalid Register Page Value\n");
        return -1;
     }
 
@@ -888,7 +907,7 @@ static int ne2k_std_read(struct guest_info * core,
     uint8_t page = regs->cmd.pg_sel;
 
     if (length > 1) {
-       PrintError("ne2k_read error: length %d\n", length);
+       PrintError(core->vm_info, core, "ne2k_read error: length %d\n", length);
        return length;
     }
 
@@ -936,7 +955,7 @@ static int ne2k_std_read(struct guest_info * core,
                break;
                
            default:
-               PrintError("NE2000 port read error: invalid port:0x%x\n", port);
+               PrintError(core->vm_info, core, "NE2000 port read error: invalid port:0x%x\n", port);
                return -1;
        }
     } else if (page == 1) {
@@ -952,7 +971,7 @@ static int ne2k_std_read(struct guest_info * core,
                break;
                
            default:
-               PrintError("ne2k_read error: invalid port:0x%x\n", port);
+               PrintError(core->vm_info, core, "ne2k_read error: invalid port:0x%x\n", port);
                return -1;
        }
     } else if (page == 2) {
@@ -991,15 +1010,15 @@ static int ne2k_std_read(struct guest_info * core,
                *(uint8_t *)dst = regs->imr.val;
                break;
            default:
-               PrintError("NE2000 port read error: invalid port:0x%x\n", port);
+               PrintError(core->vm_info, core, "NE2000 port read error: invalid port:0x%x\n", port);
                return -1;
        }
     } else {
-       PrintError("NE2000 port read: Invalid Register Page Value\n");
+       PrintError(core->vm_info, core, "NE2000 port read: Invalid Register Page Value\n");
        return -1;
     }
 
-    PrintDebug("NE2000 port read: port:0x%x  val: 0x%x\n", port, *(uint8_t *)dst);
+    PrintDebug(core->vm_info, core, "NE2000 port read: port:0x%x  val: 0x%x\n", port, *(uint8_t *)dst);
 
     return length;
 }
@@ -1015,21 +1034,21 @@ static int ne2k_pci_write(struct guest_info * core,
     int ret;
 
     switch (idx) {
-       case NIC_REG_BASE_PORT:
+       case NE2K_CMD_OFFSET:
            ret =  ne2k_cmd_write(core, port, src, length, private_data);
            break;
-       case NIC_REG_BASE_PORT+1 ... NIC_REG_BASE_PORT+15:
+       case NE2K_CMD_OFFSET+1 ... NE2K_CMD_OFFSET+15:
            ret = ne2k_std_write(core, port, src, length, private_data);
            break;
-       case NIC_DATA_PORT:
+       case NE2K_DATA_OFFSET:
            ret = ne2k_data_write(core, port, src, length, private_data);
            break;
-       case NIC_RESET_PORT:
+       case NE2K_RESET_OFFSET:
            ret = ne2k_reset_port_write(core, port, src, length, private_data);
            break;
 
        default:
-           PrintError("NE2000 port write error: invalid port:0x%x\n", port);
+           PrintError(core->vm_info, core, "NE2000 port write error: invalid port:0x%x\n", port);
            return -1;
     }
 
@@ -1045,21 +1064,21 @@ static int ne2k_pci_read(struct guest_info * core,
     int ret;
 
     switch (idx) {
-       case NIC_REG_BASE_PORT:
+       case NE2K_CMD_OFFSET:
            ret =  ne2k_cmd_read(core, port, dst, length, private_data);
            break;
-       case NIC_REG_BASE_PORT+1 ... NIC_REG_BASE_PORT+15:
+       case NE2K_CMD_OFFSET+1 ... NE2K_CMD_OFFSET+15:
            ret = ne2k_std_read(core, port, dst, length, private_data);
            break;
-       case NIC_DATA_PORT:
+       case NE2K_DATA_OFFSET:
            ret = ne2k_data_read(core, port, dst, length, private_data);
            break;
-       case NIC_RESET_PORT:
+       case NE2K_RESET_OFFSET:
            ret = ne2k_reset_port_read(core, port, dst, length, private_data);
            break;
 
        default:
-           PrintError("NE2000 port read error: invalid port:0x%x\n", port);
+           PrintError(core->vm_info, core, "NE2000 port read error: invalid port:0x%x\n", port);
            return -1;
     }
 
@@ -1068,11 +1087,12 @@ static int ne2k_pci_read(struct guest_info * core,
 
 }
 
-static int pci_config_update(uint_t reg_num, 
+static int pci_config_update(struct pci_device * pci_dev,
+                        uint32_t reg_num,
                             void * src, 
                             uint_t length,
                             void * private_data) {
-    PrintDebug("PCI Config Update\n");
+    PrintDebug(VM_NONE, VCORE_NONE, "PCI Config Update\n");
 
     /* Do we need this? */
 
@@ -1088,14 +1108,14 @@ static int register_dev(struct ne2k_state * nic_state)
        struct v3_pci_bar bars[6];
        struct pci_device * pci_dev = NULL;
 
-       PrintDebug("NE2000: PCI Enabled\n");
+       PrintDebug(VM_NONE, VCORE_NONE, "NE2000: PCI Enabled\n");
 
        for (i = 0; i < 6; i++) {
            bars[i].type = PCI_BAR_NONE;
        }
 
        bars[0].type = PCI_BAR_IO;
-       bars[0].default_base_port = NIC_REG_BASE_PORT;
+       bars[0].default_base_port = -1;
        bars[0].num_ports = 256;
 
        bars[0].io_read = ne2k_pci_read;
@@ -1104,11 +1124,11 @@ static int register_dev(struct ne2k_state * nic_state)
 
        pci_dev = v3_pci_register_device(nic_state->pci_bus, PCI_STD_DEVICE, 0, -1, 0, 
                                         "NE2000", bars,
-                                        pci_config_update, NULL, NULL, nic_state);
+                                        pci_config_update, NULL, NULL, NULL, nic_state);
 
 
        if (pci_dev == NULL) {
-           PrintError("NE2000: Could not register PCI Device\n");
+           PrintError(VM_NONE, VCORE_NONE, "NE2000: Could not register PCI Device\n");
            return -1;
        }
        
@@ -1125,7 +1145,7 @@ static int register_dev(struct ne2k_state * nic_state)
 
        nic_state->pci_dev = pci_dev;
     }else {
-       PrintDebug("NE2000: Not attached to PCI\n");
+       PrintDebug(VM_NONE, VCORE_NONE, "NE2000: Not attached to PCI\n");
 
        v3_dev_hook_io(nic_state->dev, NIC_REG_BASE_PORT , &ne2k_cmd_read, &ne2k_cmd_write);
 
@@ -1133,8 +1153,8 @@ static int register_dev(struct ne2k_state * nic_state)
            v3_dev_hook_io(nic_state->dev, NIC_REG_BASE_PORT + i, &ne2k_std_read, &ne2k_std_write);
        }
 
-       v3_dev_hook_io(nic_state->dev, NIC_DATA_PORT, &ne2k_data_read, &ne2k_data_write);
-       v3_dev_hook_io(nic_state->dev, NIC_RESET_PORT, &ne2k_reset_port_read, &ne2k_reset_port_write);
+       v3_dev_hook_io(nic_state->dev, NIC_REG_BASE_PORT + NE2K_DATA_OFFSET, &ne2k_data_read, &ne2k_data_write);
+       v3_dev_hook_io(nic_state->dev, NIC_REG_BASE_PORT + NE2K_RESET_OFFSET, &ne2k_reset_port_read, &ne2k_reset_port_write);
     }
 
 
@@ -1155,11 +1175,9 @@ static int connect_fn(struct v3_vm_info * info,
     nic_state->backend_data = private_data;    
 
     ops->recv = ne2k_rx;
-    ops->poll = NULL;
-    ops->start_tx = NULL;
-    ops->stop_tx = NULL;
-    ops->frontend_data = nic_state;
-    memcpy(ops->fnt_mac, nic_state->mac, ETH_ALEN);
+    ops->poll = NULL;   
+    ops->config.frontend_data = nic_state;
+    ops->config.fnt_mac = nic_state->mac;
 
     return 0;
 }
@@ -1175,13 +1193,11 @@ static int ne2k_free(struct ne2k_state * nic_state) {
            v3_dev_unhook_io(nic_state->dev, NIC_REG_BASE_PORT + i);
        }
     
-       v3_dev_unhook_io(nic_state->dev, NIC_DATA_PORT);
-       v3_dev_unhook_io(nic_state->dev, NIC_RESET_PORT);
+       v3_dev_unhook_io(nic_state->dev, NIC_REG_BASE_PORT + NE2K_DATA_OFFSET);
+       v3_dev_unhook_io(nic_state->dev, NIC_REG_BASE_PORT + NE2K_RESET_OFFSET);
     }else {
        /* unregistered from PCI? */
     }
-  
-    return 0;
 
     V3_Free(nic_state);
        
@@ -1201,22 +1217,28 @@ static int ne2k_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     char * macstr = v3_cfg_val(cfg, "mac");
 
     nic_state  = (struct ne2k_state *)V3_Malloc(sizeof(struct ne2k_state));
+
+    if (!nic_state) {
+       PrintError(vm, VCORE_NONE, "Cannot allocate in init\n");
+       return -1;
+    }
+
     memset(nic_state, 0, sizeof(struct ne2k_state));
 
     nic_state->pci_bus = pci_bus;
     nic_state->vm = vm;
 
     if (macstr != NULL && !str2mac(macstr, nic_state->mac)) {
-       PrintDebug("NE2000: Mac specified %s\n", macstr);
+       PrintDebug(vm, VCORE_NONE, "NE2000: Mac specified %s\n", macstr);
     }else {
-       PrintDebug("NE2000: MAC not specified\n");
+       PrintDebug(vm, VCORE_NONE, "NE2000: MAC not specified\n");
        random_ethaddr(nic_state->mac);
     }
 
     struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, nic_state);
 
     if (dev == NULL) {
-       PrintError("NE2000: Could not attach device %s\n", dev_id);
+       PrintError(vm, VCORE_NONE, "NE2000: Could not attach device %s\n", dev_id);
        V3_Free(nic_state);
        return -1;
     }
@@ -1224,7 +1246,7 @@ static int ne2k_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     nic_state->dev = dev;
 
     if (v3_dev_add_net_frontend(vm, dev_id, connect_fn, (void *)nic_state) == -1) {
-       PrintError("NE2000: Could not register %s as net frontend\n", dev_id);
+       PrintError(vm, VCORE_NONE, "NE2000: Could not register %s as net frontend\n", dev_id);
        v3_remove_device(dev);
        V3_Free(nic_state);
        return -1;