From patchwork Tue Oct 13 16:06:48 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 53444 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 n9DGJhpx005889 for ; Tue, 13 Oct 2009 16:19:44 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933962AbZJMQJX (ORCPT ); Tue, 13 Oct 2009 12:09:23 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S933940AbZJMQJX (ORCPT ); Tue, 13 Oct 2009 12:09:23 -0400 Received: from goliath.siemens.de ([192.35.17.28]:15210 "EHLO goliath.siemens.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1760062AbZJMQJS (ORCPT ); Tue, 13 Oct 2009 12:09:18 -0400 Received: from mail3.siemens.de (localhost [127.0.0.1]) by goliath.siemens.de (8.12.11.20060308/8.12.11) with ESMTP id n9DG8Ssi017607; Tue, 13 Oct 2009 18:08:28 +0200 Received: from [139.25.109.167] (mchn012c.mchp.siemens.de [139.25.109.167] (may be forged)) by mail3.siemens.de (8.12.11.20060308/8.12.11) with ESMTP id n9DG8SbX015666; Tue, 13 Oct 2009 18:08:28 +0200 From: Jan Kiszka Subject: [PATCH 4/4] KVM: x86: Add VCPU substate for NMI states To: Avi Kivity , Marcelo Tosatti Cc: kvm@vger.kernel.org Date: Tue, 13 Oct 2009 18:06:48 +0200 Message-ID: <20091013160648.27006.29041.stgit@mchn012c.ww002.siemens.net> In-Reply-To: <20091013160647.27006.58598.stgit@mchn012c.ww002.siemens.net> References: <20091013160647.27006.58598.stgit@mchn012c.ww002.siemens.net> User-Agent: StGIT/0.14.3 MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org diff --git a/arch/x86/include/asm/kvm.h b/arch/x86/include/asm/kvm.h index 1b184c3..fd5713a 100644 --- a/arch/x86/include/asm/kvm.h +++ b/arch/x86/include/asm/kvm.h @@ -256,5 +256,12 @@ struct kvm_reinject_control { #define KVM_X86_VCPU_MSRS 1000 #define KVM_X86_VCPU_CPUID 1001 #define KVM_X86_VCPU_LAPIC 1002 +#define KVM_X86_VCPU_NMI 1003 + +struct kvm_nmi_state { + __u8 pending; + __u8 masked; + __u8 pad1[2]; +}; #endif /* _ASM_X86_KVM_H */ diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 179a919..d22a0cd 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -513,6 +513,8 @@ struct kvm_x86_ops { unsigned char *hypercall_addr); void (*set_irq)(struct kvm_vcpu *vcpu); void (*set_nmi)(struct kvm_vcpu *vcpu); + int (*get_nmi_mask)(struct kvm_vcpu *vcpu); + void (*set_nmi_mask)(struct kvm_vcpu *vcpu, int masked); void (*queue_exception)(struct kvm_vcpu *vcpu, unsigned nr, bool has_error_code, u32 error_code); int (*interrupt_allowed)(struct kvm_vcpu *vcpu); diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 279a2ae..67ff5f1 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -2456,6 +2456,26 @@ static int svm_nmi_allowed(struct kvm_vcpu *vcpu) !(svm->vcpu.arch.hflags & HF_NMI_MASK); } +static int svm_get_nmi_mask(struct kvm_vcpu *vcpu) +{ + struct vcpu_svm *svm = to_svm(vcpu); + + return !!(svm->vcpu.arch.hflags & HF_NMI_MASK); +} + +static void svm_set_nmi_mask(struct kvm_vcpu *vcpu, int masked) +{ + struct vcpu_svm *svm = to_svm(vcpu); + + if (masked) { + svm->vcpu.arch.hflags |= HF_NMI_MASK; + svm->vmcb->control.intercept |= (1UL << INTERCEPT_IRET); + } else { + svm->vcpu.arch.hflags &= ~HF_NMI_MASK; + svm->vmcb->control.intercept &= ~(1UL << INTERCEPT_IRET); + } +} + static int svm_interrupt_allowed(struct kvm_vcpu *vcpu) { struct vcpu_svm *svm = to_svm(vcpu); @@ -2897,6 +2917,8 @@ static struct kvm_x86_ops svm_x86_ops = { .queue_exception = svm_queue_exception, .interrupt_allowed = svm_interrupt_allowed, .nmi_allowed = svm_nmi_allowed, + .get_nmi_mask = svm_get_nmi_mask, + .set_nmi_mask = svm_set_nmi_mask, .enable_nmi_window = enable_nmi_window, .enable_irq_window = enable_irq_window, .update_cr8_intercept = update_cr8_intercept, diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 70020e5..5dd766b 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -2619,6 +2619,34 @@ static int vmx_nmi_allowed(struct kvm_vcpu *vcpu) GUEST_INTR_STATE_NMI)); } +static int vmx_get_nmi_mask(struct kvm_vcpu *vcpu) +{ + if (!cpu_has_virtual_nmis()) + return to_vmx(vcpu)->soft_vnmi_blocked; + else + return !!(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & + GUEST_INTR_STATE_NMI); +} + +static void vmx_set_nmi_mask(struct kvm_vcpu *vcpu, int masked) +{ + struct vcpu_vmx *vmx = to_vmx(vcpu); + + if (!cpu_has_virtual_nmis()) { + if (vmx->soft_vnmi_blocked != masked) { + vmx->soft_vnmi_blocked = masked; + vmx->vnmi_blocked_time = 0; + } + } else { + if (masked) + vmcs_set_bits(GUEST_INTERRUPTIBILITY_INFO, + GUEST_INTR_STATE_NMI); + else + vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO, + GUEST_INTR_STATE_NMI); + } +} + static int vmx_interrupt_allowed(struct kvm_vcpu *vcpu) { return (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) && @@ -3957,6 +3985,8 @@ static struct kvm_x86_ops vmx_x86_ops = { .queue_exception = vmx_queue_exception, .interrupt_allowed = vmx_interrupt_allowed, .nmi_allowed = vmx_nmi_allowed, + .get_nmi_mask = vmx_get_nmi_mask, + .set_nmi_mask = vmx_set_nmi_mask, .enable_nmi_window = enable_nmi_window, .enable_irq_window = enable_irq_window, .update_cr8_intercept = update_cr8_intercept, diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 733e2d3..a06fd4d 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4674,6 +4674,19 @@ out_free_lapic: kfree(lapic); break; } + case KVM_X86_VCPU_NMI: { + struct kvm_nmi_state nmi; + + vcpu_load(vcpu); + nmi.pending = vcpu->arch.nmi_pending; + nmi.masked = kvm_x86_ops->get_nmi_mask(vcpu); + vcpu_put(vcpu); + r = -EFAULT; + if (copy_to_user(argp, &nmi, sizeof(struct kvm_nmi_state))) + break; + r = 0; + break; + } default: r = -EINVAL; } @@ -4721,6 +4734,19 @@ out_free_lapic: kfree(lapic); break; } + case KVM_X86_VCPU_NMI: { + struct kvm_nmi_state nmi; + + r = -EFAULT; + if (copy_from_user(&nmi, argp, sizeof(struct kvm_nmi_state))) + break; + vcpu_load(vcpu); + vcpu->arch.nmi_pending = nmi.pending; + kvm_x86_ops->set_nmi_mask(vcpu, nmi.masked); + vcpu_put(vcpu); + r = 0; + break; + } default: r = -EINVAL; }