aboutsummaryrefslogtreecommitdiff
path: root/target/s390x
diff options
context:
space:
mode:
authorDavid Hildenbrand <david@redhat.com>2018-06-27 15:44:02 +0200
committerCornelia Huck <cohuck@redhat.com>2018-07-02 10:37:38 +0200
commit14055ce53c2d901d826ffad7fb7d6bb8ab46bdfd (patch)
treeea862f25f01811e86b14928bbcd00ed42a20940f /target/s390x
parent87273151110b7736b34ae3e37ad778c28c36d643 (diff)
s390x/tcg: avoid overflows in time2tod/tod2time
Big values for the TOD/ns clock can result in some overflows that can be avoided. Not all overflows can be handled however, as the conversion either multiplies by 4.096 or divided by 4.096. Apply the trick used in the Linux kernel in arch/s390/include/asm/timex.h for tod_to_ns() and use the same trick also for the conversion in the other direction. Reviewed-by: Thomas Huth <thuth@redhat.com> Signed-off-by: David Hildenbrand <david@redhat.com> Message-Id: <20180627134410.4901-2-david@redhat.com> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
Diffstat (limited to 'target/s390x')
-rw-r--r--target/s390x/internal.h5
1 files changed, 3 insertions, 2 deletions
diff --git a/target/s390x/internal.h b/target/s390x/internal.h
index e392a02d12..6cf63340bf 100644
--- a/target/s390x/internal.h
+++ b/target/s390x/internal.h
@@ -243,13 +243,14 @@ enum cc_op {
/* Converts ns to s390's clock format */
static inline uint64_t time2tod(uint64_t ns)
{
- return (ns << 9) / 125;
+ return (ns << 9) / 125 + (((ns & 0xff10000000000000ull) / 125) << 9);
+
}
/* Converts s390's clock format to ns */
static inline uint64_t tod2time(uint64_t t)
{
- return (t * 125) >> 9;
+ return ((t >> 9) * 125) + (((t & 0x1ff) * 125) >> 9);
}
static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb,