arch/x86/hyperv/hv_init.c

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

File Facts

System
Linux kernel
Corpus path
arch/x86/hyperv/hv_init.c
Extension
.c
Size
21037 bytes
Lines
746
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

if (!*hvp) {
			*hvp = __vmalloc(PAGE_SIZE, GFP_KERNEL | __GFP_ZERO);

			/*
			 * Hyper-V should never specify a VM that is a Confidential
			 * VM and also running in the root partition. Root partition
			 * is blocked to run in Confidential VM. So only decrypt assist
			 * page in non-root partition here.
			 */
			if (*hvp && !ms_hyperv.paravisor_present && hv_isolation_type_snp()) {
				WARN_ON_ONCE(set_memory_decrypted((unsigned long)(*hvp), 1));
				memset(*hvp, 0, PAGE_SIZE);
			}
		}

		if (*hvp)
			msr.pfn = vmalloc_to_pfn(*hvp);

	}
	if (!WARN_ON(!(*hvp))) {
		msr.enable = 1;
		wrmsrq(HV_X64_MSR_VP_ASSIST_PAGE, msr.as_uint64);
	}

	/* Allow Hyper-V stimer vector to be injected from Hypervisor. */
	if (ms_hyperv.misc_features & HV_STIMER_DIRECT_MODE_AVAILABLE)
		apic_update_vector(cpu, HYPERV_STIMER0_VECTOR, true);

	return hyperv_init_ghcb();
}

static void (*hv_reenlightenment_cb)(void);

static void hv_reenlightenment_notify(struct work_struct *dummy)
{
	struct hv_tsc_emulation_status emu_status;

	rdmsrq(HV_X64_MSR_TSC_EMULATION_STATUS, *(u64 *)&emu_status);

	/* Don't issue the callback if TSC accesses are not emulated */
	if (hv_reenlightenment_cb && emu_status.inprogress)
		hv_reenlightenment_cb();
}
static DECLARE_DELAYED_WORK(hv_reenlightenment_work, hv_reenlightenment_notify);

void hyperv_stop_tsc_emulation(void)
{
	u64 freq;
	struct hv_tsc_emulation_status emu_status;

	rdmsrq(HV_X64_MSR_TSC_EMULATION_STATUS, *(u64 *)&emu_status);
	emu_status.inprogress = 0;
	wrmsrq(HV_X64_MSR_TSC_EMULATION_STATUS, *(u64 *)&emu_status);

	rdmsrq(HV_X64_MSR_TSC_FREQUENCY, freq);
	tsc_khz = div64_u64(freq, 1000);
}
EXPORT_SYMBOL_GPL(hyperv_stop_tsc_emulation);

static inline bool hv_reenlightenment_available(void)
{
	/*
	 * Check for required features and privileges to make TSC frequency
	 * change notifications work.
	 */
	return ms_hyperv.features & HV_ACCESS_FREQUENCY_MSRS &&
		ms_hyperv.misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE &&
		ms_hyperv.features & HV_ACCESS_REENLIGHTENMENT;
}

DEFINE_IDTENTRY_SYSVEC(sysvec_hyperv_reenlightenment)
{
	apic_eoi();
	inc_irq_stat(HYPERV_REENLIGHTENMENT);
	schedule_delayed_work(&hv_reenlightenment_work, HZ/10);
}

void set_hv_tscchange_cb(void (*cb)(void))
{
	struct hv_reenlightenment_control re_ctrl = {
		.vector = HYPERV_REENLIGHTENMENT_VECTOR,
		.enabled = 1,
	};
	struct hv_tsc_emulation_control emu_ctrl = {.enabled = 1};

	if (!hv_reenlightenment_available()) {
		pr_warn("reenlightenment support is unavailable\n");
		return;
	}

Annotation

Implementation Notes