From patchwork Wed Oct 14 08:52:37 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 53628 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 n9E8vfkN005406 for ; Wed, 14 Oct 2009 08:57:41 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755402AbZJNIx2 (ORCPT ); Wed, 14 Oct 2009 04:53:28 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1755168AbZJNIx2 (ORCPT ); Wed, 14 Oct 2009 04:53:28 -0400 Received: from david.siemens.de ([192.35.17.14]:23652 "EHLO david.siemens.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754582AbZJNIx1 (ORCPT ); Wed, 14 Oct 2009 04:53:27 -0400 Received: from mail2.siemens.de (localhost [127.0.0.1]) by david.siemens.de (8.12.11.20060308/8.12.11) with ESMTP id n9E8qb7R009349; Wed, 14 Oct 2009 10:52:37 +0200 Received: from [139.25.109.167] (mchn012c.mchp.siemens.de [139.25.109.167] (may be forged)) by mail2.siemens.de (8.12.11.20060308/8.12.11) with ESMTP id n9E8qbIk006344; Wed, 14 Oct 2009 10:52:37 +0200 Message-ID: <4AD59155.5050706@siemens.com> Date: Wed, 14 Oct 2009 10:52:37 +0200 From: Jan Kiszka User-Agent: Mozilla/5.0 (X11; U; Linux i686 (x86_64); de; rv:1.8.1.12) Gecko/20080226 SUSE/2.0.0.12-1.1 Thunderbird/2.0.0.12 Mnenhy/0.7.5.666 MIME-Version: 1.0 To: Avi Kivity , Marcelo Tosatti CC: kvm@vger.kernel.org Subject: [PATCH] qemu-kvm: x86: Add support for NMI states References: <20091013160647.27006.58598.stgit@mchn012c.ww002.siemens.net> In-Reply-To: <20091013160647.27006.58598.stgit@mchn012c.ww002.siemens.net> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c index acb1b91..86fd341 100644 --- a/qemu-kvm-x86.c +++ b/qemu-kvm-x86.c @@ -901,6 +901,53 @@ static void get_seg(SegmentCache *lhs, const struct kvm_segment *rhs) | (rhs->avl * DESC_AVL_MASK); } +static void kvm_get_nmi_state(CPUState *env) +{ +#ifdef KVM_CAP_VCPU_STATE + kvm_vcpu_context_t vcpu = env->kvm_cpu_state.vcpu_ctx; + struct { + struct kvm_vcpu_state header; + struct kvm_vcpu_substate substates[1]; + } request; + struct kvm_nmi_state nmi_state; + int r; + + request.header.nsubstates = 1; + request.header.substates[0].type = KVM_X86_VCPU_NMI; + request.header.substates[0].offset = (size_t)&nmi_state - (size_t)&request; + r = ioctl(vcpu->fd, KVM_GET_VCPU_STATE, &request); + if (r == 0) { + env->nmi_pending = nmi_state.pending; + if (nmi_state.masked) { + env->hflags2 |= HF2_NMI_MASK; + } else { + env->hflags2 &= ~HF2_NMI_MASK; + } + } +#endif + env->nmi_pending = 0; + env->hflags2 &= ~HF2_NMI_MASK; +} + +static void kvm_set_nmi_state(CPUState *env) +{ +#ifdef KVM_CAP_VCPU_STATE + kvm_vcpu_context_t vcpu = env->kvm_cpu_state.vcpu_ctx; + struct { + struct kvm_vcpu_state header; + struct kvm_vcpu_substate substates[1]; + } request; + struct kvm_nmi_state nmi_state; + + request.header.nsubstates = 1; + request.header.substates[0].type = KVM_X86_VCPU_NMI; + request.header.substates[0].offset = (size_t)&nmi_state - (size_t)&request; + nmi_state.pending = env->nmi_pending; + nmi_state.masked = !!(env->hflags2 & HF2_NMI_MASK); + ioctl(vcpu->fd, KVM_SET_VCPU_STATE, &request); +#endif +} + void kvm_arch_load_regs(CPUState *env) { struct kvm_regs regs; @@ -1010,6 +1057,8 @@ void kvm_arch_load_regs(CPUState *env) rc = kvm_set_msrs(env->kvm_cpu_state.vcpu_ctx, msrs, n); if (rc == -1) perror("kvm_set_msrs FAILED"); + + kvm_set_nmi_state(env); } void kvm_load_tsc(CPUState *env) @@ -1195,6 +1244,8 @@ void kvm_arch_save_regs(CPUState *env) return; } } + + kvm_get_nmi_state(env); } static void do_cpuid_ent(struct kvm_cpuid_entry2 *e, uint32_t function, @@ -1438,6 +1489,7 @@ void kvm_arch_push_nmi(void *opaque) void kvm_arch_cpu_reset(CPUState *env) { + env->nmi_pending = 0; kvm_arch_load_regs(env); if (!cpu_is_bsp(env)) { if (kvm_irqchip_in_kernel(kvm_context)) { diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 278d3e3..620822a 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -709,6 +709,7 @@ typedef struct CPUX86State { /* For KVM */ uint64_t interrupt_bitmap[256 / 64]; uint32_t mp_state; + uint32_t nmi_pending; /* in order to simplify APIC support, we leave this pointer to the user */ diff --git a/target-i386/machine.c b/target-i386/machine.c index e640dad..5c290f3 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -469,6 +469,7 @@ const VMStateDescription vmstate_cpu = { VMSTATE_INT32_V(pending_irq_vmstate, CPUState, 9), VMSTATE_UINT32_V(mp_state, CPUState, 9), VMSTATE_UINT64_V(tsc, CPUState, 9), + VMSTATE_UINT32_V(nmi_pending, CPUState, 11), /* MCE */ VMSTATE_UINT64_V(mcg_cap, CPUState, 10), VMSTATE_UINT64_V(mcg_status, CPUState, 10),