/*
 * 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.
 */

#include "qemu/osdep.h"
#include "qemu/iova-tree.h"

struct IOVATree {
    GTree *tree;
};

/* Args to pass to iova_tree_alloc foreach function. */
struct IOVATreeAllocArgs {
    /* Size of the desired allocation */
    size_t new_size;

    /* The minimum address allowed in the allocation */
    hwaddr iova_begin;

    /* Map at the left of the hole, can be NULL if "this" is first one */
    const DMAMap *prev;

    /* Map at the right of the hole, can be NULL if "prev" is the last one */
    const DMAMap *this;

    /* If found, we fill in the IOVA here */
    hwaddr iova_result;

    /* Whether have we found a valid IOVA */
    bool iova_found;
};

typedef struct IOVATreeFindIOVAArgs {
    const DMAMap *needle;
    const DMAMap *result;
} IOVATreeFindIOVAArgs;

/**
 * Iterate args to the next hole
 *
 * @args: The alloc arguments
 * @next: The next mapping in the tree. Can be NULL to signal the last one
 */
static void iova_tree_alloc_args_iterate(struct IOVATreeAllocArgs *args,
                                         const DMAMap *next)
{
    args->prev = args->this;
    args->this = next;
}

static int iova_tree_compare(gconstpointer a, gconstpointer b, gpointer data)
{
    const DMAMap *m1 = a, *m2 = b;

    if (m1->iova > m2->iova + m2->size) {
        return 1;
    }

    if (m1->iova + m1->size < m2->iova) {
        return -1;
    }

    /* Overlapped */
    return 0;
}

IOVATree *iova_tree_new(void)
{
    IOVATree *iova_tree = g_new0(IOVATree, 1);

    /* We don't have values actually, no need to free */
    iova_tree->tree = g_tree_new_full(iova_tree_compare, NULL, g_free, NULL);

    return iova_tree;
}

const DMAMap *iova_tree_find(const IOVATree *tree, const DMAMap *map)
{
    return g_tree_lookup(tree->tree, map);
}

static gboolean iova_tree_find_address_iterator(gpointer key, gpointer value,
                                                gpointer data)
{
    const DMAMap *map = key;
    IOVATreeFindIOVAArgs *args = data;
    const DMAMap *needle;

    g_assert(key == value);

    needle = args->needle;
    if (map->translated_addr + map->size < needle->translated_addr ||
        needle->translated_addr + needle->size < map->translated_addr) {
        return false;
    }

    args->result = map;
    return true;
}

const DMAMap *iova_tree_find_iova(const IOVATree *tree, const DMAMap *map)
{
    IOVATreeFindIOVAArgs args = {
        .needle = map,
    };

    g_tree_foreach(tree->tree, iova_tree_find_address_iterator, &args);
    return args.result;
}

const DMAMap *iova_tree_find_address(const IOVATree *tree, hwaddr iova)
{
    const DMAMap map = { .iova = iova, .size = 0 };

    return iova_tree_find(tree, &map);
}

static inline void iova_tree_insert_internal(GTree *gtree, DMAMap *range)
{
    /* Key and value are sharing the same range data */
    g_tree_insert(gtree, range, range);
}

int iova_tree_insert(IOVATree *tree, const DMAMap *map)
{
    DMAMap *new;

    if (map->iova + map->size < map->iova || map->perm == IOMMU_NONE) {
        return IOVA_ERR_INVALID;
    }

    /* We don't allow to insert range that overlaps with existings */
    if (iova_tree_find(tree, map)) {
        return IOVA_ERR_OVERLAP;
    }

    new = g_new0(DMAMap, 1);
    memcpy(new, map, sizeof(*new));
    iova_tree_insert_internal(tree->tree, new);

    return IOVA_OK;
}

static gboolean iova_tree_traverse(gpointer key, gpointer value,
                                gpointer data)
{
    iova_tree_iterator iterator = data;
    DMAMap *map = key;

    g_assert(key == value);

    return iterator(map);
}

void iova_tree_foreach(IOVATree *tree, iova_tree_iterator iterator)
{
    g_tree_foreach(tree->tree, iova_tree_traverse, iterator);
}

void iova_tree_remove(IOVATree *tree, const DMAMap *map)
{
    const DMAMap *overlap;

    while ((overlap = iova_tree_find(tree, map))) {
        g_tree_remove(tree->tree, overlap);
    }
}

/**
 * Try to find an unallocated IOVA range between prev and this elements.
 *
 * @args: Arguments to allocation
 *
 * Cases:
 *
 * (1) !prev, !this: No entries allocated, always succeed
 *
 * (2) !prev, this: We're iterating at the 1st element.
 *
 * (3) prev, !this: We're iterating at the last element.
 *
 * (4) prev, this: this is the most common case, we'll try to find a hole
 * between "prev" and "this" mapping.
 *
 * Note that this function assumes the last valid iova is HWADDR_MAX, but it
 * searches linearly so it's easy to discard the result if it's not the case.
 */
static void iova_tree_alloc_map_in_hole(struct IOVATreeAllocArgs *args)
{
    const DMAMap *prev = args->prev, *this = args->this;
    uint64_t hole_start, hole_last;

    if (this && this->iova + this->size < args->iova_begin) {
        return;
    }

    hole_start = MAX(prev ? prev->iova + prev->size + 1 : 0, args->iova_begin);
    hole_last = this ? this->iova : HWADDR_MAX;

    if (hole_last - hole_start > args->new_size) {
        args->iova_result = hole_start;
        args->iova_found = true;
    }
}

/**
 * Foreach dma node in the tree, compare if there is a hole with its previous
 * node (or minimum iova address allowed) and the node.
 *
 * @key: Node iterating
 * @value: Node iterating
 * @pargs: Struct to communicate with the outside world
 *
 * Return: false to keep iterating, true if needs break.
 */
static gboolean iova_tree_alloc_traverse(gpointer key, gpointer value,
                                         gpointer pargs)
{
    struct IOVATreeAllocArgs *args = pargs;
    DMAMap *node = value;

    assert(key == value);

    iova_tree_alloc_args_iterate(args, node);
    iova_tree_alloc_map_in_hole(args);
    return args->iova_found;
}

int iova_tree_alloc_map(IOVATree *tree, DMAMap *map, hwaddr iova_begin,
                        hwaddr iova_last)
{
    struct IOVATreeAllocArgs args = {
        .new_size = map->size,
        .iova_begin = iova_begin,
    };

    if (unlikely(iova_last < iova_begin)) {
        return IOVA_ERR_INVALID;
    }

    /*
     * Find a valid hole for the mapping
     *
     * Assuming low iova_begin, so no need to do a binary search to
     * locate the first node.
     *
     * TODO: Replace all this with g_tree_node_first/next/last when available
     * (from glib since 2.68). To do it with g_tree_foreach complicates the
     * code a lot.
     *
     */
    g_tree_foreach(tree->tree, iova_tree_alloc_traverse, &args);
    if (!args.iova_found) {
        /*
         * Either tree is empty or the last hole is still not checked.
         * g_tree_foreach does not compare (last, iova_last] range, so we check
         * it here.
         */
        iova_tree_alloc_args_iterate(&args, NULL);
        iova_tree_alloc_map_in_hole(&args);
    }

    if (!args.iova_found || args.iova_result + map->size > iova_last) {
        return IOVA_ERR_NOMEM;
    }

    map->iova = args.iova_result;
    return iova_tree_insert(tree, map);
}

void iova_tree_destroy(IOVATree *tree)
{
    g_tree_destroy(tree->tree);
    g_free(tree);
}
