/*
 * 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_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)
