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