| @@ -50,10 +50,6 @@ enum { · 49 unmodified lines |
| 50 | #define vhost_used_event(vq) ((__virtio16 __user *)&vq->avail->ring[vq->num]) | 50 | #define vhost_used_event(vq) ((__virtio16 __user *)&vq->avail->ring[vq->num]) |
| 51 | #define vhost_avail_event(vq) ((__virtio16 __user *)&vq->used->ring[vq->num]) | 51 | #define vhost_avail_event(vq) ((__virtio16 __user *)&vq->used->ring[vq->num]) |
| 52 | | 52 | |
| 53 | INTERVAL_TREE_DEFINE(struct vhost_umem_node, | | |
| 54 | rb, __u64, __subtree_last, | | |
| 55 | START, LAST, static inline, vhost_umem_interval_tree); | | |
| 56 | | | |
| 57 | #ifdef CONFIG_VHOST_CROSS_ENDIAN_LEGACY | 53 | #ifdef CONFIG_VHOST_CROSS_ENDIAN_LEGACY |
| 58 | static void vhost_disable_cross_endian(struct vhost_virtqueue *vq) | 54 | static void vhost_disable_cross_endian(struct vhost_virtqueue *vq) |
| 59 | { | 55 | { |
| @@ -584,21 +580,25 @@ err_mm: · 524 unmodified lines |
| 584 | } | 580 | } |
| 585 | EXPORT_SYMBOL_GPL(vhost_dev_set_owner); | 581 | EXPORT_SYMBOL_GPL(vhost_dev_set_owner); |
| 586 | | 582 | |
| 587 | struct vhost_umem *vhost_dev_reset_owner_prepare(void) | 583 | static struct vhost_iotlb *iotlb_alloc(void) |
| | 584 | { |
| | 585 | return vhost_iotlb_alloc(max_iotlb_entries, |
| | 586 | VHOST_IOTLB_FLAG_RETIRE); |
| | 587 | } |
| | 588 | |
| | 589 | struct vhost_iotlb *vhost_dev_reset_owner_prepare(void) |
| 588 | { | 590 | { |
| 589 | return kvzalloc(sizeof(struct vhost_umem), GFP_KERNEL); | 591 | return iotlb_alloc(); |
| 590 | } | 592 | } |
| 591 | EXPORT_SYMBOL_GPL(vhost_dev_reset_owner_prepare); | 593 | EXPORT_SYMBOL_GPL(vhost_dev_reset_owner_prepare); |
| 592 | | 594 | |
| 593 | /* Caller should have device mutex */ | 595 | /* Caller should have device mutex */ |
| 594 | void vhost_dev_reset_owner(struct vhost_dev *dev, struct vhost_umem *umem) | 596 | void vhost_dev_reset_owner(struct vhost_dev *dev, struct vhost_iotlb *umem) |
| 595 | { | 597 | { |
| 596 | int i; | 598 | int i; |
| 597 | | 599 | |
| 598 | vhost_dev_cleanup(dev); | 600 | vhost_dev_cleanup(dev); |
| 599 | | 601 | |
| 600 | /* Restore memory to default empty mapping. */ | | |
| 601 | INIT_LIST_HEAD(&umem->umem_list); | | |
| 602 | dev->umem = umem; | 602 | dev->umem = umem; |
| 603 | /* We don't need VQ locks below since vhost_dev_cleanup makes sure | 603 | /* We don't need VQ locks below since vhost_dev_cleanup makes sure |
| 604 | * VQs aren't running. | 604 | * VQs aren't running. |
| @@ -621,28 +621,6 @@ void vhost_dev_stop(struct vhost_dev *dev) · 16 unmodified lines |
| 621 | } | 621 | } |
| 622 | EXPORT_SYMBOL_GPL(vhost_dev_stop); | 622 | EXPORT_SYMBOL_GPL(vhost_dev_stop); |
| 623 | | 623 | |
| 624 | static void vhost_umem_free(struct vhost_umem *umem, | | |
| 625 | struct vhost_umem_node *node) | | |
| 626 | { | | |
| 627 | vhost_umem_interval_tree_remove(node, &umem->umem_tree); | | |
| 628 | list_del(&node->link); | | |
| 629 | kfree(node); | | |
| 630 | umem->numem--; | | |
| 631 | } | | |
| 632 | | | |
| 633 | static void vhost_umem_clean(struct vhost_umem *umem) | | |
| 634 | { | | |
| 635 | struct vhost_umem_node *node, *tmp; | | |
| 636 | | | |
| 637 | if (!umem) | | |
| 638 | return; | | |
| 639 | | | |
| 640 | list_for_each_entry_safe(node, tmp, &umem->umem_list, link) | | |
| 641 | vhost_umem_free(umem, node); | | |
| 642 | | | |
| 643 | kvfree(umem); | | |
| 644 | } | | |
| 645 | | | |
| 646 | static void vhost_clear_msg(struct vhost_dev *dev) | 624 | static void vhost_clear_msg(struct vhost_dev *dev) |
| 647 | { | 625 | { |
| 648 | struct vhost_msg_node *node, *n; | 626 | struct vhost_msg_node *node, *n; |
| @@ -680,9 +658,9 @@ void vhost_dev_cleanup(struct vhost_dev *dev) · 31 unmodified lines |
| 680 | eventfd_ctx_put(dev->log_ctx); | 658 | eventfd_ctx_put(dev->log_ctx); |
| 681 | dev->log_ctx = NULL; | 659 | dev->log_ctx = NULL; |
| 682 | /* No one will access memory at this point */ | 660 | /* No one will access memory at this point */ |
| 683 | vhost_umem_clean(dev->umem); | 661 | vhost_iotlb_free(dev->umem); |
| 684 | dev->umem = NULL; | 662 | dev->umem = NULL; |
| 685 | vhost_umem_clean(dev->iotlb); | 663 | vhost_iotlb_free(dev->iotlb); |
| 686 | dev->iotlb = NULL; | 664 | dev->iotlb = NULL; |
| 687 | vhost_clear_msg(dev); | 665 | vhost_clear_msg(dev); |
| 688 | wake_up_interruptible_poll(&dev->wait, EPOLLIN | EPOLLRDNORM); | 666 | wake_up_interruptible_poll(&dev->wait, EPOLLIN | EPOLLRDNORM); |
| @@ -718,27 +696,26 @@ static bool vhost_overflow(u64 uaddr, u64 size) · 29 unmodified lines |
| 718 | } | 696 | } |
| 719 | | 697 | |
| 720 | /* Caller should have vq mutex and device mutex. */ | 698 | /* Caller should have vq mutex and device mutex. */ |
| 721 | static bool vq_memory_access_ok(void __user *log_base, struct vhost_umem *umem, | 699 | static bool vq_memory_access_ok(void __user *log_base, struct vhost_iotlb *umem, |
| 722 | int log_all) | 700 | int log_all) |
| 723 | { | 701 | { |
| 724 | struct vhost_umem_node *node; | 702 | struct vhost_iotlb_map *map; |
| 725 | | 703 | |
| 726 | if (!umem) | 704 | if (!umem) |
| 727 | return false; | 705 | return false; |
| 728 | | 706 | |
| 729 | list_for_each_entry(node, &umem->umem_list, link) { | 707 | list_for_each_entry(map, &umem->list, link) { |
| 730 | unsigned long a = node->userspace_addr; | 708 | unsigned long a = map->addr; |
| 731 | | 709 | |
| 732 | if (vhost_overflow(node->userspace_addr, node->size)) | 710 | if (vhost_overflow(map->addr, map->size)) |
| 733 | return false; | 711 | return false; |
| 734 | | 712 | |
| 735 | | 713 | |
| 736 | if (!access_ok((void __user *)a, | 714 | if (!access_ok((void __user *)a, map->size)) |
| 737 | node->size)) | | |
| 738 | return false; | 715 | return false; |
| 739 | else if (log_all && !log_access_ok(log_base, | 716 | else if (log_all && !log_access_ok(log_base, |
| 740 | node->start, | 717 | map->start, |
| 741 | node->size)) | 718 | map->size)) |
| 742 | return false; | 719 | return false; |
| 743 | } | 720 | } |
| 744 | return true; | 721 | return true; |
| @@ -748,17 +725,17 @@ static inline void __user *vhost_vq_meta_fetch(struct vhost_virtqueue *vq, · 3 unmodified lines |
| 748 | u64 addr, unsigned int size, | 725 | u64 addr, unsigned int size, |
| 749 | int type) | 726 | int type) |
| 750 | { | 727 | { |
| 751 | const struct vhost_umem_node *node = vq->meta_iotlb[type]; | 728 | const struct vhost_iotlb_map *map = vq->meta_iotlb[type]; |
| 752 | | 729 | |
| 753 | if (!node) | 730 | if (!map) |
| 754 | return NULL; | 731 | return NULL; |
| 755 | | 732 | |
| 756 | return (void *)(uintptr_t)(node->userspace_addr + addr - node->start); | 733 | return (void *)(uintptr_t)(map->addr + addr - map->start); |
| 757 | } | 734 | } |
| 758 | | 735 | |
| 759 | /* Can we switch to this memory table? */ | 736 | /* Can we switch to this memory table? */ |
| 760 | /* Caller should have device mutex but not vq mutex */ | 737 | /* Caller should have device mutex but not vq mutex */ |
| 761 | static bool memory_access_ok(struct vhost_dev *d, struct vhost_umem *umem, | 738 | static bool memory_access_ok(struct vhost_dev *d, struct vhost_iotlb *umem, |
| 762 | int log_all) | 739 | int log_all) |
| 763 | { | 740 | { |
| 764 | int i; | 741 | int i; |
| @@ -1023,47 +1000,6 @@ static inline int vhost_get_desc(struct vhost_virtqueue *vq, · 258 unmodified lines |
| 1023 | return vhost_copy_from_user(vq, desc, vq->desc + idx, sizeof(*desc)); | 1000 | return vhost_copy_from_user(vq, desc, vq->desc + idx, sizeof(*desc)); |
| 1024 | } | 1001 | } |
| 1025 | | 1002 | |
| 1026 | static int vhost_new_umem_range(struct vhost_umem *umem, | | |
| 1027 | u64 start, u64 size, u64 end, | | |
| 1028 | u64 userspace_addr, int perm) | | |
| 1029 | { | | |
| 1030 | struct vhost_umem_node *tmp, *node; | | |
| 1031 | | | |
| 1032 | if (!size) | | |
| 1033 | return -EFAULT; | | |
| 1034 | | | |
| 1035 | node = kmalloc(sizeof(*node), GFP_ATOMIC); | | |
| 1036 | if (!node) | | |
| 1037 | return -ENOMEM; | | |
| 1038 | | | |
| 1039 | if (umem->numem == max_iotlb_entries) { | | |
| 1040 | tmp = list_first_entry(&umem->umem_list, typeof(*tmp), link); | | |
| 1041 | vhost_umem_free(umem, tmp); | | |
| 1042 | } | | |
| 1043 | | | |
| 1044 | node->start = start; | | |
| 1045 | node->size = size; | | |
| 1046 | node->last = end; | | |
| 1047 | node->userspace_addr = userspace_addr; | | |
| 1048 | node->perm = perm; | | |
| 1049 | INIT_LIST_HEAD(&node->link); | | |
| 1050 | list_add_tail(&node->link, &umem->umem_list); | | |
| 1051 | vhost_umem_interval_tree_insert(node, &umem->umem_tree); | | |
| 1052 | umem->numem++; | | |
| 1053 | | | |
| 1054 | return 0; | | |
| 1055 | } | | |
| 1056 | | | |
| 1057 | static void vhost_del_umem_range(struct vhost_umem *umem, | | |
| 1058 | u64 start, u64 end) | | |
| 1059 | { | | |
| 1060 | struct vhost_umem_node *node; | | |
| 1061 | | | |
| 1062 | while ((node = vhost_umem_interval_tree_iter_first(&umem->umem_tree, | | |
| 1063 | start, end))) | | |
| 1064 | vhost_umem_free(umem, node); | | |
| 1065 | } | | |
| 1066 | | | |
| 1067 | static void vhost_iotlb_notify_vq(struct vhost_dev *d, | 1003 | static void vhost_iotlb_notify_vq(struct vhost_dev *d, |
| 1068 | struct vhost_iotlb_msg *msg) | 1004 | struct vhost_iotlb_msg *msg) |
| 1069 | { | 1005 | { |
| @@ -1120,9 +1056,9 @@ static int vhost_process_iotlb_msg(struct vhost_dev *dev, · 50 unmodified lines |
| 1120 | break; | 1056 | break; |
| 1121 | } | 1057 | } |
| 1122 | vhost_vq_meta_reset(dev); | 1058 | vhost_vq_meta_reset(dev); |
| 1123 | if (vhost_new_umem_range(dev->iotlb, msg->iova, msg->size, | 1059 | if (vhost_iotlb_add_range(dev->iotlb, msg->iova, |
| 1124 | msg->iova + msg->size - 1, | 1060 | msg->iova + msg->size - 1, |
| 1125 | msg->uaddr, msg->perm)) { | 1061 | msg->uaddr, msg->perm)) { |
| 1126 | ret = -ENOMEM; | 1062 | ret = -ENOMEM; |
| 1127 | break; | 1063 | break; |
| 1128 | } | 1064 | } |
| @@ -1134,8 +1070,8 @@ static int vhost_process_iotlb_msg(struct vhost_dev *dev, · 5 unmodified lines |
| 1134 | break; | 1070 | break; |
| 1135 | } | 1071 | } |
| 1136 | vhost_vq_meta_reset(dev); | 1072 | vhost_vq_meta_reset(dev); |
| 1137 | vhost_del_umem_range(dev->iotlb, msg->iova, | 1073 | vhost_iotlb_del_range(dev->iotlb, msg->iova, |
| 1138 | msg->iova + msg->size - 1); | 1074 | msg->iova + msg->size - 1); |
| 1139 | break; | 1075 | break; |
| 1140 | default: | 1076 | default: |
| 1141 | ret = -EINVAL; | 1077 | ret = -EINVAL; |
| @@ -1319,44 +1255,42 @@ static bool vq_access_ok(struct vhost_virtqueue *vq, unsigned int num, · 177 unmodified lines |
| 1319 | } | 1255 | } |
| 1320 | | 1256 | |
| 1321 | static void vhost_vq_meta_update(struct vhost_virtqueue *vq, | 1257 | static void vhost_vq_meta_update(struct vhost_virtqueue *vq, |
| 1322 | const struct vhost_umem_node *node, | 1258 | const struct vhost_iotlb_map *map, |
| 1323 | int type) | 1259 | int type) |
| 1324 | { | 1260 | { |
| 1325 | int access = (type == VHOST_ADDR_USED) ? | 1261 | int access = (type == VHOST_ADDR_USED) ? |
| 1326 | VHOST_ACCESS_WO : VHOST_ACCESS_RO; | 1262 | VHOST_ACCESS_WO : VHOST_ACCESS_RO; |
| 1327 | | 1263 | |
| 1328 | if (likely(node->perm & access)) | 1264 | if (likely(map->perm & access)) |
| 1329 | vq->meta_iotlb[type] = node; | 1265 | vq->meta_iotlb[type] = map; |
| 1330 | } | 1266 | } |
| 1331 | | 1267 | |
| 1332 | static bool iotlb_access_ok(struct vhost_virtqueue *vq, | 1268 | static bool iotlb_access_ok(struct vhost_virtqueue *vq, |
| 1333 | int access, u64 addr, u64 len, int type) | 1269 | int access, u64 addr, u64 len, int type) |
| 1334 | { | 1270 | { |
| 1335 | const struct vhost_umem_node *node; | 1271 | const struct vhost_iotlb_map *map; |
| 1336 | struct vhost_umem *umem = vq->iotlb; | 1272 | struct vhost_iotlb *umem = vq->iotlb; |
| 1337 | u64 s = 0, size, orig_addr = addr, last = addr + len - 1; | 1273 | u64 s = 0, size, orig_addr = addr, last = addr + len - 1; |
| 1338 | | 1274 | |
| 1339 | if (vhost_vq_meta_fetch(vq, addr, len, type)) | 1275 | if (vhost_vq_meta_fetch(vq, addr, len, type)) |
| 1340 | return true; | 1276 | return true; |
| 1341 | | 1277 | |
| 1342 | while (len > s) { | 1278 | while (len > s) { |
| 1343 | node = vhost_umem_interval_tree_iter_first(&umem->umem_tree, | 1279 | map = vhost_iotlb_itree_first(umem, addr, last); |
| 1344 | addr, | 1280 | if (map == NULL || map->start > addr) { |
| 1345 | last); | | |
| 1346 | if (node == NULL || node->start > addr) { | | |
| 1347 | vhost_iotlb_miss(vq, addr, access); | 1281 | vhost_iotlb_miss(vq, addr, access); |
| 1348 | return false; | 1282 | return false; |
| 1349 | } else if (!(node->perm & access)) { | 1283 | } else if (!(map->perm & access)) { |
| 1350 | /* Report the possible access violation by | 1284 | /* Report the possible access violation by |
| 1351 | * request another translation from userspace. | 1285 | * request another translation from userspace. |
| 1352 | */ | 1286 | */ |
| 1353 | return false; | 1287 | return false; |
| 1354 | } | 1288 | } |
| 1355 | | 1289 | |
| 1356 | size = node->size - addr + node->start; | 1290 | size = map->size - addr + map->start; |
| 1357 | | 1291 | |
| 1358 | if (orig_addr == addr && size >= len) | 1292 | if (orig_addr == addr && size >= len) |
| 1359 | vhost_vq_meta_update(vq, node, type); | 1293 | vhost_vq_meta_update(vq, map, type); |
| 1360 | | 1294 | |
| 1361 | s += size; | 1295 | s += size; |
| 1362 | addr += size; | 1296 | addr += size; |
| @@ -1372,12 +1306,12 @@ int vq_meta_prefetch(struct vhost_virtqueue *vq) · 9 unmodified lines |
| 1372 | if (!vq->iotlb) | 1306 | if (!vq->iotlb) |
| 1373 | return 1; | 1307 | return 1; |
| 1374 | | 1308 | |
| 1375 | return iotlb_access_ok(vq, VHOST_ACCESS_RO, (u64)(uintptr_t)vq->desc, | 1309 | return iotlb_access_ok(vq, VHOST_MAP_RO, (u64)(uintptr_t)vq->desc, |
| 1376 | vhost_get_desc_size(vq, num), VHOST_ADDR_DESC) && | 1310 | vhost_get_desc_size(vq, num), VHOST_ADDR_DESC) && |
| 1377 | iotlb_access_ok(vq, VHOST_ACCESS_RO, (u64)(uintptr_t)vq->avail, | 1311 | iotlb_access_ok(vq, VHOST_MAP_RO, (u64)(uintptr_t)vq->avail, |
| 1378 | vhost_get_avail_size(vq, num), | 1312 | vhost_get_avail_size(vq, num), |
| 1379 | VHOST_ADDR_AVAIL) && | 1313 | VHOST_ADDR_AVAIL) && |
| 1380 | iotlb_access_ok(vq, VHOST_ACCESS_WO, (u64)(uintptr_t)vq->used, | 1314 | iotlb_access_ok(vq, VHOST_MAP_WO, (u64)(uintptr_t)vq->used, |
| 1381 | vhost_get_used_size(vq, num), VHOST_ADDR_USED); | 1315 | vhost_get_used_size(vq, num), VHOST_ADDR_USED); |
| 1382 | } | 1316 | } |
| 1383 | EXPORT_SYMBOL_GPL(vq_meta_prefetch); | 1317 | EXPORT_SYMBOL_GPL(vq_meta_prefetch); |
| @@ -1416,25 +1350,11 @@ bool vhost_vq_access_ok(struct vhost_virtqueue *vq) · 32 unmodified lines |
| 1416 | } | 1350 | } |
| 1417 | EXPORT_SYMBOL_GPL(vhost_vq_access_ok); | 1351 | EXPORT_SYMBOL_GPL(vhost_vq_access_ok); |
| 1418 | | 1352 | |
| 1419 | static struct vhost_umem *vhost_umem_alloc(void) | | |
| 1420 | { | | |
| 1421 | struct vhost_umem *umem = kvzalloc(sizeof(*umem), GFP_KERNEL); | | |
| 1422 | | | |
| 1423 | if (!umem) | | |
| 1424 | return NULL; | | |
| 1425 | | | |
| 1426 | umem->umem_tree = RB_ROOT_CACHED; | | |
| 1427 | umem->numem = 0; | | |
| 1428 | INIT_LIST_HEAD(&umem->umem_list); | | |
| 1429 | | | |
| 1430 | return umem; | | |
| 1431 | } | | |
| 1432 | | | |
| 1433 | static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) | 1353 | static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) |
| 1434 | { | 1354 | { |
| 1435 | struct vhost_memory mem, *newmem; | 1355 | struct vhost_memory mem, *newmem; |
| 1436 | struct vhost_memory_region *region; | 1356 | struct vhost_memory_region *region; |
| 1437 | struct vhost_umem *newumem, *oldumem; | 1357 | struct vhost_iotlb *newumem, *oldumem; |
| 1438 | unsigned long size = offsetof(struct vhost_memory, regions); | 1358 | unsigned long size = offsetof(struct vhost_memory, regions); |
| 1439 | int i; | 1359 | int i; |
| 1440 | | 1360 | |
| @@ -1456,7 +1376,7 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) · 15 unmodified lines |
| 1456 | return -EFAULT; | 1376 | return -EFAULT; |
| 1457 | } | 1377 | } |
| 1458 | | 1378 | |
| 1459 | newumem = vhost_umem_alloc(); | 1379 | newumem = iotlb_alloc(); |
| 1460 | if (!newumem) { | 1380 | if (!newumem) { |
| 1461 | kvfree(newmem); | 1381 | kvfree(newmem); |
| 1462 | return -ENOMEM; | 1382 | return -ENOMEM; |
| @@ -1465,13 +1385,12 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) · 2 unmodified lines |
| 1465 | for (region = newmem->regions; | 1385 | for (region = newmem->regions; |
| 1466 | region < newmem->regions + mem.nregions; | 1386 | region < newmem->regions + mem.nregions; |
| 1467 | region++) { | 1387 | region++) { |
| 1468 | if (vhost_new_umem_range(newumem, | 1388 | if (vhost_iotlb_add_range(newumem, |
| 1469 | region->guest_phys_addr, | 1389 | region->guest_phys_addr, |
| 1470 | region->memory_size, | 1390 | region->guest_phys_addr + |
| 1471 | region->guest_phys_addr + | 1391 | region->memory_size - 1, |
| 1472 | region->memory_size - 1, | 1392 | region->userspace_addr, |
| 1473 | region->userspace_addr, | 1393 | VHOST_MAP_RW)) |
| 1474 | VHOST_ACCESS_RW)) | | |
| 1475 | goto err; | 1394 | goto err; |
| 1476 | } | 1395 | } |
| 1477 | | 1396 | |
| @@ -1489,11 +1408,11 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) · 11 unmodified lines |
| 1489 | } | 1408 | } |
| 1490 | | 1409 | |
| 1491 | kvfree(newmem); | 1410 | kvfree(newmem); |
| 1492 | vhost_umem_clean(oldumem); | 1411 | vhost_iotlb_free(oldumem); |
| 1493 | return 0; | 1412 | return 0; |
| 1494 | | 1413 | |
| 1495 | err: | 1414 | err: |
| 1496 | vhost_umem_clean(newumem); | 1415 | vhost_iotlb_free(newumem); |
| 1497 | kvfree(newmem); | 1416 | kvfree(newmem); |
| 1498 | return -EFAULT; | 1417 | return -EFAULT; |
| 1499 | } | 1418 | } |
| @@ -1734,10 +1653,10 @@ EXPORT_SYMBOL_GPL(vhost_vring_ioctl); · 234 unmodified lines |
| 1734 | | 1653 | |
| 1735 | int vhost_init_device_iotlb(struct vhost_dev *d, bool enabled) | 1654 | int vhost_init_device_iotlb(struct vhost_dev *d, bool enabled) |
| 1736 | { | 1655 | { |
| 1737 | struct vhost_umem *niotlb, *oiotlb; | 1656 | struct vhost_iotlb *niotlb, *oiotlb; |
| 1738 | int i; | 1657 | int i; |
| 1739 | | 1658 | |
| 1740 | niotlb = vhost_umem_alloc(); | 1659 | niotlb = iotlb_alloc(); |
| 1741 | if (!niotlb) | 1660 | if (!niotlb) |
| 1742 | return -ENOMEM; | 1661 | return -ENOMEM; |
| 1743 | | 1662 | |
| @@ -1753,7 +1672,7 @@ int vhost_init_device_iotlb(struct vhost_dev *d, bool enabled) · 9 unmodified lines |
| 1753 | mutex_unlock(&vq->mutex); | 1672 | mutex_unlock(&vq->mutex); |
| 1754 | } | 1673 | } |
| 1755 | | 1674 | |
| 1756 | vhost_umem_clean(oiotlb); | 1675 | vhost_iotlb_free(oiotlb); |
| 1757 | | 1676 | |
| 1758 | return 0; | 1677 | return 0; |
| 1759 | } | 1678 | } |
| @@ -1883,8 +1802,8 @@ static int log_write(void __user *log_base, · 123 unmodified lines |
| 1883 | | 1802 | |
| 1884 | static int log_write_hva(struct vhost_virtqueue *vq, u64 hva, u64 len) | 1803 | static int log_write_hva(struct vhost_virtqueue *vq, u64 hva, u64 len) |
| 1885 | { | 1804 | { |
| 1886 | struct vhost_umem *umem = vq->umem; | 1805 | struct vhost_iotlb *umem = vq->umem; |
| 1887 | struct vhost_umem_node *u; | 1806 | struct vhost_iotlb_map *u; |
| 1888 | u64 start, end, l, min; | 1807 | u64 start, end, l, min; |
| 1889 | int r; | 1808 | int r; |
| 1890 | bool hit = false; | 1809 | bool hit = false; |
| @@ -1894,16 +1813,15 @@ static int log_write_hva(struct vhost_virtqueue *vq, u64 hva, u64 len) · 3 unmodified lines |
| 1894 | /* More than one GPAs can be mapped into a single HVA. So | 1813 | /* More than one GPAs can be mapped into a single HVA. So |
| 1895 | * iterate all possible umems here to be safe. | 1814 | * iterate all possible umems here to be safe. |
| 1896 | */ | 1815 | */ |
| 1897 | list_for_each_entry(u, &umem->umem_list, link) { | 1816 | list_for_each_entry(u, &umem->list, link) { |
| 1898 | if (u->userspace_addr > hva - 1 + len || | 1817 | if (u->addr > hva - 1 + len || |
| 1899 | u->userspace_addr - 1 + u->size < hva) | 1818 | u->addr - 1 + u->size < hva) |
| 1900 | continue; | 1819 | continue; |
| 1901 | start = max(u->userspace_addr, hva); | 1820 | start = max(u->addr, hva); |
| 1902 | end = min(u->userspace_addr - 1 + u->size, | 1821 | end = min(u->addr - 1 + u->size, hva - 1 + len); |
| 1903 | hva - 1 + len); | | |
| 1904 | l = end - start + 1; | 1822 | l = end - start + 1; |
| 1905 | r = log_write(vq->log_base, | 1823 | r = log_write(vq->log_base, |
| 1906 | u->start + start - u->userspace_addr, | 1824 | u->start + start - u->addr, |
| 1907 | l); | 1825 | l); |
| 1908 | if (r < 0) | 1826 | if (r < 0) |
| 1909 | return r; | 1827 | return r; |
| @@ -2054,9 +1972,9 @@ EXPORT_SYMBOL_GPL(vhost_vq_init_access); · 144 unmodified lines |
| 2054 | static int translate_desc(struct vhost_virtqueue *vq, u64 addr, u32 len, | 1972 | static int translate_desc(struct vhost_virtqueue *vq, u64 addr, u32 len, |
| 2055 | struct iovec iov[], int iov_size, int access) | 1973 | struct iovec iov[], int iov_size, int access) |
| 2056 | { | 1974 | { |
| 2057 | const struct vhost_umem_node *node; | 1975 | const struct vhost_iotlb_map *map; |
| 2058 | struct vhost_dev *dev = vq->dev; | 1976 | struct vhost_dev *dev = vq->dev; |
| 2059 | struct vhost_umem *umem = dev->iotlb ? dev->iotlb : dev->umem; | 1977 | struct vhost_iotlb *umem = dev->iotlb ? dev->iotlb : dev->umem; |
| 2060 | struct iovec *_iov; | 1978 | struct iovec *_iov; |
| 2061 | u64 s = 0; | 1979 | u64 s = 0; |
| 2062 | int ret = 0; | 1980 | int ret = 0; |
| @@ -2068,25 +1986,24 @@ static int translate_desc(struct vhost_virtqueue *vq, u64 addr, u32 len, · 5 unmodified lines |
| 2068 | break; | 1986 | break; |
| 2069 | } | 1987 | } |
| 2070 | | 1988 | |
| 2071 | node = vhost_umem_interval_tree_iter_first(&umem->umem_tree, | 1989 | map = vhost_iotlb_itree_first(umem, addr, addr + len - 1); |
| 2072 | addr, addr + len - 1); | 1990 | if (map == NULL || map->start > addr) { |
| 2073 | if (node == NULL || node->start > addr) { | | |
| 2074 | if (umem != dev->iotlb) { | 1991 | if (umem != dev->iotlb) { |
| 2075 | ret = -EFAULT; | 1992 | ret = -EFAULT; |
| 2076 | break; | 1993 | break; |
| 2077 | } | 1994 | } |
| 2078 | ret = -EAGAIN; | 1995 | ret = -EAGAIN; |
| 2079 | break; | 1996 | break; |
| 2080 | } else if (!(node->perm & access)) { | 1997 | } else if (!(map->perm & access)) { |
| 2081 | ret = -EPERM; | 1998 | ret = -EPERM; |
| 2082 | break; | 1999 | break; |
| 2083 | } | 2000 | } |
| 2084 | | 2001 | |
| 2085 | _iov = iov + ret; | 2002 | _iov = iov + ret; |
| 2086 | size = node->size - addr + node->start; | 2003 | size = map->size - addr + map->start; |
| 2087 | _iov->iov_len = min((u64)len - s, size); | 2004 | _iov->iov_len = min((u64)len - s, size); |
| 2088 | _iov->iov_base = (void __user *)(unsigned long) | 2005 | _iov->iov_base = (void __user *)(unsigned long) |
| 2089 | (node->userspace_addr + addr - node->start); | 2006 | (map->addr + addr - map->start); |
| 2090 | s += size; | 2007 | s += size; |
| 2091 | addr += size; | 2008 | addr += size; |
| 2092 | ++ret; | 2009 | ++ret; |