From patchwork Thu Nov 22 04:51:56 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Xu, Dongxiao" X-Patchwork-Id: 1784141 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id 6DF5DE018E for ; Thu, 22 Nov 2012 18:27:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751238Ab2KVS1M (ORCPT ); Thu, 22 Nov 2012 13:27:12 -0500 Received: from mga02.intel.com ([134.134.136.20]:29772 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751864Ab2KVS1J (ORCPT ); Thu, 22 Nov 2012 13:27:09 -0500 Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP; 21 Nov 2012 21:01:12 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.83,298,1352102400"; d="scan'208";a="245658627" Received: from unknown (HELO localhost) ([10.239.36.11]) by orsmga002.jf.intel.com with ESMTP; 21 Nov 2012 21:01:11 -0800 From: Dongxiao Xu To: kvm@vger.kernel.org Cc: mtosatti@redhat.com, gleb@redhat.com Subject: [PATCH v2 1/4] nested vmx: clean up for vmcs12 read and write Date: Thu, 22 Nov 2012 12:51:56 +0800 Message-Id: <1353559919-29439-2-git-send-email-dongxiao.xu@intel.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1353559919-29439-1-git-send-email-dongxiao.xu@intel.com> References: <1353559919-29439-1-git-send-email-dongxiao.xu@intel.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org abstract vmcs12_read and vmcs12_write functions to do the vmcs12 read/write operations. Signed-off-by: Dongxiao Xu --- arch/x86/kvm/vmx.c | 85 +++++++++++++++++++++++++--------------------------- 1 files changed, 41 insertions(+), 44 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index f858159..2f8344f 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -583,10 +583,15 @@ static const unsigned short vmcs_field_to_offset_table[] = { }; static const int max_vmcs_field = ARRAY_SIZE(vmcs_field_to_offset_table); -static inline short vmcs_field_to_offset(unsigned long field) +static inline bool vmcs_field_valid(unsigned long field) { if (field >= max_vmcs_field || vmcs_field_to_offset_table[field] == 0) - return -1; + return 0; + return 1; +} + +static inline short vmcs_field_to_offset(unsigned long field) +{ return vmcs_field_to_offset_table[field]; } @@ -5407,32 +5412,45 @@ static inline int vmcs_field_readonly(unsigned long field) * some of the bits we return here (e.g., on 32-bit guests, only 32 bits of * 64-bit fields are to be returned). */ -static inline bool vmcs12_read_any(struct kvm_vcpu *vcpu, - unsigned long field, u64 *ret) +static inline u64 vmcs12_read(struct kvm_vcpu *vcpu, unsigned long field) { - short offset = vmcs_field_to_offset(field); - char *p; + char *p = ((char *)(get_vmcs12(vcpu))) + vmcs_field_to_offset(field); - if (offset < 0) - return 0; + switch (vmcs_field_type(field)) { + case VMCS_FIELD_TYPE_NATURAL_WIDTH: + return *((natural_width *)p); + case VMCS_FIELD_TYPE_U16: + return *((u16 *)p); + case VMCS_FIELD_TYPE_U32: + return *((u32 *)p); + case VMCS_FIELD_TYPE_U64: + return *((u64 *)p); + default: + return 0; /* can never happen. */ + } +} - p = ((char *)(get_vmcs12(vcpu))) + offset; +static inline void vmcs12_write(struct kvm_vcpu *vcpu, + unsigned long field, + u64 value) +{ + char *p = ((char *)(get_vmcs12(vcpu))) + vmcs_field_to_offset(field); switch (vmcs_field_type(field)) { case VMCS_FIELD_TYPE_NATURAL_WIDTH: - *ret = *((natural_width *)p); - return 1; + *(natural_width *)p = value; + break; case VMCS_FIELD_TYPE_U16: - *ret = *((u16 *)p); - return 1; + *(u16 *)p = value; + break; case VMCS_FIELD_TYPE_U32: - *ret = *((u32 *)p); - return 1; + *(u32 *)p = value; + break; case VMCS_FIELD_TYPE_U64: - *ret = *((u64 *)p); - return 1; + *(u64 *)p = value; + break; default: - return 0; /* can never happen. */ + break; /* can never happen. */ } } @@ -5465,12 +5483,13 @@ static int handle_vmread(struct kvm_vcpu *vcpu) /* Decode instruction info and find the field to read */ field = kvm_register_read(vcpu, (((vmx_instruction_info) >> 28) & 0xf)); - /* Read the field, zero-extended to a u64 field_value */ - if (!vmcs12_read_any(vcpu, field, &field_value)) { + if (!vmcs_field_valid(field)) { nested_vmx_failValid(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT); skip_emulated_instruction(vcpu); return 1; } + /* Read the field, zero-extended to a u64 field_value */ + field_value = vmcs12_read(vcpu, field); /* * Now copy part of this value to register or memory, as requested. * Note that the number of bits actually copied is 32 or 64 depending @@ -5500,8 +5519,6 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu) gva_t gva; unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION); u32 vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO); - char *p; - short offset; /* The value to write might be 32 or 64 bits, depending on L1's long * mode, and eventually we need to write that into a field of several * possible lengths. The code below first zero-extends the value to 64 @@ -5537,33 +5554,13 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu) skip_emulated_instruction(vcpu); return 1; } - - offset = vmcs_field_to_offset(field); - if (offset < 0) { + if (!vmcs_field_valid(field)) { nested_vmx_failValid(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT); skip_emulated_instruction(vcpu); return 1; } - p = ((char *) get_vmcs12(vcpu)) + offset; - switch (vmcs_field_type(field)) { - case VMCS_FIELD_TYPE_U16: - *(u16 *)p = field_value; - break; - case VMCS_FIELD_TYPE_U32: - *(u32 *)p = field_value; - break; - case VMCS_FIELD_TYPE_U64: - *(u64 *)p = field_value; - break; - case VMCS_FIELD_TYPE_NATURAL_WIDTH: - *(natural_width *)p = field_value; - break; - default: - nested_vmx_failValid(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT); - skip_emulated_instruction(vcpu); - return 1; - } + vmcs12_write(vcpu, field, field_value); nested_vmx_succeed(vcpu); skip_emulated_instruction(vcpu);