/*
 * QEMU KVM Hyper-V test device to support Hyper-V kvm-unit-tests
 *
 * Copyright (C) 2015 Andrey Smetanin <asmetanin@virtuozzo.com>
 *
 * Authors:
 *  Andrey Smetanin <asmetanin@virtuozzo.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 "qemu/osdep.h"
#include <linux/kvm.h>
#include "hw/hw.h"
#include "hw/qdev.h"
#include "hw/isa/isa.h"
#include "sysemu/kvm.h"
#include "target/i386/hyperv.h"
#include "kvm_i386.h"

#define HV_TEST_DEV_MAX_SINT_ROUTES 64

struct HypervTestDev {
    ISADevice parent_obj;
    MemoryRegion sint_control;
    HvSintRoute *sint_route[HV_TEST_DEV_MAX_SINT_ROUTES];
};
typedef struct HypervTestDev HypervTestDev;

#define TYPE_HYPERV_TEST_DEV "hyperv-testdev"
#define HYPERV_TEST_DEV(obj) \
        OBJECT_CHECK(HypervTestDev, (obj), TYPE_HYPERV_TEST_DEV)

enum {
    HV_TEST_DEV_SINT_ROUTE_CREATE = 1,
    HV_TEST_DEV_SINT_ROUTE_DESTROY,
    HV_TEST_DEV_SINT_ROUTE_SET_SINT
};

static int alloc_sint_route_index(HypervTestDev *dev)
{
    int i;

    for (i = 0; i < ARRAY_SIZE(dev->sint_route); i++) {
        if (dev->sint_route[i] == NULL) {
            return i;
        }
    }
    return -1;
}

static void free_sint_route_index(HypervTestDev *dev, int i)
{
    assert(i >= 0 && i < ARRAY_SIZE(dev->sint_route));
    dev->sint_route[i] = NULL;
}

static int find_sint_route_index(HypervTestDev *dev, uint32_t vp_index,
                                 uint32_t sint)
{
    HvSintRoute *sint_route;
    int i;

    for (i = 0; i < ARRAY_SIZE(dev->sint_route); i++) {
        sint_route = dev->sint_route[i];
        if (sint_route && sint_route->vp_index == vp_index &&
            sint_route->sint == sint) {
            return i;
        }
    }
    return -1;
}

static void hv_synic_test_dev_control(HypervTestDev *dev, uint32_t ctl,
                                      uint32_t vp_index, uint32_t sint)
{
    int i;
    HvSintRoute *sint_route;

    switch (ctl) {
    case HV_TEST_DEV_SINT_ROUTE_CREATE:
        i = alloc_sint_route_index(dev);
        assert(i >= 0);
        sint_route = kvm_hv_sint_route_create(vp_index, sint, NULL);
        assert(sint_route);
        dev->sint_route[i] = sint_route;
        break;
    case HV_TEST_DEV_SINT_ROUTE_DESTROY:
        i = find_sint_route_index(dev, vp_index, sint);
        assert(i >= 0);
        sint_route = dev->sint_route[i];
        kvm_hv_sint_route_destroy(sint_route);
        free_sint_route_index(dev, i);
        break;
    case HV_TEST_DEV_SINT_ROUTE_SET_SINT:
        i = find_sint_route_index(dev, vp_index, sint);
        assert(i >= 0);
        sint_route = dev->sint_route[i];
        kvm_hv_sint_route_set_sint(sint_route);
        break;
    default:
        break;
    }
}

static void hv_test_dev_control(void *opaque, hwaddr addr, uint64_t data,
                                uint32_t len)
{
    HypervTestDev *dev = HYPERV_TEST_DEV(opaque);
    uint8_t ctl;

    ctl = (data >> 16ULL) & 0xFF;
    switch (ctl) {
    case HV_TEST_DEV_SINT_ROUTE_CREATE:
    case HV_TEST_DEV_SINT_ROUTE_DESTROY:
    case HV_TEST_DEV_SINT_ROUTE_SET_SINT: {
        uint8_t sint = data & 0xFF;
        uint8_t vp_index = (data >> 8ULL) & 0xFF;
        hv_synic_test_dev_control(dev, ctl, vp_index, sint);
        break;
    }
    default:
        break;
    }
}

static const MemoryRegionOps synic_test_sint_ops = {
    .write = hv_test_dev_control,
    .valid.min_access_size = 4,
    .valid.max_access_size = 4,
    .endianness = DEVICE_LITTLE_ENDIAN,
};

static void hv_test_dev_realizefn(DeviceState *d, Error **errp)
{
    ISADevice *isa = ISA_DEVICE(d);
    HypervTestDev *dev = HYPERV_TEST_DEV(d);
    MemoryRegion *io = isa_address_space_io(isa);

    memset(dev->sint_route, 0, sizeof(dev->sint_route));
    memory_region_init_io(&dev->sint_control, OBJECT(dev),
                          &synic_test_sint_ops, dev,
                          "hyperv-testdev-ctl", 4);
    memory_region_add_subregion(io, 0x3000, &dev->sint_control);
}

static void hv_test_dev_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);

    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
    dc->realize = hv_test_dev_realizefn;
}

static const TypeInfo hv_test_dev_info = {
    .name           = TYPE_HYPERV_TEST_DEV,
    .parent         = TYPE_ISA_DEVICE,
    .instance_size  = sizeof(HypervTestDev),
    .class_init     = hv_test_dev_class_init,
};

static void hv_test_dev_register_types(void)
{
    type_register_static(&hv_test_dev_info);
}
type_init(hv_test_dev_register_types);
