2 * Copyright (c) 2011 NetApp, Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include <sys/param.h>
33 #include <sys/linker_set.h>
36 #include <sys/ioctl.h>
54 #define VTBLK_RINGSZ 64
56 #define VTBLK_CFGSZ 28
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
62 #define VTBLK_REGSZ VTBLK_R_MAX+1
64 #define VTBLK_MAXSEGS 32
67 #define VTBLK_S_IOERR 1
72 #define VTBLK_S_HOSTCAPS \
73 ( 0x00000004 | /* host maximum request segments */ \
74 0x10000000 ) /* supports indirect descriptors */
76 static int use_msix = 1;
81 uint16_t hq_cur_aidx; /* trails behind 'avail_idx' */
83 /* Host-context pointers to the queue */
84 struct virtio_desc *hq_dtable;
85 uint16_t *hq_avail_flags;
86 uint16_t *hq_avail_idx; /* monotonically increasing */
87 uint16_t *hq_avail_ring;
89 uint16_t *hq_used_flags;
90 uint16_t *hq_used_idx; /* monotonically increasing */
91 struct virtio_used *hq_used_ring;
98 uint64_t vbc_capacity;
99 uint32_t vbc_size_max;
100 uint32_t vbc_seg_max;
104 uint32_t vbc_blk_size;
105 uint32_t vbc_sectors_max;
107 CTASSERT(sizeof(struct vtblk_config) == VTBLK_CFGSZ);
110 * Fixed-size block header
112 struct virtio_blk_hdr {
113 #define VBH_OP_READ 0
114 #define VBH_OP_WRITE 1
115 #define VBH_FLAG_BARRIER 0x80000000 /* OR'ed into vbh_type */
124 static int pci_vtblk_debug;
125 #define DPRINTF(params) if (pci_vtblk_debug) printf params
126 #define WPRINTF(params) printf params
131 struct pci_vtblk_softc {
132 struct pci_devinst *vbsc_pi;
137 uint32_t vbsc_features;
139 struct vring_hqueue vbsc_q;
140 struct vtblk_config vbsc_cfg;
141 uint16_t msix_table_idx_req;
142 uint16_t msix_table_idx_cfg;
144 #define vtblk_ctx(sc) ((sc)->vbsc_pi->pi_vmctx)
147 * Return the size of IO BAR that maps virtio header and device specific
148 * region. The size would vary depending on whether MSI-X is enabled or
152 pci_vtblk_iosize(struct pci_devinst *pi)
155 if (pci_msix_enabled(pi))
156 return (VTBLK_REGSZ);
158 return (VTBLK_REGSZ - (VTCFG_R_CFG1 - VTCFG_R_MSIX));
162 * Return the number of available descriptors in the vring taking care
163 * of the 16-bit index wraparound.
166 hq_num_avail(struct vring_hqueue *hq)
171 * We're just computing (a-b) in GF(216).
173 * The only glitch here is that in standard C,
174 * uint16_t promotes to (signed) int when int has
175 * more than 16 bits (pretty much always now), so
176 * we have to force it back to unsigned.
178 ndesc = (unsigned)*hq->hq_avail_idx - (unsigned)hq->hq_cur_aidx;
180 assert(ndesc <= hq->hq_size);
186 pci_vtblk_update_status(struct pci_vtblk_softc *sc, uint32_t value)
189 DPRINTF(("vtblk: device reset requested !\n"));
191 sc->msix_table_idx_req = VIRTIO_MSI_NO_VECTOR;
192 sc->msix_table_idx_cfg = VIRTIO_MSI_NO_VECTOR;
193 sc->vbsc_features = 0;
196 memset(&sc->vbsc_q, 0, sizeof(struct vring_hqueue));
199 sc->vbsc_status = value;
203 pci_vtblk_proc(struct pci_vtblk_softc *sc, struct vring_hqueue *hq)
205 struct iovec iov[VTBLK_MAXSEGS];
206 struct virtio_blk_hdr *vbh;
207 struct virtio_desc *vd, *vid;
208 struct virtio_used *vu;
213 int uidx, aidx, didx;
214 int indirect, writeop, type;
217 uidx = *hq->hq_used_idx;
218 aidx = hq->hq_cur_aidx;
219 didx = hq->hq_avail_ring[aidx % hq->hq_size];
220 assert(didx >= 0 && didx < hq->hq_size);
222 vd = &hq->hq_dtable[didx];
224 indirect = ((vd->vd_flags & VRING_DESC_F_INDIRECT) != 0);
227 vid = paddr_guest2host(vtblk_ctx(sc), vd->vd_addr, vd->vd_len);
232 * The first descriptor will be the read-only fixed header
234 vbh = paddr_guest2host(vtblk_ctx(sc), vd->vd_addr,
235 sizeof(struct virtio_blk_hdr));
236 assert(vd->vd_len == sizeof(struct virtio_blk_hdr));
237 assert(vd->vd_flags & VRING_DESC_F_NEXT);
238 assert((vd->vd_flags & VRING_DESC_F_WRITE) == 0);
242 * The guest should not be setting the BARRIER flag because
243 * we don't advertise the capability.
245 type = vbh->vbh_type & ~VBH_FLAG_BARRIER;
246 writeop = (type == VBH_OP_WRITE);
248 offset = vbh->vbh_sector * DEV_BSIZE;
251 * Build up the iovec based on the guest's data descriptors
256 vd = &vid[i + 1]; /* skip first indirect desc */
258 vd = &hq->hq_dtable[vd->vd_next];
260 if ((vd->vd_flags & VRING_DESC_F_NEXT) == 0)
263 if (i == VTBLK_MAXSEGS)
267 * - write op implies read-only descriptor,
268 * - read op implies write-only descriptor,
269 * therefore test the inverse of the descriptor bit
272 assert(((vd->vd_flags & VRING_DESC_F_WRITE) == 0) ==
275 iov[i].iov_base = paddr_guest2host(vtblk_ctx(sc),
278 iov[i].iov_len = vd->vd_len;
283 /* Lastly, get the address of the status byte */
284 status = paddr_guest2host(vtblk_ctx(sc), vd->vd_addr, 1);
285 assert(vd->vd_len == 1);
286 assert((vd->vd_flags & VRING_DESC_F_NEXT) == 0);
287 assert(vd->vd_flags & VRING_DESC_F_WRITE);
289 DPRINTF(("virtio-block: %s op, %d bytes, %d segs, offset %ld\n\r",
290 writeop ? "write" : "read", iolen, i, offset));
293 err = pwritev(sc->vbsc_fd, iov, i, offset);
295 err = preadv(sc->vbsc_fd, iov, i, offset);
297 *status = err < 0 ? VTBLK_S_IOERR : VTBLK_S_OK;
300 * Return the single descriptor back to the host
302 vu = &hq->hq_used_ring[uidx % hq->hq_size];
306 *hq->hq_used_idx += 1;
309 * Generate an interrupt if able
311 if ((*hq->hq_avail_flags & VRING_AVAIL_F_NO_INTERRUPT) == 0) {
313 pci_generate_msix(sc->vbsc_pi, sc->msix_table_idx_req);
314 } else if (sc->vbsc_isr == 0) {
316 pci_generate_msi(sc->vbsc_pi, 0);
322 pci_vtblk_qnotify(struct pci_vtblk_softc *sc)
324 struct vring_hqueue *hq = &sc->vbsc_q;
327 while ((ndescs = hq_num_avail(hq)) != 0) {
329 * Run through all the entries, placing them into iovecs and
330 * sending when an end-of-packet is found
332 pci_vtblk_proc(sc, hq);
337 pci_vtblk_ring_init(struct pci_vtblk_softc *sc, uint64_t pfn)
339 struct vring_hqueue *hq;
341 sc->vbsc_pfn = pfn << VRING_PFN;
344 * Set up host pointers to the various parts of the
348 hq->hq_size = VTBLK_RINGSZ;
350 hq->hq_dtable = paddr_guest2host(vtblk_ctx(sc), pfn << VRING_PFN,
351 vring_size(VTBLK_RINGSZ));
352 hq->hq_avail_flags = (uint16_t *)(hq->hq_dtable + hq->hq_size);
353 hq->hq_avail_idx = hq->hq_avail_flags + 1;
354 hq->hq_avail_ring = hq->hq_avail_flags + 2;
355 hq->hq_used_flags = (uint16_t *)roundup2((uintptr_t)hq->hq_avail_ring,
357 hq->hq_used_idx = hq->hq_used_flags + 1;
358 hq->hq_used_ring = (struct virtio_used *)(hq->hq_used_flags + 2);
361 * Initialize queue indexes
367 pci_vtblk_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
370 struct pci_vtblk_softc *sc;
377 printf("virtio-block: backing device required\n");
382 * The supplied backing file has to exist
384 fd = open(opts, O_RDWR);
386 perror("Could not open backing file");
390 if (fstat(fd, &sbuf) < 0) {
391 perror("Could not stat backing file");
397 * Deal with raw devices
401 if (S_ISCHR(sbuf.st_mode)) {
402 if (ioctl(fd, DIOCGMEDIASIZE, &size) < 0 ||
403 ioctl(fd, DIOCGSECTORSIZE, §sz)) {
404 perror("Could not fetch dev blk/sector size");
412 sc = malloc(sizeof(struct pci_vtblk_softc));
413 memset(sc, 0, sizeof(struct pci_vtblk_softc));
419 /* setup virtio block config space */
420 sc->vbsc_cfg.vbc_capacity = size / sectsz;
421 sc->vbsc_cfg.vbc_seg_max = VTBLK_MAXSEGS;
422 sc->vbsc_cfg.vbc_blk_size = sectsz;
423 sc->vbsc_cfg.vbc_size_max = 0; /* not negotiated */
424 sc->vbsc_cfg.vbc_geom_c = 0; /* no geometry */
425 sc->vbsc_cfg.vbc_geom_h = 0;
426 sc->vbsc_cfg.vbc_geom_s = 0;
427 sc->vbsc_cfg.vbc_sectors_max = 0;
429 /* initialize config space */
430 pci_set_cfgdata16(pi, PCIR_DEVICE, VIRTIO_DEV_BLOCK);
431 pci_set_cfgdata16(pi, PCIR_VENDOR, VIRTIO_VENDOR);
432 pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_STORAGE);
433 pci_set_cfgdata16(pi, PCIR_SUBDEV_0, VIRTIO_TYPE_BLOCK);
435 if ((env_msi = getenv("BHYVE_USE_MSI"))) {
436 if (strcasecmp(env_msi, "yes") == 0)
442 sc->msix_table_idx_req = VIRTIO_MSI_NO_VECTOR;
443 sc->msix_table_idx_cfg = VIRTIO_MSI_NO_VECTOR;
445 if (pci_emul_add_msixcap(pi, 2, 1))
449 pci_emul_add_msicap(pi, 1);
452 pci_emul_alloc_bar(pi, 0, PCIBAR_IO, VTBLK_REGSZ);
458 vtblk_adjust_offset(struct pci_devinst *pi, uint64_t offset)
461 * Device specific offsets used by guest would change
462 * based on whether MSI-X capability is enabled or not
464 if (!pci_msix_enabled(pi)) {
465 if (offset >= VTCFG_R_MSIX)
466 return (offset + (VTCFG_R_CFG1 - VTCFG_R_MSIX));
473 pci_vtblk_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
474 int baridx, uint64_t offset, int size, uint64_t value)
476 struct pci_vtblk_softc *sc = pi->pi_arg;
479 if (baridx == pci_msix_table_bar(pi) ||
480 baridx == pci_msix_pba_bar(pi)) {
481 pci_emul_msix_twrite(pi, offset, size, value);
488 if (offset + size > pci_vtblk_iosize(pi)) {
489 DPRINTF(("vtblk_write: 2big, offset %ld size %d\n",
494 offset = vtblk_adjust_offset(pi, offset);
497 case VTCFG_R_GUESTCAP:
499 sc->vbsc_features = value & VTBLK_S_HOSTCAPS;
503 pci_vtblk_ring_init(sc, value);
507 sc->vbsc_lastq = value;
509 case VTCFG_R_QNOTIFY:
512 pci_vtblk_qnotify(sc);
516 pci_vtblk_update_status(sc, value);
520 sc->msix_table_idx_cfg = value;
524 sc->msix_table_idx_req = value;
526 case VTCFG_R_HOSTCAP:
529 case VTBLK_R_CFG ... VTBLK_R_CFG_END:
530 DPRINTF(("vtblk: write to readonly reg %ld\n\r", offset));
533 DPRINTF(("vtblk: unknown i/o write offset %ld\n\r", offset));
540 pci_vtblk_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
541 int baridx, uint64_t offset, int size)
543 struct pci_vtblk_softc *sc = pi->pi_arg;
548 if (baridx == pci_msix_table_bar(pi) ||
549 baridx == pci_msix_pba_bar(pi)) {
550 return (pci_emul_msix_tread(pi, offset, size));
556 if (offset + size > pci_vtblk_iosize(pi)) {
557 DPRINTF(("vtblk_read: 2big, offset %ld size %d\n",
562 offset = vtblk_adjust_offset(pi, offset);
565 case VTCFG_R_HOSTCAP:
567 value = VTBLK_S_HOSTCAPS;
569 case VTCFG_R_GUESTCAP:
571 value = sc->vbsc_features; /* XXX never read ? */
575 value = sc->vbsc_pfn >> VRING_PFN;
578 value = (sc->vbsc_lastq == 0) ? VTBLK_RINGSZ: 0;
582 value = sc->vbsc_lastq; /* XXX never read ? */
584 case VTCFG_R_QNOTIFY:
586 value = 0; /* XXX never read ? */
590 value = sc->vbsc_status;
594 value = sc->vbsc_isr;
595 sc->vbsc_isr = 0; /* a read clears this flag */
599 value = sc->msix_table_idx_cfg;
603 value = sc->msix_table_idx_req;
605 case VTBLK_R_CFG ... VTBLK_R_CFG_END:
606 assert(size + offset <= (VTBLK_R_CFG_END + 1));
607 ptr = (uint8_t *)&sc->vbsc_cfg + offset - VTBLK_R_CFG;
609 value = *(uint8_t *) ptr;
610 } else if (size == 2) {
611 value = *(uint16_t *) ptr;
613 value = *(uint32_t *) ptr;
617 DPRINTF(("vtblk: unknown i/o read offset %ld\n\r", offset));
625 struct pci_devemu pci_de_vblk = {
626 .pe_emu = "virtio-blk",
627 .pe_init = pci_vtblk_init,
628 .pe_barwrite = pci_vtblk_write,
629 .pe_barread = pci_vtblk_read
631 PCI_EMUL_SET(pci_de_vblk);