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 static int 76 test_idxd_wq_config(void) 77 { 78 struct spdk_user_idxd_device user_idxd = {}; 79 uint32_t wq_size, i, j; 80 int rc; 81 union idxd_wqcfg *wqcfg; 82 83 user_idxd.registers = calloc(1, FAKE_REG_SIZE); 84 SPDK_CU_ASSERT_FATAL(user_idxd.registers != NULL); 85 86 user_idxd.registers->wqcap.total_wq_size = TOTAL_WQE_SIZE; 87 user_idxd.registers->wqcap.num_wqs = 1; 88 user_idxd.registers->gencap.max_batch_shift = LOG2_WQ_MAX_BATCH; 89 user_idxd.registers->gencap.max_xfer_shift = LOG2_WQ_MAX_XFER; 90 user_idxd.registers->offsets.wqcfg = WQ_CFG_OFFSET; 91 wq_size = user_idxd.registers->wqcap.total_wq_size; 92 93 wqcfg = (union idxd_wqcfg *)((uint8_t *)user_idxd.registers + 94 (user_idxd.registers->offsets.wqcfg * IDXD_TABLE_OFFSET_MULT)); 95 96 rc = idxd_wq_config(&user_idxd); 97 CU_ASSERT(rc == 0); 98 CU_ASSERT(wqcfg->wq_size == wq_size); 99 CU_ASSERT(wqcfg->mode == WQ_MODE_DEDICATED); 100 CU_ASSERT(wqcfg->max_batch_shift == LOG2_WQ_MAX_BATCH); 101 CU_ASSERT(wqcfg->max_xfer_shift == LOG2_WQ_MAX_XFER); 102 CU_ASSERT(wqcfg->wq_state == WQ_ENABLED); 103 CU_ASSERT(wqcfg->priority == WQ_PRIORITY_1); 104 105 for (i = 1; i < user_idxd.registers->wqcap.num_wqs; i++) { 106 for (j = 0 ; j < (sizeof(union idxd_wqcfg) / sizeof(uint32_t)); j++) { 107 CU_ASSERT(spdk_mmio_read_4(&wqcfg->raw[j]) == 0); 108 } 109 } 110 111 free(user_idxd.registers); 112 113 return 0; 114 } 115 116 static int 117 test_idxd_group_config(void) 118 { 119 struct spdk_user_idxd_device user_idxd = {}; 120 uint64_t wqs[MAX_ARRAY_SIZE] = {}; 121 uint64_t engines[MAX_ARRAY_SIZE] = {}; 122 union idxd_group_flags flags[MAX_ARRAY_SIZE] = {}; 123 int rc, i; 124 struct idxd_grptbl *grptbl; 125 126 user_idxd.registers = calloc(1, FAKE_REG_SIZE); 127 SPDK_CU_ASSERT_FATAL(user_idxd.registers != NULL); 128 129 user_idxd.registers->groupcap.num_groups = 1; 130 user_idxd.registers->enginecap.num_engines = 4; 131 user_idxd.registers->wqcap.num_wqs = 1; 132 user_idxd.registers->groupcap.read_bufs = MAX_TOKENS; 133 user_idxd.registers->offsets.grpcfg = GRP_CFG_OFFSET; 134 135 grptbl = (struct idxd_grptbl *)((uint8_t *)user_idxd.registers + 136 (user_idxd.registers->offsets.grpcfg * IDXD_TABLE_OFFSET_MULT)); 137 138 rc = idxd_group_config(&user_idxd); 139 CU_ASSERT(rc == 0); 140 for (i = 0 ; i < user_idxd.registers->groupcap.num_groups; i++) { 141 wqs[i] = spdk_mmio_read_8(&grptbl->group[i].wqs[0]); 142 engines[i] = spdk_mmio_read_8(&grptbl->group[i].engines); 143 flags[i].raw = spdk_mmio_read_4(&grptbl->group[i].flags.raw); 144 } 145 /* wqe and engine arrays are indexed by group id and are bitmaps of assigned elements. */ 146 CU_ASSERT(wqs[0] == 0x1); 147 CU_ASSERT(engines[0] == 0xf); 148 CU_ASSERT(flags[0].read_buffers_allowed == MAX_TOKENS); 149 150 /* groups allocated by code under test. */ 151 free(user_idxd.registers); 152 153 return 0; 154 } 155 156 static int 157 test_idxd_reset_dev(void) 158 { 159 struct spdk_user_idxd_device user_idxd = {}; 160 union idxd_cmdsts_register *fake_cmd_status_reg; 161 int rc; 162 163 user_idxd.registers = calloc(1, FAKE_REG_SIZE); 164 SPDK_CU_ASSERT_FATAL(user_idxd.registers != NULL); 165 fake_cmd_status_reg = &user_idxd.registers->cmdsts; 166 167 /* Test happy path */ 168 rc = idxd_reset_dev(&user_idxd); 169 CU_ASSERT(rc == 0); 170 171 /* Test error reported path */ 172 fake_cmd_status_reg->err = 1; 173 rc = idxd_reset_dev(&user_idxd); 174 CU_ASSERT(rc == -EINVAL); 175 176 free(user_idxd.registers); 177 178 return 0; 179 } 180 181 static int 182 test_idxd_wait_cmd(void) 183 { 184 struct spdk_user_idxd_device user_idxd = {}; 185 int timeout = 1; 186 union idxd_cmdsts_register *fake_cmd_status_reg; 187 int rc; 188 189 user_idxd.registers = calloc(1, FAKE_REG_SIZE); 190 SPDK_CU_ASSERT_FATAL(user_idxd.registers != NULL); 191 fake_cmd_status_reg = &user_idxd.registers->cmdsts; 192 193 /* Test happy path. */ 194 rc = idxd_wait_cmd(&user_idxd, timeout); 195 CU_ASSERT(rc == 0); 196 197 /* Setup up our fake register to set the error bit. */ 198 fake_cmd_status_reg->err = 1; 199 rc = idxd_wait_cmd(&user_idxd, timeout); 200 CU_ASSERT(rc == -EINVAL); 201 fake_cmd_status_reg->err = 0; 202 203 /* Setup up our fake register to set the active bit. */ 204 fake_cmd_status_reg->active = 1; 205 rc = idxd_wait_cmd(&user_idxd, timeout); 206 CU_ASSERT(rc == -EBUSY); 207 208 free(user_idxd.registers); 209 210 return 0; 211 } 212 213 int 214 main(int argc, char **argv) 215 { 216 CU_pSuite suite = NULL; 217 unsigned int num_failures; 218 219 CU_initialize_registry(); 220 221 suite = CU_add_suite("idxd_user", NULL, NULL); 222 223 CU_ADD_TEST(suite, test_idxd_wait_cmd); 224 CU_ADD_TEST(suite, test_idxd_reset_dev); 225 CU_ADD_TEST(suite, test_idxd_group_config); 226 CU_ADD_TEST(suite, test_idxd_wq_config); 227 228 num_failures = spdk_ut_run_tests(argc, argv, NULL); 229 CU_cleanup_registry(); 230 return num_failures; 231 } 232