diff options
Diffstat (limited to 'arch/x86/kvm/vmx.c')
| -rw-r--r-- | arch/x86/kvm/vmx.c | 65 | 
1 files changed, 20 insertions, 45 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index cf1b16dbc98a..5382b82462fc 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -187,6 +187,7 @@ struct vmcs {   */  struct loaded_vmcs {  	struct vmcs *vmcs; +	struct vmcs *shadow_vmcs;  	int cpu;  	int launched;  	struct list_head loaded_vmcss_on_cpu_link; @@ -411,7 +412,6 @@ struct nested_vmx {  	 * memory during VMXOFF, VMCLEAR, VMPTRLD.  	 */  	struct vmcs12 *cached_vmcs12; -	struct vmcs *current_shadow_vmcs;  	/*  	 * Indicates if the shadow vmcs must be updated with the  	 * data hold by vmcs12 @@ -421,7 +421,6 @@ struct nested_vmx {  	/* vmcs02_list cache of VMCSs recently used to run L2 guests */  	struct list_head vmcs02_pool;  	int vmcs02_num; -	u64 vmcs01_tsc_offset;  	bool change_vmcs01_virtual_x2apic_mode;  	/* L2 must run next, and mustn't decide to exit to L1. */  	bool nested_run_pending; @@ -1419,6 +1418,8 @@ static void vmcs_clear(struct vmcs *vmcs)  static inline void loaded_vmcs_init(struct loaded_vmcs *loaded_vmcs)  {  	vmcs_clear(loaded_vmcs->vmcs); +	if (loaded_vmcs->shadow_vmcs && loaded_vmcs->launched) +		vmcs_clear(loaded_vmcs->shadow_vmcs);  	loaded_vmcs->cpu = -1;  	loaded_vmcs->launched = 0;  } @@ -2605,20 +2606,6 @@ static u64 guest_read_tsc(struct kvm_vcpu *vcpu)  }  /* - * Like guest_read_tsc, but always returns L1's notion of the timestamp - * counter, even if a nested guest (L2) is currently running. - */ -static u64 vmx_read_l1_tsc(struct kvm_vcpu *vcpu, u64 host_tsc) -{ -	u64 tsc_offset; - -	tsc_offset = is_guest_mode(vcpu) ? -		to_vmx(vcpu)->nested.vmcs01_tsc_offset : -		vmcs_read64(TSC_OFFSET); -	return host_tsc + tsc_offset; -} - -/*   * writes 'offset' into guest's timestamp counter offset register   */  static void vmx_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset) @@ -2631,7 +2618,6 @@ static void vmx_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)  		 * to the newly set TSC to get L2's TSC.  		 */  		struct vmcs12 *vmcs12; -		to_vmx(vcpu)->nested.vmcs01_tsc_offset = offset;  		/* recalculate vmcs02.TSC_OFFSET: */  		vmcs12 = get_vmcs12(vcpu);  		vmcs_write64(TSC_OFFSET, offset + @@ -2644,19 +2630,6 @@ static void vmx_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)  	}  } -static void vmx_adjust_tsc_offset_guest(struct kvm_vcpu *vcpu, s64 adjustment) -{ -	u64 offset = vmcs_read64(TSC_OFFSET); - -	vmcs_write64(TSC_OFFSET, offset + adjustment); -	if (is_guest_mode(vcpu)) { -		/* Even when running L2, the adjustment needs to apply to L1 */ -		to_vmx(vcpu)->nested.vmcs01_tsc_offset += adjustment; -	} else -		trace_kvm_write_tsc_offset(vcpu->vcpu_id, offset, -					   offset + adjustment); -} -  static bool guest_cpuid_has_vmx(struct kvm_vcpu *vcpu)  {  	struct kvm_cpuid_entry2 *best = kvm_find_cpuid_entry(vcpu, 1, 0); @@ -3562,6 +3535,7 @@ static void free_loaded_vmcs(struct loaded_vmcs *loaded_vmcs)  	loaded_vmcs_clear(loaded_vmcs);  	free_vmcs(loaded_vmcs->vmcs);  	loaded_vmcs->vmcs = NULL; +	WARN_ON(loaded_vmcs->shadow_vmcs != NULL);  }  static void free_kvm_area(void) @@ -6696,6 +6670,7 @@ static struct loaded_vmcs *nested_get_current_vmcs02(struct vcpu_vmx *vmx)  	if (!item)  		return NULL;  	item->vmcs02.vmcs = alloc_vmcs(); +	item->vmcs02.shadow_vmcs = NULL;  	if (!item->vmcs02.vmcs) {  		kfree(item);  		return NULL; @@ -7072,7 +7047,7 @@ static int handle_vmon(struct kvm_vcpu *vcpu)  		shadow_vmcs->revision_id |= (1u << 31);  		/* init shadow vmcs */  		vmcs_clear(shadow_vmcs); -		vmx->nested.current_shadow_vmcs = shadow_vmcs; +		vmx->vmcs01.shadow_vmcs = shadow_vmcs;  	}  	INIT_LIST_HEAD(&(vmx->nested.vmcs02_pool)); @@ -7174,8 +7149,11 @@ static void free_nested(struct vcpu_vmx *vmx)  		free_page((unsigned long)vmx->nested.msr_bitmap);  		vmx->nested.msr_bitmap = NULL;  	} -	if (enable_shadow_vmcs) -		free_vmcs(vmx->nested.current_shadow_vmcs); +	if (enable_shadow_vmcs) { +		vmcs_clear(vmx->vmcs01.shadow_vmcs); +		free_vmcs(vmx->vmcs01.shadow_vmcs); +		vmx->vmcs01.shadow_vmcs = NULL; +	}  	kfree(vmx->nested.cached_vmcs12);  	/* Unpin physical memory we referred to in current vmcs02 */  	if (vmx->nested.apic_access_page) { @@ -7352,7 +7330,7 @@ static void copy_shadow_to_vmcs12(struct vcpu_vmx *vmx)  	int i;  	unsigned long field;  	u64 field_value; -	struct vmcs *shadow_vmcs = vmx->nested.current_shadow_vmcs; +	struct vmcs *shadow_vmcs = vmx->vmcs01.shadow_vmcs;  	const unsigned long *fields = shadow_read_write_fields;  	const int num_fields = max_shadow_read_write_fields; @@ -7401,7 +7379,7 @@ static void copy_vmcs12_to_shadow(struct vcpu_vmx *vmx)  	int i, q;  	unsigned long field;  	u64 field_value = 0; -	struct vmcs *shadow_vmcs = vmx->nested.current_shadow_vmcs; +	struct vmcs *shadow_vmcs = vmx->vmcs01.shadow_vmcs;  	vmcs_load(shadow_vmcs); @@ -7591,7 +7569,7 @@ static int handle_vmptrld(struct kvm_vcpu *vcpu)  			vmcs_set_bits(SECONDARY_VM_EXEC_CONTROL,  				      SECONDARY_EXEC_SHADOW_VMCS);  			vmcs_write64(VMCS_LINK_POINTER, -				     __pa(vmx->nested.current_shadow_vmcs)); +				     __pa(vmx->vmcs01.shadow_vmcs));  			vmx->nested.sync_shadow_vmcs = true;  		}  	} @@ -7659,7 +7637,7 @@ static int handle_invept(struct kvm_vcpu *vcpu)  	types = (vmx->nested.nested_vmx_ept_caps >> VMX_EPT_EXTENT_SHIFT) & 6; -	if (!(types & (1UL << type))) { +	if (type >= 32 || !(types & (1 << type))) {  		nested_vmx_failValid(vcpu,  				VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);  		skip_emulated_instruction(vcpu); @@ -7722,7 +7700,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)  	types = (vmx->nested.nested_vmx_vpid_caps >> 8) & 0x7; -	if (!(types & (1UL << type))) { +	if (type >= 32 || !(types & (1 << type))) {  		nested_vmx_failValid(vcpu,  			VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);  		skip_emulated_instruction(vcpu); @@ -9156,6 +9134,7 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)  	vmx->loaded_vmcs = &vmx->vmcs01;  	vmx->loaded_vmcs->vmcs = alloc_vmcs(); +	vmx->loaded_vmcs->shadow_vmcs = NULL;  	if (!vmx->loaded_vmcs->vmcs)  		goto free_msrs;  	if (!vmm_exclusive) @@ -10061,9 +10040,9 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)  	if (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETING)  		vmcs_write64(TSC_OFFSET, -			vmx->nested.vmcs01_tsc_offset + vmcs12->tsc_offset); +			vcpu->arch.tsc_offset + vmcs12->tsc_offset);  	else -		vmcs_write64(TSC_OFFSET, vmx->nested.vmcs01_tsc_offset); +		vmcs_write64(TSC_OFFSET, vcpu->arch.tsc_offset);  	if (kvm_has_tsc_control)  		decache_tsc_multiplier(vmx); @@ -10293,8 +10272,6 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)  	enter_guest_mode(vcpu); -	vmx->nested.vmcs01_tsc_offset = vmcs_read64(TSC_OFFSET); -  	if (!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS))  		vmx->nested.vmcs01_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL); @@ -10818,7 +10795,7 @@ static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason,  	load_vmcs12_host_state(vcpu, vmcs12);  	/* Update any VMCS fields that might have changed while L2 ran */ -	vmcs_write64(TSC_OFFSET, vmx->nested.vmcs01_tsc_offset); +	vmcs_write64(TSC_OFFSET, vcpu->arch.tsc_offset);  	if (vmx->hv_deadline_tsc == -1)  		vmcs_clear_bits(PIN_BASED_VM_EXEC_CONTROL,  				PIN_BASED_VMX_PREEMPTION_TIMER); @@ -11339,8 +11316,6 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {  	.has_wbinvd_exit = cpu_has_vmx_wbinvd_exit,  	.write_tsc_offset = vmx_write_tsc_offset, -	.adjust_tsc_offset_guest = vmx_adjust_tsc_offset_guest, -	.read_l1_tsc = vmx_read_l1_tsc,  	.set_tdp_cr3 = vmx_set_cr3,  | 
