1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * X86 specific Hyper-V root partition kdump/crash support module 4 * 5 * Copyright (C) 2025, Microsoft, Inc. 6 * 7 * This module implements hypervisor RAM collection into vmcore for both 8 * cases of the hypervisor crash and Linux root crash. Hyper-V implements 9 * a disable hypercall with a 32bit protected mode ABI callback. This 10 * mechanism must be used to unlock hypervisor RAM. Since the hypervisor RAM 11 * is already mapped in Linux, it is automatically collected into Linux vmcore, 12 * and can be examined by the crash command (raw RAM dump) or windbg. 13 * 14 * At a high level: 15 * 16 * Hypervisor Crash: 17 * Upon crash, hypervisor goes into an emergency minimal dispatch loop, a 18 * restrictive mode with very limited hypercall and MSR support. Each cpu 19 * then injects NMIs into root vcpus. A shared page is used to check 20 * by Linux in the NMI handler if the hypervisor has crashed. This shared 21 * page is setup in hv_root_crash_init during boot. 22 * 23 * Linux Crash: 24 * In case of Linux crash, the callback hv_crash_stop_other_cpus will send 25 * NMIs to all cpus, then proceed to the crash_nmi_callback where it waits 26 * for all cpus to be in NMI. 27 * 28 * NMI Handler (upon quorum): 29 * Eventually, in both cases, all cpus will end up in the NMI handler. 30 * Hyper-V requires the disable hypervisor must be done from the BSP. So 31 * the BSP NMI handler saves current context, does some fixups and makes 32 * the hypercall to disable the hypervisor, ie, devirtualize. Hypervisor 33 * at that point will suspend all vcpus (except the BSP), unlock all its 34 * RAM, and return to Linux at the 32bit mode entry RIP. 35 * 36 * Linux 32bit entry trampoline will then restore long mode and call C 37 * function here to restore context and continue execution to crash kexec. 38 */ 39 40 #include <linux/delay.h> 41 #include <linux/kexec.h> 42 #include <linux/crash_dump.h> 43 #include <linux/panic.h> 44 #include <asm/apic.h> 45 #include <asm/desc.h> 46 #include <asm/page.h> 47 #include <asm/pgalloc.h> 48 #include <asm/mshyperv.h> 49 #include <asm/nmi.h> 50 #include <asm/idtentry.h> 51 #include <asm/reboot.h> 52 #include <asm/intel_pt.h> 53 54 bool hv_crash_enabled; 55 EXPORT_SYMBOL_GPL(hv_crash_enabled); 56 57 struct hv_crash_ctxt { 58 ulong rsp; 59 ulong cr0; 60 ulong cr2; 61 ulong cr4; 62 ulong cr8; 63 64 u16 cs; 65 u16 ss; 66 u16 ds; 67 u16 es; 68 u16 fs; 69 u16 gs; 70 71 u16 gdt_fill; 72 struct desc_ptr gdtr; 73 char idt_fill[6]; 74 struct desc_ptr idtr; 75 76 u64 gsbase; 77 u64 efer; 78 u64 pat; 79 }; 80 static struct hv_crash_ctxt hv_crash_ctxt; 81 82 /* Shared hypervisor page that contains crash dump area we peek into. 83 * NB: windbg looks for "hv_cda" symbol so don't change it. 84 */ 85 static struct hv_crashdump_area *hv_cda; 86 87 static u32 trampoline_pa, devirt_arg; 88 static atomic_t crash_cpus_wait; 89 static void *hv_crash_ptpgs[4]; 90 static bool hv_has_crashed, lx_has_crashed; 91 92 static void __noreturn hv_panic_timeout_reboot(void) 93 { 94 #define PANIC_TIMER_STEP 100 95 96 if (panic_timeout > 0) { 97 int i; 98 99 for (i = 0; i < panic_timeout * 1000; i += PANIC_TIMER_STEP) 100 mdelay(PANIC_TIMER_STEP); 101 } 102 103 if (panic_timeout) 104 native_wrmsrq(HV_X64_MSR_RESET, 1); /* get hyp to reboot */ 105 106 for (;;) 107 cpu_relax(); 108 } 109 110 /* This cannot be inlined as it needs stack */ 111 static noinline __noclone void hv_crash_restore_tss(void) 112 { 113 load_TR_desc(); 114 } 115 116 /* This cannot be inlined as it needs stack */ 117 static noinline void hv_crash_clear_kernpt(void) 118 { 119 pgd_t *pgd; 120 p4d_t *p4d; 121 122 /* Clear entry so it's not confusing to someone looking at the core */ 123 pgd = pgd_offset_k(trampoline_pa); 124 p4d = p4d_offset(pgd, trampoline_pa); 125 native_p4d_clear(p4d); 126 } 127 128 /* 129 * This is the C entry point from the asm glue code after the disable hypercall. 130 * We enter here in IA32-e long mode, ie, full 64bit mode running on kernel 131 * page tables with our below 4G page identity mapped, but using a temporary 132 * GDT. ds/fs/gs/es are null. ss is not usable. bp is null. stack is not 133 * available. We restore kernel GDT, and rest of the context, and continue 134 * to kexec. 135 */ 136 static asmlinkage void __noreturn hv_crash_c_entry(void) 137 { 138 struct hv_crash_ctxt *ctxt = &hv_crash_ctxt; 139 140 /* first thing, restore kernel gdt */ 141 native_load_gdt(&ctxt->gdtr); 142 143 asm volatile("movw %%ax, %%ss" : : "a"(ctxt->ss)); 144 asm volatile("movq %0, %%rsp" : : "m"(ctxt->rsp)); 145 146 asm volatile("movw %%ax, %%ds" : : "a"(ctxt->ds)); 147 asm volatile("movw %%ax, %%es" : : "a"(ctxt->es)); 148 asm volatile("movw %%ax, %%fs" : : "a"(ctxt->fs)); 149 asm volatile("movw %%ax, %%gs" : : "a"(ctxt->gs)); 150 151 native_wrmsrq(MSR_IA32_CR_PAT, ctxt->pat); 152 asm volatile("movq %0, %%cr0" : : "r"(ctxt->cr0)); 153 154 asm volatile("movq %0, %%cr8" : : "r"(ctxt->cr8)); 155 asm volatile("movq %0, %%cr4" : : "r"(ctxt->cr4)); 156 asm volatile("movq %0, %%cr2" : : "r"(ctxt->cr4)); 157 158 native_load_idt(&ctxt->idtr); 159 native_wrmsrq(MSR_GS_BASE, ctxt->gsbase); 160 native_wrmsrq(MSR_EFER, ctxt->efer); 161 162 /* restore the original kernel CS now via far return */ 163 asm volatile("movzwq %0, %%rax\n\t" 164 "pushq %%rax\n\t" 165 "pushq $1f\n\t" 166 "lretq\n\t" 167 "1:nop\n\t" : : "m"(ctxt->cs) : "rax"); 168 169 /* We are in asmlinkage without stack frame, hence make C function 170 * calls which will buy stack frames. 171 */ 172 hv_crash_restore_tss(); 173 hv_crash_clear_kernpt(); 174 175 /* we are now fully in devirtualized normal kernel mode */ 176 __crash_kexec(NULL); 177 178 hv_panic_timeout_reboot(); 179 } 180 /* Tell gcc we are using lretq long jump in the above function intentionally */ 181 STACK_FRAME_NON_STANDARD(hv_crash_c_entry); 182 183 static void hv_mark_tss_not_busy(void) 184 { 185 struct desc_struct *desc = get_current_gdt_rw(); 186 tss_desc tss; 187 188 memcpy(&tss, &desc[GDT_ENTRY_TSS], sizeof(tss_desc)); 189 tss.type = 0x9; /* available 64-bit TSS. 0xB is busy TSS */ 190 write_gdt_entry(desc, GDT_ENTRY_TSS, &tss, DESC_TSS); 191 } 192 193 /* Save essential context */ 194 static void hv_hvcrash_ctxt_save(void) 195 { 196 struct hv_crash_ctxt *ctxt = &hv_crash_ctxt; 197 198 asm volatile("movq %%rsp,%0" : "=m"(ctxt->rsp)); 199 200 ctxt->cr0 = native_read_cr0(); 201 ctxt->cr4 = native_read_cr4(); 202 203 asm volatile("movq %%cr2, %0" : "=a"(ctxt->cr2)); 204 asm volatile("movq %%cr8, %0" : "=a"(ctxt->cr8)); 205 206 asm volatile("movl %%cs, %%eax" : "=a"(ctxt->cs)); 207 asm volatile("movl %%ss, %%eax" : "=a"(ctxt->ss)); 208 asm volatile("movl %%ds, %%eax" : "=a"(ctxt->ds)); 209 asm volatile("movl %%es, %%eax" : "=a"(ctxt->es)); 210 asm volatile("movl %%fs, %%eax" : "=a"(ctxt->fs)); 211 asm volatile("movl %%gs, %%eax" : "=a"(ctxt->gs)); 212 213 native_store_gdt(&ctxt->gdtr); 214 store_idt(&ctxt->idtr); 215 216 ctxt->gsbase = __rdmsr(MSR_GS_BASE); 217 ctxt->efer = __rdmsr(MSR_EFER); 218 ctxt->pat = __rdmsr(MSR_IA32_CR_PAT); 219 } 220 221 /* Add trampoline page to the kernel pagetable for transition to kernel PT */ 222 static void hv_crash_fixup_kernpt(void) 223 { 224 pgd_t *pgd; 225 p4d_t *p4d; 226 227 pgd = pgd_offset_k(trampoline_pa); 228 p4d = p4d_offset(pgd, trampoline_pa); 229 230 /* trampoline_pa is below 4G, so no pre-existing entry to clobber */ 231 p4d_populate(&init_mm, p4d, (pud_t *)hv_crash_ptpgs[1]); 232 p4d->p4d = p4d->p4d & ~(_PAGE_NX); /* enable execute */ 233 } 234 235 /* 236 * Notify the hyp that Linux has crashed. This will cause the hyp to quiesce 237 * and suspend all guest VPs. 238 */ 239 static void hv_notify_prepare_hyp(void) 240 { 241 u64 status; 242 struct hv_input_notify_partition_event *input; 243 struct hv_partition_event_root_crashdump_input *cda; 244 245 input = *this_cpu_ptr(hyperv_pcpu_input_arg); 246 cda = &input->input.crashdump_input; 247 memset(input, 0, sizeof(*input)); 248 input->event = HV_PARTITION_EVENT_ROOT_CRASHDUMP; 249 250 cda->crashdump_action = HV_CRASHDUMP_ENTRY; 251 status = hv_do_hypercall(HVCALL_NOTIFY_PARTITION_EVENT, input, NULL); 252 if (!hv_result_success(status)) 253 return; 254 255 cda->crashdump_action = HV_CRASHDUMP_SUSPEND_ALL_VPS; 256 hv_do_hypercall(HVCALL_NOTIFY_PARTITION_EVENT, input, NULL); 257 } 258 259 /* 260 * Common function for all cpus before devirtualization. 261 * 262 * Hypervisor crash: all cpus get here in NMI context. 263 * Linux crash: the panicing cpu gets here at base level, all others in NMI 264 * context. Note, panicing cpu may not be the BSP. 265 * 266 * The function is not inlined so it will show on the stack. It is named so 267 * because the crash cmd looks for certain well known function names on the 268 * stack before looking into the cpu saved note in the elf section, and 269 * that work is currently incomplete. 270 * 271 * Notes: 272 * Hypervisor crash: 273 * - the hypervisor is in a very restrictive mode at this point and any 274 * vmexit it cannot handle would result in reboot. So, no mumbo jumbo, 275 * just get to kexec as quickly as possible. 276 * 277 * Devirtualization is supported from the BSP only at present. 278 */ 279 static noinline __noclone void crash_nmi_callback(struct pt_regs *regs) 280 { 281 struct hv_input_disable_hyp_ex *input; 282 int msecs = 1000, ccpu = smp_processor_id(); 283 284 if (ccpu == 0) { 285 /* crash_save_cpu() will be done in the kexec path */ 286 cpu_emergency_stop_pt(); /* disable performance trace */ 287 atomic_inc(&crash_cpus_wait); 288 } else { 289 crash_save_cpu(regs, ccpu); 290 cpu_emergency_stop_pt(); /* disable performance trace */ 291 atomic_inc(&crash_cpus_wait); 292 for (;;) 293 cpu_relax(); 294 } 295 296 while (atomic_read(&crash_cpus_wait) < num_online_cpus() && msecs--) 297 mdelay(1); 298 299 stop_nmi(); 300 if (!hv_has_crashed) 301 hv_notify_prepare_hyp(); 302 303 if (crashing_cpu == -1) 304 crashing_cpu = ccpu; /* crash cmd uses this */ 305 306 hv_hvcrash_ctxt_save(); 307 hv_mark_tss_not_busy(); 308 hv_crash_fixup_kernpt(); 309 310 input = *this_cpu_ptr(hyperv_pcpu_input_arg); 311 memset(input, 0, sizeof(*input)); 312 input->rip = trampoline_pa; 313 input->arg = devirt_arg; 314 315 (void)hv_do_hypercall(HVCALL_DISABLE_HYP_EX, input, NULL); 316 317 hv_panic_timeout_reboot(); 318 } 319 320 321 static DEFINE_SPINLOCK(hv_crash_reboot_lk); 322 323 /* 324 * Generic NMI callback handler: could be called without any crash also. 325 * hv crash: hypervisor injects NMI's into all cpus 326 * lx crash: panicing cpu sends NMI to all but self via crash_stop_other_cpus 327 */ 328 static int hv_crash_nmi_local(unsigned int cmd, struct pt_regs *regs) 329 { 330 if (!hv_has_crashed && hv_cda && hv_cda->cda_valid) 331 hv_has_crashed = true; 332 333 if (!hv_has_crashed && !lx_has_crashed) 334 return NMI_DONE; /* ignore the NMI */ 335 336 if (hv_has_crashed && !kexec_crash_loaded()) { 337 if (spin_trylock(&hv_crash_reboot_lk)) 338 hv_panic_timeout_reboot(); 339 else 340 for (;;) 341 cpu_relax(); 342 } 343 344 crash_nmi_callback(regs); 345 346 return NMI_DONE; 347 } 348 349 /* 350 * hv_crash_stop_other_cpus() == smp_ops.crash_stop_other_cpus 351 * 352 * On normal Linux panic, this is called twice: first from panic and then again 353 * from native_machine_crash_shutdown. 354 * 355 * In case of hyperv, 3 ways to get here: 356 * 1. hv crash (only BSP will get here): 357 * BSP : NMI callback -> DisableHv -> hv_crash_asm32 -> hv_crash_c_entry 358 * -> __crash_kexec -> native_machine_crash_shutdown 359 * -> crash_smp_send_stop -> smp_ops.crash_stop_other_cpus 360 * Linux panic: 361 * 2. panic cpu x: panic() -> crash_smp_send_stop 362 * -> smp_ops.crash_stop_other_cpus 363 * 3. BSP: native_machine_crash_shutdown -> crash_smp_send_stop 364 * 365 * NB: noclone and non standard stack because of call to crash_setup_regs(). 366 */ 367 static void __noclone hv_crash_stop_other_cpus(void) 368 { 369 static bool crash_stop_done; 370 struct pt_regs lregs; 371 int ccpu = smp_processor_id(); 372 373 if (hv_has_crashed) 374 return; /* all cpus already in NMI handler path */ 375 376 if (!kexec_crash_loaded()) { 377 hv_notify_prepare_hyp(); 378 hv_panic_timeout_reboot(); /* no return */ 379 } 380 381 /* If the hv crashes also, we could come here again before cpus_stopped 382 * is set in crash_smp_send_stop(). So use our own check. 383 */ 384 if (crash_stop_done) 385 return; 386 crash_stop_done = true; 387 388 /* Linux has crashed: hv is healthy, we can IPI safely */ 389 lx_has_crashed = true; 390 wmb(); /* NMI handlers look at lx_has_crashed */ 391 392 apic->send_IPI_allbutself(NMI_VECTOR); 393 394 if (crashing_cpu == -1) 395 crashing_cpu = ccpu; /* crash cmd uses this */ 396 397 /* crash_setup_regs() happens in kexec also, but for the kexec cpu which 398 * is the BSP. We could be here on non-BSP cpu, collect regs if so. 399 */ 400 if (ccpu) 401 crash_setup_regs(&lregs, NULL); 402 403 crash_nmi_callback(&lregs); 404 } 405 STACK_FRAME_NON_STANDARD(hv_crash_stop_other_cpus); 406 407 /* This GDT is accessed in IA32-e compat mode which uses 32bits addresses */ 408 struct hv_gdtreg_32 { 409 u16 fill; 410 u16 limit; 411 u32 address; 412 } __packed; 413 414 /* We need a CS with L bit to goto IA32-e long mode from 32bit compat mode */ 415 struct hv_crash_tramp_gdt { 416 u64 null; /* index 0, selector 0, null selector */ 417 u64 cs64; /* index 1, selector 8, cs64 selector */ 418 } __packed; 419 420 /* No stack, so jump via far ptr in memory to load the 64bit CS */ 421 struct hv_cs_jmptgt { 422 u32 address; 423 u16 csval; 424 u16 fill; 425 } __packed; 426 427 /* Linux use only, hypervisor doesn't look at this struct */ 428 struct hv_crash_tramp_data { 429 u64 tramp32_cr3; 430 u64 kernel_cr3; 431 struct hv_gdtreg_32 gdtr32; 432 struct hv_crash_tramp_gdt tramp_gdt; 433 struct hv_cs_jmptgt cs_jmptgt; 434 u64 c_entry_addr; 435 } __packed; 436 437 /* 438 * Setup a temporary gdt to allow the asm code to switch to the long mode. 439 * Since the asm code is relocated/copied to a below 4G page, it cannot use rip 440 * relative addressing, hence we must use trampoline_pa here. Also, save other 441 * info like jmp and C entry targets for same reasons. 442 * 443 * Returns: 0 on success, -1 on error 444 */ 445 static int hv_crash_setup_trampdata(u64 trampoline_va) 446 { 447 int size, offs; 448 void *dest; 449 struct hv_crash_tramp_data *tramp; 450 451 /* These must match exactly the ones in the corresponding asm file */ 452 BUILD_BUG_ON(offsetof(struct hv_crash_tramp_data, tramp32_cr3) != 0); 453 BUILD_BUG_ON(offsetof(struct hv_crash_tramp_data, kernel_cr3) != 8); 454 BUILD_BUG_ON(offsetof(struct hv_crash_tramp_data, gdtr32.limit) != 18); 455 BUILD_BUG_ON(offsetof(struct hv_crash_tramp_data, 456 cs_jmptgt.address) != 40); 457 BUILD_BUG_ON(offsetof(struct hv_crash_tramp_data, c_entry_addr) != 48); 458 459 /* hv_crash_asm_end is beyond last byte by 1 */ 460 size = &hv_crash_asm_end - &hv_crash_asm32; 461 if (size + sizeof(struct hv_crash_tramp_data) > PAGE_SIZE) { 462 pr_err("%s: trampoline page overflow\n", __func__); 463 return -1; 464 } 465 466 dest = (void *)trampoline_va; 467 memcpy(dest, &hv_crash_asm32, size); 468 469 dest += size; 470 dest = (void *)round_up((ulong)dest, 16); 471 tramp = (struct hv_crash_tramp_data *)dest; 472 473 /* see MAX_ASID_AVAILABLE in tlb.c: "PCID 0 is reserved for use by 474 * non-PCID-aware users". Build cr3 with pcid 0 475 */ 476 tramp->tramp32_cr3 = __sme_pa(hv_crash_ptpgs[0]); 477 478 /* Note, when restoring X86_CR4_PCIDE, cr3[11:0] must be zero */ 479 tramp->kernel_cr3 = __sme_pa(init_mm.pgd); 480 481 tramp->gdtr32.limit = sizeof(struct hv_crash_tramp_gdt); 482 tramp->gdtr32.address = trampoline_pa + 483 (ulong)&tramp->tramp_gdt - trampoline_va; 484 485 /* base:0 limit:0xfffff type:b dpl:0 P:1 L:1 D:0 avl:0 G:1 */ 486 tramp->tramp_gdt.cs64 = 0x00af9a000000ffff; 487 488 tramp->cs_jmptgt.csval = 0x8; 489 offs = (ulong)&hv_crash_asm64 - (ulong)&hv_crash_asm32; 490 tramp->cs_jmptgt.address = trampoline_pa + offs; 491 492 tramp->c_entry_addr = (u64)&hv_crash_c_entry; 493 494 devirt_arg = trampoline_pa + (ulong)dest - trampoline_va; 495 496 return 0; 497 } 498 499 /* 500 * Build 32bit trampoline page table for transition from protected mode 501 * non-paging to long-mode paging. This transition needs pagetables below 4G. 502 */ 503 static void hv_crash_build_tramp_pt(void) 504 { 505 p4d_t *p4d; 506 pud_t *pud; 507 pmd_t *pmd; 508 pte_t *pte; 509 u64 pa, addr = trampoline_pa; 510 511 p4d = hv_crash_ptpgs[0] + pgd_index(addr) * sizeof(p4d); 512 pa = virt_to_phys(hv_crash_ptpgs[1]); 513 set_p4d(p4d, __p4d(_PAGE_TABLE | pa)); 514 p4d->p4d &= ~(_PAGE_NX); /* enable execute */ 515 516 pud = hv_crash_ptpgs[1] + pud_index(addr) * sizeof(pud); 517 pa = virt_to_phys(hv_crash_ptpgs[2]); 518 set_pud(pud, __pud(_PAGE_TABLE | pa)); 519 520 pmd = hv_crash_ptpgs[2] + pmd_index(addr) * sizeof(pmd); 521 pa = virt_to_phys(hv_crash_ptpgs[3]); 522 set_pmd(pmd, __pmd(_PAGE_TABLE | pa)); 523 524 pte = hv_crash_ptpgs[3] + pte_index(addr) * sizeof(pte); 525 set_pte(pte, pfn_pte(addr >> PAGE_SHIFT, PAGE_KERNEL_EXEC)); 526 } 527 528 /* 529 * Setup trampoline for devirtualization: 530 * - a page below 4G, ie 32bit addr containing asm glue code that hyp jmps to 531 * in protected mode. 532 * - 4 pages for a temporary page table that asm code uses to turn paging on 533 * - a temporary gdt to use in the compat mode. 534 * 535 * Returns: 0 on success 536 */ 537 static int hv_crash_trampoline_setup(void) 538 { 539 int i, rc, order; 540 struct page *page; 541 u64 trampoline_va; 542 gfp_t flags32 = GFP_KERNEL | GFP_DMA32 | __GFP_ZERO; 543 544 /* page for 32bit trampoline assembly code + hv_crash_tramp_data */ 545 page = alloc_page(flags32); 546 if (page == NULL) { 547 pr_err("%s: failed to alloc asm stub page\n", __func__); 548 return -1; 549 } 550 551 trampoline_va = (u64)page_to_virt(page); 552 trampoline_pa = (u32)page_to_phys(page); 553 554 order = 2; /* alloc 2^2 pages */ 555 page = alloc_pages(flags32, order); 556 if (page == NULL) { 557 pr_err("%s: failed to alloc pt pages\n", __func__); 558 free_page(trampoline_va); 559 return -1; 560 } 561 562 for (i = 0; i < 4; i++, page++) 563 hv_crash_ptpgs[i] = page_to_virt(page); 564 565 hv_crash_build_tramp_pt(); 566 567 rc = hv_crash_setup_trampdata(trampoline_va); 568 if (rc) 569 goto errout; 570 571 return 0; 572 573 errout: 574 free_page(trampoline_va); 575 free_pages((ulong)hv_crash_ptpgs[0], order); 576 577 return rc; 578 } 579 580 /* Setup for kdump kexec to collect hypervisor RAM when running as root */ 581 void hv_root_crash_init(void) 582 { 583 int rc; 584 struct hv_input_get_system_property *input; 585 struct hv_output_get_system_property *output; 586 unsigned long flags; 587 u64 status; 588 union hv_pfn_range cda_info; 589 590 if (pgtable_l5_enabled()) { 591 pr_err("Hyper-V: crash dump not yet supported on 5level PTs\n"); 592 return; 593 } 594 595 rc = register_nmi_handler(NMI_LOCAL, hv_crash_nmi_local, NMI_FLAG_FIRST, 596 "hv_crash_nmi"); 597 if (rc) { 598 pr_err("Hyper-V: failed to register crash nmi handler\n"); 599 return; 600 } 601 602 local_irq_save(flags); 603 input = *this_cpu_ptr(hyperv_pcpu_input_arg); 604 output = *this_cpu_ptr(hyperv_pcpu_output_arg); 605 606 memset(input, 0, sizeof(*input)); 607 input->property_id = HV_SYSTEM_PROPERTY_CRASHDUMPAREA; 608 609 status = hv_do_hypercall(HVCALL_GET_SYSTEM_PROPERTY, input, output); 610 cda_info.as_uint64 = output->hv_cda_info.as_uint64; 611 local_irq_restore(flags); 612 613 if (!hv_result_success(status)) { 614 pr_err("Hyper-V: %s: property:%d %s\n", __func__, 615 input->property_id, hv_result_to_string(status)); 616 goto err_out; 617 } 618 619 if (cda_info.base_pfn == 0) { 620 pr_err("Hyper-V: hypervisor crash dump area pfn is 0\n"); 621 goto err_out; 622 } 623 624 hv_cda = phys_to_virt(cda_info.base_pfn << HV_HYP_PAGE_SHIFT); 625 626 rc = hv_crash_trampoline_setup(); 627 if (rc) 628 goto err_out; 629 630 #ifdef CONFIG_SMP 631 smp_ops.crash_stop_other_cpus = hv_crash_stop_other_cpus; 632 #endif 633 634 crash_kexec_post_notifiers = true; 635 hv_crash_enabled = true; 636 pr_info("Hyper-V: both linux and hypervisor kdump support enabled\n"); 637 638 return; 639 640 err_out: 641 unregister_nmi_handler(NMI_LOCAL, "hv_crash_nmi"); 642 pr_err("Hyper-V: only linux root kdump support enabled\n"); 643 } 644