diff options
-rw-r--r-- | arch/s390/include/asm/timex.h | 28 | ||||
-rw-r--r-- | arch/s390/kernel/time.c | 2 | ||||
-rw-r--r-- | 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 fba4d66788a2..4c060bb5b8ea 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) | |||
128 | return get_clock_xt() - sched_clock_base_cc; | 128 | return get_clock_xt() - sched_clock_base_cc; |
129 | } | 129 | } |
130 | 130 | ||
131 | /** | ||
132 | * tod_to_ns - convert a TOD format value to nanoseconds | ||
133 | * @todval: to be converted TOD format value | ||
134 | * Returns: number of nanoseconds that correspond to the TOD format value | ||
135 | * | ||
136 | * Converting a 64 Bit TOD format value to nanoseconds means that the value | ||
137 | * must be divided by 4.096. In order to achieve that we multiply with 125 | ||
138 | * and divide by 512: | ||
139 | * | ||
140 | * ns = (todval * 125) >> 9; | ||
141 | * | ||
142 | * In order to avoid an overflow with the multiplication we can rewrite this. | ||
143 | * With a split todval == 2^32 * th + tl (th upper 32 bits, tl lower 32 bits) | ||
144 | * we end up with | ||
145 | * | ||
146 | * ns = ((2^32 * th + tl) * 125 ) >> 9; | ||
147 | * -> ns = (2^23 * th * 125) + ((tl * 125) >> 9); | ||
148 | * | ||
149 | */ | ||
150 | static inline unsigned long long tod_to_ns(unsigned long long todval) | ||
151 | { | ||
152 | unsigned long long ns; | ||
153 | |||
154 | ns = ((todval >> 32) << 23) * 125; | ||
155 | ns += ((todval & 0xffffffff) * 125) >> 9; | ||
156 | return ns; | ||
157 | } | ||
158 | |||
131 | #endif | 159 | #endif |
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index aff0e350d776..a5f4f5a1d24b 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); | |||
63 | */ | 63 | */ |
64 | unsigned long long notrace __kprobes sched_clock(void) | 64 | unsigned long long notrace __kprobes sched_clock(void) |
65 | { | 65 | { |
66 | return (get_clock_monotonic() * 125) >> 9; | 66 | return tod_to_ns(get_clock_monotonic()); |
67 | } | 67 | } |
68 | 68 | ||
69 | /* | 69 | /* |
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index c30615e605ac..82c481ddef76 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) | |||
408 | return 0; | 408 | return 0; |
409 | } | 409 | } |
410 | 410 | ||
411 | sltime = ((vcpu->arch.sie_block->ckc - now)*125)>>9; | 411 | sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now); |
412 | 412 | ||
413 | hrtimer_start(&vcpu->arch.ckc_timer, ktime_set (0, sltime) , HRTIMER_MODE_REL); | 413 | hrtimer_start(&vcpu->arch.ckc_timer, ktime_set (0, sltime) , HRTIMER_MODE_REL); |
414 | VCPU_EVENT(vcpu, 5, "enabled wait via clock comparator: %llx ns", sltime); | 414 | VCPU_EVENT(vcpu, 5, "enabled wait via clock comparator: %llx ns", sltime); |