From patchwork Tue Nov 24 23:33:03 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 39255 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 502491007D3 for ; Wed, 25 Nov 2009 10:34:01 +1100 (EST) Received: from localhost ([127.0.0.1]:39072 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1ND4tR-0006w3-C8 for incoming@patchwork.ozlabs.org; Tue, 24 Nov 2009 18:33:57 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1ND4sh-0006vV-47 for qemu-devel@nongnu.org; Tue, 24 Nov 2009 18:33:11 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1ND4sc-0006uj-Gu for qemu-devel@nongnu.org; Tue, 24 Nov 2009 18:33:10 -0500 Received: from [199.232.76.173] (port=60090 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1ND4sc-0006ud-9l for qemu-devel@nongnu.org; Tue, 24 Nov 2009 18:33:06 -0500 Received: from fmmailgate02.web.de ([217.72.192.227]:60642) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1ND4sb-0005DQ-Ng for qemu-devel@nongnu.org; Tue, 24 Nov 2009 18:33:06 -0500 Received: from smtp08.web.de (fmsmtp08.dlan.cinetic.de [172.20.5.216]) by fmmailgate02.web.de (Postfix) with ESMTP id 996DB1444062F; Wed, 25 Nov 2009 00:33:04 +0100 (CET) Received: from [88.64.22.121] (helo=[192.168.1.10]) by smtp08.web.de with asmtp (TLSv1:AES256-SHA:256) (WEB.DE 4.110 #314) id 1ND4sa-0002HR-00; Wed, 25 Nov 2009 00:33:04 +0100 Message-ID: <4B0C6D2F.6080701@web.de> Date: Wed, 25 Nov 2009 00:33:03 +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: Anthony Liguori , qemu-devel X-Enigmail-Version: 0.95.7 X-Sender: jan.kiszka@web.de X-Provags-ID: V01U2FsdGVkX1+pq/PE+oW07VP2eC7u417cmLIxKc/6QESOHf3f 2xNNzHtaNDKOAJ7O72jl2ITx34BqpVuWzG5BPS1xWfA1dC7lrG DJVOv4O/k= X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.4-2.6 Cc: Marcelo Tosatti , Avi Kivity Subject: [Qemu-devel] [PATCH] kvm: x86: Add support for VCPU event states X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This patch extends the qemu-kvm state sync logic with support for KVM_GET/SET_VCPU_EVENTS, giving access to yet missing exception, interrupt and NMI states. Signed-off-by: Jan Kiszka --- kvm-all.c | 11 +++++++ kvm.h | 1 + target-i386/cpu.h | 5 +++ target-i386/kvm.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++ target-i386/machine.c | 6 ++++ 5 files changed, 100 insertions(+), 0 deletions(-) diff --git a/kvm-all.c b/kvm-all.c index b605caa..c05e555 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -61,6 +61,7 @@ struct KVMState int coalesced_mmio; int broken_set_mem_region; int migration_log; + int vcpu_events; #ifdef KVM_CAP_SET_GUEST_DEBUG struct kvm_sw_breakpoint_head kvm_sw_breakpoints; #endif @@ -479,6 +480,11 @@ int kvm_init(int smp_cpus) } #endif + s->vcpu_events = 0; +#ifdef KVM_CAP_VCPU_EVENTS + s->vcpu_events = kvm_check_extension(s, KVM_CAP_VCPU_EVENTS); +#endif + ret = kvm_arch_init(s, smp_cpus); if (ret < 0) goto err; @@ -868,6 +874,11 @@ int kvm_has_sync_mmu(void) #endif } +int kvm_has_vcpu_events(void) +{ + return kvm_state->vcpu_events; +} + void kvm_setup_guest_memory(void *start, size_t size) { if (!kvm_has_sync_mmu()) { diff --git a/kvm.h b/kvm.h index e4cbedc..1c93ac5 100644 --- a/kvm.h +++ b/kvm.h @@ -47,6 +47,7 @@ int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size); int kvm_set_migration_log(int enable); int kvm_has_sync_mmu(void); +int kvm_has_vcpu_events(void); void kvm_setup_guest_memory(void *start, size_t size); diff --git a/target-i386/cpu.h b/target-i386/cpu.h index eb9532a..9c3e905 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -693,6 +693,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/kvm.c b/target-i386/kvm.c index 89fd7a5..3b61a7f 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -225,6 +225,8 @@ int kvm_arch_init_vcpu(CPUState *env) void kvm_arch_reset_vcpu(CPUState *env) { env->interrupt_injected = -1; + env->nmi_injected = 0; + env->nmi_pending = 0; } static int kvm_has_msr_star(CPUState *env) @@ -694,6 +696,73 @@ static int kvm_get_mp_state(CPUState *env) return 0; } +static int kvm_put_vcpu_events(CPUState *env) +{ +#ifdef KVM_CAP_VCPU_EVENTS + struct kvm_vcpu_events events; + + if (!kvm_has_vcpu_events()) { + return 0; + } + + 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; + + return kvm_vcpu_ioctl(env, KVM_SET_VCPU_EVENTS, &events); +#else + return 0; +#endif +} + +static int kvm_get_vcpu_events(CPUState *env) +{ +#ifdef KVM_CAP_VCPU_EVENTS + struct kvm_vcpu_events events; + int ret; + + if (!kvm_has_vcpu_events()) { + return 0; + } + + ret = kvm_vcpu_ioctl(env, KVM_GET_VCPU_EVENTS, &events); + if (ret < 0) { + return ret; + } + 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; +#endif + + return 0; +} + int kvm_arch_put_registers(CPUState *env) { int ret; @@ -718,6 +787,10 @@ int kvm_arch_put_registers(CPUState *env) if (ret < 0) return ret; + ret = kvm_put_vcpu_events(env); + if (ret < 0) + return ret; + return 0; } @@ -745,6 +818,10 @@ int kvm_arch_get_registers(CPUState *env) if (ret < 0) return ret; + ret = kvm_get_vcpu_events(env); + if (ret < 0) + return ret; + return 0; } diff --git a/target-i386/machine.c b/target-i386/machine.c index c09b049..cdc8898 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -448,6 +448,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), @@ -456,6 +461,7 @@ static const VMStateDescription vmstate_cpu = { /* rdtscp */ VMSTATE_UINT64_V(tsc_aux, CPUState, 11), VMSTATE_END_OF_LIST() + /* The above list is not sorted /wrt version numbers, watch out! */ } };