[s390] s390/time: fix sched_clock() overflow (Closes: #698382)
svn path=/dists/sid/linux/; revision=19753
This commit is contained in:
parent
7559b067e5
commit
546c19fa7c
|
@ -90,6 +90,7 @@ linux (3.2.37-1) UNRELEASED; urgency=low
|
|||
- sched: Adjust sched_reset_on_fork when nothing else changes
|
||||
- sched: Queue RT tasks to head when prio drops
|
||||
- sched: Consider pi boosting in setscheduler
|
||||
* [s390] s390/time: fix sched_clock() overflow (Closes: #698382)
|
||||
|
||||
[ Aurelien Jarno ]
|
||||
* [armhf/vexpress] Add kernel udebs.
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
From: Heiko Carstens <heiko.carstens@de.ibm.com>
|
||||
Date: Mon, 14 Jan 2013 16:55:55 +0100
|
||||
Subject: s390/time: fix sched_clock() overflow
|
||||
|
||||
commit ed4f20943cd4c7b55105c04daedf8d63ab6d499c upstream.
|
||||
|
||||
Converting a 64 Bit TOD format value to nanoseconds means that the value
|
||||
must be divided by 4.096. In order to achieve that we multiply with 125
|
||||
and divide by 512.
|
||||
When used within sched_clock() this triggers an overflow after appr.
|
||||
417 days. Resulting in a sched_clock() return value that is much smaller
|
||||
than previously and therefore may cause all sort of weird things in
|
||||
subsystems that rely on a monotonic sched_clock() behaviour.
|
||||
|
||||
To fix this implement a tod_to_ns() helper function which converts TOD
|
||||
values without overflow and call this function from both places that
|
||||
open coded the conversion: sched_clock() and kvm_s390_handle_wait().
|
||||
|
||||
Reviewed-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
|
||||
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
|
||||
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
|
||||
---
|
||||
arch/s390/include/asm/timex.h | 28 ++++++++++++++++++++++++++++
|
||||
arch/s390/kernel/time.c | 2 +-
|
||||
arch/s390/kvm/interrupt.c | 2 +-
|
||||
3 files changed, 30 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h
|
||||
index fba4d66..4c060bb 100644
|
||||
--- a/arch/s390/include/asm/timex.h
|
||||
+++ b/arch/s390/include/asm/timex.h
|
||||
@@ -128,4 +128,32 @@ static inline unsigned long long get_clock_monotonic(void)
|
||||
return get_clock_xt() - sched_clock_base_cc;
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * tod_to_ns - convert a TOD format value to nanoseconds
|
||||
+ * @todval: to be converted TOD format value
|
||||
+ * Returns: number of nanoseconds that correspond to the TOD format value
|
||||
+ *
|
||||
+ * Converting a 64 Bit TOD format value to nanoseconds means that the value
|
||||
+ * must be divided by 4.096. In order to achieve that we multiply with 125
|
||||
+ * and divide by 512:
|
||||
+ *
|
||||
+ * ns = (todval * 125) >> 9;
|
||||
+ *
|
||||
+ * In order to avoid an overflow with the multiplication we can rewrite this.
|
||||
+ * With a split todval == 2^32 * th + tl (th upper 32 bits, tl lower 32 bits)
|
||||
+ * we end up with
|
||||
+ *
|
||||
+ * ns = ((2^32 * th + tl) * 125 ) >> 9;
|
||||
+ * -> ns = (2^23 * th * 125) + ((tl * 125) >> 9);
|
||||
+ *
|
||||
+ */
|
||||
+static inline unsigned long long tod_to_ns(unsigned long long todval)
|
||||
+{
|
||||
+ unsigned long long ns;
|
||||
+
|
||||
+ ns = ((todval >> 32) << 23) * 125;
|
||||
+ ns += ((todval & 0xffffffff) * 125) >> 9;
|
||||
+ return ns;
|
||||
+}
|
||||
+
|
||||
#endif
|
||||
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
|
||||
index aff0e35..a5f4f5a 100644
|
||||
--- a/arch/s390/kernel/time.c
|
||||
+++ b/arch/s390/kernel/time.c
|
||||
@@ -63,7 +63,7 @@ static DEFINE_PER_CPU(struct clock_event_device, comparators);
|
||||
*/
|
||||
unsigned long long notrace __kprobes sched_clock(void)
|
||||
{
|
||||
- return (get_clock_monotonic() * 125) >> 9;
|
||||
+ return tod_to_ns(get_clock_monotonic());
|
||||
}
|
||||
|
||||
/*
|
||||
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
|
||||
index c30615e..82c481d 100644
|
||||
--- a/arch/s390/kvm/interrupt.c
|
||||
+++ b/arch/s390/kvm/interrupt.c
|
||||
@@ -408,7 +408,7 @@ int kvm_s390_handle_wait(struct kvm_vcpu *vcpu)
|
||||
return 0;
|
||||
}
|
||||
|
||||
- sltime = ((vcpu->arch.sie_block->ckc - now)*125)>>9;
|
||||
+ sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now);
|
||||
|
||||
hrtimer_start(&vcpu->arch.ckc_timer, ktime_set (0, sltime) , HRTIMER_MODE_REL);
|
||||
VCPU_EVENT(vcpu, 5, "enabled wait via clock comparator: %llx ns", sltime);
|
|
@ -466,3 +466,4 @@ features/all/rt2800-add-chipset-revision-RT5390R-support.patch
|
|||
bugfix/all/vt6656-Fix-inconsistent-structure-packing.patch
|
||||
bugfix/all/fs-cachefiles-add-support-for-large-files-in-filesys.patch
|
||||
bugfix/x86/xen-Fix-stack-corruption-in-xen_failsafe_callback-fo.patch
|
||||
bugfix/s390/s390-time-fix-sched_clock-overflow.patch
|
||||
|
|
Loading…
Reference in New Issue