2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2009, Lei Xia <lxia@northwestern.edu>
11 * Copyright (c) 2009, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * Author: Lei Xia <lxia@northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
21 * Virtual NE2K Network Card
24 #include <devices/vnic.h>
25 #include <palacios/vmm.h>
26 #include <palacios/vmm_types.h>
27 #include <palacios/vmm_io.h>
28 #include <palacios/vmm_debug.h>
34 #define PrintDebug(fmts, args...)
37 typedef enum {NIC_READY, NIC_REG_POSTED} nic_state_t;
61 uchar_t phys[6]; //mac address
63 uchar_t mult[8]; //multicast mask array
72 struct guest_info *vm;
74 nic_state_t dev_state;
78 uchar_t mac[6]; //the mac address of this nic
80 uchar_t mem[NE2K_MEM_SIZE];
83 struct vm_device *current_vnic;
85 #define compare_mac(src, dst) ({ \
86 ( (src[0] == dst[0]) && \
87 (src[1] == dst[1]) && \
88 (src[2] == dst[2]) && \
89 (src[3] == dst[3]) && \
90 (src[4] == dst[4]) && \
91 (src[5] == dst[5]) ) ? 1 : 0; \
99 * Host/Network byte conversion functions
100 * TODO: These are not compiler safe
101 * TODO: consistent names would be nice...
104 static inline uint16_t cpu2le16(uint16_t val) {
106 uchar_t * p1 = (uchar_t *)&p;
115 static inline uint32_t cpu2le32(uint32_t val) {
117 uchar_t * p1 = (uchar_t *)&p;
127 static inline uint16_t le16_to_cpu(const uint16_t * p) {
128 const uchar_t * p1 = (const uchar_t *)p;
129 return p1[0] | (p1[1] << 8);
132 static inline uint32_t le32_to_cpu(const uint32_t *p) {
133 const uchar_t * p1 = (const uchar_t *)p;
134 return p1[0] | (p1[1] << 8) | (p1[2] << 16) | (p1[3] << 24);
140 static void dump_state(struct vm_device * dev) {
143 struct nic_context * nic_state = (struct nic_context *)dev->private_data;
145 PrintDebug("====VNIC: Dumping state Begin ==========\n");
146 PrintDebug("Registers:\n");
148 p = (uchar_t *)&nic_state->regs;
150 for (i = 0; i < sizeof(struct nic_regs); i++) {
151 PrintDebug("Regs[i] = 0x%2x\n", (int)p[i]);
154 PrintDebug("Memory:\n");
156 for (i = 0; i < 32; i++) {
157 PrintDebug("0x%02x ", nic_state->mem[i]);
161 PrintDebug("====VNIC: Dumping state End==========\n");
164 static void vnic_update_irq(struct vm_device * dev) {
165 struct nic_context * nic_state = (struct nic_context *)dev->private_data;
166 struct guest_info * guest = dev->vm;
168 int isr = ((nic_state->regs.isr & nic_state->regs.imr) & 0x7f);
170 if ((isr & 0x7f) != 0x0) {
171 v3_raise_irq(guest, NIC_IRQ);
172 PrintDebug("VNIC: RaiseIrq: isr: 0x%02x imr: 0x%02x\n", nic_state->regs.isr, nic_state->regs.imr);
176 static void init_vnic_context(struct vm_device * dev) {
177 struct nic_context *nic_state = (struct nic_context *)dev->private_data;
179 uchar_t mac[6] = {0x52, 0x54, 0x0, 0x12, 0x34, 0x56};
181 nic_state->vm = dev->vm;
183 nic_state->regs.isr = ENISR_RESET;
184 nic_state->regs.imr = 0x00;
185 nic_state->regs.cmd = 0x22;
187 for (i = 0; i < 6; i++) {
188 nic_state->regs.macaddr[i] = nic_state->mac[i] = mac[i];
191 for (i = 0; i < 8; i++) {
192 nic_state->regs.mult[i] = 0xff;
195 for(i = 0; i < 32; i++) {
196 nic_state->mem[i] = 0xff;
199 memcpy(nic_state->mem, nic_state->mac, 6);
200 nic_state->mem[14] = 0x57;
201 nic_state->mem[15] = 0x57;
207 static int vnic_send_packet(struct vm_device *dev, uchar_t *pkt, int length) {
210 PrintDebug("\nVNIC: Sending Packet\n");
212 for (i = 0; i<length; i++) {
213 PrintDebug("%x ",pkt[i]);
218 return V3_SEND_PKT(pkt, length);
222 struct vm_device * get_rx_dev(uchar_t * dst_mac) {
223 struct nic_context * nic_state = (struct nic_context *)current_vnic->private_data;
224 struct nic_regs * nregs = &(nic_state->regs);
226 static const uchar_t brocast_mac[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
228 if (nregs->rcr & 0x10) {
231 if (compare_mac(dst_mac, brocast_mac)) { //broadcast address
232 if (!(nregs->rcr & 0x04)) {
235 } else if (dst_mac[0] & 0x01) {
236 // multicast packet, not fully done here
238 if (!(nregs->rcr & 0x08)) {
241 } else if (!compare_mac(dst_mac, nic_state->mac)) {
251 static int vnic_rxbuf_full(struct vm_device * dev) {
252 int empty, index, boundary;
253 struct nic_context * nic_state = (struct nic_context *)dev->private_data;
255 index = nic_state->regs.curpag << 8;
256 boundary = nic_state->regs.boundary << 8;
257 if (index < boundary) {
258 empty = boundary - index;
260 empty = ((nic_state->regs.pgstop - nic_state->regs.pgstart) << 8) - (index - boundary);
263 if (empty < (MAX_ETH_FRAME_SIZE + 4)) {
270 #define MIN_BUF_SIZE 60
272 static void vnic_receive(struct vm_device * dev, const uchar_t * pkt, int length) {
273 struct nic_context * nic_state = (struct nic_context *)dev->private_data;
274 struct nic_regs * nregs = &(nic_state->regs);
277 uint32_t total_len = 0;
283 uint32_t start = nregs->pgstart << 8;
284 uint32_t stop = nregs->pgstop << 8;
286 //PrintDebug("VNIC: received packet, len=%d\n", length);
288 if (nregs->cmd & NE2K_STOP) {
292 if (vnic_rxbuf_full(dev)){
293 PrintDebug("VNIC: received buffer overflow\n");
297 // if too small buffer, expand it
298 if (length < MIN_BUF_SIZE) {
299 memcpy(buf, pkt, length);
300 memset(buf + length, 0, MIN_BUF_SIZE - length);
304 length = MIN_BUF_SIZE;
307 index = nregs->curpag << 8;
310 total_len = length + 4;
312 // address for next packet (4 bytes for CRC)
313 next = index + ((total_len + 4 + 255) & ~0xff);
316 next -= stop - start;
319 p = nic_state->mem + index;
320 nregs->rsr = ENRSR_RXOK;
323 nregs->rsr |= ENRSR_PHY;
329 p[3] = total_len >> 8;
335 empty = stop - index;
346 memcpy(nic_state->mem + index, pkt, len);
357 nregs->curpag = next >> 8;
359 nregs->isr |= ENISR_RX;
360 vnic_update_irq(dev);
365 void pci_vnic_init(PCIBus * bus, NICInfo * nd, int devfn)
367 PCINE2000State * d = NULL;
368 NE2000State * s = NULL;
369 uint8_t * pci_conf = NULL;
370 struct pci_device * pdev = pci_register_device(bus,
371 "NE2000", sizeof(PCINE2000State),
374 pci_conf = d->dev.config;
376 pci_conf[0x00] = 0xec; // Realtek 8029
377 pci_conf[0x01] = 0x10;
378 pci_conf[0x02] = 0x29;
379 pci_conf[0x03] = 0x80;
380 pci_conf[0x0a] = 0x00; // ethernet network controller
381 pci_conf[0x0b] = 0x02;
382 pci_conf[0x0e] = 0x00; // header_type
383 pci_conf[0x3d] = 1; // interrupt pin 0
385 pci_register_io_region(&d->dev, 0, 0x100,
386 PCI_ADDRESS_SPACE_IO, ne2000_map);
389 s->irq = d->dev.irq[0];
391 s->pci_dev = (PCIDevice *)d;
393 memcpy(s->macaddr, nd->macaddr, 6);
397 s->vc = qemu_new_vlan_client(nd->vlan, ne2000_receive,
398 ne2000_can_receive, s);
400 snprintf(s->vc->info_str, sizeof(s->vc->info_str),
401 "ne2000 pci macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
409 /* XXX: instance number ? */
410 register_savevm("ne2000", 0, 3, ne2000_save, ne2000_load, s);
413 //End Here====================================
415 static int netif_input(uchar_t * pkt, uint_t size) {
417 struct vm_device * dev = NULL;
419 PrintDebug("\nVNIC: Packet Received:\nSource:");
421 for (i = 6; i < 12; i++) {
422 PrintDebug("%x ", pkt[i]);
425 dev = get_rx_dev(pkt);
432 for(i = 0; i < size; i++) {
433 PrintDebug("%x ", pkt[i]);
436 vnic_receive(dev, pkt, size);
442 static int vnic_ioport_write(ushort_t port,
445 struct vm_device * dev) {
447 struct nic_context *nic_state = (struct nic_context* )dev->private_data;
452 memcpy(&val, src, 1);
454 PrintDebug("vnic_write error: length %d\n", length);
460 PrintDebug("vnic_write: port:0x%x (%u bytes): 0x%x\n", port, length, (int)val);
462 if (port == EN0_COMMAND) {
463 nic_state->regs.cmd = val;
465 if (!(val & NE2K_STOP)) {
466 nic_state->regs.isr &= ~ENISR_RESET;
468 if ((val & (NE2K_DMAREAD | NE2K_DMAWRITE)) &&
469 nic_state->regs.rbcr == 0) {
470 nic_state->regs.isr |= ENISR_RDC;
471 vnic_update_irq(dev);
475 if (val & NE2K_TRANSMIT) {
476 index = (nic_state->regs.tpsr << 8);
478 if (index >= NE2K_PMEM_END) {
479 index -= NE2K_PMEM_SIZE;
482 if (index + nic_state->regs.tbcr <= NE2K_PMEM_END) {
483 vnic_send_packet(dev, nic_state->mem + index, nic_state->regs.tbcr);
486 nic_state->regs.tsr = ENTSR_PTX;
487 nic_state->regs.isr |= ENISR_TX;
488 nic_state->regs.cmd &= ~NE2K_TRANSMIT;
490 vnic_update_irq(dev);
495 page = nic_state->regs.cmd >> 6;
501 nic_state->regs.pgstart = val;
504 nic_state->regs.pgstop = val;
507 nic_state->regs.boundary = val;
510 nic_state->regs.tpsr = val;
513 nic_state->regs.tbcr = (nic_state->regs.tbcr & 0xff00) | val;
516 nic_state->regs.tbcr = (nic_state->regs.tbcr & 0x00ff) | (val << 8);
519 nic_state->regs.isr &= ~(val & 0x7f);
520 vnic_update_irq(dev);
523 nic_state->regs.rsar = (nic_state->regs.rsar & 0xff00) | val;
526 nic_state->regs.rsar = (nic_state->regs.rsar & 0x00ff) | (val << 8);
529 nic_state->regs.rbcr = (nic_state->regs.rbcr & 0xff00) | val;
532 nic_state->regs.rbcr = (nic_state->regs.rbcr & 0x00ff) | (val << 8);
535 nic_state->regs.rcr = val;
538 nic_state->regs.tcr = val;
540 nic_state->regs.dcr = val;
543 nic_state->regs.imr = val;
544 vnic_update_irq(dev);
547 PrintDebug("vnic_write error: invalid port:0x%x\n", port);
556 case EN1_PHYS ... EN1_PHYS + 5:
557 nic_state->regs.phys[port - EN1_PHYS] = val;
560 nic_state->regs.curpag = val;
562 case EN1_MULT ... EN1_MULT + 7:
563 nic_state->regs.mult[port - EN1_MULT] = val;
566 PrintDebug("vnic_write error: invalid port:0x%x\n", port);
576 nic_state->regs.clda = (nic_state->regs.clda & 0xff00) | val;
579 nic_state->regs.clda = (nic_state->regs.clda & 0x00ff) | (val << 8);
582 nic_state->regs.rnpp = val;
585 nic_state->regs.lnpp = val;
588 nic_state->regs.addcnt = (nic_state->regs.addcnt & 0xff00) | val;
591 nic_state->regs.addcnt = (nic_state->regs.addcnt & 0x00ff) | (val << 8);
594 PrintDebug("vnic_write error: invalid port:0x%x\n", port);
606 static int vnic_ioport_read(ushort_t port, void * dst, uint_t length, struct vm_device *dev) {
610 struct nic_context *nic_state = (struct nic_context* )dev->private_data;
613 PrintDebug("vnic_read error: length %d\n", length);
619 if (port == EN0_COMMAND) {
620 val = nic_state->regs.cmd;
622 page = nic_state->regs.cmd >> 6;
628 val = nic_state->regs.clda & 0x00ff;
631 val = (nic_state->regs.clda & 0xff00) >> 8;
634 val = nic_state->regs.boundary;
637 val = nic_state->regs.tsr;
640 val = nic_state->regs.ncr;
643 val = nic_state->regs.fifo;
646 val = nic_state->regs.isr;
647 vnic_update_irq(dev);
650 val = nic_state->regs.crda & 0x00ff;
653 val = (nic_state->regs.crda & 0xff00) >> 8;
656 val = nic_state->regs.rsr;
659 val = nic_state->regs.cntr & 0x000000ff;
662 val = (nic_state->regs.cntr & 0x0000ff00) >> 8;
665 val = (nic_state->regs.cntr & 0x00ff0000) >> 16;
668 PrintDebug("vnic_read error: invalid port:0x%x\n", port);
673 } else if (page == 1) {
676 case EN1_PHYS ... EN1_PHYS + 5:
677 val = nic_state->regs.phys[port - EN1_PHYS];
680 val = nic_state->regs.curpag;
682 case EN1_MULT ... EN1_MULT + 7:
683 val = nic_state->regs.mult[port - EN1_MULT];
686 PrintDebug("vnic_read error: invalid port:0x%x\n", port);
691 } else if (page == 2) {
695 val = nic_state->regs.pgstart;
698 val = nic_state->regs.pgstop;
701 val = nic_state->regs.rnpp;
704 val = nic_state->regs.lnpp;
707 val = nic_state->regs.tpsr;
710 val = nic_state->regs.addcnt & 0x00ff;
713 val = (nic_state->regs.addcnt & 0xff00) >> 8;
716 val = nic_state->regs.rcr;
719 val = nic_state->regs.tcr;
722 val = nic_state->regs.dcr;
725 val = nic_state->regs.imr;
728 PrintDebug("vnic_read error: invalid port:0x%x\n", port);
735 memcpy(dst, &val, 1);
737 PrintDebug("vnic_read: port:0x%x (%u bytes): 0x%x\n", port,length, (uint32_t)val);
747 static void vnic_mem_writeb(struct nic_context * nic_state,
750 uchar_t tmp = (uchar_t) (val & 0x000000ff);
753 ((addr >= NE2K_PMEM_START && addr) < NE2K_MEM_SIZE) ) {
754 nic_state->mem[addr] = tmp;
757 PrintDebug("wmem addr: %x val: %x\n", addr, val);
760 static void vnic_mem_writew(struct nic_context * nic_state,
764 addr &= ~1; //XXX: check exact behaviour if not even
767 ((addr >= NE2K_PMEM_START && addr) < NE2K_MEM_SIZE)) {
768 *(ushort_t *)(nic_state->mem + addr) = cpu2le16(val);
771 PrintDebug("wmem addr: %x val: %x\n", addr, val);
774 static void vnic_mem_writel(struct nic_context * nic_state,
777 addr &= ~1; // XXX: check exact behaviour if not even
780 ( (addr >= NE2K_PMEM_START) && (addr < NE2K_MEM_SIZE) ) ) {
781 *(uint32_t *)(nic_state->mem + addr) = cpu2le32(val);
784 PrintDebug("wmem addr: %x val: %x\n", addr, val);
787 static uchar_t vnic_mem_readb(struct nic_context * nic_state, uint32_t addr) {
788 PrintDebug("rmem addr: %x\n", addr);
791 ( (addr >= NE2K_PMEM_START) && (addr < NE2K_MEM_SIZE)) ) {
792 return nic_state->mem[addr];
798 static ushort_t vnic_mem_readw(struct nic_context * nic_state, uint32_t addr) {
799 PrintDebug("rmem addr: %x\n", addr);
801 addr &= ~1; //XXX: check exact behaviour if not even
803 ( (addr >= NE2K_PMEM_START) && (addr < NE2K_MEM_SIZE))) {
804 return (ushort_t)le16_to_cpu((ushort_t *)(nic_state->mem + addr));
810 static uint32_t vnic_mem_readl(struct nic_context * nic_state, uint32_t addr) {
811 PrintDebug("rmem addr: %x\n", addr);
813 addr &= ~1; //XXX: check exact behaviour if not even
816 ( (addr >= NE2K_PMEM_START && addr < NE2K_MEM_SIZE))) {
817 return (uint32_t)le32_to_cpu((uint32_t *)(nic_state->mem + addr));
823 static void vnic_dma_update(struct vm_device * dev, int len) {
824 struct nic_context *nic_state = (struct nic_context *)dev->private_data;
826 nic_state->regs.rsar += len;
829 if (nic_state->regs.rsar == nic_state->regs.pgstop) {
830 nic_state->regs.rsar = nic_state->regs.pgstart;
833 if (nic_state->regs.rbcr <= len) {
834 nic_state->regs.rbcr = 0;
835 nic_state->regs.isr |= ENISR_RDC;
837 vnic_update_irq(dev);
839 nic_state->regs.rbcr -= len;
844 //for data port read/write
845 static int vnic_data_read(ushort_t port,
848 struct vm_device * dev) {
850 struct nic_context *nic_state = (struct nic_context *)dev->private_data;
852 // current dma address
853 uint32_t addr = nic_state->regs.rsar;
857 val = vnic_mem_readb(nic_state, addr);
860 val = vnic_mem_readw(nic_state, addr);
863 val = vnic_mem_readl(nic_state, addr);
866 PrintDebug("vnic_data_read error: invalid length %d\n", length);
870 vnic_dma_update(dev, length);
872 memcpy(dst, &val, length);
874 PrintDebug("vnic_read: port:0x%x (%u bytes): 0x%x", port & 0x1f,length, val);
879 static int vnic_data_write(ushort_t port,
882 struct vm_device * dev) {
884 struct nic_context * nic_state = (struct nic_context *)dev->private_data;
886 uint32_t addr = nic_state->regs.rsar;
888 if (nic_state->regs.rbcr == 0) {
892 memcpy(&val, src, length);
894 //determine the starting address of reading/writing
899 vnic_mem_writeb(nic_state, addr, val);
902 vnic_mem_writew(nic_state, addr, val);
905 vnic_mem_writel(nic_state, addr, val);
908 PrintDebug("nic_data_write error: invalid length %d\n", length);
911 vnic_dma_update(dev, length);
913 PrintDebug("vnic_write: port:0x%x (%u bytes): 0x%x\n", port & 0x1f,length, val);
918 static int vnic_reset_device(struct vm_device * dev) {
920 PrintDebug("vnic: reset device\n");
922 init_vnic_context(dev);
929 static int vnic_reset_port_read(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
932 PrintDebug("vnic_read: port:0x%x (%u bytes): 0x%x\n", port,length, val);
933 memcpy(dst, &val, length);
935 vnic_reset_device(dev);
940 static int vnic_reset_port_write(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
943 PrintDebug("vnic_write: port:0x%x (%u bytes): 0x%x\n", port,length, val);
944 memcpy(&val, src, length);
950 static int vnic_start_device(struct vm_device * dev) {
951 PrintDebug("vnic: start device\n");
956 static int vnic_stop_device(struct vm_device * dev) {
957 PrintDebug("vnic: stop device\n");
961 static void init_phy_network() {
962 V3_REGISTER_PKT_DELIVERY(&netif_input);
965 static int vnic_init_device(struct vm_device * dev) {
968 PrintDebug("vnic: init_device\n");
971 init_vnic_context(dev);
975 for (i = 0; i < 16; i++) {
976 v3_dev_hook_io(dev, NIC_BASE_ADDR + i, &vnic_ioport_read, &vnic_ioport_write);
979 v3_dev_hook_io(dev, NIC_BASE_ADDR + NIC_DATA_PORT, &vnic_data_read, &vnic_data_write);
980 v3_dev_hook_io(dev, NIC_BASE_ADDR + NIC_RESET_PORT, &vnic_reset_port_read, &vnic_reset_port_write);
987 static int vnic_deinit_device(struct vm_device * dev) {
990 for (i = 0; i < 16; i++){
991 v3_dev_unhook_io(dev, NIC_BASE_ADDR + i);
994 v3_dev_unhook_io(dev, NIC_BASE_ADDR + NIC_DATA_PORT);
995 v3_dev_unhook_io(dev, NIC_BASE_ADDR + NIC_RESET_PORT);
997 //vnic_reset_device(dev);
1003 static struct vm_device_ops dev_ops = {
1004 .init = vnic_init_device,
1005 .deinit = vnic_deinit_device,
1006 .reset = vnic_reset_device,
1007 .start = vnic_start_device,
1008 .stop = vnic_stop_device,
1012 struct vm_device * v3_create_vnic() {
1013 struct nic_context * nic_state = V3_Malloc(sizeof(struct nic_context));
1015 //memset(nic_state, 0, sizeof(struct nic_context));
1017 //PrintDebug("VNIC internal at %x\n",(int)nic_state);
1019 struct vm_device *device = v3_create_device("VNIC", &dev_ops, nic_state);