qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

vhost-iova-tree.c (2840B)


      1 /*
      2  * vhost software live migration iova tree
      3  *
      4  * SPDX-FileCopyrightText: Red Hat, Inc. 2021
      5  * SPDX-FileContributor: Author: Eugenio Pérez <eperezma@redhat.com>
      6  *
      7  * SPDX-License-Identifier: GPL-2.0-or-later
      8  */
      9 
     10 #include "qemu/osdep.h"
     11 #include "qemu/iova-tree.h"
     12 #include "vhost-iova-tree.h"
     13 
     14 #define iova_min_addr qemu_real_host_page_size()
     15 
     16 /**
     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)
     21  */
     22 struct VhostIOVATree {
     23     /* First addressable iova address in the device */
     24     uint64_t iova_first;
     25 
     26     /* Last addressable iova address in the device */
     27     uint64_t iova_last;
     28 
     29     /* IOVA address to qemu memory maps. */
     30     IOVATree *iova_taddr_map;
     31 };
     32 
     33 /**
     34  * Create a new IOVA tree
     35  *
     36  * Returns the new IOVA tree
     37  */
     38 VhostIOVATree *vhost_iova_tree_new(hwaddr iova_first, hwaddr iova_last)
     39 {
     40     VhostIOVATree *tree = g_new(VhostIOVATree, 1);
     41 
     42     /* Some devices do not like 0 addresses */
     43     tree->iova_first = MAX(iova_first, iova_min_addr);
     44     tree->iova_last = iova_last;
     45 
     46     tree->iova_taddr_map = iova_tree_new();
     47     return tree;
     48 }
     49 
     50 /**
     51  * Delete an iova tree
     52  */
     53 void vhost_iova_tree_delete(VhostIOVATree *iova_tree)
     54 {
     55     iova_tree_destroy(iova_tree->iova_taddr_map);
     56     g_free(iova_tree);
     57 }
     58 
     59 /**
     60  * Find the IOVA address stored from a memory address
     61  *
     62  * @tree: The iova tree
     63  * @map: The map with the memory address
     64  *
     65  * Return the stored mapping, or NULL if not found.
     66  */
     67 const DMAMap *vhost_iova_tree_find_iova(const VhostIOVATree *tree,
     68                                         const DMAMap *map)
     69 {
     70     return iova_tree_find_iova(tree->iova_taddr_map, map);
     71 }
     72 
     73 /**
     74  * Allocate a new mapping
     75  *
     76  * @tree: The iova tree
     77  * @map: The iova map
     78  *
     79  * Returns:
     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.
     83  *
     84  * It returns assignated iova in map->iova if return value is VHOST_DMA_MAP_OK.
     85  */
     86 int vhost_iova_tree_map_alloc(VhostIOVATree *tree, DMAMap *map)
     87 {
     88     /* Some vhost devices do not like addr 0. Skip first page */
     89     hwaddr iova_first = tree->iova_first ?: qemu_real_host_page_size();
     90 
     91     if (map->translated_addr + map->size < map->translated_addr ||
     92         map->perm == IOMMU_NONE) {
     93         return IOVA_ERR_INVALID;
     94     }
     95 
     96     /* Allocate a node in IOVA address */
     97     return iova_tree_alloc_map(tree->iova_taddr_map, map, iova_first,
     98                                tree->iova_last);
     99 }
    100 
    101 /**
    102  * Remove existing mappings from iova tree
    103  *
    104  * @iova_tree: The vhost iova tree
    105  * @map: The map to remove
    106  */
    107 void vhost_iova_tree_remove(VhostIOVATree *iova_tree, DMAMap map)
    108 {
    109     iova_tree_remove(iova_tree->iova_taddr_map, map);
    110 }