arch/x86/hyperv/hv_crash.c

Source file repositories/reference/linux-study-clean/arch/x86/hyperv/hv_crash.c

File Facts

System
Linux kernel
Corpus path
arch/x86/hyperv/hv_crash.c
Extension
.c
Size
18796 bytes
Lines
648
Domain
Architecture Layer
Bucket
arch/x86
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

struct hv_crash_ctxt {
	ulong rsp;
	ulong cr0;
	ulong cr2;
	ulong cr4;
	ulong cr8;

	u16 cs;
	u16 ss;
	u16 ds;
	u16 es;
	u16 fs;
	u16 gs;

	u16 gdt_fill;
	struct desc_ptr gdtr;
	char idt_fill[6];
	struct desc_ptr idtr;

	u64 gsbase;
	u64 efer;
	u64 pat;
};
static struct hv_crash_ctxt hv_crash_ctxt;

/* Shared hypervisor page that contains crash dump area we peek into.
 * NB: windbg looks for "hv_cda" symbol so don't change it.
 */
static struct hv_crashdump_area *hv_cda;

static u32 trampoline_pa, devirt_arg;
static atomic_t crash_cpus_wait;
static void *hv_crash_ptpgs[4];
static bool hv_has_crashed, lx_has_crashed;

static void __noreturn hv_panic_timeout_reboot(void)
{
	#define PANIC_TIMER_STEP 100

	if (panic_timeout > 0) {
		int i;

		for (i = 0; i < panic_timeout * 1000; i += PANIC_TIMER_STEP)
			mdelay(PANIC_TIMER_STEP);
	}

	if (panic_timeout)
		native_wrmsrq(HV_X64_MSR_RESET, 1);    /* get hyp to reboot */

	for (;;)
		cpu_relax();
}

static void hv_crash_restore_tss(void)
{
	load_TR_desc();
}

static void hv_crash_clear_kernpt(void)
{
	pgd_t *pgd;
	p4d_t *p4d;

	/* Clear entry so it's not confusing to someone looking at the core */
	pgd = pgd_offset_k(trampoline_pa);
	p4d = p4d_offset(pgd, trampoline_pa);
	native_p4d_clear(p4d);
}


static void __noreturn hv_crash_handle(void)
{
	hv_crash_restore_tss();
	hv_crash_clear_kernpt();

	/* we are now fully in devirtualized normal kernel mode */
	__crash_kexec(NULL);

	hv_panic_timeout_reboot();
}

/*
 * __naked functions do not permit function calls, not even to __always_inline
 * functions that only contain asm() blocks themselves. So use a macro instead.
 */
#define hv_wrmsr(msr, val) \
	asm volatile("wrmsr" :: "c"(msr), "a"((u32)val), "d"((u32)(val >> 32)) : "memory")

/*
 * This is the C entry point from the asm glue code after the disable hypercall.

Annotation

Implementation Notes