aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
authorCyril Bur <cyrilbur@gmail.com>2015-02-12 18:01:28 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-02-12 21:54:13 -0500
commit4be1b29795d692d512bb67b770665d6f8ea5cb0b (patch)
tree7502b10178a0c16f65e7be2aecf583691f78dedf /arch/powerpc/kernel
parent545a2bf742fb41f17d03486dd8a8c74ad511dec2 (diff)
powerpc: add running_clock for powerpc to prevent spurious softlockup warnings
On POWER8 virtualised kernels the VTB register can be read to have a view of time that only increases while the guest is running. This will prevent guests from seeing time jump if a guest is paused for significant amounts of time. On POWER7 and below virtualised kernels stolen time is subtracted from local_clock as a best effort approximation. This will not eliminate spurious warnings in the case of a suspended guest but may reduce the occurance in the case of softlockups due to host over commit. Bare metal kernels should avoid reading the VTB as KVM does not restore sane values when not executing, the approxmation is fine as host kernels won't observe any stolen time. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Cyril Bur <cyrilbur@gmail.com> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Andrew Jones <drjones@redhat.com> Acked-by: Don Zickus <dzickus@redhat.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Ulrich Obergfell <uobergfe@redhat.com> Cc: chai wen <chaiw.fnst@cn.fujitsu.com> Cc: Fabian Frederick <fabf@skynet.be> Cc: Aaron Tomlin <atomlin@redhat.com> Cc: Ben Zhang <benzh@chromium.org> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: John Stultz <john.stultz@linaro.org> Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/time.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index fa7c4f12104f..7316dd15278a 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -621,6 +621,38 @@ unsigned long long sched_clock(void)
621 return mulhdu(get_tb() - boot_tb, tb_to_ns_scale) << tb_to_ns_shift; 621 return mulhdu(get_tb() - boot_tb, tb_to_ns_scale) << tb_to_ns_shift;
622} 622}
623 623
624
625#ifdef CONFIG_PPC_PSERIES
626
627/*
628 * Running clock - attempts to give a view of time passing for a virtualised
629 * kernels.
630 * Uses the VTB register if available otherwise a next best guess.
631 */
632unsigned long long running_clock(void)
633{
634 /*
635 * Don't read the VTB as a host since KVM does not switch in host
636 * timebase into the VTB when it takes a guest off the CPU, reading the
637 * VTB would result in reading 'last switched out' guest VTB.
638 *
639 * Host kernels are often compiled with CONFIG_PPC_PSERIES checked, it
640 * would be unsafe to rely only on the #ifdef above.
641 */
642 if (firmware_has_feature(FW_FEATURE_LPAR) &&
643 cpu_has_feature(CPU_FTR_ARCH_207S))
644 return mulhdu(get_vtb() - boot_tb, tb_to_ns_scale) << tb_to_ns_shift;
645
646 /*
647 * This is a next best approximation without a VTB.
648 * On a host which is running bare metal there should never be any stolen
649 * time and on a host which doesn't do any virtualisation TB *should* equal
650 * VTB so it makes no difference anyway.
651 */
652 return local_clock() - cputime_to_nsecs(kcpustat_this_cpu->cpustat[CPUTIME_STEAL]);
653}
654#endif
655
624static int __init get_freq(char *name, int cells, unsigned long *val) 656static int __init get_freq(char *name, int cells, unsigned long *val)
625{ 657{
626 struct device_node *cpu; 658 struct device_node *cpu;