From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from [140.186.70.92] (port=38185 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OP9iN-0003Wh-QN for qemu-devel@nongnu.org; Thu, 17 Jun 2010 03:40:45 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1OP9iL-0000jL-UD for qemu-devel@nongnu.org; Thu, 17 Jun 2010 03:40:43 -0400 Received: from fmmailgate02.web.de ([217.72.192.227]:39044) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1OP9iL-0000j3-Es for qemu-devel@nongnu.org; Thu, 17 Jun 2010 03:40:41 -0400 Message-ID: <4C19D173.8040808@web.de> Date: Thu, 17 Jun 2010 09:40:35 +0200 From: Jan Kiszka MIME-Version: 1.0 References: <1276759096-29104-1-git-send-email-sheng@linux.intel.com> <1276759096-29104-4-git-send-email-sheng@linux.intel.com> In-Reply-To: <1276759096-29104-4-git-send-email-sheng@linux.intel.com> Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="------------enigBDA1FEEC9EAF267001012B64" Sender: jan.kiszka@web.de Subject: [Qemu-devel] Re: [PATCH 3/4] qemu: kvm: Enable XSAVE live migration support List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Sheng Yang Cc: qemu-devel@nongnu.org, Marcelo Tosatti , Avi Kivity , kvm@vger.kernel.org This is an OpenPGP/MIME signed message (RFC 2440 and 3156) --------------enigBDA1FEEC9EAF267001012B64 Content-Type: text/plain; charset=ISO-8859-15 Content-Transfer-Encoding: quoted-printable Sheng Yang wrote: > Signed-off-by: Sheng Yang > --- > target-i386/cpu.h | 5 ++ > target-i386/kvm.c | 134 +++++++++++++++++++++++++++++++++++++++++= ++++++++ > target-i386/machine.c | 20 +++++++ > 3 files changed, 159 insertions(+), 0 deletions(-) >=20 > diff --git a/target-i386/cpu.h b/target-i386/cpu.h > index 548ab80..75070d3 100644 > --- a/target-i386/cpu.h > +++ b/target-i386/cpu.h > @@ -718,6 +718,11 @@ typedef struct CPUX86State { > uint16_t fpus_vmstate; > uint16_t fptag_vmstate; > uint16_t fpregs_format_vmstate; > + > + uint64_t xstate_bv; > + XMMReg ymmh_regs[CPU_NB_REGS]; > + > + uint64_t xcr0; > } CPUX86State; > =20 > CPUX86State *cpu_x86_init(const char *cpu_model); > diff --git a/target-i386/kvm.c b/target-i386/kvm.c > index bb6a12f..90ff323 100644 > --- a/target-i386/kvm.c > +++ b/target-i386/kvm.c > @@ -289,6 +289,8 @@ void kvm_arch_reset_vcpu(CPUState *env) > } else { > env->mp_state =3D KVM_MP_STATE_RUNNABLE; > } > + /* Legal xcr0 for loading */ > + env->xcr0 =3D 1; > } > =20 > static int kvm_has_msr_star(CPUState *env) > @@ -504,6 +506,57 @@ static int kvm_put_fpu(CPUState *env) > return kvm_vcpu_ioctl(env, KVM_SET_FPU, &fpu); > } > =20 > +#ifdef KVM_CAP_XSAVE > + > +#define XSAVE_CWD_RIP 2 > +#define XSAVE_CWD_RDP 4 > +#define XSAVE_MXCSR 6 > +#define XSAVE_ST_SPACE 8 > +#define XSAVE_XMM_SPACE 40 > +#define XSAVE_XSTATE_BV 128 > +#define XSAVE_YMMH_SPACE 144 > + > +static int kvm_put_xsave(CPUState *env) > +{ > + int i; > + struct kvm_xsave* xsave; > + uint16_t cwd, swd, twd, fop; > + > + xsave =3D qemu_memalign(4096, sizeof(struct kvm_xsave)); > + memset(xsave, 0, sizeof(struct kvm_xsave)); > + cwd =3D swd =3D twd =3D fop =3D 0; > + swd =3D env->fpus & ~(7 << 11); > + swd |=3D (env->fpstt & 7) << 11; > + cwd =3D env->fpuc; > + for (i =3D 0; i < 8; ++i) > + twd |=3D (!env->fptags[i]) << i; > + xsave->region[0] =3D (uint32_t)(swd << 16) + cwd; > + xsave->region[1] =3D (uint32_t)(fop << 16) + twd; > + memcpy(&xsave->region[XSAVE_ST_SPACE], env->fpregs, > + sizeof env->fpregs); > + memcpy(&xsave->region[XSAVE_XMM_SPACE], env->xmm_regs, > + sizeof env->xmm_regs); > + xsave->region[XSAVE_MXCSR] =3D env->mxcsr; > + *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV] =3D env->xstate_bv; > + memcpy(&xsave->region[XSAVE_YMMH_SPACE], env->ymmh_regs, > + sizeof env->ymmh_regs); > + return kvm_vcpu_ioctl(env, KVM_SET_XSAVE, xsave); > +} > +#endif > + > +#ifdef KVM_CAP_XCRS > +static int kvm_put_xcrs(CPUState *env) > +{ > + struct kvm_xcrs xcrs; > + > + xcrs.nr_xcrs =3D 1; > + xcrs.flags =3D 0; > + xcrs.xcrs[0].xcr =3D 0; > + xcrs.xcrs[0].value =3D env->xcr0; > + return kvm_vcpu_ioctl(env, KVM_SET_XCRS, &xcrs); > +} > +#endif > + > static int kvm_put_sregs(CPUState *env) > { > struct kvm_sregs sregs; > @@ -621,6 +674,59 @@ static int kvm_get_fpu(CPUState *env) > return 0; > } > =20 > +#ifdef KVM_CAP_XSAVE > +static int kvm_get_xsave(CPUState *env) > +{ > + struct kvm_xsave* xsave; > + int ret, i; > + uint16_t cwd, swd, twd, fop; > + > + xsave =3D qemu_memalign(4096, sizeof(struct kvm_xsave)); > + ret =3D kvm_vcpu_ioctl(env, KVM_GET_XSAVE, xsave); > + if (ret < 0) > + return ret; > + > + cwd =3D (uint16_t)xsave->region[0]; > + swd =3D (uint16_t)(xsave->region[0] >> 16); > + twd =3D (uint16_t)xsave->region[1]; > + fop =3D (uint16_t)(xsave->region[1] >> 16); > + env->fpstt =3D (swd >> 11) & 7; > + env->fpus =3D swd; > + env->fpuc =3D cwd; > + for (i =3D 0; i < 8; ++i) > + env->fptags[i] =3D !((twd >> i) & 1); > + env->mxcsr =3D xsave->region[XSAVE_MXCSR]; > + memcpy(env->fpregs, &xsave->region[XSAVE_ST_SPACE], > + sizeof env->fpregs); > + memcpy(env->xmm_regs, &xsave->region[XSAVE_XMM_SPACE], > + sizeof env->xmm_regs); > + env->xstate_bv =3D *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV]; > + memcpy(env->ymmh_regs, &xsave->region[XSAVE_YMMH_SPACE], > + sizeof env->ymmh_regs); > + return 0; > +} > +#endif > + > +#ifdef KVM_CAP_XCRS > +static int kvm_get_xcrs(CPUState *env) > +{ > + int i, ret; > + struct kvm_xcrs xcrs; > + > + ret =3D kvm_vcpu_ioctl(env, KVM_GET_XCRS, &xcrs); > + if (ret < 0) > + return ret; > + > + for (i =3D 0; i < xcrs.nr_xcrs; i++) > + /* Only support xcr0 now */ > + if (xcrs.xcrs[0].xcr =3D=3D 0) { > + env->xcr0 =3D xcrs.xcrs[0].value; > + break; > + } > + return 0; > +} > +#endif > + > static int kvm_get_sregs(CPUState *env) > { > struct kvm_sregs sregs; > @@ -965,9 +1071,23 @@ int kvm_arch_put_registers(CPUState *env, int lev= el) > if (ret < 0) > return ret; > =20 > +#ifdef KVM_CAP_XSAVE > + if (kvm_check_extension(env->kvm_state, KVM_CAP_XSAVE)) > + ret =3D kvm_put_xsave(env); > + else > + ret =3D kvm_put_fpu(env); > +#else > ret =3D kvm_put_fpu(env); > +#endif > + if (ret < 0) > + return ret; > + > +#ifdef KVM_CAP_XCRS > + if (kvm_check_extension(env->kvm_state, KVM_CAP_XCRS)) > + ret =3D kvm_put_xcrs(env); > if (ret < 0) > return ret; > +#endif No #ifdefs in kvm_arch_put/get_registers please. kvm_put_fpu can call kvm_put_xsave and fall back to its own code on error, kvm_put_xcrs can include the cap check. Moreover, capabilities should not be checked during runtime but during init. See the other users here. > =20 > ret =3D kvm_put_sregs(env); > if (ret < 0) > @@ -1009,9 +1129,23 @@ int kvm_arch_get_registers(CPUState *env) > if (ret < 0) > return ret; > =20 > +#ifdef KVM_CAP_XSAVE > + if (kvm_check_extension(env->kvm_state, KVM_CAP_XSAVE)) > + ret =3D kvm_get_xsave(env); > + else > + ret =3D kvm_get_fpu(env); > +#else > ret =3D kvm_get_fpu(env); > +#endif > + if (ret < 0) > + return ret; > + > +#ifdef KVM_CAP_XCRS > + if (kvm_check_extension(env->kvm_state, KVM_CAP_XCRS)) > + ret =3D kvm_get_xcrs(env); > if (ret < 0) > return ret; > +#endif > =20 > ret =3D kvm_get_sregs(env); > if (ret < 0) > diff --git a/target-i386/machine.c b/target-i386/machine.c > index b547e2a..5f8376c 100644 > --- a/target-i386/machine.c > +++ b/target-i386/machine.c > @@ -47,6 +47,22 @@ static const VMStateDescription vmstate_xmm_reg =3D = { > #define VMSTATE_XMM_REGS(_field, _state, _n) \= > VMSTATE_STRUCT_ARRAY(_field, _state, _n, 0, vmstate_xmm_reg, XMMRe= g) > =20 > +/* YMMH format is the same as XMM */ > +static const VMStateDescription vmstate_ymmh_reg =3D { > + .name =3D "ymmh_reg", > + .version_id =3D 1, > + .minimum_version_id =3D 1, > + .minimum_version_id_old =3D 1, > + .fields =3D (VMStateField []) { > + VMSTATE_UINT64(XMM_Q(0), XMMReg), > + VMSTATE_UINT64(XMM_Q(1), XMMReg), > + VMSTATE_END_OF_LIST() > + } > +}; > + > +#define VMSTATE_YMMH_REGS_VARS(_field, _state, _n, _v) = \ > + VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_ymmh_reg, XMM= Reg) > + > static const VMStateDescription vmstate_mtrr_var =3D { > .name =3D "mtrr_var", > .version_id =3D 1, > @@ -453,6 +469,10 @@ static const VMStateDescription vmstate_cpu =3D { > /* KVM pvclock msr */ > VMSTATE_UINT64_V(system_time_msr, CPUState, 11), > VMSTATE_UINT64_V(wall_clock_msr, CPUState, 11), > + /* XSAVE related fields */ > + VMSTATE_UINT64_V(xcr0, CPUState, 12), > + VMSTATE_UINT64_V(xstate_bv, CPUState, 12), > + VMSTATE_YMMH_REGS_VARS(ymmh_regs, CPUState, CPU_NB_REGS, 12), > VMSTATE_END_OF_LIST() > /* The above list is not sorted /wrt version numbers, watch ou= t! */ > } You did not increment CPU_SAVE_VERSION, did you? Jan --------------enigBDA1FEEC9EAF267001012B64 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 iEYEARECAAYFAkwZ0XYACgkQitSsb3rl5xSkJACeJTXBvrNI36aMVX51DbBk9gMj GNwAnjEUfsieq/BRt1r6hwDLmTki92iU =p9CX -----END PGP SIGNATURE----- --------------enigBDA1FEEC9EAF267001012B64--