1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2019 Intel Corporation 3 */ 4 5 #ifndef _VHOST_BLK_COMPAT_H_ 6 #define _VHOST_BLK_COMPAT_H_ 7 8 #include <sys/uio.h> 9 #include <stdint.h> 10 #include <linux/virtio_blk.h> 11 #include <linux/virtio_ring.h> 12 13 #include <rte_vhost.h> 14 #include "vhost_blk.h" 15 #include "blk_spec.h" 16 17 #define VHOST_MAX_VQUEUES 256 18 #define SPDK_VHOST_MAX_VQ_SIZE 1024 19 20 #define VHOST_USER_GET_CONFIG 24 21 #define VHOST_USER_SET_CONFIG 25 22 23 static int 24 vhost_blk_get_config(struct vhost_block_dev *bdev, uint8_t *config, 25 uint32_t len) 26 { 27 struct virtio_blk_config blkcfg; 28 uint32_t blk_size; 29 uint64_t blkcnt; 30 31 if (bdev == NULL) { 32 /* We can't just return -1 here as this GET_CONFIG message might 33 * be caused by a QEMU VM reboot. Returning -1 will indicate an 34 * error to QEMU, who might then decide to terminate itself. 35 * We don't want that. A simple reboot shouldn't break the 36 * system. 37 * 38 * Presenting a block device with block size 0 and block count 0 39 * doesn't cause any problems on QEMU side and the virtio-pci 40 * device is even still available inside the VM, but there will 41 * be no block device created for it - the kernel drivers will 42 * silently reject it. 43 */ 44 blk_size = 0; 45 blkcnt = 0; 46 } else { 47 blk_size = bdev->blocklen; 48 blkcnt = bdev->blockcnt; 49 } 50 51 memset(&blkcfg, 0, sizeof(blkcfg)); 52 blkcfg.blk_size = blk_size; 53 /* minimum I/O size in blocks */ 54 blkcfg.min_io_size = 1; 55 /* expressed in 512 Bytes sectors */ 56 blkcfg.capacity = (blkcnt * blk_size) / 512; 57 /* QEMU can overwrite this value when started */ 58 blkcfg.num_queues = VHOST_MAX_VQUEUES; 59 60 fprintf(stdout, "block device:blk_size = %d, blkcnt = %"PRIx64"\n", 61 blk_size, blkcnt); 62 63 memcpy(config, &blkcfg, RTE_MIN(len, sizeof(blkcfg))); 64 65 return 0; 66 } 67 68 static enum rte_vhost_msg_result 69 extern_vhost_pre_msg_handler(int vid, void *_msg) 70 { 71 char path[PATH_MAX]; 72 struct vhost_blk_ctrlr *ctrlr; 73 struct vhost_user_msg *msg = _msg; 74 int ret; 75 76 ret = rte_vhost_get_ifname(vid, path, PATH_MAX); 77 if (ret) { 78 fprintf(stderr, "Cannot get socket name\n"); 79 return -1; 80 } 81 82 ctrlr = vhost_blk_ctrlr_find(path); 83 if (!ctrlr) { 84 fprintf(stderr, "Controller is not ready\n"); 85 return -1; 86 } 87 88 switch ((int)msg->request) { 89 case VHOST_USER_GET_VRING_BASE: 90 case VHOST_USER_SET_VRING_BASE: 91 case VHOST_USER_SET_VRING_ADDR: 92 case VHOST_USER_SET_VRING_NUM: 93 case VHOST_USER_SET_VRING_KICK: 94 case VHOST_USER_SET_VRING_CALL: 95 case VHOST_USER_SET_MEM_TABLE: 96 break; 97 case VHOST_USER_GET_CONFIG: { 98 int rc = 0; 99 100 rc = vhost_blk_get_config(ctrlr->bdev, 101 msg->payload.cfg.region, 102 msg->payload.cfg.size); 103 if (rc != 0) 104 msg->size = 0; 105 106 return RTE_VHOST_MSG_RESULT_REPLY; 107 } 108 case VHOST_USER_SET_CONFIG: 109 default: 110 break; 111 } 112 113 return RTE_VHOST_MSG_RESULT_NOT_HANDLED; 114 } 115 116 static enum rte_vhost_msg_result 117 extern_vhost_post_msg_handler(int vid, void *_msg) 118 { 119 char path[PATH_MAX]; 120 struct vhost_blk_ctrlr *ctrlr; 121 struct vhost_user_msg *msg = _msg; 122 int ret; 123 124 ret = rte_vhost_get_ifname(vid, path, PATH_MAX); 125 if (ret) { 126 fprintf(stderr, "Cannot get socket name\n"); 127 return -1; 128 } 129 130 ctrlr = vhost_blk_ctrlr_find(path); 131 if (!ctrlr) { 132 fprintf(stderr, "Controller is not ready\n"); 133 return -1; 134 } 135 136 switch (msg->request) { 137 case VHOST_USER_SET_FEATURES: 138 case VHOST_USER_SET_VRING_KICK: 139 default: 140 break; 141 } 142 143 return RTE_VHOST_MSG_RESULT_NOT_HANDLED; 144 } 145 146 struct rte_vhost_user_extern_ops g_extern_vhost_ops = { 147 .pre_msg_handle = extern_vhost_pre_msg_handler, 148 .post_msg_handle = extern_vhost_post_msg_handler, 149 }; 150 151 void 152 vhost_session_install_rte_compat_hooks(uint32_t vid) 153 { 154 int rc; 155 156 rc = rte_vhost_extern_callback_register(vid, &g_extern_vhost_ops, NULL); 157 if (rc != 0) 158 fprintf(stderr, 159 "rte_vhost_extern_callback_register() failed for vid = %d\n", 160 vid); 161 } 162 163 void 164 vhost_dev_install_rte_compat_hooks(const char *path) 165 { 166 uint64_t protocol_features = 0; 167 168 rte_vhost_driver_get_protocol_features(path, &protocol_features); 169 protocol_features |= (1ULL << VHOST_USER_PROTOCOL_F_CONFIG); 170 protocol_features |= (1ULL << VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD); 171 rte_vhost_driver_set_protocol_features(path, protocol_features); 172 } 173 174 #endif 175