|
@@ -621,6 +621,38 @@ unsigned long long sched_clock(void)
|
|
|
return mulhdu(get_tb() - boot_tb, tb_to_ns_scale) << tb_to_ns_shift;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+#ifdef CONFIG_PPC_PSERIES
|
|
|
+
|
|
|
+/*
|
|
|
+ * Running clock - attempts to give a view of time passing for a virtualised
|
|
|
+ * kernels.
|
|
|
+ * Uses the VTB register if available otherwise a next best guess.
|
|
|
+ */
|
|
|
+unsigned long long running_clock(void)
|
|
|
+{
|
|
|
+ /*
|
|
|
+ * Don't read the VTB as a host since KVM does not switch in host
|
|
|
+ * timebase into the VTB when it takes a guest off the CPU, reading the
|
|
|
+ * VTB would result in reading 'last switched out' guest VTB.
|
|
|
+ *
|
|
|
+ * Host kernels are often compiled with CONFIG_PPC_PSERIES checked, it
|
|
|
+ * would be unsafe to rely only on the #ifdef above.
|
|
|
+ */
|
|
|
+ if (firmware_has_feature(FW_FEATURE_LPAR) &&
|
|
|
+ cpu_has_feature(CPU_FTR_ARCH_207S))
|
|
|
+ return mulhdu(get_vtb() - boot_tb, tb_to_ns_scale) << tb_to_ns_shift;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * This is a next best approximation without a VTB.
|
|
|
+ * On a host which is running bare metal there should never be any stolen
|
|
|
+ * time and on a host which doesn't do any virtualisation TB *should* equal
|
|
|
+ * VTB so it makes no difference anyway.
|
|
|
+ */
|
|
|
+ return local_clock() - cputime_to_nsecs(kcpustat_this_cpu->cpustat[CPUTIME_STEAL]);
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
static int __init get_freq(char *name, int cells, unsigned long *val)
|
|
|
{
|
|
|
struct device_node *cpu;
|