From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jan Kiszka Subject: [PATCH v2] qemu-kvm: x86: Refactor persistent CPU state Date: Mon, 25 May 2009 08:47:49 +0200 Message-ID: <4A1A3F15.30809@web.de> References: <4A15BFCB.6050403@web.de> <4A1939CC.8030206@redhat.com> Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="------------enigD03E5C2F56FC1F0AD22794C1" Cc: Gleb Natapov , kvm-devel To: Avi Kivity Return-path: Received: from fmmailgate03.web.de ([217.72.192.234]:46443 "EHLO fmmailgate03.web.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751004AbZEYGr4 (ORCPT ); Mon, 25 May 2009 02:47:56 -0400 In-Reply-To: <4A1939CC.8030206@redhat.com> Sender: kvm-owner@vger.kernel.org List-ID: This is an OpenPGP/MIME signed message (RFC 2440 and 3156) --------------enigD03E5C2F56FC1F0AD22794C1 Content-Type: text/plain; charset=ISO-8859-15 Content-Transfer-Encoding: quoted-printable Avi Kivity wrote: > Jan Kiszka wrote: >> This patch reworks the KVM-related layout and encoding of the CPU stat= e >> to be saved to disk or migrated. The goal is to define a format, versi= on >> 9, that is also acceptable for upstream and can later be merged into >> QEMU. Besides unconditionally writing KVM states, this format compress= es >> interrupt_bitmap into a single number as there can be no more than one= >> pending IRQ at a time. >> >> =20 >> - if (kvm_enabled()) { >> - for (i =3D 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 =3D -1; >> + for (i =3D 0; i < sizeof(env->interrupt_bitmap)/2; i++) { >> + bit =3D ffs(((uint16_t *)env->interrupt_bitmap)[i]); >> + if (bit) { >> + pending_irq =3D i * 16 + bit; >> =20 >=20 > bit - 1 Fixed. >=20 >> + break; >> } >> =20 >=20 > Why are you using uint64_t? It would be more natural to use ffsll and > the natural type of the bitmap vector. Better don't ask how I interpreted the ffs doc. >=20 >> + } else { >> + kvm_load_registers(env); >> + kvm_load_tsc(env); >> kvm_load_mpstate(env); >> } >> } >> =20 >=20 > Don't you need to load the pending interrupt? >=20 For >=3D v9 this is done in the previous hunk. ------------> 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 v2: - fixed and simplified interrupt_bitmap parsing 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 =20 -#define CPU_SAVE_VERSION 8 +#define CPU_SAVE_VERSION 9 =20 /* MMU modes definitions */ #define MMU_MODE0_SUFFIX _kernel diff --git a/target-i386/machine.c b/target-i386/machine.c index 59472d0..67a6e60 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -28,7 +28,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; =20 if (kvm_enabled()) { kvm_save_registers(env); @@ -143,13 +144,21 @@ void cpu_save(QEMUFile *f, void *opaque) qemu_put_be64s(f, &env->mtrr_var[i].mask); } =20 - if (kvm_enabled()) { - for (i =3D 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 =3D -1; + for (i =3D 0; i < ARRAY_SIZE(env->interrupt_bitmap); i++) { + bit =3D ffsll(env->interrupt_bitmap[i]); + if (bit) { + pending_irq =3D i * 64 + bit - 1; + 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); } =20 #ifdef USE_X86LDOUBLE @@ -183,9 +192,9 @@ int cpu_load(QEMUFile *f, void *opaque, int version_i= d) uint32_t hflags; uint16_t fpus, fpuc, fptag, fpregs_format; int32_t a20_mask; + int32_t pending_irq; =20 - if (version_id !=3D 3 && version_id !=3D 4 && version_id !=3D 5 - && version_id !=3D 6 && version_id !=3D 7 && version_id !=3D 8) + if (version_id < 3 || version_id > CPU_SAVE_VERSION) return -EINVAL; for(i =3D 0; i < CPU_NB_REGS; i++) qemu_get_betls(f, &env->regs[i]); @@ -330,6 +339,16 @@ int cpu_load(QEMUFile *f, void *opaque, int version_= id) } } =20 + if (version_id >=3D 9) { + qemu_get_sbe32s(f, &pending_irq); + memset(&env->interrupt_bitmap, 0, sizeof(env->interrupt_bitmap))= ; + if (pending_irq >=3D 0) { + env->interrupt_bitmap[pending_irq / 64] |=3D 1 << (pending_i= rq % 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 =3D hflags; @@ -338,14 +357,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 =3D 0; - for (i =3D 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 >=3D 5) { - qemu_get_be32s(f, &env->mp_state); + if (version_id < 9) { + for (i =3D 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 >=3D 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); } } --------------enigD03E5C2F56FC1F0AD22794C1 Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.9 (GNU/Linux) Comment: Using GnuPG with SUSE - http://enigmail.mozdev.org iEUEARECAAYFAkoaPxsACgkQniDOoMHTA+nFEQCWNzj3GpZnOR1K+VowxAAGu2XH HgCfcnWgwjJLxkIrGACrmcfbrAeh9hw= =svlc -----END PGP SIGNATURE----- --------------enigD03E5C2F56FC1F0AD22794C1--