From patchwork Wed May 27 10:16:17 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kiszka X-Patchwork-Id: 26422 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 n4RAGkE4023107 for ; Wed, 27 May 2009 10:16:46 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1759338AbZE0KQl (ORCPT ); Wed, 27 May 2009 06:16:41 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1759160AbZE0KQl (ORCPT ); Wed, 27 May 2009 06:16:41 -0400 Received: from lizzard.sbs.de ([194.138.37.39]:23677 "EHLO lizzard.sbs.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757460AbZE0KQk (ORCPT ); Wed, 27 May 2009 06:16:40 -0400 Received: from mail1.sbs.de (localhost [127.0.0.1]) by lizzard.sbs.de (8.12.11.20060308/8.12.11) with ESMTP id n4RAGL4U024890; Wed, 27 May 2009 12:16:23 +0200 Received: from [139.25.109.167] (mchn012c.mchp.siemens.de [139.25.109.167] (may be forged)) by mail1.sbs.de (8.12.11.20060308/8.12.11) with ESMTP id n4RAGHai031033; Wed, 27 May 2009 12:16:17 +0200 Message-ID: <4A1D12F1.7070405@siemens.com> Date: Wed, 27 May 2009 12:16:17 +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: [PATCH v3] qemu-kvm: x86: Refactor persistent CPU state References: <4A15BFCB.6050403@web.de> <4A1939CC.8030206@redhat.com> <4A1A3F15.30809@web.de> <4A1D0C6A.2070009@redhat.com> In-Reply-To: <4A1D0C6A.2070009@redhat.com> 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. Changes in v3: - fixed bit-shift overflow - replace upstream v9 format (should be merged upstream quickly) Changes in v2: - fixed and simplified interrupt_bitmap parsing Signed-off-by: Jan Kiszka --- target-i386/machine.c | 51 ++++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 44 insertions(+), 7 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/target-i386/machine.c b/target-i386/machine.c index 124f8dc..f280d3d 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -29,7 +29,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; cpu_synchronize_state(env, 0); @@ -141,11 +142,21 @@ void cpu_save(QEMUFile *f, void *opaque) qemu_put_be64s(f, &env->mtrr_var[i].mask); } - 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 < ARRAY_SIZE(env->interrupt_bitmap); i++) { + bit = ffsll(env->interrupt_bitmap[i]); + if (bit) { + pending_irq = i * 64 + bit - 1; + break; + } } - qemu_put_be64s(f, &env->tsc); + qemu_put_sbe32s(f, &pending_irq); qemu_put_be32s(f, &env->mp_state); + qemu_put_be64s(f, &env->tsc); } #ifdef USE_X86LDOUBLE @@ -179,6 +190,7 @@ 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 > CPU_SAVE_VERSION) return -EINVAL; @@ -324,12 +336,16 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) qemu_get_be64s(f, &env->mtrr_var[i].mask); } } + if (version_id >= 9) { - for (i = 0; i < sizeof(env->interrupt_bitmap)/8; i++) { - qemu_get_be64s(f, &env->interrupt_bitmap[i]); + 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] |= + (uint64_t)1 << (pending_irq % 64); } - qemu_get_be64s(f, &env->tsc); qemu_get_be32s(f, &env->mp_state); + qemu_get_be64s(f, &env->tsc); } /* XXX: ensure compatiblity for halted bit ? */ @@ -337,5 +353,26 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) env->hflags = hflags; tlb_flush(env, 1); cpu_synchronize_state(env, 1); + if (kvm_enabled()) { + /* when in-kernel irqchip is used, env->halted causes deadlock + because no userspace IRQs will ever clear this flag */ + env->halted = 0; + 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); + } + } return 0; }