int kvm_arch_init(void *opaque)
{
	struct kvm_x86_init_ops *ops = opaque;
	int r;

	if (kvm_x86_ops.hardware_enable) {
		pr_err("kvm: already loaded vendor module '%s'\n", kvm_x86_ops.name);
		r = -EEXIST;
		goto out;
	}

	if (!ops->cpu_has_kvm_support()) {
		pr_err_ratelimited("kvm: no hardware support for '%s'\n",
				   ops->runtime_ops->name);
		r = -EOPNOTSUPP;
		goto out;
	}
	if (ops->disabled_by_bios()) {
		pr_err_ratelimited("kvm: support for '%s' disabled by bios\n",
				   ops->runtime_ops->name);
		r = -EOPNOTSUPP;
		goto out;
	}

	/*
	 * KVM explicitly assumes that the guest has an FPU and
	 * FXSAVE/FXRSTOR. For example, the KVM_GET_FPU explicitly casts the
	 * vCPU's FPU state as a fxregs_state struct.
	 */
	if (!boot_cpu_has(X86_FEATURE_FPU) || !boot_cpu_has(X86_FEATURE_FXSR)) {
		printk(KERN_ERR "kvm: inadequate fpu\n");
		r = -EOPNOTSUPP;
		goto out;
	}

	if (IS_ENABLED(CONFIG_PREEMPT_RT) && !boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) {
		pr_err("RT requires X86_FEATURE_CONSTANT_TSC\n");
		r = -EOPNOTSUPP;
		goto out;
	}

	r = -ENOMEM;

	x86_emulator_cache = kvm_alloc_emulator_cache();
	if (!x86_emulator_cache) {
		pr_err("kvm: failed to allocate cache for x86 emulator\n");
		goto out;
	}

	user_return_msrs = alloc_percpu(struct kvm_user_return_msrs);
	if (!user_return_msrs) {
		printk(KERN_ERR "kvm: failed to allocate percpu kvm_user_return_msrs\n");
		goto out_free_x86_emulator_cache;
	}
	kvm_nr_uret_msrs = 0;

	r = kvm_mmu_vendor_module_init();
	if (r)
		goto out_free_percpu;

	kvm_timer_init();

	if (boot_cpu_has(X86_FEATURE_XSAVE)) {
		host_xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK);
		supported_xcr0 = host_xcr0 & KVM_SUPPORTED_XCR0;
	}

	if (pi_inject_timer == -1)
		pi_inject_timer = housekeeping_enabled(HK_TYPE_TIMER);
#ifdef CONFIG_X86_64
	pvclock_gtod_register_notifier(&pvclock_gtod_notifier);

	if (hypervisor_is_type(X86_HYPER_MS_HYPERV))
		set_hv_tscchange_cb(kvm_hyperv_tsc_notifier);
#endif

	return 0;

out_free_percpu:
	free_percpu(user_return_msrs);
out_free_x86_emulator_cache:
	kmem_cache_destroy(x86_emulator_cache);
out:
	return r;
}
int kvm_arch_init(void *opaque)
{
	struct kvm_x86_init_ops *ops = opaque;
	int r;

	if (kvm_x86_ops.hardware_enable) {
		pr_err("kvm: already loaded vendor module '%s'\n", kvm_x86_ops.name);
		r = -EEXIST;
		goto out;
	}

	if (!ops->cpu_has_kvm_support()) {
		pr_err_ratelimited("kvm: no hardware support for '%s'\n",
				   ops->runtime_ops->name);
		r = -EOPNOTSUPP;
		goto out;
	}
	if (ops->disabled_by_bios()) {
		pr_err_ratelimited("kvm: support for '%s' disabled by bios\n",
				   ops->runtime_ops->name);
		r = -EOPNOTSUPP;
		goto out;
	}

	 
	if (!boot_cpu_has(X86_FEATURE_FPU) || !boot_cpu_has(X86_FEATURE_FXSR)) {
		printk(KERN_ERR "kvm: inadequate fpu\n");
		r = -EOPNOTSUPP;
		goto out;
	}

	if (IS_ENABLED(CONFIG_PREEMPT_RT) && !boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) {
		pr_err("RT requires X86_FEATURE_CONSTANT_TSC\n");
		r = -EOPNOTSUPP;
		goto out;
	}

	r = -ENOMEM;

	x86_emulator_cache = kvm_alloc_emulator_cache();
	if (!x86_emulator_cache) {
		pr_err("kvm: failed to allocate cache for x86 emulator\n");
		goto out;
	}

	user_return_msrs = alloc_percpu(struct kvm_user_return_msrs);
	if (!user_return_msrs) {
		printk(KERN_ERR "kvm: failed to allocate percpu kvm_user_return_msrs\n");
		goto out_free_x86_emulator_cache;
	}
	kvm_nr_uret_msrs = 0;

	r = kvm_mmu_vendor_module_init();
	if (r)
		goto out_free_percpu;

	kvm_timer_init();

	if (boot_cpu_has(X86_FEATURE_XSAVE)) {
		host_xcr0 = xgetbv(XCR_XFEATURE_ENABLED_MASK);
		supported_xcr0 = host_xcr0 & KVM_SUPPORTED_XCR0;
	}

	if (pi_inject_timer == -1)
		pi_inject_timer = housekeeping_enabled(HK_TYPE_TIMER);
#ifdef CONFIG_X86_64
	pvclock_gtod_register_notifier(&pvclock_gtod_notifier);

	if (hypervisor_is_type(X86_HYPER_MS_HYPERV))
		set_hv_tscchange_cb(kvm_hyperv_tsc_notifier);
#endif

	return 0;

out_free_percpu:
	free_percpu(user_return_msrs);
out_free_x86_emulator_cache:
	kmem_cache_destroy(x86_emulator_cache);
out:
	return r;
}