1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2019 Intel Corporation
5 #ifndef _VHOST_BLK_COMPAT_H_
6 #define _VHOST_BLK_COMPAT_H_
10 #include <linux/virtio_blk.h>
11 #include <linux/virtio_ring.h>
13 #include <rte_vhost.h>
14 #include "vhost_blk.h"
17 #define VHOST_MAX_VQUEUES 256
18 #define SPDK_VHOST_MAX_VQ_SIZE 1024
20 #define VHOST_USER_GET_CONFIG 24
21 #define VHOST_USER_SET_CONFIG 25
24 vhost_blk_get_config(struct vhost_block_dev *bdev, uint8_t *config,
27 struct virtio_blk_config blkcfg;
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
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
47 blk_size = bdev->blocklen;
48 blkcnt = bdev->blockcnt;
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;
60 fprintf(stdout, "block device:blk_size = %d, blkcnt = %"PRIx64"\n",
63 memcpy(config, &blkcfg, RTE_MIN(len, sizeof(blkcfg)));
68 static enum rte_vhost_msg_result
69 extern_vhost_pre_msg_handler(int vid, void *_msg)
72 struct vhost_blk_ctrlr *ctrlr;
73 struct vhost_user_msg *msg = _msg;
76 ret = rte_vhost_get_ifname(vid, path, PATH_MAX);
78 fprintf(stderr, "Cannot get socket name\n");
82 ctrlr = vhost_blk_ctrlr_find(path);
84 fprintf(stderr, "Controller is not ready\n");
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:
97 case VHOST_USER_GET_CONFIG: {
100 rc = vhost_blk_get_config(ctrlr->bdev,
101 msg->payload.cfg.region,
102 msg->payload.cfg.size);
106 return RTE_VHOST_MSG_RESULT_REPLY;
108 case VHOST_USER_SET_CONFIG:
113 return RTE_VHOST_MSG_RESULT_NOT_HANDLED;
116 static enum rte_vhost_msg_result
117 extern_vhost_post_msg_handler(int vid, void *_msg)
120 struct vhost_blk_ctrlr *ctrlr;
121 struct vhost_user_msg *msg = _msg;
124 ret = rte_vhost_get_ifname(vid, path, PATH_MAX);
126 fprintf(stderr, "Cannot get socket name\n");
130 ctrlr = vhost_blk_ctrlr_find(path);
132 fprintf(stderr, "Controller is not ready\n");
136 switch (msg->request) {
137 case VHOST_USER_SET_FEATURES:
138 case VHOST_USER_SET_VRING_KICK:
143 return RTE_VHOST_MSG_RESULT_NOT_HANDLED;
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,
152 vhost_session_install_rte_compat_hooks(uint32_t vid)
156 rc = rte_vhost_extern_callback_register(vid, &g_extern_vhost_ops, NULL);
159 "rte_vhost_extern_callback_register() failed for vid = %d\n",
164 vhost_dev_install_rte_compat_hooks(const char *path)
166 uint64_t protocol_features = 0;
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);