mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-04 16:23:55 -06:00
util: implement simple iova tree
Introduce a simplest iova tree implementation based on GTree. CC: QEMU Stable <qemu-stable@nongnu.org> Signed-off-by: Peter Xu <peterx@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
d118c06ebb
commit
eecf5eedbd
4 changed files with 255 additions and 0 deletions
134
include/qemu/iova-tree.h
Normal file
134
include/qemu/iova-tree.h
Normal file
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* An very simplified iova tree implementation based on GTree.
|
||||
*
|
||||
* Copyright 2018 Red Hat, Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Peter Xu <peterx@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
*/
|
||||
#ifndef IOVA_TREE_H
|
||||
#define IOVA_TREE_H
|
||||
|
||||
/*
|
||||
* Currently the iova tree will only allow to keep ranges
|
||||
* information, and no extra user data is allowed for each element. A
|
||||
* benefit is that we can merge adjacent ranges internally within the
|
||||
* tree. It can save a lot of memory when the ranges are splitted but
|
||||
* mostly continuous.
|
||||
*
|
||||
* Note that current implementation does not provide any thread
|
||||
* protections. Callers of the iova tree should be responsible
|
||||
* for the thread safety issue.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "exec/memory.h"
|
||||
#include "exec/hwaddr.h"
|
||||
|
||||
#define IOVA_OK (0)
|
||||
#define IOVA_ERR_INVALID (-1) /* Invalid parameters */
|
||||
#define IOVA_ERR_OVERLAP (-2) /* IOVA range overlapped */
|
||||
|
||||
typedef struct IOVATree IOVATree;
|
||||
typedef struct DMAMap {
|
||||
hwaddr iova;
|
||||
hwaddr translated_addr;
|
||||
hwaddr size; /* Inclusive */
|
||||
IOMMUAccessFlags perm;
|
||||
} QEMU_PACKED DMAMap;
|
||||
typedef gboolean (*iova_tree_iterator)(DMAMap *map);
|
||||
|
||||
/**
|
||||
* iova_tree_new:
|
||||
*
|
||||
* Create a new iova tree.
|
||||
*
|
||||
* Returns: the tree pointer when succeeded, or NULL if error.
|
||||
*/
|
||||
IOVATree *iova_tree_new(void);
|
||||
|
||||
/**
|
||||
* iova_tree_insert:
|
||||
*
|
||||
* @tree: the iova tree to insert
|
||||
* @map: the mapping to insert
|
||||
*
|
||||
* Insert an iova range to the tree. If there is overlapped
|
||||
* ranges, IOVA_ERR_OVERLAP will be returned.
|
||||
*
|
||||
* Return: 0 if succeeded, or <0 if error.
|
||||
*/
|
||||
int iova_tree_insert(IOVATree *tree, DMAMap *map);
|
||||
|
||||
/**
|
||||
* iova_tree_remove:
|
||||
*
|
||||
* @tree: the iova tree to remove range from
|
||||
* @map: the map range to remove
|
||||
*
|
||||
* Remove mappings from the tree that are covered by the map range
|
||||
* provided. The range does not need to be exactly what has inserted,
|
||||
* all the mappings that are included in the provided range will be
|
||||
* removed from the tree. Here map->translated_addr is meaningless.
|
||||
*
|
||||
* Return: 0 if succeeded, or <0 if error.
|
||||
*/
|
||||
int iova_tree_remove(IOVATree *tree, DMAMap *map);
|
||||
|
||||
/**
|
||||
* iova_tree_find:
|
||||
*
|
||||
* @tree: the iova tree to search from
|
||||
* @map: the mapping to search
|
||||
*
|
||||
* Search for a mapping in the iova tree that overlaps with the
|
||||
* mapping range specified. Only the first found mapping will be
|
||||
* returned.
|
||||
*
|
||||
* Return: DMAMap pointer if found, or NULL if not found. Note that
|
||||
* the returned DMAMap pointer is maintained internally. User should
|
||||
* only read the content but never modify or free the content. Also,
|
||||
* user is responsible to make sure the pointer is valid (say, no
|
||||
* concurrent deletion in progress).
|
||||
*/
|
||||
DMAMap *iova_tree_find(IOVATree *tree, DMAMap *map);
|
||||
|
||||
/**
|
||||
* iova_tree_find_address:
|
||||
*
|
||||
* @tree: the iova tree to search from
|
||||
* @iova: the iova address to find
|
||||
*
|
||||
* Similar to iova_tree_find(), but it tries to find mapping with
|
||||
* range iova=iova & size=0.
|
||||
*
|
||||
* Return: same as iova_tree_find().
|
||||
*/
|
||||
DMAMap *iova_tree_find_address(IOVATree *tree, hwaddr iova);
|
||||
|
||||
/**
|
||||
* iova_tree_foreach:
|
||||
*
|
||||
* @tree: the iova tree to iterate on
|
||||
* @iterator: the interator for the mappings, return true to stop
|
||||
*
|
||||
* Iterate over the iova tree.
|
||||
*
|
||||
* Return: 1 if found any overlap, 0 if not, <0 if error.
|
||||
*/
|
||||
void iova_tree_foreach(IOVATree *tree, iova_tree_iterator iterator);
|
||||
|
||||
/**
|
||||
* iova_tree_destroy:
|
||||
*
|
||||
* @tree: the iova tree to destroy
|
||||
*
|
||||
* Destroy an existing iova tree.
|
||||
*
|
||||
* Return: None.
|
||||
*/
|
||||
void iova_tree_destroy(IOVATree *tree);
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue