1#include "vmkitmon.h" 2#include "pci.h" 3#include "pci_devices.h" 4#include "pci_vmkitmon_eth.h" 5#include "guest.h" 6#include "string.h" 7#include "benchmark.h" 8#include <pci/devids.h> 9#include <net_queue_manager/net_queue_manager.h> 10#include <if/net_queue_manager_defs.h> 11 12#define PCI_ETHERNET_IRQ 11 13#define INVALID 0xffffffff 14#define PCI_HEADER_MEM_ROM_BASE_REGISTER 0xc 15 16#define DRIVER_RECEIVE_BUFFERS 256 17#define DRIVER_TRANSMIT_BUFFER 256 18 19int global_packet_in_count = 0; 20 21static uint8_t guest_mac[] = { 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}; //The mac address presented to virt. linux 22static uint8_t host_mac[] = { 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xBF}; //The mac address presented to barrelfish 23static uint64_t assumed_queue_id = 0; 24static struct pci_device *the_pci_vmkitmon_eth; 25 26// Data-structure to map sent buffer slots back to application slots 27struct pbuf_desc { 28 void *opaque; 29}; 30static struct pbuf_desc pbuf_list_tx[DRIVER_TRANSMIT_BUFFER]; 31 32// tx_index = head, tx_bufptr = tail 33static uint32_t ether_transmit_index = 0, ether_transmit_bufptr = 0; 34 35// rx_index = head, rx_bufptr = tail 36static uint32_t receive_index = 0, receive_bufptr = 0; 37static uint32_t receive_free = 0; 38 39struct rx_buffer { 40 uint64_t paddr; 41 void *vaddr; 42 void *opaque; 43}; 44static struct rx_buffer rx_buffer_ring[DRIVER_RECEIVE_BUFFERS]; 45 46static void generate_interrupt(struct pci_device *dev){ 47 struct pci_vmkitmon_eth * h = dev->state; 48 h->mmio_register[PCI_VMKITMON_ETH_STATUS] |= PCI_VMKITMON_ETH_IRQST; 49 lpc_pic_assert_irq(dev->lpc, dev->irq); 50} 51 52static void confspace_write(struct pci_device *dev, 53 union pci_config_address_word addr, 54 enum opsize size, uint32_t val) 55{ 56 VMKITMON_ETH_DEBUG("pci_vmkitmon_eth confspace_write addr: 0x%x, val: 0x%x\n", addr.d.doubleword, val); 57 struct pci_vmkitmon_eth *h = dev->state; 58 if(4 <= addr.d.doubleword && addr.d.doubleword <= 9 && val == INVALID){ 59 //caller wants to figure out bar size 60 val = ~h->pci_device->bars[addr.d.doubleword - 4].bytes + 1; //~0x100000 + 1 61 VMKITMON_ETH_DEBUG("pci_vmkitmon_eth writing bar %d size. 0x%x\n", addr.d.doubleword-4, val); 62 } 63 if(addr.d.doubleword == 1){ 64 //status register is clear by write 1 65 val = (val & 0xffff) | (h->pci_header[addr.d.doubleword] & ~val)<<16; 66 } 67 h->pci_header[addr.d.doubleword] = val; 68} 69 70static void confspace_read(struct pci_device *dev, 71 union pci_config_address_word addr, 72 enum opsize size, uint32_t *val) 73{ 74 VMKITMON_ETH_DEBUG("confspace_read addr: 0x%x, ",addr.d.doubleword); 75 struct pci_vmkitmon_eth *h = dev->state; 76 77 if(addr.d.fnct_nr != 0) { 78 *val = INVALID; 79 } else { 80 if(addr.d.doubleword == PCI_HEADER_MEM_ROM_BASE_REGISTER) { 81 //we dont support a rom, return always 0 82 *val = 0; 83 } else if(addr.d.doubleword < 0x40) { 84 *val = h->pci_header[addr.d.doubleword]; 85 } else { 86 *val = INVALID; 87 } 88 } 89 90 VMKITMON_ETH_DEBUG(" val: 0x%x\n", *val); 91} 92 93static void get_mac_address_fn(uint8_t* mac) 94{ 95 memcpy(mac, &host_mac, 6); 96} 97 98#if defined(VMKITMON_ETH_DEBUG_SWITCH) 99static void dumpRegion(uint8_t *start){ 100 printf("-- dump starting from 0x%lx --\n", (uint64_t)start); 101 for(int i=0; i<64;i++){ 102 printf("0x%04x: ", i*16); 103 for(int j=0; j<16; j++){ 104 printf("%02x ", *( (start) + (i*16 + j))); 105 } 106 printf("\n"); 107 } 108 printf("-- dump finished --\n"); 109} 110#endif 111 112static errval_t transmit_pbuf_list_fn(struct driver_buffer *buffers, size_t size) { 113 struct pci_vmkitmon_eth *h = the_pci_vmkitmon_eth->state; 114 int i; 115 uint64_t paddr; 116 117 record_packet_receive_from_bf(); 118 119 VMKITMON_ETH_DEBUG("transmit_pbuf_list_fn, no_pbufs: 0x%lx\n", size); 120 121 struct pci_vmkitmon_eth_rxdesc * first_rx = (struct pci_vmkitmon_eth_rxdesc *) guest_to_host( h->mmio_register[PCI_VMKITMON_ETH_RXDESC_ADR] ); 122 uint32_t rxdesc_len = h->mmio_register[PCI_VMKITMON_ETH_RXDESC_ADR]; 123 124 int transmitted = 0; 125 for (i = 0; i < size; i++) { 126 struct driver_buffer *buffer = &buffers[i]; 127 128 paddr = buffer->pa; 129 VMKITMON_ETH_DEBUG("paddr: 0x%lx, len: 0x%lx\n", paddr, buffer->len); 130#if defined(VMKITMON_ETH_DEBUG_SWITCH) 131 dumpRegion(buffer->va); 132#endif 133 134 for(int j = 0; j <= rxdesc_len/sizeof(struct pci_vmkitmon_eth_rxdesc); j++){ 135 struct pci_vmkitmon_eth_rxdesc * cur_rx =first_rx + j; 136 if(cur_rx->len == 0 && cur_rx->addr != 0){ 137 void *hv_addr = (void *)guest_to_host(cur_rx->addr); 138 memcpy(hv_addr, buffer->va, buffer->len); 139 cur_rx->len = buffer->len; 140 VMKITMON_ETH_DEBUG("Used rxdesc %d to transmit\n", j); 141 transmitted = 1; 142 143 pbuf_list_tx[ether_transmit_index].opaque = buffer->opaque; 144 ether_transmit_index = (ether_transmit_index + 1) % DRIVER_TRANSMIT_BUFFER; 145 146 break; 147 } 148 } 149 } 150 151 if(transmitted){ 152 generate_interrupt(the_pci_vmkitmon_eth); 153 } 154 155 return SYS_ERR_OK; 156} 157 158static uint64_t find_tx_free_slot_count_fn(void) { 159 //only called once at beginning & looks fine (returns 256) 160 uint64_t nr_free; 161 if (ether_transmit_index >= ether_transmit_bufptr) { 162 nr_free = DRIVER_TRANSMIT_BUFFER - 163 ((ether_transmit_index - ether_transmit_bufptr) % 164 DRIVER_TRANSMIT_BUFFER); 165 } else { 166 nr_free = DRIVER_TRANSMIT_BUFFER - 167 ((ether_transmit_bufptr - ether_transmit_index) % 168 DRIVER_TRANSMIT_BUFFER); 169 } 170 //printf("find_tx_free_slot_count_fn: %lu, case1?: %d\n", nr_free, ether_transmit_index >= ether_transmit_bufptr); 171 return nr_free; 172} 173 174static bool handle_free_TX_slot_fn(void) { 175 VMKITMON_ETH_DEBUG("handle_free_TX_slot_fn\n"); 176 177 if(ether_transmit_bufptr == ether_transmit_index) { 178 return false; 179 } 180 181 handle_tx_done(pbuf_list_tx[ether_transmit_bufptr].opaque); 182 183 ether_transmit_bufptr = (ether_transmit_bufptr + 1) % DRIVER_TRANSMIT_BUFFER; 184 //netbench_record_event_simple(bm, RE_TX_DONE, rdtsc()); 185 return true; 186} 187 188static void transmit_pending_packets(struct pci_vmkitmon_eth * h){ 189 VMKITMON_ETH_DEBUG("transmit_pending_packets\n"); 190 uint32_t rxdesc_len = h->mmio_register[PCI_VMKITMON_ETH_TXDESC_LEN]; 191 struct pci_vmkitmon_eth_txdesc * first_tx = (struct pci_vmkitmon_eth_txdesc *) guest_to_host( h->mmio_register[PCI_VMKITMON_ETH_TXDESC_ADR] ); 192 for(int i=0; i <= rxdesc_len/sizeof(struct pci_vmkitmon_eth_rxdesc); i++){ 193 struct pci_vmkitmon_eth_txdesc * cur_tx =first_tx + i; 194 if(cur_tx->len != 0 && cur_tx->addr != 0){ 195 void *hv_addr = (void *)guest_to_host(cur_tx->addr); 196 //VMKITMON_ETH_DEBUG("Sending packet at txdesc %d, addr: 0x%x, len: 0x%x\n", i, cur_tx->addr, cur_tx->len); 197 //printf("Sending packet at txdesc %d, addr: 0x%x, len: 0x%x\n", i, cur_tx->addr, cur_tx->len); 198 199 if(receive_free == 0) { 200 VMKITMON_ETH_DEBUG("Could not deliver packet, no receive buffer available. Drop packet.\n"); 201 printf("Could not deliver packet, no receive buffer available. Drop packet.\n"); 202 } else { 203 struct driver_rx_buffer buf; 204 memcpy(rx_buffer_ring[receive_bufptr].vaddr, hv_addr, cur_tx->len); 205 //printf("got packet with len: %d\n",cur_tx->len); 206 if(cur_tx->len == 185){ 207 print_bench_stats(); 208 } else { 209 record_packet_transmit_to_bf(); 210 } 211 buf.opaque = rx_buffer_ring[receive_bufptr].opaque; 212 buf.len = cur_tx->len; 213 process_received_packet(&buf, 1, 0); 214 /* 215 if(*(unsigned char *)hv_addr == 0xaa) { 216 //printf("packet %d delivered to barrelfish\n", ++global_packet_in_count); 217 if(0) dumpRegion(hv_addr); 218 unsigned char *xid = hv_addr + 42; 219 if(*xid == 0 && *(xid + 1) == 0){ 220 printf("XID: 0x%02x%02x%02x%02x\n", *xid, *(xid + 1), *(xid + 2), *(xid + 3)); 221 //dumpRegion(hv_addr); 222 } 223 } */ 224 receive_bufptr = (receive_bufptr + 1) % DRIVER_RECEIVE_BUFFERS; 225 --receive_free; 226 } 227 memset(hv_addr, 0xBF, cur_tx->len); 228 cur_tx->len = 0; 229 } 230 } 231} 232 233static errval_t rx_register_buffer_fn(uint64_t paddr, void *vaddr, void *opaque) { 234 VMKITMON_ETH_DEBUG("rx_register_buffer_fn called\n"); 235 236 rx_buffer_ring[receive_index].paddr = paddr; 237 rx_buffer_ring[receive_index].vaddr = vaddr; 238 rx_buffer_ring[receive_index].opaque = opaque; 239 240 receive_index = (receive_index + 1) % DRIVER_RECEIVE_BUFFERS; 241 receive_free++; 242 return SYS_ERR_OK; 243} 244 245static uint64_t rx_find_free_slot_count_fn(void) { 246 uint64_t nr_free; 247 if (receive_index >= receive_bufptr) { 248 nr_free = DRIVER_RECEIVE_BUFFERS - 249 ((receive_index - receive_bufptr) % 250 DRIVER_RECEIVE_BUFFERS); 251 } else { 252 nr_free = DRIVER_RECEIVE_BUFFERS - 253 ((receive_bufptr - receive_index) % 254 DRIVER_RECEIVE_BUFFERS); 255 } 256 VMKITMON_ETH_DEBUG("rx_find_free_slot_count_fn called, returning %lu\n", nr_free); 257 return nr_free; 258} 259 260static void mem_write(struct pci_device *dev, uint32_t addr, int bar, uint32_t val){ 261 struct pci_vmkitmon_eth *h = dev->state; 262 VMKITMON_ETH_DEBUG("mem_write addr: 0x%x, bar: %d, val: 0x%x, irq: %d\n",addr, bar, val, dev->irq ); 263 switch(addr) { 264 case PCI_VMKITMON_ETH_STATUS: 265 break; 266 case PCI_VMKITMON_ETH_CONTROL: 267 if( val & PCI_VMKITMON_ETH_RSTIRQ ) 268 h->mmio_register[PCI_VMKITMON_ETH_STATUS] &= ~PCI_VMKITMON_ETH_IRQST; 269 if( val & PCI_VMKITMON_ETH_TXMIT ) { 270 VMKITMON_ETH_DEBUG("Transmitting packet. guest-phys packet base address: 0x%x, packet-len: 0x%x\n",h->mmio_register[PCI_VMKITMON_ETH_TXDESC_ADR], h->mmio_register[PCI_VMKITMON_ETH_TXDESC_LEN]); 271 transmit_pending_packets(h); 272 } 273 if( val & PCI_VMKITMON_ETH_IFUP) { 274 VMKITMON_ETH_DEBUG("Interface up, registering\n"); 275 // register to queue_manager 276 ethersrv_init("vmkitmon_eth", 277 assumed_queue_id, 278 get_mac_address_fn, 279 NULL, 280 transmit_pbuf_list_fn, 281 find_tx_free_slot_count_fn, 282 handle_free_TX_slot_fn, 283 2048, // rx_buffer_size, 284 rx_register_buffer_fn, 285 rx_find_free_slot_count_fn 286 ); 287 288 } 289 break; 290 default: 291 h->mmio_register[addr] = val; 292 break; 293 } 294} 295 296static void mem_read(struct pci_device *dev, uint32_t addr, int bar, uint32_t *val){ 297 struct pci_vmkitmon_eth *h = (struct pci_vmkitmon_eth *) dev->state; 298 if(addr != 0) VMKITMON_ETH_DEBUG("mem_read addr: 0x%x, bar: %d, asserting irq: %d\n",addr, bar, dev->irq); 299 switch(addr){ 300 case PCI_VMKITMON_ETH_MAC_LOW: 301 memcpy(val, guest_mac, 4); 302 break; 303 case PCI_VMKITMON_ETH_MAC_HIGH: 304 memcpy(val, guest_mac+4, 2); 305 break; 306 default: 307 *val = h->mmio_register[addr]; 308 } 309} 310 311 312struct pci_device *pci_vmkitmon_eth_new(struct lpc *lpc, struct guest *g) { 313 struct pci_device *dev = calloc(1, sizeof(struct pci_device)); 314 struct pci_vmkitmon_eth *host = calloc(1, sizeof(struct pci_vmkitmon_eth)); 315 host->pci_device = dev; 316 317 //initialize device 318 dev->confspace_write = confspace_write; 319 dev->confspace_read = confspace_read; 320 dev->mem_read = mem_read; 321 dev->mem_write = mem_write; 322 dev->state = host; 323 dev->irq = PCI_ETHERNET_IRQ; 324 dev->lpc = lpc; 325 326 pci_hdr0_mem_t *ph = &host->ph; 327 pci_hdr0_mem_initialize(ph, (mackerel_addr_t) host->pci_header); 328 329 pci_hdr0_mem_vendor_id_wr(ph, PCI_VENDOR_FISH); 330 pci_hdr0_mem_device_id_wr(ph, PCI_VMKITMON_ETH_DEVID); 331 pci_hdr0_mem_class_code_clss_wrf(ph, PCI_CLASS_ETHERNET); 332 333 //The next line could be: pci_hdr0_mem_int_line_wr(ph, PCI_ETHERNET_IRQ); 334 //but the register is defined read only... 335 host->pci_header[0xf] = 1<<8 | PCI_ETHERNET_IRQ; 336 337 338 //Figure out a nice address, for the moment, make sure you dont go over 0xce000000 339 // and stay close beyond (thats the point where the ixgbe is mapped). 340 host->mem_guest_paddr = 0xcb000000; 341 dev->bars[0].paddr = host->mem_guest_paddr; 342 dev->bars[0].bytes = 0x100000; //1 MB 343 344 //Write BAR0 into pci header 345 pci_hdr0_mem_bars_wr(ph, 0, host->mem_guest_paddr); 346 347 the_pci_vmkitmon_eth = dev; 348 return dev; 349} 350