/*
 * Copyright © 2018, 2021 Oracle and/or its affiliates.
 *
 * 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 "hw/remote/proxy.h"
#include "hw/pci/pci.h"
#include "qapi/error.h"
#include "io/channel-util.h"
#include "hw/qdev-properties.h"
#include "monitor/monitor.h"
#include "migration/blocker.h"
#include "qemu/sockets.h"
#include "hw/remote/mpqemu-link.h"
#include "qemu/error-report.h"
#include "hw/remote/proxy-memory-listener.h"
#include "qom/object.h"
#include "qemu/event_notifier.h"
#include "system/kvm.h"

static void probe_pci_info(PCIDevice *dev, Error **errp);
static void proxy_device_reset(DeviceState *dev);

static void proxy_intx_update(PCIDevice *pci_dev)
{
    PCIProxyDev *dev = PCI_PROXY_DEV(pci_dev);
    PCIINTxRoute route;
    int pin = pci_get_byte(pci_dev->config + PCI_INTERRUPT_PIN) - 1;

    if (dev->virq != -1) {
        kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, &dev->intr, dev->virq);
        dev->virq = -1;
    }

    route = pci_device_route_intx_to_irq(pci_dev, pin);

    dev->virq = route.irq;

    if (dev->virq != -1) {
        kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, &dev->intr,
                                           &dev->resample, dev->virq);
    }
}

static void setup_irqfd(PCIProxyDev *dev)
{
    PCIDevice *pci_dev = PCI_DEVICE(dev);
    MPQemuMsg msg;
    Error *local_err = NULL;

    event_notifier_init(&dev->intr, 0);
    event_notifier_init(&dev->resample, 0);

    memset(&msg, 0, sizeof(MPQemuMsg));
    msg.cmd = MPQEMU_CMD_SET_IRQFD;
    msg.num_fds = 2;
    msg.fds[0] = event_notifier_get_fd(&dev->intr);
    msg.fds[1] = event_notifier_get_fd(&dev->resample);
    msg.size = 0;

    if (!mpqemu_msg_send(&msg, dev->ioc, &local_err)) {
        error_report_err(local_err);
    }

    dev->virq = -1;

    proxy_intx_update(pci_dev);

    pci_device_set_intx_routing_notifier(pci_dev, proxy_intx_update);
}

static void pci_proxy_dev_realize(PCIDevice *device, Error **errp)
{
    ERRP_GUARD();
    PCIProxyDev *dev = PCI_PROXY_DEV(device);
    uint8_t *pci_conf = device->config;
    int fd;

    if (!dev->fd) {
        error_setg(errp, "fd parameter not specified for %s",
                   DEVICE(device)->id);
        return;
    }

    fd = monitor_fd_param(monitor_cur(), dev->fd, errp);
    if (fd == -1) {
        error_prepend(errp, "proxy: unable to parse fd %s: ", dev->fd);
        return;
    }

    if (!fd_is_socket(fd)) {
        error_setg(errp, "proxy: fd %d is not a socket", fd);
        close(fd);
        return;
    }

    dev->ioc = qio_channel_new_fd(fd, errp);
    if (!dev->ioc) {
        close(fd);
        return;
    }

    error_setg(&dev->migration_blocker, "%s does not support migration",
               TYPE_PCI_PROXY_DEV);
    if (migrate_add_blocker(&dev->migration_blocker, errp) < 0) {
        object_unref(dev->ioc);
        return;
    }

    qemu_mutex_init(&dev->io_mutex);
    qio_channel_set_blocking(dev->ioc, true, NULL);

    pci_conf[PCI_LATENCY_TIMER] = 0xff;
    pci_conf[PCI_INTERRUPT_PIN] = 0x01;

    proxy_memory_listener_configure(&dev->proxy_listener, dev->ioc);

    setup_irqfd(dev);

    probe_pci_info(PCI_DEVICE(dev), errp);
}

static void pci_proxy_dev_exit(PCIDevice *pdev)
{
    PCIProxyDev *dev = PCI_PROXY_DEV(pdev);

    if (dev->ioc) {
        qio_channel_close(dev->ioc, NULL);
    }

    migrate_del_blocker(&dev->migration_blocker);

    proxy_memory_listener_deconfigure(&dev->proxy_listener);

    event_notifier_cleanup(&dev->intr);
    event_notifier_cleanup(&dev->resample);
}

static void config_op_send(PCIProxyDev *pdev, uint32_t addr, uint32_t *val,
                           int len, unsigned int op)
{
    MPQemuMsg msg = { 0 };
    uint64_t ret = -EINVAL;
    Error *local_err = NULL;

    msg.cmd = op;
    msg.data.pci_conf_data.addr = addr;
    msg.data.pci_conf_data.val = (op == MPQEMU_CMD_PCI_CFGWRITE) ? *val : 0;
    msg.data.pci_conf_data.len = len;
    msg.size = sizeof(PciConfDataMsg);

    ret = mpqemu_msg_send_and_await_reply(&msg, pdev, &local_err);
    if (local_err) {
        error_report_err(local_err);
    }

    if (ret == UINT64_MAX) {
        error_report("Failed to perform PCI config %s operation",
                     (op == MPQEMU_CMD_PCI_CFGREAD) ? "READ" : "WRITE");
    }

    if (op == MPQEMU_CMD_PCI_CFGREAD) {
        *val = (uint32_t)ret;
    }
}

static uint32_t pci_proxy_read_config(PCIDevice *d, uint32_t addr, int len)
{
    uint32_t val;

    config_op_send(PCI_PROXY_DEV(d), addr, &val, len, MPQEMU_CMD_PCI_CFGREAD);

    return val;
}

static void pci_proxy_write_config(PCIDevice *d, uint32_t addr, uint32_t val,
                                   int len)
{
    /*
     * Some of the functions access the copy of remote device's PCI config
     * space which is cached in the proxy device. Therefore, maintain
     * it updated.
     */
    pci_default_write_config(d, addr, val, len);

    config_op_send(PCI_PROXY_DEV(d), addr, &val, len, MPQEMU_CMD_PCI_CFGWRITE);
}

static const Property proxy_properties[] = {
    DEFINE_PROP_STRING("fd", PCIProxyDev, fd),
};

static void pci_proxy_dev_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);

    k->realize = pci_proxy_dev_realize;
    k->exit = pci_proxy_dev_exit;
    k->config_read = pci_proxy_read_config;
    k->config_write = pci_proxy_write_config;

    device_class_set_legacy_reset(dc, proxy_device_reset);

    device_class_set_props(dc, proxy_properties);
}

static const TypeInfo pci_proxy_dev_type_info = {
    .name          = TYPE_PCI_PROXY_DEV,
    .parent        = TYPE_PCI_DEVICE,
    .instance_size = sizeof(PCIProxyDev),
    .class_init    = pci_proxy_dev_class_init,
    .interfaces = (InterfaceInfo[]) {
        { INTERFACE_CONVENTIONAL_PCI_DEVICE },
        { },
    },
};

static void pci_proxy_dev_register_types(void)
{
    type_register_static(&pci_proxy_dev_type_info);
}

type_init(pci_proxy_dev_register_types)

static void send_bar_access_msg(PCIProxyDev *pdev, MemoryRegion *mr,
                                bool write, hwaddr addr, uint64_t *val,
                                unsigned size, bool memory)
{
    MPQemuMsg msg = { 0 };
    long ret = -EINVAL;
    Error *local_err = NULL;

    msg.size = sizeof(BarAccessMsg);
    msg.data.bar_access.addr = mr->addr + addr;
    msg.data.bar_access.size = size;
    msg.data.bar_access.memory = memory;

    if (write) {
        msg.cmd = MPQEMU_CMD_BAR_WRITE;
        msg.data.bar_access.val = *val;
    } else {
        msg.cmd = MPQEMU_CMD_BAR_READ;
    }

    ret = mpqemu_msg_send_and_await_reply(&msg, pdev, &local_err);
    if (local_err) {
        error_report_err(local_err);
    }

    if (!write) {
        *val = ret;
    }
}

static void proxy_bar_write(void *opaque, hwaddr addr, uint64_t val,
                            unsigned size)
{
    ProxyMemoryRegion *pmr = opaque;

    send_bar_access_msg(pmr->dev, &pmr->mr, true, addr, &val, size,
                        pmr->memory);
}

static uint64_t proxy_bar_read(void *opaque, hwaddr addr, unsigned size)
{
    ProxyMemoryRegion *pmr = opaque;
    uint64_t val;

    send_bar_access_msg(pmr->dev, &pmr->mr, false, addr, &val, size,
                        pmr->memory);

    return val;
}

const MemoryRegionOps proxy_mr_ops = {
    .read = proxy_bar_read,
    .write = proxy_bar_write,
    .endianness = DEVICE_NATIVE_ENDIAN,
    .impl = {
        .min_access_size = 1,
        .max_access_size = 8,
    },
};

static void probe_pci_info(PCIDevice *dev, Error **errp)
{
    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
    uint32_t orig_val, new_val, base_class, val;
    PCIProxyDev *pdev = PCI_PROXY_DEV(dev);
    DeviceClass *dc = DEVICE_CLASS(pc);
    uint8_t type;
    int i, size;

    config_op_send(pdev, PCI_VENDOR_ID, &val, 2, MPQEMU_CMD_PCI_CFGREAD);
    pc->vendor_id = (uint16_t)val;

    config_op_send(pdev, PCI_DEVICE_ID, &val, 2, MPQEMU_CMD_PCI_CFGREAD);
    pc->device_id = (uint16_t)val;

    config_op_send(pdev, PCI_CLASS_DEVICE, &val, 2, MPQEMU_CMD_PCI_CFGREAD);
    pc->class_id = (uint16_t)val;

    config_op_send(pdev, PCI_SUBSYSTEM_ID, &val, 2, MPQEMU_CMD_PCI_CFGREAD);
    pc->subsystem_id = (uint16_t)val;

    base_class = pc->class_id >> 4;
    switch (base_class) {
    case PCI_BASE_CLASS_BRIDGE:
        set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
        break;
    case PCI_BASE_CLASS_STORAGE:
        set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
        break;
    case PCI_BASE_CLASS_NETWORK:
    case PCI_BASE_CLASS_WIRELESS:
        set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
        break;
    case PCI_BASE_CLASS_INPUT:
        set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
        break;
    case PCI_BASE_CLASS_DISPLAY:
        set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
        break;
    case PCI_BASE_CLASS_PROCESSOR:
        set_bit(DEVICE_CATEGORY_CPU, dc->categories);
        break;
    default:
        set_bit(DEVICE_CATEGORY_MISC, dc->categories);
        break;
    }

    for (i = 0; i < PCI_NUM_REGIONS; i++) {
        config_op_send(pdev, PCI_BASE_ADDRESS_0 + (4 * i), &orig_val, 4,
                       MPQEMU_CMD_PCI_CFGREAD);
        new_val = 0xffffffff;
        config_op_send(pdev, PCI_BASE_ADDRESS_0 + (4 * i), &new_val, 4,
                       MPQEMU_CMD_PCI_CFGWRITE);
        config_op_send(pdev, PCI_BASE_ADDRESS_0 + (4 * i), &new_val, 4,
                       MPQEMU_CMD_PCI_CFGREAD);
        size = (~(new_val & 0xFFFFFFF0)) + 1;
        config_op_send(pdev, PCI_BASE_ADDRESS_0 + (4 * i), &orig_val, 4,
                       MPQEMU_CMD_PCI_CFGWRITE);
        type = (new_val & 0x1) ?
                   PCI_BASE_ADDRESS_SPACE_IO : PCI_BASE_ADDRESS_SPACE_MEMORY;

        if (size) {
            g_autofree char *name = g_strdup_printf("bar-region-%d", i);
            pdev->region[i].dev = pdev;
            pdev->region[i].present = true;
            if (type == PCI_BASE_ADDRESS_SPACE_MEMORY) {
                pdev->region[i].memory = true;
            }
            memory_region_init_io(&pdev->region[i].mr, OBJECT(pdev),
                                  &proxy_mr_ops, &pdev->region[i],
                                  name, size);
            pci_register_bar(dev, i, type, &pdev->region[i].mr);
        }
    }
}

static void proxy_device_reset(DeviceState *dev)
{
    PCIProxyDev *pdev = PCI_PROXY_DEV(dev);
    MPQemuMsg msg = { 0 };
    Error *local_err = NULL;

    msg.cmd = MPQEMU_CMD_DEVICE_RESET;
    msg.size = 0;

    mpqemu_msg_send_and_await_reply(&msg, pdev, &local_err);
    if (local_err) {
        error_report_err(local_err);
    }

}
