Index: usr.sbin/bhyve/pci_nvme.c =================================================================== --- usr.sbin/bhyve/pci_nvme.c +++ usr.sbin/bhyve/pci_nvme.c @@ -35,6 +35,7 @@ * * options: * -s ,nvme,devpath,maxq=#,qsz=#,ioslots=#,sectsz=#,ser=A-Z,eui64=#,dsm= + * ,clone=nvmedev * * accepted devpath: * /dev/blockdev @@ -48,6 +49,7 @@ * ser = serial number (20-chars max) * eui64 = IEEE Extended Unique Identifier (8 byte value) * dsm = DataSet Management support. Option is one of auto, enable,disable + * clone = Clone the host's NVMe identify information * */ @@ -59,12 +61,22 @@ #include __FBSDID("$FreeBSD$"); +#include +#ifndef WITHOUT_CAPSICUM +#include +#endif #include #include +#include #include #include +#ifndef WITHOUT_CAPSICUM +#include +#endif +#include #include +#include #include #include #include @@ -72,6 +84,8 @@ #include #include #include +#include +#include #include #include @@ -276,6 +290,7 @@ uint32_t num_cqueues; uint32_t num_squeues; bool num_q_is_set; /* Has host set Number of Queues */ + bool clone_is_set; struct pci_nvme_ioreq *ioreqs; STAILQ_HEAD(, pci_nvme_ioreq) ioreqs_free; /* free list of ioreqs */ @@ -448,20 +463,22 @@ { struct nvme_controller_data *cd = &sc->ctrldata; - cd->vid = 0xFB5D; - cd->ssvid = 0x0000; + if(!sc->clone_is_set) { + cd->vid = 0xFB5D; + cd->ssvid = 0x0000; - cpywithpad((char *)cd->mn, sizeof(cd->mn), "bhyve-NVMe", ' '); - cpywithpad((char *)cd->fr, sizeof(cd->fr), "1.0", ' '); + cpywithpad((char *)cd->mn, sizeof(cd->mn), "bhyve-NVMe", ' '); + cpywithpad((char *)cd->fr, sizeof(cd->fr), "1.0", ' '); + + /* FreeBSD OUI */ + cd->ieee[0] = 0x58; + cd->ieee[1] = 0x9c; + cd->ieee[2] = 0xfc; + } /* Num of submission commands that we can handle at a time (2^rab) */ cd->rab = 4; - /* FreeBSD OUI */ - cd->ieee[0] = 0x58; - cd->ieee[1] = 0x9c; - cd->ieee[2] = 0xfc; - cd->mic = 0; cd->mdts = NVME_MDTS; /* max data transfer size (2^mdts * CAP.MPSMIN) */ @@ -2610,6 +2627,13 @@ char *uopt, *xopts, *config; uint32_t sectsz; int optidx; + int fd; + struct nvme_pt_command pt; + +#ifndef WITHOUT_CAPSICUM + cap_rights_t rights; + cap_ioctl_t cmds[] = { NVME_PASSTHROUGH_CMD }; +#endif sc->max_queues = NVME_QUEUES; sc->max_qentries = NVME_MAX_QENTRIES; @@ -2668,6 +2692,29 @@ sc->dataset_management = NVME_DATASET_MANAGEMENT_ENABLE; else if (!strcmp("disable", config)) sc->dataset_management = NVME_DATASET_MANAGEMENT_DISABLE; + } else if (!strcmp("clone", xopts)) { + fd = open(config, O_RDONLY); + if (fd < 0) { + perror("Could not open clone device"); + free(uopt); + return (-1); + } +#ifndef WITHOUT_CAPSICUM + cap_rights_init(&rights, CAP_IOCTL); + + if (caph_rights_limit(fd, &rights) == -1) + errx(EX_OSERR, "Unable to apply rights for sandbox"); + if (caph_ioctls_limit(fd, cmds, nitems(cmds)) == -1) + errx(EX_OSERR, "Unable to apply rights for sandbox"); +#endif + memset(&pt, 0, sizeof(pt)); + pt.cmd.opc = NVME_OPC_IDENTIFY; + pt.cmd.cdw10 = htole32(1); + pt.buf = &sc->ctrldata; + pt.len = sizeof(sc->ctrldata); + pt.is_read = 1; + if(ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) >= 0) + sc->clone_is_set = true; } else if (optidx == 0) { snprintf(bident, sizeof(bident), "%d:%d", sc->nsc_pi->pi_slot, sc->nsc_pi->pi_func);