aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAbel Gordon <abelg@il.ibm.com>2013-04-18 07:36:25 -0400
committerGleb Natapov <gleb@redhat.com>2013-04-22 03:51:44 -0400
commit20b97feaf615da2c43361e1dda7efd068a4446ef (patch)
tree74976cbba36be27a16cfd8b13ccc7fe17b6abf4c
parent4607c2d7a2ee90707de2b3b37e4d9156e05cdf29 (diff)
KVM: nVMX: Refactor handle_vmwrite
Refactor existent code so we re-use vmcs12_write_any to copy fields from the shadow vmcs specified by the link pointer (used by the processor, implementation-specific) to the VMCS12 software format used by L0 to hold the fields in L1 memory address space. Signed-off-by: Abel Gordon <abelg@il.ibm.com> Reviewed-by: Orit Wasserman <owasserm@redhat.com> Signed-off-by: Gleb Natapov <gleb@redhat.com>
-rw-r--r--arch/x86/kvm/vmx.c52
1 files changed, 28 insertions, 24 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 7dc599630430..1ee63cae82cd 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -5842,6 +5842,33 @@ static inline bool vmcs12_read_any(struct kvm_vcpu *vcpu,
5842 } 5842 }
5843} 5843}
5844 5844
5845
5846static inline bool vmcs12_write_any(struct kvm_vcpu *vcpu,
5847 unsigned long field, u64 field_value){
5848 short offset = vmcs_field_to_offset(field);
5849 char *p = ((char *) get_vmcs12(vcpu)) + offset;
5850 if (offset < 0)
5851 return false;
5852
5853 switch (vmcs_field_type(field)) {
5854 case VMCS_FIELD_TYPE_U16:
5855 *(u16 *)p = field_value;
5856 return true;
5857 case VMCS_FIELD_TYPE_U32:
5858 *(u32 *)p = field_value;
5859 return true;
5860 case VMCS_FIELD_TYPE_U64:
5861 *(u64 *)p = field_value;
5862 return true;
5863 case VMCS_FIELD_TYPE_NATURAL_WIDTH:
5864 *(natural_width *)p = field_value;
5865 return true;
5866 default:
5867 return false; /* can never happen. */
5868 }
5869
5870}
5871
5845/* 5872/*
5846 * VMX instructions which assume a current vmcs12 (i.e., that VMPTRLD was 5873 * VMX instructions which assume a current vmcs12 (i.e., that VMPTRLD was
5847 * used before) all generate the same failure when it is missing. 5874 * used before) all generate the same failure when it is missing.
@@ -5906,8 +5933,6 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu)
5906 gva_t gva; 5933 gva_t gva;
5907 unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION); 5934 unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
5908 u32 vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO); 5935 u32 vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
5909 char *p;
5910 short offset;
5911 /* The value to write might be 32 or 64 bits, depending on L1's long 5936 /* The value to write might be 32 or 64 bits, depending on L1's long
5912 * mode, and eventually we need to write that into a field of several 5937 * mode, and eventually we need to write that into a field of several
5913 * possible lengths. The code below first zero-extends the value to 64 5938 * possible lengths. The code below first zero-extends the value to 64
@@ -5944,28 +5969,7 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu)
5944 return 1; 5969 return 1;
5945 } 5970 }
5946 5971
5947 offset = vmcs_field_to_offset(field); 5972 if (!vmcs12_write_any(vcpu, field, field_value)) {
5948 if (offset < 0) {
5949 nested_vmx_failValid(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT);
5950 skip_emulated_instruction(vcpu);
5951 return 1;
5952 }
5953 p = ((char *) get_vmcs12(vcpu)) + offset;
5954
5955 switch (vmcs_field_type(field)) {
5956 case VMCS_FIELD_TYPE_U16:
5957 *(u16 *)p = field_value;
5958 break;
5959 case VMCS_FIELD_TYPE_U32:
5960 *(u32 *)p = field_value;
5961 break;
5962 case VMCS_FIELD_TYPE_U64:
5963 *(u64 *)p = field_value;
5964 break;
5965 case VMCS_FIELD_TYPE_NATURAL_WIDTH:
5966 *(natural_width *)p = field_value;
5967 break;
5968 default:
5969 nested_vmx_failValid(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT); 5973 nested_vmx_failValid(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT);
5970 skip_emulated_instruction(vcpu); 5974 skip_emulated_instruction(vcpu);
5971 return 1; 5975 return 1;