From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from [140.186.70.92] (port=38474 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OP9jT-0004iC-Td for qemu-devel@nongnu.org; Thu, 17 Jun 2010 03:41:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1OP9jQ-0000so-5W for qemu-devel@nongnu.org; Thu, 17 Jun 2010 03:41:51 -0400 Received: from fmmailgate02.web.de ([217.72.192.227]:40006) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1OP9jP-0000sR-OQ for qemu-devel@nongnu.org; Thu, 17 Jun 2010 03:41:48 -0400 Message-ID: <4C19D1B7.50006@web.de> Date: Thu, 17 Jun 2010 09:41:43 +0200 From: Jan Kiszka MIME-Version: 1.0 References: <1276759096-29104-1-git-send-email-sheng@linux.intel.com> <1276759096-29104-5-git-send-email-sheng@linux.intel.com> In-Reply-To: <1276759096-29104-5-git-send-email-sheng@linux.intel.com> Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="------------enig0A8B3C66507A61666AB26C0A" Sender: jan.kiszka@web.de Subject: [Qemu-devel] Re: [PATCH 4/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) --------------enig0A8B3C66507A61666AB26C0A Content-Type: text/plain; charset=ISO-8859-15 Content-Transfer-Encoding: quoted-printable Sheng Yang wrote: > Based on upstream xsave related fields. >=20 > Signed-off-by: Sheng Yang > --- > qemu-kvm-x86.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++= +++++++- > qemu-kvm.c | 24 ++++++++++++++ > qemu-kvm.h | 28 ++++++++++++++++ > 3 files changed, 146 insertions(+), 1 deletions(-) >=20 > diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c > index 3c33e64..dcef8b5 100644 > --- a/qemu-kvm-x86.c > +++ b/qemu-kvm-x86.c > @@ -772,10 +772,26 @@ static void get_seg(SegmentCache *lhs, const stru= ct kvm_segment *rhs) > | (rhs->avl * DESC_AVL_MASK); > } > =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 > +#endif > + > void kvm_arch_load_regs(CPUState *env, int level) > { > struct kvm_regs regs; > struct kvm_fpu fpu; > +#ifdef KVM_CAP_XSAVE > + struct kvm_xsave* xsave; > +#endif > +#ifdef KVM_CAP_XCRS > + struct kvm_xcrs xcrs; > +#endif > struct kvm_sregs sregs; > struct kvm_msr_entry msrs[100]; > int rc, n, i; > @@ -806,16 +822,53 @@ void kvm_arch_load_regs(CPUState *env, int level)= > =20 > kvm_set_regs(env, ®s); > =20 > +#ifdef KVM_CAP_XSAVE > + if (kvm_check_extension(kvm_state, KVM_CAP_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_b= v; > + memcpy(&xsave->region[XSAVE_YMMH_SPACE], env->ymmh_regs, > + sizeof env->ymmh_regs); > + kvm_set_xsave(env, xsave); > +#ifdef KVM_CAP_XCRS > + if (kvm_check_extension(kvm_state, KVM_CAP_XCRS)) { > + xcrs.nr_xcrs =3D 1; > + xcrs.flags =3D 0; > + xcrs.xcrs[0].xcr =3D 0; > + xcrs.xcrs[0].value =3D env->xcr0; > + kvm_set_xcrs(env, &xcrs); > + } > +#endif /* KVM_CAP_XCRS */ > + } else { > +#endif /* KVM_CAP_XSAVE */ Why not reusing kvm_put/get_xsave as defined for upstream? There should be enough examples for that pattern. The result will be a tiny qemu-kvm patch. Jan > memset(&fpu, 0, sizeof fpu); > fpu.fsw =3D env->fpus & ~(7 << 11); > fpu.fsw |=3D (env->fpstt & 7) << 11; > fpu.fcw =3D env->fpuc; > for (i =3D 0; i < 8; ++i) > - fpu.ftwx |=3D (!env->fptags[i]) << i; > + fpu.ftwx |=3D (!env->fptags[i]) << i; > memcpy(fpu.fpr, env->fpregs, sizeof env->fpregs); > memcpy(fpu.xmm, env->xmm_regs, sizeof env->xmm_regs); > fpu.mxcsr =3D env->mxcsr; > kvm_set_fpu(env, &fpu); > +#ifdef KVM_CAP_XSAVE > + } > +#endif > =20 > memset(sregs.interrupt_bitmap, 0, sizeof(sregs.interrupt_bitmap));= > if (env->interrupt_injected >=3D 0) { > @@ -934,6 +987,12 @@ void kvm_arch_save_regs(CPUState *env) > { > struct kvm_regs regs; > struct kvm_fpu fpu; > +#ifdef KVM_CAP_XSAVE > + struct kvm_xsave* xsave; > +#endif > +#ifdef KVM_CAP_XCRS > + struct kvm_xcrs xcrs; > +#endif > struct kvm_sregs sregs; > struct kvm_msr_entry msrs[100]; > uint32_t hflags; > @@ -965,6 +1024,37 @@ void kvm_arch_save_regs(CPUState *env) > env->eflags =3D regs.rflags; > env->eip =3D regs.rip; > =20 > +#ifdef KVM_CAP_XSAVE > + if (kvm_check_extension(kvm_state, KVM_CAP_XSAVE)) { > + uint16_t cwd, swd, twd, fop; > + xsave =3D qemu_memalign(4096, sizeof(struct kvm_xsave)); > + kvm_get_xsave(env, xsave); > + 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); > +#ifdef KVM_CAP_XCRS > + if (kvm_check_extension(kvm_state, KVM_CAP_XCRS)) { > + kvm_get_xcrs(env, &xcrs); > + if (xcrs.xcrs[0].xcr =3D=3D 0) > + env->xcr0 =3D xcrs.xcrs[0].value; > + } > +#endif > + } else { > +#endif > kvm_get_fpu(env, &fpu); > env->fpstt =3D (fpu.fsw >> 11) & 7; > env->fpus =3D fpu.fsw; > @@ -974,6 +1064,9 @@ void kvm_arch_save_regs(CPUState *env) > memcpy(env->fpregs, fpu.fpr, sizeof env->fpregs); > memcpy(env->xmm_regs, fpu.xmm, sizeof env->xmm_regs); > env->mxcsr =3D fpu.mxcsr; > +#ifdef KVM_CAP_XSAVE > + } > +#endif > =20 > kvm_get_sregs(env, &sregs); > =20 > diff --git a/qemu-kvm.c b/qemu-kvm.c > index 96d458c..be1dac2 100644 > --- a/qemu-kvm.c > +++ b/qemu-kvm.c > @@ -503,6 +503,30 @@ int kvm_set_mpstate(CPUState *env, struct kvm_mp_s= tate *mp_state) > } > #endif > =20 > +#ifdef KVM_CAP_XSAVE > +int kvm_get_xsave(CPUState *env, struct kvm_xsave *xsave) > +{ > + return kvm_vcpu_ioctl(env, KVM_GET_XSAVE, xsave); > +} > + > +int kvm_set_xsave(CPUState *env, struct kvm_xsave *xsave) > +{ > + return kvm_vcpu_ioctl(env, KVM_SET_XSAVE, xsave); > +} > +#endif > + > +#ifdef KVM_CAP_XCRS > +int kvm_get_xcrs(CPUState *env, struct kvm_xcrs *xcrs) > +{ > + return kvm_vcpu_ioctl(env, KVM_GET_XCRS, xcrs); > +} > + > +int kvm_set_xcrs(CPUState *env, struct kvm_xcrs *xcrs) > +{ > + return kvm_vcpu_ioctl(env, KVM_SET_XCRS, xcrs); > +} > +#endif > + > static int handle_mmio(CPUState *env) > { > unsigned long addr =3D env->kvm_run->mmio.phys_addr; > diff --git a/qemu-kvm.h b/qemu-kvm.h > index 6f6c6d8..3ace503 100644 > --- a/qemu-kvm.h > +++ b/qemu-kvm.h > @@ -300,6 +300,34 @@ int kvm_get_mpstate(CPUState *env, struct kvm_mp_s= tate *mp_state); > int kvm_set_mpstate(CPUState *env, struct kvm_mp_state *mp_state); > #endif > =20 > +#ifdef KVM_CAP_XSAVE > +/*! > + * * \brief Read VCPU xsave state > + * > + */ > +int kvm_get_xsave(CPUState *env, struct kvm_xsave *xsave); > + > +/*! > + * * \brief Write VCPU xsave state > + * > + */ > +int kvm_set_xsave(CPUState *env, struct kvm_xsave *xsave); > +#endif > + > +#ifdef KVM_CAP_XCRS > +/*! > + * * \brief Read VCPU XCRs > + * > + */ > +int kvm_get_xcrs(CPUState *env, struct kvm_xcrs *xcrs); > + > +/*! > + * * \brief Write VCPU XCRs > + * > + */ > +int kvm_set_xcrs(CPUState *env, struct kvm_xcrs *xcrs); > +#endif > + > /*! > * \brief Simulate an external vectored interrupt > * --------------enig0A8B3C66507A61666AB26C0A 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 iEYEARECAAYFAkwZ0bcACgkQitSsb3rl5xTF6wCg4aW4i8A4tQMHLy37UklIJpRY sZgAoOJwRa/biidzIjPt3BlDH2xwgn83 =YK27 -----END PGP SIGNATURE----- --------------enig0A8B3C66507A61666AB26C0A--