diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e18a99c1..df9d6a22a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,9 @@ Added the `nvmf_set_crdt` RPC for setting command retry delay times. ### nvme +`spdk_nvme_map_prps` and `spdk_nvme_map_cmd` were moved to nvmf/vfio-user as internal APIs +as vfio-user is the only user for the above two APIs. + Added a new function `spdk_nvme_ns_cmd_copy` to submit a Simple Copy Command to a Namespace. Update the spdk_nvme_generic_command_status_code structure with new status code diff --git a/include/spdk/nvme.h b/include/spdk/nvme.h index db9797d1b..b37d42329 100644 --- a/include/spdk/nvme.h +++ b/include/spdk/nvme.h @@ -3587,25 +3587,6 @@ int spdk_nvme_cuse_register(struct spdk_nvme_ctrlr *ctrlr); */ int spdk_nvme_cuse_unregister(struct spdk_nvme_ctrlr *ctrlr); -int spdk_nvme_map_prps(void *prv, struct spdk_nvme_cmd *cmd, struct iovec *iovs, - uint32_t len, size_t mps, - void *(*gpa_to_vva)(void *prv, uint64_t addr, uint64_t len)); - -/** - * Map NVMe command data buffers sent from Virtual Machine to virtual addresses - * - *\param prv Opaque handle to gpa_to_vva callback - *\param cmd NVMe command - *\param iovs IO vectors used to point the data buffers in NVMe command - *\param max_iovcnt Maximum IO vectors that can be used - *\param len Total buffer length for the NVMe command - *\param mps Memory page size - *\param gpa_to_vva Callback to map memory from Guest Physical address to Virtual address - */ -int spdk_nvme_map_cmd(void *prv, struct spdk_nvme_cmd *cmd, struct iovec *iovs, uint32_t max_iovcnt, - uint32_t len, size_t mps, - void *(*gpa_to_vva)(void *prv, uint64_t addr, uint64_t len)); - /** * Opaque handle for a transport poll group. Used by the transport function table. */ diff --git a/lib/nvme/Makefile b/lib/nvme/Makefile index f722ea56d..791ea486f 100644 --- a/lib/nvme/Makefile +++ b/lib/nvme/Makefile @@ -34,8 +34,8 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..) include $(SPDK_ROOT_DIR)/mk/spdk.common.mk -SO_VER := 5 -SO_MINOR := 1 +SO_VER := 6 +SO_MINOR := 0 C_SRCS = nvme_ctrlr_cmd.c nvme_ctrlr.c nvme_fabric.c nvme_ns_cmd.c nvme_ns.c nvme_pcie_common.c nvme_pcie.c nvme_qpair.c nvme.c nvme_quirks.c nvme_transport.c \ nvme_ctrlr_ocssd_cmd.c nvme_ns_ocssd_cmd.c nvme_tcp.c nvme_opal.c nvme_io_msg.c nvme_poll_group.c nvme_zns.c diff --git a/lib/nvme/nvme_ctrlr.c b/lib/nvme/nvme_ctrlr.c index aab339507..8221aa603 100644 --- a/lib/nvme/nvme_ctrlr.c +++ b/lib/nvme/nvme_ctrlr.c @@ -4414,231 +4414,3 @@ spdk_nvme_ctrlr_free_qid(struct spdk_nvme_ctrlr *ctrlr, uint16_t qid) spdk_bit_array_set(ctrlr->free_io_qids, qid); nvme_robust_mutex_unlock(&ctrlr->ctrlr_lock); } - -static int -nvme_cmd_map_prps(void *prv, struct spdk_nvme_cmd *cmd, struct iovec *iovs, - uint32_t max_iovcnt, uint32_t len, size_t mps, - void *(*gpa_to_vva)(void *prv, uint64_t addr, uint64_t len)) -{ - uint64_t prp1, prp2; - void *vva; - uint32_t i; - uint32_t residue_len, nents; - uint64_t *prp_list; - uint32_t iovcnt; - - assert(max_iovcnt > 0); - - prp1 = cmd->dptr.prp.prp1; - prp2 = cmd->dptr.prp.prp2; - - /* PRP1 may started with unaligned page address */ - residue_len = mps - (prp1 % mps); - residue_len = spdk_min(len, residue_len); - - vva = gpa_to_vva(prv, prp1, residue_len); - if (spdk_unlikely(vva == NULL)) { - SPDK_ERRLOG("GPA to VVA failed\n"); - return -EINVAL; - } - len -= residue_len; - if (len && max_iovcnt < 2) { - SPDK_ERRLOG("Too many page entries, at least two iovs are required\n"); - return -ERANGE; - } - iovs[0].iov_base = vva; - iovs[0].iov_len = residue_len; - - if (len) { - if (spdk_unlikely(prp2 == 0)) { - SPDK_ERRLOG("no PRP2, %d remaining\n", len); - return -EINVAL; - } - - if (len <= mps) { - /* 2 PRP used */ - iovcnt = 2; - vva = gpa_to_vva(prv, prp2, len); - if (spdk_unlikely(vva == NULL)) { - SPDK_ERRLOG("no VVA for %#" PRIx64 ", len%#x\n", - prp2, len); - return -EINVAL; - } - iovs[1].iov_base = vva; - iovs[1].iov_len = len; - } else { - /* PRP list used */ - nents = (len + mps - 1) / mps; - if (spdk_unlikely(nents + 1 > max_iovcnt)) { - SPDK_ERRLOG("Too many page entries\n"); - return -ERANGE; - } - - vva = gpa_to_vva(prv, prp2, nents * sizeof(*prp_list)); - if (spdk_unlikely(vva == NULL)) { - SPDK_ERRLOG("no VVA for %#" PRIx64 ", nents=%#x\n", - prp2, nents); - return -EINVAL; - } - prp_list = vva; - i = 0; - while (len != 0) { - residue_len = spdk_min(len, mps); - vva = gpa_to_vva(prv, prp_list[i], residue_len); - if (spdk_unlikely(vva == NULL)) { - SPDK_ERRLOG("no VVA for %#" PRIx64 ", residue_len=%#x\n", - prp_list[i], residue_len); - return -EINVAL; - } - iovs[i + 1].iov_base = vva; - iovs[i + 1].iov_len = residue_len; - len -= residue_len; - i++; - } - iovcnt = i + 1; - } - } else { - /* 1 PRP used */ - iovcnt = 1; - } - - assert(iovcnt <= max_iovcnt); - return iovcnt; -} - -static int -nvme_cmd_map_sgls_data(void *prv, struct spdk_nvme_sgl_descriptor *sgls, uint32_t num_sgls, - struct iovec *iovs, uint32_t max_iovcnt, - void *(*gpa_to_vva)(void *prv, uint64_t addr, uint64_t len)) -{ - uint32_t i; - void *vva; - - if (spdk_unlikely(max_iovcnt < num_sgls)) { - return -ERANGE; - } - - for (i = 0; i < num_sgls; i++) { - if (spdk_unlikely(sgls[i].unkeyed.type != SPDK_NVME_SGL_TYPE_DATA_BLOCK)) { - SPDK_ERRLOG("Invalid SGL type %u\n", sgls[i].unkeyed.type); - return -EINVAL; - } - vva = gpa_to_vva(prv, sgls[i].address, sgls[i].unkeyed.length); - if (spdk_unlikely(vva == NULL)) { - SPDK_ERRLOG("GPA to VVA failed\n"); - return -EINVAL; - } - iovs[i].iov_base = vva; - iovs[i].iov_len = sgls[i].unkeyed.length; - } - - return num_sgls; -} - -static int -nvme_cmd_map_sgls(void *prv, struct spdk_nvme_cmd *cmd, struct iovec *iovs, uint32_t max_iovcnt, - uint32_t len, size_t mps, - void *(*gpa_to_vva)(void *prv, uint64_t addr, uint64_t len)) -{ - struct spdk_nvme_sgl_descriptor *sgl, *last_sgl; - uint32_t num_sgls, seg_len; - void *vva; - int ret; - uint32_t total_iovcnt = 0; - - /* SGL cases */ - sgl = &cmd->dptr.sgl1; - - /* only one SGL segment */ - if (sgl->unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK) { - assert(max_iovcnt > 0); - vva = gpa_to_vva(prv, sgl->address, sgl->unkeyed.length); - if (spdk_unlikely(vva == NULL)) { - SPDK_ERRLOG("GPA to VVA failed\n"); - return -EINVAL; - } - iovs[0].iov_base = vva; - iovs[0].iov_len = sgl->unkeyed.length; - assert(sgl->unkeyed.length == len); - - return 1; - } - - for (;;) { - if (spdk_unlikely((sgl->unkeyed.type != SPDK_NVME_SGL_TYPE_SEGMENT) && - (sgl->unkeyed.type != SPDK_NVME_SGL_TYPE_LAST_SEGMENT))) { - SPDK_ERRLOG("Invalid SGL type %u\n", sgl->unkeyed.type); - return -EINVAL; - } - - seg_len = sgl->unkeyed.length; - if (spdk_unlikely(seg_len % sizeof(struct spdk_nvme_sgl_descriptor))) { - SPDK_ERRLOG("Invalid SGL segment len %u\n", seg_len); - return -EINVAL; - } - - num_sgls = seg_len / sizeof(struct spdk_nvme_sgl_descriptor); - vva = gpa_to_vva(prv, sgl->address, sgl->unkeyed.length); - if (spdk_unlikely(vva == NULL)) { - SPDK_ERRLOG("GPA to VVA failed\n"); - return -EINVAL; - } - - /* sgl point to the first segment */ - sgl = (struct spdk_nvme_sgl_descriptor *)vva; - last_sgl = &sgl[num_sgls - 1]; - - /* we are done */ - if (last_sgl->unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK) { - /* map whole sgl list */ - ret = nvme_cmd_map_sgls_data(prv, sgl, num_sgls, &iovs[total_iovcnt], - max_iovcnt - total_iovcnt, gpa_to_vva); - if (spdk_unlikely(ret < 0)) { - return ret; - } - total_iovcnt += ret; - - return total_iovcnt; - } - - if (num_sgls > 1) { - /* map whole sgl exclude last_sgl */ - ret = nvme_cmd_map_sgls_data(prv, sgl, num_sgls - 1, &iovs[total_iovcnt], - max_iovcnt - total_iovcnt, gpa_to_vva); - if (spdk_unlikely(ret < 0)) { - return ret; - } - total_iovcnt += ret; - } - - /* move to next level's segments */ - sgl = last_sgl; - } - - return 0; -} - -/* FIXME need to specify max number of iovs */ -int -spdk_nvme_map_prps(void *prv, struct spdk_nvme_cmd *cmd, struct iovec *iovs, - uint32_t len, size_t mps, - void *(*gpa_to_vva)(void *prv, uint64_t addr, uint64_t len)) -{ - if (cmd->psdt == SPDK_NVME_PSDT_PRP) { - return nvme_cmd_map_prps(prv, cmd, iovs, UINT32_MAX, len, mps, gpa_to_vva); - } - - return -EINVAL; -} - -int -spdk_nvme_map_cmd(void *prv, struct spdk_nvme_cmd *cmd, struct iovec *iovs, uint32_t max_iovcnt, - uint32_t len, size_t mps, - void *(*gpa_to_vva)(void *prv, uint64_t addr, uint64_t len)) -{ - if (cmd->psdt == SPDK_NVME_PSDT_PRP) { - return nvme_cmd_map_prps(prv, cmd, iovs, max_iovcnt, len, mps, gpa_to_vva); - } - - return nvme_cmd_map_sgls(prv, cmd, iovs, max_iovcnt, len, mps, gpa_to_vva); -} diff --git a/lib/nvme/spdk_nvme.map b/lib/nvme/spdk_nvme.map index 0b5bc5cb0..475f93b90 100644 --- a/lib/nvme/spdk_nvme.map +++ b/lib/nvme/spdk_nvme.map @@ -175,9 +175,6 @@ spdk_nvme_cuse_unregister; spdk_nvme_cuse_update_namespaces; - spdk_nvme_map_prps; - spdk_nvme_map_cmd; - spdk_nvme_poll_group_get_stats; spdk_nvme_poll_group_free_stats; diff --git a/lib/nvmf/vfio_user.c b/lib/nvmf/vfio_user.c index 9f9e7e0cf..3504cbc0f 100644 --- a/lib/nvmf/vfio_user.c +++ b/lib/nvmf/vfio_user.c @@ -221,6 +221,221 @@ post_completion(struct nvmf_vfio_user_ctrlr *ctrlr, struct spdk_nvme_cmd *cmd, struct nvme_q *cq, uint32_t cdw0, uint16_t sc, uint16_t sct); +static int +nvme_cmd_map_prps(void *prv, struct spdk_nvme_cmd *cmd, struct iovec *iovs, + uint32_t max_iovcnt, uint32_t len, size_t mps, + void *(*gpa_to_vva)(void *prv, uint64_t addr, uint64_t len)) +{ + uint64_t prp1, prp2; + void *vva; + uint32_t i; + uint32_t residue_len, nents; + uint64_t *prp_list; + uint32_t iovcnt; + + assert(max_iovcnt > 0); + + prp1 = cmd->dptr.prp.prp1; + prp2 = cmd->dptr.prp.prp2; + + /* PRP1 may started with unaligned page address */ + residue_len = mps - (prp1 % mps); + residue_len = spdk_min(len, residue_len); + + vva = gpa_to_vva(prv, prp1, residue_len); + if (spdk_unlikely(vva == NULL)) { + SPDK_ERRLOG("GPA to VVA failed\n"); + return -EINVAL; + } + len -= residue_len; + if (len && max_iovcnt < 2) { + SPDK_ERRLOG("Too many page entries, at least two iovs are required\n"); + return -ERANGE; + } + iovs[0].iov_base = vva; + iovs[0].iov_len = residue_len; + + if (len) { + if (spdk_unlikely(prp2 == 0)) { + SPDK_ERRLOG("no PRP2, %d remaining\n", len); + return -EINVAL; + } + + if (len <= mps) { + /* 2 PRP used */ + iovcnt = 2; + vva = gpa_to_vva(prv, prp2, len); + if (spdk_unlikely(vva == NULL)) { + SPDK_ERRLOG("no VVA for %#" PRIx64 ", len%#x\n", + prp2, len); + return -EINVAL; + } + iovs[1].iov_base = vva; + iovs[1].iov_len = len; + } else { + /* PRP list used */ + nents = (len + mps - 1) / mps; + if (spdk_unlikely(nents + 1 > max_iovcnt)) { + SPDK_ERRLOG("Too many page entries\n"); + return -ERANGE; + } + + vva = gpa_to_vva(prv, prp2, nents * sizeof(*prp_list)); + if (spdk_unlikely(vva == NULL)) { + SPDK_ERRLOG("no VVA for %#" PRIx64 ", nents=%#x\n", + prp2, nents); + return -EINVAL; + } + prp_list = vva; + i = 0; + while (len != 0) { + residue_len = spdk_min(len, mps); + vva = gpa_to_vva(prv, prp_list[i], residue_len); + if (spdk_unlikely(vva == NULL)) { + SPDK_ERRLOG("no VVA for %#" PRIx64 ", residue_len=%#x\n", + prp_list[i], residue_len); + return -EINVAL; + } + iovs[i + 1].iov_base = vva; + iovs[i + 1].iov_len = residue_len; + len -= residue_len; + i++; + } + iovcnt = i + 1; + } + } else { + /* 1 PRP used */ + iovcnt = 1; + } + + assert(iovcnt <= max_iovcnt); + return iovcnt; +} + +static int +nvme_cmd_map_sgls_data(void *prv, struct spdk_nvme_sgl_descriptor *sgls, uint32_t num_sgls, + struct iovec *iovs, uint32_t max_iovcnt, + void *(*gpa_to_vva)(void *prv, uint64_t addr, uint64_t len)) +{ + uint32_t i; + void *vva; + + if (spdk_unlikely(max_iovcnt < num_sgls)) { + return -ERANGE; + } + + for (i = 0; i < num_sgls; i++) { + if (spdk_unlikely(sgls[i].unkeyed.type != SPDK_NVME_SGL_TYPE_DATA_BLOCK)) { + SPDK_ERRLOG("Invalid SGL type %u\n", sgls[i].unkeyed.type); + return -EINVAL; + } + vva = gpa_to_vva(prv, sgls[i].address, sgls[i].unkeyed.length); + if (spdk_unlikely(vva == NULL)) { + SPDK_ERRLOG("GPA to VVA failed\n"); + return -EINVAL; + } + iovs[i].iov_base = vva; + iovs[i].iov_len = sgls[i].unkeyed.length; + } + + return num_sgls; +} + +static int +nvme_cmd_map_sgls(void *prv, struct spdk_nvme_cmd *cmd, struct iovec *iovs, uint32_t max_iovcnt, + uint32_t len, size_t mps, + void *(*gpa_to_vva)(void *prv, uint64_t addr, uint64_t len)) +{ + struct spdk_nvme_sgl_descriptor *sgl, *last_sgl; + uint32_t num_sgls, seg_len; + void *vva; + int ret; + uint32_t total_iovcnt = 0; + + /* SGL cases */ + sgl = &cmd->dptr.sgl1; + + /* only one SGL segment */ + if (sgl->unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK) { + assert(max_iovcnt > 0); + vva = gpa_to_vva(prv, sgl->address, sgl->unkeyed.length); + if (spdk_unlikely(vva == NULL)) { + SPDK_ERRLOG("GPA to VVA failed\n"); + return -EINVAL; + } + iovs[0].iov_base = vva; + iovs[0].iov_len = sgl->unkeyed.length; + assert(sgl->unkeyed.length == len); + + return 1; + } + + for (;;) { + if (spdk_unlikely((sgl->unkeyed.type != SPDK_NVME_SGL_TYPE_SEGMENT) && + (sgl->unkeyed.type != SPDK_NVME_SGL_TYPE_LAST_SEGMENT))) { + SPDK_ERRLOG("Invalid SGL type %u\n", sgl->unkeyed.type); + return -EINVAL; + } + + seg_len = sgl->unkeyed.length; + if (spdk_unlikely(seg_len % sizeof(struct spdk_nvme_sgl_descriptor))) { + SPDK_ERRLOG("Invalid SGL segment len %u\n", seg_len); + return -EINVAL; + } + + num_sgls = seg_len / sizeof(struct spdk_nvme_sgl_descriptor); + vva = gpa_to_vva(prv, sgl->address, sgl->unkeyed.length); + if (spdk_unlikely(vva == NULL)) { + SPDK_ERRLOG("GPA to VVA failed\n"); + return -EINVAL; + } + + /* sgl point to the first segment */ + sgl = (struct spdk_nvme_sgl_descriptor *)vva; + last_sgl = &sgl[num_sgls - 1]; + + /* we are done */ + if (last_sgl->unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK) { + /* map whole sgl list */ + ret = nvme_cmd_map_sgls_data(prv, sgl, num_sgls, &iovs[total_iovcnt], + max_iovcnt - total_iovcnt, gpa_to_vva); + if (spdk_unlikely(ret < 0)) { + return ret; + } + total_iovcnt += ret; + + return total_iovcnt; + } + + if (num_sgls > 1) { + /* map whole sgl exclude last_sgl */ + ret = nvme_cmd_map_sgls_data(prv, sgl, num_sgls - 1, &iovs[total_iovcnt], + max_iovcnt - total_iovcnt, gpa_to_vva); + if (spdk_unlikely(ret < 0)) { + return ret; + } + total_iovcnt += ret; + } + + /* move to next level's segments */ + sgl = last_sgl; + } + + return 0; +} + +static int +nvme_map_cmd(void *prv, struct spdk_nvme_cmd *cmd, struct iovec *iovs, uint32_t max_iovcnt, + uint32_t len, size_t mps, + void *(*gpa_to_vva)(void *prv, uint64_t addr, uint64_t len)) +{ + if (cmd->psdt == SPDK_NVME_PSDT_PRP) { + return nvme_cmd_map_prps(prv, cmd, iovs, max_iovcnt, len, mps, gpa_to_vva); + } + + return nvme_cmd_map_sgls(prv, cmd, iovs, max_iovcnt, len, mps, gpa_to_vva); +} + static char * endpoint_id(struct nvmf_vfio_user_endpoint *endpoint) { @@ -562,8 +777,8 @@ vfio_user_map_cmd(struct nvmf_vfio_user_ctrlr *ctrlr, struct spdk_nvmf_request * /* Map PRP list to from Guest physical memory to * virtual memory address. */ - return spdk_nvme_map_cmd(req, &req->cmd->nvme_cmd, iov, NVMF_REQ_MAX_BUFFERS, - length, 4096, _map_one); + return nvme_map_cmd(req, &req->cmd->nvme_cmd, iov, NVMF_REQ_MAX_BUFFERS, + length, 4096, _map_one); } static struct spdk_nvmf_request * diff --git a/test/unit/lib/nvme/nvme_ctrlr.c/nvme_ctrlr_ut.c b/test/unit/lib/nvme/nvme_ctrlr.c/nvme_ctrlr_ut.c index 8de8b739b..4c3d5b3ec 100644 --- a/test/unit/lib/nvme/nvme_ctrlr.c/nvme_ctrlr_ut.c +++ b/test/unit/lib/nvme/nvme_ctrlr.c/nvme_ctrlr_ut.c @@ -2392,175 +2392,6 @@ test_nvme_ctrlr_add_remove_process(void) CU_ASSERT(TAILQ_EMPTY(&ctrlr.active_procs)); } -static void * -gpa_to_vva(void *prv, uint64_t addr, uint64_t len) -{ - return (void *)(uintptr_t)addr; -} - -static void -test_nvme_cmd_map_prps(void) -{ - struct spdk_nvme_cmd cmd = {}; - struct iovec iovs[33]; - uint64_t phy_addr, *prp; - uint32_t len; - void *buf, *prps; - int i, ret; - size_t mps = 4096; - - buf = spdk_zmalloc(132 * 1024, 4096, &phy_addr, 0, 0); - CU_ASSERT(buf != NULL); - prps = spdk_zmalloc(4096, 4096, &phy_addr, 0, 0); - CU_ASSERT(prps != NULL); - - /* test case 1: 4KiB with PRP1 only */ - cmd.dptr.prp.prp1 = (uint64_t)(uintptr_t)buf; - len = 4096; - ret = nvme_cmd_map_prps(NULL, &cmd, iovs, 33, len, mps, gpa_to_vva); - CU_ASSERT(ret == 1); - CU_ASSERT(iovs[0].iov_base == (void *)(uintptr_t)cmd.dptr.prp.prp1); - CU_ASSERT(iovs[0].iov_len == len); - - /* test case 2: 4KiB with PRP1 and PRP2, 1KiB in first iov, and 3KiB in second iov */ - cmd.dptr.prp.prp1 = (uint64_t)(uintptr_t)buf + 1024 * 3; - cmd.dptr.prp.prp2 = (uint64_t)(uintptr_t)buf + 4096; - len = 4096; - ret = nvme_cmd_map_prps(NULL, &cmd, iovs, 1, len, mps, gpa_to_vva); - CU_ASSERT(ret == -ERANGE); - ret = nvme_cmd_map_prps(NULL, &cmd, iovs, 33, len, mps, gpa_to_vva); - CU_ASSERT(ret == 2); - CU_ASSERT(iovs[0].iov_base == (void *)(uintptr_t)cmd.dptr.prp.prp1); - CU_ASSERT(iovs[0].iov_len == 1024); - CU_ASSERT(iovs[1].iov_base == (void *)(uintptr_t)cmd.dptr.prp.prp2); - CU_ASSERT(iovs[1].iov_len == 1024 * 3); - - /* test case 3: 128KiB with PRP list, 1KiB in first iov, 3KiB in last iov */ - cmd.dptr.prp.prp1 = (uint64_t)(uintptr_t)buf + 1024 * 3; - cmd.dptr.prp.prp2 = (uint64_t)(uintptr_t)prps; - len = 128 * 1024; - prp = prps; - for (i = 1; i < 33; i++) { - *prp = (uint64_t)(uintptr_t)buf + i * 4096; - prp++; - } - ret = nvme_cmd_map_prps(NULL, &cmd, iovs, 33, len, mps, gpa_to_vva); - CU_ASSERT(ret == 33); - CU_ASSERT(iovs[0].iov_base == (void *)(uintptr_t)cmd.dptr.prp.prp1); - CU_ASSERT(iovs[0].iov_len == 1024); - for (i = 1; i < 32; i++) { - CU_ASSERT(iovs[i].iov_base == (void *)((uintptr_t)buf + i * 4096)); - CU_ASSERT(iovs[i].iov_len == 4096); - } - CU_ASSERT(iovs[32].iov_base == (void *)((uintptr_t)buf + 32 * 4096)); - CU_ASSERT(iovs[32].iov_len == 1024 * 3); - - /* test case 4: 256KiB with PRP list, not enough iovs */ - cmd.dptr.prp.prp1 = (uint64_t)(uintptr_t)buf + 1024 * 3; - cmd.dptr.prp.prp2 = (uint64_t)(uintptr_t)prps; - len = 256 * 1024; - ret = nvme_cmd_map_prps(NULL, &cmd, iovs, 33, len, mps, gpa_to_vva); - CU_ASSERT(ret == -ERANGE); - - spdk_free(buf); - spdk_free(prps); -} - -static void -test_nvme_cmd_map_sgls(void) -{ - struct spdk_nvme_cmd cmd = {}; - struct iovec iovs[33]; - uint64_t phy_addr; - uint32_t len; - void *buf, *sgls; - struct spdk_nvme_sgl_descriptor *sgl; - int i, ret; - size_t mps = 4096; - - buf = spdk_zmalloc(132 * 1024, 4096, &phy_addr, 0, 0); - CU_ASSERT(buf != NULL); - sgls = spdk_zmalloc(4096, 4096, &phy_addr, 0, 0); - CU_ASSERT(sgls != NULL); - - /* test case 1: 8KiB with 1 data block */ - len = 8192; - cmd.dptr.sgl1.unkeyed.type = SPDK_NVME_SGL_TYPE_DATA_BLOCK; - cmd.dptr.sgl1.unkeyed.length = len; - cmd.dptr.sgl1.address = (uint64_t)(uintptr_t)buf; - - ret = nvme_cmd_map_sgls(NULL, &cmd, iovs, 33, len, mps, gpa_to_vva); - CU_ASSERT(ret == 1); - CU_ASSERT(iovs[0].iov_base == buf); - CU_ASSERT(iovs[0].iov_len == 8192); - - /* test case 2: 8KiB with 2 data blocks and 1 last segment */ - sgl = (struct spdk_nvme_sgl_descriptor *)sgls; - sgl[0].unkeyed.type = SPDK_NVME_SGL_TYPE_DATA_BLOCK; - sgl[0].unkeyed.length = 2048; - sgl[0].address = (uint64_t)(uintptr_t)buf; - sgl[1].unkeyed.type = SPDK_NVME_SGL_TYPE_DATA_BLOCK; - sgl[1].unkeyed.length = len - 2048; - sgl[1].address = (uint64_t)(uintptr_t)buf + 16 * 1024; - - cmd.dptr.sgl1.unkeyed.type = SPDK_NVME_SGL_TYPE_LAST_SEGMENT; - cmd.dptr.sgl1.unkeyed.length = 2 * sizeof(*sgl); - cmd.dptr.sgl1.address = (uint64_t)(uintptr_t)sgls; - - ret = nvme_cmd_map_sgls(NULL, &cmd, iovs, 33, len, mps, gpa_to_vva); - CU_ASSERT(ret == 2); - CU_ASSERT(iovs[0].iov_base == (void *)(uintptr_t)buf); - CU_ASSERT(iovs[0].iov_len == 2048); - CU_ASSERT(iovs[1].iov_base == (void *)((uintptr_t)buf + 16 * 1024)); - CU_ASSERT(iovs[1].iov_len == len - 2048); - - /* test case 3: 8KiB with 1 segment, 1 last segment and 3 data blocks */ - sgl[0].unkeyed.type = SPDK_NVME_SGL_TYPE_DATA_BLOCK; - sgl[0].unkeyed.length = 2048; - sgl[0].address = (uint64_t)(uintptr_t)buf; - sgl[1].unkeyed.type = SPDK_NVME_SGL_TYPE_LAST_SEGMENT; - sgl[1].unkeyed.length = 2 * sizeof(*sgl); - sgl[1].address = (uint64_t)(uintptr_t)&sgl[9]; - - sgl[9].unkeyed.type = SPDK_NVME_SGL_TYPE_DATA_BLOCK; - sgl[9].unkeyed.length = 4096; - sgl[9].address = (uint64_t)(uintptr_t)buf + 4 * 1024; - sgl[10].unkeyed.type = SPDK_NVME_SGL_TYPE_DATA_BLOCK; - sgl[10].unkeyed.length = 2048; - sgl[10].address = (uint64_t)(uintptr_t)buf + 16 * 1024; - - cmd.dptr.sgl1.unkeyed.type = SPDK_NVME_SGL_TYPE_SEGMENT; - cmd.dptr.sgl1.unkeyed.length = 2 * sizeof(*sgl); - cmd.dptr.sgl1.address = (uint64_t)(uintptr_t)&sgl[0]; - - ret = nvme_cmd_map_sgls(NULL, &cmd, iovs, 33, len, mps, gpa_to_vva); - CU_ASSERT(ret == 3); - CU_ASSERT(iovs[0].iov_base == (void *)(uintptr_t)buf); - CU_ASSERT(iovs[0].iov_len == 2048); - CU_ASSERT(iovs[1].iov_base == (void *)((uintptr_t)buf + 4 * 1024)); - CU_ASSERT(iovs[1].iov_len == 4096); - CU_ASSERT(iovs[2].iov_base == (void *)((uintptr_t)buf + 16 * 1024)); - CU_ASSERT(iovs[2].iov_len == 2048); - - /* test case 4: not enough iovs */ - len = 12 * 1024; - for (i = 0; i < 6; i++) { - sgl[0].unkeyed.type = SPDK_NVME_SGL_TYPE_DATA_BLOCK; - sgl[0].unkeyed.length = 2048; - sgl[0].address = (uint64_t)(uintptr_t)buf + i * 4096; - } - - cmd.dptr.sgl1.unkeyed.type = SPDK_NVME_SGL_TYPE_LAST_SEGMENT; - cmd.dptr.sgl1.unkeyed.length = 6 * sizeof(*sgl); - cmd.dptr.sgl1.address = (uint64_t)(uintptr_t)sgls; - - ret = nvme_cmd_map_sgls(NULL, &cmd, iovs, 4, len, mps, gpa_to_vva); - CU_ASSERT(ret == -ERANGE); - - spdk_free(buf); - spdk_free(sgls); -} - static void test_nvme_ctrlr_set_arbitration_feature(void) { @@ -3095,8 +2926,6 @@ int main(int argc, char **argv) CU_ADD_TEST(suite, test_nvme_ctrlr_init_set_keep_alive_timeout); CU_ADD_TEST(suite, test_alloc_io_qpair_fail); CU_ADD_TEST(suite, test_nvme_ctrlr_add_remove_process); - CU_ADD_TEST(suite, test_nvme_cmd_map_prps); - CU_ADD_TEST(suite, test_nvme_cmd_map_sgls); CU_ADD_TEST(suite, test_nvme_ctrlr_set_arbitration_feature); CU_ADD_TEST(suite, test_nvme_ctrlr_set_state); CU_ADD_TEST(suite, test_nvme_ctrlr_active_ns_list_v0);