/*
 * WHPX platform APIC support
 *
 * Copyright (c) 2011 Siemens AG
 *
 * Authors:
 *  Jan Kiszka          <jan.kiszka@siemens.com>
 *  John Starks         <jostarks@microsoft.com>
 *
 * This work is licensed under the terms of the GNU GPL version 2.
 * See the COPYING file in the top-level directory.
 */
#include "qemu/osdep.h"
#include "cpu.h"
#include "hw/i386/apic_internal.h"
#include "hw/i386/apic-msidef.h"
#include "hw/pci/msi.h"
#include "sysemu/hw_accel.h"
#include "sysemu/whpx.h"
#include "whpx-internal.h"

struct whpx_lapic_state {
    struct {
        uint32_t data;
        uint32_t padding[3];
    } fields[256];
};

static void whpx_put_apic_state(APICCommonState *s,
                                struct whpx_lapic_state *kapic)
{
    int i;

    memset(kapic, 0, sizeof(*kapic));
    kapic->fields[0x2].data = s->id << 24;
    kapic->fields[0x3].data = s->version | ((APIC_LVT_NB - 1) << 16);
    kapic->fields[0x8].data = s->tpr;
    kapic->fields[0xd].data = s->log_dest << 24;
    kapic->fields[0xe].data = s->dest_mode << 28 | 0x0fffffff;
    kapic->fields[0xf].data = s->spurious_vec;
    for (i = 0; i < 8; i++) {
        kapic->fields[0x10 + i].data = s->isr[i];
        kapic->fields[0x18 + i].data = s->tmr[i];
        kapic->fields[0x20 + i].data = s->irr[i];
    }

    kapic->fields[0x28].data = s->esr;
    kapic->fields[0x30].data = s->icr[0];
    kapic->fields[0x31].data = s->icr[1];
    for (i = 0; i < APIC_LVT_NB; i++) {
        kapic->fields[0x32 + i].data = s->lvt[i];
    }

    kapic->fields[0x38].data = s->initial_count;
    kapic->fields[0x3e].data = s->divide_conf;
}

static void whpx_get_apic_state(APICCommonState *s,
                                struct whpx_lapic_state *kapic)
{
    int i, v;

    s->id = kapic->fields[0x2].data >> 24;
    s->tpr = kapic->fields[0x8].data;
    s->arb_id = kapic->fields[0x9].data;
    s->log_dest = kapic->fields[0xd].data >> 24;
    s->dest_mode = kapic->fields[0xe].data >> 28;
    s->spurious_vec = kapic->fields[0xf].data;
    for (i = 0; i < 8; i++) {
        s->isr[i] = kapic->fields[0x10 + i].data;
        s->tmr[i] = kapic->fields[0x18 + i].data;
        s->irr[i] = kapic->fields[0x20 + i].data;
    }

    s->esr = kapic->fields[0x28].data;
    s->icr[0] = kapic->fields[0x30].data;
    s->icr[1] = kapic->fields[0x31].data;
    for (i = 0; i < APIC_LVT_NB; i++) {
        s->lvt[i] = kapic->fields[0x32 + i].data;
    }

    s->initial_count = kapic->fields[0x38].data;
    s->divide_conf = kapic->fields[0x3e].data;

    v = (s->divide_conf & 3) | ((s->divide_conf >> 1) & 4);
    s->count_shift = (v + 1) & 7;

    s->initial_count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
    apic_next_timer(s, s->initial_count_load_time);
}

static void whpx_apic_set_base(APICCommonState *s, uint64_t val)
{
    s->apicbase = val;
}

static void whpx_put_apic_base(CPUState *cpu, uint64_t val)
{
    HRESULT hr;
    WHV_REGISTER_VALUE reg_value = {.Reg64 = val};
    WHV_REGISTER_NAME reg_name = WHvX64RegisterApicBase;

    hr = whp_dispatch.WHvSetVirtualProcessorRegisters(
             whpx_global.partition,
             cpu->cpu_index,
             &reg_name, 1,
             &reg_value);

    if (FAILED(hr)) {
        error_report("WHPX: Failed to set MSR APIC base, hr=%08lx", hr);
    }
}

static void whpx_apic_set_tpr(APICCommonState *s, uint8_t val)
{
    s->tpr = val;
}

static uint8_t whpx_apic_get_tpr(APICCommonState *s)
{
    return s->tpr;
}

static void whpx_apic_vapic_base_update(APICCommonState *s)
{
    /* not implemented yet */
}

static void whpx_apic_put(CPUState *cs, run_on_cpu_data data)
{
    APICCommonState *s = data.host_ptr;
    struct whpx_lapic_state kapic;
    HRESULT hr;

    whpx_put_apic_base(CPU(s->cpu), s->apicbase);
    whpx_put_apic_state(s, &kapic);

    hr = whp_dispatch.WHvSetVirtualProcessorInterruptControllerState2(
        whpx_global.partition,
        cs->cpu_index,
        &kapic,
        sizeof(kapic));
    if (FAILED(hr)) {
        fprintf(stderr,
            "WHvSetVirtualProcessorInterruptControllerState failed: %08lx\n",
             hr);

        abort();
    }
}

void whpx_apic_get(DeviceState *dev)
{
    APICCommonState *s = APIC_COMMON(dev);
    CPUState *cpu = CPU(s->cpu);
    struct whpx_lapic_state kapic;

    HRESULT hr = whp_dispatch.WHvGetVirtualProcessorInterruptControllerState2(
        whpx_global.partition,
        cpu->cpu_index,
        &kapic,
        sizeof(kapic),
        NULL);
    if (FAILED(hr)) {
        fprintf(stderr,
            "WHvSetVirtualProcessorInterruptControllerState failed: %08lx\n",
            hr);

        abort();
    }

    whpx_get_apic_state(s, &kapic);
}

static void whpx_apic_post_load(APICCommonState *s)
{
    run_on_cpu(CPU(s->cpu), whpx_apic_put, RUN_ON_CPU_HOST_PTR(s));
}

static void whpx_apic_external_nmi(APICCommonState *s)
{
}

static void whpx_send_msi(MSIMessage *msg)
{
    uint64_t addr = msg->address;
    uint32_t data = msg->data;
    uint8_t dest = (addr & MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT;
    uint8_t vector = (data & MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SHIFT;
    uint8_t dest_mode = (addr >> MSI_ADDR_DEST_MODE_SHIFT) & 0x1;
    uint8_t trigger_mode = (data >> MSI_DATA_TRIGGER_SHIFT) & 0x1;
    uint8_t delivery = (data >> MSI_DATA_DELIVERY_MODE_SHIFT) & 0x7;

    WHV_INTERRUPT_CONTROL interrupt = {
        /* Values correspond to delivery modes */
        .Type = delivery,
        .DestinationMode = dest_mode ?
            WHvX64InterruptDestinationModeLogical :
            WHvX64InterruptDestinationModePhysical,

        .TriggerMode = trigger_mode ?
            WHvX64InterruptTriggerModeLevel : WHvX64InterruptTriggerModeEdge,
        .Reserved = 0,
        .Vector = vector,
        .Destination = dest,
    };
    HRESULT hr = whp_dispatch.WHvRequestInterrupt(whpx_global.partition,
                     &interrupt, sizeof(interrupt));
    if (FAILED(hr)) {
        fprintf(stderr, "whpx: injection failed, MSI (%llx, %x) delivery: %d, "
                "dest_mode: %d, trigger mode: %d, vector: %d, lost (%08lx)\n",
                addr, data, delivery, dest_mode, trigger_mode, vector, hr);
    }
}

static uint64_t whpx_apic_mem_read(void *opaque, hwaddr addr,
                                   unsigned size)
{
    return ~(uint64_t)0;
}

static void whpx_apic_mem_write(void *opaque, hwaddr addr,
                                uint64_t data, unsigned size)
{
    MSIMessage msg = { .address = addr, .data = data };
    whpx_send_msi(&msg);
}

static const MemoryRegionOps whpx_apic_io_ops = {
    .read = whpx_apic_mem_read,
    .write = whpx_apic_mem_write,
    .endianness = DEVICE_NATIVE_ENDIAN,
};

static void whpx_apic_reset(APICCommonState *s)
{
    /* Not used by WHPX. */
    s->wait_for_sipi = 0;

    run_on_cpu(CPU(s->cpu), whpx_apic_put, RUN_ON_CPU_HOST_PTR(s));
}

static void whpx_apic_realize(DeviceState *dev, Error **errp)
{
    APICCommonState *s = APIC_COMMON(dev);

    memory_region_init_io(&s->io_memory, OBJECT(s), &whpx_apic_io_ops, s,
                          "whpx-apic-msi", APIC_SPACE_SIZE);

    msi_nonbroken = true;
}

static void whpx_apic_class_init(ObjectClass *klass, void *data)
{
    APICCommonClass *k = APIC_COMMON_CLASS(klass);

    k->realize = whpx_apic_realize;
    k->reset = whpx_apic_reset;
    k->set_base = whpx_apic_set_base;
    k->set_tpr = whpx_apic_set_tpr;
    k->get_tpr = whpx_apic_get_tpr;
    k->post_load = whpx_apic_post_load;
    k->vapic_base_update = whpx_apic_vapic_base_update;
    k->external_nmi = whpx_apic_external_nmi;
    k->send_msi = whpx_send_msi;
}

static const TypeInfo whpx_apic_info = {
    .name = "whpx-apic",
    .parent = TYPE_APIC_COMMON,
    .instance_size = sizeof(APICCommonState),
    .class_init = whpx_apic_class_init,
};

static void whpx_apic_register_types(void)
{
    type_register_static(&whpx_apic_info);
}

type_init(whpx_apic_register_types)
