LCOV - code coverage report
Current view: top level - spdk/test/unit/lib/nvme/nvme_pcie.c - nvme_pcie_ut.c (source / functions) Hit Total Coverage
Test: Combined Lines: 698 725 96.3 %
Date: 2024-07-12 17:03:22 Functions: 31 79 39.2 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 75 196 38.3 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2017 Intel Corporation.
       3                 :            :  *   All rights reserved.
       4                 :            :  *   Copyright (c) 2021 Mellanox Technologies LTD. All rights reserved.
       5                 :            :  */
       6                 :            : 
       7                 :            : #include "spdk/stdinc.h"
       8                 :            : 
       9                 :            : #include "spdk_internal/cunit.h"
      10                 :            : 
      11                 :            : #define UNIT_TEST_NO_VTOPHYS
      12                 :            : 
      13                 :            : #include "nvme/nvme_pcie.c"
      14                 :            : #include "nvme/nvme_pcie_common.c"
      15                 :            : #include "common/lib/nvme/common_stubs.h"
      16                 :            : 
      17                 :            : pid_t g_spdk_nvme_pid;
      18         [ -  + ]:          8 : DEFINE_STUB(spdk_mem_register, int, (void *vaddr, size_t len), 0);
      19         [ -  + ]:          4 : DEFINE_STUB(spdk_mem_unregister, int, (void *vaddr, size_t len), 0);
      20                 :            : 
      21         [ #  # ]:          0 : DEFINE_STUB(nvme_get_quirks, uint64_t, (const struct spdk_pci_id *id), 0);
      22                 :            : 
      23         [ #  # ]:          0 : DEFINE_STUB(nvme_wait_for_completion, int,
      24                 :            :             (struct spdk_nvme_qpair *qpair,
      25                 :            :              struct nvme_completion_poll_status *status), 0);
      26                 :          0 : DEFINE_STUB_V(nvme_completion_poll_cb, (void *arg, const struct spdk_nvme_cpl *cpl));
      27                 :            : 
      28         [ #  # ]:          0 : DEFINE_STUB(nvme_ctrlr_submit_admin_request, int, (struct spdk_nvme_ctrlr *ctrlr,
      29                 :            :                 struct nvme_request *req), 0);
      30                 :            : 
      31         [ #  # ]:          0 : DEFINE_STUB(nvme_ctrlr_proc_get_devhandle, struct spdk_pci_device *,
      32                 :            :             (struct spdk_nvme_ctrlr *ctrlr), NULL);
      33         [ #  # ]:          0 : DEFINE_STUB(spdk_nvme_ctrlr_get_socket_id, uint32_t, (struct spdk_nvme_ctrlr *ctrlr),
      34                 :            :             SPDK_ENV_SOCKET_ID_ANY);
      35                 :            : 
      36         [ -  + ]:          8 : DEFINE_STUB(spdk_pci_device_unmap_bar, int, (struct spdk_pci_device *dev, uint32_t bar, void *addr),
      37                 :            :             0);
      38         [ #  # ]:          0 : DEFINE_STUB(spdk_pci_device_attach, int, (struct spdk_pci_driver *driver, spdk_pci_enum_cb enum_cb,
      39                 :            :                 void *enum_ctx, struct spdk_pci_addr *pci_address), 0);
      40         [ #  # ]:          0 : DEFINE_STUB(spdk_pci_device_claim, int, (struct spdk_pci_device *dev), 0);
      41                 :          0 : DEFINE_STUB_V(spdk_pci_device_unclaim, (struct spdk_pci_device *dev));
      42                 :          0 : DEFINE_STUB_V(spdk_pci_device_detach, (struct spdk_pci_device *device));
      43         [ #  # ]:          0 : DEFINE_STUB(spdk_pci_device_cfg_write16, int, (struct spdk_pci_device *dev, uint16_t value,
      44                 :            :                 uint32_t offset), 0);
      45         [ #  # ]:          0 : DEFINE_STUB(spdk_pci_device_cfg_read16, int, (struct spdk_pci_device *dev, uint16_t *value,
      46                 :            :                 uint32_t offset), 0);
      47         [ #  # ]:          0 : DEFINE_STUB(spdk_pci_device_get_id, struct spdk_pci_id, (struct spdk_pci_device *dev), {0});
      48         [ #  # ]:          0 : DEFINE_STUB(spdk_pci_event_listen, int, (void), 0);
      49         [ #  # ]:          0 : DEFINE_STUB(spdk_pci_register_error_handler, int, (spdk_pci_error_handler sighandler, void *ctx),
      50                 :            :             0);
      51                 :          0 : DEFINE_STUB_V(spdk_pci_unregister_error_handler, (spdk_pci_error_handler sighandler));
      52         [ #  # ]:          0 : DEFINE_STUB(spdk_pci_enumerate, int,
      53                 :            :             (struct spdk_pci_driver *driver, spdk_pci_enum_cb enum_cb, void *enum_ctx),
      54                 :            :             -1);
      55                 :            : 
      56                 :          4 : SPDK_LOG_REGISTER_COMPONENT(nvme)
      57                 :            : 
      58                 :            : struct dev_mem_resource {
      59                 :            :         uint64_t phys_addr;
      60                 :            :         uint64_t len;
      61                 :            :         void *addr;
      62                 :            : };
      63                 :            : 
      64                 :            : struct nvme_pcie_ut_bdev_io {
      65                 :            :         struct iovec iovs[NVME_MAX_SGL_DESCRIPTORS];
      66                 :            :         int iovpos;
      67                 :            : };
      68                 :            : 
      69                 :            : struct nvme_driver *g_spdk_nvme_driver = NULL;
      70                 :            : 
      71                 :            : int
      72                 :          8 : spdk_pci_device_map_bar(struct spdk_pci_device *dev, uint32_t bar,
      73                 :            :                         void **mapped_addr, uint64_t *phys_addr, uint64_t *size)
      74                 :            : {
      75                 :          8 :         struct dev_mem_resource *dev_mem_res = (void *)dev;
      76                 :            : 
      77                 :          8 :         *mapped_addr = dev_mem_res->addr;
      78                 :          8 :         *phys_addr = dev_mem_res->phys_addr;
      79                 :          8 :         *size = dev_mem_res->len;
      80                 :            : 
      81                 :          8 :         return 0;
      82                 :            : }
      83                 :            : 
      84                 :            : void
      85                 :         12 : nvme_ctrlr_fail(struct spdk_nvme_ctrlr *ctrlr, bool hot_remove)
      86                 :            : {
      87                 :         12 :         CU_ASSERT(ctrlr != NULL);
      88         [ +  - ]:         12 :         if (hot_remove) {
      89                 :         12 :                 ctrlr->is_removed = true;
      90                 :            :         }
      91                 :            : 
      92                 :         12 :         ctrlr->is_failed = true;
      93                 :         12 : }
      94                 :            : 
      95                 :            : static uint64_t g_vtophys_size = 0;
      96                 :            : 
      97         [ #  # ]:          0 : DEFINE_RETURN_MOCK(spdk_vtophys, uint64_t);
      98                 :            : uint64_t
      99                 :       8220 : spdk_vtophys(const void *buf, uint64_t *size)
     100                 :            : {
     101   [ +  +  +  + ]:       8220 :         if (size && g_vtophys_size > 0) {
     102                 :         40 :                 *size = g_vtophys_size;
     103                 :            :         }
     104                 :            : 
     105   [ -  +  +  +  :       8220 :         HANDLE_RETURN_MOCK(spdk_vtophys);
                   +  + ]
     106                 :            : 
     107                 :       8180 :         return (uintptr_t)buf;
     108                 :            : }
     109                 :            : 
     110         [ #  # ]:          0 : DEFINE_STUB(spdk_pci_device_get_addr, struct spdk_pci_addr, (struct spdk_pci_device *dev), {});
     111         [ #  # ]:          0 : DEFINE_STUB(nvme_ctrlr_probe, int, (const struct spdk_nvme_transport_id *trid,
     112                 :            :                                     struct spdk_nvme_probe_ctx *probe_ctx, void *devhandle), 0);
     113   [ -  +  -  + ]:         12 : DEFINE_STUB(spdk_pci_device_is_removed, bool, (struct spdk_pci_device *dev), false);
     114         [ -  + ]:          4 : DEFINE_STUB(nvme_get_ctrlr_by_trid_unsafe, struct spdk_nvme_ctrlr *,
     115                 :            :             (const struct spdk_nvme_transport_id *trid, const char *hostnqn), NULL);
     116         [ #  # ]:          0 : DEFINE_STUB(spdk_nvme_ctrlr_get_regs_csts, union spdk_nvme_csts_register,
     117                 :            :             (struct spdk_nvme_ctrlr *ctrlr), {});
     118         [ #  # ]:          0 : DEFINE_STUB(nvme_ctrlr_get_process, struct spdk_nvme_ctrlr_process *,
     119                 :            :             (struct spdk_nvme_ctrlr *ctrlr, pid_t pid), NULL);
     120   [ #  #  #  # ]:          0 : DEFINE_STUB(nvme_completion_is_retry, bool, (const struct spdk_nvme_cpl *cpl), false);
     121                 :          0 : DEFINE_STUB_V(spdk_nvme_qpair_print_command, (struct spdk_nvme_qpair *qpair,
     122                 :            :                 struct spdk_nvme_cmd *cmd));
     123                 :          0 : DEFINE_STUB_V(spdk_nvme_qpair_print_completion, (struct spdk_nvme_qpair *qpair,
     124                 :            :                 struct spdk_nvme_cpl *cpl));
     125                 :            : 
     126                 :            : static void
     127                 :         84 : prp_list_prep(struct nvme_tracker *tr, struct nvme_request *req, uint32_t *prp_index)
     128                 :            : {
     129         [ -  + ]:         84 :         memset(req, 0, sizeof(*req));
     130         [ -  + ]:         84 :         memset(tr, 0, sizeof(*tr));
     131                 :         84 :         tr->req = req;
     132                 :         84 :         tr->prp_sgl_bus_addr = 0xDEADBEEF;
     133         [ +  + ]:         84 :         if (prp_index) {
     134                 :         68 :                 *prp_index = 0;
     135                 :            :         }
     136                 :         84 : }
     137                 :            : 
     138                 :            : static void
     139                 :          4 : test_prp_list_append(void)
     140                 :            : {
     141                 :          4 :         struct nvme_request req;
     142                 :          4 :         struct nvme_tracker tr;
     143                 :          4 :         struct spdk_nvme_ctrlr ctrlr = {};
     144                 :          4 :         uint32_t prp_index;
     145                 :            : 
     146                 :          4 :         ctrlr.trid.trtype = SPDK_NVME_TRANSPORT_PCIE;
     147                 :            :         /* Non-DWORD-aligned buffer (invalid) */
     148                 :          4 :         prp_list_prep(&tr, &req, &prp_index);
     149                 :          4 :         CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100001, 0x1000,
     150                 :            :                                             0x1000) == -EFAULT);
     151                 :            : 
     152                 :            :         /* 512-byte buffer, 4K aligned */
     153                 :          4 :         prp_list_prep(&tr, &req, &prp_index);
     154                 :          4 :         CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100000, 0x200, 0x1000) == 0);
     155                 :          4 :         CU_ASSERT(prp_index == 1);
     156                 :          4 :         CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x100000);
     157                 :            : 
     158                 :            :         /* 512-byte buffer, non-4K-aligned */
     159                 :          4 :         prp_list_prep(&tr, &req, &prp_index);
     160                 :          4 :         CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x108000, 0x200, 0x1000) == 0);
     161                 :          4 :         CU_ASSERT(prp_index == 1);
     162                 :          4 :         CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x108000);
     163                 :            : 
     164                 :            :         /* 4K buffer, 4K aligned */
     165                 :          4 :         prp_list_prep(&tr, &req, &prp_index);
     166                 :          4 :         CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100000, 0x1000,
     167                 :            :                                             0x1000) == 0);
     168                 :          4 :         CU_ASSERT(prp_index == 1);
     169                 :          4 :         CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x100000);
     170                 :            : 
     171                 :            :         /* 4K buffer, non-4K aligned */
     172                 :          4 :         prp_list_prep(&tr, &req, &prp_index);
     173                 :          4 :         CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100800, 0x1000,
     174                 :            :                                             0x1000) == 0);
     175                 :          4 :         CU_ASSERT(prp_index == 2);
     176                 :          4 :         CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x100800);
     177                 :          4 :         CU_ASSERT(req.cmd.dptr.prp.prp2 == 0x101000);
     178                 :            : 
     179                 :            :         /* 8K buffer, 4K aligned */
     180                 :          4 :         prp_list_prep(&tr, &req, &prp_index);
     181                 :          4 :         CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100000, 0x2000,
     182                 :            :                                             0x1000) == 0);
     183                 :          4 :         CU_ASSERT(prp_index == 2);
     184                 :          4 :         CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x100000);
     185                 :          4 :         CU_ASSERT(req.cmd.dptr.prp.prp2 == 0x101000);
     186                 :            : 
     187                 :            :         /* 8K buffer, non-4K aligned */
     188                 :          4 :         prp_list_prep(&tr, &req, &prp_index);
     189                 :          4 :         CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100800, 0x2000,
     190                 :            :                                             0x1000) == 0);
     191                 :          4 :         CU_ASSERT(prp_index == 3);
     192                 :          4 :         CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x100800);
     193                 :          4 :         CU_ASSERT(req.cmd.dptr.prp.prp2 == tr.prp_sgl_bus_addr);
     194                 :          4 :         CU_ASSERT(tr.u.prp[0] == 0x101000);
     195                 :          4 :         CU_ASSERT(tr.u.prp[1] == 0x102000);
     196                 :            : 
     197                 :            :         /* 12K buffer, 4K aligned */
     198                 :          4 :         prp_list_prep(&tr, &req, &prp_index);
     199                 :          4 :         CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100000, 0x3000,
     200                 :            :                                             0x1000) == 0);
     201                 :          4 :         CU_ASSERT(prp_index == 3);
     202                 :          4 :         CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x100000);
     203                 :          4 :         CU_ASSERT(req.cmd.dptr.prp.prp2 == tr.prp_sgl_bus_addr);
     204                 :          4 :         CU_ASSERT(tr.u.prp[0] == 0x101000);
     205                 :          4 :         CU_ASSERT(tr.u.prp[1] == 0x102000);
     206                 :            : 
     207                 :            :         /* 12K buffer, non-4K aligned */
     208                 :          4 :         prp_list_prep(&tr, &req, &prp_index);
     209                 :          4 :         CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100800, 0x3000,
     210                 :            :                                             0x1000) == 0);
     211                 :          4 :         CU_ASSERT(prp_index == 4);
     212                 :          4 :         CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x100800);
     213                 :          4 :         CU_ASSERT(req.cmd.dptr.prp.prp2 == tr.prp_sgl_bus_addr);
     214                 :          4 :         CU_ASSERT(tr.u.prp[0] == 0x101000);
     215                 :          4 :         CU_ASSERT(tr.u.prp[1] == 0x102000);
     216                 :          4 :         CU_ASSERT(tr.u.prp[2] == 0x103000);
     217                 :            : 
     218                 :            :         /* Two 4K buffers, both 4K aligned */
     219                 :          4 :         prp_list_prep(&tr, &req, &prp_index);
     220                 :          4 :         CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100000, 0x1000,
     221                 :            :                                             0x1000) == 0);
     222                 :          4 :         CU_ASSERT(prp_index == 1);
     223                 :          4 :         CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x900000, 0x1000,
     224                 :            :                                             0x1000) == 0);
     225                 :          4 :         CU_ASSERT(prp_index == 2);
     226                 :          4 :         CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x100000);
     227                 :          4 :         CU_ASSERT(req.cmd.dptr.prp.prp2 == 0x900000);
     228                 :            : 
     229                 :            :         /* Two 4K buffers, first non-4K aligned, second 4K aligned */
     230                 :          4 :         prp_list_prep(&tr, &req, &prp_index);
     231                 :          4 :         CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100800, 0x1000,
     232                 :            :                                             0x1000) == 0);
     233                 :          4 :         CU_ASSERT(prp_index == 2);
     234                 :          4 :         CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x900000, 0x1000,
     235                 :            :                                             0x1000) == 0);
     236                 :          4 :         CU_ASSERT(prp_index == 3);
     237                 :          4 :         CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x100800);
     238                 :          4 :         CU_ASSERT(req.cmd.dptr.prp.prp2 == tr.prp_sgl_bus_addr);
     239                 :          4 :         CU_ASSERT(tr.u.prp[0] == 0x101000);
     240                 :          4 :         CU_ASSERT(tr.u.prp[1] == 0x900000);
     241                 :            : 
     242                 :            :         /* Two 4K buffers, both non-4K aligned (invalid) */
     243                 :          4 :         prp_list_prep(&tr, &req, &prp_index);
     244                 :          4 :         CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100800, 0x1000,
     245                 :            :                                             0x1000) == 0);
     246                 :          4 :         CU_ASSERT(prp_index == 2);
     247                 :          4 :         CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x900800, 0x1000,
     248                 :            :                                             0x1000) == -EFAULT);
     249                 :          4 :         CU_ASSERT(prp_index == 2);
     250                 :            : 
     251                 :            :         /* 4K buffer, 4K aligned, but vtophys fails */
     252                 :          4 :         MOCK_SET(spdk_vtophys, SPDK_VTOPHYS_ERROR);
     253                 :          4 :         prp_list_prep(&tr, &req, &prp_index);
     254                 :          4 :         CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100000, 0x1000,
     255                 :            :                                             0x1000) == -EFAULT);
     256   [ -  -  -  + ]:          4 :         MOCK_CLEAR(spdk_vtophys);
     257                 :            : 
     258                 :            :         /* Largest aligned buffer that can be described in NVME_MAX_PRP_LIST_ENTRIES (plus PRP1) */
     259                 :          4 :         prp_list_prep(&tr, &req, &prp_index);
     260                 :          4 :         CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100000,
     261                 :            :                                             (NVME_MAX_PRP_LIST_ENTRIES + 1) * 0x1000, 0x1000) == 0);
     262                 :          4 :         CU_ASSERT(prp_index == NVME_MAX_PRP_LIST_ENTRIES + 1);
     263                 :            : 
     264                 :            :         /* Largest non-4K-aligned buffer that can be described in NVME_MAX_PRP_LIST_ENTRIES (plus PRP1) */
     265                 :          4 :         prp_list_prep(&tr, &req, &prp_index);
     266                 :          4 :         CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100800,
     267                 :            :                                             NVME_MAX_PRP_LIST_ENTRIES * 0x1000, 0x1000) == 0);
     268                 :          4 :         CU_ASSERT(prp_index == NVME_MAX_PRP_LIST_ENTRIES + 1);
     269                 :            : 
     270                 :            :         /* Buffer too large to be described in NVME_MAX_PRP_LIST_ENTRIES */
     271                 :          4 :         prp_list_prep(&tr, &req, &prp_index);
     272                 :          4 :         CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100000,
     273                 :            :                                             (NVME_MAX_PRP_LIST_ENTRIES + 2) * 0x1000, 0x1000) == -EFAULT);
     274                 :            : 
     275                 :            :         /* Non-4K-aligned buffer too large to be described in NVME_MAX_PRP_LIST_ENTRIES */
     276                 :          4 :         prp_list_prep(&tr, &req, &prp_index);
     277                 :          4 :         CU_ASSERT(nvme_pcie_prp_list_append(&ctrlr, &tr, &prp_index, (void *)0x100800,
     278                 :            :                                             (NVME_MAX_PRP_LIST_ENTRIES + 1) * 0x1000, 0x1000) == -EFAULT);
     279                 :          4 : }
     280                 :            : 
     281                 :            : struct spdk_event_entry {
     282                 :            :         struct spdk_pci_event           event;
     283                 :            :         STAILQ_ENTRY(spdk_event_entry)  link;
     284                 :            : };
     285                 :            : 
     286                 :            : static STAILQ_HEAD(, spdk_event_entry) g_events = STAILQ_HEAD_INITIALIZER(g_events);
     287                 :            : static bool g_device_allowed = false;
     288                 :            : 
     289                 :            : int
     290                 :         28 : spdk_pci_get_event(int fd, struct spdk_pci_event *event)
     291                 :            : {
     292                 :            :         struct spdk_event_entry *entry;
     293                 :            : 
     294         [ +  + ]:         28 :         if (STAILQ_EMPTY(&g_events)) {
     295                 :         20 :                 return 0;
     296                 :            :         }
     297                 :            : 
     298                 :          8 :         entry = STAILQ_FIRST(&g_events);
     299         [ +  - ]:          8 :         STAILQ_REMOVE_HEAD(&g_events, link);
     300                 :            : 
     301                 :          8 :         *event = entry->event;
     302                 :            : 
     303                 :          8 :         return 1;
     304                 :            : }
     305                 :            : 
     306                 :            : int
     307                 :          4 : spdk_pci_device_allow(struct spdk_pci_addr *pci_addr)
     308                 :            : {
     309                 :          4 :         g_device_allowed = true;
     310                 :            : 
     311                 :          4 :         return 0;
     312                 :            : }
     313                 :            : 
     314                 :            : static void
     315                 :          4 : test_nvme_pcie_hotplug_monitor(void)
     316                 :            : {
     317                 :          4 :         struct nvme_pcie_ctrlr pctrlr = {};
     318                 :          4 :         struct spdk_event_entry entry = {};
     319                 :          4 :         struct nvme_driver driver;
     320                 :          4 :         pthread_mutexattr_t attr;
     321                 :          4 :         struct spdk_nvme_probe_ctx test_nvme_probe_ctx = {};
     322                 :            : 
     323                 :            :         /* Initiate variables and ctrlr */
     324                 :          4 :         driver.initialized = true;
     325                 :          4 :         driver.hotplug_fd = 123;
     326         [ -  + ]:          4 :         CU_ASSERT(pthread_mutexattr_init(&attr) == 0);
     327         [ -  + ]:          4 :         CU_ASSERT(pthread_mutex_init(&pctrlr.ctrlr.ctrlr_lock, &attr) == 0);
     328         [ -  + ]:          4 :         CU_ASSERT(pthread_mutex_init(&driver.lock, &attr) == 0);
     329                 :          4 :         TAILQ_INIT(&driver.shared_attached_ctrlrs);
     330                 :          4 :         g_spdk_nvme_driver = &driver;
     331                 :            : 
     332                 :            :         /* Case 1:  SPDK_NVME_UEVENT_ADD/ NVME_VFIO / NVME_UIO */
     333                 :          4 :         entry.event.action = SPDK_UEVENT_ADD;
     334                 :          4 :         spdk_pci_addr_parse(&entry.event.traddr, "0000:05:00.0");
     335                 :          4 :         CU_ASSERT(STAILQ_EMPTY(&g_events));
     336                 :          4 :         STAILQ_INSERT_TAIL(&g_events, &entry, link);
     337                 :            : 
     338                 :          4 :         _nvme_pcie_hotplug_monitor(&test_nvme_probe_ctx);
     339                 :            : 
     340                 :          4 :         CU_ASSERT(STAILQ_EMPTY(&g_events));
     341         [ -  + ]:          4 :         CU_ASSERT(g_device_allowed == true);
     342                 :          4 :         g_device_allowed = false;
     343                 :            : 
     344                 :            :         /* Case 2: SPDK_NVME_UEVENT_REMOVE/ NVME_UIO */
     345                 :          4 :         entry.event.action = SPDK_UEVENT_REMOVE;
     346                 :          4 :         spdk_pci_addr_parse(&entry.event.traddr, "0000:05:00.0");
     347                 :          4 :         CU_ASSERT(STAILQ_EMPTY(&g_events));
     348                 :          4 :         STAILQ_INSERT_TAIL(&g_events, &entry, link);
     349                 :            : 
     350                 :          4 :         MOCK_SET(nvme_get_ctrlr_by_trid_unsafe, &pctrlr.ctrlr);
     351                 :            : 
     352                 :          4 :         _nvme_pcie_hotplug_monitor(&test_nvme_probe_ctx);
     353                 :            : 
     354                 :          4 :         CU_ASSERT(STAILQ_EMPTY(&g_events));
     355         [ -  + ]:          4 :         CU_ASSERT(pctrlr.ctrlr.is_failed == true);
     356         [ -  + ]:          4 :         CU_ASSERT(pctrlr.ctrlr.is_removed == true);
     357                 :          4 :         pctrlr.ctrlr.is_failed = false;
     358                 :          4 :         pctrlr.ctrlr.is_removed = false;
     359   [ -  -  -  + ]:          4 :         MOCK_CLEAR(nvme_get_ctrlr_by_trid_unsafe);
     360                 :            : 
     361                 :            :         /* Case 3: SPDK_NVME_UEVENT_REMOVE/ NVME_VFIO without event */
     362                 :          4 :         pctrlr.ctrlr.trid.trtype = SPDK_NVME_TRANSPORT_PCIE;
     363         [ -  + ]:          4 :         snprintf(pctrlr.ctrlr.trid.traddr, sizeof(pctrlr.ctrlr.trid.traddr), "0000:02:00.0");
     364                 :          4 :         pctrlr.ctrlr.remove_cb = NULL;
     365                 :          4 :         pctrlr.ctrlr.is_failed = false;
     366                 :          4 :         pctrlr.ctrlr.is_removed = false;
     367                 :          4 :         TAILQ_INSERT_TAIL(&g_spdk_nvme_driver->shared_attached_ctrlrs, &pctrlr.ctrlr, tailq);
     368                 :            : 
     369                 :            :         /* This should be set in the vfio req notifier cb */
     370                 :          4 :         MOCK_SET(spdk_pci_device_is_removed, true);
     371                 :            : 
     372                 :          4 :         _nvme_pcie_hotplug_monitor(&test_nvme_probe_ctx);
     373                 :            : 
     374                 :          4 :         CU_ASSERT(STAILQ_EMPTY(&g_events));
     375         [ -  + ]:          4 :         CU_ASSERT(pctrlr.ctrlr.is_failed == true);
     376         [ -  + ]:          4 :         CU_ASSERT(pctrlr.ctrlr.is_removed == true);
     377                 :          4 :         pctrlr.ctrlr.is_failed = false;
     378                 :          4 :         pctrlr.ctrlr.is_removed = false;
     379   [ -  -  -  + ]:          4 :         MOCK_CLEAR(spdk_pci_device_is_removed);
     380                 :            : 
     381                 :            :         /* Case 4:  Removed device detected in another process  */
     382                 :          4 :         MOCK_SET(spdk_pci_device_is_removed, false);
     383                 :            : 
     384                 :          4 :         _nvme_pcie_hotplug_monitor(&test_nvme_probe_ctx);
     385                 :            : 
     386         [ -  + ]:          4 :         CU_ASSERT(pctrlr.ctrlr.is_failed == false);
     387                 :            : 
     388                 :          4 :         MOCK_SET(spdk_pci_device_is_removed, true);
     389                 :            : 
     390                 :          4 :         _nvme_pcie_hotplug_monitor(&test_nvme_probe_ctx);
     391                 :            : 
     392         [ -  + ]:          4 :         CU_ASSERT(pctrlr.ctrlr.is_failed == true);
     393                 :            : 
     394         [ -  + ]:          4 :         pthread_mutex_destroy(&driver.lock);
     395         [ -  + ]:          4 :         pthread_mutex_destroy(&pctrlr.ctrlr.ctrlr_lock);
     396         [ -  + ]:          4 :         pthread_mutexattr_destroy(&attr);
     397                 :          4 :         g_spdk_nvme_driver = NULL;
     398                 :          4 : }
     399                 :            : 
     400                 :            : static void
     401                 :          4 : test_shadow_doorbell_update(void)
     402                 :            : {
     403                 :            :         bool ret;
     404                 :            : 
     405                 :            :         /* nvme_pcie_qpair_need_event(uint16_t event_idx, uint16_t new_idx, uint16_t old) */
     406                 :          4 :         ret = nvme_pcie_qpair_need_event(10, 15, 14);
     407                 :          4 :         CU_ASSERT(ret == false);
     408                 :            : 
     409                 :          4 :         ret = nvme_pcie_qpair_need_event(14, 15, 14);
     410                 :          4 :         CU_ASSERT(ret == true);
     411                 :          4 : }
     412                 :            : 
     413                 :            : static void
     414                 :          4 : test_build_contig_hw_sgl_request(void)
     415                 :            : {
     416                 :          4 :         struct spdk_nvme_qpair qpair = {};
     417                 :          4 :         struct nvme_request req = {};
     418                 :          4 :         struct nvme_tracker tr = {};
     419                 :          4 :         struct spdk_nvme_ctrlr ctrlr = {};
     420                 :            :         int rc;
     421                 :            : 
     422                 :          4 :         ctrlr.trid.trtype = SPDK_NVME_TRANSPORT_PCIE;
     423                 :          4 :         qpair.ctrlr = &ctrlr;
     424                 :            :         /* Test 1: Payload covered by a single mapping */
     425                 :          4 :         req.payload_size = 100;
     426                 :          4 :         req.payload = NVME_PAYLOAD_CONTIG((void *)0xbeef0, NULL);
     427                 :          4 :         g_vtophys_size = 100;
     428                 :          4 :         MOCK_SET(spdk_vtophys, 0xDEADBEEF);
     429                 :            : 
     430                 :          4 :         rc = nvme_pcie_qpair_build_contig_hw_sgl_request(&qpair, &req, &tr, 0);
     431                 :          4 :         CU_ASSERT(rc == 0);
     432                 :          4 :         CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK);
     433                 :          4 :         CU_ASSERT(req.cmd.dptr.sgl1.address == 0xDEADBEEF);
     434                 :          4 :         CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.length == 100);
     435                 :            : 
     436   [ -  -  -  + ]:          4 :         MOCK_CLEAR(spdk_vtophys);
     437                 :          4 :         g_vtophys_size = 0;
     438         [ -  + ]:          4 :         memset(&qpair, 0, sizeof(qpair));
     439         [ -  + ]:          4 :         memset(&req, 0, sizeof(req));
     440         [ -  + ]:          4 :         memset(&tr, 0, sizeof(tr));
     441                 :            : 
     442                 :            :         /* Test 2: Payload covered by a single mapping, but request is at an offset */
     443                 :          4 :         qpair.ctrlr = &ctrlr;
     444                 :          4 :         req.payload_size = 100;
     445                 :          4 :         req.payload_offset = 50;
     446                 :          4 :         req.payload = NVME_PAYLOAD_CONTIG((void *)0xbeef0, NULL);
     447                 :          4 :         g_vtophys_size = 1000;
     448                 :          4 :         MOCK_SET(spdk_vtophys, 0xDEADBEEF);
     449                 :            : 
     450                 :          4 :         rc = nvme_pcie_qpair_build_contig_hw_sgl_request(&qpair, &req, &tr, 0);
     451                 :          4 :         CU_ASSERT(rc == 0);
     452                 :          4 :         CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK);
     453                 :          4 :         CU_ASSERT(req.cmd.dptr.sgl1.address == 0xDEADBEEF);
     454                 :          4 :         CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.length == 100);
     455                 :            : 
     456   [ -  -  -  + ]:          4 :         MOCK_CLEAR(spdk_vtophys);
     457                 :          4 :         g_vtophys_size = 0;
     458         [ -  + ]:          4 :         memset(&qpair, 0, sizeof(qpair));
     459         [ -  + ]:          4 :         memset(&req, 0, sizeof(req));
     460         [ -  + ]:          4 :         memset(&tr, 0, sizeof(tr));
     461                 :            : 
     462                 :            :         /* Test 3: Payload spans two mappings */
     463                 :          4 :         qpair.ctrlr = &ctrlr;
     464                 :          4 :         req.payload_size = 100;
     465                 :          4 :         req.payload = NVME_PAYLOAD_CONTIG((void *)0xbeef0, NULL);
     466                 :          4 :         g_vtophys_size = 60;
     467                 :          4 :         tr.prp_sgl_bus_addr = 0xFF0FF;
     468                 :          4 :         MOCK_SET(spdk_vtophys, 0xDEADBEEF);
     469                 :            : 
     470                 :          4 :         rc = nvme_pcie_qpair_build_contig_hw_sgl_request(&qpair, &req, &tr, 0);
     471                 :          4 :         CU_ASSERT(rc == 0);
     472                 :          4 :         CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.type == SPDK_NVME_SGL_TYPE_LAST_SEGMENT);
     473                 :          4 :         CU_ASSERT(req.cmd.dptr.sgl1.address == tr.prp_sgl_bus_addr);
     474                 :          4 :         CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.length == 2 * sizeof(struct spdk_nvme_sgl_descriptor));
     475                 :          4 :         CU_ASSERT(tr.u.sgl[0].unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK);
     476                 :          4 :         CU_ASSERT(tr.u.sgl[0].unkeyed.length == 60);
     477                 :          4 :         CU_ASSERT(tr.u.sgl[0].address == 0xDEADBEEF);
     478                 :          4 :         CU_ASSERT(tr.u.sgl[1].unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK);
     479                 :          4 :         CU_ASSERT(tr.u.sgl[1].unkeyed.length == 40);
     480                 :          4 :         CU_ASSERT(tr.u.sgl[1].address == 0xDEADBEEF);
     481                 :            : 
     482   [ -  -  -  + ]:          4 :         MOCK_CLEAR(spdk_vtophys);
     483                 :          4 :         g_vtophys_size = 0;
     484         [ -  + ]:          4 :         memset(&qpair, 0, sizeof(qpair));
     485         [ -  + ]:          4 :         memset(&req, 0, sizeof(req));
     486         [ -  + ]:          4 :         memset(&tr, 0, sizeof(tr));
     487                 :          4 : }
     488                 :            : 
     489                 :            : static void
     490                 :          4 : test_nvme_pcie_qpair_build_metadata(void)
     491                 :            : {
     492                 :          4 :         struct nvme_pcie_qpair pqpair = {};
     493                 :          4 :         struct spdk_nvme_qpair *qpair = &pqpair.qpair;
     494                 :          4 :         struct nvme_tracker tr = {};
     495                 :          4 :         struct nvme_request req = {};
     496                 :          4 :         struct spdk_nvme_ctrlr  ctrlr = {};
     497                 :            :         int rc;
     498                 :            : 
     499                 :          4 :         ctrlr.trid.trtype = SPDK_NVME_TRANSPORT_PCIE;
     500                 :          4 :         tr.req = &req;
     501                 :          4 :         qpair->ctrlr = &ctrlr;
     502                 :            : 
     503                 :          4 :         req.payload = NVME_PAYLOAD_CONTIG(NULL, (void *)0xDEADBEE0);
     504                 :          4 :         req.md_offset = 0;
     505                 :          4 :         req.md_size = 4096;
     506                 :            :         /* The nvme_pcie_qpair_build_metadata() function expects the cmd.psdt
     507                 :            :          * is set to SPDK_NVME_PSDT_SGL_MPTR_CONTIG, and then if metadata is
     508                 :            :          * built using SGL, cmd.psdt is changed to SPDK_NVME_PSDT_SGL_MPTR_SGL
     509                 :            :          * by this function. We need to verify if this indeed is the case.
     510                 :            :          */
     511                 :          4 :         req.cmd.psdt = SPDK_NVME_PSDT_SGL_MPTR_CONTIG;
     512                 :          4 :         tr.prp_sgl_bus_addr = 0xDBADBEEF;
     513                 :          4 :         MOCK_SET(spdk_vtophys, 0xDCADBEE0);
     514                 :            : 
     515                 :          4 :         rc = nvme_pcie_qpair_build_metadata(qpair, &tr, true, true, true);
     516                 :          4 :         CU_ASSERT(rc == 0);
     517                 :          4 :         CU_ASSERT(req.cmd.psdt == SPDK_NVME_PSDT_SGL_MPTR_SGL);
     518                 :          4 :         CU_ASSERT(tr.meta_sgl.address == 0xDCADBEE0);
     519                 :          4 :         CU_ASSERT(tr.meta_sgl.unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK);
     520                 :          4 :         CU_ASSERT(tr.meta_sgl.unkeyed.length == 4096);
     521                 :          4 :         CU_ASSERT(tr.meta_sgl.unkeyed.subtype == 0);
     522                 :          4 :         CU_ASSERT(req.cmd.mptr == (0xDBADBEEF - sizeof(struct spdk_nvme_sgl_descriptor)));
     523                 :            : 
     524                 :            :         /* Non-IOVA contiguous metadata buffers should fail. */
     525                 :          4 :         g_vtophys_size = 1024;
     526                 :          4 :         req.cmd.psdt = SPDK_NVME_PSDT_SGL_MPTR_CONTIG;
     527                 :          4 :         rc = nvme_pcie_qpair_build_metadata(qpair, &tr, true, true, true);
     528                 :          4 :         CU_ASSERT(rc == -EINVAL);
     529                 :          4 :         g_vtophys_size = 0;
     530                 :            : 
     531   [ -  -  -  + ]:          4 :         MOCK_CLEAR(spdk_vtophys);
     532                 :            : 
     533                 :            :         /* Build non sgl metadata */
     534                 :          4 :         MOCK_SET(spdk_vtophys, 0xDDADBEE0);
     535                 :            : 
     536                 :          4 :         rc = nvme_pcie_qpair_build_metadata(qpair, &tr, false, false, true);
     537                 :          4 :         CU_ASSERT(rc == 0);
     538                 :          4 :         CU_ASSERT(req.cmd.mptr == 0xDDADBEE0);
     539                 :            : 
     540                 :            :         /* Build non sgl metadata while sgls are supported */
     541         [ -  + ]:          4 :         memset(&tr.meta_sgl, 0, sizeof(tr.meta_sgl));
     542                 :            :         /* If SGLs are supported, but not in metadata, the cmd.psdt
     543                 :            :          * shall not be changed to SPDK_NVME_PSDT_SGL_MPTR_SGL
     544                 :            :          */
     545                 :          4 :         req.cmd.psdt = SPDK_NVME_PSDT_SGL_MPTR_CONTIG;
     546                 :          4 :         rc = nvme_pcie_qpair_build_metadata(qpair, &tr, true, false, true);
     547                 :          4 :         CU_ASSERT(rc == 0);
     548                 :          4 :         CU_ASSERT(tr.meta_sgl.address == 0);
     549                 :          4 :         CU_ASSERT(tr.meta_sgl.unkeyed.length == 0);
     550                 :          4 :         CU_ASSERT(req.cmd.psdt == SPDK_NVME_PSDT_SGL_MPTR_CONTIG);
     551                 :          4 :         CU_ASSERT(req.cmd.mptr == 0xDDADBEE0);
     552                 :            : 
     553                 :            :         /* Non-IOVA contiguous metadata buffers should fail. */
     554                 :          4 :         g_vtophys_size = 1024;
     555                 :          4 :         rc = nvme_pcie_qpair_build_metadata(qpair, &tr, false, false, true);
     556                 :          4 :         CU_ASSERT(rc == -EINVAL);
     557                 :          4 :         g_vtophys_size = 0;
     558                 :            : 
     559   [ -  -  -  + ]:          4 :         MOCK_CLEAR(spdk_vtophys);
     560                 :          4 : }
     561                 :            : 
     562                 :            : static int
     563                 :         20 : nvme_pcie_ut_next_sge(void *cb_arg, void **address, uint32_t *length)
     564                 :            : {
     565                 :         20 :         struct nvme_pcie_ut_bdev_io *bio = cb_arg;
     566                 :            :         struct iovec *iov;
     567                 :            : 
     568         [ -  + ]:         20 :         SPDK_CU_ASSERT_FATAL(bio->iovpos < NVME_MAX_SGL_DESCRIPTORS);
     569                 :            : 
     570                 :         20 :         iov = &bio->iovs[bio->iovpos];
     571                 :            : 
     572                 :         20 :         *address = iov->iov_base;
     573                 :         20 :         *length = iov->iov_len;
     574                 :         20 :         bio->iovpos++;
     575                 :            : 
     576                 :         20 :         return 0;
     577                 :            : }
     578                 :            : 
     579                 :            : static void
     580                 :         12 : nvme_pcie_ut_reset_sgl(void *cb_arg, uint32_t offset)
     581                 :            : {
     582                 :         12 :         struct nvme_pcie_ut_bdev_io *bio = cb_arg;
     583                 :            :         struct iovec *iov;
     584                 :            : 
     585         [ +  - ]:         12 :         for (bio->iovpos = 0; bio->iovpos < NVME_MAX_SGL_DESCRIPTORS; bio->iovpos++) {
     586                 :         12 :                 iov = &bio->iovs[bio->iovpos];
     587                 :            :                 /* Offset must be aligned with the start of any SGL entry */
     588         [ +  - ]:         12 :                 if (offset == 0) {
     589                 :         12 :                         break;
     590                 :            :                 }
     591                 :            : 
     592         [ #  # ]:          0 :                 SPDK_CU_ASSERT_FATAL(offset >= iov->iov_len);
     593                 :          0 :                 offset -= iov->iov_len;
     594                 :            :         }
     595                 :            : 
     596         [ -  + ]:         12 :         SPDK_CU_ASSERT_FATAL(offset == 0);
     597         [ -  + ]:         12 :         SPDK_CU_ASSERT_FATAL(bio->iovpos < NVME_MAX_SGL_DESCRIPTORS);
     598                 :         12 : }
     599                 :            : 
     600                 :            : static void
     601                 :          4 : test_nvme_pcie_qpair_build_prps_sgl_request(void)
     602                 :            : {
     603                 :          4 :         struct spdk_nvme_qpair qpair = {};
     604                 :          4 :         struct nvme_request req = {};
     605                 :          4 :         struct nvme_tracker tr = {};
     606                 :          4 :         struct spdk_nvme_ctrlr ctrlr = {};
     607                 :          4 :         struct nvme_pcie_ut_bdev_io bio = {};
     608                 :            :         int rc;
     609                 :            : 
     610                 :          4 :         tr.req = &req;
     611                 :          4 :         qpair.ctrlr = &ctrlr;
     612                 :          4 :         req.payload = NVME_PAYLOAD_SGL(nvme_pcie_ut_reset_sgl, nvme_pcie_ut_next_sge, &bio, NULL);
     613                 :          4 :         req.payload_size = 4096;
     614                 :          4 :         ctrlr.page_size = 4096;
     615                 :          4 :         bio.iovs[0].iov_base = (void *)0x100000;
     616                 :          4 :         bio.iovs[0].iov_len = 4096;
     617                 :            : 
     618                 :          4 :         rc = nvme_pcie_qpair_build_prps_sgl_request(&qpair, &req, &tr, NULL);
     619                 :          4 :         CU_ASSERT(rc == 0);
     620                 :          4 :         CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x100000);
     621                 :          4 : }
     622                 :            : 
     623                 :            : static void
     624                 :          4 : test_nvme_pcie_qpair_build_hw_sgl_request(void)
     625                 :            : {
     626                 :          4 :         struct spdk_nvme_qpair qpair = {};
     627                 :          4 :         struct nvme_request req = {};
     628                 :          4 :         struct nvme_tracker tr = {};
     629                 :          4 :         struct nvme_pcie_ut_bdev_io bio = {};
     630                 :          4 :         struct spdk_nvme_ctrlr ctrlr = {};
     631                 :            :         int rc;
     632                 :            : 
     633                 :          4 :         ctrlr.trid.trtype = SPDK_NVME_TRANSPORT_PCIE;
     634                 :          4 :         qpair.ctrlr = &ctrlr;
     635                 :          4 :         req.payload = NVME_PAYLOAD_SGL(nvme_pcie_ut_reset_sgl, nvme_pcie_ut_next_sge, &bio, NULL);
     636                 :          4 :         req.cmd.opc = SPDK_NVME_OPC_WRITE;
     637                 :          4 :         tr.prp_sgl_bus_addr =  0xDAADBEE0;
     638                 :          4 :         g_vtophys_size = 4096;
     639                 :            : 
     640                 :            :         /* Multiple vectors, 2k + 4k + 2k */
     641                 :          4 :         req.payload_size = 8192;
     642                 :          4 :         bio.iovpos = 3;
     643                 :          4 :         bio.iovs[0].iov_base = (void *)0xDBADBEE0;
     644                 :          4 :         bio.iovs[0].iov_len = 2048;
     645                 :          4 :         bio.iovs[1].iov_base = (void *)0xDCADBEE0;
     646                 :          4 :         bio.iovs[1].iov_len = 4096;
     647                 :          4 :         bio.iovs[2].iov_base = (void *)0xDDADBEE0;
     648                 :          4 :         bio.iovs[2].iov_len = 2048;
     649                 :            : 
     650                 :          4 :         rc = nvme_pcie_qpair_build_hw_sgl_request(&qpair, &req, &tr, true);
     651                 :          4 :         CU_ASSERT(rc == 0);
     652                 :          4 :         CU_ASSERT(tr.u.sgl[0].unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK);
     653                 :          4 :         CU_ASSERT(tr.u.sgl[0].unkeyed.length == 2048);
     654                 :          4 :         CU_ASSERT(tr.u.sgl[0].address == 0xDBADBEE0);
     655                 :          4 :         CU_ASSERT(tr.u.sgl[0].unkeyed.subtype == 0);
     656                 :          4 :         CU_ASSERT(tr.u.sgl[1].unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK);
     657                 :          4 :         CU_ASSERT(tr.u.sgl[1].unkeyed.length == 4096);
     658                 :          4 :         CU_ASSERT(tr.u.sgl[1].address == 0xDCADBEE0);
     659                 :          4 :         CU_ASSERT(tr.u.sgl[2].unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK);
     660                 :          4 :         CU_ASSERT(tr.u.sgl[2].unkeyed.length == 2048);
     661                 :          4 :         CU_ASSERT(tr.u.sgl[2].unkeyed.length == 2048);
     662                 :          4 :         CU_ASSERT(tr.u.sgl[2].address == 0xDDADBEE0);
     663                 :          4 :         CU_ASSERT(req.cmd.psdt == SPDK_NVME_PSDT_SGL_MPTR_CONTIG);
     664                 :          4 :         CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.subtype == 0);
     665                 :          4 :         CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.type == SPDK_NVME_SGL_TYPE_LAST_SEGMENT);
     666                 :          4 :         CU_ASSERT(req.cmd.dptr.sgl1.address == 0xDAADBEE0);
     667                 :          4 :         CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.length == 48);
     668                 :            : 
     669                 :            :         /* Single vector */
     670         [ -  + ]:          4 :         memset(&tr, 0, sizeof(tr));
     671         [ -  + ]:          4 :         memset(&bio, 0, sizeof(bio));
     672         [ -  + ]:          4 :         memset(&req, 0, sizeof(req));
     673                 :          4 :         req.payload = NVME_PAYLOAD_SGL(nvme_pcie_ut_reset_sgl, nvme_pcie_ut_next_sge, &bio, NULL);
     674                 :          4 :         req.cmd.opc = SPDK_NVME_OPC_WRITE;
     675                 :          4 :         req.payload_size = 4096;
     676                 :          4 :         bio.iovpos = 1;
     677                 :          4 :         bio.iovs[0].iov_base = (void *)0xDBADBEE0;
     678                 :          4 :         bio.iovs[0].iov_len = 4096;
     679                 :            : 
     680                 :          4 :         rc = nvme_pcie_qpair_build_hw_sgl_request(&qpair, &req, &tr, true);
     681                 :          4 :         CU_ASSERT(rc == 0);
     682                 :          4 :         CU_ASSERT(tr.u.sgl[0].unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK);
     683                 :          4 :         CU_ASSERT(tr.u.sgl[0].unkeyed.length == 4096);
     684                 :          4 :         CU_ASSERT(tr.u.sgl[0].address == 0xDBADBEE0);
     685                 :          4 :         CU_ASSERT(tr.u.sgl[0].unkeyed.subtype == 0);
     686                 :          4 :         CU_ASSERT(req.cmd.psdt == SPDK_NVME_PSDT_SGL_MPTR_CONTIG);
     687                 :          4 :         CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.subtype == 0);
     688                 :          4 :         CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.type == SPDK_NVME_SGL_TYPE_DATA_BLOCK);
     689                 :          4 :         CU_ASSERT(req.cmd.dptr.sgl1.address == 0xDBADBEE0);
     690                 :          4 :         CU_ASSERT(req.cmd.dptr.sgl1.unkeyed.length == 4096);
     691                 :          4 : }
     692                 :            : 
     693                 :            : static void
     694                 :          4 : test_nvme_pcie_qpair_build_contig_request(void)
     695                 :            : {
     696                 :          4 :         struct nvme_pcie_qpair pqpair = {};
     697                 :          4 :         struct nvme_request req = {};
     698                 :          4 :         struct nvme_tracker tr = {};
     699                 :          4 :         struct spdk_nvme_ctrlr ctrlr = {};
     700                 :            :         int rc;
     701                 :            : 
     702                 :          4 :         pqpair.qpair.ctrlr = &ctrlr;
     703                 :          4 :         ctrlr.page_size = 0x1000;
     704                 :            : 
     705                 :            :         /* 1 prp, 4k-aligned */
     706                 :          4 :         prp_list_prep(&tr, &req, NULL);
     707                 :          4 :         req.payload = NVME_PAYLOAD_CONTIG((void *)0x100000, NULL);
     708                 :          4 :         req.payload_size = 0x1000;
     709                 :            : 
     710                 :          4 :         rc = nvme_pcie_qpair_build_contig_request(&pqpair.qpair, &req, &tr, true);
     711                 :          4 :         CU_ASSERT(rc == 0);
     712                 :          4 :         CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x100000);
     713                 :            : 
     714                 :            :         /* 2 prps, non-4K-aligned */
     715                 :          4 :         prp_list_prep(&tr, &req, NULL);
     716                 :          4 :         req.payload = NVME_PAYLOAD_CONTIG((void *)0x100000, NULL);
     717                 :          4 :         req.payload_size = 0x1000;
     718                 :          4 :         req.payload_offset = 0x800;
     719                 :            : 
     720                 :          4 :         rc = nvme_pcie_qpair_build_contig_request(&pqpair.qpair, &req, &tr, true);
     721                 :          4 :         CU_ASSERT(rc == 0);
     722                 :          4 :         CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x100800);
     723                 :          4 :         CU_ASSERT(req.cmd.dptr.prp.prp2 == 0x101000);
     724                 :            : 
     725                 :            :         /* 3 prps, 4k-aligned */
     726                 :          4 :         prp_list_prep(&tr, &req, NULL);
     727                 :          4 :         req.payload = NVME_PAYLOAD_CONTIG((void *)0x100000, NULL);
     728                 :          4 :         req.payload_size = 0x3000;
     729                 :            : 
     730                 :          4 :         rc = nvme_pcie_qpair_build_contig_request(&pqpair.qpair, &req, &tr, true);
     731                 :          4 :         CU_ASSERT(rc == 0);
     732                 :          4 :         CU_ASSERT(req.cmd.dptr.prp.prp1 == 0x100000);
     733                 :          4 :         CU_ASSERT(req.cmd.dptr.prp.prp2 == tr.prp_sgl_bus_addr);
     734                 :          4 :         CU_ASSERT(tr.u.prp[0] == 0x101000);
     735                 :          4 :         CU_ASSERT(tr.u.prp[1] == 0x102000);
     736                 :            : 
     737                 :            :         /* address not dword aligned */
     738                 :          4 :         prp_list_prep(&tr, &req, NULL);
     739                 :          4 :         req.payload = NVME_PAYLOAD_CONTIG((void *)0x100001, NULL);
     740                 :          4 :         req.payload_size = 0x3000;
     741                 :          4 :         req.qpair = &pqpair.qpair;
     742                 :          4 :         TAILQ_INIT(&pqpair.outstanding_tr);
     743                 :          4 :         TAILQ_INSERT_TAIL(&pqpair.outstanding_tr, &tr, tq_list);
     744                 :            : 
     745                 :          4 :         rc = nvme_pcie_qpair_build_contig_request(&pqpair.qpair, &req, &tr, true);
     746                 :          4 :         CU_ASSERT(rc == -EFAULT);
     747                 :          4 : }
     748                 :            : 
     749                 :            : static void
     750                 :          4 : test_nvme_pcie_ctrlr_regs_get_set(void)
     751                 :            : {
     752                 :          4 :         struct nvme_pcie_ctrlr pctrlr = {};
     753                 :          4 :         volatile struct spdk_nvme_registers regs = {};
     754                 :          4 :         uint32_t value_4;
     755                 :          4 :         uint64_t value_8;
     756                 :            :         int rc;
     757                 :            : 
     758                 :          4 :         pctrlr.regs = &regs;
     759                 :            : 
     760                 :          4 :         rc = nvme_pcie_ctrlr_set_reg_4(&pctrlr.ctrlr, 8, 4);
     761                 :          4 :         CU_ASSERT(rc == 0);
     762                 :            : 
     763                 :          4 :         rc = nvme_pcie_ctrlr_get_reg_4(&pctrlr.ctrlr, 8, &value_4);
     764                 :          4 :         CU_ASSERT(rc == 0);
     765                 :          4 :         CU_ASSERT(value_4 == 4);
     766                 :            : 
     767                 :          4 :         rc = nvme_pcie_ctrlr_set_reg_8(&pctrlr.ctrlr, 0, 0x100000000);
     768                 :          4 :         CU_ASSERT(rc == 0);
     769                 :            : 
     770                 :          4 :         rc = nvme_pcie_ctrlr_get_reg_8(&pctrlr.ctrlr, 0, &value_8);
     771                 :          4 :         CU_ASSERT(rc == 0);
     772                 :          4 :         CU_ASSERT(value_8 == 0x100000000);
     773                 :          4 : }
     774                 :            : 
     775                 :            : static void
     776                 :          4 : test_nvme_pcie_ctrlr_map_unmap_cmb(void)
     777                 :            : {
     778                 :          4 :         struct nvme_pcie_ctrlr pctrlr = {};
     779                 :          4 :         volatile struct spdk_nvme_registers regs = {};
     780                 :          4 :         union spdk_nvme_cmbsz_register cmbsz = {};
     781                 :          4 :         union spdk_nvme_cmbloc_register cmbloc = {};
     782                 :          4 :         struct dev_mem_resource cmd_res = {};
     783                 :            :         int rc;
     784                 :            : 
     785                 :          4 :         pctrlr.regs = &regs;
     786                 :          4 :         pctrlr.devhandle = (void *)&cmd_res;
     787                 :          4 :         cmd_res.addr = (void *)0x7f7c0080d000;
     788                 :          4 :         cmd_res.len = 0x800000;
     789                 :          4 :         cmd_res.phys_addr = 0xFC800000;
     790                 :            :         /* Configure cmb size with unit size 4k, offset 100, unsupported SQ */
     791                 :          4 :         cmbsz.bits.sz = 512;
     792                 :          4 :         cmbsz.bits.szu = 0;
     793                 :          4 :         cmbsz.bits.sqs = 0;
     794                 :          4 :         cmbloc.bits.bir = 0;
     795                 :          4 :         cmbloc.bits.ofst = 100;
     796                 :            : 
     797                 :          4 :         nvme_pcie_ctrlr_set_reg_4(&pctrlr.ctrlr, offsetof(struct spdk_nvme_registers, cmbsz.raw),
     798                 :            :                                   cmbsz.raw);
     799                 :          4 :         nvme_pcie_ctrlr_set_reg_4(&pctrlr.ctrlr, offsetof(struct spdk_nvme_registers, cmbloc.raw),
     800                 :            :                                   cmbloc.raw);
     801                 :            : 
     802                 :          4 :         nvme_pcie_ctrlr_map_cmb(&pctrlr);
     803                 :          4 :         CU_ASSERT(pctrlr.cmb.bar_va == (void *)0x7f7c0080d000);
     804                 :          4 :         CU_ASSERT(pctrlr.cmb.bar_pa == 0xFC800000);
     805                 :          4 :         CU_ASSERT(pctrlr.cmb.size == 512 * 4096);
     806                 :          4 :         CU_ASSERT(pctrlr.cmb.current_offset == 4096 * 100);
     807         [ -  + ]:          4 :         CU_ASSERT(pctrlr.ctrlr.opts.use_cmb_sqs == false);
     808                 :            : 
     809                 :          4 :         rc = nvme_pcie_ctrlr_unmap_cmb(&pctrlr);
     810                 :          4 :         CU_ASSERT(rc == 0);
     811                 :            : 
     812                 :            :         /* Invalid mapping information */
     813         [ -  + ]:          4 :         memset(&pctrlr.cmb, 0, sizeof(pctrlr.cmb));
     814                 :          4 :         nvme_pcie_ctrlr_set_reg_4(&pctrlr.ctrlr, offsetof(struct spdk_nvme_registers, cmbsz.raw), 0);
     815                 :          4 :         nvme_pcie_ctrlr_set_reg_4(&pctrlr.ctrlr, offsetof(struct spdk_nvme_registers, cmbloc.raw), 0);
     816                 :            : 
     817                 :          4 :         nvme_pcie_ctrlr_map_cmb(&pctrlr);
     818                 :          4 :         CU_ASSERT(pctrlr.cmb.bar_va == NULL);
     819                 :          4 :         CU_ASSERT(pctrlr.cmb.bar_pa == 0);
     820                 :          4 :         CU_ASSERT(pctrlr.cmb.size == 0);
     821                 :          4 :         CU_ASSERT(pctrlr.cmb.current_offset == 0);
     822         [ -  + ]:          4 :         CU_ASSERT(pctrlr.ctrlr.opts.use_cmb_sqs == false);
     823                 :          4 : }
     824                 :            : 
     825                 :            : 
     826                 :            : static void
     827                 :         24 : prepare_map_io_cmd(struct nvme_pcie_ctrlr *pctrlr)
     828                 :            : {
     829                 :         24 :         union spdk_nvme_cmbsz_register cmbsz = {};
     830                 :         24 :         union spdk_nvme_cmbloc_register cmbloc = {};
     831                 :            : 
     832                 :         24 :         cmbsz.bits.sz = 512;
     833                 :         24 :         cmbsz.bits.wds = 1;
     834                 :         24 :         cmbsz.bits.rds = 1;
     835                 :            : 
     836                 :         24 :         nvme_pcie_ctrlr_set_reg_4(&pctrlr->ctrlr, offsetof(struct spdk_nvme_registers, cmbsz.raw),
     837                 :            :                                   cmbsz.raw);
     838                 :         24 :         nvme_pcie_ctrlr_set_reg_4(&pctrlr->ctrlr, offsetof(struct spdk_nvme_registers, cmbloc.raw),
     839                 :            :                                   cmbloc.raw);
     840                 :            : 
     841                 :         24 :         pctrlr->cmb.bar_va = (void *)0x7F7C0080D000;
     842                 :         24 :         pctrlr->cmb.bar_pa = 0xFC800000;
     843                 :         24 :         pctrlr->cmb.current_offset = 1ULL << 22;
     844                 :         24 :         pctrlr->cmb.size = (1ULL << 22) * 512;
     845                 :         24 :         pctrlr->cmb.mem_register_addr = NULL;
     846                 :         24 :         pctrlr->ctrlr.opts.use_cmb_sqs = false;
     847                 :         24 : }
     848                 :            : 
     849                 :            : static void
     850                 :          4 : test_nvme_pcie_ctrlr_map_io_cmb(void)
     851                 :            : {
     852                 :          4 :         struct nvme_pcie_ctrlr pctrlr = {};
     853                 :          4 :         volatile struct spdk_nvme_registers regs = {};
     854                 :          4 :         union spdk_nvme_cmbsz_register cmbsz = {};
     855                 :          4 :         void *mem_reg_addr = NULL;
     856                 :          4 :         size_t size;
     857                 :            :         int rc;
     858                 :            : 
     859                 :          4 :         pctrlr.regs = &regs;
     860                 :          4 :         prepare_map_io_cmd(&pctrlr);
     861                 :            : 
     862                 :          4 :         mem_reg_addr = nvme_pcie_ctrlr_map_io_cmb(&pctrlr.ctrlr, &size);
     863                 :            :         /* Ceil the current cmb vaddr and cmb size to 2MB_aligned */
     864                 :          4 :         CU_ASSERT(mem_reg_addr == (void *)0x7F7C00E00000);
     865                 :          4 :         CU_ASSERT(size == 0x7FE00000);
     866                 :            : 
     867                 :          4 :         rc = nvme_pcie_ctrlr_unmap_io_cmb(&pctrlr.ctrlr);
     868                 :          4 :         CU_ASSERT(rc == 0);
     869                 :          4 :         CU_ASSERT(pctrlr.cmb.mem_register_addr == NULL);
     870                 :          4 :         CU_ASSERT(pctrlr.cmb.mem_register_size == 0);
     871                 :            : 
     872                 :            :         /* cmb mem_register_addr not NULL */
     873                 :          4 :         prepare_map_io_cmd(&pctrlr);
     874                 :          4 :         pctrlr.cmb.mem_register_addr = (void *)0xDEADBEEF;
     875                 :          4 :         pctrlr.cmb.mem_register_size = 1024;
     876                 :            : 
     877                 :          4 :         mem_reg_addr = nvme_pcie_ctrlr_map_io_cmb(&pctrlr.ctrlr, &size);
     878                 :          4 :         CU_ASSERT(size == 1024);
     879                 :          4 :         CU_ASSERT(mem_reg_addr == (void *)0xDEADBEEF);
     880                 :            : 
     881                 :            :         /* cmb.bar_va is NULL */
     882                 :          4 :         prepare_map_io_cmd(&pctrlr);
     883                 :          4 :         pctrlr.cmb.bar_va = NULL;
     884                 :            : 
     885                 :          4 :         mem_reg_addr = nvme_pcie_ctrlr_map_io_cmb(&pctrlr.ctrlr, &size);
     886                 :          4 :         CU_ASSERT(mem_reg_addr == NULL);
     887                 :          4 :         CU_ASSERT(size == 0);
     888                 :            : 
     889                 :            :         /* submission queue already used */
     890                 :          4 :         prepare_map_io_cmd(&pctrlr);
     891                 :          4 :         pctrlr.ctrlr.opts.use_cmb_sqs = true;
     892                 :            : 
     893                 :          4 :         mem_reg_addr = nvme_pcie_ctrlr_map_io_cmb(&pctrlr.ctrlr, &size);
     894                 :          4 :         CU_ASSERT(mem_reg_addr == NULL);
     895                 :          4 :         CU_ASSERT(size == 0);
     896                 :            : 
     897                 :          4 :         pctrlr.ctrlr.opts.use_cmb_sqs = false;
     898                 :            : 
     899                 :            :         /* Only SQS is supported */
     900                 :          4 :         prepare_map_io_cmd(&pctrlr);
     901                 :          4 :         cmbsz.bits.wds = 0;
     902                 :          4 :         cmbsz.bits.rds = 0;
     903                 :          4 :         nvme_pcie_ctrlr_set_reg_4(&pctrlr.ctrlr, offsetof(struct spdk_nvme_registers, cmbsz.raw),
     904                 :            :                                   cmbsz.raw);
     905                 :            : 
     906                 :          4 :         mem_reg_addr = nvme_pcie_ctrlr_map_io_cmb(&pctrlr.ctrlr, &size);
     907                 :          4 :         CU_ASSERT(mem_reg_addr == NULL);
     908                 :          4 :         CU_ASSERT(size == 0);
     909                 :            : 
     910                 :            :         /* CMB size is less than 4MB */
     911                 :          4 :         prepare_map_io_cmd(&pctrlr);
     912                 :          4 :         pctrlr.cmb.size = 1ULL << 16;
     913                 :            : 
     914                 :          4 :         mem_reg_addr = nvme_pcie_ctrlr_map_io_cmb(&pctrlr.ctrlr, &size);
     915                 :          4 :         CU_ASSERT(mem_reg_addr == NULL);
     916                 :          4 :         CU_ASSERT(size == 0);
     917                 :          4 : }
     918                 :            : 
     919                 :            : static void
     920                 :          4 : test_nvme_pcie_ctrlr_map_unmap_pmr(void)
     921                 :            : {
     922                 :          4 :         struct nvme_pcie_ctrlr pctrlr = {};
     923                 :          4 :         volatile struct spdk_nvme_registers regs = {};
     924                 :          4 :         union spdk_nvme_pmrcap_register pmrcap = {};
     925                 :          4 :         struct dev_mem_resource cmd_res = {};
     926                 :            :         int rc;
     927                 :            : 
     928                 :          4 :         pctrlr.regs = &regs;
     929                 :          4 :         pctrlr.devhandle = (void *)&cmd_res;
     930                 :          4 :         regs.cap.bits.pmrs = 1;
     931                 :          4 :         cmd_res.addr = (void *)0x7F7C0080d000;
     932                 :          4 :         cmd_res.len = 0x800000;
     933                 :          4 :         cmd_res.phys_addr = 0xFC800000;
     934                 :          4 :         pmrcap.bits.bir = 2;
     935                 :          4 :         pmrcap.bits.cmss = 1;
     936                 :          4 :         nvme_pcie_ctrlr_set_reg_4(&pctrlr.ctrlr,
     937                 :            :                                   offsetof(struct spdk_nvme_registers, pmrcap.raw),
     938                 :            :                                   pmrcap.raw);
     939                 :            : 
     940                 :          4 :         nvme_pcie_ctrlr_map_pmr(&pctrlr);
     941                 :          4 :         CU_ASSERT(pctrlr.regs->pmrmscu == 0);
     942                 :            :         /* Controller memory space enable, bit 1 */
     943                 :          4 :         CU_ASSERT(pctrlr.regs->pmrmscl.raw == 0xFC800002);
     944                 :          4 :         CU_ASSERT(pctrlr.regs->pmrsts.raw == 0);
     945                 :          4 :         CU_ASSERT(pctrlr.pmr.bar_va == (void *)0x7F7C0080d000);
     946                 :          4 :         CU_ASSERT(pctrlr.pmr.bar_pa == 0xFC800000);
     947                 :          4 :         CU_ASSERT(pctrlr.pmr.size == 0x800000);
     948                 :            : 
     949                 :          4 :         rc = nvme_pcie_ctrlr_unmap_pmr(&pctrlr);
     950                 :          4 :         CU_ASSERT(rc == 0);
     951                 :          4 :         CU_ASSERT(pctrlr.regs->pmrmscu == 0);
     952                 :          4 :         CU_ASSERT(pctrlr.regs->pmrmscl.raw == 0);
     953                 :            : 
     954                 :            :         /* pmrcap value invalid */
     955         [ -  + ]:          4 :         memset(&pctrlr, 0, sizeof(pctrlr));
     956         [ -  + ]:          4 :         memset((void *)&regs, 0, sizeof(regs));
     957         [ -  + ]:          4 :         memset(&cmd_res, 0, sizeof(cmd_res));
     958                 :            : 
     959                 :          4 :         pctrlr.regs = &regs;
     960                 :          4 :         pctrlr.devhandle = (void *)&cmd_res;
     961                 :          4 :         regs.cap.bits.pmrs = 1;
     962                 :          4 :         cmd_res.addr = (void *)0x7F7C0080d000;
     963                 :          4 :         cmd_res.len = 0x800000;
     964                 :          4 :         cmd_res.phys_addr = 0xFC800000;
     965                 :          4 :         pmrcap.raw = 0;
     966                 :          4 :         nvme_pcie_ctrlr_set_reg_4(&pctrlr.ctrlr,
     967                 :            :                                   offsetof(struct spdk_nvme_registers, pmrcap.raw),
     968                 :            :                                   pmrcap.raw);
     969                 :            : 
     970                 :          4 :         nvme_pcie_ctrlr_map_pmr(&pctrlr);
     971                 :          4 :         CU_ASSERT(pctrlr.pmr.bar_va == NULL);
     972                 :          4 :         CU_ASSERT(pctrlr.pmr.bar_pa == 0);
     973                 :          4 :         CU_ASSERT(pctrlr.pmr.size == 0);
     974                 :          4 : }
     975                 :            : 
     976                 :            : static void
     977                 :          4 : test_nvme_pcie_ctrlr_config_pmr(void)
     978                 :            : {
     979                 :          4 :         struct nvme_pcie_ctrlr pctrlr = {};
     980                 :          4 :         union spdk_nvme_pmrcap_register pmrcap = {};
     981                 :          4 :         union spdk_nvme_pmrsts_register pmrsts = {};
     982                 :          4 :         union spdk_nvme_cap_register    cap = {};
     983                 :          4 :         union spdk_nvme_pmrctl_register pmrctl = {};
     984                 :          4 :         volatile struct spdk_nvme_registers regs = {};
     985                 :            :         int rc;
     986                 :            : 
     987                 :            :         /* pmrctl enable */
     988                 :          4 :         pctrlr.regs = &regs;
     989                 :          4 :         pmrcap.bits.pmrtu = 0;
     990                 :          4 :         pmrcap.bits.pmrto = 1;
     991                 :          4 :         pmrsts.bits.nrdy = false;
     992                 :          4 :         pmrctl.bits.en = 0;
     993                 :          4 :         cap.bits.pmrs = 1;
     994                 :            : 
     995                 :          4 :         rc = nvme_pcie_ctrlr_set_pmrctl(&pctrlr, &pmrctl);
     996         [ -  + ]:          4 :         SPDK_CU_ASSERT_FATAL(rc == 0);
     997                 :          4 :         rc = nvme_pcie_ctrlr_set_reg_8(&pctrlr.ctrlr, offsetof(struct spdk_nvme_registers, cap.raw),
     998                 :            :                                        cap.raw);
     999         [ -  + ]:          4 :         SPDK_CU_ASSERT_FATAL(rc == 0);
    1000                 :          4 :         rc = nvme_pcie_ctrlr_set_reg_4(&pctrlr.ctrlr, offsetof(struct spdk_nvme_registers, pmrcap.raw),
    1001                 :            :                                        pmrcap.raw);
    1002         [ -  + ]:          4 :         SPDK_CU_ASSERT_FATAL(rc == 0);
    1003                 :          4 :         rc = nvme_pcie_ctrlr_set_reg_4(&pctrlr.ctrlr, offsetof(struct spdk_nvme_registers, pmrsts.raw),
    1004                 :            :                                        pmrsts.raw);
    1005         [ -  + ]:          4 :         SPDK_CU_ASSERT_FATAL(rc == 0);
    1006                 :            : 
    1007                 :          4 :         rc = nvme_pcie_ctrlr_config_pmr(&pctrlr.ctrlr, true);
    1008                 :          4 :         CU_ASSERT(rc == 0);
    1009                 :          4 :         rc = nvme_pcie_ctrlr_get_pmrctl(&pctrlr, &pmrctl);
    1010                 :          4 :         CU_ASSERT(rc == 0);
    1011                 :          4 :         CU_ASSERT(pmrctl.bits.en == true);
    1012                 :            : 
    1013                 :            :         /* pmrctl disable */
    1014                 :          4 :         pmrsts.bits.nrdy = true;
    1015                 :          4 :         rc = nvme_pcie_ctrlr_set_reg_4(&pctrlr.ctrlr, offsetof(struct spdk_nvme_registers, pmrsts.raw),
    1016                 :            :                                        pmrsts.raw);
    1017         [ -  + ]:          4 :         SPDK_CU_ASSERT_FATAL(rc == 0);
    1018                 :          4 :         rc = nvme_pcie_ctrlr_set_pmrctl(&pctrlr, &pmrctl);
    1019         [ -  + ]:          4 :         SPDK_CU_ASSERT_FATAL(rc == 0);
    1020                 :            : 
    1021                 :          4 :         rc = nvme_pcie_ctrlr_config_pmr(&pctrlr.ctrlr, false);
    1022                 :          4 :         CU_ASSERT(rc == 0);
    1023                 :          4 :         rc = nvme_pcie_ctrlr_get_pmrctl(&pctrlr, &pmrctl);
    1024                 :          4 :         CU_ASSERT(rc == 0);
    1025                 :          4 :         CU_ASSERT(pmrctl.bits.en == false);
    1026                 :            : 
    1027                 :            :         /* configuration exist */
    1028                 :          4 :         rc = nvme_pcie_ctrlr_config_pmr(&pctrlr.ctrlr, false);
    1029                 :          4 :         CU_ASSERT(rc == -EINVAL);
    1030                 :          4 : }
    1031                 :            : 
    1032                 :            : static void
    1033                 :         24 : map_io_pmr_init(struct nvme_pcie_ctrlr *pctrlr, union spdk_nvme_pmrcap_register *pmrcap)
    1034                 :            : {
    1035                 :         24 :         pmrcap->raw = 0;
    1036                 :         24 :         pmrcap->bits.rds = 1;
    1037                 :         24 :         pmrcap->bits.wds = 1;
    1038                 :         24 :         nvme_pcie_ctrlr_set_reg_4(&pctrlr->ctrlr, offsetof(struct spdk_nvme_registers, pmrcap.raw),
    1039                 :            :                                   pmrcap->raw);
    1040                 :         24 :         pctrlr->regs->cap.bits.pmrs = 1;
    1041                 :         24 :         pctrlr->pmr.mem_register_size = 0;
    1042                 :         24 :         pctrlr->pmr.mem_register_addr = NULL;
    1043                 :         24 :         pctrlr->pmr.bar_va = (void *)0x7F7C00E30000;
    1044                 :         24 :         pctrlr->pmr.size = (1 << 22) * 128;
    1045                 :         24 : }
    1046                 :            : 
    1047                 :            : static void
    1048                 :          4 : test_nvme_pcie_ctrlr_map_io_pmr(void)
    1049                 :            : {
    1050                 :          4 :         struct nvme_pcie_ctrlr pctrlr = {};
    1051                 :            :         struct spdk_nvme_ctrlr *ctrlr;
    1052                 :          4 :         volatile struct spdk_nvme_registers regs = {};
    1053                 :          4 :         union spdk_nvme_pmrcap_register pmrcap;
    1054                 :          4 :         void *mem_reg_addr = NULL;
    1055                 :          4 :         size_t rt_size = 0;
    1056                 :            : 
    1057                 :          4 :         ctrlr = &pctrlr.ctrlr;
    1058                 :          4 :         pctrlr.regs = &regs;
    1059                 :            : 
    1060                 :            :         /* PMR is not supported by the controller */
    1061                 :          4 :         map_io_pmr_init(&pctrlr, &pmrcap);
    1062                 :          4 :         regs.cap.bits.pmrs = 0;
    1063                 :            : 
    1064                 :          4 :         mem_reg_addr = nvme_pcie_ctrlr_map_io_pmr(ctrlr, &rt_size);
    1065                 :          4 :         CU_ASSERT(mem_reg_addr == NULL);
    1066                 :            : 
    1067                 :            :         /* mem_register_addr not NULL. */
    1068                 :          4 :         map_io_pmr_init(&pctrlr, &pmrcap);
    1069                 :          4 :         pctrlr.pmr.mem_register_addr = (void *)0xDEADBEEF;
    1070                 :          4 :         pctrlr.pmr.mem_register_size = 1024;
    1071                 :            : 
    1072                 :          4 :         mem_reg_addr = nvme_pcie_ctrlr_map_io_pmr(ctrlr, &rt_size);
    1073                 :          4 :         CU_ASSERT(rt_size == 1024);
    1074                 :          4 :         CU_ASSERT(mem_reg_addr == (void *)0xDEADBEEF);
    1075                 :            : 
    1076                 :            :         /* PMR not available */
    1077                 :          4 :         map_io_pmr_init(&pctrlr, &pmrcap);
    1078                 :          4 :         pctrlr.pmr.bar_va = NULL;
    1079                 :          4 :         pctrlr.pmr.mem_register_addr = NULL;
    1080                 :            : 
    1081                 :          4 :         mem_reg_addr = nvme_pcie_ctrlr_map_io_pmr(ctrlr, &rt_size);
    1082                 :          4 :         CU_ASSERT(mem_reg_addr == NULL);
    1083                 :          4 :         CU_ASSERT(rt_size == 0);
    1084                 :            : 
    1085                 :            :         /* WDS / RDS is not supported */
    1086                 :          4 :         map_io_pmr_init(&pctrlr, &pmrcap);
    1087                 :          4 :         pmrcap.bits.rds = 0;
    1088                 :          4 :         pmrcap.bits.wds = 0;
    1089                 :          4 :         nvme_pcie_ctrlr_set_reg_4(&pctrlr.ctrlr, offsetof(struct spdk_nvme_registers, pmrcap.raw),
    1090                 :            :                                   pmrcap.raw);
    1091                 :            : 
    1092                 :          4 :         mem_reg_addr = nvme_pcie_ctrlr_map_io_pmr(ctrlr, &rt_size);
    1093                 :          4 :         CU_ASSERT(mem_reg_addr == NULL);
    1094                 :          4 :         CU_ASSERT(rt_size == 0);
    1095                 :            : 
    1096                 :            :         /* PMR is less than 4MiB in size then abort PMR mapping  */
    1097                 :          4 :         map_io_pmr_init(&pctrlr, &pmrcap);
    1098                 :          4 :         pctrlr.pmr.size = (1ULL << 20);
    1099                 :            : 
    1100                 :          4 :         mem_reg_addr = nvme_pcie_ctrlr_map_io_pmr(ctrlr, &rt_size);
    1101                 :          4 :         CU_ASSERT(mem_reg_addr == NULL);
    1102                 :          4 :         CU_ASSERT(rt_size == 0);
    1103                 :            : 
    1104                 :            :         /* All parameters success */
    1105                 :          4 :         map_io_pmr_init(&pctrlr, &pmrcap);
    1106                 :            : 
    1107                 :          4 :         mem_reg_addr = nvme_pcie_ctrlr_map_io_pmr(ctrlr, &rt_size);
    1108                 :          4 :         CU_ASSERT(mem_reg_addr == (void *)0x7F7C01000000);
    1109                 :          4 :         CU_ASSERT(rt_size == 0x1FE00000);
    1110                 :          4 : }
    1111                 :            : 
    1112                 :            : int
    1113                 :          4 : main(int argc, char **argv)
    1114                 :            : {
    1115                 :          4 :         CU_pSuite       suite = NULL;
    1116                 :            :         unsigned int    num_failures;
    1117                 :            : 
    1118                 :          4 :         CU_initialize_registry();
    1119                 :            : 
    1120                 :          4 :         suite = CU_add_suite("nvme_pcie", NULL, NULL);
    1121                 :          4 :         CU_ADD_TEST(suite, test_prp_list_append);
    1122                 :          4 :         CU_ADD_TEST(suite, test_nvme_pcie_hotplug_monitor);
    1123                 :          4 :         CU_ADD_TEST(suite, test_shadow_doorbell_update);
    1124                 :          4 :         CU_ADD_TEST(suite, test_build_contig_hw_sgl_request);
    1125                 :          4 :         CU_ADD_TEST(suite, test_nvme_pcie_qpair_build_metadata);
    1126                 :          4 :         CU_ADD_TEST(suite, test_nvme_pcie_qpair_build_prps_sgl_request);
    1127                 :          4 :         CU_ADD_TEST(suite, test_nvme_pcie_qpair_build_hw_sgl_request);
    1128                 :          4 :         CU_ADD_TEST(suite, test_nvme_pcie_qpair_build_contig_request);
    1129                 :          4 :         CU_ADD_TEST(suite, test_nvme_pcie_ctrlr_regs_get_set);
    1130                 :          4 :         CU_ADD_TEST(suite, test_nvme_pcie_ctrlr_map_unmap_cmb);
    1131                 :          4 :         CU_ADD_TEST(suite, test_nvme_pcie_ctrlr_map_io_cmb);
    1132                 :          4 :         CU_ADD_TEST(suite, test_nvme_pcie_ctrlr_map_unmap_pmr);
    1133                 :          4 :         CU_ADD_TEST(suite, test_nvme_pcie_ctrlr_config_pmr);
    1134                 :          4 :         CU_ADD_TEST(suite, test_nvme_pcie_ctrlr_map_io_pmr);
    1135                 :            : 
    1136                 :          4 :         num_failures = spdk_ut_run_tests(argc, argv, NULL);
    1137                 :          4 :         CU_cleanup_registry();
    1138                 :          4 :         return num_failures;
    1139                 :            : }

Generated by: LCOV version 1.14