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 |