1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * VDPA simulator for block device. 4 * 5 * Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. 6 * Copyright (c) 2021, Red Hat Inc. All rights reserved. 7 * 8 */ 9 10 #include <linux/init.h> 11 #include <linux/module.h> 12 #include <linux/device.h> 13 #include <linux/kernel.h> 14 #include <linux/blkdev.h> 15 #include <linux/vringh.h> 16 #include <linux/vdpa.h> 17 #include <uapi/linux/virtio_blk.h> 18 19 #include "vdpa_sim.h" 20 21 #define DRV_VERSION "0.1" 22 #define DRV_AUTHOR "Max Gurtovoy <mgurtovoy@nvidia.com>" 23 #define DRV_DESC "vDPA Device Simulator for block device" 24 #define DRV_LICENSE "GPL v2" 25 26 #define VDPASIM_BLK_FEATURES (VDPASIM_FEATURES | \ 27 (1ULL << VIRTIO_BLK_F_FLUSH) | \ 28 (1ULL << VIRTIO_BLK_F_SIZE_MAX) | \ 29 (1ULL << VIRTIO_BLK_F_SEG_MAX) | \ 30 (1ULL << VIRTIO_BLK_F_BLK_SIZE) | \ 31 (1ULL << VIRTIO_BLK_F_TOPOLOGY) | \ 32 (1ULL << VIRTIO_BLK_F_MQ) | \ 33 (1ULL << VIRTIO_BLK_F_DISCARD) | \ 34 (1ULL << VIRTIO_BLK_F_WRITE_ZEROES)) 35 36 #define VDPASIM_BLK_CAPACITY 0x40000 37 #define VDPASIM_BLK_SIZE_MAX 0x1000 38 #define VDPASIM_BLK_SEG_MAX 32 39 #define VDPASIM_BLK_DWZ_MAX_SECTORS UINT_MAX 40 41 /* 1 virtqueue, 1 address space, 1 virtqueue group */ 42 #define VDPASIM_BLK_VQ_NUM 1 43 #define VDPASIM_BLK_AS_NUM 1 44 #define VDPASIM_BLK_GROUP_NUM 1 45 46 struct vdpasim_blk { 47 struct vdpasim vdpasim; 48 void *buffer; 49 bool shared_backend; 50 }; 51 52 static struct vdpasim_blk *sim_to_blk(struct vdpasim *vdpasim) 53 { 54 return container_of(vdpasim, struct vdpasim_blk, vdpasim); 55 } 56 57 static char vdpasim_blk_id[VIRTIO_BLK_ID_BYTES] = "vdpa_blk_sim"; 58 59 static bool shared_backend; 60 module_param(shared_backend, bool, 0444); 61 MODULE_PARM_DESC(shared_backend, "Enable the shared backend between virtio-blk devices"); 62 63 static void *shared_buffer; 64 /* mutex to synchronize shared_buffer access */ 65 static DEFINE_MUTEX(shared_buffer_mutex); 66 67 static void vdpasim_blk_buffer_lock(struct vdpasim_blk *blk) 68 { 69 if (blk->shared_backend) 70 mutex_lock(&shared_buffer_mutex); 71 } 72 73 static void vdpasim_blk_buffer_unlock(struct vdpasim_blk *blk) 74 { 75 if (blk->shared_backend) 76 mutex_unlock(&shared_buffer_mutex); 77 } 78 79 static bool vdpasim_blk_check_range(struct vdpasim *vdpasim, u64 start_sector, 80 u64 num_sectors, u64 max_sectors) 81 { 82 if (start_sector > VDPASIM_BLK_CAPACITY) { 83 dev_dbg(&vdpasim->vdpa.dev, 84 "starting sector exceeds the capacity - start: 0x%llx capacity: 0x%x\n", 85 start_sector, VDPASIM_BLK_CAPACITY); 86 } 87 88 if (num_sectors > max_sectors) { 89 dev_dbg(&vdpasim->vdpa.dev, 90 "number of sectors exceeds the max allowed in a request - num: 0x%llx max: 0x%llx\n", 91 num_sectors, max_sectors); 92 return false; 93 } 94 95 if (num_sectors > VDPASIM_BLK_CAPACITY - start_sector) { 96 dev_dbg(&vdpasim->vdpa.dev, 97 "request exceeds the capacity - start: 0x%llx num: 0x%llx capacity: 0x%x\n", 98 start_sector, num_sectors, VDPASIM_BLK_CAPACITY); 99 return false; 100 } 101 102 return true; 103 } 104 105 /* Returns 'true' if the request is handled (with or without an I/O error) 106 * and the status is correctly written in the last byte of the 'in iov', 107 * 'false' otherwise. 108 */ 109 static bool vdpasim_blk_handle_req(struct vdpasim *vdpasim, 110 struct vdpasim_virtqueue *vq) 111 { 112 struct vdpasim_blk *blk = sim_to_blk(vdpasim); 113 size_t pushed = 0, to_pull, to_push; 114 struct virtio_blk_outhdr hdr; 115 bool handled = false; 116 ssize_t bytes; 117 loff_t offset; 118 u64 sector; 119 u8 status; 120 u32 type; 121 int ret; 122 123 ret = vringh_getdesc_iotlb(&vq->vring, &vq->out_iov, &vq->in_iov, 124 &vq->head, GFP_ATOMIC); 125 if (ret != 1) 126 return false; 127 128 if (vq->out_iov.used < 1 || vq->in_iov.used < 1) { 129 dev_dbg(&vdpasim->vdpa.dev, "missing headers - out_iov: %u in_iov %u\n", 130 vq->out_iov.used, vq->in_iov.used); 131 goto err; 132 } 133 134 if (vq->in_iov.iov[vq->in_iov.used - 1].iov_len < 1) { 135 dev_dbg(&vdpasim->vdpa.dev, "request in header too short\n"); 136 goto err; 137 } 138 139 /* The last byte is the status and we checked if the last iov has 140 * enough room for it. 141 */ 142 to_push = vringh_kiov_length(&vq->in_iov) - 1; 143 144 to_pull = vringh_kiov_length(&vq->out_iov); 145 146 bytes = vringh_iov_pull_iotlb(&vq->vring, &vq->out_iov, &hdr, 147 sizeof(hdr)); 148 if (bytes != sizeof(hdr)) { 149 dev_dbg(&vdpasim->vdpa.dev, "request out header too short\n"); 150 goto err; 151 } 152 153 to_pull -= bytes; 154 155 type = vdpasim32_to_cpu(vdpasim, hdr.type); 156 sector = vdpasim64_to_cpu(vdpasim, hdr.sector); 157 offset = sector << SECTOR_SHIFT; 158 status = VIRTIO_BLK_S_OK; 159 160 if (type != VIRTIO_BLK_T_IN && type != VIRTIO_BLK_T_OUT && 161 sector != 0) { 162 dev_dbg(&vdpasim->vdpa.dev, 163 "sector must be 0 for %u request - sector: 0x%llx\n", 164 type, sector); 165 status = VIRTIO_BLK_S_IOERR; 166 goto err_status; 167 } 168 169 switch (type) { 170 case VIRTIO_BLK_T_IN: 171 if (!vdpasim_blk_check_range(vdpasim, sector, 172 to_push >> SECTOR_SHIFT, 173 VDPASIM_BLK_SIZE_MAX * VDPASIM_BLK_SEG_MAX)) { 174 status = VIRTIO_BLK_S_IOERR; 175 break; 176 } 177 178 vdpasim_blk_buffer_lock(blk); 179 bytes = vringh_iov_push_iotlb(&vq->vring, &vq->in_iov, 180 blk->buffer + offset, to_push); 181 vdpasim_blk_buffer_unlock(blk); 182 if (bytes < 0) { 183 dev_dbg(&vdpasim->vdpa.dev, 184 "vringh_iov_push_iotlb() error: %zd offset: 0x%llx len: 0x%zx\n", 185 bytes, offset, to_push); 186 status = VIRTIO_BLK_S_IOERR; 187 break; 188 } 189 190 pushed += bytes; 191 break; 192 193 case VIRTIO_BLK_T_OUT: 194 if (!vdpasim_blk_check_range(vdpasim, sector, 195 to_pull >> SECTOR_SHIFT, 196 VDPASIM_BLK_SIZE_MAX * VDPASIM_BLK_SEG_MAX)) { 197 status = VIRTIO_BLK_S_IOERR; 198 break; 199 } 200 201 vdpasim_blk_buffer_lock(blk); 202 bytes = vringh_iov_pull_iotlb(&vq->vring, &vq->out_iov, 203 blk->buffer + offset, to_pull); 204 vdpasim_blk_buffer_unlock(blk); 205 if (bytes < 0) { 206 dev_dbg(&vdpasim->vdpa.dev, 207 "vringh_iov_pull_iotlb() error: %zd offset: 0x%llx len: 0x%zx\n", 208 bytes, offset, to_pull); 209 status = VIRTIO_BLK_S_IOERR; 210 break; 211 } 212 break; 213 214 case VIRTIO_BLK_T_GET_ID: 215 bytes = vringh_iov_push_iotlb(&vq->vring, &vq->in_iov, 216 vdpasim_blk_id, 217 VIRTIO_BLK_ID_BYTES); 218 if (bytes < 0) { 219 dev_dbg(&vdpasim->vdpa.dev, 220 "vringh_iov_push_iotlb() error: %zd\n", bytes); 221 status = VIRTIO_BLK_S_IOERR; 222 break; 223 } 224 225 pushed += bytes; 226 break; 227 228 case VIRTIO_BLK_T_FLUSH: 229 /* nothing to do */ 230 break; 231 232 case VIRTIO_BLK_T_DISCARD: 233 case VIRTIO_BLK_T_WRITE_ZEROES: { 234 struct virtio_blk_discard_write_zeroes range; 235 u32 num_sectors, flags; 236 237 if (to_pull != sizeof(range)) { 238 dev_dbg(&vdpasim->vdpa.dev, 239 "discard/write_zeroes header len: 0x%zx [expected: 0x%zx]\n", 240 to_pull, sizeof(range)); 241 status = VIRTIO_BLK_S_IOERR; 242 break; 243 } 244 245 bytes = vringh_iov_pull_iotlb(&vq->vring, &vq->out_iov, &range, 246 to_pull); 247 if (bytes < 0) { 248 dev_dbg(&vdpasim->vdpa.dev, 249 "vringh_iov_pull_iotlb() error: %zd offset: 0x%llx len: 0x%zx\n", 250 bytes, offset, to_pull); 251 status = VIRTIO_BLK_S_IOERR; 252 break; 253 } 254 255 sector = le64_to_cpu(range.sector); 256 offset = sector << SECTOR_SHIFT; 257 num_sectors = le32_to_cpu(range.num_sectors); 258 flags = le32_to_cpu(range.flags); 259 260 if (type == VIRTIO_BLK_T_DISCARD && flags != 0) { 261 dev_dbg(&vdpasim->vdpa.dev, 262 "discard unexpected flags set - flags: 0x%x\n", 263 flags); 264 status = VIRTIO_BLK_S_UNSUPP; 265 break; 266 } 267 268 if (type == VIRTIO_BLK_T_WRITE_ZEROES && 269 flags & ~VIRTIO_BLK_WRITE_ZEROES_FLAG_UNMAP) { 270 dev_dbg(&vdpasim->vdpa.dev, 271 "write_zeroes unexpected flags set - flags: 0x%x\n", 272 flags); 273 status = VIRTIO_BLK_S_UNSUPP; 274 break; 275 } 276 277 if (!vdpasim_blk_check_range(vdpasim, sector, num_sectors, 278 VDPASIM_BLK_DWZ_MAX_SECTORS)) { 279 status = VIRTIO_BLK_S_IOERR; 280 break; 281 } 282 283 if (type == VIRTIO_BLK_T_WRITE_ZEROES) { 284 vdpasim_blk_buffer_lock(blk); 285 memset(blk->buffer + offset, 0, 286 num_sectors << SECTOR_SHIFT); 287 vdpasim_blk_buffer_unlock(blk); 288 } 289 290 break; 291 } 292 default: 293 dev_dbg(&vdpasim->vdpa.dev, 294 "Unsupported request type %d\n", type); 295 status = VIRTIO_BLK_S_IOERR; 296 break; 297 } 298 299 err_status: 300 /* If some operations fail, we need to skip the remaining bytes 301 * to put the status in the last byte 302 */ 303 if (to_push - pushed > 0) 304 vringh_kiov_advance(&vq->in_iov, to_push - pushed); 305 306 /* Last byte is the status */ 307 bytes = vringh_iov_push_iotlb(&vq->vring, &vq->in_iov, &status, 1); 308 if (bytes != 1) 309 goto err; 310 311 pushed += bytes; 312 313 /* Make sure data is wrote before advancing index */ 314 smp_wmb(); 315 316 handled = true; 317 318 err: 319 vringh_complete_iotlb(&vq->vring, vq->head, pushed); 320 321 return handled; 322 } 323 324 static void vdpasim_blk_work(struct vdpasim *vdpasim) 325 { 326 bool reschedule = false; 327 int i; 328 329 mutex_lock(&vdpasim->mutex); 330 331 if (!(vdpasim->status & VIRTIO_CONFIG_S_DRIVER_OK)) 332 goto out; 333 334 if (!vdpasim->running) 335 goto out; 336 337 for (i = 0; i < VDPASIM_BLK_VQ_NUM; i++) { 338 struct vdpasim_virtqueue *vq = &vdpasim->vqs[i]; 339 int reqs = 0; 340 341 if (!vq->ready) 342 continue; 343 344 while (vdpasim_blk_handle_req(vdpasim, vq)) { 345 /* Make sure used is visible before rasing the interrupt. */ 346 smp_wmb(); 347 348 local_bh_disable(); 349 if (vringh_need_notify_iotlb(&vq->vring) > 0) 350 vringh_notify(&vq->vring); 351 local_bh_enable(); 352 353 if (++reqs > 4) { 354 reschedule = true; 355 break; 356 } 357 } 358 } 359 out: 360 mutex_unlock(&vdpasim->mutex); 361 362 if (reschedule) 363 vdpasim_schedule_work(vdpasim); 364 } 365 366 static void vdpasim_blk_get_config(struct vdpasim *vdpasim, void *config) 367 { 368 struct virtio_blk_config *blk_config = config; 369 370 memset(config, 0, sizeof(struct virtio_blk_config)); 371 372 blk_config->capacity = cpu_to_vdpasim64(vdpasim, VDPASIM_BLK_CAPACITY); 373 blk_config->size_max = cpu_to_vdpasim32(vdpasim, VDPASIM_BLK_SIZE_MAX); 374 blk_config->seg_max = cpu_to_vdpasim32(vdpasim, VDPASIM_BLK_SEG_MAX); 375 blk_config->num_queues = cpu_to_vdpasim16(vdpasim, VDPASIM_BLK_VQ_NUM); 376 blk_config->min_io_size = cpu_to_vdpasim16(vdpasim, 1); 377 blk_config->opt_io_size = cpu_to_vdpasim32(vdpasim, 1); 378 blk_config->blk_size = cpu_to_vdpasim32(vdpasim, SECTOR_SIZE); 379 /* VIRTIO_BLK_F_DISCARD */ 380 blk_config->discard_sector_alignment = 381 cpu_to_vdpasim32(vdpasim, SECTOR_SIZE); 382 blk_config->max_discard_sectors = 383 cpu_to_vdpasim32(vdpasim, VDPASIM_BLK_DWZ_MAX_SECTORS); 384 blk_config->max_discard_seg = cpu_to_vdpasim32(vdpasim, 1); 385 /* VIRTIO_BLK_F_WRITE_ZEROES */ 386 blk_config->max_write_zeroes_sectors = 387 cpu_to_vdpasim32(vdpasim, VDPASIM_BLK_DWZ_MAX_SECTORS); 388 blk_config->max_write_zeroes_seg = cpu_to_vdpasim32(vdpasim, 1); 389 390 } 391 392 static void vdpasim_blk_free(struct vdpasim *vdpasim) 393 { 394 struct vdpasim_blk *blk = sim_to_blk(vdpasim); 395 396 if (!blk->shared_backend) 397 kvfree(blk->buffer); 398 } 399 400 static void vdpasim_blk_mgmtdev_release(struct device *dev) 401 { 402 } 403 404 static struct device vdpasim_blk_mgmtdev = { 405 .init_name = "vdpasim_blk", 406 .release = vdpasim_blk_mgmtdev_release, 407 }; 408 409 static int vdpasim_blk_dev_add(struct vdpa_mgmt_dev *mdev, const char *name, 410 const struct vdpa_dev_set_config *config) 411 { 412 struct vdpasim_dev_attr dev_attr = {}; 413 struct vdpasim_blk *blk; 414 struct vdpasim *simdev; 415 int ret; 416 417 dev_attr.mgmt_dev = mdev; 418 dev_attr.name = name; 419 dev_attr.id = VIRTIO_ID_BLOCK; 420 dev_attr.supported_features = VDPASIM_BLK_FEATURES; 421 dev_attr.nvqs = VDPASIM_BLK_VQ_NUM; 422 dev_attr.ngroups = VDPASIM_BLK_GROUP_NUM; 423 dev_attr.nas = VDPASIM_BLK_AS_NUM; 424 dev_attr.alloc_size = sizeof(struct vdpasim_blk); 425 dev_attr.config_size = sizeof(struct virtio_blk_config); 426 dev_attr.get_config = vdpasim_blk_get_config; 427 dev_attr.work_fn = vdpasim_blk_work; 428 dev_attr.free = vdpasim_blk_free; 429 430 simdev = vdpasim_create(&dev_attr, config); 431 if (IS_ERR(simdev)) 432 return PTR_ERR(simdev); 433 434 blk = sim_to_blk(simdev); 435 blk->shared_backend = shared_backend; 436 437 if (blk->shared_backend) { 438 blk->buffer = shared_buffer; 439 } else { 440 blk->buffer = kvzalloc(VDPASIM_BLK_CAPACITY << SECTOR_SHIFT, 441 GFP_KERNEL); 442 if (!blk->buffer) { 443 ret = -ENOMEM; 444 goto put_dev; 445 } 446 } 447 448 ret = _vdpa_register_device(&simdev->vdpa, VDPASIM_BLK_VQ_NUM); 449 if (ret) 450 goto put_dev; 451 452 return 0; 453 454 put_dev: 455 put_device(&simdev->vdpa.dev); 456 return ret; 457 } 458 459 static void vdpasim_blk_dev_del(struct vdpa_mgmt_dev *mdev, 460 struct vdpa_device *dev) 461 { 462 struct vdpasim *simdev = container_of(dev, struct vdpasim, vdpa); 463 464 _vdpa_unregister_device(&simdev->vdpa); 465 } 466 467 static const struct vdpa_mgmtdev_ops vdpasim_blk_mgmtdev_ops = { 468 .dev_add = vdpasim_blk_dev_add, 469 .dev_del = vdpasim_blk_dev_del 470 }; 471 472 static struct virtio_device_id id_table[] = { 473 { VIRTIO_ID_BLOCK, VIRTIO_DEV_ANY_ID }, 474 { 0 }, 475 }; 476 477 static struct vdpa_mgmt_dev mgmt_dev = { 478 .device = &vdpasim_blk_mgmtdev, 479 .id_table = id_table, 480 .ops = &vdpasim_blk_mgmtdev_ops, 481 }; 482 483 static int __init vdpasim_blk_init(void) 484 { 485 int ret; 486 487 ret = device_register(&vdpasim_blk_mgmtdev); 488 if (ret) { 489 put_device(&vdpasim_blk_mgmtdev); 490 return ret; 491 } 492 493 ret = vdpa_mgmtdev_register(&mgmt_dev); 494 if (ret) 495 goto parent_err; 496 497 if (shared_backend) { 498 shared_buffer = kvzalloc(VDPASIM_BLK_CAPACITY << SECTOR_SHIFT, 499 GFP_KERNEL); 500 if (!shared_buffer) { 501 ret = -ENOMEM; 502 goto mgmt_dev_err; 503 } 504 } 505 506 return 0; 507 mgmt_dev_err: 508 vdpa_mgmtdev_unregister(&mgmt_dev); 509 parent_err: 510 device_unregister(&vdpasim_blk_mgmtdev); 511 return ret; 512 } 513 514 static void __exit vdpasim_blk_exit(void) 515 { 516 kvfree(shared_buffer); 517 vdpa_mgmtdev_unregister(&mgmt_dev); 518 device_unregister(&vdpasim_blk_mgmtdev); 519 } 520 521 module_init(vdpasim_blk_init) 522 module_exit(vdpasim_blk_exit) 523 524 MODULE_VERSION(DRV_VERSION); 525 MODULE_LICENSE(DRV_LICENSE); 526 MODULE_AUTHOR(DRV_AUTHOR); 527 MODULE_DESCRIPTION(DRV_DESC); 528