Deleted Added
full compact
pci_virtio_block.c (245678) pci_virtio_block.c (246214)
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 unchanged lines hidden (view full) ---

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 *
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 unchanged lines hidden (view full) ---

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: head/usr.sbin/bhyve/pci_virtio_block.c 245678 2013-01-20 03:42:49Z neel $
26 * $FreeBSD: head/usr.sbin/bhyve/pci_virtio_block.c 246214 2013-02-01 16:58:59Z neel $
27 */
28
29#include <sys/cdefs.h>
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD: head/usr.sbin/bhyve/pci_virtio_block.c 245678 2013-01-20 03:42:49Z neel $");
30__FBSDID("$FreeBSD: head/usr.sbin/bhyve/pci_virtio_block.c 246214 2013-02-01 16:58:59Z neel $");
31
32#include <sys/param.h>
33#include <sys/linker_set.h>
34#include <sys/stat.h>
35#include <sys/uio.h>
36#include <sys/ioctl.h>
37#include <sys/disk.h>
38

--- 11 unchanged lines hidden (view full) ---

50#include "bhyverun.h"
51#include "pci_emul.h"
52#include "virtio.h"
53
54#define VTBLK_RINGSZ 64
55
56#define VTBLK_CFGSZ 28
57
31
32#include <sys/param.h>
33#include <sys/linker_set.h>
34#include <sys/stat.h>
35#include <sys/uio.h>
36#include <sys/ioctl.h>
37#include <sys/disk.h>
38

--- 11 unchanged lines hidden (view full) ---

50#include "bhyverun.h"
51#include "pci_emul.h"
52#include "virtio.h"
53
54#define VTBLK_RINGSZ 64
55
56#define VTBLK_CFGSZ 28
57
58#define VTBLK_R_CFG VTCFG_R_CFG0
58#define VTBLK_R_CFG VTCFG_R_CFG1
59#define VTBLK_R_CFG_END VTBLK_R_CFG + VTBLK_CFGSZ -1
60#define VTBLK_R_MAX VTBLK_R_CFG_END
61
62#define VTBLK_REGSZ VTBLK_R_MAX+1
63
64#define VTBLK_MAXSEGS 32
65
66#define VTBLK_S_OK 0
67#define VTBLK_S_IOERR 1
68
69/*
70 * Host capabilities
71 */
72#define VTBLK_S_HOSTCAPS \
73 ( 0x00000004 | /* host maximum request segments */ \
74 0x10000000 ) /* supports indirect descriptors */
75
59#define VTBLK_R_CFG_END VTBLK_R_CFG + VTBLK_CFGSZ -1
60#define VTBLK_R_MAX VTBLK_R_CFG_END
61
62#define VTBLK_REGSZ VTBLK_R_MAX+1
63
64#define VTBLK_MAXSEGS 32
65
66#define VTBLK_S_OK 0
67#define VTBLK_S_IOERR 1
68
69/*
70 * Host capabilities
71 */
72#define VTBLK_S_HOSTCAPS \
73 ( 0x00000004 | /* host maximum request segments */ \
74 0x10000000 ) /* supports indirect descriptors */
75
76static int use_msix = 1;
77
76struct vring_hqueue {
77 /* Internal state */
78 uint16_t hq_size;
79 uint16_t hq_cur_aidx; /* trails behind 'avail_idx' */
80
81 /* Host-context pointers to the queue */
82 struct virtio_desc *hq_dtable;
83 uint16_t *hq_avail_flags;

--- 46 unchanged lines hidden (view full) ---

130 int vbsc_fd;
131 int vbsc_status;
132 int vbsc_isr;
133 int vbsc_lastq;
134 uint32_t vbsc_features;
135 uint64_t vbsc_pfn;
136 struct vring_hqueue vbsc_q;
137 struct vtblk_config vbsc_cfg;
78struct vring_hqueue {
79 /* Internal state */
80 uint16_t hq_size;
81 uint16_t hq_cur_aidx; /* trails behind 'avail_idx' */
82
83 /* Host-context pointers to the queue */
84 struct virtio_desc *hq_dtable;
85 uint16_t *hq_avail_flags;

--- 46 unchanged lines hidden (view full) ---

132 int vbsc_fd;
133 int vbsc_status;
134 int vbsc_isr;
135 int vbsc_lastq;
136 uint32_t vbsc_features;
137 uint64_t vbsc_pfn;
138 struct vring_hqueue vbsc_q;
139 struct vtblk_config vbsc_cfg;
140 uint16_t msix_table_idx_req;
141 uint16_t msix_table_idx_cfg;
138};
139
142};
143
144/*
145 * Return the size of IO BAR that maps virtio header and device specific
146 * region. The size would vary depending on whether MSI-X is enabled or
147 * not
148 */
149static uint64_t
150pci_vtblk_iosize(struct pci_devinst *pi)
151{
152
153 if (pci_msix_enabled(pi))
154 return (VTBLK_REGSZ);
155 else
156 return (VTBLK_REGSZ - (VTCFG_R_CFG1 - VTCFG_R_MSIX));
157}
158
140/*
141 * Return the number of available descriptors in the vring taking care
142 * of the 16-bit index wraparound.
143 */
144static int
145hq_num_avail(struct vring_hqueue *hq)
146{
147 int ndesc;

--- 137 unchanged lines hidden (view full) ---

285 * sending when an end-of-packet is found
286 */
287 for (i = 0; i < ndescs; i++)
288 pci_vtblk_proc(sc, hq);
289
290 /*
291 * Generate an interrupt if able
292 */
159/*
160 * Return the number of available descriptors in the vring taking care
161 * of the 16-bit index wraparound.
162 */
163static int
164hq_num_avail(struct vring_hqueue *hq)
165{
166 int ndesc;

--- 137 unchanged lines hidden (view full) ---

304 * sending when an end-of-packet is found
305 */
306 for (i = 0; i < ndescs; i++)
307 pci_vtblk_proc(sc, hq);
308
309 /*
310 * Generate an interrupt if able
311 */
293 if ((*hq->hq_avail_flags & VRING_AVAIL_F_NO_INTERRUPT) == 0 &&
294 sc->vbsc_isr == 0) {
295 sc->vbsc_isr = 1;
296 pci_generate_msi(sc->vbsc_pi, 0);
312 if ((*hq->hq_avail_flags & VRING_AVAIL_F_NO_INTERRUPT) == 0) {
313 if (use_msix) {
314 pci_generate_msix(sc->vbsc_pi, sc->msix_table_idx_req);
315 } else if (sc->vbsc_isr == 0) {
316 sc->vbsc_isr = 1;
317 pci_generate_msi(sc->vbsc_pi, 0);
318 }
297 }
298
299}
300
301static void
302pci_vtblk_ring_init(struct pci_vtblk_softc *sc, uint64_t pfn)
303{
304 struct vring_hqueue *hq;

--- 25 unchanged lines hidden (view full) ---

330static int
331pci_vtblk_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
332{
333 struct stat sbuf;
334 struct pci_vtblk_softc *sc;
335 off_t size;
336 int fd;
337 int sectsz;
319 }
320
321}
322
323static void
324pci_vtblk_ring_init(struct pci_vtblk_softc *sc, uint64_t pfn)
325{
326 struct vring_hqueue *hq;

--- 25 unchanged lines hidden (view full) ---

352static int
353pci_vtblk_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
354{
355 struct stat sbuf;
356 struct pci_vtblk_softc *sc;
357 off_t size;
358 int fd;
359 int sectsz;
360 const char *env_msi;
338
339 if (opts == NULL) {
340 printf("virtio-block: backing device required\n");
341 return (1);
342 }
343
344 /*
345 * Access to guest memory is required. Fail if

--- 50 unchanged lines hidden (view full) ---

396 sc->vbsc_cfg.vbc_geom_s = 0;
397 sc->vbsc_cfg.vbc_sectors_max = 0;
398
399 /* initialize config space */
400 pci_set_cfgdata16(pi, PCIR_DEVICE, VIRTIO_DEV_BLOCK);
401 pci_set_cfgdata16(pi, PCIR_VENDOR, VIRTIO_VENDOR);
402 pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_STORAGE);
403 pci_set_cfgdata16(pi, PCIR_SUBDEV_0, VIRTIO_TYPE_BLOCK);
361
362 if (opts == NULL) {
363 printf("virtio-block: backing device required\n");
364 return (1);
365 }
366
367 /*
368 * Access to guest memory is required. Fail if

--- 50 unchanged lines hidden (view full) ---

419 sc->vbsc_cfg.vbc_geom_s = 0;
420 sc->vbsc_cfg.vbc_sectors_max = 0;
421
422 /* initialize config space */
423 pci_set_cfgdata16(pi, PCIR_DEVICE, VIRTIO_DEV_BLOCK);
424 pci_set_cfgdata16(pi, PCIR_VENDOR, VIRTIO_VENDOR);
425 pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_STORAGE);
426 pci_set_cfgdata16(pi, PCIR_SUBDEV_0, VIRTIO_TYPE_BLOCK);
404 pci_emul_add_msicap(pi, 1);
427
428 if ((env_msi = getenv("BHYVE_USE_MSI"))) {
429 if (strcasecmp(env_msi, "yes") == 0)
430 use_msix = 0;
431 }
432
433 if (use_msix) {
434 /* MSI-X Support */
435 sc->msix_table_idx_req = VIRTIO_MSI_NO_VECTOR;
436 sc->msix_table_idx_cfg = VIRTIO_MSI_NO_VECTOR;
437
438 if (pci_emul_add_msixcap(pi, 2, 1))
439 return (1);
440 } else {
441 /* MSI Support */
442 pci_emul_add_msicap(pi, 1);
443 }
444
405 pci_emul_alloc_bar(pi, 0, PCIBAR_IO, VTBLK_REGSZ);
406
407 return (0);
408}
409
445 pci_emul_alloc_bar(pi, 0, PCIBAR_IO, VTBLK_REGSZ);
446
447 return (0);
448}
449
450static uint64_t
451vtblk_adjust_offset(struct pci_devinst *pi, uint64_t offset)
452{
453 /*
454 * Device specific offsets used by guest would change
455 * based on whether MSI-X capability is enabled or not
456 */
457 if (!pci_msix_enabled(pi)) {
458 if (offset >= VTCFG_R_MSIX)
459 return (offset + (VTCFG_R_CFG1 - VTCFG_R_MSIX));
460 }
461
462 return (offset);
463}
464
410static void
411pci_vtblk_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
412 int baridx, uint64_t offset, int size, uint64_t value)
413{
414 struct pci_vtblk_softc *sc = pi->pi_arg;
415
465static void
466pci_vtblk_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
467 int baridx, uint64_t offset, int size, uint64_t value)
468{
469 struct pci_vtblk_softc *sc = pi->pi_arg;
470
471 if (use_msix) {
472 if (baridx == pci_msix_table_bar(pi) ||
473 baridx == pci_msix_pba_bar(pi)) {
474 pci_emul_msix_twrite(pi, offset, size, value);
475 return;
476 }
477 }
478
416 assert(baridx == 0);
417
479 assert(baridx == 0);
480
418 if (offset + size > VTBLK_REGSZ) {
481 if (offset + size > pci_vtblk_iosize(pi)) {
419 DPRINTF(("vtblk_write: 2big, offset %ld size %d\n",
420 offset, size));
421 return;
422 }
423
482 DPRINTF(("vtblk_write: 2big, offset %ld size %d\n",
483 offset, size));
484 return;
485 }
486
487 offset = vtblk_adjust_offset(pi, offset);
488
424 switch (offset) {
425 case VTCFG_R_GUESTCAP:
426 assert(size == 4);
427 sc->vbsc_features = value & VTBLK_S_HOSTCAPS;
428 break;
429 case VTCFG_R_PFN:
430 assert(size == 4);
431 pci_vtblk_ring_init(sc, value);

--- 6 unchanged lines hidden (view full) ---

438 assert(size == 2);
439 assert(value == 0);
440 pci_vtblk_qnotify(sc);
441 break;
442 case VTCFG_R_STATUS:
443 assert(size == 1);
444 pci_vtblk_update_status(sc, value);
445 break;
489 switch (offset) {
490 case VTCFG_R_GUESTCAP:
491 assert(size == 4);
492 sc->vbsc_features = value & VTBLK_S_HOSTCAPS;
493 break;
494 case VTCFG_R_PFN:
495 assert(size == 4);
496 pci_vtblk_ring_init(sc, value);

--- 6 unchanged lines hidden (view full) ---

503 assert(size == 2);
504 assert(value == 0);
505 pci_vtblk_qnotify(sc);
506 break;
507 case VTCFG_R_STATUS:
508 assert(size == 1);
509 pci_vtblk_update_status(sc, value);
510 break;
511 case VTCFG_R_CFGVEC:
512 assert(size == 2);
513 sc->msix_table_idx_cfg = value;
514 break;
515 case VTCFG_R_QVEC:
516 assert(size == 2);
517 sc->msix_table_idx_req = value;
518 break;
446 case VTCFG_R_HOSTCAP:
447 case VTCFG_R_QNUM:
448 case VTCFG_R_ISR:
449 case VTBLK_R_CFG ... VTBLK_R_CFG_END:
450 DPRINTF(("vtblk: write to readonly reg %ld\n\r", offset));
451 break;
452 default:
453 DPRINTF(("vtblk: unknown i/o write offset %ld\n\r", offset));

--- 5 unchanged lines hidden (view full) ---

459uint64_t
460pci_vtblk_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
461 int baridx, uint64_t offset, int size)
462{
463 struct pci_vtblk_softc *sc = pi->pi_arg;
464 void *ptr;
465 uint32_t value;
466
519 case VTCFG_R_HOSTCAP:
520 case VTCFG_R_QNUM:
521 case VTCFG_R_ISR:
522 case VTBLK_R_CFG ... VTBLK_R_CFG_END:
523 DPRINTF(("vtblk: write to readonly reg %ld\n\r", offset));
524 break;
525 default:
526 DPRINTF(("vtblk: unknown i/o write offset %ld\n\r", offset));

--- 5 unchanged lines hidden (view full) ---

532uint64_t
533pci_vtblk_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
534 int baridx, uint64_t offset, int size)
535{
536 struct pci_vtblk_softc *sc = pi->pi_arg;
537 void *ptr;
538 uint32_t value;
539
540 if (use_msix) {
541 if (baridx == pci_msix_table_bar(pi) ||
542 baridx == pci_msix_pba_bar(pi)) {
543 return (pci_emul_msix_tread(pi, offset, size));
544 }
545 }
546
467 assert(baridx == 0);
468
547 assert(baridx == 0);
548
469 if (offset + size > VTBLK_REGSZ) {
549 if (offset + size > pci_vtblk_iosize(pi)) {
470 DPRINTF(("vtblk_read: 2big, offset %ld size %d\n",
471 offset, size));
472 return (0);
473 }
474
550 DPRINTF(("vtblk_read: 2big, offset %ld size %d\n",
551 offset, size));
552 return (0);
553 }
554
555 offset = vtblk_adjust_offset(pi, offset);
556
475 switch (offset) {
476 case VTCFG_R_HOSTCAP:
477 assert(size == 4);
478 value = VTBLK_S_HOSTCAPS;
479 break;
480 case VTCFG_R_GUESTCAP:
481 assert(size == 4);
482 value = sc->vbsc_features; /* XXX never read ? */

--- 17 unchanged lines hidden (view full) ---

500 assert(size == 1);
501 value = sc->vbsc_status;
502 break;
503 case VTCFG_R_ISR:
504 assert(size == 1);
505 value = sc->vbsc_isr;
506 sc->vbsc_isr = 0; /* a read clears this flag */
507 break;
557 switch (offset) {
558 case VTCFG_R_HOSTCAP:
559 assert(size == 4);
560 value = VTBLK_S_HOSTCAPS;
561 break;
562 case VTCFG_R_GUESTCAP:
563 assert(size == 4);
564 value = sc->vbsc_features; /* XXX never read ? */

--- 17 unchanged lines hidden (view full) ---

582 assert(size == 1);
583 value = sc->vbsc_status;
584 break;
585 case VTCFG_R_ISR:
586 assert(size == 1);
587 value = sc->vbsc_isr;
588 sc->vbsc_isr = 0; /* a read clears this flag */
589 break;
590 case VTCFG_R_CFGVEC:
591 assert(size == 2);
592 value = sc->msix_table_idx_cfg;
593 break;
594 case VTCFG_R_QVEC:
595 assert(size == 2);
596 value = sc->msix_table_idx_req;
597 break;
508 case VTBLK_R_CFG ... VTBLK_R_CFG_END:
509 assert(size + offset <= (VTBLK_R_CFG_END + 1));
510 ptr = (uint8_t *)&sc->vbsc_cfg + offset - VTBLK_R_CFG;
511 if (size == 1) {
512 value = *(uint8_t *) ptr;
513 } else if (size == 2) {
514 value = *(uint16_t *) ptr;
515 } else {

--- 19 unchanged lines hidden ---
598 case VTBLK_R_CFG ... VTBLK_R_CFG_END:
599 assert(size + offset <= (VTBLK_R_CFG_END + 1));
600 ptr = (uint8_t *)&sc->vbsc_cfg + offset - VTBLK_R_CFG;
601 if (size == 1) {
602 value = *(uint8_t *) ptr;
603 } else if (size == 2) {
604 value = *(uint16_t *) ptr;
605 } else {

--- 19 unchanged lines hidden ---