mirror of
				https://github.com/qemu/qemu.git
				synced 2025-10-31 20:44:16 +00:00 
			
		
		
		
	 8e3b0cbb72
			
		
	
	
		8e3b0cbb72
		
	
	
	
	
		
			
			Replace the global variables with inlined helper functions. getpagesize() is very likely annotated with a "const" function attribute (at least with glibc), and thus optimization should apply even better. This avoids the need for a constructor initialization too. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-Id: <20220323155743.1585078-12-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
		
			
				
	
	
		
			111 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			111 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * vhost software live migration iova tree
 | |
|  *
 | |
|  * SPDX-FileCopyrightText: Red Hat, Inc. 2021
 | |
|  * SPDX-FileContributor: Author: Eugenio Pérez <eperezma@redhat.com>
 | |
|  *
 | |
|  * SPDX-License-Identifier: GPL-2.0-or-later
 | |
|  */
 | |
| 
 | |
| #include "qemu/osdep.h"
 | |
| #include "qemu/iova-tree.h"
 | |
| #include "vhost-iova-tree.h"
 | |
| 
 | |
| #define iova_min_addr qemu_real_host_page_size()
 | |
| 
 | |
| /**
 | |
|  * VhostIOVATree, able to:
 | |
|  * - Translate iova address
 | |
|  * - Reverse translate iova address (from translated to iova)
 | |
|  * - Allocate IOVA regions for translated range (linear operation)
 | |
|  */
 | |
| struct VhostIOVATree {
 | |
|     /* First addressable iova address in the device */
 | |
|     uint64_t iova_first;
 | |
| 
 | |
|     /* Last addressable iova address in the device */
 | |
|     uint64_t iova_last;
 | |
| 
 | |
|     /* IOVA address to qemu memory maps. */
 | |
|     IOVATree *iova_taddr_map;
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Create a new IOVA tree
 | |
|  *
 | |
|  * Returns the new IOVA tree
 | |
|  */
 | |
| VhostIOVATree *vhost_iova_tree_new(hwaddr iova_first, hwaddr iova_last)
 | |
| {
 | |
|     VhostIOVATree *tree = g_new(VhostIOVATree, 1);
 | |
| 
 | |
|     /* Some devices do not like 0 addresses */
 | |
|     tree->iova_first = MAX(iova_first, iova_min_addr);
 | |
|     tree->iova_last = iova_last;
 | |
| 
 | |
|     tree->iova_taddr_map = iova_tree_new();
 | |
|     return tree;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Delete an iova tree
 | |
|  */
 | |
| void vhost_iova_tree_delete(VhostIOVATree *iova_tree)
 | |
| {
 | |
|     iova_tree_destroy(iova_tree->iova_taddr_map);
 | |
|     g_free(iova_tree);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Find the IOVA address stored from a memory address
 | |
|  *
 | |
|  * @tree: The iova tree
 | |
|  * @map: The map with the memory address
 | |
|  *
 | |
|  * Return the stored mapping, or NULL if not found.
 | |
|  */
 | |
| const DMAMap *vhost_iova_tree_find_iova(const VhostIOVATree *tree,
 | |
|                                         const DMAMap *map)
 | |
| {
 | |
|     return iova_tree_find_iova(tree->iova_taddr_map, map);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Allocate a new mapping
 | |
|  *
 | |
|  * @tree: The iova tree
 | |
|  * @map: The iova map
 | |
|  *
 | |
|  * Returns:
 | |
|  * - IOVA_OK if the map fits in the container
 | |
|  * - IOVA_ERR_INVALID if the map does not make sense (like size overflow)
 | |
|  * - IOVA_ERR_NOMEM if tree cannot allocate more space.
 | |
|  *
 | |
|  * It returns assignated iova in map->iova if return value is VHOST_DMA_MAP_OK.
 | |
|  */
 | |
| int vhost_iova_tree_map_alloc(VhostIOVATree *tree, DMAMap *map)
 | |
| {
 | |
|     /* Some vhost devices do not like addr 0. Skip first page */
 | |
|     hwaddr iova_first = tree->iova_first ?: qemu_real_host_page_size();
 | |
| 
 | |
|     if (map->translated_addr + map->size < map->translated_addr ||
 | |
|         map->perm == IOMMU_NONE) {
 | |
|         return IOVA_ERR_INVALID;
 | |
|     }
 | |
| 
 | |
|     /* Allocate a node in IOVA address */
 | |
|     return iova_tree_alloc_map(tree->iova_taddr_map, map, iova_first,
 | |
|                                tree->iova_last);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Remove existing mappings from iova tree
 | |
|  *
 | |
|  * @iova_tree: The vhost iova tree
 | |
|  * @map: The map to remove
 | |
|  */
 | |
| void vhost_iova_tree_remove(VhostIOVATree *iova_tree, const DMAMap *map)
 | |
| {
 | |
|     iova_tree_remove(iova_tree->iova_taddr_map, map);
 | |
| }
 |