qemu: kvm: Enable XSAVE live migration support
PATCH 1/1 qemu: kvm: Enable XSAVE live migration support
Signed-off-by Sheng Yang <[email protected]>
--- qemu-kvm-x86.c | 77 +++++++++++++++++++++++++++++++++++++------------ qemu-kvm.c | 12 +++++++ qemu-kvm.h | 14 +++++++++ target-i386/cpu.h | 5 +++ target-i386/machine.c | 20 +++++++++++++ 5 files changed, 109 insertions(+), 19 deletions(-)
qemu-kvm-x86.c +58 -19
@@ -776,6 +776,7 @@ void kvm_arch_load_regs(CPUState *env, int level) {struct kvm_regs regs;struct kvm_fpu fpu; +struct kvm_xsave xsave;struct kvm_sregs sregs;struct kvm_msr_entry msrs[100 ];int rc, n, i;
@@ -806,16 +807,35 @@ void kvm_arch_load_regs(CPUState *env, int level)kvm_set_regs (env, ®s); -memset (&fpu,0 ,sizeof fpu); - fpu.fsw = env->fpus & ~(7 <<11 ); - fpu.fsw |= (env->fpstt &7 ) <<11 ; - fpu.fcw = env->fpuc; -for (i =0 ; i <8 ; ++i) - fpu.ftwx |= (!env->fptags[i]) << i; -memcpy (fpu.fpr, env->fpregs,sizeof env->fpregs); -memcpy (fpu.xmm, env->xmm_regs,sizeof env->xmm_regs); - fpu.mxcsr = env->mxcsr; -kvm_set_fpu (env, &fpu); +if (kvm_check_extension (kvm_state,KVM_CAP_XSAVE )) { +memset (&xsave,0 ,sizeof xsave); + xsave.i387.swd = env->fpus & ~(7 <<11 ); + xsave.i387.swd |= (env->fpstt &7 ) <<11 ; + xsave.i387.cwd = env->fpuc; +for (i =0 ; i <8 ; ++i) + xsave.i387.twd |= (!env->fptags[i]) << i; +memcpy (xsave.i387.st_space, env->fpregs, +sizeof env->fpregs); +memcpy (xsave.i387.xmm_space, env->xmm_regs, +sizeof env->xmm_regs); + xsave.i387.mxcsr = env->mxcsr; + xsave.xsave_hdr.xstate_bv = env->xstate_bv; +memcpy (xsave.ymmh.ymmh_space, env->ymmh_regs, +sizeof env->ymmh_regs); + xsave.xcr0 = env->xcr0; +kvm_set_xsave (env, &xsave); + }else { +memset (&fpu,0 ,sizeof fpu); + fpu.fsw = env->fpus & ~(7 <<11 ); + fpu.fsw |= (env->fpstt &7 ) <<11 ; + fpu.fcw = env->fpuc; +for (i =0 ; i <8 ; ++i) + fpu.ftwx |= (!env->fptags[i]) << i; +memcpy (fpu.fpr, env->fpregs,sizeof env->fpregs); +memcpy (fpu.xmm, env->xmm_regs,sizeof env->xmm_regs); + fpu.mxcsr = env->mxcsr; +kvm_set_fpu (env, &fpu); + }memset (sregs.interrupt_bitmap,0 ,sizeof (sregs.interrupt_bitmap));if (env->interrupt_injected >=0 ) {
@@ -938,6 +958,7 @@ void kvm_arch_save_regs(CPUState *env) {struct kvm_regs regs;struct kvm_fpu fpu; +struct kvm_xsave xsave;struct kvm_sregs sregs;struct kvm_msr_entry msrs[100 ];uint32_t hflags;
@@ -969,15 +990,33 @@ void kvm_arch_save_regs(CPUState *env) env->eflags = regs.rflags; env->eip = regs.rip; -kvm_get_fpu (env, &fpu); - env->fpstt = (fpu.fsw >>11 ) &7 ; - env->fpus = fpu.fsw; - env->fpuc = fpu.fcw; -for (i =0 ; i <8 ; ++i) - env->fptags[i] = !((fpu.ftwx >> i) &1 ); -memcpy (env->fpregs, fpu.fpr,sizeof env->fpregs); -memcpy (env->xmm_regs, fpu.xmm,sizeof env->xmm_regs); - env->mxcsr = fpu.mxcsr; +if (kvm_check_extension (kvm_state,KVM_CAP_XSAVE )) { +kvm_get_xsave (env, &xsave); + env->fpstt = (xsave.i387.swd >>11 ) &7 ; + env->fpus = xsave.i387.swd; + env->fpuc = xsave.i387.cwd; +for (i =0 ; i <8 ; ++i) + env->fptags[i] = !((xsave.i387.twd >> i) &1 ); +memcpy (env->fpregs, xsave.i387.st_space, +sizeof env->fpregs); +memcpy (env->xmm_regs, xsave.i387.xmm_space, +sizeof env->xmm_regs); + env->mxcsr = xsave.i387.mxcsr; + env->xstate_bv = xsave.xsave_hdr.xstate_bv; +memcpy (env->ymmh_regs, xsave.ymmh.ymmh_space, +sizeof env->ymmh_regs); + env->xcr0 = xsave.xcr0; + }else { +kvm_get_fpu (env, &fpu); + env->fpstt = (fpu.fsw >>11 ) &7 ; + env->fpus = fpu.fsw; + env->fpuc = fpu.fcw; +for (i =0 ; i <8 ; ++i) + env->fptags[i] = !((fpu.ftwx >> i) &1 ); +memcpy (env->fpregs, fpu.fpr,sizeof env->fpregs); +memcpy (env->xmm_regs, fpu.xmm,sizeof env->xmm_regs); + env->mxcsr = fpu.mxcsr; + }kvm_get_sregs (env, &sregs);
qemu-kvm.c +12 -0
@@ -485,6 +485,18 @@ int kvm_set_mpstate(CPUState *env, struct kvm_mp_state *mp_state) }#endif +#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 +static int handle_mmio (CPUState *env) {unsigned long addr = env->kvm_run->mmio.phys_addr;
qemu-kvm.h +14 -0
@@ -300,6 +300,20 @@ int kvm_get_mpstate(CPUState *env, struct kvm_mp_state *mp_state);int kvm_set_mpstate (CPUState *env,struct kvm_mp_state *mp_state);#endif +#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 +/*! * \brief Simulate an external vectored interrupt *
target-i386/cpu.h +5 -0
@@ -736,6 +736,11 @@ typedef struct CPUX86State {uint16_t fpregs_format_vmstate;int kvm_vcpu_update_vapic; + +uint64_t xstate_bv; +XMMReg ymmh_regs[CPU_NB_REGS ]; + +uint64_t xcr0; } CPUX86State;CPUX86State *cpu_x86_init (const char *cpu_model);
target-i386/machine.c +20 -0
@@ -47,6 +47,22 @@ static const VMStateDescription vmstate_xmm_reg = {#define VMSTATE_XMM_REGS (_field, _state, _n) \ VMSTATE_STRUCT_ARRAY(_field, _state, _n, 0, vmstate_xmm_reg, XMMReg) +/* YMMH format is the same as XMM */ +static const VMStateDescription vmstate_ymmh_reg = { + .name ="ymmh_reg" , + .version_id =1 , + .minimum_version_id =1 , + .minimum_version_id_old =1 , + .fields = (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, XMMReg) +static const VMStateDescription vmstate_mtrr_var = { .name ="mtrr_var" , .version_id =1 ,
@@ -453,6 +469,10 @@ static const VMStateDescription vmstate_cpu = {/* KVM pvclock msr */ VMSTATE_UINT64_V (system_time_msr, CPUState,11 ),VMSTATE_UINT64_V (wall_clock_msr, CPUState,11 ), + +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 out! */ }
Signature · 1 line
1.7.0.1