From patchwork Thu May 21 20:55:39 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 25292 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 n4LKvGiY010258 for ; Thu, 21 May 2009 20:57:16 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754222AbZEUU5I (ORCPT ); Thu, 21 May 2009 16:57:08 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1753894AbZEUU5H (ORCPT ); Thu, 21 May 2009 16:57:07 -0400 Received: from fmmailgate02.web.de ([217.72.192.227]:51941 "EHLO fmmailgate02.web.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754052AbZEUU5G (ORCPT ); Thu, 21 May 2009 16:57:06 -0400 Received: from smtp06.web.de (fmsmtp06.dlan.cinetic.de [172.20.5.172]) by fmmailgate02.web.de (Postfix) with ESMTP id C512A10098D99; Thu, 21 May 2009 22:55:44 +0200 (CEST) Received: from [88.66.121.94] (helo=[192.168.1.3]) by smtp06.web.de with asmtp (TLSv1:AES256-SHA:256) (WEB.DE 4.110 #277) id 1M7FIm-0003mz-00; Thu, 21 May 2009 22:55:44 +0200 Message-ID: <4A15BFCB.6050403@web.de> Date: Thu, 21 May 2009 22:55:39 +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 CC: Gleb Natapov , kvm-devel Subject: [RFC][PATCH] qemu-kvm: x86: Refactor persistent CPU state X-Enigmail-Version: 0.95.7 X-Sender: jan.kiszka@web.de X-Provags-ID: V01U2FsdGVkX194mSdgSgTT4nfZn7baofzFWOWAkkGCuijNisse vBFzkVNjLSncyl6iUmRXIkpZZ8wTpGXn0XtPskiEGTdayRtzgX dVFDiyWME= Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org This patch reworks the KVM-related layout and encoding of the CPU state to be saved to disk or migrated. The goal is to define a format, version 9, that is also acceptable for upstream and can later be merged into QEMU. Besides unconditionally writing KVM states, this format compresses interrupt_bitmap into a single number as there can be no more than one pending IRQ at a time. Signed-off-by: Jan Kiszka --- target-i386/cpu.h | 2 +- target-i386/machine.c | 57 +++++++++++++++++++++++++++++++++++-------------- 2 files changed, 42 insertions(+), 17 deletions(-) diff --git a/target-i386/cpu.h b/target-i386/cpu.h index f054af1..e07b504 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -838,7 +838,7 @@ static inline int cpu_get_time_fast(void) #define cpu_signal_handler cpu_x86_signal_handler #define cpu_list x86_cpu_list -#define CPU_SAVE_VERSION 8 +#define CPU_SAVE_VERSION 9 /* MMU modes definitions */ #define MMU_MODE0_SUFFIX _kernel diff --git a/target-i386/machine.c b/target-i386/machine.c index 399204d..18ba983 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -37,7 +37,8 @@ void cpu_save(QEMUFile *f, void *opaque) uint16_t fptag, fpus, fpuc, fpregs_format; uint32_t hflags; int32_t a20_mask; - int i; + int32_t pending_irq; + int i, bit; if (kvm_enabled()) { kvm_save_registers(env); @@ -152,13 +153,21 @@ void cpu_save(QEMUFile *f, void *opaque) qemu_put_be64s(f, &env->mtrr_var[i].mask); } - if (kvm_enabled()) { - for (i = 0; i < sizeof(env->interrupt_bitmap)/8 ; i++) { - qemu_put_be64s(f, &env->interrupt_bitmap[i]); + /* KVM-related states */ + + /* There can only be one pending IRQ set in the bitmap at a time, so try + to find it and save its number instead (-1 for none). */ + pending_irq = -1; + for (i = 0; i < sizeof(env->interrupt_bitmap)/2; i++) { + bit = ffs(((uint16_t *)env->interrupt_bitmap)[i]); + if (bit) { + pending_irq = i * 16 + bit; + break; } - qemu_put_be64s(f, &env->tsc); - qemu_put_be32s(f, &env->mp_state); } + qemu_put_sbe32s(f, &pending_irq); + qemu_put_be32s(f, &env->mp_state); + qemu_put_be64s(f, &env->tsc); } #ifdef USE_X86LDOUBLE @@ -192,9 +201,9 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) uint32_t hflags; uint16_t fpus, fpuc, fptag, fpregs_format; int32_t a20_mask; + int32_t pending_irq; - if (version_id != 3 && version_id != 4 && version_id != 5 - && version_id != 6 && version_id != 7 && version_id != 8) + if (version_id < 3 || version_id > CPU_SAVE_VERSION) return -EINVAL; for(i = 0; i < CPU_NB_REGS; i++) qemu_get_betls(f, &env->regs[i]); @@ -339,6 +348,16 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) } } + if (version_id >= 9) { + qemu_get_sbe32s(f, &pending_irq); + memset(&env->interrupt_bitmap, 0, sizeof(env->interrupt_bitmap)); + if (pending_irq >= 0) { + env->interrupt_bitmap[pending_irq / 64] |= 1 << (pending_irq % 64); + } + qemu_get_be32s(f, &env->mp_state); + qemu_get_be64s(f, &env->tsc); + } + /* XXX: ensure compatiblity for halted bit ? */ /* XXX: compute redundant hflags bits */ env->hflags = hflags; @@ -347,14 +366,20 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) /* when in-kernel irqchip is used, env->halted causes deadlock because no userspace IRQs will ever clear this flag */ env->halted = 0; - for (i = 0; i < sizeof(env->interrupt_bitmap)/8; i++) { - qemu_get_be64s(f, &env->interrupt_bitmap[i]); - } - qemu_get_be64s(f, &env->tsc); - kvm_load_registers(env); - kvm_load_tsc(env); - if (version_id >= 5) { - qemu_get_be32s(f, &env->mp_state); + if (version_id < 9) { + for (i = 0; i < sizeof(env->interrupt_bitmap)/8; i++) { + qemu_get_be64s(f, &env->interrupt_bitmap[i]); + } + qemu_get_be64s(f, &env->tsc); + kvm_load_registers(env); + kvm_load_tsc(env); + if (version_id >= 5) { + qemu_get_be32s(f, &env->mp_state); + kvm_load_mpstate(env); + } + } else { + kvm_load_registers(env); + kvm_load_tsc(env); kvm_load_mpstate(env); } }