At the time of CPU startup, we want to read a TSC value and store it
in the variable named 'tsc_at_head'. This operation is supposed to be
performed only when the first CPU starts (the boot CPU), i.e., inside
startup_64(). However, the current code puts this logic inside
secondary_startup_64(), which is the initialization logic for all the
other CPUs (non-boot or secondary CPUs).
Fix this by moving the read-tsc logic to the beginning of the boot CPU
init sequence (startup_64()).
Change-Id: I12671d47169570cbbdada261baf8abd5b1d9198c
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/6468
Tested-by: gerrit-photon <photon-checkins@vmware.com>
Reviewed-by: Alexey Makhalov <amakhalov@vmware.com>
| ... | ... |
@@ -13,10 +13,10 @@ Subject: [PATCH] x86/vmware: pv-ops boot_clock |
| 13 | 13 |
6 files changed, 57 insertions(+), 1 deletion(-) |
| 14 | 14 |
|
| 15 | 15 |
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h |
| 16 |
-index ce932812f142..3d4ba2a999cb 100644 |
|
| 16 |
+index 24af8b1..65af182 100644 |
|
| 17 | 17 |
--- a/arch/x86/include/asm/paravirt.h |
| 18 | 18 |
+++ b/arch/x86/include/asm/paravirt.h |
| 19 |
-@@ -193,6 +193,11 @@ static inline u64 paravirt_steal_clock(int cpu) |
|
| 19 |
+@@ -194,6 +194,11 @@ static inline u64 paravirt_steal_clock(int cpu) |
|
| 20 | 20 |
return PVOP_CALL1(u64, pv_time_ops.steal_clock, cpu); |
| 21 | 21 |
} |
| 22 | 22 |
|
| ... | ... |
@@ -29,10 +29,10 @@ index ce932812f142..3d4ba2a999cb 100644 |
| 29 | 29 |
{
|
| 30 | 30 |
return PVOP_CALL1(u64, pv_cpu_ops.read_pmc, counter); |
| 31 | 31 |
diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h |
| 32 |
-index 0f400c0e4979..5f09979f612d 100644 |
|
| 32 |
+index 04b7971..b3c7f41 100644 |
|
| 33 | 33 |
--- a/arch/x86/include/asm/paravirt_types.h |
| 34 | 34 |
+++ b/arch/x86/include/asm/paravirt_types.h |
| 35 |
-@@ -51,6 +51,10 @@ struct mm_struct; |
|
| 35 |
+@@ -52,6 +52,10 @@ struct mm_struct; |
|
| 36 | 36 |
struct desc_struct; |
| 37 | 37 |
struct task_struct; |
| 38 | 38 |
struct cpumask; |
| ... | ... |
@@ -43,7 +43,7 @@ index 0f400c0e4979..5f09979f612d 100644 |
| 43 | 43 |
|
| 44 | 44 |
/* |
| 45 | 45 |
* Wrapper type for pointers to code which uses the non-standard |
| 46 |
-@@ -96,6 +100,7 @@ struct pv_lazy_ops {
|
|
| 46 |
+@@ -97,6 +101,7 @@ struct pv_lazy_ops {
|
|
| 47 | 47 |
struct pv_time_ops {
|
| 48 | 48 |
unsigned long long (*sched_clock)(void); |
| 49 | 49 |
unsigned long long (*steal_clock)(int cpu); |
| ... | ... |
@@ -52,7 +52,7 @@ index 0f400c0e4979..5f09979f612d 100644 |
| 52 | 52 |
|
| 53 | 53 |
struct pv_cpu_ops {
|
| 54 | 54 |
diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c |
| 55 |
-index 987ac571d16c..0e1fc6e17efc 100644 |
|
| 55 |
+index 569356f..ad82ac3 100644 |
|
| 56 | 56 |
--- a/arch/x86/kernel/cpu/vmware.c |
| 57 | 57 |
+++ b/arch/x86/kernel/cpu/vmware.c |
| 58 | 58 |
@@ -124,6 +124,7 @@ static struct kmsg_dumper kmsg_dumper = {
|
| ... | ... |
@@ -72,7 +72,7 @@ index 987ac571d16c..0e1fc6e17efc 100644 |
| 72 | 72 |
|
| 73 | 73 |
clocks_calc_mult_shift(&d->cyc2ns_mul, &d->cyc2ns_shift, |
| 74 | 74 |
vmware_tsc_khz, NSEC_PER_MSEC, 0); |
| 75 |
-@@ -175,6 +176,26 @@ struct clocksource * __init clocksource_default_clock(void) |
|
| 75 |
+@@ -176,6 +177,26 @@ struct clocksource * __init clocksource_default_clock(void) |
|
| 76 | 76 |
return &clocksource_vmware; |
| 77 | 77 |
} |
| 78 | 78 |
|
| ... | ... |
@@ -99,7 +99,7 @@ index 987ac571d16c..0e1fc6e17efc 100644 |
| 99 | 99 |
static uint64_t vmware_steal_clock(int cpu) |
| 100 | 100 |
{
|
| 101 | 101 |
struct vmware_steal_time *steal; |
| 102 |
-@@ -311,6 +332,7 @@ static void __init vmware_paravirt_ops_setup(void) |
|
| 102 |
+@@ -312,6 +333,7 @@ static void __init vmware_paravirt_ops_setup(void) |
|
| 103 | 103 |
#endif |
| 104 | 104 |
} |
| 105 | 105 |
clocksource_register_khz(&clocksource_vmware, vmware_tsc_khz); |
| ... | ... |
@@ -108,14 +108,13 @@ index 987ac571d16c..0e1fc6e17efc 100644 |
| 108 | 108 |
#else |
| 109 | 109 |
#define vmware_paravirt_ops_setup() do {} while (0)
|
| 110 | 110 |
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S |
| 111 |
-index b4421cc191b0..f7b8017fa90a 100644 |
|
| 111 |
+index 9d72cf5..42d8307 100644 |
|
| 112 | 112 |
--- a/arch/x86/kernel/head_64.S |
| 113 | 113 |
+++ b/arch/x86/kernel/head_64.S |
| 114 |
-@@ -184,6 +184,14 @@ ENTRY(secondary_startup_64) |
|
| 115 |
- * after the boot processor executes this code. |
|
| 114 |
+@@ -68,6 +68,14 @@ startup_64: |
|
| 116 | 115 |
*/ |
| 117 | 116 |
|
| 118 |
-+ /* |
|
| 117 |
+ /* |
|
| 119 | 118 |
+ * Read a TSC value first |
| 120 | 119 |
+ */ |
| 121 | 120 |
+ rdtsc |
| ... | ... |
@@ -123,14 +122,15 @@ index b4421cc191b0..f7b8017fa90a 100644 |
| 123 | 123 |
+ or %rax, %rdx |
| 124 | 124 |
+ mov %rdx, tsc_at_head(%rip) |
| 125 | 125 |
+ |
| 126 |
- /* Sanitize CPU configuration */ |
|
| 127 |
- call verify_cpu |
|
| 128 |
- |
|
| 126 |
++ /* |
|
| 127 |
+ * Setup stack for verify_cpu(). "-8" because initial_stack is defined |
|
| 128 |
+ * this way, see below. Our best guess is a NULL ptr for stack |
|
| 129 |
+ * termination heuristics and we don't want to break anything which |
|
| 129 | 130 |
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c |
| 130 |
-index bbf3d5933eaa..10bbdb3e6651 100644 |
|
| 131 |
+index bf9552b..22319ab 100644 |
|
| 131 | 132 |
--- a/arch/x86/kernel/paravirt.c |
| 132 | 133 |
+++ b/arch/x86/kernel/paravirt.c |
| 133 |
-@@ -203,6 +203,12 @@ static u64 native_steal_clock(int cpu) |
|
| 134 |
+@@ -209,6 +209,12 @@ static u64 native_steal_clock(int cpu) |
|
| 134 | 135 |
return 0; |
| 135 | 136 |
} |
| 136 | 137 |
|
| ... | ... |
@@ -143,7 +143,7 @@ index bbf3d5933eaa..10bbdb3e6651 100644 |
| 143 | 143 |
/* These are in entry.S */ |
| 144 | 144 |
extern void native_iret(void); |
| 145 | 145 |
extern void native_usergs_sysret64(void); |
| 146 |
-@@ -310,6 +316,7 @@ struct pv_init_ops pv_init_ops = {
|
|
| 146 |
+@@ -316,6 +322,7 @@ struct pv_init_ops pv_init_ops = {
|
|
| 147 | 147 |
struct pv_time_ops pv_time_ops = {
|
| 148 | 148 |
.sched_clock = native_sched_clock, |
| 149 | 149 |
.steal_clock = native_steal_clock, |
| ... | ... |
@@ -152,10 +152,10 @@ index bbf3d5933eaa..10bbdb3e6651 100644 |
| 152 | 152 |
|
| 153 | 153 |
__visible struct pv_irq_ops pv_irq_ops = {
|
| 154 | 154 |
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c |
| 155 |
-index 9c337b0e8ba7..67a42e58b118 100644 |
|
| 155 |
+index 49960ec..87d7870 100644 |
|
| 156 | 156 |
--- a/arch/x86/kernel/setup.c |
| 157 | 157 |
+++ b/arch/x86/kernel/setup.c |
| 158 |
-@@ -1302,3 +1302,12 @@ void arch_show_smap(struct seq_file *m, struct vm_area_struct *vma) |
|
| 158 |
+@@ -1322,3 +1322,12 @@ void arch_show_smap(struct seq_file *m, struct vm_area_struct *vma) |
|
| 159 | 159 |
|
| 160 | 160 |
seq_printf(m, "ProtectionKey: %8u\n", vma_pkey(vma)); |
| 161 | 161 |
} |
| ... | ... |
@@ -168,6 +168,3 @@ index 9c337b0e8ba7..67a42e58b118 100644 |
| 168 | 168 |
+ paravirt_read_boot_clock64(ts); |
| 169 | 169 |
+} |
| 170 | 170 |
+#endif |
| 171 |
-2.11.0 |
|
| 172 |
- |
| ... | ... |
@@ -2,7 +2,7 @@ |
| 2 | 2 |
Summary: Kernel |
| 3 | 3 |
Name: linux-esx |
| 4 | 4 |
Version: 4.9.140 |
| 5 |
-Release: 2%{?dist}
|
|
| 5 |
+Release: 3%{?dist}
|
|
| 6 | 6 |
License: GPLv2 |
| 7 | 7 |
URL: http://www.kernel.org/ |
| 8 | 8 |
Group: System Environment/Kernel |
| ... | ... |
@@ -233,6 +233,8 @@ ln -sf linux-%{uname_r}.cfg /boot/photon.cfg
|
| 233 | 233 |
/usr/src/linux-headers-%{uname_r}
|
| 234 | 234 |
|
| 235 | 235 |
%changelog |
| 236 |
+* Tue Jan 08 2019 Srivatsa S. Bhat (VMware) <srivatsa@csail.mit.edu> 4.9.140-3 |
|
| 237 |
+- Read TSC only during the startup of the boot-CPU. |
|
| 236 | 238 |
* Mon Dec 03 2018 Alexey Makhalov <amakhalov@vmware.com> 4.9.140-2 |
| 237 | 239 |
- Fix BAR4 is zero issue for IDE devices |
| 238 | 240 |
* Mon Nov 26 2018 Srivatsa S. Bhat (VMware) <srivatsa@csail.mit.edu> 4.9.140-1 |