1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2021 Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk_internal/cunit.h" 7 #include "spdk_internal/mock.h" 8 #include "spdk_internal/idxd.h" 9 #include "common/lib/test_env.c" 10 11 #include "idxd/idxd_user.c" 12 13 #define FAKE_REG_SIZE 0x1000 14 #define GRP_CFG_OFFSET (0x800 / IDXD_TABLE_OFFSET_MULT) 15 #define MAX_TOKENS 0x40 16 #define MAX_ARRAY_SIZE 0x20 17 18 SPDK_LOG_REGISTER_COMPONENT(idxd); 19 20 DEFINE_STUB(spdk_pci_idxd_get_driver, struct spdk_pci_driver *, (void), NULL); 21 DEFINE_STUB_V(idxd_impl_register, (struct spdk_idxd_impl *impl)); 22 DEFINE_STUB_V(spdk_pci_device_detach, (struct spdk_pci_device *device)); 23 DEFINE_STUB(spdk_pci_device_claim, int, (struct spdk_pci_device *dev), 0); 24 DEFINE_STUB(spdk_pci_device_get_device_id, uint16_t, (struct spdk_pci_device *dev), 0); 25 DEFINE_STUB(spdk_pci_device_get_vendor_id, uint16_t, (struct spdk_pci_device *dev), 0); 26 27 struct spdk_pci_addr 28 spdk_pci_device_get_addr(struct spdk_pci_device *pci_dev) 29 { 30 struct spdk_pci_addr pci_addr; 31 32 memset(&pci_addr, 0, sizeof(pci_addr)); 33 return pci_addr; 34 } 35 36 int 37 spdk_pci_enumerate(struct spdk_pci_driver *driver, spdk_pci_enum_cb enum_cb, void *enum_ctx) 38 { 39 return -1; 40 } 41 42 int 43 spdk_pci_device_map_bar(struct spdk_pci_device *dev, uint32_t bar, 44 void **mapped_addr, uint64_t *phys_addr, uint64_t *size) 45 { 46 *mapped_addr = NULL; 47 *phys_addr = 0; 48 *size = 0; 49 return 0; 50 } 51 52 int 53 spdk_pci_device_unmap_bar(struct spdk_pci_device *dev, uint32_t bar, void *addr) 54 { 55 return 0; 56 } 57 58 int 59 spdk_pci_device_cfg_read32(struct spdk_pci_device *dev, uint32_t *value, 60 uint32_t offset) 61 { 62 *value = 0xFFFFFFFFu; 63 return 0; 64 } 65 66 int 67 spdk_pci_device_cfg_write32(struct spdk_pci_device *dev, uint32_t value, 68 uint32_t offset) 69 { 70 return 0; 71 } 72 73 #define WQ_CFG_OFFSET (0x800 / IDXD_TABLE_OFFSET_MULT) 74 #define TOTAL_WQE_SIZE 0x40 75 #define LOG2_WQ_MAX_BATCH 5 76 static int 77 test_idxd_wq_config(void) 78 { 79 struct spdk_user_idxd_device user_idxd = {}; 80 uint32_t wq_size, i, j; 81 int rc; 82 union idxd_wqcfg *wqcfg; 83 84 user_idxd.registers = calloc(1, FAKE_REG_SIZE); 85 SPDK_CU_ASSERT_FATAL(user_idxd.registers != NULL); 86 87 user_idxd.registers->wqcap.total_wq_size = TOTAL_WQE_SIZE; 88 user_idxd.registers->wqcap.num_wqs = 1; 89 user_idxd.registers->gencap.max_batch_shift = LOG2_WQ_MAX_BATCH; 90 user_idxd.registers->gencap.max_xfer_shift = LOG2_WQ_MAX_XFER; 91 user_idxd.registers->offsets.wqcfg = WQ_CFG_OFFSET; 92 wq_size = user_idxd.registers->wqcap.total_wq_size; 93 94 wqcfg = (union idxd_wqcfg *)((uint8_t *)user_idxd.registers + 95 (user_idxd.registers->offsets.wqcfg * IDXD_TABLE_OFFSET_MULT)); 96 97 rc = idxd_wq_config(&user_idxd); 98 CU_ASSERT(rc == 0); 99 CU_ASSERT(wqcfg->wq_size == wq_size); 100 CU_ASSERT(wqcfg->mode == WQ_MODE_DEDICATED); 101 CU_ASSERT(wqcfg->max_batch_shift == LOG2_WQ_MAX_BATCH); 102 CU_ASSERT(wqcfg->max_xfer_shift == LOG2_WQ_MAX_XFER); 103 CU_ASSERT(wqcfg->wq_state == WQ_ENABLED); 104 CU_ASSERT(wqcfg->priority == WQ_PRIORITY_1); 105 106 for (i = 1; i < user_idxd.registers->wqcap.num_wqs; i++) { 107 for (j = 0 ; j < (sizeof(union idxd_wqcfg) / sizeof(uint32_t)); j++) { 108 CU_ASSERT(spdk_mmio_read_4(&wqcfg->raw[j]) == 0); 109 } 110 } 111 112 free(user_idxd.registers); 113 114 return 0; 115 } 116 117 static int 118 test_idxd_group_config(void) 119 { 120 struct spdk_user_idxd_device user_idxd = {}; 121 uint64_t wqs[MAX_ARRAY_SIZE] = {}; 122 uint64_t engines[MAX_ARRAY_SIZE] = {}; 123 union idxd_group_flags flags[MAX_ARRAY_SIZE] = {}; 124 int rc, i; 125 struct idxd_grptbl *grptbl; 126 127 user_idxd.registers = calloc(1, FAKE_REG_SIZE); 128 SPDK_CU_ASSERT_FATAL(user_idxd.registers != NULL); 129 130 user_idxd.registers->groupcap.num_groups = 1; 131 user_idxd.registers->enginecap.num_engines = 4; 132 user_idxd.registers->wqcap.num_wqs = 1; 133 user_idxd.registers->groupcap.read_bufs = MAX_TOKENS; 134 user_idxd.registers->offsets.grpcfg = GRP_CFG_OFFSET; 135 136 grptbl = (struct idxd_grptbl *)((uint8_t *)user_idxd.registers + 137 (user_idxd.registers->offsets.grpcfg * IDXD_TABLE_OFFSET_MULT)); 138 139 rc = idxd_group_config(&user_idxd); 140 CU_ASSERT(rc == 0); 141 for (i = 0 ; i < user_idxd.registers->groupcap.num_groups; i++) { 142 wqs[i] = spdk_mmio_read_8(&grptbl->group[i].wqs[0]); 143 engines[i] = spdk_mmio_read_8(&grptbl->group[i].engines); 144 flags[i].raw = spdk_mmio_read_4(&grptbl->group[i].flags.raw); 145 } 146 /* wqe and engine arrays are indexed by group id and are bitmaps of assigned elements. */ 147 CU_ASSERT(wqs[0] == 0x1); 148 CU_ASSERT(engines[0] == 0xf); 149 CU_ASSERT(flags[0].read_buffers_allowed == MAX_TOKENS); 150 151 /* groups allocated by code under test. */ 152 free(user_idxd.registers); 153 154 return 0; 155 } 156 157 static int 158 test_idxd_reset_dev(void) 159 { 160 struct spdk_user_idxd_device user_idxd = {}; 161 union idxd_cmdsts_register *fake_cmd_status_reg; 162 int rc; 163 164 user_idxd.registers = calloc(1, FAKE_REG_SIZE); 165 SPDK_CU_ASSERT_FATAL(user_idxd.registers != NULL); 166 fake_cmd_status_reg = &user_idxd.registers->cmdsts; 167 168 /* Test happy path */ 169 rc = idxd_reset_dev(&user_idxd); 170 CU_ASSERT(rc == 0); 171 172 /* Test error reported path */ 173 fake_cmd_status_reg->err = 1; 174 rc = idxd_reset_dev(&user_idxd); 175 CU_ASSERT(rc == -EINVAL); 176 177 free(user_idxd.registers); 178 179 return 0; 180 } 181 182 static int 183 test_idxd_wait_cmd(void) 184 { 185 struct spdk_user_idxd_device user_idxd = {}; 186 int timeout = 1; 187 union idxd_cmdsts_register *fake_cmd_status_reg; 188 int rc; 189 190 user_idxd.registers = calloc(1, FAKE_REG_SIZE); 191 SPDK_CU_ASSERT_FATAL(user_idxd.registers != NULL); 192 fake_cmd_status_reg = &user_idxd.registers->cmdsts; 193 194 /* Test happy path. */ 195 rc = idxd_wait_cmd(&user_idxd, timeout); 196 CU_ASSERT(rc == 0); 197 198 /* Setup up our fake register to set the error bit. */ 199 fake_cmd_status_reg->err = 1; 200 rc = idxd_wait_cmd(&user_idxd, timeout); 201 CU_ASSERT(rc == -EINVAL); 202 fake_cmd_status_reg->err = 0; 203 204 /* Setup up our fake register to set the active bit. */ 205 fake_cmd_status_reg->active = 1; 206 rc = idxd_wait_cmd(&user_idxd, timeout); 207 CU_ASSERT(rc == -EBUSY); 208 209 free(user_idxd.registers); 210 211 return 0; 212 } 213 214 int 215 main(int argc, char **argv) 216 { 217 CU_pSuite suite = NULL; 218 unsigned int num_failures; 219 220 CU_initialize_registry(); 221 222 suite = CU_add_suite("idxd_user", NULL, NULL); 223 224 CU_ADD_TEST(suite, test_idxd_wait_cmd); 225 CU_ADD_TEST(suite, test_idxd_reset_dev); 226 CU_ADD_TEST(suite, test_idxd_group_config); 227 CU_ADD_TEST(suite, test_idxd_wq_config); 228 229 num_failures = spdk_ut_run_tests(argc, argv, NULL); 230 CU_cleanup_registry(); 231 return num_failures; 232 } 233