From patchwork Thu Mar 12 17:06:51 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bernhard Kohl X-Patchwork-Id: 11426 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 n2CH78Q1007911 for ; Thu, 12 Mar 2009 17:07:09 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755148AbZCLRHI (ORCPT ); Thu, 12 Mar 2009 13:07:08 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1754936AbZCLRHH (ORCPT ); Thu, 12 Mar 2009 13:07:07 -0400 Received: from main.gmane.org ([80.91.229.2]:50824 "EHLO ciao.gmane.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754843AbZCLRHG (ORCPT ); Thu, 12 Mar 2009 13:07:06 -0400 Received: from list by ciao.gmane.org with local (Exim 4.43) id 1LhoN5-0001LU-P5 for kvm@vger.kernel.org; Thu, 12 Mar 2009 17:07:03 +0000 Received: from 192.100.130.229 ([192.100.130.229]) by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Thu, 12 Mar 2009 17:07:03 +0000 Received: from bernhard.kohl by 192.100.130.229 with local (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Thu, 12 Mar 2009 17:07:03 +0000 X-Injected-Via-Gmane: http://gmane.org/ To: kvm@vger.kernel.org From: Bernhard Kohl Subject: [PATCH] KVM: Improvements for task switching Date: Thu, 12 Mar 2009 17:06:51 +0000 (UTC) Lines: 86 Message-ID: Mime-Version: 1.0 X-Complaints-To: usenet@ger.gmane.org X-Gmane-NNTP-Posting-Host: main.gmane.org User-Agent: Loom/3.14 (http://gmane.org/) X-Loom-IP: 192.100.130.229 (Mozilla/5.0 (X11; U; Linux i686; de; rv:1.9.0.7) Gecko/2009030503 Fedora/3.0.7-1.fc10 Firefox/3.0.7) Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org NSN's proprietary OS DMX sometimes does task switches. To get it running in KVM the following changes were necessary: Interrupt injection only with interrupt flag set. Linking the tss->prev_task_link to itself removed. Task linking is required for CALL and GATE. Do not call skip_emulated_instruction() for GATE. Signed-off-by: Bernhard Kohl --- arch/x86/kvm/vmx.c | 3 ++- arch/x86/kvm/x86.c | 19 +++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) @@ -3882,10 +3895,12 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason) kvm_x86_ops->set_rflags(vcpu, eflags & ~X86_EFLAGS_NT); } - kvm_x86_ops->skip_emulated_instruction(vcpu); + if (reason != TASK_SWITCH_GATE) + kvm_x86_ops->skip_emulated_instruction(vcpu); if (nseg_desc.type & 8) ret = kvm_task_switch_32(vcpu, tss_selector, old_tss_base, + old_tss_sel, reason, &nseg_desc); else ret = kvm_task_switch_16(vcpu, tss_selector, old_tss_base, diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 5cf28df..eca57a3 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -3357,7 +3357,8 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu) enable_irq_window(vcpu); } if (vcpu->arch.interrupt.pending) { - vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr); + if (vcpu->arch.interrupt_window_open) + vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr); if (kvm_cpu_has_interrupt(vcpu)) enable_irq_window(vcpu); } diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index b556b6a..9052058 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3683,7 +3683,7 @@ static void save_state_to_tss32(struct kvm_vcpu *vcpu, tss->fs = get_segment_selector(vcpu, VCPU_SREG_FS); tss->gs = get_segment_selector(vcpu, VCPU_SREG_GS); tss->ldt_selector = get_segment_selector(vcpu, VCPU_SREG_LDTR); - tss->prev_task_link = get_segment_selector(vcpu, VCPU_SREG_TR); + tss->prev_task_link = 0; } static int load_state_from_tss32(struct kvm_vcpu *vcpu, @@ -3810,6 +3810,7 @@ out: static int kvm_task_switch_32(struct kvm_vcpu *vcpu, u16 tss_selector, u32 old_tss_base, + u16 old_tss_selector, int reason, struct desc_struct *nseg_desc) { struct tss_segment_32 tss_segment_32; @@ -3829,6 +3830,18 @@ static int kvm_task_switch_32(struct kvm_vcpu *vcpu, u16 tss_selector, &tss_segment_32, sizeof tss_segment_32)) goto out; + /* + * SDM 3: table 6-2 + * Task linking required for CALL and GATE. + */ + if (reason == TASK_SWITCH_CALL || reason == TASK_SWITCH_GATE) + { + tss_segment_32.prev_task_link = old_tss_selector; + kvm_write_guest(vcpu->kvm, get_tss_base_addr(vcpu, nseg_desc), + &tss_segment_32, sizeof(struct tss_segment_32)); + + } + if (load_state_from_tss32(vcpu, &tss_segment_32)) goto out;