/*
 * QEMU sPAPR VIO code
 *
 * Copyright (c) 2010 David Gibson, IBM Corporation <dwg@au1.ibm.com>
 * Based on the s390 virtio bus code:
 * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */

#include "qemu/osdep.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
#include "qapi/visitor.h"
#include "qemu/log.h"
#include "hw/loader.h"
#include "elf.h"
#include "hw/sysbus.h"
#include "sysemu/kvm.h"
#include "sysemu/device_tree.h"
#include "kvm_ppc.h"
#include "migration/vmstate.h"

#include "hw/ppc/spapr.h"
#include "hw/ppc/spapr_vio.h"
#include "hw/ppc/fdt.h"
#include "trace.h"

#include <libfdt.h>

#define SPAPR_VIO_REG_BASE 0x71000000

static char *spapr_vio_get_dev_name(DeviceState *qdev)
{
    SpaprVioDevice *dev = VIO_SPAPR_DEVICE(qdev);
    SpaprVioDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);

    /* Device tree style name device@reg */
    return g_strdup_printf("%s@%x", pc->dt_name, dev->reg);
}

static void spapr_vio_bus_class_init(ObjectClass *klass, void *data)
{
    BusClass *k = BUS_CLASS(klass);

    k->get_dev_path = spapr_vio_get_dev_name;
    k->get_fw_dev_path = spapr_vio_get_dev_name;
}

static const TypeInfo spapr_vio_bus_info = {
    .name = TYPE_SPAPR_VIO_BUS,
    .parent = TYPE_BUS,
    .class_init = spapr_vio_bus_class_init,
    .instance_size = sizeof(SpaprVioBus),
};

SpaprVioDevice *spapr_vio_find_by_reg(SpaprVioBus *bus, uint32_t reg)
{
    BusChild *kid;
    SpaprVioDevice *dev = NULL;

    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
        dev = (SpaprVioDevice *)kid->child;
        if (dev->reg == reg) {
            return dev;
        }
    }

    return NULL;
}

static int vio_make_devnode(SpaprVioDevice *dev,
                            void *fdt)
{
    SpaprVioDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
    int vdevice_off, node_off, ret;
    char *dt_name;
    const char *dt_compatible;

    vdevice_off = fdt_path_offset(fdt, "/vdevice");
    if (vdevice_off < 0) {
        return vdevice_off;
    }

    dt_name = spapr_vio_get_dev_name(DEVICE(dev));
    node_off = fdt_add_subnode(fdt, vdevice_off, dt_name);
    g_free(dt_name);
    if (node_off < 0) {
        return node_off;
    }

    ret = fdt_setprop_cell(fdt, node_off, "reg", dev->reg);
    if (ret < 0) {
        return ret;
    }

    if (pc->dt_type) {
        ret = fdt_setprop_string(fdt, node_off, "device_type",
                                 pc->dt_type);
        if (ret < 0) {
            return ret;
        }
    }

    if (pc->get_dt_compatible) {
        dt_compatible = pc->get_dt_compatible(dev);
    } else {
        dt_compatible = pc->dt_compatible;
    }

    if (dt_compatible) {
        ret = fdt_setprop_string(fdt, node_off, "compatible",
                                 dt_compatible);
        if (ret < 0) {
            return ret;
        }
    }

    if (dev->irq) {
        uint32_t ints_prop[2];

        spapr_dt_irq(ints_prop, dev->irq, false);
        ret = fdt_setprop(fdt, node_off, "interrupts", ints_prop,
                          sizeof(ints_prop));
        if (ret < 0) {
            return ret;
        }
    }

    ret = spapr_tcet_dma_dt(fdt, node_off, "ibm,my-dma-window", dev->tcet);
    if (ret < 0) {
        return ret;
    }

    if (pc->devnode) {
        ret = (pc->devnode)(dev, fdt, node_off);
        if (ret < 0) {
            return ret;
        }
    }

    return node_off;
}

/*
 * CRQ handling
 */
static target_ulong h_reg_crq(PowerPCCPU *cpu, SpaprMachineState *spapr,
                              target_ulong opcode, target_ulong *args)
{
    target_ulong reg = args[0];
    target_ulong queue_addr = args[1];
    target_ulong queue_len = args[2];
    SpaprVioDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);

    if (!dev) {
        hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
        return H_PARAMETER;
    }

    /* We can't grok a queue size bigger than 256M for now */
    if (queue_len < 0x1000 || queue_len > 0x10000000) {
        hcall_dprintf("Queue size too small or too big (0x" TARGET_FMT_lx
                      ")\n", queue_len);
        return H_PARAMETER;
    }

    /* Check queue alignment */
    if (queue_addr & 0xfff) {
        hcall_dprintf("Queue not aligned (0x" TARGET_FMT_lx ")\n", queue_addr);
        return H_PARAMETER;
    }

    /* Check if device supports CRQs */
    if (!dev->crq.SendFunc) {
        hcall_dprintf("Device does not support CRQ\n");
        return H_NOT_FOUND;
    }

    /* Already a queue ? */
    if (dev->crq.qsize) {
        hcall_dprintf("CRQ already registered\n");
        return H_RESOURCE;
    }
    dev->crq.qladdr = queue_addr;
    dev->crq.qsize = queue_len;
    dev->crq.qnext = 0;

    trace_spapr_vio_h_reg_crq(reg, queue_addr, queue_len);
    return H_SUCCESS;
}

static target_ulong free_crq(SpaprVioDevice *dev)
{
    dev->crq.qladdr = 0;
    dev->crq.qsize = 0;
    dev->crq.qnext = 0;

    trace_spapr_vio_free_crq(dev->reg);

    return H_SUCCESS;
}

static target_ulong h_free_crq(PowerPCCPU *cpu, SpaprMachineState *spapr,
                               target_ulong opcode, target_ulong *args)
{
    target_ulong reg = args[0];
    SpaprVioDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);

    if (!dev) {
        hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
        return H_PARAMETER;
    }

    return free_crq(dev);
}

static target_ulong h_send_crq(PowerPCCPU *cpu, SpaprMachineState *spapr,
                               target_ulong opcode, target_ulong *args)
{
    target_ulong reg = args[0];
    target_ulong msg_hi = args[1];
    target_ulong msg_lo = args[2];
    SpaprVioDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
    uint64_t crq_mangle[2];

    if (!dev) {
        hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
        return H_PARAMETER;
    }
    crq_mangle[0] = cpu_to_be64(msg_hi);
    crq_mangle[1] = cpu_to_be64(msg_lo);

    if (dev->crq.SendFunc) {
        return dev->crq.SendFunc(dev, (uint8_t *)crq_mangle);
    }

    return H_HARDWARE;
}

static target_ulong h_enable_crq(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                 target_ulong opcode, target_ulong *args)
{
    target_ulong reg = args[0];
    SpaprVioDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);

    if (!dev) {
        hcall_dprintf("Unit 0x" TARGET_FMT_lx " does not exist\n", reg);
        return H_PARAMETER;
    }

    return 0;
}

/* Returns negative error, 0 success, or positive: queue full */
int spapr_vio_send_crq(SpaprVioDevice *dev, uint8_t *crq)
{
    int rc;
    uint8_t byte;

    if (!dev->crq.qsize) {
        error_report("spapr_vio_send_creq on uninitialized queue");
        return -1;
    }

    /* Maybe do a fast path for KVM just writing to the pages */
    rc = spapr_vio_dma_read(dev, dev->crq.qladdr + dev->crq.qnext, &byte, 1);
    if (rc) {
        return rc;
    }
    if (byte != 0) {
        return 1;
    }

    rc = spapr_vio_dma_write(dev, dev->crq.qladdr + dev->crq.qnext + 8,
                             &crq[8], 8);
    if (rc) {
        return rc;
    }

    kvmppc_eieio();

    rc = spapr_vio_dma_write(dev, dev->crq.qladdr + dev->crq.qnext, crq, 8);
    if (rc) {
        return rc;
    }

    dev->crq.qnext = (dev->crq.qnext + 16) % dev->crq.qsize;

    if (dev->signal_state & 1) {
        spapr_vio_irq_pulse(dev);
    }

    return 0;
}

/* "quiesce" handling */

static void spapr_vio_quiesce_one(SpaprVioDevice *dev)
{
    if (dev->tcet) {
        device_cold_reset(DEVICE(dev->tcet));
    }
    free_crq(dev);
}

void spapr_vio_set_bypass(SpaprVioDevice *dev, bool bypass)
{
    if (!dev->tcet) {
        return;
    }

    memory_region_set_enabled(&dev->mrbypass, bypass);
    memory_region_set_enabled(spapr_tce_get_iommu(dev->tcet), !bypass);

    dev->tcet->bypass = bypass;
}

static void rtas_set_tce_bypass(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                uint32_t token,
                                uint32_t nargs, target_ulong args,
                                uint32_t nret, target_ulong rets)
{
    SpaprVioBus *bus = spapr->vio_bus;
    SpaprVioDevice *dev;
    uint32_t unit, enable;

    if (nargs != 2) {
        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
        return;
    }
    unit = rtas_ld(args, 0);
    enable = rtas_ld(args, 1);
    dev = spapr_vio_find_by_reg(bus, unit);
    if (!dev) {
        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
        return;
    }

    if (!dev->tcet) {
        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
        return;
    }

    spapr_vio_set_bypass(dev, !!enable);

    rtas_st(rets, 0, RTAS_OUT_SUCCESS);
}

static void rtas_quiesce(PowerPCCPU *cpu, SpaprMachineState *spapr,
                         uint32_t token,
                         uint32_t nargs, target_ulong args,
                         uint32_t nret, target_ulong rets)
{
    SpaprVioBus *bus = spapr->vio_bus;
    BusChild *kid;
    SpaprVioDevice *dev = NULL;

    if (nargs != 0) {
        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
        return;
    }

    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
        dev = (SpaprVioDevice *)kid->child;
        spapr_vio_quiesce_one(dev);
    }

    rtas_st(rets, 0, RTAS_OUT_SUCCESS);
}

static SpaprVioDevice *reg_conflict(SpaprVioDevice *dev)
{
    SpaprVioBus *bus = SPAPR_VIO_BUS(dev->qdev.parent_bus);
    BusChild *kid;
    SpaprVioDevice *other;

    /*
     * Check for a device other than the given one which is already
     * using the requested address. We have to open code this because
     * the given dev might already be in the list.
     */
    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
        other = VIO_SPAPR_DEVICE(kid->child);

        if (other != dev && other->reg == dev->reg) {
            return other;
        }
    }

    return 0;
}

static void spapr_vio_busdev_reset(DeviceState *qdev)
{
    SpaprVioDevice *dev = VIO_SPAPR_DEVICE(qdev);
    SpaprVioDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);

    /* Shut down the request queue and TCEs if necessary */
    spapr_vio_quiesce_one(dev);

    dev->signal_state = 0;

    spapr_vio_set_bypass(dev, false);
    if (pc->reset) {
        pc->reset(dev);
    }
}

/*
 * The register property of a VIO device is defined in libvirt using
 * 0x1000 as a base register number plus a 0x1000 increment. For the
 * VIO tty device, the base number is changed to 0x30000000. QEMU uses
 * a base register number of 0x71000000 and then a simple increment.
 *
 * The formula below tries to compute a unique index number from the
 * register value that will be used to define the IRQ number of the
 * VIO device.
 *
 * A maximum of 256 VIO devices is covered. Collisions are possible
 * but they will be detected when the IRQ is claimed.
 */
static inline uint32_t spapr_vio_reg_to_irq(uint32_t reg)
{
    uint32_t irq;

    if (reg >= SPAPR_VIO_REG_BASE) {
        /*
         * VIO device register values when allocated by QEMU. For
         * these, we simply mask the high bits to fit the overall
         * range: [0x00 - 0xff].
         *
         * The nvram VIO device (reg=0x71000000) is a static device of
         * the pseries machine and so is always allocated by QEMU. Its
         * IRQ number is 0x0.
         */
        irq = reg & 0xff;

    } else if (reg >= 0x30000000) {
        /*
         * VIO tty devices register values, when allocated by libvirt,
         * are mapped in range [0xf0 - 0xff], gives us a maximum of 16
         * vtys.
         */
        irq = 0xf0 | ((reg >> 12) & 0xf);

    } else {
        /*
         * Other VIO devices register values, when allocated by
         * libvirt, should be mapped in range [0x00 - 0xef]. Conflicts
         * will be detected when IRQ is claimed.
         */
        irq = (reg >> 12) & 0xff;
    }

    return SPAPR_IRQ_VIO | irq;
}

static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp)
{
    SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
    SpaprVioDevice *dev = (SpaprVioDevice *)qdev;
    SpaprVioDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
    char *id;

    if (dev->reg != -1) {
        /*
         * Explicitly assigned address, just verify that no-one else
         * is using it.  other mechanism). We have to open code this
         * rather than using spapr_vio_find_by_reg() because sdev
         * itself is already in the list.
         */
        SpaprVioDevice *other = reg_conflict(dev);

        if (other) {
            error_setg(errp, "%s and %s devices conflict at address %#x",
                       object_get_typename(OBJECT(qdev)),
                       object_get_typename(OBJECT(&other->qdev)),
                       dev->reg);
            return;
        }
    } else {
        /* Need to assign an address */
        SpaprVioBus *bus = SPAPR_VIO_BUS(dev->qdev.parent_bus);

        do {
            dev->reg = bus->next_reg++;
        } while (reg_conflict(dev));
    }

    /* Don't overwrite ids assigned on the command line */
    if (!dev->qdev.id) {
        id = spapr_vio_get_dev_name(DEVICE(dev));
        dev->qdev.id = id;
    }

    dev->irq = spapr_vio_reg_to_irq(dev->reg);

    if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
        int irq = spapr_irq_findone(spapr, errp);

        if (irq < 0) {
            return;
        }
        dev->irq = irq;
    }

    if (spapr_irq_claim(spapr, dev->irq, false, errp) < 0) {
        return;
    }

    if (pc->rtce_window_size) {
        uint32_t liobn = SPAPR_VIO_LIOBN(dev->reg);

        memory_region_init(&dev->mrroot, OBJECT(dev), "iommu-spapr-root",
                           MACHINE(spapr)->ram_size);
        memory_region_init_alias(&dev->mrbypass, OBJECT(dev),
                                 "iommu-spapr-bypass", get_system_memory(),
                                 0, MACHINE(spapr)->ram_size);
        memory_region_add_subregion_overlap(&dev->mrroot, 0, &dev->mrbypass, 1);
        address_space_init(&dev->as, &dev->mrroot, qdev->id);

        dev->tcet = spapr_tce_new_table(qdev, liobn);
        spapr_tce_table_enable(dev->tcet, SPAPR_TCE_PAGE_SHIFT, 0,
                               pc->rtce_window_size >> SPAPR_TCE_PAGE_SHIFT);
        dev->tcet->vdev = dev;
        memory_region_add_subregion_overlap(&dev->mrroot, 0,
                                            spapr_tce_get_iommu(dev->tcet), 2);
    }

    pc->realize(dev, errp);
}

static target_ulong h_vio_signal(PowerPCCPU *cpu, SpaprMachineState *spapr,
                                 target_ulong opcode,
                                 target_ulong *args)
{
    target_ulong reg = args[0];
    target_ulong mode = args[1];
    SpaprVioDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
    SpaprVioDeviceClass *pc;

    if (!dev) {
        return H_PARAMETER;
    }

    pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);

    if (mode & ~pc->signal_mask) {
        return H_PARAMETER;
    }

    dev->signal_state = mode;

    return H_SUCCESS;
}

SpaprVioBus *spapr_vio_bus_init(void)
{
    SpaprVioBus *bus;
    BusState *qbus;
    DeviceState *dev;

    /* Create bridge device */
    dev = qdev_new(TYPE_SPAPR_VIO_BRIDGE);
    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);

    /* Create bus on bridge device */
    qbus = qbus_new(TYPE_SPAPR_VIO_BUS, dev, "spapr-vio");
    bus = SPAPR_VIO_BUS(qbus);
    bus->next_reg = SPAPR_VIO_REG_BASE;

    /* hcall-vio */
    spapr_register_hypercall(H_VIO_SIGNAL, h_vio_signal);

    /* hcall-crq */
    spapr_register_hypercall(H_REG_CRQ, h_reg_crq);
    spapr_register_hypercall(H_FREE_CRQ, h_free_crq);
    spapr_register_hypercall(H_SEND_CRQ, h_send_crq);
    spapr_register_hypercall(H_ENABLE_CRQ, h_enable_crq);

    /* RTAS calls */
    spapr_rtas_register(RTAS_IBM_SET_TCE_BYPASS, "ibm,set-tce-bypass",
                        rtas_set_tce_bypass);
    spapr_rtas_register(RTAS_QUIESCE, "quiesce", rtas_quiesce);

    return bus;
}

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

    dc->fw_name = "vdevice";
}

static const TypeInfo spapr_vio_bridge_info = {
    .name          = TYPE_SPAPR_VIO_BRIDGE,
    .parent        = TYPE_SYS_BUS_DEVICE,
    .class_init    = spapr_vio_bridge_class_init,
};

const VMStateDescription vmstate_spapr_vio = {
    .name = "spapr_vio",
    .version_id = 1,
    .minimum_version_id = 1,
    .fields = (VMStateField[]) {
        /* Sanity check */
        VMSTATE_UINT32_EQUAL(reg, SpaprVioDevice, NULL),
        VMSTATE_UINT32_EQUAL(irq, SpaprVioDevice, NULL),

        /* General VIO device state */
        VMSTATE_UINT64(signal_state, SpaprVioDevice),
        VMSTATE_UINT64(crq.qladdr, SpaprVioDevice),
        VMSTATE_UINT32(crq.qsize, SpaprVioDevice),
        VMSTATE_UINT32(crq.qnext, SpaprVioDevice),

        VMSTATE_END_OF_LIST()
    },
};

static void vio_spapr_device_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *k = DEVICE_CLASS(klass);
    k->realize = spapr_vio_busdev_realize;
    k->reset = spapr_vio_busdev_reset;
    k->bus_type = TYPE_SPAPR_VIO_BUS;
}

static const TypeInfo spapr_vio_type_info = {
    .name = TYPE_VIO_SPAPR_DEVICE,
    .parent = TYPE_DEVICE,
    .instance_size = sizeof(SpaprVioDevice),
    .abstract = true,
    .class_size = sizeof(SpaprVioDeviceClass),
    .class_init = vio_spapr_device_class_init,
};

static void spapr_vio_register_types(void)
{
    type_register_static(&spapr_vio_bus_info);
    type_register_static(&spapr_vio_bridge_info);
    type_register_static(&spapr_vio_type_info);
}

type_init(spapr_vio_register_types)

static int compare_reg(const void *p1, const void *p2)
{
    SpaprVioDevice const *dev1, *dev2;

    dev1 = (SpaprVioDevice *)*(DeviceState **)p1;
    dev2 = (SpaprVioDevice *)*(DeviceState **)p2;

    if (dev1->reg < dev2->reg) {
        return -1;
    }
    if (dev1->reg == dev2->reg) {
        return 0;
    }

    /* dev1->reg > dev2->reg */
    return 1;
}

void spapr_dt_vdevice(SpaprVioBus *bus, void *fdt)
{
    DeviceState *qdev, **qdevs;
    BusChild *kid;
    int i, num, ret = 0;
    int node;

    _FDT(node = fdt_add_subnode(fdt, 0, "vdevice"));

    _FDT(fdt_setprop_string(fdt, node, "device_type", "vdevice"));
    _FDT(fdt_setprop_string(fdt, node, "compatible", "IBM,vdevice"));
    _FDT(fdt_setprop_cell(fdt, node, "#address-cells", 1));
    _FDT(fdt_setprop_cell(fdt, node, "#size-cells", 0));
    _FDT(fdt_setprop_cell(fdt, node, "#interrupt-cells", 2));
    _FDT(fdt_setprop(fdt, node, "interrupt-controller", NULL, 0));

    /* Count qdevs on the bus list */
    num = 0;
    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
        num++;
    }

    /* Copy out into an array of pointers */
    qdevs = g_new(DeviceState *, num);
    num = 0;
    QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
        qdevs[num++] = kid->child;
    }

    /* Sort the array */
    qsort(qdevs, num, sizeof(qdev), compare_reg);

    /* Hack alert. Give the devices to libfdt in reverse order, we happen
     * to know that will mean they are in forward order in the tree. */
    for (i = num - 1; i >= 0; i--) {
        SpaprVioDevice *dev = (SpaprVioDevice *)(qdevs[i]);
        SpaprVioDeviceClass *vdc = VIO_SPAPR_DEVICE_GET_CLASS(dev);

        ret = vio_make_devnode(dev, fdt);
        if (ret < 0) {
            error_report("Couldn't create device node /vdevice/%s@%"PRIx32,
                         vdc->dt_name, dev->reg);
            exit(1);
        }
    }

    g_free(qdevs);
}

gchar *spapr_vio_stdout_path(SpaprVioBus *bus)
{
    SpaprVioDevice *dev;
    g_autofree char *name = NULL;

    dev = spapr_vty_get_default(bus);
    if (!dev) {
        return NULL;
    }

    name = spapr_vio_get_dev_name(DEVICE(dev));

    return g_strdup_printf("/vdevice/%s", name);
}
