Index: usr.sbin/bhyve/pci_nvme.c =================================================================== --- usr.sbin/bhyve/pci_nvme.c +++ usr.sbin/bhyve/pci_nvme.c @@ -234,6 +234,16 @@ NVME_DATASET_MANAGEMENT_DISABLE, }; +struct nvme_lba_range_type { + uint8_t type; + uint8_t attributes; + uint8_t rsvd2[14]; + uint64_t slba; + uint64_t nlb; + uint8_t guid[16]; + uint8_t rsvd48[16]; +} __packed; + struct pci_nvme_softc; struct nvme_feature_obj; @@ -323,6 +333,8 @@ enum nvme_dsm_type dataset_management; + struct nvme_lba_range_type lba_range; + /* Accounting for SMART data */ __uint128_t read_data_units; __uint128_t write_data_units; @@ -392,6 +404,10 @@ struct nvme_feature_obj *, struct nvme_command *, struct nvme_completion *); +static void nvme_feature_lba_range_type(struct pci_nvme_softc *, + struct nvme_feature_obj *, + struct nvme_command *, + struct nvme_completion *); static void nvme_feature_num_queues(struct pci_nvme_softc *, struct nvme_feature_obj *, struct nvme_command *, @@ -671,6 +687,8 @@ sc->feat[0].get = nvme_feature_invalid_cb; sc->feat[NVME_FEAT_LBA_RANGE_TYPE].namespace_specific = true; + sc->feat[NVME_FEAT_LBA_RANGE_TYPE].set = nvme_feature_lba_range_type; + sc->feat[NVME_FEAT_LBA_RANGE_TYPE].get = nvme_feature_lba_range_type; sc->feat[NVME_FEAT_ERROR_RECOVERY].namespace_specific = true; sc->feat[NVME_FEAT_NUMBER_OF_QUEUES].set = nvme_feature_num_queues; sc->feat[NVME_FEAT_INTERRUPT_VECTOR_CONFIGURATION].set = @@ -1593,6 +1611,20 @@ } +static void +nvme_feature_lba_range_type(struct pci_nvme_softc *sc, + struct nvme_feature_obj *feat, + struct nvme_command *command, + struct nvme_completion *compl) +{ + + nvme_prp_memcpy(sc->nsc_pi->pi_vmctx, command->prp1, command->prp2, + (uint8_t *)&sc->lba_range, sizeof(sc->lba_range), + command->opc == NVME_OPC_SET_FEATURES ? NVME_COPY_FROM_PRP : + NVME_COPY_TO_PRP); +} + + static void nvme_feature_num_queues(struct pci_nvme_softc *sc, struct nvme_feature_obj *feat,