Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/x86/hyperv/hv_init.c
49968 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* X86 specific Hyper-V initialization code.
4
*
5
* Copyright (C) 2016, Microsoft, Inc.
6
*
7
* Author : K. Y. Srinivasan <[email protected]>
8
*/
9
10
#define pr_fmt(fmt) "Hyper-V: " fmt
11
12
#include <linux/efi.h>
13
#include <linux/types.h>
14
#include <linux/bitfield.h>
15
#include <linux/io.h>
16
#include <asm/apic.h>
17
#include <asm/desc.h>
18
#include <asm/e820/api.h>
19
#include <asm/sev.h>
20
#include <asm/hypervisor.h>
21
#include <hyperv/hvhdk.h>
22
#include <asm/mshyperv.h>
23
#include <asm/msr.h>
24
#include <asm/idtentry.h>
25
#include <asm/set_memory.h>
26
#include <linux/kexec.h>
27
#include <linux/version.h>
28
#include <linux/vmalloc.h>
29
#include <linux/mm.h>
30
#include <linux/slab.h>
31
#include <linux/kernel.h>
32
#include <linux/cpuhotplug.h>
33
#include <linux/syscore_ops.h>
34
#include <clocksource/hyperv_timer.h>
35
#include <linux/highmem.h>
36
#include <linux/export.h>
37
38
void *hv_hypercall_pg;
39
40
#ifdef CONFIG_X86_64
41
static u64 __hv_hyperfail(u64 control, u64 param1, u64 param2)
42
{
43
return U64_MAX;
44
}
45
46
DEFINE_STATIC_CALL(__hv_hypercall, __hv_hyperfail);
47
48
u64 hv_std_hypercall(u64 control, u64 param1, u64 param2)
49
{
50
u64 hv_status;
51
52
register u64 __r8 asm("r8") = param2;
53
asm volatile ("call " STATIC_CALL_TRAMP_STR(__hv_hypercall)
54
: "=a" (hv_status), ASM_CALL_CONSTRAINT,
55
"+c" (control), "+d" (param1), "+r" (__r8)
56
: : "cc", "memory", "r9", "r10", "r11");
57
58
return hv_status;
59
}
60
61
typedef u64 (*hv_hypercall_f)(u64 control, u64 param1, u64 param2);
62
63
static inline void hv_set_hypercall_pg(void *ptr)
64
{
65
hv_hypercall_pg = ptr;
66
67
if (!ptr)
68
ptr = &__hv_hyperfail;
69
static_call_update(__hv_hypercall, (hv_hypercall_f)ptr);
70
}
71
#else
72
static inline void hv_set_hypercall_pg(void *ptr)
73
{
74
hv_hypercall_pg = ptr;
75
}
76
EXPORT_SYMBOL_GPL(hv_hypercall_pg);
77
#endif
78
79
union hv_ghcb * __percpu *hv_ghcb_pg;
80
81
/* Storage to save the hypercall page temporarily for hibernation */
82
static void *hv_hypercall_pg_saved;
83
84
struct hv_vp_assist_page **hv_vp_assist_page;
85
EXPORT_SYMBOL_GPL(hv_vp_assist_page);
86
87
static int hyperv_init_ghcb(void)
88
{
89
u64 ghcb_gpa;
90
void *ghcb_va;
91
void **ghcb_base;
92
93
if (!ms_hyperv.paravisor_present || !hv_isolation_type_snp())
94
return 0;
95
96
if (!hv_ghcb_pg)
97
return -EINVAL;
98
99
/*
100
* GHCB page is allocated by paravisor. The address
101
* returned by MSR_AMD64_SEV_ES_GHCB is above shared
102
* memory boundary and map it here.
103
*/
104
rdmsrq(MSR_AMD64_SEV_ES_GHCB, ghcb_gpa);
105
106
/* Mask out vTOM bit. ioremap_cache() maps decrypted */
107
ghcb_gpa &= ~ms_hyperv.shared_gpa_boundary;
108
ghcb_va = (void *)ioremap_cache(ghcb_gpa, HV_HYP_PAGE_SIZE);
109
if (!ghcb_va)
110
return -ENOMEM;
111
112
ghcb_base = (void **)this_cpu_ptr(hv_ghcb_pg);
113
*ghcb_base = ghcb_va;
114
115
return 0;
116
}
117
118
static int hv_cpu_init(unsigned int cpu)
119
{
120
union hv_vp_assist_msr_contents msr = { 0 };
121
struct hv_vp_assist_page **hvp;
122
int ret;
123
124
ret = hv_common_cpu_init(cpu);
125
if (ret)
126
return ret;
127
128
if (!hv_vp_assist_page)
129
return 0;
130
131
hvp = &hv_vp_assist_page[cpu];
132
if (hv_root_partition()) {
133
/*
134
* For root partition we get the hypervisor provided VP assist
135
* page, instead of allocating a new page.
136
*/
137
rdmsrq(HV_X64_MSR_VP_ASSIST_PAGE, msr.as_uint64);
138
*hvp = memremap(msr.pfn << HV_X64_MSR_VP_ASSIST_PAGE_ADDRESS_SHIFT,
139
PAGE_SIZE, MEMREMAP_WB);
140
} else {
141
/*
142
* The VP assist page is an "overlay" page (see Hyper-V TLFS's
143
* Section 5.2.1 "GPA Overlay Pages"). Here it must be zeroed
144
* out to make sure we always write the EOI MSR in
145
* hv_apic_eoi_write() *after* the EOI optimization is disabled
146
* in hv_cpu_die(), otherwise a CPU may not be stopped in the
147
* case of CPU offlining and the VM will hang.
148
*/
149
if (!*hvp) {
150
*hvp = __vmalloc(PAGE_SIZE, GFP_KERNEL | __GFP_ZERO);
151
152
/*
153
* Hyper-V should never specify a VM that is a Confidential
154
* VM and also running in the root partition. Root partition
155
* is blocked to run in Confidential VM. So only decrypt assist
156
* page in non-root partition here.
157
*/
158
if (*hvp && !ms_hyperv.paravisor_present && hv_isolation_type_snp()) {
159
WARN_ON_ONCE(set_memory_decrypted((unsigned long)(*hvp), 1));
160
memset(*hvp, 0, PAGE_SIZE);
161
}
162
}
163
164
if (*hvp)
165
msr.pfn = vmalloc_to_pfn(*hvp);
166
167
}
168
if (!WARN_ON(!(*hvp))) {
169
msr.enable = 1;
170
wrmsrq(HV_X64_MSR_VP_ASSIST_PAGE, msr.as_uint64);
171
}
172
173
/* Allow Hyper-V stimer vector to be injected from Hypervisor. */
174
if (ms_hyperv.misc_features & HV_STIMER_DIRECT_MODE_AVAILABLE)
175
apic_update_vector(cpu, HYPERV_STIMER0_VECTOR, true);
176
177
return hyperv_init_ghcb();
178
}
179
180
static void (*hv_reenlightenment_cb)(void);
181
182
static void hv_reenlightenment_notify(struct work_struct *dummy)
183
{
184
struct hv_tsc_emulation_status emu_status;
185
186
rdmsrq(HV_X64_MSR_TSC_EMULATION_STATUS, *(u64 *)&emu_status);
187
188
/* Don't issue the callback if TSC accesses are not emulated */
189
if (hv_reenlightenment_cb && emu_status.inprogress)
190
hv_reenlightenment_cb();
191
}
192
static DECLARE_DELAYED_WORK(hv_reenlightenment_work, hv_reenlightenment_notify);
193
194
void hyperv_stop_tsc_emulation(void)
195
{
196
u64 freq;
197
struct hv_tsc_emulation_status emu_status;
198
199
rdmsrq(HV_X64_MSR_TSC_EMULATION_STATUS, *(u64 *)&emu_status);
200
emu_status.inprogress = 0;
201
wrmsrq(HV_X64_MSR_TSC_EMULATION_STATUS, *(u64 *)&emu_status);
202
203
rdmsrq(HV_X64_MSR_TSC_FREQUENCY, freq);
204
tsc_khz = div64_u64(freq, 1000);
205
}
206
EXPORT_SYMBOL_GPL(hyperv_stop_tsc_emulation);
207
208
static inline bool hv_reenlightenment_available(void)
209
{
210
/*
211
* Check for required features and privileges to make TSC frequency
212
* change notifications work.
213
*/
214
return ms_hyperv.features & HV_ACCESS_FREQUENCY_MSRS &&
215
ms_hyperv.misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE &&
216
ms_hyperv.features & HV_ACCESS_REENLIGHTENMENT;
217
}
218
219
DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_reenlightenment)
220
{
221
apic_eoi();
222
inc_irq_stat(irq_hv_reenlightenment_count);
223
schedule_delayed_work(&hv_reenlightenment_work, HZ/10);
224
}
225
226
void set_hv_tscchange_cb(void (*cb)(void))
227
{
228
struct hv_reenlightenment_control re_ctrl = {
229
.vector = HYPERV_REENLIGHTENMENT_VECTOR,
230
.enabled = 1,
231
};
232
struct hv_tsc_emulation_control emu_ctrl = {.enabled = 1};
233
234
if (!hv_reenlightenment_available()) {
235
pr_warn("reenlightenment support is unavailable\n");
236
return;
237
}
238
239
if (!hv_vp_index)
240
return;
241
242
hv_reenlightenment_cb = cb;
243
244
/* Make sure callback is registered before we write to MSRs */
245
wmb();
246
247
re_ctrl.target_vp = hv_vp_index[get_cpu()];
248
249
wrmsrq(HV_X64_MSR_REENLIGHTENMENT_CONTROL, *((u64 *)&re_ctrl));
250
wrmsrq(HV_X64_MSR_TSC_EMULATION_CONTROL, *((u64 *)&emu_ctrl));
251
252
put_cpu();
253
}
254
EXPORT_SYMBOL_GPL(set_hv_tscchange_cb);
255
256
void clear_hv_tscchange_cb(void)
257
{
258
struct hv_reenlightenment_control re_ctrl;
259
260
if (!hv_reenlightenment_available())
261
return;
262
263
rdmsrq(HV_X64_MSR_REENLIGHTENMENT_CONTROL, *(u64 *)&re_ctrl);
264
re_ctrl.enabled = 0;
265
wrmsrq(HV_X64_MSR_REENLIGHTENMENT_CONTROL, *(u64 *)&re_ctrl);
266
267
hv_reenlightenment_cb = NULL;
268
}
269
EXPORT_SYMBOL_GPL(clear_hv_tscchange_cb);
270
271
static int hv_cpu_die(unsigned int cpu)
272
{
273
struct hv_reenlightenment_control re_ctrl;
274
unsigned int new_cpu;
275
void **ghcb_va;
276
277
if (hv_ghcb_pg) {
278
ghcb_va = (void **)this_cpu_ptr(hv_ghcb_pg);
279
if (*ghcb_va)
280
iounmap(*ghcb_va);
281
*ghcb_va = NULL;
282
}
283
284
if (ms_hyperv.misc_features & HV_STIMER_DIRECT_MODE_AVAILABLE)
285
apic_update_vector(cpu, HYPERV_STIMER0_VECTOR, false);
286
287
hv_common_cpu_die(cpu);
288
289
if (hv_vp_assist_page && hv_vp_assist_page[cpu]) {
290
union hv_vp_assist_msr_contents msr = { 0 };
291
if (hv_root_partition()) {
292
/*
293
* For root partition the VP assist page is mapped to
294
* hypervisor provided page, and thus we unmap the
295
* page here and nullify it, so that in future we have
296
* correct page address mapped in hv_cpu_init.
297
*/
298
memunmap(hv_vp_assist_page[cpu]);
299
hv_vp_assist_page[cpu] = NULL;
300
rdmsrq(HV_X64_MSR_VP_ASSIST_PAGE, msr.as_uint64);
301
msr.enable = 0;
302
}
303
wrmsrq(HV_X64_MSR_VP_ASSIST_PAGE, msr.as_uint64);
304
}
305
306
if (hv_reenlightenment_cb == NULL)
307
return 0;
308
309
rdmsrq(HV_X64_MSR_REENLIGHTENMENT_CONTROL, *((u64 *)&re_ctrl));
310
if (re_ctrl.target_vp == hv_vp_index[cpu]) {
311
/*
312
* Reassign reenlightenment notifications to some other online
313
* CPU or just disable the feature if there are no online CPUs
314
* left (happens on hibernation).
315
*/
316
new_cpu = cpumask_any_but(cpu_online_mask, cpu);
317
318
if (new_cpu < nr_cpu_ids)
319
re_ctrl.target_vp = hv_vp_index[new_cpu];
320
else
321
re_ctrl.enabled = 0;
322
323
wrmsrq(HV_X64_MSR_REENLIGHTENMENT_CONTROL, *((u64 *)&re_ctrl));
324
}
325
326
return 0;
327
}
328
329
static int __init hv_pci_init(void)
330
{
331
bool gen2vm = efi_enabled(EFI_BOOT);
332
333
/*
334
* A Generation-2 VM doesn't support legacy PCI/PCIe, so both
335
* raw_pci_ops and raw_pci_ext_ops are NULL, and pci_subsys_init() ->
336
* pcibios_init() doesn't call pcibios_resource_survey() ->
337
* e820__reserve_resources_late(); as a result, any emulated persistent
338
* memory of E820_TYPE_PRAM (12) via the kernel parameter
339
* memmap=nn[KMG]!ss is not added into iomem_resource and hence can't be
340
* detected by register_e820_pmem(). Fix this by directly calling
341
* e820__reserve_resources_late() here: e820__reserve_resources_late()
342
* depends on e820__reserve_resources(), which has been called earlier
343
* from setup_arch(). Note: e820__reserve_resources_late() also adds
344
* any memory of E820_TYPE_PMEM (7) into iomem_resource, and
345
* acpi_nfit_register_region() -> acpi_nfit_insert_resource() ->
346
* region_intersects() returns REGION_INTERSECTS, so the memory of
347
* E820_TYPE_PMEM won't get added twice.
348
*
349
* We return 0 here so that pci_arch_init() won't print the warning:
350
* "PCI: Fatal: No config space access function found"
351
*/
352
if (gen2vm) {
353
e820__reserve_resources_late();
354
return 0;
355
}
356
357
/* For Generation-1 VM, we'll proceed in pci_arch_init(). */
358
return 1;
359
}
360
361
static int hv_suspend(void *data)
362
{
363
union hv_x64_msr_hypercall_contents hypercall_msr;
364
int ret;
365
366
if (hv_root_partition())
367
return -EPERM;
368
369
/*
370
* Reset the hypercall page as it is going to be invalidated
371
* across hibernation. Setting hv_hypercall_pg to NULL ensures
372
* that any subsequent hypercall operation fails safely instead of
373
* crashing due to an access of an invalid page. The hypercall page
374
* pointer is restored on resume.
375
*/
376
hv_hypercall_pg_saved = hv_hypercall_pg;
377
hv_set_hypercall_pg(NULL);
378
379
/* Disable the hypercall page in the hypervisor */
380
rdmsrq(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
381
hypercall_msr.enable = 0;
382
wrmsrq(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
383
384
ret = hv_cpu_die(0);
385
return ret;
386
}
387
388
static void hv_resume(void *data)
389
{
390
union hv_x64_msr_hypercall_contents hypercall_msr;
391
int ret;
392
393
ret = hv_cpu_init(0);
394
WARN_ON(ret);
395
396
/* Re-enable the hypercall page */
397
rdmsrq(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
398
hypercall_msr.enable = 1;
399
hypercall_msr.guest_physical_address =
400
vmalloc_to_pfn(hv_hypercall_pg_saved);
401
wrmsrq(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
402
403
hv_set_hypercall_pg(hv_hypercall_pg_saved);
404
hv_hypercall_pg_saved = NULL;
405
406
/*
407
* Reenlightenment notifications are disabled by hv_cpu_die(0),
408
* reenable them here if hv_reenlightenment_cb was previously set.
409
*/
410
if (hv_reenlightenment_cb)
411
set_hv_tscchange_cb(hv_reenlightenment_cb);
412
}
413
414
/* Note: when the ops are called, only CPU0 is online and IRQs are disabled. */
415
static const struct syscore_ops hv_syscore_ops = {
416
.suspend = hv_suspend,
417
.resume = hv_resume,
418
};
419
420
static struct syscore hv_syscore = {
421
.ops = &hv_syscore_ops,
422
};
423
424
static void (* __initdata old_setup_percpu_clockev)(void);
425
426
static void __init hv_stimer_setup_percpu_clockev(void)
427
{
428
/*
429
* Ignore any errors in setting up stimer clockevents
430
* as we can run with the LAPIC timer as a fallback.
431
*/
432
(void)hv_stimer_alloc(false);
433
434
/*
435
* Still register the LAPIC timer, because the direct-mode STIMER is
436
* not supported by old versions of Hyper-V. This also allows users
437
* to switch to LAPIC timer via /sys, if they want to.
438
*/
439
if (old_setup_percpu_clockev)
440
old_setup_percpu_clockev();
441
}
442
443
/*
444
* This function is to be invoked early in the boot sequence after the
445
* hypervisor has been detected.
446
*
447
* 1. Setup the hypercall page.
448
* 2. Register Hyper-V specific clocksource.
449
* 3. Setup Hyper-V specific APIC entry points.
450
*/
451
void __init hyperv_init(void)
452
{
453
u64 guest_id;
454
union hv_x64_msr_hypercall_contents hypercall_msr;
455
int cpuhp;
456
457
if (x86_hyper_type != X86_HYPER_MS_HYPERV)
458
return;
459
460
if (hv_common_init())
461
return;
462
463
/*
464
* The VP assist page is useless to a TDX guest: the only use we
465
* would have for it is lazy EOI, which can not be used with TDX.
466
*/
467
if (hv_isolation_type_tdx())
468
hv_vp_assist_page = NULL;
469
else
470
hv_vp_assist_page = kcalloc(nr_cpu_ids,
471
sizeof(*hv_vp_assist_page),
472
GFP_KERNEL);
473
if (!hv_vp_assist_page) {
474
ms_hyperv.hints &= ~HV_X64_ENLIGHTENED_VMCS_RECOMMENDED;
475
476
if (!hv_isolation_type_tdx())
477
goto common_free;
478
}
479
480
if (ms_hyperv.paravisor_present && hv_isolation_type_snp()) {
481
/* Negotiate GHCB Version. */
482
if (!hv_ghcb_negotiate_protocol())
483
hv_ghcb_terminate(SEV_TERM_SET_GEN,
484
GHCB_SEV_ES_PROT_UNSUPPORTED);
485
486
hv_ghcb_pg = alloc_percpu(union hv_ghcb *);
487
if (!hv_ghcb_pg)
488
goto free_vp_assist_page;
489
}
490
491
cpuhp = cpuhp_setup_state(CPUHP_AP_HYPERV_ONLINE, "x86/hyperv_init:online",
492
hv_cpu_init, hv_cpu_die);
493
if (cpuhp < 0)
494
goto free_ghcb_page;
495
496
/*
497
* Setup the hypercall page and enable hypercalls.
498
* 1. Register the guest ID
499
* 2. Enable the hypercall and register the hypercall page
500
*
501
* A TDX VM with no paravisor only uses TDX GHCI rather than hv_hypercall_pg:
502
* when the hypercall input is a page, such a VM must pass a decrypted
503
* page to Hyper-V, e.g. hv_post_message() uses the per-CPU page
504
* hyperv_pcpu_input_arg, which is decrypted if no paravisor is present.
505
*
506
* A TDX VM with the paravisor uses hv_hypercall_pg for most hypercalls,
507
* which are handled by the paravisor and the VM must use an encrypted
508
* input page: in such a VM, the hyperv_pcpu_input_arg is encrypted and
509
* used in the hypercalls, e.g. see hv_mark_gpa_visibility() and
510
* hv_arch_irq_unmask(). Such a VM uses TDX GHCI for two hypercalls:
511
* 1. HVCALL_SIGNAL_EVENT: see vmbus_set_event() and _hv_do_fast_hypercall8().
512
* 2. HVCALL_POST_MESSAGE: the input page must be a decrypted page, i.e.
513
* hv_post_message() in such a VM can't use the encrypted hyperv_pcpu_input_arg;
514
* instead, hv_post_message() uses the post_msg_page, which is decrypted
515
* in such a VM and is only used in such a VM.
516
*/
517
guest_id = hv_generate_guest_id(LINUX_VERSION_CODE);
518
wrmsrq(HV_X64_MSR_GUEST_OS_ID, guest_id);
519
520
/* With the paravisor, the VM must also write the ID via GHCB/GHCI */
521
hv_ivm_msr_write(HV_X64_MSR_GUEST_OS_ID, guest_id);
522
523
/* A TDX VM with no paravisor only uses TDX GHCI rather than hv_hypercall_pg */
524
if (hv_isolation_type_tdx() && !ms_hyperv.paravisor_present)
525
goto skip_hypercall_pg_init;
526
527
hv_hypercall_pg = __vmalloc_node_range(PAGE_SIZE, 1, MODULES_VADDR,
528
MODULES_END, GFP_KERNEL, PAGE_KERNEL_ROX,
529
VM_FLUSH_RESET_PERMS, NUMA_NO_NODE,
530
__builtin_return_address(0));
531
if (hv_hypercall_pg == NULL)
532
goto clean_guest_os_id;
533
534
rdmsrq(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
535
hypercall_msr.enable = 1;
536
537
if (hv_root_partition()) {
538
struct page *pg;
539
void *src;
540
541
/*
542
* For the root partition, the hypervisor will set up its
543
* hypercall page. The hypervisor guarantees it will not show
544
* up in the root's address space. The root can't change the
545
* location of the hypercall page.
546
*
547
* Order is important here. We must enable the hypercall page
548
* so it is populated with code, then copy the code to an
549
* executable page.
550
*/
551
wrmsrq(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
552
553
pg = vmalloc_to_page(hv_hypercall_pg);
554
src = memremap(hypercall_msr.guest_physical_address << PAGE_SHIFT, PAGE_SIZE,
555
MEMREMAP_WB);
556
BUG_ON(!src);
557
memcpy_to_page(pg, 0, src, HV_HYP_PAGE_SIZE);
558
memunmap(src);
559
560
hv_remap_tsc_clocksource();
561
hv_root_crash_init();
562
hv_sleep_notifiers_register();
563
} else {
564
hypercall_msr.guest_physical_address = vmalloc_to_pfn(hv_hypercall_pg);
565
wrmsrq(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
566
}
567
568
hv_set_hypercall_pg(hv_hypercall_pg);
569
570
skip_hypercall_pg_init:
571
/*
572
* hyperv_init() is called before LAPIC is initialized: see
573
* apic_intr_mode_init() -> x86_platform.apic_post_init() and
574
* apic_bsp_setup() -> setup_local_APIC(). The direct-mode STIMER
575
* depends on LAPIC, so hv_stimer_alloc() should be called from
576
* x86_init.timers.setup_percpu_clockev.
577
*/
578
old_setup_percpu_clockev = x86_init.timers.setup_percpu_clockev;
579
x86_init.timers.setup_percpu_clockev = hv_stimer_setup_percpu_clockev;
580
581
hv_apic_init();
582
583
x86_init.pci.arch_init = hv_pci_init;
584
585
register_syscore(&hv_syscore);
586
587
if (ms_hyperv.priv_high & HV_ACCESS_PARTITION_ID)
588
hv_get_partition_id();
589
590
#ifdef CONFIG_PCI_MSI
591
/*
592
* If we're running as root, we want to create our own PCI MSI domain.
593
* We can't set this in hv_pci_init because that would be too late.
594
*/
595
if (hv_root_partition())
596
x86_init.irqs.create_pci_msi_domain = hv_create_pci_msi_domain;
597
#endif
598
599
/* Query the VMs extended capability once, so that it can be cached. */
600
hv_query_ext_cap(0);
601
602
/* Find the VTL */
603
ms_hyperv.vtl = get_vtl();
604
605
if (ms_hyperv.vtl > 0) /* non default VTL */
606
hv_vtl_early_init();
607
608
return;
609
610
clean_guest_os_id:
611
wrmsrq(HV_X64_MSR_GUEST_OS_ID, 0);
612
hv_ivm_msr_write(HV_X64_MSR_GUEST_OS_ID, 0);
613
cpuhp_remove_state(CPUHP_AP_HYPERV_ONLINE);
614
free_ghcb_page:
615
free_percpu(hv_ghcb_pg);
616
free_vp_assist_page:
617
kfree(hv_vp_assist_page);
618
hv_vp_assist_page = NULL;
619
common_free:
620
hv_common_free();
621
}
622
623
/*
624
* This routine is called before kexec/kdump, it does the required cleanup.
625
*/
626
void hyperv_cleanup(void)
627
{
628
union hv_x64_msr_hypercall_contents hypercall_msr;
629
union hv_reference_tsc_msr tsc_msr;
630
631
/* Reset our OS id */
632
wrmsrq(HV_X64_MSR_GUEST_OS_ID, 0);
633
hv_ivm_msr_write(HV_X64_MSR_GUEST_OS_ID, 0);
634
635
/*
636
* Reset hypercall page reference before reset the page,
637
* let hypercall operations fail safely rather than
638
* panic the kernel for using invalid hypercall page
639
*/
640
hv_hypercall_pg = NULL;
641
642
/* Reset the hypercall page */
643
hypercall_msr.as_uint64 = hv_get_msr(HV_X64_MSR_HYPERCALL);
644
hypercall_msr.enable = 0;
645
hv_set_msr(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
646
647
/* Reset the TSC page */
648
tsc_msr.as_uint64 = hv_get_msr(HV_X64_MSR_REFERENCE_TSC);
649
tsc_msr.enable = 0;
650
hv_set_msr(HV_X64_MSR_REFERENCE_TSC, tsc_msr.as_uint64);
651
}
652
653
void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die)
654
{
655
static bool panic_reported;
656
u64 guest_id;
657
658
if (in_die && !panic_on_oops)
659
return;
660
661
/*
662
* We prefer to report panic on 'die' chain as we have proper
663
* registers to report, but if we miss it (e.g. on BUG()) we need
664
* to report it on 'panic'.
665
*/
666
if (panic_reported)
667
return;
668
panic_reported = true;
669
670
rdmsrq(HV_X64_MSR_GUEST_OS_ID, guest_id);
671
672
wrmsrq(HV_X64_MSR_CRASH_P0, err);
673
wrmsrq(HV_X64_MSR_CRASH_P1, guest_id);
674
wrmsrq(HV_X64_MSR_CRASH_P2, regs->ip);
675
wrmsrq(HV_X64_MSR_CRASH_P3, regs->ax);
676
wrmsrq(HV_X64_MSR_CRASH_P4, regs->sp);
677
678
/*
679
* Let Hyper-V know there is crash data available
680
*/
681
wrmsrq(HV_X64_MSR_CRASH_CTL, HV_CRASH_CTL_CRASH_NOTIFY);
682
}
683
EXPORT_SYMBOL_GPL(hyperv_report_panic);
684
685
bool hv_is_hyperv_initialized(void)
686
{
687
union hv_x64_msr_hypercall_contents hypercall_msr;
688
689
/*
690
* Ensure that we're really on Hyper-V, and not a KVM or Xen
691
* emulation of Hyper-V
692
*/
693
if (x86_hyper_type != X86_HYPER_MS_HYPERV)
694
return false;
695
696
/* A TDX VM with no paravisor uses TDX GHCI call rather than hv_hypercall_pg */
697
if (hv_isolation_type_tdx() && !ms_hyperv.paravisor_present)
698
return true;
699
/*
700
* Verify that earlier initialization succeeded by checking
701
* that the hypercall page is setup
702
*/
703
hypercall_msr.as_uint64 = 0;
704
rdmsrq(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
705
706
return hypercall_msr.enable;
707
}
708
EXPORT_SYMBOL_GPL(hv_is_hyperv_initialized);
709
710
int hv_apicid_to_vp_index(u32 apic_id)
711
{
712
u64 control;
713
u64 status;
714
unsigned long irq_flags;
715
struct hv_get_vp_from_apic_id_in *input;
716
u32 *output, ret;
717
718
local_irq_save(irq_flags);
719
720
input = *this_cpu_ptr(hyperv_pcpu_input_arg);
721
memset(input, 0, sizeof(*input));
722
input->partition_id = HV_PARTITION_ID_SELF;
723
input->apic_ids[0] = apic_id;
724
725
output = *this_cpu_ptr(hyperv_pcpu_output_arg);
726
727
control = HV_HYPERCALL_REP_COMP_1 | HVCALL_GET_VP_INDEX_FROM_APIC_ID;
728
status = hv_do_hypercall(control, input, output);
729
ret = output[0];
730
731
local_irq_restore(irq_flags);
732
733
if (!hv_result_success(status)) {
734
pr_err("failed to get vp index from apic id %d, status %#llx\n",
735
apic_id, status);
736
return -EINVAL;
737
}
738
739
return ret;
740
}
741
EXPORT_SYMBOL_GPL(hv_apicid_to_vp_index);
742
743