diff --git a/debian/changelog b/debian/changelog index f5d38a341..2f82ca248 100644 --- a/debian/changelog +++ b/debian/changelog @@ -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. diff --git a/debian/patches/bugfix/s390/s390-time-fix-sched_clock-overflow.patch b/debian/patches/bugfix/s390/s390-time-fix-sched_clock-overflow.patch new file mode 100644 index 000000000..b31fad87d --- /dev/null +++ b/debian/patches/bugfix/s390/s390-time-fix-sched_clock-overflow.patch @@ -0,0 +1,90 @@ +From: Heiko Carstens +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 +Signed-off-by: Heiko Carstens +Signed-off-by: Martin Schwidefsky +--- + 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); diff --git a/debian/patches/series b/debian/patches/series index 24ddd7edb..3c499daa9 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -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