14c87aefeSPatrick Mooney /*- 24c87aefeSPatrick Mooney * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 34c87aefeSPatrick Mooney * 44c87aefeSPatrick Mooney * Copyright (c) 2014 Nahanni Systems Inc. 54c87aefeSPatrick Mooney * All rights reserved. 64c87aefeSPatrick Mooney * 74c87aefeSPatrick Mooney * Redistribution and use in source and binary forms, with or without 84c87aefeSPatrick Mooney * modification, are permitted provided that the following conditions 94c87aefeSPatrick Mooney * are met: 104c87aefeSPatrick Mooney * 1. Redistributions of source code must retain the above copyright 114c87aefeSPatrick Mooney * notice, this list of conditions and the following disclaimer 124c87aefeSPatrick Mooney * in this position and unchanged. 134c87aefeSPatrick Mooney * 2. Redistributions in binary form must reproduce the above copyright 144c87aefeSPatrick Mooney * notice, this list of conditions and the following disclaimer in the 154c87aefeSPatrick Mooney * documentation and/or other materials provided with the distribution. 164c87aefeSPatrick Mooney * 174c87aefeSPatrick Mooney * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 184c87aefeSPatrick Mooney * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 194c87aefeSPatrick Mooney * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 204c87aefeSPatrick Mooney * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 214c87aefeSPatrick Mooney * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 224c87aefeSPatrick Mooney * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 234c87aefeSPatrick Mooney * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 244c87aefeSPatrick Mooney * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 254c87aefeSPatrick Mooney * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 264c87aefeSPatrick Mooney * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 274c87aefeSPatrick Mooney * SUCH DAMAGE. 284c87aefeSPatrick Mooney */ 294c87aefeSPatrick Mooney 304c87aefeSPatrick Mooney /* 314c87aefeSPatrick Mooney * virtio entropy device emulation. 324c87aefeSPatrick Mooney * Randomness is sourced from /dev/random which does not block 334c87aefeSPatrick Mooney * once it has been seeded at bootup. 344c87aefeSPatrick Mooney */ 354c87aefeSPatrick Mooney 364c87aefeSPatrick Mooney #include <sys/cdefs.h> 374c87aefeSPatrick Mooney __FBSDID("$FreeBSD$"); 384c87aefeSPatrick Mooney 394c87aefeSPatrick Mooney #include <sys/param.h> 404c87aefeSPatrick Mooney #ifndef WITHOUT_CAPSICUM 414c87aefeSPatrick Mooney #include <sys/capsicum.h> 424c87aefeSPatrick Mooney #endif 434c87aefeSPatrick Mooney #include <sys/linker_set.h> 444c87aefeSPatrick Mooney #include <sys/uio.h> 454c87aefeSPatrick Mooney 464c87aefeSPatrick Mooney #ifndef WITHOUT_CAPSICUM 474c87aefeSPatrick Mooney #include <capsicum_helpers.h> 484c87aefeSPatrick Mooney #endif 494c87aefeSPatrick Mooney #include <err.h> 504c87aefeSPatrick Mooney #include <errno.h> 514c87aefeSPatrick Mooney #include <fcntl.h> 524c87aefeSPatrick Mooney #include <stdio.h> 534c87aefeSPatrick Mooney #include <stdlib.h> 544c87aefeSPatrick Mooney #include <string.h> 554c87aefeSPatrick Mooney #include <unistd.h> 564c87aefeSPatrick Mooney #include <assert.h> 574c87aefeSPatrick Mooney #include <pthread.h> 584c87aefeSPatrick Mooney #include <sysexits.h> 594c87aefeSPatrick Mooney 604c87aefeSPatrick Mooney #include "bhyverun.h" 61154972afSPatrick Mooney #include "debug.h" 624c87aefeSPatrick Mooney #include "pci_emul.h" 634c87aefeSPatrick Mooney #include "virtio.h" 644c87aefeSPatrick Mooney 654c87aefeSPatrick Mooney #define VTRND_RINGSZ 64 664c87aefeSPatrick Mooney 674c87aefeSPatrick Mooney 684c87aefeSPatrick Mooney static int pci_vtrnd_debug; 69154972afSPatrick Mooney #define DPRINTF(params) if (pci_vtrnd_debug) PRINTLN params 70154972afSPatrick Mooney #define WPRINTF(params) PRINTLN params 714c87aefeSPatrick Mooney 724c87aefeSPatrick Mooney /* 734c87aefeSPatrick Mooney * Per-device softc 744c87aefeSPatrick Mooney */ 754c87aefeSPatrick Mooney struct pci_vtrnd_softc { 764c87aefeSPatrick Mooney struct virtio_softc vrsc_vs; 774c87aefeSPatrick Mooney struct vqueue_info vrsc_vq; 784c87aefeSPatrick Mooney pthread_mutex_t vrsc_mtx; 794c87aefeSPatrick Mooney uint64_t vrsc_cfg; 804c87aefeSPatrick Mooney int vrsc_fd; 814c87aefeSPatrick Mooney }; 824c87aefeSPatrick Mooney 834c87aefeSPatrick Mooney static void pci_vtrnd_reset(void *); 844c87aefeSPatrick Mooney static void pci_vtrnd_notify(void *, struct vqueue_info *); 854c87aefeSPatrick Mooney 864c87aefeSPatrick Mooney static struct virtio_consts vtrnd_vi_consts = { 874c87aefeSPatrick Mooney "vtrnd", /* our name */ 884c87aefeSPatrick Mooney 1, /* we support 1 virtqueue */ 894c87aefeSPatrick Mooney 0, /* config reg size */ 904c87aefeSPatrick Mooney pci_vtrnd_reset, /* reset */ 914c87aefeSPatrick Mooney pci_vtrnd_notify, /* device-wide qnotify */ 924c87aefeSPatrick Mooney NULL, /* read virtio config */ 934c87aefeSPatrick Mooney NULL, /* write virtio config */ 944c87aefeSPatrick Mooney NULL, /* apply negotiated features */ 954c87aefeSPatrick Mooney 0, /* our capabilities */ 964c87aefeSPatrick Mooney }; 974c87aefeSPatrick Mooney 984c87aefeSPatrick Mooney 994c87aefeSPatrick Mooney static void 1004c87aefeSPatrick Mooney pci_vtrnd_reset(void *vsc) 1014c87aefeSPatrick Mooney { 1024c87aefeSPatrick Mooney struct pci_vtrnd_softc *sc; 1034c87aefeSPatrick Mooney 1044c87aefeSPatrick Mooney sc = vsc; 1054c87aefeSPatrick Mooney 106154972afSPatrick Mooney DPRINTF(("vtrnd: device reset requested !")); 1074c87aefeSPatrick Mooney vi_reset_dev(&sc->vrsc_vs); 1084c87aefeSPatrick Mooney } 1094c87aefeSPatrick Mooney 1104c87aefeSPatrick Mooney 1114c87aefeSPatrick Mooney static void 1124c87aefeSPatrick Mooney pci_vtrnd_notify(void *vsc, struct vqueue_info *vq) 1134c87aefeSPatrick Mooney { 1144c87aefeSPatrick Mooney struct iovec iov; 1154c87aefeSPatrick Mooney struct pci_vtrnd_softc *sc; 116b0de25cbSAndy Fiddaman struct vi_req req; 117b0de25cbSAndy Fiddaman int len, n; 1184c87aefeSPatrick Mooney 1194c87aefeSPatrick Mooney sc = vsc; 1204c87aefeSPatrick Mooney 1214c87aefeSPatrick Mooney if (sc->vrsc_fd < 0) { 1224c87aefeSPatrick Mooney vq_endchains(vq, 0); 1234c87aefeSPatrick Mooney return; 1244c87aefeSPatrick Mooney } 1254c87aefeSPatrick Mooney 1264c87aefeSPatrick Mooney while (vq_has_descs(vq)) { 127b0de25cbSAndy Fiddaman n = vq_getchain(vq, &iov, 1, &req); 128b0de25cbSAndy Fiddaman assert(n == 1); 1294c87aefeSPatrick Mooney 1304c87aefeSPatrick Mooney len = read(sc->vrsc_fd, iov.iov_base, iov.iov_len); 1314c87aefeSPatrick Mooney 132154972afSPatrick Mooney DPRINTF(("vtrnd: vtrnd_notify(): %d", len)); 1334c87aefeSPatrick Mooney 1344c87aefeSPatrick Mooney /* Catastrophe if unable to read from /dev/random */ 1354c87aefeSPatrick Mooney assert(len > 0); 1364c87aefeSPatrick Mooney 1374c87aefeSPatrick Mooney /* 1384c87aefeSPatrick Mooney * Release this chain and handle more 1394c87aefeSPatrick Mooney */ 140b0de25cbSAndy Fiddaman vq_relchain(vq, req.idx, len); 1414c87aefeSPatrick Mooney } 1424c87aefeSPatrick Mooney vq_endchains(vq, 1); /* Generate interrupt if appropriate. */ 1434c87aefeSPatrick Mooney } 1444c87aefeSPatrick Mooney 1454c87aefeSPatrick Mooney 1464c87aefeSPatrick Mooney static int 1472b948146SAndy Fiddaman pci_vtrnd_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl) 1484c87aefeSPatrick Mooney { 1494c87aefeSPatrick Mooney struct pci_vtrnd_softc *sc; 1504c87aefeSPatrick Mooney int fd; 1514c87aefeSPatrick Mooney int len; 1524c87aefeSPatrick Mooney uint8_t v; 1534c87aefeSPatrick Mooney #ifndef WITHOUT_CAPSICUM 1544c87aefeSPatrick Mooney cap_rights_t rights; 1554c87aefeSPatrick Mooney #endif 1564c87aefeSPatrick Mooney 1574c87aefeSPatrick Mooney /* 1584c87aefeSPatrick Mooney * Should always be able to open /dev/random. 1594c87aefeSPatrick Mooney */ 1604c87aefeSPatrick Mooney fd = open("/dev/random", O_RDONLY | O_NONBLOCK); 1614c87aefeSPatrick Mooney 1624c87aefeSPatrick Mooney assert(fd >= 0); 1634c87aefeSPatrick Mooney 1644c87aefeSPatrick Mooney #ifndef WITHOUT_CAPSICUM 1654c87aefeSPatrick Mooney cap_rights_init(&rights, CAP_READ); 1664c87aefeSPatrick Mooney if (caph_rights_limit(fd, &rights) == -1) 1674c87aefeSPatrick Mooney errx(EX_OSERR, "Unable to apply rights for sandbox"); 1684c87aefeSPatrick Mooney #endif 1694c87aefeSPatrick Mooney 1704c87aefeSPatrick Mooney /* 1714c87aefeSPatrick Mooney * Check that device is seeded and non-blocking. 1724c87aefeSPatrick Mooney */ 1734c87aefeSPatrick Mooney len = read(fd, &v, sizeof(v)); 1744c87aefeSPatrick Mooney if (len <= 0) { 1754c87aefeSPatrick Mooney WPRINTF(("vtrnd: /dev/random not ready, read(): %d", len)); 1764c87aefeSPatrick Mooney close(fd); 1774c87aefeSPatrick Mooney return (1); 1784c87aefeSPatrick Mooney } 1794c87aefeSPatrick Mooney 1804c87aefeSPatrick Mooney sc = calloc(1, sizeof(struct pci_vtrnd_softc)); 1814c87aefeSPatrick Mooney 1827bb0eb34SAndy Fiddaman pthread_mutex_init(&sc->vrsc_mtx, NULL); 1837bb0eb34SAndy Fiddaman 1844c87aefeSPatrick Mooney vi_softc_linkup(&sc->vrsc_vs, &vtrnd_vi_consts, sc, pi, &sc->vrsc_vq); 1854c87aefeSPatrick Mooney sc->vrsc_vs.vs_mtx = &sc->vrsc_mtx; 1864c87aefeSPatrick Mooney 1874c87aefeSPatrick Mooney sc->vrsc_vq.vq_qsize = VTRND_RINGSZ; 1884c87aefeSPatrick Mooney 1894c87aefeSPatrick Mooney /* keep /dev/random opened while emulating */ 1904c87aefeSPatrick Mooney sc->vrsc_fd = fd; 1914c87aefeSPatrick Mooney 1924c87aefeSPatrick Mooney /* initialize config space */ 1934c87aefeSPatrick Mooney pci_set_cfgdata16(pi, PCIR_DEVICE, VIRTIO_DEV_RANDOM); 1944c87aefeSPatrick Mooney pci_set_cfgdata16(pi, PCIR_VENDOR, VIRTIO_VENDOR); 1954c87aefeSPatrick Mooney pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_CRYPTO); 1962b948146SAndy Fiddaman pci_set_cfgdata16(pi, PCIR_SUBDEV_0, VIRTIO_ID_ENTROPY); 1974c87aefeSPatrick Mooney pci_set_cfgdata16(pi, PCIR_SUBVEND_0, VIRTIO_VENDOR); 1984c87aefeSPatrick Mooney 1994c87aefeSPatrick Mooney if (vi_intr_init(&sc->vrsc_vs, 1, fbsdrun_virtio_msix())) 2004c87aefeSPatrick Mooney return (1); 2014c87aefeSPatrick Mooney vi_set_io_bar(&sc->vrsc_vs, 0); 2024c87aefeSPatrick Mooney 2034c87aefeSPatrick Mooney return (0); 2044c87aefeSPatrick Mooney } 2054c87aefeSPatrick Mooney 2064c87aefeSPatrick Mooney 207*4f3f3e9aSAndy Fiddaman static const struct pci_devemu pci_de_vrnd = { 2084c87aefeSPatrick Mooney .pe_emu = "virtio-rnd", 2094c87aefeSPatrick Mooney .pe_init = pci_vtrnd_init, 2104c87aefeSPatrick Mooney .pe_barwrite = vi_pci_write, 2112b948146SAndy Fiddaman .pe_barread = vi_pci_read, 2124c87aefeSPatrick Mooney }; 2134c87aefeSPatrick Mooney PCI_EMUL_SET(pci_de_vrnd); 214