/*
 * Virtio vsock device
 *
 * Copyright 2015 Red Hat, Inc.
 *
 * Authors:
 *  Stefan Hajnoczi <stefanha@redhat.com>
 *
 * 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 "standard-headers/linux/virtio_vsock.h"
#include "qapi/error.h"
#include "hw/virtio/virtio-access.h"
#include "qemu/error-report.h"
#include "qemu/sockets.h"
#include "hw/qdev-properties.h"
#include "hw/virtio/vhost-vsock.h"
#include "monitor/monitor.h"

static void vhost_vsock_get_config(VirtIODevice *vdev, uint8_t *config)
{
    VHostVSock *vsock = VHOST_VSOCK(vdev);
    struct virtio_vsock_config vsockcfg = {};

    virtio_stq_p(vdev, &vsockcfg.guest_cid, vsock->conf.guest_cid);
    memcpy(config, &vsockcfg, sizeof(vsockcfg));
}

static int vhost_vsock_set_guest_cid(VirtIODevice *vdev)
{
    VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
    VHostVSock *vsock = VHOST_VSOCK(vdev);
    const VhostOps *vhost_ops = vvc->vhost_dev.vhost_ops;
    int ret;

    if (!vhost_ops->vhost_vsock_set_guest_cid) {
        return -ENOSYS;
    }

    ret = vhost_ops->vhost_vsock_set_guest_cid(&vvc->vhost_dev,
                                               vsock->conf.guest_cid);
    if (ret < 0) {
        return -errno;
    }
    return 0;
}

static int vhost_vsock_set_running(VirtIODevice *vdev, int start)
{
    VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
    const VhostOps *vhost_ops = vvc->vhost_dev.vhost_ops;
    int ret;

    if (!vhost_ops->vhost_vsock_set_running) {
        return -ENOSYS;
    }

    ret = vhost_ops->vhost_vsock_set_running(&vvc->vhost_dev, start);
    if (ret < 0) {
        return -errno;
    }
    return 0;
}


static void vhost_vsock_set_status(VirtIODevice *vdev, uint8_t status)
{
    VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
    bool should_start = virtio_device_started(vdev, status);
    int ret;

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

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

        ret = vhost_vsock_set_running(vdev, 1);
        if (ret < 0) {
            vhost_vsock_common_stop(vdev);
            error_report("Error starting vhost vsock: %d", -ret);
            return;
        }
    } else {
        ret = vhost_vsock_set_running(vdev, 0);
        if (ret < 0) {
            error_report("vhost vsock set running failed: %d", ret);
            return;
        }

        vhost_vsock_common_stop(vdev);
    }
}

static uint64_t vhost_vsock_get_features(VirtIODevice *vdev,
                                         uint64_t requested_features,
                                         Error **errp)
{
    return vhost_vsock_common_get_features(vdev, requested_features, errp);
}

static const VMStateDescription vmstate_virtio_vhost_vsock = {
    .name = "virtio-vhost_vsock",
    .minimum_version_id = VHOST_VSOCK_SAVEVM_VERSION,
    .version_id = VHOST_VSOCK_SAVEVM_VERSION,
    .fields = (VMStateField[]) {
        VMSTATE_VIRTIO_DEVICE,
        VMSTATE_END_OF_LIST()
    },
    .pre_save = vhost_vsock_common_pre_save,
    .post_load = vhost_vsock_common_post_load,
};

static void vhost_vsock_device_realize(DeviceState *dev, Error **errp)
{
    VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(dev);
    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
    VHostVSock *vsock = VHOST_VSOCK(dev);
    int vhostfd;
    int ret;

    /* Refuse to use reserved CID numbers */
    if (vsock->conf.guest_cid <= 2) {
        error_setg(errp, "guest-cid property must be greater than 2");
        return;
    }

    if (vsock->conf.guest_cid > UINT32_MAX) {
        error_setg(errp, "guest-cid property must be a 32-bit number");
        return;
    }

    if (vsock->conf.vhostfd) {
        vhostfd = monitor_fd_param(monitor_cur(), vsock->conf.vhostfd, errp);
        if (vhostfd == -1) {
            error_prepend(errp, "vhost-vsock: unable to parse vhostfd: ");
            return;
        }

        if (!g_unix_set_fd_nonblocking(vhostfd, true, NULL)) {
            error_setg_errno(errp, errno,
                             "vhost-vsock: unable to set non-blocking mode");
            return;
        }
    } else {
        vhostfd = open("/dev/vhost-vsock", O_RDWR);
        if (vhostfd < 0) {
            error_setg_errno(errp, errno,
                             "vhost-vsock: failed to open vhost device");
            return;
        }

        if (!g_unix_set_fd_nonblocking(vhostfd, true, NULL)) {
            error_setg_errno(errp, errno,
                             "Failed to set FD nonblocking");
            return;
        }
    }

    vhost_vsock_common_realize(vdev);

    ret = vhost_dev_init(&vvc->vhost_dev, (void *)(uintptr_t)vhostfd,
                         VHOST_BACKEND_TYPE_KERNEL, 0, errp);
    if (ret < 0) {
        /*
         * vhostfd is closed by vhost_dev_cleanup, which is called
         * by vhost_dev_init on initialization error.
         */
        goto err_virtio;
    }

    ret = vhost_vsock_set_guest_cid(vdev);
    if (ret < 0) {
        error_setg_errno(errp, -ret, "vhost-vsock: unable to set guest cid");
        goto err_vhost_dev;
    }

    return;

err_vhost_dev:
    /* vhost_dev_cleanup() closes the vhostfd passed to vhost_dev_init() */
    vhost_dev_cleanup(&vvc->vhost_dev);
err_virtio:
    vhost_vsock_common_unrealize(vdev);
}

static void vhost_vsock_device_unrealize(DeviceState *dev)
{
    VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(dev);
    VirtIODevice *vdev = VIRTIO_DEVICE(dev);

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

    vhost_dev_cleanup(&vvc->vhost_dev);
    vhost_vsock_common_unrealize(vdev);
}

static Property vhost_vsock_properties[] = {
    DEFINE_PROP_UINT64("guest-cid", VHostVSock, conf.guest_cid, 0),
    DEFINE_PROP_STRING("vhostfd", VHostVSock, conf.vhostfd),
    DEFINE_PROP_END_OF_LIST(),
};

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

    device_class_set_props(dc, vhost_vsock_properties);
    dc->vmsd = &vmstate_virtio_vhost_vsock;
    vdc->realize = vhost_vsock_device_realize;
    vdc->unrealize = vhost_vsock_device_unrealize;
    vdc->get_features = vhost_vsock_get_features;
    vdc->get_config = vhost_vsock_get_config;
    vdc->set_status = vhost_vsock_set_status;
}

static const TypeInfo vhost_vsock_info = {
    .name = TYPE_VHOST_VSOCK,
    .parent = TYPE_VHOST_VSOCK_COMMON,
    .instance_size = sizeof(VHostVSock),
    .class_init = vhost_vsock_class_init,
};

static void vhost_vsock_register_types(void)
{
    type_register_static(&vhost_vsock_info);
}

type_init(vhost_vsock_register_types)
