/*
 * Copyright © 2020, 2021 Oracle and/or its affiliates.
 *
 * This work is licensed under the terms of the GNU GPL-v2, version 2 or later.
 *
 * See the COPYING file in the top-level directory.
 *
 */

#include "qemu/osdep.h"

#include "hw/remote/machine.h"
#include "io/channel.h"
#include "hw/remote/mpqemu-link.h"
#include "qapi/error.h"
#include "sysemu/runstate.h"
#include "hw/pci/pci.h"
#include "exec/memattrs.h"
#include "hw/remote/memory.h"
#include "hw/remote/iohub.h"
#include "sysemu/reset.h"

static void process_config_write(QIOChannel *ioc, PCIDevice *dev,
                                 MPQemuMsg *msg, Error **errp);
static void process_config_read(QIOChannel *ioc, PCIDevice *dev,
                                MPQemuMsg *msg, Error **errp);
static void process_bar_write(QIOChannel *ioc, MPQemuMsg *msg, Error **errp);
static void process_bar_read(QIOChannel *ioc, MPQemuMsg *msg, Error **errp);
static void process_device_reset_msg(QIOChannel *ioc, PCIDevice *dev,
                                     Error **errp);

void coroutine_fn mpqemu_remote_msg_loop_co(void *data)
{
    g_autofree RemoteCommDev *com = (RemoteCommDev *)data;
    PCIDevice *pci_dev = NULL;
    Error *local_err = NULL;

    assert(com->ioc);

    pci_dev = com->dev;
    for (; !local_err;) {
        MPQemuMsg msg = {0};

        if (!mpqemu_msg_recv(&msg, com->ioc, &local_err)) {
            break;
        }

        if (!mpqemu_msg_valid(&msg)) {
            error_setg(&local_err, "Received invalid message from proxy"
                                   "in remote process pid="FMT_pid"",
                                   getpid());
            break;
        }

        switch (msg.cmd) {
        case MPQEMU_CMD_PCI_CFGWRITE:
            process_config_write(com->ioc, pci_dev, &msg, &local_err);
            break;
        case MPQEMU_CMD_PCI_CFGREAD:
            process_config_read(com->ioc, pci_dev, &msg, &local_err);
            break;
        case MPQEMU_CMD_BAR_WRITE:
            process_bar_write(com->ioc, &msg, &local_err);
            break;
        case MPQEMU_CMD_BAR_READ:
            process_bar_read(com->ioc, &msg, &local_err);
            break;
        case MPQEMU_CMD_SYNC_SYSMEM:
            remote_sysmem_reconfig(&msg, &local_err);
            break;
        case MPQEMU_CMD_SET_IRQFD:
            process_set_irqfd_msg(pci_dev, &msg);
            break;
        case MPQEMU_CMD_DEVICE_RESET:
            process_device_reset_msg(com->ioc, pci_dev, &local_err);
            break;
        default:
            error_setg(&local_err,
                       "Unknown command (%d) received for device %s"
                       " (pid="FMT_pid")",
                       msg.cmd, DEVICE(pci_dev)->id, getpid());
        }
    }

    if (local_err) {
        error_report_err(local_err);
        qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_ERROR);
    } else {
        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
    }
}

static void process_config_write(QIOChannel *ioc, PCIDevice *dev,
                                 MPQemuMsg *msg, Error **errp)
{
    ERRP_GUARD();
    PciConfDataMsg *conf = (PciConfDataMsg *)&msg->data.pci_conf_data;
    MPQemuMsg ret = { 0 };

    if ((conf->addr + sizeof(conf->val)) > pci_config_size(dev)) {
        error_setg(errp, "Bad address for PCI config write, pid "FMT_pid".",
                   getpid());
        ret.data.u64 = UINT64_MAX;
    } else {
        pci_default_write_config(dev, conf->addr, conf->val, conf->len);
    }

    ret.cmd = MPQEMU_CMD_RET;
    ret.size = sizeof(ret.data.u64);

    if (!mpqemu_msg_send(&ret, ioc, NULL)) {
        error_prepend(errp, "Error returning code to proxy, pid "FMT_pid": ",
                      getpid());
    }
}

static void process_config_read(QIOChannel *ioc, PCIDevice *dev,
                                MPQemuMsg *msg, Error **errp)
{
    ERRP_GUARD();
    PciConfDataMsg *conf = (PciConfDataMsg *)&msg->data.pci_conf_data;
    MPQemuMsg ret = { 0 };

    if ((conf->addr + sizeof(conf->val)) > pci_config_size(dev)) {
        error_setg(errp, "Bad address for PCI config read, pid "FMT_pid".",
                   getpid());
        ret.data.u64 = UINT64_MAX;
    } else {
        ret.data.u64 = pci_default_read_config(dev, conf->addr, conf->len);
    }

    ret.cmd = MPQEMU_CMD_RET;
    ret.size = sizeof(ret.data.u64);

    if (!mpqemu_msg_send(&ret, ioc, NULL)) {
        error_prepend(errp, "Error returning code to proxy, pid "FMT_pid": ",
                      getpid());
    }
}

static void process_bar_write(QIOChannel *ioc, MPQemuMsg *msg, Error **errp)
{
    ERRP_GUARD();
    BarAccessMsg *bar_access = &msg->data.bar_access;
    AddressSpace *as =
        bar_access->memory ? &address_space_memory : &address_space_io;
    MPQemuMsg ret = { 0 };
    MemTxResult res;
    uint64_t val;

    if (!is_power_of_2(bar_access->size) ||
       (bar_access->size > sizeof(uint64_t))) {
        ret.data.u64 = UINT64_MAX;
        goto fail;
    }

    val = cpu_to_le64(bar_access->val);

    res = address_space_rw(as, bar_access->addr, MEMTXATTRS_UNSPECIFIED,
                           (void *)&val, bar_access->size, true);

    if (res != MEMTX_OK) {
        error_setg(errp, "Bad address %"PRIx64" for mem write, pid "FMT_pid".",
                   bar_access->addr, getpid());
        ret.data.u64 = -1;
    }

fail:
    ret.cmd = MPQEMU_CMD_RET;
    ret.size = sizeof(ret.data.u64);

    if (!mpqemu_msg_send(&ret, ioc, NULL)) {
        error_prepend(errp, "Error returning code to proxy, pid "FMT_pid": ",
                      getpid());
    }
}

static void process_bar_read(QIOChannel *ioc, MPQemuMsg *msg, Error **errp)
{
    ERRP_GUARD();
    BarAccessMsg *bar_access = &msg->data.bar_access;
    MPQemuMsg ret = { 0 };
    AddressSpace *as;
    MemTxResult res;
    uint64_t val = 0;

    as = bar_access->memory ? &address_space_memory : &address_space_io;

    if (!is_power_of_2(bar_access->size) ||
       (bar_access->size > sizeof(uint64_t))) {
        val = UINT64_MAX;
        goto fail;
    }

    res = address_space_rw(as, bar_access->addr, MEMTXATTRS_UNSPECIFIED,
                           (void *)&val, bar_access->size, false);

    if (res != MEMTX_OK) {
        error_setg(errp, "Bad address %"PRIx64" for mem read, pid "FMT_pid".",
                   bar_access->addr, getpid());
        val = UINT64_MAX;
    }

fail:
    ret.cmd = MPQEMU_CMD_RET;
    ret.data.u64 = le64_to_cpu(val);
    ret.size = sizeof(ret.data.u64);

    if (!mpqemu_msg_send(&ret, ioc, NULL)) {
        error_prepend(errp, "Error returning code to proxy, pid "FMT_pid": ",
                      getpid());
    }
}

static void process_device_reset_msg(QIOChannel *ioc, PCIDevice *dev,
                                     Error **errp)
{
    DeviceState *s = DEVICE(dev);
    MPQemuMsg ret = { 0 };

    device_cold_reset(s);

    ret.cmd = MPQEMU_CMD_RET;

    mpqemu_msg_send(&ret, ioc, errp);
}
