From patchwork Thu May 6 08:45:43 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Xu, Dongxiao" X-Patchwork-Id: 97292 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o469wiiC017208 for ; Thu, 6 May 2010 10:02:00 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756495Ab0EFIqu (ORCPT ); Thu, 6 May 2010 04:46:50 -0400 Received: from mga01.intel.com ([192.55.52.88]:27712 "EHLO mga01.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756123Ab0EFIqs convert rfc822-to-8bit (ORCPT ); Thu, 6 May 2010 04:46:48 -0400 Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga101.fm.intel.com with ESMTP; 06 May 2010 01:44:35 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.52,339,1270450800"; d="scan'208";a="564687084" Received: from pgsmsx603.gar.corp.intel.com ([10.221.43.87]) by fmsmga002.fm.intel.com with ESMTP; 06 May 2010 01:46:07 -0700 Received: from shsmsx602.ccr.corp.intel.com (10.239.4.104) by pgsmsx603.gar.corp.intel.com (10.221.43.87) with Microsoft SMTP Server (TLS) id 8.2.176.0; Thu, 6 May 2010 16:45:30 +0800 Received: from shsmsx501.ccr.corp.intel.com ([10.239.4.141]) by SHSMSX602.ccr.corp.intel.com ([10.239.4.104]) with mapi; Thu, 6 May 2010 16:45:29 +0800 From: "Xu, Dongxiao" To: "kvm@vger.kernel.org" CC: Avi Kivity , Marcelo Tosatti , Alexander Graf Date: Thu, 6 May 2010 16:45:43 +0800 Subject: [PATCH 2/3 v2] KVM: VMX: VMCLEAR/VMPTRLD usage changes. Thread-Topic: [PATCH 2/3 v2] KVM: VMX: VMCLEAR/VMPTRLD usage changes. Thread-Index: Acrs+IN1dQYdyyJXQ+m8wl3yNWZ88Q== Message-ID: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: acceptlanguage: en-US MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Thu, 06 May 2010 10:02:04 +0000 (UTC) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index e77da89..aa3b2f9 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -62,6 +62,9 @@ module_param_named(unrestricted_guest, static int __read_mostly emulate_invalid_guest_state = 0; module_param(emulate_invalid_guest_state, bool, S_IRUGO); +static int __read_mostly vmm_coexistence; +module_param(vmm_coexistence, bool, S_IRUGO); + #define KVM_GUEST_CR0_MASK_UNRESTRICTED_GUEST \ (X86_CR0_WP | X86_CR0_NE | X86_CR0_NW | X86_CR0_CD) #define KVM_GUEST_CR0_MASK \ @@ -222,6 +225,7 @@ static u64 host_efer; static void ept_save_pdptrs(struct kvm_vcpu *vcpu); +static void vmx_flush_tlb(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. @@ -784,25 +788,31 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu) struct vcpu_vmx *vmx = to_vmx(vcpu); u64 tsc_this, delta, new_offset; - if (vcpu->cpu != cpu) { - vcpu_clear(vmx); - kvm_migrate_timers(vcpu); + if (vmm_coexistence) { + vmcs_load(vmx->vmcs); set_bit(KVM_REQ_TLB_FLUSH, &vcpu->requests); - local_irq_disable(); - list_add(&vmx->local_vcpus_link, - &per_cpu(vcpus_on_cpu, cpu)); - local_irq_enable(); - } + } else { + if (vcpu->cpu != cpu) { + vcpu_clear(vmx); + set_bit(KVM_REQ_TLB_FLUSH, &vcpu->requests); + local_irq_disable(); + list_add(&vmx->local_vcpus_link, + &per_cpu(vcpus_on_cpu, cpu)); + local_irq_enable(); + } - if (per_cpu(current_vmcs, cpu) != vmx->vmcs) { - per_cpu(current_vmcs, cpu) = vmx->vmcs; - vmcs_load(vmx->vmcs); + if (per_cpu(current_vmcs, cpu) != vmx->vmcs) { + per_cpu(current_vmcs, cpu) = vmx->vmcs; + vmcs_load(vmx->vmcs); + } } if (vcpu->cpu != cpu) { struct desc_ptr dt; unsigned long sysenter_esp; + kvm_migrate_timers(vcpu); + vcpu->cpu = cpu; /* * Linux uses per-cpu TSS and GDT, so set these when switching @@ -829,7 +839,14 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu) static void vmx_vcpu_put(struct kvm_vcpu *vcpu) { + struct vcpu_vmx *vmx = to_vmx(vcpu); + __vmx_load_host_state(to_vmx(vcpu)); + if (vmm_coexistence) { + vmcs_clear(vmx->vmcs); + rdtscll(vmx->vcpu.arch.host_tsc); + vmx->launched = 0; + } } static void vmx_fpu_activate(struct kvm_vcpu *vcpu) @@ -1280,7 +1297,8 @@ static void kvm_cpu_vmxoff(void) static void hardware_disable(void *garbage) { - vmclear_local_vcpus(); + if (!vmm_coexistence) + vmclear_local_vcpus(); kvm_cpu_vmxoff(); write_cr4(read_cr4() & ~X86_CR4_VMXE); } @@ -3927,7 +3945,8 @@ static void vmx_free_vmcs(struct kvm_vcpu *vcpu) struct vcpu_vmx *vmx = to_vmx(vcpu); if (vmx->vmcs) { - vcpu_clear(vmx); + if (!vmm_coexistence) + vcpu_clear(vmx); free_vmcs(vmx->vmcs); vmx->vmcs = NULL; } @@ -3969,13 +3988,20 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id) if (!vmx->vmcs) goto free_msrs; - vmcs_clear(vmx->vmcs); - - cpu = get_cpu(); - vmx_vcpu_load(&vmx->vcpu, cpu); - err = vmx_vcpu_setup(vmx); - vmx_vcpu_put(&vmx->vcpu); - put_cpu(); + if (vmm_coexistence) { + preempt_disable(); + vmcs_load(vmx->vmcs); + err = vmx_vcpu_setup(vmx); + vmcs_clear(vmx->vmcs); + preempt_enable(); + } else { + vmcs_clear(vmx->vmcs); + cpu = get_cpu(); + vmx_vcpu_load(&vmx->vcpu, cpu); + err = vmx_vcpu_setup(vmx); + vmx_vcpu_put(&vmx->vcpu); + put_cpu(); + } if (err) goto free_vmcs; if (vm_need_virtualize_apic_accesses(kvm)) @@ -4116,6 +4142,8 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu) vmx->rdtscp_enabled = false; if (vmx_rdtscp_supported()) { + if (vmm_coexistence) + vmcs_load(vmx->vmcs); exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL); if (exec_control & SECONDARY_EXEC_RDTSCP) { best = kvm_find_cpuid_entry(vcpu, 0x80000001, 0); @@ -4127,6 +4155,8 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu) exec_control); } } + if (vmm_coexistence) + vmcs_clear(vmx->vmcs); } }