From patchwork Thu Nov 5 08:25:46 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 57857 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 nA58Q1s9028382 for ; Thu, 5 Nov 2009 08:26:01 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754621AbZKEIZy (ORCPT ); Thu, 5 Nov 2009 03:25:54 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1753601AbZKEIZx (ORCPT ); Thu, 5 Nov 2009 03:25:53 -0500 Received: from goliath.siemens.de ([192.35.17.28]:19996 "EHLO goliath.siemens.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753538AbZKEIZx (ORCPT ); Thu, 5 Nov 2009 03:25:53 -0500 Received: from mail2.siemens.de (localhost [127.0.0.1]) by goliath.siemens.de (8.12.11.20060308/8.12.11) with ESMTP id nA58PkE0008171; Thu, 5 Nov 2009 09:25:46 +0100 Received: from [139.25.173.59] ([139.25.173.59]) by mail2.siemens.de (8.12.11.20060308/8.12.11) with ESMTP id nA58Pjnq028349; Thu, 5 Nov 2009 09:25:46 +0100 Message-ID: <4AF28C0A.8050209@siemens.com> Date: Thu, 05 Nov 2009 09:25:46 +0100 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: Marcelo Tosatti , Avi Kivity CC: kvm Subject: [PATCH v2 2/2] qemu-kvm: x86: Add support for event states References: <4AF06A10.6000208@siemens.com> <4AF06B7A.8000901@siemens.com> In-Reply-To: <4AF06B7A.8000901@siemens.com> 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 e03a4ba..dc3e6cb 100644 --- a/qemu-kvm-x86.c +++ b/qemu-kvm-x86.c @@ -903,6 +903,82 @@ static void get_seg(SegmentCache *lhs, const struct kvm_segment *rhs) | (rhs->avl * DESC_AVL_MASK); } +static void kvm_get_events(CPUState *env) +{ +#ifdef KVM_CAP_VCPU_STATE + struct { + struct kvm_vcpu_state header; + struct kvm_vcpu_substate substates[1]; + } request; + struct kvm_x86_event_state events; + int r; + + request.header.nsubstates = 1; + request.header.substates[0].type = KVM_X86_VCPU_STATE_EVENTS; + request.header.substates[0].offset = (size_t)&events - (size_t)&request; + r = kvm_vcpu_ioctl(env, KVM_GET_VCPU_STATE, &request); + if (r == 0) { + env->exception_index = + events.exception.injected ? events.exception.nr : -1; + env->has_error_code = events.exception.has_error_code; + env->error_code = events.exception.error_code; + + env->interrupt_injected = + events.interrupt.injected ? events.interrupt.nr : -1; + env->soft_interrupt = events.interrupt.soft; + + env->nmi_injected = events.nmi.injected; + env->nmi_pending = events.nmi.pending; + if (events.nmi.masked) { + env->hflags2 |= HF2_NMI_MASK; + } else { + env->hflags2 &= ~HF2_NMI_MASK; + } + + env->sipi_vector = events.sipi_vector; + + return; + } +#endif + env->exception_index = -1; + env->interrupt_injected = -1; + env->nmi_injected = 0; + env->nmi_pending = 0; + env->hflags2 &= ~HF2_NMI_MASK; +} + +static void kvm_set_events(CPUState *env) +{ +#ifdef KVM_CAP_VCPU_STATE + struct { + struct kvm_vcpu_state header; + struct kvm_vcpu_substate substates[1]; + } request; + struct kvm_x86_event_state events; + + request.header.nsubstates = 1; + request.header.substates[0].type = KVM_X86_VCPU_STATE_EVENTS; + request.header.substates[0].offset = (size_t)&events - (size_t)&request; + + events.exception.injected = (env->exception_index >= 0); + events.exception.nr = env->exception_index; + events.exception.has_error_code = env->has_error_code; + events.exception.error_code = env->error_code; + + events.interrupt.injected = (env->interrupt_injected >= 0); + events.interrupt.nr = env->interrupt_injected; + events.interrupt.soft = env->soft_interrupt; + + events.nmi.injected = env->nmi_injected; + events.nmi.pending = env->nmi_pending; + events.nmi.masked = !!(env->hflags2 & HF2_NMI_MASK); + + events.sipi_vector = env->sipi_vector; + + kvm_vcpu_ioctl(env, KVM_SET_VCPU_STATE, &request); +#endif +} + void kvm_arch_load_regs(CPUState *env) { struct kvm_regs regs; @@ -1019,6 +1095,8 @@ void kvm_arch_load_regs(CPUState *env) rc = kvm_set_msrs(env, msrs, n); if (rc == -1) perror("kvm_set_msrs FAILED"); + + kvm_set_events(env); } void kvm_load_tsc(CPUState *env) @@ -1215,6 +1293,8 @@ void kvm_arch_save_regs(CPUState *env) return; } } + + kvm_get_events(env); } static void do_cpuid_ent(struct kvm_cpuid_entry2 *e, uint32_t function, @@ -1383,7 +1463,10 @@ int kvm_arch_init_vcpu(CPUState *cenv) kvm_tpr_vcpu_start(cenv); #endif + cenv->exception_index = -1; cenv->interrupt_injected = -1; + cenv->nmi_injected = 0; + cenv->nmi_pending = 0; return 0; } @@ -1453,7 +1536,10 @@ void kvm_arch_push_nmi(void *opaque) void kvm_arch_cpu_reset(CPUState *env) { + env->exception_index = -1; env->interrupt_injected = -1; + env->nmi_injected = 0; + env->nmi_pending = 0; kvm_arch_load_regs(env); if (!cpu_is_bsp(env)) { if (kvm_irqchip_in_kernel()) { diff --git a/target-i386/cpu.h b/target-i386/cpu.h index a638e70..31412a8 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -711,6 +711,11 @@ typedef struct CPUX86State { /* For KVM */ uint32_t mp_state; int32_t interrupt_injected; + uint8_t soft_interrupt; + uint8_t nmi_injected; + uint8_t nmi_pending; + uint8_t has_error_code; + uint32_t sipi_vector; /* 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 6bd447f..1eda7c5 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -452,6 +452,11 @@ static const VMStateDescription vmstate_cpu = { VMSTATE_INT32_V(interrupt_injected, CPUState, 9), VMSTATE_UINT32_V(mp_state, CPUState, 9), VMSTATE_UINT64_V(tsc, CPUState, 9), + VMSTATE_UINT8_V(soft_interrupt, CPUState, 11), + VMSTATE_UINT8_V(nmi_injected, CPUState, 11), + VMSTATE_UINT8_V(nmi_pending, CPUState, 11), + VMSTATE_UINT8_V(has_error_code, CPUState, 11), + VMSTATE_UINT32_V(sipi_vector, CPUState, 11), /* MCE */ VMSTATE_UINT64_V(mcg_cap, CPUState, 10), VMSTATE_UINT64_V(mcg_status, CPUState, 10),