diff options
author | David Hildenbrand <david@redhat.com> | 2018-06-27 15:44:06 +0200 |
---|---|---|
committer | Cornelia Huck <cohuck@redhat.com> | 2018-07-02 10:37:38 +0200 |
commit | 7de3b1cdc67dcb572c1761c2051252e91a438b22 (patch) | |
tree | 0c3045416a75bd11ecc4eac3c2743bea454b1cb1 /target/s390x/misc_helper.c | |
parent | f777b20544fe5db3de179a83374cbf9f1e454427 (diff) |
s390x/tcg: properly implement the TOD
Right now, each CPU has its own TOD. Especially, the TOD will differ
based on creation time of a CPU - e.g. when hotplugging a CPU the times
will differ quite a lot, resulting in stall warnings in the guest.
Let's use a single TOD by implementing our new TOD device. Prepare it
for TOD-clock epoch extension.
Most importantly, whenever we set the TOD, we have to update the CKC
timer.
Introduce "tcg_s390x.h" just like "kvm_s390x.h" for tcg specific
function declarations that should not go into cpu.h.
Reviewed-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20180627134410.4901-6-david@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
Diffstat (limited to 'target/s390x/misc_helper.c')
-rw-r--r-- | target/s390x/misc_helper.c | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/target/s390x/misc_helper.c b/target/s390x/misc_helper.c index dd5273949b..229f14d3da 100644 --- a/target/s390x/misc_helper.c +++ b/target/s390x/misc_helper.c @@ -28,6 +28,8 @@ #include "qemu/timer.h" #include "exec/exec-all.h" #include "exec/cpu_ldst.h" +#include "qapi/error.h" +#include "tcg_s390x.h" #if !defined(CONFIG_USER_ONLY) #include "sysemu/cpus.h" @@ -39,6 +41,7 @@ #include "hw/s390x/ioinst.h" #include "hw/s390x/s390-pci-inst.h" #include "hw/boards.h" +#include "hw/s390x/tod.h" #endif /* #define DEBUG_HELPER */ @@ -138,17 +141,19 @@ void HELPER(spx)(CPUS390XState *env, uint64_t a1) /* Store Clock */ uint64_t HELPER(stck)(CPUS390XState *env) { - uint64_t time; + S390TODState *td = s390_get_todstate(); + S390TODClass *tdc = S390_TOD_GET_CLASS(td); + S390TOD tod; - time = env->tod_offset + - time2tod(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); - - return time; + tdc->get(td, &tod, &error_abort); + return tod.low; } /* Set Clock Comparator */ void HELPER(sckc)(CPUS390XState *env, uint64_t time) { + S390TODState *td = s390_get_todstate(); + if (time == -1ULL) { return; } @@ -156,7 +161,7 @@ void HELPER(sckc)(CPUS390XState *env, uint64_t time) env->ckc = time; /* difference between origins */ - time -= env->tod_offset; + time -= td->base.low; /* nanoseconds */ time = tod2time(time); @@ -164,6 +169,14 @@ void HELPER(sckc)(CPUS390XState *env, uint64_t time) timer_mod(env->tod_timer, time); } +void tcg_s390_tod_updated(CPUState *cs, run_on_cpu_data opaque) +{ + S390CPU *cpu = S390_CPU(cs); + CPUS390XState *env = &cpu->env; + + helper_sckc(env, env->ckc); +} + /* Set Tod Programmable Field */ void HELPER(sckpf)(CPUS390XState *env, uint64_t r0) { |