kvm: x86: vmx: move some vmx setting from vmx_init() to hardware_setup()
Instead of vmx_init(), actually it would make reasonable sense to do anything specific to vmx hardware setting in vmx_x86_ops->hardware_setup(). Signed-off-by: Tiejun Chen <tiejun.chen@intel.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
		
							parent
							
								
									f2c7648d91
								
							
						
					
					
						commit
						34a1cd60d1
					
				| @ -5720,8 +5720,108 @@ static void update_ple_window_actual_max(void) | ||||
| 
 | ||||
| static __init int hardware_setup(void) | ||||
| { | ||||
| 	if (setup_vmcs_config(&vmcs_config) < 0) | ||||
| 		return -EIO; | ||||
| 	int r = -ENOMEM, i, msr; | ||||
| 
 | ||||
| 	rdmsrl_safe(MSR_EFER, &host_efer); | ||||
| 
 | ||||
| 	for (i = 0; i < ARRAY_SIZE(vmx_msr_index); ++i) | ||||
| 		kvm_define_shared_msr(i, vmx_msr_index[i]); | ||||
| 
 | ||||
| 	vmx_io_bitmap_a = (unsigned long *)__get_free_page(GFP_KERNEL); | ||||
| 	if (!vmx_io_bitmap_a) | ||||
| 		return r; | ||||
| 
 | ||||
| 	vmx_io_bitmap_b = (unsigned long *)__get_free_page(GFP_KERNEL); | ||||
| 	if (!vmx_io_bitmap_b) | ||||
| 		goto out; | ||||
| 
 | ||||
| 	vmx_msr_bitmap_legacy = (unsigned long *)__get_free_page(GFP_KERNEL); | ||||
| 	if (!vmx_msr_bitmap_legacy) | ||||
| 		goto out1; | ||||
| 
 | ||||
| 	vmx_msr_bitmap_legacy_x2apic = | ||||
| 				(unsigned long *)__get_free_page(GFP_KERNEL); | ||||
| 	if (!vmx_msr_bitmap_legacy_x2apic) | ||||
| 		goto out2; | ||||
| 
 | ||||
| 	vmx_msr_bitmap_longmode = (unsigned long *)__get_free_page(GFP_KERNEL); | ||||
| 	if (!vmx_msr_bitmap_longmode) | ||||
| 		goto out3; | ||||
| 
 | ||||
| 	vmx_msr_bitmap_longmode_x2apic = | ||||
| 				(unsigned long *)__get_free_page(GFP_KERNEL); | ||||
| 	if (!vmx_msr_bitmap_longmode_x2apic) | ||||
| 		goto out4; | ||||
| 	vmx_vmread_bitmap = (unsigned long *)__get_free_page(GFP_KERNEL); | ||||
| 	if (!vmx_vmread_bitmap) | ||||
| 		goto out5; | ||||
| 
 | ||||
| 	vmx_vmwrite_bitmap = (unsigned long *)__get_free_page(GFP_KERNEL); | ||||
| 	if (!vmx_vmwrite_bitmap) | ||||
| 		goto out6; | ||||
| 
 | ||||
| 	memset(vmx_vmread_bitmap, 0xff, PAGE_SIZE); | ||||
| 	memset(vmx_vmwrite_bitmap, 0xff, PAGE_SIZE); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Allow direct access to the PC debug port (it is often used for I/O | ||||
| 	 * delays, but the vmexits simply slow things down). | ||||
| 	 */ | ||||
| 	memset(vmx_io_bitmap_a, 0xff, PAGE_SIZE); | ||||
| 	clear_bit(0x80, vmx_io_bitmap_a); | ||||
| 
 | ||||
| 	memset(vmx_io_bitmap_b, 0xff, PAGE_SIZE); | ||||
| 
 | ||||
| 	memset(vmx_msr_bitmap_legacy, 0xff, PAGE_SIZE); | ||||
| 	memset(vmx_msr_bitmap_longmode, 0xff, PAGE_SIZE); | ||||
| 
 | ||||
| 	vmx_disable_intercept_for_msr(MSR_FS_BASE, false); | ||||
| 	vmx_disable_intercept_for_msr(MSR_GS_BASE, false); | ||||
| 	vmx_disable_intercept_for_msr(MSR_KERNEL_GS_BASE, true); | ||||
| 	vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_CS, false); | ||||
| 	vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_ESP, false); | ||||
| 	vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP, false); | ||||
| 	vmx_disable_intercept_for_msr(MSR_IA32_BNDCFGS, true); | ||||
| 
 | ||||
| 	memcpy(vmx_msr_bitmap_legacy_x2apic, | ||||
| 			vmx_msr_bitmap_legacy, PAGE_SIZE); | ||||
| 	memcpy(vmx_msr_bitmap_longmode_x2apic, | ||||
| 			vmx_msr_bitmap_longmode, PAGE_SIZE); | ||||
| 
 | ||||
| 	if (enable_apicv) { | ||||
| 		for (msr = 0x800; msr <= 0x8ff; msr++) | ||||
| 			vmx_disable_intercept_msr_read_x2apic(msr); | ||||
| 
 | ||||
| 		/* According SDM, in x2apic mode, the whole id reg is used.
 | ||||
| 		 * But in KVM, it only use the highest eight bits. Need to | ||||
| 		 * intercept it */ | ||||
| 		vmx_enable_intercept_msr_read_x2apic(0x802); | ||||
| 		/* TMCCT */ | ||||
| 		vmx_enable_intercept_msr_read_x2apic(0x839); | ||||
| 		/* TPR */ | ||||
| 		vmx_disable_intercept_msr_write_x2apic(0x808); | ||||
| 		/* EOI */ | ||||
| 		vmx_disable_intercept_msr_write_x2apic(0x80b); | ||||
| 		/* SELF-IPI */ | ||||
| 		vmx_disable_intercept_msr_write_x2apic(0x83f); | ||||
| 	} | ||||
| 
 | ||||
| 	if (enable_ept) { | ||||
| 		kvm_mmu_set_mask_ptes(0ull, | ||||
| 			(enable_ept_ad_bits) ? VMX_EPT_ACCESS_BIT : 0ull, | ||||
| 			(enable_ept_ad_bits) ? VMX_EPT_DIRTY_BIT : 0ull, | ||||
| 			0ull, VMX_EPT_EXECUTABLE_MASK); | ||||
| 		ept_set_mmio_spte_mask(); | ||||
| 		kvm_enable_tdp(); | ||||
| 	} else | ||||
| 		kvm_disable_tdp(); | ||||
| 
 | ||||
| 	update_ple_window_actual_max(); | ||||
| 
 | ||||
| 	if (setup_vmcs_config(&vmcs_config) < 0) { | ||||
| 		r = -EIO; | ||||
| 		goto out7; | ||||
|     } | ||||
| 
 | ||||
| 	if (boot_cpu_has(X86_FEATURE_NX)) | ||||
| 		kvm_enable_efer_bits(EFER_NX); | ||||
| @ -5781,10 +5881,38 @@ static __init int hardware_setup(void) | ||||
| 		nested_vmx_setup_ctls_msrs(); | ||||
| 
 | ||||
| 	return alloc_kvm_area(); | ||||
| 
 | ||||
| out7: | ||||
| 	free_page((unsigned long)vmx_vmwrite_bitmap); | ||||
| out6: | ||||
| 	free_page((unsigned long)vmx_vmread_bitmap); | ||||
| out5: | ||||
| 	free_page((unsigned long)vmx_msr_bitmap_longmode_x2apic); | ||||
| out4: | ||||
| 	free_page((unsigned long)vmx_msr_bitmap_longmode); | ||||
| out3: | ||||
| 	free_page((unsigned long)vmx_msr_bitmap_legacy_x2apic); | ||||
| out2: | ||||
| 	free_page((unsigned long)vmx_msr_bitmap_legacy); | ||||
| out1: | ||||
| 	free_page((unsigned long)vmx_io_bitmap_b); | ||||
| out: | ||||
| 	free_page((unsigned long)vmx_io_bitmap_a); | ||||
| 
 | ||||
|     return r; | ||||
| } | ||||
| 
 | ||||
| static __exit void hardware_unsetup(void) | ||||
| { | ||||
| 	free_page((unsigned long)vmx_msr_bitmap_legacy_x2apic); | ||||
| 	free_page((unsigned long)vmx_msr_bitmap_longmode_x2apic); | ||||
| 	free_page((unsigned long)vmx_msr_bitmap_legacy); | ||||
| 	free_page((unsigned long)vmx_msr_bitmap_longmode); | ||||
| 	free_page((unsigned long)vmx_io_bitmap_b); | ||||
| 	free_page((unsigned long)vmx_io_bitmap_a); | ||||
| 	free_page((unsigned long)vmx_vmwrite_bitmap); | ||||
| 	free_page((unsigned long)vmx_vmread_bitmap); | ||||
| 
 | ||||
| 	free_kvm_area(); | ||||
| } | ||||
| 
 | ||||
| @ -9187,150 +9315,21 @@ static struct kvm_x86_ops vmx_x86_ops = { | ||||
| 
 | ||||
| static int __init vmx_init(void) | ||||
| { | ||||
| 	int r, i, msr; | ||||
| 
 | ||||
| 	rdmsrl_safe(MSR_EFER, &host_efer); | ||||
| 
 | ||||
| 	for (i = 0; i < ARRAY_SIZE(vmx_msr_index); ++i) | ||||
| 		kvm_define_shared_msr(i, vmx_msr_index[i]); | ||||
| 
 | ||||
| 	vmx_io_bitmap_a = (unsigned long *)__get_free_page(GFP_KERNEL); | ||||
| 	if (!vmx_io_bitmap_a) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	r = -ENOMEM; | ||||
| 
 | ||||
| 	vmx_io_bitmap_b = (unsigned long *)__get_free_page(GFP_KERNEL); | ||||
| 	if (!vmx_io_bitmap_b) | ||||
| 		goto out; | ||||
| 
 | ||||
| 	vmx_msr_bitmap_legacy = (unsigned long *)__get_free_page(GFP_KERNEL); | ||||
| 	if (!vmx_msr_bitmap_legacy) | ||||
| 		goto out1; | ||||
| 
 | ||||
| 	vmx_msr_bitmap_legacy_x2apic = | ||||
| 				(unsigned long *)__get_free_page(GFP_KERNEL); | ||||
| 	if (!vmx_msr_bitmap_legacy_x2apic) | ||||
| 		goto out2; | ||||
| 
 | ||||
| 	vmx_msr_bitmap_longmode = (unsigned long *)__get_free_page(GFP_KERNEL); | ||||
| 	if (!vmx_msr_bitmap_longmode) | ||||
| 		goto out3; | ||||
| 
 | ||||
| 	vmx_msr_bitmap_longmode_x2apic = | ||||
| 				(unsigned long *)__get_free_page(GFP_KERNEL); | ||||
| 	if (!vmx_msr_bitmap_longmode_x2apic) | ||||
| 		goto out4; | ||||
| 	vmx_vmread_bitmap = (unsigned long *)__get_free_page(GFP_KERNEL); | ||||
| 	if (!vmx_vmread_bitmap) | ||||
| 		goto out5; | ||||
| 
 | ||||
| 	vmx_vmwrite_bitmap = (unsigned long *)__get_free_page(GFP_KERNEL); | ||||
| 	if (!vmx_vmwrite_bitmap) | ||||
| 		goto out6; | ||||
| 
 | ||||
| 	memset(vmx_vmread_bitmap, 0xff, PAGE_SIZE); | ||||
| 	memset(vmx_vmwrite_bitmap, 0xff, PAGE_SIZE); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Allow direct access to the PC debug port (it is often used for I/O | ||||
| 	 * delays, but the vmexits simply slow things down). | ||||
| 	 */ | ||||
| 	memset(vmx_io_bitmap_a, 0xff, PAGE_SIZE); | ||||
| 	clear_bit(0x80, vmx_io_bitmap_a); | ||||
| 
 | ||||
| 	memset(vmx_io_bitmap_b, 0xff, PAGE_SIZE); | ||||
| 
 | ||||
| 	memset(vmx_msr_bitmap_legacy, 0xff, PAGE_SIZE); | ||||
| 	memset(vmx_msr_bitmap_longmode, 0xff, PAGE_SIZE); | ||||
| 
 | ||||
| 	set_bit(0, vmx_vpid_bitmap); /* 0 is reserved for host */ | ||||
| 
 | ||||
| 	r = kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx), | ||||
| 		     __alignof__(struct vcpu_vmx), THIS_MODULE); | ||||
| 	int r = kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx), | ||||
|                      __alignof__(struct vcpu_vmx), THIS_MODULE); | ||||
| 	if (r) | ||||
| 		goto out7; | ||||
| 		return r; | ||||
| 
 | ||||
| #ifdef CONFIG_KEXEC | ||||
| 	rcu_assign_pointer(crash_vmclear_loaded_vmcss, | ||||
| 			   crash_vmclear_local_loaded_vmcss); | ||||
| #endif | ||||
| 
 | ||||
| 	vmx_disable_intercept_for_msr(MSR_FS_BASE, false); | ||||
| 	vmx_disable_intercept_for_msr(MSR_GS_BASE, false); | ||||
| 	vmx_disable_intercept_for_msr(MSR_KERNEL_GS_BASE, true); | ||||
| 	vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_CS, false); | ||||
| 	vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_ESP, false); | ||||
| 	vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP, false); | ||||
| 	vmx_disable_intercept_for_msr(MSR_IA32_BNDCFGS, true); | ||||
| 
 | ||||
| 	memcpy(vmx_msr_bitmap_legacy_x2apic, | ||||
| 			vmx_msr_bitmap_legacy, PAGE_SIZE); | ||||
| 	memcpy(vmx_msr_bitmap_longmode_x2apic, | ||||
| 			vmx_msr_bitmap_longmode, PAGE_SIZE); | ||||
| 
 | ||||
| 	if (enable_apicv) { | ||||
| 		for (msr = 0x800; msr <= 0x8ff; msr++) | ||||
| 			vmx_disable_intercept_msr_read_x2apic(msr); | ||||
| 
 | ||||
| 		/* According SDM, in x2apic mode, the whole id reg is used.
 | ||||
| 		 * But in KVM, it only use the highest eight bits. Need to | ||||
| 		 * intercept it */ | ||||
| 		vmx_enable_intercept_msr_read_x2apic(0x802); | ||||
| 		/* TMCCT */ | ||||
| 		vmx_enable_intercept_msr_read_x2apic(0x839); | ||||
| 		/* TPR */ | ||||
| 		vmx_disable_intercept_msr_write_x2apic(0x808); | ||||
| 		/* EOI */ | ||||
| 		vmx_disable_intercept_msr_write_x2apic(0x80b); | ||||
| 		/* SELF-IPI */ | ||||
| 		vmx_disable_intercept_msr_write_x2apic(0x83f); | ||||
| 	} | ||||
| 
 | ||||
| 	if (enable_ept) { | ||||
| 		kvm_mmu_set_mask_ptes(0ull, | ||||
| 			(enable_ept_ad_bits) ? VMX_EPT_ACCESS_BIT : 0ull, | ||||
| 			(enable_ept_ad_bits) ? VMX_EPT_DIRTY_BIT : 0ull, | ||||
| 			0ull, VMX_EPT_EXECUTABLE_MASK); | ||||
| 		ept_set_mmio_spte_mask(); | ||||
| 		kvm_enable_tdp(); | ||||
| 	} else | ||||
| 		kvm_disable_tdp(); | ||||
| 
 | ||||
| 	update_ple_window_actual_max(); | ||||
| 
 | ||||
| 	return 0; | ||||
| 
 | ||||
| out7: | ||||
| 	free_page((unsigned long)vmx_vmwrite_bitmap); | ||||
| out6: | ||||
| 	free_page((unsigned long)vmx_vmread_bitmap); | ||||
| out5: | ||||
| 	free_page((unsigned long)vmx_msr_bitmap_longmode_x2apic); | ||||
| out4: | ||||
| 	free_page((unsigned long)vmx_msr_bitmap_longmode); | ||||
| out3: | ||||
| 	free_page((unsigned long)vmx_msr_bitmap_legacy_x2apic); | ||||
| out2: | ||||
| 	free_page((unsigned long)vmx_msr_bitmap_legacy); | ||||
| out1: | ||||
| 	free_page((unsigned long)vmx_io_bitmap_b); | ||||
| out: | ||||
| 	free_page((unsigned long)vmx_io_bitmap_a); | ||||
| 	return r; | ||||
| } | ||||
| 
 | ||||
| static void __exit vmx_exit(void) | ||||
| { | ||||
| 	free_page((unsigned long)vmx_msr_bitmap_legacy_x2apic); | ||||
| 	free_page((unsigned long)vmx_msr_bitmap_longmode_x2apic); | ||||
| 	free_page((unsigned long)vmx_msr_bitmap_legacy); | ||||
| 	free_page((unsigned long)vmx_msr_bitmap_longmode); | ||||
| 	free_page((unsigned long)vmx_io_bitmap_b); | ||||
| 	free_page((unsigned long)vmx_io_bitmap_a); | ||||
| 	free_page((unsigned long)vmx_vmwrite_bitmap); | ||||
| 	free_page((unsigned long)vmx_vmread_bitmap); | ||||
| 
 | ||||
| #ifdef CONFIG_KEXEC | ||||
| 	RCU_INIT_POINTER(crash_vmclear_loaded_vmcss, NULL); | ||||
| 	synchronize_rcu(); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user