/*
 * Thread-safe guest to host memory mapping
 *
 * Copyright 2012 Red Hat, Inc. and/or its affiliates
 *
 * Authors:
 *   Stefan Hajnoczi <stefanha@redhat.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 * See the COPYING file in the top-level directory.
 *
 */

#include "exec/address-spaces.h"
#include "hw/virtio/dataplane/hostmem.h"

static int hostmem_lookup_cmp(const void *phys_, const void *region_)
{
    hwaddr phys = *(const hwaddr *)phys_;
    const HostMemRegion *region = region_;

    if (phys < region->guest_addr) {
        return -1;
    } else if (phys >= region->guest_addr + region->size) {
        return 1;
    } else {
        return 0;
    }
}

/**
 * Map guest physical address to host pointer
 */
void *hostmem_lookup(HostMem *hostmem, hwaddr phys, hwaddr len, bool is_write)
{
    HostMemRegion *region;
    void *host_addr = NULL;
    hwaddr offset_within_region;

    qemu_mutex_lock(&hostmem->current_regions_lock);
    region = bsearch(&phys, hostmem->current_regions,
                     hostmem->num_current_regions,
                     sizeof(hostmem->current_regions[0]),
                     hostmem_lookup_cmp);
    if (!region) {
        goto out;
    }
    if (is_write && region->readonly) {
        goto out;
    }
    offset_within_region = phys - region->guest_addr;
    if (len <= region->size - offset_within_region) {
        host_addr = region->host_addr + offset_within_region;
    }
out:
    qemu_mutex_unlock(&hostmem->current_regions_lock);

    return host_addr;
}

/**
 * Install new regions list
 */
static void hostmem_listener_commit(MemoryListener *listener)
{
    HostMem *hostmem = container_of(listener, HostMem, listener);

    qemu_mutex_lock(&hostmem->current_regions_lock);
    g_free(hostmem->current_regions);
    hostmem->current_regions = hostmem->new_regions;
    hostmem->num_current_regions = hostmem->num_new_regions;
    qemu_mutex_unlock(&hostmem->current_regions_lock);

    /* Reset new regions list */
    hostmem->new_regions = NULL;
    hostmem->num_new_regions = 0;
}

/**
 * Add a MemoryRegionSection to the new regions list
 */
static void hostmem_append_new_region(HostMem *hostmem,
                                      MemoryRegionSection *section)
{
    void *ram_ptr = memory_region_get_ram_ptr(section->mr);
    size_t num = hostmem->num_new_regions;
    size_t new_size = (num + 1) * sizeof(hostmem->new_regions[0]);

    hostmem->new_regions = g_realloc(hostmem->new_regions, new_size);
    hostmem->new_regions[num] = (HostMemRegion){
        .host_addr = ram_ptr + section->offset_within_region,
        .guest_addr = section->offset_within_address_space,
        .size = int128_get64(section->size),
        .readonly = section->readonly,
    };
    hostmem->num_new_regions++;
}

static void hostmem_listener_append_region(MemoryListener *listener,
                                           MemoryRegionSection *section)
{
    HostMem *hostmem = container_of(listener, HostMem, listener);

    /* Ignore non-RAM regions, we may not be able to map them */
    if (!memory_region_is_ram(section->mr)) {
        return;
    }

    /* Ignore regions with dirty logging, we cannot mark them dirty */
    if (memory_region_is_logging(section->mr)) {
        return;
    }

    hostmem_append_new_region(hostmem, section);
}

/* We don't implement most MemoryListener callbacks, use these nop stubs */
static void hostmem_listener_dummy(MemoryListener *listener)
{
}

static void hostmem_listener_section_dummy(MemoryListener *listener,
                                           MemoryRegionSection *section)
{
}

static void hostmem_listener_eventfd_dummy(MemoryListener *listener,
                                           MemoryRegionSection *section,
                                           bool match_data, uint64_t data,
                                           EventNotifier *e)
{
}

static void hostmem_listener_coalesced_mmio_dummy(MemoryListener *listener,
                                                  MemoryRegionSection *section,
                                                  hwaddr addr, hwaddr len)
{
}

void hostmem_init(HostMem *hostmem)
{
    memset(hostmem, 0, sizeof(*hostmem));

    qemu_mutex_init(&hostmem->current_regions_lock);

    hostmem->listener = (MemoryListener){
        .begin = hostmem_listener_dummy,
        .commit = hostmem_listener_commit,
        .region_add = hostmem_listener_append_region,
        .region_del = hostmem_listener_section_dummy,
        .region_nop = hostmem_listener_append_region,
        .log_start = hostmem_listener_section_dummy,
        .log_stop = hostmem_listener_section_dummy,
        .log_sync = hostmem_listener_section_dummy,
        .log_global_start = hostmem_listener_dummy,
        .log_global_stop = hostmem_listener_dummy,
        .eventfd_add = hostmem_listener_eventfd_dummy,
        .eventfd_del = hostmem_listener_eventfd_dummy,
        .coalesced_mmio_add = hostmem_listener_coalesced_mmio_dummy,
        .coalesced_mmio_del = hostmem_listener_coalesced_mmio_dummy,
        .priority = 10,
    };

    memory_listener_register(&hostmem->listener, &address_space_memory);
    if (hostmem->num_new_regions > 0) {
        hostmem_listener_commit(&hostmem->listener);
    }
}

void hostmem_finalize(HostMem *hostmem)
{
    memory_listener_unregister(&hostmem->listener);
    g_free(hostmem->new_regions);
    g_free(hostmem->current_regions);
    qemu_mutex_destroy(&hostmem->current_regions_lock);
}
