/*
 * A sparse memory device. Useful for fuzzing
 *
 * Copyright Red Hat Inc., 2021
 *
 * Authors:
 *  Alexander Bulekov   <alxndr@bu.edu>
 *
 * 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 "qemu/osdep.h"
#include "qemu/error-report.h"

#include "hw/qdev-properties.h"
#include "hw/sysbus.h"
#include "qapi/error.h"
#include "qemu/units.h"
#include "sysemu/qtest.h"
#include "hw/mem/sparse-mem.h"

#define SPARSE_MEM(obj) OBJECT_CHECK(SparseMemState, (obj), TYPE_SPARSE_MEM)
#define SPARSE_BLOCK_SIZE 0x1000

typedef struct SparseMemState {
    SysBusDevice parent_obj;
    MemoryRegion mmio;
    uint64_t baseaddr;
    uint64_t length;
    uint64_t size_used;
    uint64_t maxsize;
    GHashTable *mapped;
} SparseMemState;

typedef struct sparse_mem_block {
    uint8_t data[SPARSE_BLOCK_SIZE];
} sparse_mem_block;

static uint64_t sparse_mem_read(void *opaque, hwaddr addr, unsigned int size)
{
    SparseMemState *s = opaque;
    uint64_t ret = 0;
    size_t pfn = addr / SPARSE_BLOCK_SIZE;
    size_t offset = addr % SPARSE_BLOCK_SIZE;
    sparse_mem_block *block;

    block = g_hash_table_lookup(s->mapped, (void *)pfn);
    if (block) {
        assert(offset + size <= sizeof(block->data));
        memcpy(&ret, block->data + offset, size);
    }
    return ret;
}

static void sparse_mem_write(void *opaque, hwaddr addr, uint64_t v,
                             unsigned int size)
{
    SparseMemState *s = opaque;
    size_t pfn = addr / SPARSE_BLOCK_SIZE;
    size_t offset = addr % SPARSE_BLOCK_SIZE;
    sparse_mem_block *block;

    if (!g_hash_table_lookup(s->mapped, (void *)pfn) &&
        s->size_used + SPARSE_BLOCK_SIZE < s->maxsize && v) {
        g_hash_table_insert(s->mapped, (void *)pfn,
                            g_new0(sparse_mem_block, 1));
        s->size_used += sizeof(block->data);
    }
    block = g_hash_table_lookup(s->mapped, (void *)pfn);
    if (!block) {
        return;
    }

    assert(offset + size <= sizeof(block->data));

    memcpy(block->data + offset, &v, size);

}

static void sparse_mem_enter_reset(Object *obj, ResetType type)
{
    SparseMemState *s = SPARSE_MEM(obj);
    g_hash_table_remove_all(s->mapped);
    return;
}

static const MemoryRegionOps sparse_mem_ops = {
    .read = sparse_mem_read,
    .write = sparse_mem_write,
    .endianness = DEVICE_LITTLE_ENDIAN,
    .valid = {
            .min_access_size = 1,
            .max_access_size = 8,
            .unaligned = false,
        },
};

static Property sparse_mem_properties[] = {
    /* The base address of the memory */
    DEFINE_PROP_UINT64("baseaddr", SparseMemState, baseaddr, 0x0),
    /* The length of the sparse memory region */
    DEFINE_PROP_UINT64("length", SparseMemState, length, UINT64_MAX),
    /* Max amount of actual memory that can be used to back the sparse memory */
    DEFINE_PROP_UINT64("maxsize", SparseMemState, maxsize, 10 * MiB),
    DEFINE_PROP_END_OF_LIST(),
};

MemoryRegion *sparse_mem_init(uint64_t addr, uint64_t length)
{
    DeviceState *dev;

    dev = qdev_new(TYPE_SPARSE_MEM);
    qdev_prop_set_uint64(dev, "baseaddr", addr);
    qdev_prop_set_uint64(dev, "length", length);
    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
    sysbus_mmio_map_overlap(SYS_BUS_DEVICE(dev), 0, addr, -10000);
    return &SPARSE_MEM(dev)->mmio;
}

static void sparse_mem_realize(DeviceState *dev, Error **errp)
{
    SparseMemState *s = SPARSE_MEM(dev);
    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);

    if (!qtest_enabled()) {
        error_setg(errp, "sparse_mem device should only be used "
                         "for testing with QTest");
        return;
    }

    assert(s->baseaddr + s->length > s->baseaddr);

    s->mapped = g_hash_table_new_full(NULL, NULL, NULL,
                                      (GDestroyNotify)g_free);
    memory_region_init_io(&s->mmio, OBJECT(s), &sparse_mem_ops, s,
                          "sparse-mem", s->length);
    sysbus_init_mmio(sbd, &s->mmio);
}

static void sparse_mem_class_init(ObjectClass *klass, void *data)
{
    ResettableClass *rc = RESETTABLE_CLASS(klass);
    DeviceClass *dc = DEVICE_CLASS(klass);

    device_class_set_props(dc, sparse_mem_properties);

    dc->desc = "Sparse Memory Device";
    dc->realize = sparse_mem_realize;

    rc->phases.enter = sparse_mem_enter_reset;
}

static const TypeInfo sparse_mem_types[] = {
    {
        .name = TYPE_SPARSE_MEM,
        .parent = TYPE_SYS_BUS_DEVICE,
        .instance_size = sizeof(SparseMemState),
        .class_init = sparse_mem_class_init,
    },
};
DEFINE_TYPES(sparse_mem_types);
