xref: /freebsd/usr.sbin/bhyve/pci_virtio_net.c (revision ddd5b8e9b4d8957fce018c520657cdfa4ecffad3)
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