2 * TOD (Time Of Day) clock
4 * Copyright 2018 Red Hat, Inc.
5 * Author(s): David Hildenbrand <david@redhat.com>
7 * This work is licensed under the terms of the GNU GPL, version 2 or later.
8 * See the COPYING file in the top-level directory.
11 #include "qemu/osdep.h"
12 #include "hw/s390x/tod.h"
13 #include "qapi/error.h"
14 #include "qemu/error-report.h"
15 #include "qemu/module.h"
16 #include "sysemu/kvm.h"
17 #include "sysemu/tcg.h"
18 #include "sysemu/qtest.h"
19 #include "migration/qemu-file-types.h"
20 #include "migration/register.h"
22 void s390_init_tod(void)
27 obj
= object_new(TYPE_KVM_S390_TOD
);
28 } else if (tcg_enabled()) {
29 obj
= object_new(TYPE_QEMU_S390_TOD
);
30 } else if (qtest_enabled()) {
33 error_report("current accelerator not handled in s390_init_tod!");
36 object_property_add_child(qdev_get_machine(), TYPE_S390_TOD
, obj
);
39 qdev_realize(DEVICE(obj
), NULL
, &error_fatal
);
42 S390TODState
*s390_get_todstate(void)
44 static S390TODState
*ts
;
47 ts
= S390_TOD(object_resolve_path_type("", TYPE_S390_TOD
, NULL
));
53 #define S390_TOD_CLOCK_VALUE_MISSING 0x00
54 #define S390_TOD_CLOCK_VALUE_PRESENT 0x01
56 static void s390_tod_save(QEMUFile
*f
, void *opaque
)
58 S390TODState
*td
= opaque
;
59 S390TODClass
*tdc
= S390_TOD_GET_CLASS(td
);
63 tdc
->get(td
, &tod
, &err
);
66 error_printf("Guest clock will not be migrated "
67 "which could cause the guest to hang.");
68 qemu_put_byte(f
, S390_TOD_CLOCK_VALUE_MISSING
);
72 qemu_put_byte(f
, S390_TOD_CLOCK_VALUE_PRESENT
);
73 qemu_put_byte(f
, tod
.high
);
74 qemu_put_be64(f
, tod
.low
);
77 static int s390_tod_load(QEMUFile
*f
, void *opaque
, int version_id
)
79 S390TODState
*td
= opaque
;
80 S390TODClass
*tdc
= S390_TOD_GET_CLASS(td
);
84 if (qemu_get_byte(f
) == S390_TOD_CLOCK_VALUE_MISSING
) {
85 warn_report("Guest clock was not migrated. This could "
86 "cause the guest to hang.");
90 tod
.high
= qemu_get_byte(f
);
91 tod
.low
= qemu_get_be64(f
);
93 tdc
->set(td
, &tod
, &err
);
95 error_report_err(err
);
101 static SaveVMHandlers savevm_tod
= {
102 .save_state
= s390_tod_save
,
103 .load_state
= s390_tod_load
,
106 static void s390_tod_realize(DeviceState
*dev
, Error
**errp
)
108 S390TODState
*td
= S390_TOD(dev
);
110 /* Legacy migration interface */
111 register_savevm_live("todclock", 0, 1, &savevm_tod
, td
);
114 static void s390_tod_class_init(ObjectClass
*oc
, void *data
)
116 DeviceClass
*dc
= DEVICE_CLASS(oc
);
118 dc
->desc
= "TOD (Time Of Day) Clock";
119 dc
->realize
= s390_tod_realize
;
120 set_bit(DEVICE_CATEGORY_MISC
, dc
->categories
);
122 /* We only have one TOD clock in the system attached to the machine */
123 dc
->user_creatable
= false;
126 static const TypeInfo s390_tod_info
= {
127 .name
= TYPE_S390_TOD
,
128 .parent
= TYPE_DEVICE
,
129 .instance_size
= sizeof(S390TODState
),
130 .class_init
= s390_tod_class_init
,
131 .class_size
= sizeof(S390TODClass
),
135 static void register_types(void)
137 type_register_static(&s390_tod_info
);
139 type_init(register_types
);