From patchwork Wed Sep 30 13:32:09 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: oritw@il.ibm.com X-Patchwork-Id: 50699 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n8UDWlQ2008695 for ; Wed, 30 Sep 2009 13:32:47 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754289AbZI3Ncl (ORCPT ); Wed, 30 Sep 2009 09:32:41 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1754285AbZI3Ncl (ORCPT ); Wed, 30 Sep 2009 09:32:41 -0400 Received: from mtagate3.uk.ibm.com ([195.212.29.136]:56776 "EHLO mtagate3.uk.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754270AbZI3Nck (ORCPT ); Wed, 30 Sep 2009 09:32:40 -0400 Received: from d06nrmr1407.portsmouth.uk.ibm.com (d06nrmr1407.portsmouth.uk.ibm.com [9.149.38.185]) by mtagate3.uk.ibm.com (8.14.3/8.13.8) with ESMTP id n8UDWTnA584874 for ; Wed, 30 Sep 2009 13:32:34 GMT Received: from d06av02.portsmouth.uk.ibm.com (d06av02.portsmouth.uk.ibm.com [9.149.37.228]) by d06nrmr1407.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id n8UDWIvZ1851570 for ; Wed, 30 Sep 2009 14:32:18 +0100 Received: from d06av02.portsmouth.uk.ibm.com (loopback [127.0.0.1]) by d06av02.portsmouth.uk.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id n8UDWIrc005336 for ; Wed, 30 Sep 2009 14:32:18 +0100 Received: from localhost.localdomain (cluwyn.haifa.ibm.com [9.148.27.75]) by d06av02.portsmouth.uk.ibm.com (8.12.11.20060308/8.12.11) with ESMTP id n8UDWD9S005118; Wed, 30 Sep 2009 14:32:16 +0100 From: oritw@il.ibm.com To: kvm@vger.kernel.org Cc: oritw@il.ibm.com, benami@il.ibm.com, abelg@il.ibm.com, muli@il.ibm.com, aliguori@us.ibm.com, -mday@us.ibm.com Subject: [PATCH 2/5] Nested VMX patch 2 implements vmclear Date: Wed, 30 Sep 2009 15:32:09 +0200 Message-Id: <1254317532-26123-3-git-send-email-oritw@il.ibm.com> X-Mailer: git-send-email 1.6.0.4 In-Reply-To: <1254317532-26123-2-git-send-email-oritw@il.ibm.com> References: <1254317532-26123-1-git-send-email-oritw@il.ibm.com> <1254317532-26123-2-git-send-email-oritw@il.ibm.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 71bd91a..411cbdb 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -61,15 +61,26 @@ module_param_named(unrestricted_guest, static int __read_mostly emulate_invalid_guest_state = 0; module_param(emulate_invalid_guest_state, bool, S_IRUGO); -struct vmcs { - u32 revision_id; - u32 abort; - char data[0]; +struct __attribute__ ((__packed__)) level_state { + /* Has the level1 guest done vmclear? */ + bool vmclear; }; struct nested_vmx { /* Has the level1 guest done vmxon? */ bool vmxon; + + /* + * Level 2 state : includes vmcs,registers and + * a copy of vmcs12 for vmread/vmwrite + */ + struct level_state *l2_state; +}; + +struct vmcs { + u32 revision_id; + u32 abort; + char data[0]; }; struct vcpu_vmx { @@ -186,6 +197,8 @@ static struct kvm_vmx_segment_field { static void ept_save_pdptrs(struct kvm_vcpu *vcpu); +static int create_l2_state(struct kvm_vcpu *vcpu); + /* * Keep MSR_K6_STAR at the end, as setup_msrs() will try to optimize it * away by decrementing the array size. @@ -1293,6 +1306,30 @@ static void vmclear_local_vcpus(void) __vcpu_clear(vmx); } +struct level_state *create_state(void) +{ + struct level_state *state = NULL; + + state = kzalloc(sizeof(struct level_state), GFP_KERNEL); + if (!state) { + printk(KERN_INFO "Error create level state\n"); + return NULL; + } + return state; +} + +int create_l2_state(struct kvm_vcpu *vcpu) +{ + struct vcpu_vmx *vmx = to_vmx(vcpu); + + if (!vmx->nested.l2_state) { + vmx->nested.l2_state = create_state(); + if (!vmx->nested.l2_state) + return -ENOMEM; + } + + return 0; +} /* Just like cpu_vmxoff(), but with the __kvm_handle_fault_on_reboot() * tricks. @@ -3261,6 +3298,27 @@ static int handle_vmx_insn(struct kvm_vcpu *vcpu) return 1; } +static void clear_rflags_cf_zf(struct kvm_vcpu *vcpu) +{ + unsigned long rflags; + rflags = vmx_get_rflags(vcpu); + rflags &= ~(X86_EFLAGS_CF | X86_EFLAGS_ZF); + vmx_set_rflags(vcpu, rflags); +} + +static int handle_vmclear(struct kvm_vcpu *vcpu) +{ + if (!nested_vmx_check_permission(vcpu)) + return 1; + + to_vmx(vcpu)->nested.l2_state->vmclear = 1; + + skip_emulated_instruction(vcpu); + clear_rflags_cf_zf(vcpu); + + return 1; +} + static int handle_vmoff(struct kvm_vcpu *vcpu) { struct vcpu_vmx *vmx = to_vmx(vcpu); @@ -3310,6 +3368,8 @@ static int handle_vmon(struct kvm_vcpu *vcpu) vmx->nested.vmxon = 1; + create_l2_state(vcpu); + skip_emulated_instruction(vcpu); return 1; } @@ -3582,7 +3642,7 @@ static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = { [EXIT_REASON_HLT] = handle_halt, [EXIT_REASON_INVLPG] = handle_invlpg, [EXIT_REASON_VMCALL] = handle_vmcall, - [EXIT_REASON_VMCLEAR] = handle_vmx_insn, + [EXIT_REASON_VMCLEAR] = handle_vmclear, [EXIT_REASON_VMLAUNCH] = handle_vmx_insn, [EXIT_REASON_VMPTRLD] = handle_vmx_insn, [EXIT_REASON_VMPTRST] = handle_vmx_insn,