1 /*- 2 * Copyright (c) 2011 NetApp, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include <sys/param.h> 33 #include <sys/linker_set.h> 34 #include <sys/select.h> 35 #include <sys/uio.h> 36 #include <sys/ioctl.h> 37 38 #include <errno.h> 39 #include <fcntl.h> 40 #include <stdio.h> 41 #include <stdlib.h> 42 #include <stdint.h> 43 #include <string.h> 44 #include <strings.h> 45 #include <unistd.h> 46 #include <assert.h> 47 #include <md5.h> 48 #include <pthread.h> 49 50 #include "bhyverun.h" 51 #include "pci_emul.h" 52 #include "mevent.h" 53 #include "virtio.h" 54 55 #define VTNET_RINGSZ 256 56 57 #define VTNET_MAXSEGS 32 58 59 /* 60 * PCI config-space register offsets 61 */ 62 #define VTNET_R_CFG0 24 63 #define VTNET_R_CFG1 25 64 #define VTNET_R_CFG2 26 65 #define VTNET_R_CFG3 27 66 #define VTNET_R_CFG4 28 67 #define VTNET_R_CFG5 29 68 #define VTNET_R_CFG6 30 69 #define VTNET_R_CFG7 31 70 #define VTNET_R_MAX 31 71 72 #define VTNET_REGSZ VTNET_R_MAX+1 73 74 /* 75 * Host capabilities 76 */ 77 #define VTNET_S_HOSTCAPS \ 78 ( 0x00000020 | /* host supplies MAC */ \ 79 0x00008000 | /* host can merge Rx buffers */ \ 80 0x00010000 ) /* config status available */ 81 82 /* 83 * Queue definitions. 84 */ 85 #define VTNET_RXQ 0 86 #define VTNET_TXQ 1 87 #define VTNET_CTLQ 2 88 89 #define VTNET_MAXQ 3 90 91 static int use_msix = 1; 92 93 struct vring_hqueue { 94 /* Internal state */ 95 uint16_t hq_size; 96 uint16_t hq_cur_aidx; /* trails behind 'avail_idx' */ 97 98 /* Host-context pointers to the queue */ 99 struct virtio_desc *hq_dtable; 100 uint16_t *hq_avail_flags; 101 uint16_t *hq_avail_idx; /* monotonically increasing */ 102 uint16_t *hq_avail_ring; 103 104 uint16_t *hq_used_flags; 105 uint16_t *hq_used_idx; /* monotonically increasing */ 106 struct virtio_used *hq_used_ring; 107 }; 108 109 /* 110 * Fixed network header size 111 */ 112 struct virtio_net_rxhdr { 113 uint8_t vrh_flags; 114 uint8_t vrh_gso_type; 115 uint16_t vrh_hdr_len; 116 uint16_t vrh_gso_size; 117 uint16_t vrh_csum_start; 118 uint16_t vrh_csum_offset; 119 uint16_t vrh_bufs; 120 } __packed; 121 122 /* 123 * Debug printf 124 */ 125 static int pci_vtnet_debug; 126 #define DPRINTF(params) if (pci_vtnet_debug) printf params 127 #define WPRINTF(params) printf params 128 129 /* 130 * Per-device softc 131 */ 132 struct pci_vtnet_softc { 133 struct pci_devinst *vsc_pi; 134 pthread_mutex_t vsc_mtx; 135 struct mevent *vsc_mevp; 136 137 int vsc_curq; 138 int vsc_status; 139 int vsc_isr; 140 int vsc_tapfd; 141 int vsc_rx_ready; 142 int vsc_rxpend; 143 144 uint32_t vsc_features; 145 uint8_t vsc_macaddr[6]; 146 147 uint64_t vsc_pfn[VTNET_MAXQ]; 148 struct vring_hqueue vsc_hq[VTNET_MAXQ]; 149 uint16_t vsc_msix_table_idx[VTNET_MAXQ]; 150 }; 151 #define vtnet_ctx(sc) ((sc)->vsc_pi->pi_vmctx) 152 153 /* 154 * Return the size of IO BAR that maps virtio header and device specific 155 * region. The size would vary depending on whether MSI-X is enabled or 156 * not. 157 */ 158 static uint64_t 159 pci_vtnet_iosize(struct pci_devinst *pi) 160 { 161 if (pci_msix_enabled(pi)) 162 return (VTNET_REGSZ); 163 else 164 return (VTNET_REGSZ - (VTCFG_R_CFG1 - VTCFG_R_MSIX)); 165 } 166 167 /* 168 * Return the number of available descriptors in the vring taking care 169 * of the 16-bit index wraparound. 170 */ 171 static int 172 hq_num_avail(struct vring_hqueue *hq) 173 { 174 uint16_t ndesc; 175 176 /* 177 * We're just computing (a-b) in GF(216). 178 * 179 * The only glitch here is that in standard C, 180 * uint16_t promotes to (signed) int when int has 181 * more than 16 bits (pretty much always now), so 182 * we have to force it back to unsigned. 183 */ 184 ndesc = (unsigned)*hq->hq_avail_idx - (unsigned)hq->hq_cur_aidx; 185 186 assert(ndesc <= hq->hq_size); 187 188 return (ndesc); 189 } 190 191 static uint16_t 192 pci_vtnet_qsize(int qnum) 193 { 194 /* XXX no ctl queue currently */ 195 if (qnum == VTNET_CTLQ) { 196 return (0); 197 } 198 199 /* XXX fixed currently. Maybe different for tx/rx/ctl */ 200 return (VTNET_RINGSZ); 201 } 202 203 static void 204 pci_vtnet_ring_reset(struct pci_vtnet_softc *sc, int ring) 205 { 206 struct vring_hqueue *hq; 207 208 assert(ring < VTNET_MAXQ); 209 210 hq = &sc->vsc_hq[ring]; 211 212 /* 213 * Reset all soft state 214 */ 215 hq->hq_cur_aidx = 0; 216 } 217 218 static void 219 pci_vtnet_update_status(struct pci_vtnet_softc *sc, uint32_t value) 220 { 221 222 if (value == 0) { 223 DPRINTF(("vtnet: device reset requested !\n")); 224 pci_vtnet_ring_reset(sc, VTNET_RXQ); 225 pci_vtnet_ring_reset(sc, VTNET_TXQ); 226 sc->vsc_rx_ready = 0; 227 } 228 229 sc->vsc_status = value; 230 } 231 232 /* 233 * Called to send a buffer chain out to the tap device 234 */ 235 static void 236 pci_vtnet_tap_tx(struct pci_vtnet_softc *sc, struct iovec *iov, int iovcnt, 237 int len) 238 { 239 char pad[60]; 240 241 if (sc->vsc_tapfd == -1) 242 return; 243 244 /* 245 * If the length is < 60, pad out to that and add the 246 * extra zero'd segment to the iov. It is guaranteed that 247 * there is always an extra iov available by the caller. 248 */ 249 if (len < 60) { 250 memset(pad, 0, 60 - len); 251 iov[iovcnt].iov_base = pad; 252 iov[iovcnt].iov_len = 60 - len; 253 iovcnt++; 254 } 255 (void) writev(sc->vsc_tapfd, iov, iovcnt); 256 } 257 258 /* 259 * Called when there is read activity on the tap file descriptor. 260 * Each buffer posted by the guest is assumed to be able to contain 261 * an entire ethernet frame + rx header. 262 * MP note: the dummybuf is only used for discarding frames, so there 263 * is no need for it to be per-vtnet or locked. 264 */ 265 static uint8_t dummybuf[2048]; 266 267 static void 268 pci_vtnet_tap_rx(struct pci_vtnet_softc *sc) 269 { 270 struct virtio_desc *vd; 271 struct virtio_used *vu; 272 struct vring_hqueue *hq; 273 struct virtio_net_rxhdr *vrx; 274 uint8_t *buf; 275 int i; 276 int len; 277 int ndescs; 278 int didx, uidx, aidx; /* descriptor, avail and used index */ 279 280 /* 281 * Should never be called without a valid tap fd 282 */ 283 assert(sc->vsc_tapfd != -1); 284 285 /* 286 * But, will be called when the rx ring hasn't yet 287 * been set up. 288 */ 289 if (sc->vsc_rx_ready == 0) { 290 /* 291 * Drop the packet and try later. 292 */ 293 (void) read(sc->vsc_tapfd, dummybuf, sizeof(dummybuf)); 294 return; 295 } 296 297 /* 298 * Calculate the number of available rx buffers 299 */ 300 hq = &sc->vsc_hq[VTNET_RXQ]; 301 302 ndescs = hq_num_avail(hq); 303 304 if (ndescs == 0) { 305 /* 306 * Need to wait for host notification to read 307 */ 308 if (sc->vsc_rxpend == 0) { 309 WPRINTF(("vtnet: no rx descriptors !\n")); 310 sc->vsc_rxpend = 1; 311 } 312 313 /* 314 * Drop the packet and try later 315 */ 316 (void) read(sc->vsc_tapfd, dummybuf, sizeof(dummybuf)); 317 return; 318 } 319 320 aidx = hq->hq_cur_aidx; 321 uidx = *hq->hq_used_idx; 322 for (i = 0; i < ndescs; i++) { 323 /* 324 * 'aidx' indexes into the an array of descriptor indexes 325 */ 326 didx = hq->hq_avail_ring[aidx % hq->hq_size]; 327 assert(didx >= 0 && didx < hq->hq_size); 328 329 vd = &hq->hq_dtable[didx]; 330 331 /* 332 * Get a pointer to the rx header, and use the 333 * data immediately following it for the packet buffer. 334 */ 335 vrx = paddr_guest2host(vtnet_ctx(sc), vd->vd_addr, vd->vd_len); 336 buf = (uint8_t *)(vrx + 1); 337 338 len = read(sc->vsc_tapfd, buf, 339 vd->vd_len - sizeof(struct virtio_net_rxhdr)); 340 341 if (len < 0 && errno == EWOULDBLOCK) { 342 break; 343 } 344 345 /* 346 * The only valid field in the rx packet header is the 347 * number of buffers, which is always 1 without TSO 348 * support. 349 */ 350 memset(vrx, 0, sizeof(struct virtio_net_rxhdr)); 351 vrx->vrh_bufs = 1; 352 353 /* 354 * Write this descriptor into the used ring 355 */ 356 vu = &hq->hq_used_ring[uidx % hq->hq_size]; 357 vu->vu_idx = didx; 358 vu->vu_tlen = len + sizeof(struct virtio_net_rxhdr); 359 uidx++; 360 aidx++; 361 } 362 363 /* 364 * Update the used pointer, and signal an interrupt if allowed 365 */ 366 *hq->hq_used_idx = uidx; 367 hq->hq_cur_aidx = aidx; 368 369 if ((*hq->hq_avail_flags & VRING_AVAIL_F_NO_INTERRUPT) == 0) { 370 if (use_msix) { 371 pci_generate_msix(sc->vsc_pi, 372 sc->vsc_msix_table_idx[VTNET_RXQ]); 373 } else { 374 sc->vsc_isr |= 1; 375 pci_generate_msi(sc->vsc_pi, 0); 376 } 377 } 378 } 379 380 static void 381 pci_vtnet_tap_callback(int fd, enum ev_type type, void *param) 382 { 383 struct pci_vtnet_softc *sc = param; 384 385 pthread_mutex_lock(&sc->vsc_mtx); 386 pci_vtnet_tap_rx(sc); 387 pthread_mutex_unlock(&sc->vsc_mtx); 388 389 } 390 391 static void 392 pci_vtnet_ping_rxq(struct pci_vtnet_softc *sc) 393 { 394 /* 395 * A qnotify means that the rx process can now begin 396 */ 397 if (sc->vsc_rx_ready == 0) { 398 sc->vsc_rx_ready = 1; 399 } 400 401 /* 402 * If the rx queue was empty, attempt to receive a 403 * packet that was previously blocked due to no rx bufs 404 * available 405 */ 406 if (sc->vsc_rxpend) { 407 WPRINTF(("vtnet: rx resumed\n\r")); 408 sc->vsc_rxpend = 0; 409 pci_vtnet_tap_rx(sc); 410 } 411 } 412 413 static void 414 pci_vtnet_proctx(struct pci_vtnet_softc *sc, struct vring_hqueue *hq) 415 { 416 struct iovec iov[VTNET_MAXSEGS + 1]; 417 struct virtio_desc *vd; 418 struct virtio_used *vu; 419 int i; 420 int plen; 421 int tlen; 422 int uidx, aidx, didx; 423 424 uidx = *hq->hq_used_idx; 425 aidx = hq->hq_cur_aidx; 426 didx = hq->hq_avail_ring[aidx % hq->hq_size]; 427 assert(didx >= 0 && didx < hq->hq_size); 428 429 vd = &hq->hq_dtable[didx]; 430 431 /* 432 * Run through the chain of descriptors, ignoring the 433 * first header descriptor. However, include the header 434 * length in the total length that will be put into the 435 * used queue. 436 */ 437 tlen = vd->vd_len; 438 vd = &hq->hq_dtable[vd->vd_next]; 439 440 for (i = 0, plen = 0; 441 i < VTNET_MAXSEGS; 442 i++, vd = &hq->hq_dtable[vd->vd_next]) { 443 iov[i].iov_base = paddr_guest2host(vtnet_ctx(sc), 444 vd->vd_addr, vd->vd_len); 445 iov[i].iov_len = vd->vd_len; 446 plen += vd->vd_len; 447 tlen += vd->vd_len; 448 449 if ((vd->vd_flags & VRING_DESC_F_NEXT) == 0) 450 break; 451 } 452 assert(i < VTNET_MAXSEGS); 453 454 DPRINTF(("virtio: packet send, %d bytes, %d segs\n\r", plen, i + 1)); 455 pci_vtnet_tap_tx(sc, iov, i + 1, plen); 456 457 /* 458 * Return this chain back to the host 459 */ 460 vu = &hq->hq_used_ring[uidx % hq->hq_size]; 461 vu->vu_idx = didx; 462 vu->vu_tlen = tlen; 463 hq->hq_cur_aidx = aidx + 1; 464 *hq->hq_used_idx = uidx + 1; 465 466 /* 467 * Generate an interrupt if able 468 */ 469 if ((*hq->hq_avail_flags & VRING_AVAIL_F_NO_INTERRUPT) == 0) { 470 if (use_msix) { 471 pci_generate_msix(sc->vsc_pi, 472 sc->vsc_msix_table_idx[VTNET_TXQ]); 473 } else { 474 sc->vsc_isr |= 1; 475 pci_generate_msi(sc->vsc_pi, 0); 476 } 477 } 478 } 479 480 static void 481 pci_vtnet_ping_txq(struct pci_vtnet_softc *sc) 482 { 483 struct vring_hqueue *hq = &sc->vsc_hq[VTNET_TXQ]; 484 int i; 485 int ndescs; 486 487 /* 488 * Calculate number of ring entries to process 489 */ 490 ndescs = hq_num_avail(hq); 491 492 if (ndescs == 0) 493 return; 494 495 /* 496 * Run through all the entries, placing them into iovecs and 497 * sending when an end-of-packet is found 498 */ 499 for (i = 0; i < ndescs; i++) 500 pci_vtnet_proctx(sc, hq); 501 } 502 503 static void 504 pci_vtnet_ping_ctlq(struct pci_vtnet_softc *sc) 505 { 506 507 DPRINTF(("vtnet: control qnotify!\n\r")); 508 } 509 510 static void 511 pci_vtnet_ring_init(struct pci_vtnet_softc *sc, uint64_t pfn) 512 { 513 struct vring_hqueue *hq; 514 int qnum = sc->vsc_curq; 515 516 assert(qnum < VTNET_MAXQ); 517 518 sc->vsc_pfn[qnum] = pfn << VRING_PFN; 519 520 /* 521 * Set up host pointers to the various parts of the 522 * queue 523 */ 524 hq = &sc->vsc_hq[qnum]; 525 hq->hq_size = pci_vtnet_qsize(qnum); 526 527 hq->hq_dtable = paddr_guest2host(vtnet_ctx(sc), pfn << VRING_PFN, 528 vring_size(hq->hq_size)); 529 hq->hq_avail_flags = (uint16_t *)(hq->hq_dtable + hq->hq_size); 530 hq->hq_avail_idx = hq->hq_avail_flags + 1; 531 hq->hq_avail_ring = hq->hq_avail_flags + 2; 532 hq->hq_used_flags = (uint16_t *)roundup2((uintptr_t)hq->hq_avail_ring, 533 VRING_ALIGN); 534 hq->hq_used_idx = hq->hq_used_flags + 1; 535 hq->hq_used_ring = (struct virtio_used *)(hq->hq_used_flags + 2); 536 537 /* 538 * Initialize queue indexes 539 */ 540 hq->hq_cur_aidx = 0; 541 } 542 543 static int 544 pci_vtnet_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) 545 { 546 MD5_CTX mdctx; 547 unsigned char digest[16]; 548 char nstr[80]; 549 struct pci_vtnet_softc *sc; 550 const char *env_msi; 551 552 sc = malloc(sizeof(struct pci_vtnet_softc)); 553 memset(sc, 0, sizeof(struct pci_vtnet_softc)); 554 555 pi->pi_arg = sc; 556 sc->vsc_pi = pi; 557 558 pthread_mutex_init(&sc->vsc_mtx, NULL); 559 560 /* 561 * Use MSI if set by user 562 */ 563 if ((env_msi = getenv("BHYVE_USE_MSI")) != NULL) { 564 if (strcasecmp(env_msi, "yes") == 0) 565 use_msix = 0; 566 } 567 568 /* 569 * Attempt to open the tap device 570 */ 571 sc->vsc_tapfd = -1; 572 if (opts != NULL) { 573 char tbuf[80]; 574 575 strcpy(tbuf, "/dev/"); 576 strlcat(tbuf, opts, sizeof(tbuf)); 577 578 sc->vsc_tapfd = open(tbuf, O_RDWR); 579 if (sc->vsc_tapfd == -1) { 580 WPRINTF(("open of tap device %s failed\n", tbuf)); 581 } else { 582 /* 583 * Set non-blocking and register for read 584 * notifications with the event loop 585 */ 586 int opt = 1; 587 if (ioctl(sc->vsc_tapfd, FIONBIO, &opt) < 0) { 588 WPRINTF(("tap device O_NONBLOCK failed\n")); 589 close(sc->vsc_tapfd); 590 sc->vsc_tapfd = -1; 591 } 592 593 sc->vsc_mevp = mevent_add(sc->vsc_tapfd, 594 EVF_READ, 595 pci_vtnet_tap_callback, 596 sc); 597 if (sc->vsc_mevp == NULL) { 598 WPRINTF(("Could not register event\n")); 599 close(sc->vsc_tapfd); 600 sc->vsc_tapfd = -1; 601 } 602 } 603 } 604 605 /* 606 * The MAC address is the standard NetApp OUI of 00-a0-98, 607 * followed by an MD5 of the vm name. The slot/func number is 608 * prepended to this for slots other than 1:0, so that 609 * a bootloader can netboot from the equivalent of slot 1. 610 */ 611 if (pi->pi_slot == 1 && pi->pi_func == 0) { 612 strncpy(nstr, vmname, sizeof(nstr)); 613 } else { 614 snprintf(nstr, sizeof(nstr), "%d-%d-%s", pi->pi_slot, 615 pi->pi_func, vmname); 616 } 617 618 MD5Init(&mdctx); 619 MD5Update(&mdctx, nstr, strlen(nstr)); 620 MD5Final(digest, &mdctx); 621 622 sc->vsc_macaddr[0] = 0x00; 623 sc->vsc_macaddr[1] = 0xa0; 624 sc->vsc_macaddr[2] = 0x98; 625 sc->vsc_macaddr[3] = digest[0]; 626 sc->vsc_macaddr[4] = digest[1]; 627 sc->vsc_macaddr[5] = digest[2]; 628 629 /* initialize config space */ 630 pci_set_cfgdata16(pi, PCIR_DEVICE, VIRTIO_DEV_NET); 631 pci_set_cfgdata16(pi, PCIR_VENDOR, VIRTIO_VENDOR); 632 pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_NETWORK); 633 pci_set_cfgdata16(pi, PCIR_SUBDEV_0, VIRTIO_TYPE_NET); 634 635 if (use_msix) { 636 /* MSI-X support */ 637 int i; 638 639 for (i = 0; i < VTNET_MAXQ; i++) 640 sc->vsc_msix_table_idx[i] = VIRTIO_MSI_NO_VECTOR; 641 642 /* 643 * BAR 1 used to map MSI-X table and PBA 644 */ 645 if (pci_emul_add_msixcap(pi, VTNET_MAXQ, 1)) 646 return (1); 647 } else { 648 /* MSI support */ 649 pci_emul_add_msicap(pi, 1); 650 } 651 652 pci_emul_alloc_bar(pi, 0, PCIBAR_IO, VTNET_REGSZ); 653 654 return (0); 655 } 656 657 /* 658 * Function pointer array to handle queue notifications 659 */ 660 static void (*pci_vtnet_qnotify[VTNET_MAXQ])(struct pci_vtnet_softc *) = { 661 pci_vtnet_ping_rxq, 662 pci_vtnet_ping_txq, 663 pci_vtnet_ping_ctlq 664 }; 665 666 static uint64_t 667 vtnet_adjust_offset(struct pci_devinst *pi, uint64_t offset) 668 { 669 /* 670 * Device specific offsets used by guest would change based on 671 * whether MSI-X capability is enabled or not 672 */ 673 if (!pci_msix_enabled(pi)) { 674 if (offset >= VTCFG_R_MSIX) 675 return (offset + (VTCFG_R_CFG1 - VTCFG_R_MSIX)); 676 } 677 678 return (offset); 679 } 680 681 static void 682 pci_vtnet_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, 683 int baridx, uint64_t offset, int size, uint64_t value) 684 { 685 struct pci_vtnet_softc *sc = pi->pi_arg; 686 void *ptr; 687 688 if (use_msix) { 689 if (baridx == pci_msix_table_bar(pi) || 690 baridx == pci_msix_pba_bar(pi)) { 691 pci_emul_msix_twrite(pi, offset, size, value); 692 return; 693 } 694 } 695 696 assert(baridx == 0); 697 698 if (offset + size > pci_vtnet_iosize(pi)) { 699 DPRINTF(("vtnet_write: 2big, offset %ld size %d\n", 700 offset, size)); 701 return; 702 } 703 704 pthread_mutex_lock(&sc->vsc_mtx); 705 706 offset = vtnet_adjust_offset(pi, offset); 707 708 switch (offset) { 709 case VTCFG_R_GUESTCAP: 710 assert(size == 4); 711 sc->vsc_features = value & VTNET_S_HOSTCAPS; 712 break; 713 case VTCFG_R_PFN: 714 assert(size == 4); 715 pci_vtnet_ring_init(sc, value); 716 break; 717 case VTCFG_R_QSEL: 718 assert(size == 2); 719 assert(value < VTNET_MAXQ); 720 sc->vsc_curq = value; 721 break; 722 case VTCFG_R_QNOTIFY: 723 assert(size == 2); 724 assert(value < VTNET_MAXQ); 725 (*pci_vtnet_qnotify[value])(sc); 726 break; 727 case VTCFG_R_STATUS: 728 assert(size == 1); 729 pci_vtnet_update_status(sc, value); 730 break; 731 case VTCFG_R_CFGVEC: 732 assert(size == 2); 733 sc->vsc_msix_table_idx[VTNET_CTLQ] = value; 734 break; 735 case VTCFG_R_QVEC: 736 assert(size == 2); 737 assert(sc->vsc_curq != VTNET_CTLQ); 738 sc->vsc_msix_table_idx[sc->vsc_curq] = value; 739 break; 740 case VTNET_R_CFG0: 741 case VTNET_R_CFG1: 742 case VTNET_R_CFG2: 743 case VTNET_R_CFG3: 744 case VTNET_R_CFG4: 745 case VTNET_R_CFG5: 746 assert((size + offset) <= (VTNET_R_CFG5 + 1)); 747 ptr = &sc->vsc_macaddr[offset - VTNET_R_CFG0]; 748 /* 749 * The driver is allowed to change the MAC address 750 */ 751 sc->vsc_macaddr[offset - VTNET_R_CFG0] = value; 752 if (size == 1) { 753 *(uint8_t *) ptr = value; 754 } else if (size == 2) { 755 *(uint16_t *) ptr = value; 756 } else { 757 *(uint32_t *) ptr = value; 758 } 759 break; 760 case VTCFG_R_HOSTCAP: 761 case VTCFG_R_QNUM: 762 case VTCFG_R_ISR: 763 case VTNET_R_CFG6: 764 case VTNET_R_CFG7: 765 DPRINTF(("vtnet: write to readonly reg %ld\n\r", offset)); 766 break; 767 default: 768 DPRINTF(("vtnet: unknown i/o write offset %ld\n\r", offset)); 769 value = 0; 770 break; 771 } 772 773 pthread_mutex_unlock(&sc->vsc_mtx); 774 } 775 776 uint64_t 777 pci_vtnet_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, 778 int baridx, uint64_t offset, int size) 779 { 780 struct pci_vtnet_softc *sc = pi->pi_arg; 781 void *ptr; 782 uint64_t value; 783 784 if (use_msix) { 785 if (baridx == pci_msix_table_bar(pi) || 786 baridx == pci_msix_pba_bar(pi)) { 787 return (pci_emul_msix_tread(pi, offset, size)); 788 } 789 } 790 791 assert(baridx == 0); 792 793 if (offset + size > pci_vtnet_iosize(pi)) { 794 DPRINTF(("vtnet_read: 2big, offset %ld size %d\n", 795 offset, size)); 796 return (0); 797 } 798 799 pthread_mutex_lock(&sc->vsc_mtx); 800 801 offset = vtnet_adjust_offset(pi, offset); 802 803 switch (offset) { 804 case VTCFG_R_HOSTCAP: 805 assert(size == 4); 806 value = VTNET_S_HOSTCAPS; 807 break; 808 case VTCFG_R_GUESTCAP: 809 assert(size == 4); 810 value = sc->vsc_features; /* XXX never read ? */ 811 break; 812 case VTCFG_R_PFN: 813 assert(size == 4); 814 value = sc->vsc_pfn[sc->vsc_curq] >> VRING_PFN; 815 break; 816 case VTCFG_R_QNUM: 817 assert(size == 2); 818 value = pci_vtnet_qsize(sc->vsc_curq); 819 break; 820 case VTCFG_R_QSEL: 821 assert(size == 2); 822 value = sc->vsc_curq; /* XXX never read ? */ 823 break; 824 case VTCFG_R_QNOTIFY: 825 assert(size == 2); 826 value = sc->vsc_curq; /* XXX never read ? */ 827 break; 828 case VTCFG_R_STATUS: 829 assert(size == 1); 830 value = sc->vsc_status; 831 break; 832 case VTCFG_R_ISR: 833 assert(size == 1); 834 value = sc->vsc_isr; 835 sc->vsc_isr = 0; /* a read clears this flag */ 836 break; 837 case VTCFG_R_CFGVEC: 838 assert(size == 2); 839 value = sc->vsc_msix_table_idx[VTNET_CTLQ]; 840 break; 841 case VTCFG_R_QVEC: 842 assert(size == 2); 843 assert(sc->vsc_curq != VTNET_CTLQ); 844 value = sc->vsc_msix_table_idx[sc->vsc_curq]; 845 break; 846 case VTNET_R_CFG0: 847 case VTNET_R_CFG1: 848 case VTNET_R_CFG2: 849 case VTNET_R_CFG3: 850 case VTNET_R_CFG4: 851 case VTNET_R_CFG5: 852 assert((size + offset) <= (VTNET_R_CFG5 + 1)); 853 ptr = &sc->vsc_macaddr[offset - VTNET_R_CFG0]; 854 if (size == 1) { 855 value = *(uint8_t *) ptr; 856 } else if (size == 2) { 857 value = *(uint16_t *) ptr; 858 } else { 859 value = *(uint32_t *) ptr; 860 } 861 break; 862 case VTNET_R_CFG6: 863 assert(size != 4); 864 value = 0x01; /* XXX link always up */ 865 break; 866 case VTNET_R_CFG7: 867 assert(size == 1); 868 value = 0; /* XXX link status in LSB */ 869 break; 870 default: 871 DPRINTF(("vtnet: unknown i/o read offset %ld\n\r", offset)); 872 value = 0; 873 break; 874 } 875 876 pthread_mutex_unlock(&sc->vsc_mtx); 877 878 return (value); 879 } 880 881 struct pci_devemu pci_de_vnet = { 882 .pe_emu = "virtio-net", 883 .pe_init = pci_vtnet_init, 884 .pe_barwrite = pci_vtnet_write, 885 .pe_barread = pci_vtnet_read 886 }; 887 PCI_EMUL_SET(pci_de_vnet); 888