/*
 * Vhost-user vsock virtio device
 *
 * Copyright 2020 Red Hat, Inc.
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or
 * (at your option) any later version.  See the COPYING file in the
 * top-level directory.
 */

#include "qemu/osdep.h"

#include "qapi/error.h"
#include "qemu/error-report.h"
#include "hw/qdev-properties.h"
#include "hw/qdev-properties-system.h"
#include "hw/virtio/vhost-user-vsock.h"

static const int user_feature_bits[] = {
    VIRTIO_F_VERSION_1,
    VIRTIO_RING_F_INDIRECT_DESC,
    VIRTIO_RING_F_EVENT_IDX,
    VIRTIO_F_NOTIFY_ON_EMPTY,
    VIRTIO_F_IN_ORDER,
    VIRTIO_F_NOTIFICATION_DATA,
    VHOST_INVALID_FEATURE_BIT
};

static void vuv_get_config(VirtIODevice *vdev, uint8_t *config)
{
    VHostUserVSock *vsock = VHOST_USER_VSOCK(vdev);

    memcpy(config, &vsock->vsockcfg, sizeof(struct virtio_vsock_config));
}

static int vuv_handle_config_change(struct vhost_dev *dev)
{
    VHostUserVSock *vsock = VHOST_USER_VSOCK(dev->vdev);
    Error *local_err = NULL;
    int ret = vhost_dev_get_config(dev, (uint8_t *)&vsock->vsockcfg,
                                   sizeof(struct virtio_vsock_config),
                                   &local_err);
    if (ret < 0) {
        error_report_err(local_err);
        return -1;
    }

    virtio_notify_config(dev->vdev);

    return 0;
}

const VhostDevConfigOps vsock_ops = {
    .vhost_dev_config_notifier = vuv_handle_config_change,
};

static void vuv_set_status(VirtIODevice *vdev, uint8_t status)
{
    VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
    bool should_start = virtio_device_should_start(vdev, status);

    if (vhost_dev_is_started(&vvc->vhost_dev) == should_start) {
        return;
    }

    if (should_start) {
        int ret = vhost_vsock_common_start(vdev);
        if (ret < 0) {
            return;
        }
    } else {
        vhost_vsock_common_stop(vdev);
    }
}

static uint64_t vuv_get_features(VirtIODevice *vdev,
                                 uint64_t features,
                                 Error **errp)
{
    VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);

    features = vhost_get_features(&vvc->vhost_dev, user_feature_bits, features);

    return vhost_vsock_common_get_features(vdev, features, errp);
}

static const VMStateDescription vuv_vmstate = {
    .name = "vhost-user-vsock",
    .unmigratable = 1,
};

static void vuv_device_realize(DeviceState *dev, Error **errp)
{
    VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(dev);
    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
    VHostUserVSock *vsock = VHOST_USER_VSOCK(dev);
    int ret;

    if (!vsock->conf.chardev.chr) {
        error_setg(errp, "missing chardev");
        return;
    }

    if (!vhost_user_init(&vsock->vhost_user, &vsock->conf.chardev, errp)) {
        return;
    }

    vhost_vsock_common_realize(vdev);

    vhost_dev_set_config_notifier(&vvc->vhost_dev, &vsock_ops);

    ret = vhost_dev_init(&vvc->vhost_dev, &vsock->vhost_user,
                         VHOST_BACKEND_TYPE_USER, 0, errp);
    if (ret < 0) {
        goto err_virtio;
    }

    ret = vhost_dev_get_config(&vvc->vhost_dev, (uint8_t *)&vsock->vsockcfg,
                               sizeof(struct virtio_vsock_config), errp);
    if (ret < 0) {
        goto err_vhost_dev;
    }

    return;

err_vhost_dev:
    vhost_dev_cleanup(&vvc->vhost_dev);
err_virtio:
    vhost_vsock_common_unrealize(vdev);
    vhost_user_cleanup(&vsock->vhost_user);
    return;
}

static void vuv_device_unrealize(DeviceState *dev)
{
    VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(dev);
    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
    VHostUserVSock *vsock = VHOST_USER_VSOCK(dev);

    /* This will stop vhost backend if appropriate. */
    vuv_set_status(vdev, 0);

    vhost_dev_cleanup(&vvc->vhost_dev);

    vhost_vsock_common_unrealize(vdev);

    vhost_user_cleanup(&vsock->vhost_user);

}

static Property vuv_properties[] = {
    DEFINE_PROP_CHR("chardev", VHostUserVSock, conf.chardev),
    DEFINE_PROP_END_OF_LIST(),
};

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

    device_class_set_props(dc, vuv_properties);
    dc->vmsd = &vuv_vmstate;
    vdc->realize = vuv_device_realize;
    vdc->unrealize = vuv_device_unrealize;
    vdc->get_features = vuv_get_features;
    vdc->get_config = vuv_get_config;
    vdc->set_status = vuv_set_status;
}

static const TypeInfo vuv_info = {
    .name = TYPE_VHOST_USER_VSOCK,
    .parent = TYPE_VHOST_VSOCK_COMMON,
    .instance_size = sizeof(VHostUserVSock),
    .class_init = vuv_class_init,
};

static void vuv_register_types(void)
{
    type_register_static(&vuv_info);
}

type_init(vuv_register_types)
