2 * vhost software live migration iova tree
4 * SPDX-FileCopyrightText: Red Hat, Inc. 2021
5 * SPDX-FileContributor: Author: Eugenio PĂ©rez <eperezma@redhat.com>
7 * SPDX-License-Identifier: GPL-2.0-or-later
10 #include "qemu/osdep.h"
11 #include "qemu/iova-tree.h"
12 #include "vhost-iova-tree.h"
14 #define iova_min_addr qemu_real_host_page_size()
17 * VhostIOVATree, able to:
18 * - Translate iova address
19 * - Reverse translate iova address (from translated to iova)
20 * - Allocate IOVA regions for translated range (linear operation)
22 struct VhostIOVATree
{
23 /* First addressable iova address in the device */
26 /* Last addressable iova address in the device */
29 /* IOVA address to qemu memory maps. */
30 IOVATree
*iova_taddr_map
;
34 * Create a new IOVA tree
36 * Returns the new IOVA tree
38 VhostIOVATree
*vhost_iova_tree_new(hwaddr iova_first
, hwaddr iova_last
)
40 VhostIOVATree
*tree
= g_new(VhostIOVATree
, 1);
42 /* Some devices do not like 0 addresses */
43 tree
->iova_first
= MAX(iova_first
, iova_min_addr
);
44 tree
->iova_last
= iova_last
;
46 tree
->iova_taddr_map
= iova_tree_new();
53 void vhost_iova_tree_delete(VhostIOVATree
*iova_tree
)
55 iova_tree_destroy(iova_tree
->iova_taddr_map
);
60 * Find the IOVA address stored from a memory address
62 * @tree: The iova tree
63 * @map: The map with the memory address
65 * Return the stored mapping, or NULL if not found.
67 const DMAMap
*vhost_iova_tree_find_iova(const VhostIOVATree
*tree
,
70 return iova_tree_find_iova(tree
->iova_taddr_map
, map
);
74 * Allocate a new mapping
76 * @tree: The iova tree
80 * - IOVA_OK if the map fits in the container
81 * - IOVA_ERR_INVALID if the map does not make sense (like size overflow)
82 * - IOVA_ERR_NOMEM if tree cannot allocate more space.
84 * It returns assignated iova in map->iova if return value is VHOST_DMA_MAP_OK.
86 int vhost_iova_tree_map_alloc(VhostIOVATree
*tree
, DMAMap
*map
)
88 /* Some vhost devices do not like addr 0. Skip first page */
89 hwaddr iova_first
= tree
->iova_first
?: qemu_real_host_page_size();
91 if (map
->translated_addr
+ map
->size
< map
->translated_addr
||
92 map
->perm
== IOMMU_NONE
) {
93 return IOVA_ERR_INVALID
;
96 /* Allocate a node in IOVA address */
97 return iova_tree_alloc_map(tree
->iova_taddr_map
, map
, iova_first
,
102 * Remove existing mappings from iova tree
104 * @iova_tree: The vhost iova tree
105 * @map: The map to remove
107 void vhost_iova_tree_remove(VhostIOVATree
*iova_tree
, const DMAMap
*map
)
109 iova_tree_remove(iova_tree
->iova_taddr_map
, map
);