Re: [PATCH 2/5] X86: Hyper-V: Enable IPI enlightenments
From: kbuild test robot
Date: Fri Apr 27 2018 - 07:22:09 EST
Hi Srinivasan,
I love your patch! Perhaps something to improve:
[auto build test WARNING on v4.17-rc2]
[also build test WARNING on next-20180426]
[cannot apply to tip/x86/core]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/kys-linuxonhyperv-com/X86-Hyper-V-APIC-enlightenments/20180427-114416
reproduce:
# apt-get install sparse
make ARCH=x86_64 allmodconfig
make C=1 CF=-D__CHECK_ENDIAN__
sparse warnings: (new ones prefixed by >>)
>> arch/x86/hyperv/hv_init.c:105:30: sparse: incorrect type in initializer (different address spaces) @@ expected void const [noderef] <asn:3>*__vpp_verify @@ got const [noderef] <asn:3>*__vpp_verify @@
arch/x86/hyperv/hv_init.c:105:30: expected void const [noderef] <asn:3>*__vpp_verify
arch/x86/hyperv/hv_init.c:105:30: got void [noderef] <asn:3>**<noident>
arch/x86/hyperv/hv_init.c:229:30: sparse: incorrect type in initializer (different address spaces) @@ expected void const [noderef] <asn:3>*__vpp_verify @@ got const [noderef] <asn:3>*__vpp_verify @@
arch/x86/hyperv/hv_init.c:229:30: expected void const [noderef] <asn:3>*__vpp_verify
arch/x86/hyperv/hv_init.c:229:30: got void [noderef] <asn:3>**<noident>
>> arch/x86/hyperv/hv_init.c:275:31: sparse: incorrect type in assignment (different address spaces) @@ expected void [noderef] <asn:3>**extern [addressable] [toplevel] hyperv_pcpu_input_arg @@ got addressable] [toplevel] hyperv_pcpu_input_arg @@
arch/x86/hyperv/hv_init.c:275:31: expected void [noderef] <asn:3>**extern [addressable] [toplevel] hyperv_pcpu_input_arg
arch/x86/hyperv/hv_init.c:275:31: got void *[noderef] <asn:3>*<noident>
arch/x86/include/asm/paravirt.h:150:9: sparse: cast truncates bits from constant value (8000000000000000 becomes 0)
--
>> arch/x86/hyperv/hv_apic.c:118:41: sparse: incorrect type in initializer (different address spaces) @@ expected void const [noderef] <asn:3>*__vpp_verify @@ got const [noderef] <asn:3>*__vpp_verify @@
arch/x86/hyperv/hv_apic.c:118:41: expected void const [noderef] <asn:3>*__vpp_verify
arch/x86/hyperv/hv_apic.c:118:41: got void [noderef] <asn:3>**<noident>
vim +105 arch/x86/hyperv/hv_init.c
98
99 static int hv_cpu_init(unsigned int cpu)
100 {
101 u64 msr_vp_index;
102 struct hv_vp_assist_page **hvp = &hv_vp_assist_page[smp_processor_id()];
103 void **input_arg;
104
> 105 input_arg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
106 *input_arg = page_address(alloc_page(GFP_ATOMIC));
107
108 hv_get_vp_index(msr_vp_index);
109
110 hv_vp_index[smp_processor_id()] = msr_vp_index;
111
112 if (msr_vp_index > hv_max_vp_index)
113 hv_max_vp_index = msr_vp_index;
114
115 if (!hv_vp_assist_page)
116 return 0;
117
118 if (!*hvp)
119 *hvp = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL);
120
121 if (*hvp) {
122 u64 val;
123
124 val = vmalloc_to_pfn(*hvp);
125 val = (val << HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_SHIFT) |
126 HV_X64_MSR_VP_ASSIST_PAGE_ENABLE;
127
128 wrmsrl(HV_X64_MSR_VP_ASSIST_PAGE, val);
129 }
130
131 return 0;
132 }
133
134 static void (*hv_reenlightenment_cb)(void);
135
136 static void hv_reenlightenment_notify(struct work_struct *dummy)
137 {
138 struct hv_tsc_emulation_status emu_status;
139
140 rdmsrl(HV_X64_MSR_TSC_EMULATION_STATUS, *(u64 *)&emu_status);
141
142 /* Don't issue the callback if TSC accesses are not emulated */
143 if (hv_reenlightenment_cb && emu_status.inprogress)
144 hv_reenlightenment_cb();
145 }
146 static DECLARE_DELAYED_WORK(hv_reenlightenment_work, hv_reenlightenment_notify);
147
148 void hyperv_stop_tsc_emulation(void)
149 {
150 u64 freq;
151 struct hv_tsc_emulation_status emu_status;
152
153 rdmsrl(HV_X64_MSR_TSC_EMULATION_STATUS, *(u64 *)&emu_status);
154 emu_status.inprogress = 0;
155 wrmsrl(HV_X64_MSR_TSC_EMULATION_STATUS, *(u64 *)&emu_status);
156
157 rdmsrl(HV_X64_MSR_TSC_FREQUENCY, freq);
158 tsc_khz = div64_u64(freq, 1000);
159 }
160 EXPORT_SYMBOL_GPL(hyperv_stop_tsc_emulation);
161
162 static inline bool hv_reenlightenment_available(void)
163 {
164 /*
165 * Check for required features and priviliges to make TSC frequency
166 * change notifications work.
167 */
168 return ms_hyperv.features & HV_X64_ACCESS_FREQUENCY_MSRS &&
169 ms_hyperv.misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE &&
170 ms_hyperv.features & HV_X64_ACCESS_REENLIGHTENMENT;
171 }
172
173 __visible void __irq_entry hyperv_reenlightenment_intr(struct pt_regs *regs)
174 {
175 entering_ack_irq();
176
177 inc_irq_stat(irq_hv_reenlightenment_count);
178
179 schedule_delayed_work(&hv_reenlightenment_work, HZ/10);
180
181 exiting_irq();
182 }
183
184 void set_hv_tscchange_cb(void (*cb)(void))
185 {
186 struct hv_reenlightenment_control re_ctrl = {
187 .vector = HYPERV_REENLIGHTENMENT_VECTOR,
188 .enabled = 1,
189 .target_vp = hv_vp_index[smp_processor_id()]
190 };
191 struct hv_tsc_emulation_control emu_ctrl = {.enabled = 1};
192
193 if (!hv_reenlightenment_available()) {
194 pr_warn("Hyper-V: reenlightenment support is unavailable\n");
195 return;
196 }
197
198 hv_reenlightenment_cb = cb;
199
200 /* Make sure callback is registered before we write to MSRs */
201 wmb();
202
203 wrmsrl(HV_X64_MSR_REENLIGHTENMENT_CONTROL, *((u64 *)&re_ctrl));
204 wrmsrl(HV_X64_MSR_TSC_EMULATION_CONTROL, *((u64 *)&emu_ctrl));
205 }
206 EXPORT_SYMBOL_GPL(set_hv_tscchange_cb);
207
208 void clear_hv_tscchange_cb(void)
209 {
210 struct hv_reenlightenment_control re_ctrl;
211
212 if (!hv_reenlightenment_available())
213 return;
214
215 rdmsrl(HV_X64_MSR_REENLIGHTENMENT_CONTROL, *(u64 *)&re_ctrl);
216 re_ctrl.enabled = 0;
217 wrmsrl(HV_X64_MSR_REENLIGHTENMENT_CONTROL, *(u64 *)&re_ctrl);
218
219 hv_reenlightenment_cb = NULL;
220 }
221 EXPORT_SYMBOL_GPL(clear_hv_tscchange_cb);
222
223 static int hv_cpu_die(unsigned int cpu)
224 {
225 struct hv_reenlightenment_control re_ctrl;
226 unsigned int new_cpu;
227 void **input_arg;
228
229 input_arg = (void **)this_cpu_ptr(hyperv_pcpu_input_arg);
230 free_page((unsigned long)*input_arg);
231
232 if (hv_vp_assist_page && hv_vp_assist_page[cpu])
233 wrmsrl(HV_X64_MSR_VP_ASSIST_PAGE, 0);
234
235 if (hv_reenlightenment_cb == NULL)
236 return 0;
237
238 rdmsrl(HV_X64_MSR_REENLIGHTENMENT_CONTROL, *((u64 *)&re_ctrl));
239 if (re_ctrl.target_vp == hv_vp_index[cpu]) {
240 /* Reassign to some other online CPU */
241 new_cpu = cpumask_any_but(cpu_online_mask, cpu);
242
243 re_ctrl.target_vp = hv_vp_index[new_cpu];
244 wrmsrl(HV_X64_MSR_REENLIGHTENMENT_CONTROL, *((u64 *)&re_ctrl));
245 }
246
247 return 0;
248 }
249
250 /*
251 * This function is to be invoked early in the boot sequence after the
252 * hypervisor has been detected.
253 *
254 * 1. Setup the hypercall page.
255 * 2. Register Hyper-V specific clocksource.
256 * 3. Setup Hyper-V specific APIC entry points.
257 */
258 void __init hyperv_init(void)
259 {
260 u64 guest_id, required_msrs;
261 union hv_x64_msr_hypercall_contents hypercall_msr;
262 int cpuhp;
263
264 if (x86_hyper_type != X86_HYPER_MS_HYPERV)
265 return;
266
267 /* Absolutely required MSRs */
268 required_msrs = HV_X64_MSR_HYPERCALL_AVAILABLE |
269 HV_X64_MSR_VP_INDEX_AVAILABLE;
270
271 if ((ms_hyperv.features & required_msrs) != required_msrs)
272 return;
273
274 /* Allocate the per-CPU state for the hypercall input arg */
> 275 hyperv_pcpu_input_arg = alloc_percpu(void *);
276
277 if (hyperv_pcpu_input_arg == NULL)
278 return;
279
280 /* Allocate percpu VP index */
281 hv_vp_index = kmalloc_array(num_possible_cpus(), sizeof(*hv_vp_index),
282 GFP_KERNEL);
283 if (!hv_vp_index)
284 return;
285
286 hv_vp_assist_page = kcalloc(num_possible_cpus(),
287 sizeof(*hv_vp_assist_page), GFP_KERNEL);
288 if (!hv_vp_assist_page) {
289 ms_hyperv.hints &= ~HV_X64_ENLIGHTENED_VMCS_RECOMMENDED;
290 goto free_vp_index;
291 }
292
293 cpuhp = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/hyperv_init:online",
294 hv_cpu_init, hv_cpu_die);
295 if (cpuhp < 0)
296 goto free_vp_assist_page;
297
298 /*
299 * Setup the hypercall page and enable hypercalls.
300 * 1. Register the guest ID
301 * 2. Enable the hypercall and register the hypercall page
302 */
303 guest_id = generate_guest_id(0, LINUX_VERSION_CODE, 0);
304 wrmsrl(HV_X64_MSR_GUEST_OS_ID, guest_id);
305
306 hv_hypercall_pg = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_RX);
307 if (hv_hypercall_pg == NULL) {
308 wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
309 goto remove_cpuhp_state;
310 }
311
312 rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
313 hypercall_msr.enable = 1;
314 hypercall_msr.guest_physical_address = vmalloc_to_pfn(hv_hypercall_pg);
315 wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
316
317 hyper_alloc_mmu();
318
319 hv_apic_init();
320
321 /*
322 * Register Hyper-V specific clocksource.
323 */
324 #ifdef CONFIG_HYPERV_TSCPAGE
325 if (ms_hyperv.features & HV_X64_MSR_REFERENCE_TSC_AVAILABLE) {
326 union hv_x64_msr_hypercall_contents tsc_msr;
327
328 tsc_pg = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL);
329 if (!tsc_pg)
330 goto register_msr_cs;
331
332 hyperv_cs = &hyperv_cs_tsc;
333
334 rdmsrl(HV_X64_MSR_REFERENCE_TSC, tsc_msr.as_uint64);
335
336 tsc_msr.enable = 1;
337 tsc_msr.guest_physical_address = vmalloc_to_pfn(tsc_pg);
338
339 wrmsrl(HV_X64_MSR_REFERENCE_TSC, tsc_msr.as_uint64);
340
341 hyperv_cs_tsc.archdata.vclock_mode = VCLOCK_HVCLOCK;
342
343 clocksource_register_hz(&hyperv_cs_tsc, NSEC_PER_SEC/100);
344 return;
345 }
346 register_msr_cs:
347 #endif
348 /*
349 * For 32 bit guests just use the MSR based mechanism for reading
350 * the partition counter.
351 */
352
353 hyperv_cs = &hyperv_cs_msr;
354 if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE)
355 clocksource_register_hz(&hyperv_cs_msr, NSEC_PER_SEC/100);
356
357 return;
358
359 remove_cpuhp_state:
360 cpuhp_remove_state(cpuhp);
361 free_vp_assist_page:
362 kfree(hv_vp_assist_page);
363 hv_vp_assist_page = NULL;
364 free_vp_index:
365 kfree(hv_vp_index);
366 hv_vp_index = NULL;
367 }
368
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation