/*
 * TOD (Time Of Day) clock
 *
 * 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 "hw/s390x/tod.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "sysemu/kvm.h"
#include "migration/register.h"

void s390_init_tod(void)
{
    Object *obj;

    if (kvm_enabled()) {
        obj = object_new(TYPE_KVM_S390_TOD);
    } else {
        obj = object_new(TYPE_QEMU_S390_TOD);
    }
    object_property_add_child(qdev_get_machine(), TYPE_S390_TOD, obj, NULL);
    object_unref(obj);

    qdev_init_nofail(DEVICE(obj));
}

S390TODState *s390_get_todstate(void)
{
    static S390TODState *ts;

    if (!ts) {
        ts = S390_TOD(object_resolve_path_type("", TYPE_S390_TOD, NULL));
    }

    return ts;
}

#define S390_TOD_CLOCK_VALUE_MISSING    0x00
#define S390_TOD_CLOCK_VALUE_PRESENT    0x01

static void s390_tod_save(QEMUFile *f, void *opaque)
{
    S390TODState *td = opaque;
    S390TODClass *tdc = S390_TOD_GET_CLASS(td);
    Error *err = NULL;
    S390TOD tod;

    tdc->get(td, &tod, &err);
    if (err) {
        warn_report_err(err);
        error_printf("Guest clock will not be migrated "
                     "which could cause the guest to hang.");
        qemu_put_byte(f, S390_TOD_CLOCK_VALUE_MISSING);
        return;
    }

    qemu_put_byte(f, S390_TOD_CLOCK_VALUE_PRESENT);
    qemu_put_byte(f, tod.high);
    qemu_put_be64(f, tod.low);
}

static int s390_tod_load(QEMUFile *f, void *opaque, int version_id)
{
    S390TODState *td = opaque;
    S390TODClass *tdc = S390_TOD_GET_CLASS(td);
    Error *err = NULL;
    S390TOD tod;

    if (qemu_get_byte(f) == S390_TOD_CLOCK_VALUE_MISSING) {
        warn_report("Guest clock was not migrated. This could "
                    "cause the guest to hang.");
        return 0;
    }

    tod.high = qemu_get_byte(f);
    tod.low = qemu_get_be64(f);

    tdc->set(td, &tod, &err);
    if (err) {
        error_report_err(err);
        return -1;
    }
    return 0;
}

static SaveVMHandlers savevm_tod = {
    .save_state = s390_tod_save,
    .load_state = s390_tod_load,
};

static void s390_tod_realize(DeviceState *dev, Error **errp)
{
    S390TODState *td = S390_TOD(dev);

    /* Legacy migration interface */
    register_savevm_live(NULL, "todclock", 0, 1, &savevm_tod, td);
}

static void s390_tod_class_init(ObjectClass *oc, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(oc);

    dc->desc = "TOD (Time Of Day) Clock";
    dc->realize = s390_tod_realize;
    set_bit(DEVICE_CATEGORY_MISC, dc->categories);

    /* We only have one TOD clock in the system attached to the machine */
    dc->user_creatable = false;
}

static TypeInfo s390_tod_info = {
    .name = TYPE_S390_TOD,
    .parent = TYPE_DEVICE,
    .instance_size = sizeof(S390TODState),
    .class_init = s390_tod_class_init,
    .class_size = sizeof(S390TODClass),
    .abstract = true,
};

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