/*
 * TOD (Time Of Day) clock - KVM implementation
 *
 * Copyright 2018 Red Hat, Inc.
 * Author(s): David Hildenbrand <david@redhat.com>
 *
 * 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 "qapi/error.h"
#include "qemu/module.h"
#include "sysemu/sysemu.h"
#include "hw/s390x/tod.h"
#include "kvm_s390x.h"

static void kvm_s390_get_tod_raw(S390TOD *tod, Error **errp)
{
    int r;

    r = kvm_s390_get_clock_ext(&tod->high, &tod->low);
    if (r == -ENXIO) {
        r = kvm_s390_get_clock(&tod->high, &tod->low);
    }
    if (r) {
        error_setg(errp, "Unable to get KVM guest TOD clock: %s",
                   strerror(-r));
    }
}

static void kvm_s390_tod_get(const S390TODState *td, S390TOD *tod, Error **errp)
{
    if (td->stopped) {
        *tod = td->base;
        return;
    }

    kvm_s390_get_tod_raw(tod, errp);
}

static void kvm_s390_set_tod_raw(const S390TOD *tod, Error **errp)
{
    int r;

    r = kvm_s390_set_clock_ext(tod->high, tod->low);
    if (r == -ENXIO) {
        r = kvm_s390_set_clock(tod->high, tod->low);
    }
    if (r) {
        error_setg(errp, "Unable to set KVM guest TOD clock: %s",
                   strerror(-r));
    }
}

static void kvm_s390_tod_set(S390TODState *td, const S390TOD *tod, Error **errp)
{
    Error *local_err = NULL;

    /*
     * Somebody (e.g. migration) set the TOD. We'll store it into KVM to
     * properly detect errors now but take a look at the runstate to decide
     * whether really to keep the tod running. E.g. during migration, this
     * is the point where we want to stop the initially running TOD to fire
     * it back up when actually starting the migrated guest.
     */
    kvm_s390_set_tod_raw(tod, &local_err);
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }

    if (runstate_is_running()) {
        td->stopped = false;
    } else {
        td->stopped = true;
        td->base = *tod;
    }
}

static void kvm_s390_tod_vm_state_change(void *opaque, int running,
                                         RunState state)
{
    S390TODState *td = opaque;
    Error *local_err = NULL;

    if (running && td->stopped) {
        /* Set the old TOD when running the VM - start the TOD clock. */
        kvm_s390_set_tod_raw(&td->base, &local_err);
        if (local_err) {
            warn_report_err(local_err);
        }
        /* Treat errors like the TOD was running all the time. */
        td->stopped = false;
    } else if (!running && !td->stopped) {
        /* Store the TOD when stopping the VM - stop the TOD clock. */
        kvm_s390_get_tod_raw(&td->base, &local_err);
        if (local_err) {
            /* Keep the TOD running in case we could not back it up. */
            warn_report_err(local_err);
        } else {
            td->stopped = true;
        }
    }
}

static void kvm_s390_tod_realize(DeviceState *dev, Error **errp)
{
    S390TODState *td = S390_TOD(dev);
    S390TODClass *tdc = S390_TOD_GET_CLASS(td);
    Error *local_err = NULL;

    tdc->parent_realize(dev, &local_err);
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }

    /*
     * We need to know when the VM gets started/stopped to start/stop the TOD.
     * As we can never have more than one TOD instance (and that will never be
     * removed), registering here and never unregistering is good enough.
     */
    qemu_add_vm_change_state_handler(kvm_s390_tod_vm_state_change, td);
}

static void kvm_s390_tod_class_init(ObjectClass *oc, void *data)
{
    S390TODClass *tdc = S390_TOD_CLASS(oc);

    device_class_set_parent_realize(DEVICE_CLASS(oc), kvm_s390_tod_realize,
                                    &tdc->parent_realize);
    tdc->get = kvm_s390_tod_get;
    tdc->set = kvm_s390_tod_set;
}

static void kvm_s390_tod_init(Object *obj)
{
    S390TODState *td = S390_TOD(obj);

    /*
     * The TOD is initially running (value stored in KVM). Avoid needless
     * loading/storing of the TOD when starting a simple VM, so let it
     * run although the (never started) VM is stopped. For migration, we
     * will properly set the TOD later.
     */
    td->stopped = false;
}

static TypeInfo kvm_s390_tod_info = {
    .name = TYPE_KVM_S390_TOD,
    .parent = TYPE_S390_TOD,
    .instance_size = sizeof(S390TODState),
    .instance_init = kvm_s390_tod_init,
    .class_init = kvm_s390_tod_class_init,
    .class_size = sizeof(S390TODClass),
};

static void register_types(void)
{
    type_register_static(&kvm_s390_tod_info);
}
type_init(register_types);
