arch/x86/kernel/kvmclock.c

Source file repositories/reference/linux-study-clean/arch/x86/kernel/kvmclock.c

File Facts

System
Linux kernel
Corpus path
arch/x86/kernel/kvmclock.c
Extension
.c
Size
9401 bytes
Lines
373
Domain
Architecture Layer
Bucket
arch/x86
Inferred role
Architecture Layer: implementation source
Status
source 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 (r) {
			__free_pages(p, order);
			hvclock_mem = NULL;
			pr_warn("kvmclock: set_memory_decrypted() failed. Disabling\n");
			return;
		}
	}

	memset(hvclock_mem, 0, PAGE_SIZE << order);
}

static int __init kvm_setup_vsyscall_timeinfo(void)
{
	if (!kvm_para_available() || !kvmclock || nopv)
		return 0;

	kvmclock_init_mem();

#ifdef CONFIG_X86_64
	if (per_cpu(hv_clock_per_cpu, 0) && kvmclock_vsyscall) {
		u8 flags;

		flags = pvclock_read_flags(&hv_clock_boot[0].pvti);
		if (!(flags & PVCLOCK_TSC_STABLE_BIT))
			return 0;

		kvm_clock.vdso_clock_mode = VDSO_CLOCKMODE_PVCLOCK;
	}
#endif

	return 0;
}
early_initcall(kvm_setup_vsyscall_timeinfo);

static int kvmclock_setup_percpu(unsigned int cpu)
{
	struct pvclock_vsyscall_time_info *p = per_cpu(hv_clock_per_cpu, cpu);

	/*
	 * The per cpu area setup replicates CPU0 data to all cpu
	 * pointers. So carefully check. CPU0 has been set up in init
	 * already.
	 */
	if (!cpu || (p && p != per_cpu(hv_clock_per_cpu, 0)))
		return 0;

	/* Use the static page for the first CPUs, allocate otherwise */
	if (cpu < HVC_BOOT_ARRAY_SIZE)
		p = &hv_clock_boot[cpu];
	else if (hvclock_mem)
		p = hvclock_mem + cpu - HVC_BOOT_ARRAY_SIZE;
	else
		return -ENOMEM;

	per_cpu(hv_clock_per_cpu, cpu) = p;
	return p ? 0 : -ENOMEM;
}

void __init kvmclock_init(void)
{
	u8 flags;

	if (!kvm_para_available() || !kvmclock)
		return;

	if (kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE2)) {
		msr_kvm_system_time = MSR_KVM_SYSTEM_TIME_NEW;
		msr_kvm_wall_clock = MSR_KVM_WALL_CLOCK_NEW;
	} else if (kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE)) {
		msr_kvm_system_time = MSR_KVM_SYSTEM_TIME;
		msr_kvm_wall_clock = MSR_KVM_WALL_CLOCK;
	} else {
		return;
	}

	if (cpuhp_setup_state(CPUHP_BP_PREPARE_DYN, "kvmclock:setup_percpu",
			      kvmclock_setup_percpu, NULL) < 0) {
		return;
	}

	pr_info("kvm-clock: Using msrs %x and %x",
		msr_kvm_system_time, msr_kvm_wall_clock);

	this_cpu_write(hv_clock_per_cpu, &hv_clock_boot[0]);
	kvm_register_clock("primary cpu clock");
	pvclock_set_pvti_cpu0_va(hv_clock_boot);

	if (kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE_STABLE_BIT))
		pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT);

Annotation

Implementation Notes