1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/stdinc.h" 35 36 #include "CUnit/Basic.h" 37 #include "spdk_cunit.h" 38 #include "spdk_internal/mock.h" 39 40 #include "vhost.c" 41 42 DEFINE_STUB(rte_vhost_driver_unregister, int, (const char *path), 0); 43 DEFINE_STUB(spdk_event_allocate, struct spdk_event *, 44 (uint32_t lcore, spdk_event_fn fn, void *arg1, void *arg2), NULL); 45 DEFINE_STUB(spdk_mem_register, int, (void *vaddr, size_t len), 0); 46 DEFINE_STUB(spdk_mem_unregister, int, (void *vaddr, size_t len), 0); 47 DEFINE_STUB(spdk_vtophys, uint64_t, (void *vaddr), 1); 48 DEFINE_STUB(spdk_iommu_mem_register, int, (uint64_t addr, uint64_t len), 0); 49 DEFINE_STUB(spdk_app_get_core_mask, uint64_t, (void), 0); 50 DEFINE_STUB_V(spdk_app_stop, (int rc)); 51 DEFINE_STUB_V(spdk_event_call, (struct spdk_event *event)); 52 DEFINE_STUB(spdk_iommu_mem_unregister, int, (uint64_t addr, uint64_t len), 0); 53 DEFINE_STUB(rte_vhost_get_mem_table, int, (int vid, struct rte_vhost_memory **mem), 0); 54 DEFINE_STUB(rte_vhost_get_negotiated_features, int, (int vid, uint64_t *features), 0); 55 DEFINE_STUB(rte_vhost_get_vhost_vring, int, 56 (int vid, uint16_t vring_idx, struct rte_vhost_vring *vring), 0); 57 DEFINE_STUB(rte_vhost_enable_guest_notification, int, 58 (int vid, uint16_t queue_id, int enable), 0); 59 DEFINE_STUB(rte_vhost_get_ifname, int, (int vid, char *buf, size_t len), 0); 60 DEFINE_STUB(rte_vhost_get_vring_num, uint16_t, (int vid), 0); 61 DEFINE_STUB(rte_vhost_driver_start, int, (const char *name), 0); 62 DEFINE_STUB(rte_vhost_driver_callback_register, int, 63 (const char *path, struct vhost_device_ops const *const ops), 0); 64 DEFINE_STUB(rte_vhost_driver_disable_features, int, (const char *path, uint64_t features), 0); 65 DEFINE_STUB(rte_vhost_driver_set_features, int, (const char *path, uint64_t features), 0); 66 DEFINE_STUB(rte_vhost_driver_register, int, (const char *path, uint64_t flags), 0); 67 DEFINE_STUB(spdk_vhost_scsi_controller_construct, int, (void), 0); 68 DEFINE_STUB(spdk_vhost_blk_controller_construct, int, (void), 0); 69 DEFINE_STUB(rte_vhost_set_vhost_vring_last_idx, int, 70 (int vid, uint16_t vring_idx, uint16_t last_avail_idx, uint16_t last_used_idx), 0); 71 72 static int 73 test_setup(void) 74 { 75 return 0; 76 } 77 78 static struct spdk_vhost_dev * 79 alloc_vdev(void) 80 { 81 struct spdk_vhost_dev *vdev = NULL; 82 int rc; 83 84 /* spdk_vhost_dev must be allocated on a cache line boundary. */ 85 rc = posix_memalign((void **)&vdev, 64, sizeof(*vdev)); 86 CU_ASSERT(rc == 0); 87 SPDK_CU_ASSERT_FATAL(vdev != NULL); 88 89 vdev->mem = calloc(1, sizeof(*vdev->mem) + 2 * sizeof(struct rte_vhost_mem_region)); 90 SPDK_CU_ASSERT_FATAL(vdev->mem != NULL); 91 vdev->mem->nregions = 2; 92 vdev->mem->regions[0].guest_phys_addr = 0; 93 vdev->mem->regions[0].size = 0x400000; /* 4 MB */ 94 vdev->mem->regions[0].host_user_addr = 0x1000000; 95 vdev->mem->regions[1].guest_phys_addr = 0x400000; 96 vdev->mem->regions[1].size = 0x400000; /* 4 MB */ 97 vdev->mem->regions[1].host_user_addr = 0x2000000; 98 99 return vdev; 100 } 101 102 static void 103 free_vdev(struct spdk_vhost_dev *vdev) 104 { 105 free(vdev->mem); 106 free(vdev); 107 } 108 109 static void 110 desc_to_iov_test(void) 111 { 112 struct spdk_vhost_dev *vdev; 113 struct iovec iov[SPDK_VHOST_IOVS_MAX]; 114 uint16_t iov_index; 115 struct vring_desc desc; 116 int rc; 117 118 vdev = alloc_vdev(); 119 120 /* Test simple case where iov falls fully within a 2MB page. */ 121 desc.addr = 0x110000; 122 desc.len = 0x1000; 123 iov_index = 0; 124 rc = spdk_vhost_vring_desc_to_iov(vdev, iov, &iov_index, &desc); 125 CU_ASSERT(rc == 0); 126 CU_ASSERT(iov_index == 1); 127 CU_ASSERT(iov[0].iov_base == (void *)0x1110000); 128 CU_ASSERT(iov[0].iov_len == 0x1000); 129 /* 130 * Always memset the iov to ensure each test validates data written by its call 131 * to the function under test. 132 */ 133 memset(iov, 0, sizeof(iov)); 134 135 /* Same test, but ensure it respects the non-zero starting iov_index. */ 136 iov_index = SPDK_VHOST_IOVS_MAX - 1; 137 rc = spdk_vhost_vring_desc_to_iov(vdev, iov, &iov_index, &desc); 138 CU_ASSERT(rc == 0); 139 CU_ASSERT(iov_index == SPDK_VHOST_IOVS_MAX); 140 CU_ASSERT(iov[SPDK_VHOST_IOVS_MAX - 1].iov_base == (void *)0x1110000); 141 CU_ASSERT(iov[SPDK_VHOST_IOVS_MAX - 1].iov_len == 0x1000); 142 memset(iov, 0, sizeof(iov)); 143 144 /* Test for failure if iov_index already equals SPDK_VHOST_IOVS_MAX. */ 145 iov_index = SPDK_VHOST_IOVS_MAX; 146 rc = spdk_vhost_vring_desc_to_iov(vdev, iov, &iov_index, &desc); 147 CU_ASSERT(rc != 0); 148 memset(iov, 0, sizeof(iov)); 149 150 /* Test case where iov spans a 2MB boundary, but does not span a vhost memory region. */ 151 desc.addr = 0x1F0000; 152 desc.len = 0x20000; 153 iov_index = 0; 154 rc = spdk_vhost_vring_desc_to_iov(vdev, iov, &iov_index, &desc); 155 CU_ASSERT(rc == 0); 156 CU_ASSERT(iov_index == 2); 157 CU_ASSERT(iov[0].iov_base == (void *)0x11F0000); 158 CU_ASSERT(iov[0].iov_len == 0x10000); 159 CU_ASSERT(iov[1].iov_base == (void *)0x1200000); 160 CU_ASSERT(iov[1].iov_len == 0x10000); 161 memset(iov, 0, sizeof(iov)); 162 163 /* Same test, but ensure it respects the non-zero starting iov_index. */ 164 iov_index = SPDK_VHOST_IOVS_MAX - 2; 165 rc = spdk_vhost_vring_desc_to_iov(vdev, iov, &iov_index, &desc); 166 CU_ASSERT(rc == 0); 167 CU_ASSERT(iov_index == SPDK_VHOST_IOVS_MAX); 168 CU_ASSERT(iov[SPDK_VHOST_IOVS_MAX - 2].iov_base == (void *)0x11F0000); 169 CU_ASSERT(iov[SPDK_VHOST_IOVS_MAX - 2].iov_len == 0x10000); 170 CU_ASSERT(iov[SPDK_VHOST_IOVS_MAX - 1].iov_base == (void *)0x1200000); 171 CU_ASSERT(iov[SPDK_VHOST_IOVS_MAX - 1].iov_len == 0x10000); 172 memset(iov, 0, sizeof(iov)); 173 174 /* 175 * This test should fail. The first part of the descriptor will fit in the last 176 * iov, but the part after the 2MB boundary would overflow. 177 */ 178 iov_index = SPDK_VHOST_IOVS_MAX - 1; 179 rc = spdk_vhost_vring_desc_to_iov(vdev, iov, &iov_index, &desc); 180 CU_ASSERT(rc != 0); 181 memset(iov, 0, sizeof(iov)); 182 183 /* Test case where iov spans a vhost memory region. */ 184 desc.addr = 0x3F0000; 185 desc.len = 0x20000; 186 iov_index = 0; 187 rc = spdk_vhost_vring_desc_to_iov(vdev, iov, &iov_index, &desc); 188 CU_ASSERT(rc == 0); 189 CU_ASSERT(iov_index == 2); 190 CU_ASSERT(iov[0].iov_base == (void *)0x13F0000); 191 CU_ASSERT(iov[0].iov_len == 0x10000); 192 CU_ASSERT(iov[1].iov_base == (void *)0x2000000); 193 CU_ASSERT(iov[1].iov_len == 0x10000); 194 memset(iov, 0, sizeof(iov)); 195 196 free_vdev(vdev); 197 198 CU_ASSERT(true); 199 } 200 201 int 202 main(int argc, char **argv) 203 { 204 CU_pSuite suite = NULL; 205 unsigned int num_failures; 206 207 if (CU_initialize_registry() != CUE_SUCCESS) { 208 return CU_get_error(); 209 } 210 211 suite = CU_add_suite("vhost_suite", test_setup, NULL); 212 if (suite == NULL) { 213 CU_cleanup_registry(); 214 return CU_get_error(); 215 } 216 217 if ( 218 CU_add_test(suite, "desc_to_iov", desc_to_iov_test) == NULL 219 ) { 220 CU_cleanup_registry(); 221 return CU_get_error(); 222 } 223 224 CU_basic_set_mode(CU_BRM_VERBOSE); 225 CU_basic_run_tests(); 226 num_failures = CU_get_number_of_failures(); 227 CU_cleanup_registry(); 228 229 return num_failures; 230 } 231