/*
 * Vhost Vdpa Device
 *
 * Copyright (c) Huawei Technologies Co., Ltd. 2022. All Rights Reserved.
 *
 * Authors:
 *   Longpeng <longpeng2@huawei.com>
 *
 * Largely based on the "vhost-user-blk-pci.c" and "vhost-user-blk.c"
 * implemented by:
 *   Changpeng Liu <changpeng.liu@intel.com>
 *
 * This work is licensed under the terms of the GNU LGPL, version 2 or later.
 * See the COPYING.LIB file in the top-level directory.
 */
#include "qemu/osdep.h"
#include <sys/ioctl.h>
#include <linux/vhost.h>
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "qemu/cutils.h"
#include "hw/qdev-core.h"
#include "hw/qdev-properties.h"
#include "hw/qdev-properties-system.h"
#include "hw/virtio/vhost.h"
#include "hw/virtio/virtio.h"
#include "hw/virtio/virtio-bus.h"
#include "hw/virtio/virtio-access.h"
#include "hw/virtio/vdpa-dev.h"
#include "sysemu/sysemu.h"
#include "sysemu/runstate.h"

static void
vhost_vdpa_device_dummy_handle_output(VirtIODevice *vdev, VirtQueue *vq)
{
    /* Nothing to do */
}

static uint32_t
vhost_vdpa_device_get_u32(int fd, unsigned long int cmd, Error **errp)
{
    uint32_t val = (uint32_t)-1;

    if (ioctl(fd, cmd, &val) < 0) {
        error_setg(errp, "vhost-vdpa-device: cmd 0x%lx failed: %s",
                   cmd, strerror(errno));
    }

    return val;
}

static void vhost_vdpa_device_realize(DeviceState *dev, Error **errp)
{
    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
    VhostVdpaDevice *v = VHOST_VDPA_DEVICE(vdev);
    struct vhost_vdpa_iova_range iova_range;
    uint16_t max_queue_size;
    struct vhost_virtqueue *vqs;
    int i, ret;

    if (!v->vhostdev) {
        error_setg(errp, "vhost-vdpa-device: vhostdev are missing");
        return;
    }

    v->vhostfd = qemu_open(v->vhostdev, O_RDWR, errp);
    if (*errp) {
        return;
    }
    v->vdpa.device_fd = v->vhostfd;

    v->vdev_id = vhost_vdpa_device_get_u32(v->vhostfd,
                                           VHOST_VDPA_GET_DEVICE_ID, errp);
    if (*errp) {
        goto out;
    }

    max_queue_size = vhost_vdpa_device_get_u32(v->vhostfd,
                                               VHOST_VDPA_GET_VRING_NUM, errp);
    if (*errp) {
        goto out;
    }

    if (v->queue_size > max_queue_size) {
        error_setg(errp, "vhost-vdpa-device: invalid queue_size: %u (max:%u)",
                   v->queue_size, max_queue_size);
        goto out;
    } else if (!v->queue_size) {
        v->queue_size = max_queue_size;
    }

    v->num_queues = vhost_vdpa_device_get_u32(v->vhostfd,
                                              VHOST_VDPA_GET_VQS_COUNT, errp);
    if (*errp) {
        goto out;
    }

    if (!v->num_queues || v->num_queues > VIRTIO_QUEUE_MAX) {
        error_setg(errp, "invalid number of virtqueues: %u (max:%u)",
                   v->num_queues, VIRTIO_QUEUE_MAX);
        goto out;
    }

    v->dev.nvqs = v->num_queues;
    vqs = g_new0(struct vhost_virtqueue, v->dev.nvqs);
    v->dev.vqs = vqs;
    v->dev.vq_index = 0;
    v->dev.vq_index_end = v->dev.nvqs;
    v->dev.backend_features = 0;
    v->started = false;

    ret = vhost_vdpa_get_iova_range(v->vhostfd, &iova_range);
    if (ret < 0) {
        error_setg(errp, "vhost-vdpa-device: get iova range failed: %s",
                   strerror(-ret));
        goto free_vqs;
    }
    v->vdpa.iova_range = iova_range;

    ret = vhost_dev_init(&v->dev, &v->vdpa, VHOST_BACKEND_TYPE_VDPA, 0, NULL);
    if (ret < 0) {
        error_setg(errp, "vhost-vdpa-device: vhost initialization failed: %s",
                   strerror(-ret));
        goto free_vqs;
    }

    v->config_size = vhost_vdpa_device_get_u32(v->vhostfd,
                                               VHOST_VDPA_GET_CONFIG_SIZE,
                                               errp);
    if (*errp) {
        goto vhost_cleanup;
    }

    /*
     * Invoke .post_init() to initialize the transport-specific fields
     * before calling virtio_init().
     */
    if (v->post_init && v->post_init(v, errp) < 0) {
        goto vhost_cleanup;
    }

    v->config = g_malloc0(v->config_size);

    ret = vhost_dev_get_config(&v->dev, v->config, v->config_size, NULL);
    if (ret < 0) {
        error_setg(errp, "vhost-vdpa-device: get config failed");
        goto free_config;
    }

    virtio_init(vdev, v->vdev_id, v->config_size);

    v->virtqs = g_new0(VirtQueue *, v->dev.nvqs);
    for (i = 0; i < v->dev.nvqs; i++) {
        v->virtqs[i] = virtio_add_queue(vdev, v->queue_size,
                                        vhost_vdpa_device_dummy_handle_output);
    }

    return;

free_config:
    g_free(v->config);
vhost_cleanup:
    vhost_dev_cleanup(&v->dev);
free_vqs:
    g_free(vqs);
out:
    qemu_close(v->vhostfd);
    v->vhostfd = -1;
}

static void vhost_vdpa_device_unrealize(DeviceState *dev)
{
    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
    VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev);
    int i;

    virtio_set_status(vdev, 0);

    for (i = 0; i < s->num_queues; i++) {
        virtio_delete_queue(s->virtqs[i]);
    }
    g_free(s->virtqs);
    virtio_cleanup(vdev);

    g_free(s->config);
    g_free(s->dev.vqs);
    vhost_dev_cleanup(&s->dev);
    qemu_close(s->vhostfd);
    s->vhostfd = -1;
}

static void
vhost_vdpa_device_get_config(VirtIODevice *vdev, uint8_t *config)
{
    VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev);

    memcpy(config, s->config, s->config_size);
}

static void
vhost_vdpa_device_set_config(VirtIODevice *vdev, const uint8_t *config)
{
    VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev);
    int ret;

    ret = vhost_dev_set_config(&s->dev, s->config, 0, s->config_size,
                               VHOST_SET_CONFIG_TYPE_MASTER);
    if (ret) {
        error_report("set device config space failed");
        return;
    }
}

static uint64_t vhost_vdpa_device_get_features(VirtIODevice *vdev,
                                               uint64_t features,
                                               Error **errp)
{
    VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev);
    uint64_t backend_features = s->dev.features;

    if (!virtio_has_feature(features, VIRTIO_F_IOMMU_PLATFORM)) {
        virtio_clear_feature(&backend_features, VIRTIO_F_IOMMU_PLATFORM);
    }

    return backend_features;
}

static int vhost_vdpa_device_start(VirtIODevice *vdev, Error **errp)
{
    VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev);
    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
    int i, ret;

    if (!k->set_guest_notifiers) {
        error_setg(errp, "binding does not support guest notifiers");
        return -ENOSYS;
    }

    ret = vhost_dev_enable_notifiers(&s->dev, vdev);
    if (ret < 0) {
        error_setg_errno(errp, -ret, "Error enabling host notifiers");
        return ret;
    }

    ret = k->set_guest_notifiers(qbus->parent, s->dev.nvqs, true);
    if (ret < 0) {
        error_setg_errno(errp, -ret, "Error binding guest notifier");
        goto err_host_notifiers;
    }

    s->dev.acked_features = vdev->guest_features;

    ret = vhost_dev_start(&s->dev, vdev, false);
    if (ret < 0) {
        error_setg_errno(errp, -ret, "Error starting vhost");
        goto err_guest_notifiers;
    }
    s->started = true;

    /*
     * guest_notifier_mask/pending not used yet, so just unmask
     * everything here. virtio-pci will do the right thing by
     * enabling/disabling irqfd.
     */
    for (i = 0; i < s->dev.nvqs; i++) {
        vhost_virtqueue_mask(&s->dev, vdev, i, false);
    }

    return ret;

err_guest_notifiers:
    k->set_guest_notifiers(qbus->parent, s->dev.nvqs, false);
err_host_notifiers:
    vhost_dev_disable_notifiers(&s->dev, vdev);
    return ret;
}

static void vhost_vdpa_device_stop(VirtIODevice *vdev)
{
    VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev);
    BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
    int ret;

    if (!s->started) {
        return;
    }
    s->started = false;

    if (!k->set_guest_notifiers) {
        return;
    }

    vhost_dev_stop(&s->dev, vdev, false);

    ret = k->set_guest_notifiers(qbus->parent, s->dev.nvqs, false);
    if (ret < 0) {
        error_report("vhost guest notifier cleanup failed: %d", ret);
        return;
    }

    vhost_dev_disable_notifiers(&s->dev, vdev);
}

static void vhost_vdpa_device_set_status(VirtIODevice *vdev, uint8_t status)
{
    VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev);
    bool should_start = virtio_device_started(vdev, status);
    Error *local_err = NULL;
    int ret;

    if (!vdev->vm_running) {
        should_start = false;
    }

    if (s->started == should_start) {
        return;
    }

    if (should_start) {
        ret = vhost_vdpa_device_start(vdev, &local_err);
        if (ret < 0) {
            error_reportf_err(local_err, "vhost-vdpa-device: start failed: ");
        }
    } else {
        vhost_vdpa_device_stop(vdev);
    }
}

static Property vhost_vdpa_device_properties[] = {
    DEFINE_PROP_STRING("vhostdev", VhostVdpaDevice, vhostdev),
    DEFINE_PROP_UINT16("queue-size", VhostVdpaDevice, queue_size, 0),
    DEFINE_PROP_END_OF_LIST(),
};

static const VMStateDescription vmstate_vhost_vdpa_device = {
    .name = "vhost-vdpa-device",
    .unmigratable = 1,
    .minimum_version_id = 1,
    .version_id = 1,
    .fields = (VMStateField[]) {
        VMSTATE_VIRTIO_DEVICE,
        VMSTATE_END_OF_LIST()
    },
};

static void vhost_vdpa_device_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);
    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);

    device_class_set_props(dc, vhost_vdpa_device_properties);
    dc->desc = "VDPA-based generic device assignment";
    dc->vmsd = &vmstate_vhost_vdpa_device;
    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
    vdc->realize = vhost_vdpa_device_realize;
    vdc->unrealize = vhost_vdpa_device_unrealize;
    vdc->get_config = vhost_vdpa_device_get_config;
    vdc->set_config = vhost_vdpa_device_set_config;
    vdc->get_features = vhost_vdpa_device_get_features;
    vdc->set_status = vhost_vdpa_device_set_status;
}

static void vhost_vdpa_device_instance_init(Object *obj)
{
    VhostVdpaDevice *s = VHOST_VDPA_DEVICE(obj);

    device_add_bootindex_property(obj, &s->bootindex, "bootindex",
                                  NULL, DEVICE(obj));
}

static const TypeInfo vhost_vdpa_device_info = {
    .name = TYPE_VHOST_VDPA_DEVICE,
    .parent = TYPE_VIRTIO_DEVICE,
    .instance_size = sizeof(VhostVdpaDevice),
    .class_init = vhost_vdpa_device_class_init,
    .instance_init = vhost_vdpa_device_instance_init,
};

static void register_vhost_vdpa_device_type(void)
{
    type_register_static(&vhost_vdpa_device_info);
}

type_init(register_vhost_vdpa_device_type);
