tod-tcg.c (2281B)
1/* 2 * TOD (Time Of Day) clock - TCG implementation 3 * 4 * Copyright 2018 Red Hat, Inc. 5 * Author(s): David Hildenbrand <david@redhat.com> 6 * 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. 9 */ 10 11#include "qemu/osdep.h" 12#include "qemu-common.h" 13#include "qapi/error.h" 14#include "hw/s390x/tod.h" 15#include "qemu/timer.h" 16#include "qemu/cutils.h" 17#include "qemu/module.h" 18#include "cpu.h" 19#include "tcg/tcg_s390x.h" 20 21static void qemu_s390_tod_get(const S390TODState *td, S390TOD *tod, 22 Error **errp) 23{ 24 *tod = td->base; 25 26 tod->low += time2tod(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); 27 if (tod->low < td->base.low) { 28 tod->high++; 29 } 30} 31 32static void qemu_s390_tod_set(S390TODState *td, const S390TOD *tod, 33 Error **errp) 34{ 35 CPUState *cpu; 36 37 td->base = *tod; 38 39 td->base.low -= time2tod(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); 40 if (td->base.low > tod->low) { 41 td->base.high--; 42 } 43 44 /* 45 * The TOD has been changed and we have to recalculate the CKC values 46 * for all CPUs. We do this asynchronously, as "SET CLOCK should be 47 * issued only while all other activity on all CPUs .. has been 48 * suspended". 49 */ 50 CPU_FOREACH(cpu) { 51 async_run_on_cpu(cpu, tcg_s390_tod_updated, RUN_ON_CPU_NULL); 52 } 53} 54 55static void qemu_s390_tod_class_init(ObjectClass *oc, void *data) 56{ 57 S390TODClass *tdc = S390_TOD_CLASS(oc); 58 59 tdc->get = qemu_s390_tod_get; 60 tdc->set = qemu_s390_tod_set; 61} 62 63static void qemu_s390_tod_init(Object *obj) 64{ 65 S390TODState *td = S390_TOD(obj); 66 struct tm tm; 67 68 qemu_get_timedate(&tm, 0); 69 td->base.high = 0; 70 td->base.low = TOD_UNIX_EPOCH + (time2tod(mktimegm(&tm)) * 1000000000ULL); 71 if (td->base.low < TOD_UNIX_EPOCH) { 72 td->base.high += 1; 73 } 74} 75 76static TypeInfo qemu_s390_tod_info = { 77 .name = TYPE_QEMU_S390_TOD, 78 .parent = TYPE_S390_TOD, 79 .instance_size = sizeof(S390TODState), 80 .instance_init = qemu_s390_tod_init, 81 .class_init = qemu_s390_tod_class_init, 82 .class_size = sizeof(S390TODClass), 83}; 84 85static void register_types(void) 86{ 87 type_register_static(&qemu_s390_tod_info); 88} 89type_init(register_types);