Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only
2 : : /*
3 : : * HyperV Detection code.
4 : : *
5 : : * Copyright (C) 2010, Novell, Inc.
6 : : * Author : K. Y. Srinivasan <ksrinivasan@novell.com>
7 : : */
8 : :
9 : : #include <linux/types.h>
10 : : #include <linux/time.h>
11 : : #include <linux/clocksource.h>
12 : : #include <linux/init.h>
13 : : #include <linux/export.h>
14 : : #include <linux/hardirq.h>
15 : : #include <linux/efi.h>
16 : : #include <linux/interrupt.h>
17 : : #include <linux/irq.h>
18 : : #include <linux/kexec.h>
19 : : #include <linux/i8253.h>
20 : : #include <linux/random.h>
21 : : #include <asm/processor.h>
22 : : #include <asm/hypervisor.h>
23 : : #include <asm/hyperv-tlfs.h>
24 : : #include <asm/mshyperv.h>
25 : : #include <asm/desc.h>
26 : : #include <asm/irq_regs.h>
27 : : #include <asm/i8259.h>
28 : : #include <asm/apic.h>
29 : : #include <asm/timer.h>
30 : : #include <asm/reboot.h>
31 : : #include <asm/nmi.h>
32 : : #include <clocksource/hyperv_timer.h>
33 : :
34 : : struct ms_hyperv_info ms_hyperv;
35 : : EXPORT_SYMBOL_GPL(ms_hyperv);
36 : :
37 : : #if IS_ENABLED(CONFIG_HYPERV)
38 : : static void (*vmbus_handler)(void);
39 : : static void (*hv_stimer0_handler)(void);
40 : : static void (*hv_kexec_handler)(void);
41 : : static void (*hv_crash_handler)(struct pt_regs *regs);
42 : :
43 : : __visible void __irq_entry hyperv_vector_handler(struct pt_regs *regs)
44 : : {
45 : : struct pt_regs *old_regs = set_irq_regs(regs);
46 : :
47 : : entering_irq();
48 : : inc_irq_stat(irq_hv_callback_count);
49 : : if (vmbus_handler)
50 : : vmbus_handler();
51 : :
52 : : if (ms_hyperv.hints & HV_DEPRECATING_AEOI_RECOMMENDED)
53 : : ack_APIC_irq();
54 : :
55 : : exiting_irq();
56 : : set_irq_regs(old_regs);
57 : : }
58 : :
59 : : void hv_setup_vmbus_irq(void (*handler)(void))
60 : : {
61 : : vmbus_handler = handler;
62 : : }
63 : :
64 : : void hv_remove_vmbus_irq(void)
65 : : {
66 : : /* We have no way to deallocate the interrupt gate */
67 : : vmbus_handler = NULL;
68 : : }
69 : : EXPORT_SYMBOL_GPL(hv_setup_vmbus_irq);
70 : : EXPORT_SYMBOL_GPL(hv_remove_vmbus_irq);
71 : :
72 : : /*
73 : : * Routines to do per-architecture handling of stimer0
74 : : * interrupts when in Direct Mode
75 : : */
76 : :
77 : : __visible void __irq_entry hv_stimer0_vector_handler(struct pt_regs *regs)
78 : : {
79 : : struct pt_regs *old_regs = set_irq_regs(regs);
80 : :
81 : : entering_irq();
82 : : inc_irq_stat(hyperv_stimer0_count);
83 : : if (hv_stimer0_handler)
84 : : hv_stimer0_handler();
85 : : add_interrupt_randomness(HYPERV_STIMER0_VECTOR, 0);
86 : : ack_APIC_irq();
87 : :
88 : : exiting_irq();
89 : : set_irq_regs(old_regs);
90 : : }
91 : :
92 : : int hv_setup_stimer0_irq(int *irq, int *vector, void (*handler)(void))
93 : : {
94 : : *vector = HYPERV_STIMER0_VECTOR;
95 : : *irq = -1; /* Unused on x86/x64 */
96 : : hv_stimer0_handler = handler;
97 : : return 0;
98 : : }
99 : : EXPORT_SYMBOL_GPL(hv_setup_stimer0_irq);
100 : :
101 : : void hv_remove_stimer0_irq(int irq)
102 : : {
103 : : /* We have no way to deallocate the interrupt gate */
104 : : hv_stimer0_handler = NULL;
105 : : }
106 : : EXPORT_SYMBOL_GPL(hv_remove_stimer0_irq);
107 : :
108 : : void hv_setup_kexec_handler(void (*handler)(void))
109 : : {
110 : : hv_kexec_handler = handler;
111 : : }
112 : : EXPORT_SYMBOL_GPL(hv_setup_kexec_handler);
113 : :
114 : : void hv_remove_kexec_handler(void)
115 : : {
116 : : hv_kexec_handler = NULL;
117 : : }
118 : : EXPORT_SYMBOL_GPL(hv_remove_kexec_handler);
119 : :
120 : : void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs))
121 : : {
122 : : hv_crash_handler = handler;
123 : : }
124 : : EXPORT_SYMBOL_GPL(hv_setup_crash_handler);
125 : :
126 : : void hv_remove_crash_handler(void)
127 : : {
128 : : hv_crash_handler = NULL;
129 : : }
130 : : EXPORT_SYMBOL_GPL(hv_remove_crash_handler);
131 : :
132 : : #ifdef CONFIG_KEXEC_CORE
133 : : static void hv_machine_shutdown(void)
134 : : {
135 : : if (kexec_in_progress && hv_kexec_handler)
136 : : hv_kexec_handler();
137 : : native_machine_shutdown();
138 : : }
139 : :
140 : : static void hv_machine_crash_shutdown(struct pt_regs *regs)
141 : : {
142 : : if (hv_crash_handler)
143 : : hv_crash_handler(regs);
144 : : native_machine_crash_shutdown(regs);
145 : : }
146 : : #endif /* CONFIG_KEXEC_CORE */
147 : : #endif /* CONFIG_HYPERV */
148 : :
149 : 30 : static uint32_t __init ms_hyperv_platform(void)
150 : : {
151 : 30 : u32 eax;
152 : 30 : u32 hyp_signature[3];
153 : :
154 [ + - ]: 30 : if (!boot_cpu_has(X86_FEATURE_HYPERVISOR))
155 : : return 0;
156 : :
157 : 30 : cpuid(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS,
158 : : &eax, &hyp_signature[0], &hyp_signature[1], &hyp_signature[2]);
159 : :
160 [ - + ]: 30 : if (eax >= HYPERV_CPUID_MIN &&
161 : 0 : eax <= HYPERV_CPUID_MAX &&
162 [ # # ]: 0 : !memcmp("Microsoft Hv", hyp_signature, 12))
163 : 0 : return HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS;
164 : :
165 : : return 0;
166 : : }
167 : :
168 : 0 : static unsigned char hv_get_nmi_reason(void)
169 : : {
170 : 0 : return 0;
171 : : }
172 : :
173 : : #ifdef CONFIG_X86_LOCAL_APIC
174 : : /*
175 : : * Prior to WS2016 Debug-VM sends NMIs to all CPUs which makes
176 : : * it dificult to process CHANNELMSG_UNLOAD in case of crash. Handle
177 : : * unknown NMI on the first CPU which gets it.
178 : : */
179 : 0 : static int hv_nmi_unknown(unsigned int val, struct pt_regs *regs)
180 : : {
181 : 0 : static atomic_t nmi_cpu = ATOMIC_INIT(-1);
182 : :
183 [ # # ]: 0 : if (!unknown_nmi_panic)
184 : : return NMI_DONE;
185 : :
186 [ # # ]: 0 : if (atomic_cmpxchg(&nmi_cpu, -1, raw_smp_processor_id()) != -1)
187 : 0 : return NMI_HANDLED;
188 : :
189 : : return NMI_DONE;
190 : : }
191 : : #endif
192 : :
193 : 0 : static unsigned long hv_get_tsc_khz(void)
194 : : {
195 : 0 : unsigned long freq;
196 : :
197 : 0 : rdmsrl(HV_X64_MSR_TSC_FREQUENCY, freq);
198 : :
199 : 0 : return freq / 1000;
200 : : }
201 : :
202 : : #if defined(CONFIG_SMP) && IS_ENABLED(CONFIG_HYPERV)
203 : : static void __init hv_smp_prepare_boot_cpu(void)
204 : : {
205 : : native_smp_prepare_boot_cpu();
206 : : #if defined(CONFIG_X86_64) && defined(CONFIG_PARAVIRT_SPINLOCKS)
207 : : hv_init_spinlocks();
208 : : #endif
209 : : }
210 : : #endif
211 : :
212 : 0 : static void __init ms_hyperv_init_platform(void)
213 : : {
214 : 0 : int hv_host_info_eax;
215 : 0 : int hv_host_info_ebx;
216 : 0 : int hv_host_info_ecx;
217 : 0 : int hv_host_info_edx;
218 : :
219 : : #ifdef CONFIG_PARAVIRT
220 : 0 : pv_info.name = "Hyper-V";
221 : : #endif
222 : :
223 : : /*
224 : : * Extract the features and hints
225 : : */
226 : 0 : ms_hyperv.features = cpuid_eax(HYPERV_CPUID_FEATURES);
227 : 0 : ms_hyperv.misc_features = cpuid_edx(HYPERV_CPUID_FEATURES);
228 : 0 : ms_hyperv.hints = cpuid_eax(HYPERV_CPUID_ENLIGHTMENT_INFO);
229 : :
230 : 0 : pr_info("Hyper-V: features 0x%x, hints 0x%x\n",
231 : : ms_hyperv.features, ms_hyperv.hints);
232 : :
233 : 0 : ms_hyperv.max_vp_index = cpuid_eax(HYPERV_CPUID_IMPLEMENT_LIMITS);
234 : 0 : ms_hyperv.max_lp_index = cpuid_ebx(HYPERV_CPUID_IMPLEMENT_LIMITS);
235 : :
236 : 0 : pr_debug("Hyper-V: max %u virtual processors, %u logical processors\n",
237 : : ms_hyperv.max_vp_index, ms_hyperv.max_lp_index);
238 : :
239 : : /*
240 : : * Extract host information.
241 : : */
242 [ # # ]: 0 : if (cpuid_eax(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS) >=
243 : : HYPERV_CPUID_VERSION) {
244 : 0 : hv_host_info_eax = cpuid_eax(HYPERV_CPUID_VERSION);
245 : 0 : hv_host_info_ebx = cpuid_ebx(HYPERV_CPUID_VERSION);
246 : 0 : hv_host_info_ecx = cpuid_ecx(HYPERV_CPUID_VERSION);
247 : 0 : hv_host_info_edx = cpuid_edx(HYPERV_CPUID_VERSION);
248 : :
249 : 0 : pr_info("Hyper-V Host Build:%d-%d.%d-%d-%d.%d\n",
250 : : hv_host_info_eax, hv_host_info_ebx >> 16,
251 : : hv_host_info_ebx & 0xFFFF, hv_host_info_ecx,
252 : : hv_host_info_edx >> 24, hv_host_info_edx & 0xFFFFFF);
253 : : }
254 : :
255 [ # # ]: 0 : if (ms_hyperv.features & HV_X64_ACCESS_FREQUENCY_MSRS &&
256 [ # # ]: 0 : ms_hyperv.misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE) {
257 : 0 : x86_platform.calibrate_tsc = hv_get_tsc_khz;
258 : 0 : x86_platform.calibrate_cpu = hv_get_tsc_khz;
259 : : }
260 : :
261 [ # # ]: 0 : if (ms_hyperv.hints & HV_X64_ENLIGHTENED_VMCS_RECOMMENDED) {
262 : 0 : ms_hyperv.nested_features =
263 : : cpuid_eax(HYPERV_CPUID_NESTED_FEATURES);
264 : : }
265 : :
266 : : #ifdef CONFIG_X86_LOCAL_APIC
267 [ # # ]: 0 : if (ms_hyperv.features & HV_X64_ACCESS_FREQUENCY_MSRS &&
268 [ # # ]: 0 : ms_hyperv.misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE) {
269 : : /*
270 : : * Get the APIC frequency.
271 : : */
272 : 0 : u64 hv_lapic_frequency;
273 : :
274 : 0 : rdmsrl(HV_X64_MSR_APIC_FREQUENCY, hv_lapic_frequency);
275 : 0 : hv_lapic_frequency = div_u64(hv_lapic_frequency, HZ);
276 : 0 : lapic_timer_period = hv_lapic_frequency;
277 : 0 : pr_info("Hyper-V: LAPIC Timer Frequency: %#x\n",
278 : : lapic_timer_period);
279 : : }
280 : :
281 : 0 : register_nmi_handler(NMI_UNKNOWN, hv_nmi_unknown, NMI_FLAG_FIRST,
282 : : "hv_nmi_unknown");
283 : : #endif
284 : :
285 : : #ifdef CONFIG_X86_IO_APIC
286 : 0 : no_timer_check = 1;
287 : : #endif
288 : :
289 : : #if IS_ENABLED(CONFIG_HYPERV) && defined(CONFIG_KEXEC_CORE)
290 : : machine_ops.shutdown = hv_machine_shutdown;
291 : : machine_ops.crash_shutdown = hv_machine_crash_shutdown;
292 : : #endif
293 [ # # ]: 0 : if (ms_hyperv.features & HV_X64_ACCESS_TSC_INVARIANT) {
294 : 0 : wrmsrl(HV_X64_MSR_TSC_INVARIANT_CONTROL, 0x1);
295 : 0 : setup_force_cpu_cap(X86_FEATURE_TSC_RELIABLE);
296 : : } else {
297 : 0 : mark_tsc_unstable("running on Hyper-V");
298 : : }
299 : :
300 : : /*
301 : : * Generation 2 instances don't support reading the NMI status from
302 : : * 0x61 port.
303 : : */
304 [ # # ]: 0 : if (efi_enabled(EFI_BOOT))
305 : 0 : x86_platform.get_nmi_reason = hv_get_nmi_reason;
306 : :
307 : : /*
308 : : * Hyper-V VMs have a PIT emulation quirk such that zeroing the
309 : : * counter register during PIT shutdown restarts the PIT. So it
310 : : * continues to interrupt @18.2 HZ. Setting i8253_clear_counter
311 : : * to false tells pit_shutdown() not to zero the counter so that
312 : : * the PIT really is shutdown. Generation 2 VMs don't have a PIT,
313 : : * and setting this value has no effect.
314 : : */
315 : 0 : i8253_clear_counter_on_shutdown = false;
316 : :
317 : : #if IS_ENABLED(CONFIG_HYPERV)
318 : : /*
319 : : * Setup the hook to get control post apic initialization.
320 : : */
321 : : x86_platform.apic_post_init = hyperv_init;
322 : : hyperv_setup_mmu_ops();
323 : : /* Setup the IDT for hypervisor callback */
324 : : alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, hyperv_callback_vector);
325 : :
326 : : /* Setup the IDT for reenlightenment notifications */
327 : : if (ms_hyperv.features & HV_X64_ACCESS_REENLIGHTENMENT)
328 : : alloc_intr_gate(HYPERV_REENLIGHTENMENT_VECTOR,
329 : : hyperv_reenlightenment_vector);
330 : :
331 : : /* Setup the IDT for stimer0 */
332 : : if (ms_hyperv.misc_features & HV_STIMER_DIRECT_MODE_AVAILABLE)
333 : : alloc_intr_gate(HYPERV_STIMER0_VECTOR,
334 : : hv_stimer0_callback_vector);
335 : :
336 : : # ifdef CONFIG_SMP
337 : : smp_ops.smp_prepare_boot_cpu = hv_smp_prepare_boot_cpu;
338 : : # endif
339 : :
340 : : /*
341 : : * Hyper-V doesn't provide irq remapping for IO-APIC. To enable x2apic,
342 : : * set x2apic destination mode to physcial mode when x2apic is available
343 : : * and Hyper-V IOMMU driver makes sure cpus assigned with IO-APIC irqs
344 : : * have 8-bit APIC id.
345 : : */
346 : : # ifdef CONFIG_X86_X2APIC
347 : : if (x2apic_supported())
348 : : x2apic_phys = 1;
349 : : # endif
350 : :
351 : : /* Register Hyper-V specific clocksource */
352 : : hv_init_clocksource();
353 : : #endif
354 : 0 : }
355 : :
356 : 0 : void hv_setup_sched_clock(void *sched_clock)
357 : : {
358 : : #ifdef CONFIG_PARAVIRT
359 : 0 : pv_ops.time.sched_clock = sched_clock;
360 : : #endif
361 : 0 : }
362 : :
363 : : const __initconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
364 : : .name = "Microsoft Hyper-V",
365 : : .detect = ms_hyperv_platform,
366 : : .type = X86_HYPER_MS_HYPERV,
367 : : .init.init_platform = ms_hyperv_init_platform,
368 : : };
|