XSAVE enabling in QEmu
v4 cover XSAVE enabling in QEmu
Notice the first three patches applied to uq/master branch of qemu-kvm, the last one applied to qemu-kvm master branch. And the last one would only apply after the first three merged in master branch.
PATCH v4 1/4 qemu: kvm: Extend kvm_arch_get_supported_cpuid() to support index
Would use it later for XSAVE related CPUID.
--- kvm.h | 2 +- target-i386/kvm.c | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-)
kvm.h +1 -1
@@ -145,7 +145,7 @@ bool kvm_arch_stop_on_emulation_error(CPUState *env);int kvm_check_extension (KVMState *s,unsigned int extension);uint32_t kvm_arch_get_supported_cpuid (CPUState *env,uint32_t function, -int reg); +uint32_t index,int reg);void kvm_cpu_synchronize_state (CPUState *env);void kvm_cpu_synchronize_post_reset (CPUState *env);void kvm_cpu_synchronize_post_init (CPUState *env);
target-i386/kvm.c +11 -8
@@ -72,7 +72,8 @@ static struct kvm_cpuid2 *try_get_cpuid(KVMState *s, int max)return cpuid; } -uint32_t kvm_arch_get_supported_cpuid (CPUState *env,uint32_t function,int reg) +uint32_t kvm_arch_get_supported_cpuid (CPUState *env,uint32_t function, +uint32_t index,int reg) {struct kvm_cpuid2 *cpuid;int i, max;
@@ -89,7 +90,8 @@ uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function, int reg) }for (i =0 ; i < cpuid->nent; ++i) { -if (cpuid->entries[i].function == function) { +if (cpuid->entries[i].function == function && + cpuid->entries[i].index == index) {switch (reg) {case R_EAX : ret = cpuid->entries[i].eax;
@@ -111,7 +113,7 @@ uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function, int reg)/* On Intel, kvm returns cpuid according to the Intel spec, * so add missing bits according to the AMD spec: */ - cpuid_1_edx =kvm_arch_get_supported_cpuid (env,1 ,R_EDX ); + cpuid_1_edx =kvm_arch_get_supported_cpuid (env,1 ,0 ,R_EDX ); ret |= cpuid_1_edx &0x183f7ff ;break ; }
@@ -127,7 +129,8 @@ uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function, int reg)#else -uint32_t kvm_arch_get_supported_cpuid (CPUState *env,uint32_t function,int reg) +uint32_t kvm_arch_get_supported_cpuid (CPUState *env,uint32_t function, +uint32_t index,int reg) {return -1U ; }
@@ -179,16 +182,16 @@ int kvm_arch_init_vcpu(CPUState *env) env->mp_state =KVM_MP_STATE_RUNNABLE ; - env->cpuid_features &=kvm_arch_get_supported_cpuid (env,1 ,R_EDX ); + env->cpuid_features &=kvm_arch_get_supported_cpuid (env,1 ,0 ,R_EDX ); i = env->cpuid_ext_features &CPUID_EXT_HYPERVISOR ; - env->cpuid_ext_features &=kvm_arch_get_supported_cpuid (env,1 ,R_ECX ); + env->cpuid_ext_features &=kvm_arch_get_supported_cpuid (env,1 ,0 ,R_ECX ); env->cpuid_ext_features |= i; env->cpuid_ext2_features &=kvm_arch_get_supported_cpuid (env,0x80000001 , -R_EDX ); +0 ,R_EDX ); env->cpuid_ext3_features &=kvm_arch_get_supported_cpuid (env,0x80000001 , -R_ECX ); +0 ,R_ECX ); cpuid_i =0 ;
Signature · 1 line
1.7.0.1
PATCH v4 2/4 qemu: Enable XSAVE related CPUID
In reply to Sheng YangWe can support it in KVM now. The 0xd leaf is queried from KVM.
--- target-i386/cpuid.c | 21 +++++++++++++++++++++ 1 files changed, 21 insertions(+), 0 deletions(-)
target-i386/cpuid.c +21 -0
@@ -1067,6 +1067,27 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, *ecx =0 ; *edx =0 ;break ; +case 0xD : +/* Processor Extended State */ +if (!(env->cpuid_ext_features &CPUID_EXT_XSAVE )) { + *eax =0 ; + *ebx =0 ; + *ecx =0 ; + *edx =0 ; +break ; + } +if (kvm_enabled ()) { + *eax =kvm_arch_get_supported_cpuid (env,0xd , count,R_EAX ); + *ebx =kvm_arch_get_supported_cpuid (env,0xd , count,R_EBX ); + *ecx =kvm_arch_get_supported_cpuid (env,0xd , count,R_ECX ); + *edx =kvm_arch_get_supported_cpuid (env,0xd , count,R_EDX ); + }else { + *eax =0 ; + *ebx =0 ; + *ecx =0 ; + *edx =0 ; + } +break ;case 0x80000000 : *eax = env->cpuid_xlevel; *ebx = env->cpuid_vendor1;
Signature · 1 line
1.7.0.1
PATCH v4 3/4 qemu: kvm: Enable XSAVE live migration support
In reply to Sheng Yang--- target-i386/cpu.h | 5 ++ target-i386/kvm.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++ target-i386/machine.c | 20 +++++++ 3 files changed, 159 insertions(+), 0 deletions(-)
target-i386/cpu.h +5 -0
@@ -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;CPUX86State *cpu_x86_init (const char *cpu_model);
target-i386/kvm.c +134 -0
170 lines not on this page · raw message
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 ), +/* 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 out! */ }
Signature · 1 line
1.7.0.1
Re: [PATCH 3/4] qemu: kvm: Enable XSAVE live migration support
Quoted 165 lines · Sheng Yang
Signed-off-by Sheng Yang <[email protected]>--- target-i386/cpu.h | 5 ++ target-i386/kvm.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++ target-i386/machine.c | 20 +++++++ 3 files changed, 159 insertions(+), 0 deletions(-)target-i386/cpu.h +5
-0@@ -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;CPUX86State *cpu_x86_init (const char *cpu_model);target-i386/kvm.c +112
-0@@ -289,6 +289,8 @@ void kvm_arch_reset_vcpu(CPUState *env) }else { env->mp_state =KVM_MP_STATE_RUNNABLE ; } +/* Legal xcr0 for loading */ + env->xcr0 =1 ; }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); } +#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 =qemu_memalign (4096 ,sizeof (struct kvm_xsave )); +memset (xsave,0 ,sizeof (struct kvm_xsave )); + cwd = swd = twd = fop =0 ; + swd = env->fpus & ~(7 <<11 ); + swd |= (env->fpstt &7 ) <<11 ; + cwd = env->fpuc; +for (i =0 ; i <8 ; ++i) + twd |= (!env->fptags[i]) << i; + xsave->region[0 ] = (uint32_t )(swd <<16 ) + cwd; + xsave->region[1 ] = (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 ] = env->mxcsr; + *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV ] = 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 =1 ; + xcrs.flags =0 ; + xcrs.xcrs[0 ].xcr =0 ; + xcrs.xcrs[0 ].value = 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 ; } +#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 =qemu_memalign (4096 ,sizeof (struct kvm_xsave )); + ret =kvm_vcpu_ioctl (env,KVM_GET_XSAVE , xsave); +if (ret <0 ) +return ret; + + cwd = (uint16_t )xsave->region[0 ]; + swd = (uint16_t )(xsave->region[0 ] >>16 ); + twd = (uint16_t )xsave->region[1 ]; + fop = (uint16_t )(xsave->region[1 ] >>16 ); + env->fpstt = (swd >>11 ) &7 ; + env->fpus = swd; + env->fpuc = cwd; +for (i =0 ; i <8 ; ++i) + env->fptags[i] = !((twd >> i) &1 ); + env->mxcsr = 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 = *(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 =kvm_vcpu_ioctl (env,KVM_GET_XCRS , &xcrs); +if (ret <0 ) +return ret; + +for (i =0 ; i < xcrs.nr_xcrs; i++) +/* Only support xcr0 now */ +if (xcrs.xcrs[0 ].xcr ==0 ) { + env->xcr0 = 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 level)if (ret <0 )return ret; +#ifdef KVM_CAP_XSAVE +if (kvm_check_extension (env->kvm_state,KVM_CAP_XSAVE )) + ret =kvm_put_xsave (env); +else + ret =kvm_put_fpu (env); +#else ret =kvm_put_fpu (env);
target-i386/kvm.c int kvm_arch_put_registers(CPUState *env, int level) · line 1090
Quoted 10 lines
target-i386/kvm.c +8
-0+#endif +if (ret <0 ) +return ret; + +#ifdef KVM_CAP_XCRS +if (kvm_check_extension (env->kvm_state,KVM_CAP_XCRS )) + ret =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.
Quoted 55 lines
target-i386/kvm.c +14
-0ret =kvm_put_sregs (env);if (ret <0 )@@ -1009,9 +1129,23 @@ int kvm_arch_get_registers(CPUState *env)if (ret <0 )return ret; +#ifdef KVM_CAP_XSAVE +if (kvm_check_extension (env->kvm_state,KVM_CAP_XSAVE )) + ret =kvm_get_xsave (env); +else + ret =kvm_get_fpu (env); +#else ret =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 =kvm_get_xcrs (env);if (ret <0 )return ret; +#endif ret =kvm_get_sregs (env);if (ret <0 )target-i386/machine.c +16
-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 ,
target-i386/machine.c static const VMStateDescription vmstate_cpu = { · line 478
Quoted 10 lines
target-i386/machine.c +4
-0@@ -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 ), +/* 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 out! */ }
You did not increment CPU_SAVE_VERSION, did you?
Jan
PATCH v4 3/4 qemu: kvm: Enable XSAVE live migration support
--- target-i386/cpu.h | 7 ++- target-i386/kvm.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++- target-i386/machine.c | 20 +++++++ 3 files changed, 163 insertions(+), 3 deletions(-)
target-i386/cpu.h +6 -1
@@ -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;CPUX86State *cpu_x86_init (const char *cpu_model);
@@ -895,7 +900,7 @@ uint64_t cpu_get_tsc(CPUX86State *env);#define cpu_list_id x86_cpu_list#define cpudef_setup x86_cpudef_setup -#define CPU_SAVE_VERSION 11 +#define CPU_SAVE_VERSION 12/* MMU modes definitions */ #define MMU_MODE0_SUFFIX _kernel
target-i386/kvm.c +137 -2
169 lines not on this page · raw message
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 ), +/* 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 out! */ }
Signature · 1 line
1.7.0.1
Re: [PATCH 3/4] qemu: kvm: Enable XSAVE live migration support
Quoted 57 lines · Sheng Yang
Signed-off-by Sheng Yang <[email protected]>--- target-i386/cpu.h | 7 ++- target-i386/kvm.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++- target-i386/machine.c | 20 +++++++ 3 files changed, 163 insertions(+), 3 deletions(-)target-i386/cpu.h +6
-1@@ -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;CPUX86State *cpu_x86_init (const char *cpu_model);@@ -895,7 +900,7 @@ uint64_t cpu_get_tsc(CPUX86State *env);#define cpu_list_id x86_cpu_list#define cpudef_setup x86_cpudef_setup -#define CPU_SAVE_VERSION 11 +#define CPU_SAVE_VERSION 12/* MMU modes definitions */ #define MMU_MODE0_SUFFIX _kerneltarget-i386/kvm.c +10
-0@@ -289,6 +289,8 @@ void kvm_arch_reset_vcpu(CPUState *env) }else { env->mp_state =KVM_MP_STATE_RUNNABLE ; } +/* Legal xcr0 for loading */ + env->xcr0 =1 ; }static int kvm_has_msr_star (CPUState *env)@@ -504,6 +506,68 @@ static int kvm_put_fpu(CPUState *env)return kvm_vcpu_ioctl (env,KVM_SET_FPU , &fpu); } +#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
target-i386/kvm.c static int kvm_put_fpu(CPUState *env) · line 526
Quoted 10 lines
target-i386/kvm.c +10
-0+#endif + +static int kvm_put_xsave (CPUState *env) +{ +#ifdef KVM_CAP_XSAVE +int i; +struct kvm_xsave * xsave; +uint16_t cwd, swd, twd, fop; + +if (kvm_check_extension (env->kvm_state,KVM_CAP_XSAVE ))
That's still one syscall too much for this path (which will be a fast-path for Kemari). Get that value during arch_init.
Quoted 171 lines
target-i386/kvm.c +117
-2+return kvm_put_fpu (env); + + xsave =qemu_memalign (4096 ,sizeof (struct kvm_xsave )); +memset (xsave,0 ,sizeof (struct kvm_xsave )); + cwd = swd = twd = fop =0 ; + swd = env->fpus & ~(7 <<11 ); + swd |= (env->fpstt &7 ) <<11 ; + cwd = env->fpuc; +for (i =0 ; i <8 ; ++i) + twd |= (!env->fptags[i]) << i; + xsave->region[0 ] = (uint32_t )(swd <<16 ) + cwd; + xsave->region[1 ] = (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 ] = env->mxcsr; + *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV ] = 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); +#else +return kvm_put_fpu (env); +#endif +} + +static int kvm_put_xcrs (CPUState *env) +{ +#ifdef KVM_CAP_XCRS +struct kvm_xcrs xcrs; + +if (!kvm_check_extension (env->kvm_state,KVM_CAP_XCRS )) +return 0 ; + + xcrs.nr_xcrs =1 ; + xcrs.flags =0 ; + xcrs.xcrs[0 ].xcr =0 ; + xcrs.xcrs[0 ].value = env->xcr0; +return kvm_vcpu_ioctl (env,KVM_SET_XCRS , &xcrs); +#else +return 0 ; +#endif +} +static int kvm_put_sregs (CPUState *env) {struct kvm_sregs sregs;@@ -621,6 +685,69 @@ static int kvm_get_fpu(CPUState *env)return 0 ; } +static int kvm_get_xsave (CPUState *env) +{ +#ifdef KVM_CAP_XSAVE +struct kvm_xsave * xsave; +int ret, i; +uint16_t cwd, swd, twd, fop; + +if (!kvm_check_extension (env->kvm_state,KVM_CAP_XSAVE )) +return kvm_get_fpu (env); + + xsave =qemu_memalign (4096 ,sizeof (struct kvm_xsave )); + ret =kvm_vcpu_ioctl (env,KVM_GET_XSAVE , xsave); +if (ret <0 ) +return ret; + + cwd = (uint16_t )xsave->region[0 ]; + swd = (uint16_t )(xsave->region[0 ] >>16 ); + twd = (uint16_t )xsave->region[1 ]; + fop = (uint16_t )(xsave->region[1 ] >>16 ); + env->fpstt = (swd >>11 ) &7 ; + env->fpus = swd; + env->fpuc = cwd; +for (i =0 ; i <8 ; ++i) + env->fptags[i] = !((twd >> i) &1 ); + env->mxcsr = 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 = *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV ]; +memcpy (env->ymmh_regs, &xsave->region[XSAVE_YMMH_SPACE ], +sizeof env->ymmh_regs); +return 0 ; +#else +return kvm_get_fpu (env); +#endif +} + +static int kvm_get_xcrs (CPUState *env) +{ +#ifdef KVM_CAP_XCRS +int i, ret; +struct kvm_xcrs xcrs; + +if (!kvm_check_extension (env->kvm_state,KVM_CAP_XCRS )) +return 0 ; + + ret =kvm_vcpu_ioctl (env,KVM_GET_XCRS , &xcrs); +if (ret <0 ) +return ret; + +for (i =0 ; i < xcrs.nr_xcrs; i++) +/* Only support xcr0 now */ +if (xcrs.xcrs[0 ].xcr ==0 ) { + env->xcr0 = xcrs.xcrs[0 ].value; +break ; + } +return 0 ; +#else +return 0 ; +#endif +} +static int kvm_get_sregs (CPUState *env) {struct kvm_sregs sregs;@@ -965,7 +1092,11 @@ int kvm_arch_put_registers(CPUState *env, int level)if (ret <0 )return ret; - ret =kvm_put_fpu (env); + ret =kvm_put_xsave (env); +if (ret <0 ) +return ret; + + ret =kvm_put_xcrs (env);if (ret <0 )return ret;@@ -1009,7 +1140,11 @@ int kvm_arch_get_registers(CPUState *env)if (ret <0 )return ret; - ret =kvm_get_fpu (env); + ret =kvm_get_xsave (env); +if (ret <0 ) +return ret; + + ret =kvm_get_xcrs (env);if (ret <0 )return ret;target-i386/machine.c +16
-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 ,
target-i386/machine.c static const VMStateDescription vmstate_cpu = { · line 478
Quoted 10 lines
target-i386/machine.c +4
-0@@ -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 ), +/* 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 out! */ }
Looks good otherwise.
Thanks,
Jan
Signature · 2 lines
Siemens AG, Corporate Technology, CT T DE IT 1 Corporate Competence Center Embedded Linux
PATCH v4 3/4 qemu: kvm: Enable XSAVE live migration support
--- kvm-all.c | 21 +++++++ kvm.h | 2 + target-i386/cpu.h | 7 ++- target-i386/kvm.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++- target-i386/machine.c | 20 +++++++ 5 files changed, 186 insertions(+), 3 deletions(-)
kvm-all.c +21 -0
@@ -71,6 +71,7 @@ struct KVMState#endif int irqchip_in_kernel;int pit_in_kernel; +int xsave, xcrs; };static KVMState *kvm_state;
@@ -685,6 +686,16 @@ int kvm_init(int smp_cpus) s->debugregs =kvm_check_extension (s,KVM_CAP_DEBUGREGS );#endif + s->xsave =0 ; +#ifdef KVM_CAP_XSAVE + s->xsave =kvm_check_extension (s,KVM_CAP_XSAVE ); +#endif + + s->xcrs =0 ; +#ifdef KVM_CAP_XCRS + s->xcrs =kvm_check_extension (s,KVM_CAP_XCRS ); +#endif + ret =kvm_arch_init (s, smp_cpus);if (ret <0 ) goto err;
@@ -1013,6 +1024,16 @@ int kvm_has_debugregs(void)return kvm_state->debugregs; } +int kvm_has_xsave (void ) +{ +return kvm_state->xsave; +} + +int kvm_has_xcrs (void ) +{ +return kvm_state->xcrs; +} +void kvm_setup_guest_memory (void *start,size_t size) {if (!kvm_has_sync_mmu ()) {
kvm.h +2 -0
@@ -41,6 +41,8 @@ int kvm_has_sync_mmu(void);int kvm_has_vcpu_events (void );int kvm_has_robust_singlestep (void );int kvm_has_debugregs (void ); +int kvm_has_xsave (void ); +int kvm_has_xcrs (void );#ifdef NEED_CPU_H int kvm_init_vcpu (CPUState *env);
target-i386/cpu.h +6 -1
@@ -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;CPUX86State *cpu_x86_init (const char *cpu_model);
@@ -895,7 +900,7 @@ uint64_t cpu_get_tsc(CPUX86State *env);#define cpu_list_id x86_cpu_list#define cpudef_setup x86_cpudef_setup -#define CPU_SAVE_VERSION 11 +#define CPU_SAVE_VERSION 12/* MMU modes definitions */ #define MMU_MODE0_SUFFIX _kernel
target-i386/kvm.c +137 -2
169 lines not on this page · raw message
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 ), +/* 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 out! */ }
Signature · 1 line
1.7.0.1
Re: [PATCH 3/4] qemu: kvm: Enable XSAVE live migration support
Quoted 299 lines · Sheng Yang
Signed-off-by Sheng Yang <[email protected]>--- kvm-all.c | 21 +++++++ kvm.h | 2 + target-i386/cpu.h | 7 ++- target-i386/kvm.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++- target-i386/machine.c | 20 +++++++ 5 files changed, 186 insertions(+), 3 deletions(-)kvm-all.c +21
-0@@ -71,6 +71,7 @@ struct KVMState#endif int irqchip_in_kernel;int pit_in_kernel; +int xsave, xcrs; };static KVMState *kvm_state;@@ -685,6 +686,16 @@ int kvm_init(int smp_cpus) s->debugregs =kvm_check_extension (s,KVM_CAP_DEBUGREGS );#endif + s->xsave =0 ; +#ifdef KVM_CAP_XSAVE + s->xsave =kvm_check_extension (s,KVM_CAP_XSAVE ); +#endif + + s->xcrs =0 ; +#ifdef KVM_CAP_XCRS + s->xcrs =kvm_check_extension (s,KVM_CAP_XCRS ); +#endif + ret =kvm_arch_init (s, smp_cpus);if (ret <0 ) goto err;@@ -1013,6 +1024,16 @@ int kvm_has_debugregs(void)return kvm_state->debugregs; } +int kvm_has_xsave (void ) +{ +return kvm_state->xsave; +} + +int kvm_has_xcrs (void ) +{ +return kvm_state->xcrs; +} +void kvm_setup_guest_memory (void *start,size_t size) {if (!kvm_has_sync_mmu ()) {kvm.h +2
-0@@ -41,6 +41,8 @@ int kvm_has_sync_mmu(void);int kvm_has_vcpu_events (void );int kvm_has_robust_singlestep (void );int kvm_has_debugregs (void ); +int kvm_has_xsave (void ); +int kvm_has_xcrs (void );#ifdef NEED_CPU_H int kvm_init_vcpu (CPUState *env);target-i386/cpu.h +6
-1@@ -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;CPUX86State *cpu_x86_init (const char *cpu_model);@@ -895,7 +900,7 @@ uint64_t cpu_get_tsc(CPUX86State *env);#define cpu_list_id x86_cpu_list#define cpudef_setup x86_cpudef_setup -#define CPU_SAVE_VERSION 11 +#define CPU_SAVE_VERSION 12/* MMU modes definitions */ #define MMU_MODE0_SUFFIX _kerneltarget-i386/kvm.c +137
-2@@ -289,6 +289,8 @@ void kvm_arch_reset_vcpu(CPUState *env) }else { env->mp_state =KVM_MP_STATE_RUNNABLE ; } +/* Legal xcr0 for loading */ + env->xcr0 =1 ; }static int kvm_has_msr_star (CPUState *env)@@ -504,6 +506,68 @@ static int kvm_put_fpu(CPUState *env)return kvm_vcpu_ioctl (env,KVM_SET_FPU , &fpu); } +#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 + +static int kvm_put_xsave (CPUState *env) +{ +#ifdef KVM_CAP_XSAVE +int i; +struct kvm_xsave * xsave; +uint16_t cwd, swd, twd, fop; + +if (!kvm_has_xsave ()) +return kvm_put_fpu (env); + + xsave =qemu_memalign (4096 ,sizeof (struct kvm_xsave )); +memset (xsave,0 ,sizeof (struct kvm_xsave )); + cwd = swd = twd = fop =0 ; + swd = env->fpus & ~(7 <<11 ); + swd |= (env->fpstt &7 ) <<11 ; + cwd = env->fpuc; +for (i =0 ; i <8 ; ++i) + twd |= (!env->fptags[i]) << i; + xsave->region[0 ] = (uint32_t )(swd <<16 ) + cwd; + xsave->region[1 ] = (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 ] = env->mxcsr; + *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV ] = 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); +#else +return kvm_put_fpu (env); +#endif +} + +static int kvm_put_xcrs (CPUState *env) +{ +#ifdef KVM_CAP_XCRS +struct kvm_xcrs xcrs; + +if (!kvm_has_xcrs ()) +return 0 ; + + xcrs.nr_xcrs =1 ; + xcrs.flags =0 ; + xcrs.xcrs[0 ].xcr =0 ; + xcrs.xcrs[0 ].value = env->xcr0; +return kvm_vcpu_ioctl (env,KVM_SET_XCRS , &xcrs); +#else +return 0 ; +#endif +} +static int kvm_put_sregs (CPUState *env) {struct kvm_sregs sregs;@@ -621,6 +685,69 @@ static int kvm_get_fpu(CPUState *env)return 0 ; } +static int kvm_get_xsave (CPUState *env) +{ +#ifdef KVM_CAP_XSAVE +struct kvm_xsave * xsave; +int ret, i; +uint16_t cwd, swd, twd, fop; + +if (!kvm_has_xsave ()) +return kvm_get_fpu (env); + + xsave =qemu_memalign (4096 ,sizeof (struct kvm_xsave )); + ret =kvm_vcpu_ioctl (env,KVM_GET_XSAVE , xsave); +if (ret <0 ) +return ret; + + cwd = (uint16_t )xsave->region[0 ]; + swd = (uint16_t )(xsave->region[0 ] >>16 ); + twd = (uint16_t )xsave->region[1 ]; + fop = (uint16_t )(xsave->region[1 ] >>16 ); + env->fpstt = (swd >>11 ) &7 ; + env->fpus = swd; + env->fpuc = cwd; +for (i =0 ; i <8 ; ++i) + env->fptags[i] = !((twd >> i) &1 ); + env->mxcsr = 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 = *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV ]; +memcpy (env->ymmh_regs, &xsave->region[XSAVE_YMMH_SPACE ], +sizeof env->ymmh_regs); +return 0 ; +#else +return kvm_get_fpu (env); +#endif +} + +static int kvm_get_xcrs (CPUState *env) +{ +#ifdef KVM_CAP_XCRS +int i, ret; +struct kvm_xcrs xcrs; + +if (!kvm_has_xcrs ()) +return 0 ; + + ret =kvm_vcpu_ioctl (env,KVM_GET_XCRS , &xcrs); +if (ret <0 ) +return ret; + +for (i =0 ; i < xcrs.nr_xcrs; i++) +/* Only support xcr0 now */ +if (xcrs.xcrs[0 ].xcr ==0 ) { + env->xcr0 = xcrs.xcrs[0 ].value; +break ; + } +return 0 ; +#else +return 0 ; +#endif +} +static int kvm_get_sregs (CPUState *env) {struct kvm_sregs sregs;@@ -965,7 +1092,11 @@ int kvm_arch_put_registers(CPUState *env, int level)if (ret <0 )return ret; - ret =kvm_put_fpu (env); + ret =kvm_put_xsave (env); +if (ret <0 ) +return ret; + + ret =kvm_put_xcrs (env);if (ret <0 )return ret;@@ -1009,7 +1140,11 @@ int kvm_arch_get_registers(CPUState *env)if (ret <0 )return ret; - ret =kvm_get_fpu (env); + ret =kvm_get_xsave (env); +if (ret <0 ) +return ret; + + ret =kvm_get_xcrs (env);if (ret <0 )return ret;target-i386/machine.c +16
-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 ,
target-i386/machine.c static const VMStateDescription vmstate_cpu = { · line 478
Quoted 10 lines
target-i386/machine.c +4
-0@@ -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 ), +/* 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 out! */ }
Looks all fine to me now.
Thanks again,
Jan
Signature · 2 lines
Siemens AG, Corporate Technology, CT T DE IT 1 Corporate Competence Center Embedded Linux
PATCH v4 4/4 qemu-kvm: Enable XSAVE live migration support
In reply to Sheng YangBased on upstream xsave related fields.
--- qemu-kvm-x86.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- qemu-kvm.c | 24 ++++++++++++++ qemu-kvm.h | 28 ++++++++++++++++ 3 files changed, 146 insertions(+), 1 deletions(-)
qemu-kvm-x86.c +94 -1
@@ -772,10 +772,26 @@ static void get_seg(SegmentCache *lhs, const struct kvm_segment *rhs) | (rhs->avl * DESC_AVL_MASK); } +#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)kvm_set_regs (env, ®s); +#ifdef KVM_CAP_XSAVE +if (kvm_check_extension (kvm_state,KVM_CAP_XSAVE )) { +uint16_t cwd, swd, twd, fop; + + xsave =qemu_memalign (4096 ,sizeof (struct kvm_xsave )); +memset (xsave,0 ,sizeof (struct kvm_xsave )); + cwd = swd = twd = fop =0 ; + swd = env->fpus & ~(7 <<11 ); + swd |= (env->fpstt &7 ) <<11 ; + cwd = env->fpuc; +for (i =0 ; i <8 ; ++i) + twd |= (!env->fptags[i]) << i; + xsave->region[0 ] = (uint32_t )(swd <<16 ) + cwd; + xsave->region[1 ] = (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 ] = env->mxcsr; + *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV ] = env->xstate_bv; +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 =1 ; + xcrs.flags =0 ; + xcrs.xcrs[0 ].xcr =0 ; + xcrs.xcrs[0 ].value = env->xcr0; +kvm_set_xcrs (env, &xcrs); + } +#endif /* KVM_CAP_XCRS */ + }else { +#endif /* KVM_CAP_XSAVE */ 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; + 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); +#ifdef KVM_CAP_XSAVE + } +#endif memset (sregs.interrupt_bitmap,0 ,sizeof (sregs.interrupt_bitmap));if (env->interrupt_injected >=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 = regs.rflags; env->eip = regs.rip; +#ifdef KVM_CAP_XSAVE +if (kvm_check_extension (kvm_state,KVM_CAP_XSAVE )) { +uint16_t cwd, swd, twd, fop; + xsave =qemu_memalign (4096 ,sizeof (struct kvm_xsave )); +kvm_get_xsave (env, xsave); + cwd = (uint16_t )xsave->region[0 ]; + swd = (uint16_t )(xsave->region[0 ] >>16 ); + twd = (uint16_t )xsave->region[1 ]; + fop = (uint16_t )(xsave->region[1 ] >>16 ); + env->fpstt = (swd >>11 ) &7 ; + env->fpus = swd; + env->fpuc = cwd; +for (i =0 ; i <8 ; ++i) + env->fptags[i] = !((twd >> i) &1 ); + env->mxcsr = 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 = *(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 ==0 ) + env->xcr0 = xcrs.xcrs[0 ].value; + } +#endif + }else { +#endif kvm_get_fpu (env, &fpu); env->fpstt = (fpu.fsw >>11 ) &7 ; env->fpus = 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 = fpu.mxcsr; +#ifdef KVM_CAP_XSAVE + } +#endif kvm_get_sregs (env, &sregs);
qemu-kvm.c +24 -0
@@ -503,6 +503,30 @@ 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 + +#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 = env->kvm_run->mmio.phys_addr;
qemu-kvm.h +28 -0
@@ -300,6 +300,34 @@ 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 + +#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 *
Signature · 1 line
1.7.0.1
Re: [PATCH 4/4] qemu-kvm: Enable XSAVE live migration support
Quoted 68 lines · Sheng Yang
Based on upstream xsave related fields.
Signed-off-by Sheng Yang <[email protected]>--- qemu-kvm-x86.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- qemu-kvm.c | 24 ++++++++++++++ qemu-kvm.h | 28 ++++++++++++++++ 3 files changed, 146 insertions(+), 1 deletions(-)qemu-kvm-x86.c +40
-0@@ -772,10 +772,26 @@ static void get_seg(SegmentCache *lhs, const struct kvm_segment *rhs) | (rhs->avl * DESC_AVL_MASK); } +#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)kvm_set_regs (env, ®s); +#ifdef KVM_CAP_XSAVE +if (kvm_check_extension (kvm_state,KVM_CAP_XSAVE )) { +uint16_t cwd, swd, twd, fop; + + xsave =qemu_memalign (4096 ,sizeof (struct kvm_xsave )); +memset (xsave,0 ,sizeof (struct kvm_xsave )); + cwd = swd = twd = fop =0 ; + swd = env->fpus & ~(7 <<11 ); + swd |= (env->fpstt &7 ) <<11 ; + cwd = env->fpuc; +for (i =0 ; i <8 ; ++i) + twd |= (!env->fptags[i]) << i; + xsave->region[0 ] = (uint32_t )(swd <<16 ) + cwd; + xsave->region[1 ] = (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 ] = env->mxcsr; + *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV ] = env->xstate_bv; +memcpy (&xsave->region[XSAVE_YMMH_SPACE ], env->ymmh_regs, +sizeof env->ymmh_regs); +kvm_set_xsave (env, xsave); +#ifdef KVM_CAP_XCRS
qemu-kvm-x86.c void kvm_arch_load_regs(CPUState *env, int level) · line 858
Quoted 10 lines
qemu-kvm-x86.c +10
-0+if (kvm_check_extension (kvm_state,KVM_CAP_XCRS )) { + xcrs.nr_xcrs =1 ; + xcrs.flags =0 ; + xcrs.xcrs[0 ].xcr =0 ; + xcrs.xcrs[0 ].value = 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
Quoted 152 lines
qemu-kvm-x86.c +44
-1memset (&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; + 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); +#ifdef KVM_CAP_XSAVE + } +#endif memset (sregs.interrupt_bitmap,0 ,sizeof (sregs.interrupt_bitmap));if (env->interrupt_injected >=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 = regs.rflags; env->eip = regs.rip; +#ifdef KVM_CAP_XSAVE +if (kvm_check_extension (kvm_state,KVM_CAP_XSAVE )) { +uint16_t cwd, swd, twd, fop; + xsave =qemu_memalign (4096 ,sizeof (struct kvm_xsave )); +kvm_get_xsave (env, xsave); + cwd = (uint16_t )xsave->region[0 ]; + swd = (uint16_t )(xsave->region[0 ] >>16 ); + twd = (uint16_t )xsave->region[1 ]; + fop = (uint16_t )(xsave->region[1 ] >>16 ); + env->fpstt = (swd >>11 ) &7 ; + env->fpus = swd; + env->fpuc = cwd; +for (i =0 ; i <8 ; ++i) + env->fptags[i] = !((twd >> i) &1 ); + env->mxcsr = 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 = *(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 ==0 ) + env->xcr0 = xcrs.xcrs[0 ].value; + } +#endif + }else { +#endif kvm_get_fpu (env, &fpu); env->fpstt = (fpu.fsw >>11 ) &7 ; env->fpus = 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 = fpu.mxcsr; +#ifdef KVM_CAP_XSAVE + } +#endif kvm_get_sregs (env, &sregs);qemu-kvm.c +24
-0@@ -503,6 +503,30 @@ 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 + +#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 = env->kvm_run->mmio.phys_addr;qemu-kvm.h +28
-0@@ -300,6 +300,34 @@ 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 + +#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 *
Re: [PATCH 4/4] qemu-kvm: Enable XSAVE live migration support
Quoted 85 lines · On Thursday 17 June 2010 15:41:43 Jan Kiszka wrote:
Quoted 84 lines · Sheng Yang
Based on upstream xsave related fields.
Signed-off-by Sheng Yang <[email protected]>---
qemu-kvm-x86.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- qemu-kvm.c | 24 ++++++++++++++ qemu-kvm.h | 28 ++++++++++++++++ 3 files changed, 146 insertions(+), 1 deletions(-)qemu-kvm-x86.c +46
-0@@ -772,10 +772,26 @@ static void get_seg(SegmentCache *lhs, const struct kvm_segment *rhs) | (rhs->avl * DESC_AVL_MASK); } +#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)kvm_set_regs (env, ®s); +#ifdef KVM_CAP_XSAVE +if (kvm_check_extension (kvm_state,KVM_CAP_XSAVE )) { +uint16_t cwd, swd, twd, fop; + + xsave =qemu_memalign (4096 ,sizeof (struct kvm_xsave )); +memset (xsave,0 ,sizeof (struct kvm_xsave )); + cwd = swd = twd = fop =0 ; + swd = env->fpus & ~(7 <<11 ); + swd |= (env->fpstt &7 ) <<11 ; + cwd = env->fpuc; +for (i =0 ; i <8 ; ++i) + twd |= (!env->fptags[i]) << i; + xsave->region[0 ] = (uint32_t )(swd <<16 ) + cwd; + xsave->region[1 ] = (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 ] = env->mxcsr; + *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV ] = env->xstate_bv; +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 =1 ; + xcrs.flags =0 ; + xcrs.xcrs[0 ].xcr =0 ; + xcrs.xcrs[0 ].value = env->xcr0; +kvm_set_xcrs (env, &xcrs);
Quoted 8 lines
qemu-kvm-x86.c void kvm_arch_load_regs(CPUState *env, int level) · line 858
Quoted 4 lines
qemu-kvm-x86.c +4
-0+ } +#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.
Still lots of codes in kvm_arch_load/save_regs() duplicate with ones in kvm.c, e.g. kvm_get/put_sregs, kvm_get/put_msrs. So would like to wait for merging.
--
regards
Yang, Sheng
Quoted 178 lines
Jan
Quoted 175 lines
qemu-kvm-x86.c +4
-1memset (&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; + 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); +#ifdef KVM_CAP_XSAVE + } +#endif memset(sregs.interrupt_bitmap, 0, sizeof(sregs.interrupt_bitmap)); if (env->interrupt_injected >= 0) {qemu-kvm-x86.c +6
-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;qemu-kvm-x86.c +31
-0@@ -965,6 +1024,37 @@ void kvm_arch_save_regs(CPUState *env) env->eflags = regs.rflags; env->eip = regs.rip; +#ifdef KVM_CAP_XSAVE +if (kvm_check_extension (kvm_state,KVM_CAP_XSAVE )) { +uint16_t cwd, swd, twd, fop; + xsave =qemu_memalign (4096 ,sizeof (struct kvm_xsave )); +kvm_get_xsave (env, xsave); + cwd = (uint16_t )xsave->region[0 ]; + swd = (uint16_t )(xsave->region[0 ] >>16 ); + twd = (uint16_t )xsave->region[1 ]; + fop = (uint16_t )(xsave->region[1 ] >>16 ); + env->fpstt = (swd >>11 ) &7 ; + env->fpus = swd; + env->fpuc = cwd; +for (i =0 ; i <8 ; ++i) + env->fptags[i] = !((twd >> i) &1 ); + env->mxcsr = 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 = *(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 ==0 ) + env->xcr0 = xcrs.xcrs[0 ].value; + } +#endif + }else { +#endif kvm_get_fpu (env, &fpu);env->fpstt = (fpu.fsw >> 11) & 7; env->fpus = fpu.fsw;qemu-kvm-x86.c +3
-0@@ -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 = fpu.mxcsr; +#ifdef KVM_CAP_XSAVE + } +#endif kvm_get_sregs(env, &sregs);qemu-kvm.c +24
-0@@ -503,6 +503,30 @@ 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 + +#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 = env->kvm_run->mmio.phys_addr;qemu-kvm.h +28
-0@@ -300,6 +300,34 @@ 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 + +#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 *
Re: [PATCH 4/4] qemu-kvm: Enable XSAVE live migration support
Quoted 94 lines · Sheng Yang
Quoted 84 lines · On Thursday 17 June 2010 15:41:43 Jan Kiszka wrote:
Quoted 83 lines · Sheng Yang
Based on upstream xsave related fields.
Signed-off-by Sheng Yang <[email protected]>---
qemu-kvm-x86.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- qemu-kvm.c | 24 ++++++++++++++ qemu-kvm.h | 28 ++++++++++++++++ 3 files changed, 146 insertions(+), 1 deletions(-)qemu-kvm-x86.c +45
-0@@ -772,10 +772,26 @@ static void get_seg(SegmentCache *lhs, const struct kvm_segment *rhs) | (rhs->avl * DESC_AVL_MASK); } +#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)kvm_set_regs (env, ®s); +#ifdef KVM_CAP_XSAVE +if (kvm_check_extension (kvm_state,KVM_CAP_XSAVE )) { +uint16_t cwd, swd, twd, fop; + + xsave =qemu_memalign (4096 ,sizeof (struct kvm_xsave )); +memset (xsave,0 ,sizeof (struct kvm_xsave )); + cwd = swd = twd = fop =0 ; + swd = env->fpus & ~(7 <<11 ); + swd |= (env->fpstt &7 ) <<11 ; + cwd = env->fpuc; +for (i =0 ; i <8 ; ++i) + twd |= (!env->fptags[i]) << i; + xsave->region[0 ] = (uint32_t )(swd <<16 ) + cwd; + xsave->region[1 ] = (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 ] = env->mxcsr; + *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV ] = env->xstate_bv; +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 =1 ; + xcrs.flags =0 ; + xcrs.xcrs[0 ].xcr =0 ; + xcrs.xcrs[0 ].value = env->xcr0;Quoted 8 lines
qemu-kvm-x86.c void kvm_arch_load_regs(CPUState *env, int level) · line 858
Quoted 5 lines
qemu-kvm-x86.c +5
-0+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.
Quoted 2 lines
Still lots of codes in kvm_arch_load/save_regs() duplicate with ones in
kvm.c, e.g. kvm_get/put_sregs, kvm_get/put_msrs. So would like to wait for merging.
That we still have some legacy here is no good reason to increase it. Just check how debugregs were introduced.
Jan
PATCH 1/1 qemu-kvm: Replace kvm_set/get_fpu() with upstream version.
---
Would send out XSAVE patch after the upstream ones have been merged, since the patch would be affected by the merge.
qemu-kvm-x86.c | 23 ++--------------------- qemu-kvm.c | 10 ---------- qemu-kvm.h | 30 ------------------------------ target-i386/kvm.c | 5 ++++- 4 files changed, 6 insertions(+), 62 deletions(-)
qemu-kvm-x86.c +2 -21
@@ -775,7 +775,6 @@ static void get_seg(SegmentCache *lhs, const struct kvm_segment *rhs)void kvm_arch_load_regs (CPUState *env,int level) {struct kvm_regs regs; -struct kvm_fpu fpu;struct kvm_sregs sregs;struct kvm_msr_entry msrs[100 ];int rc, n, i;
@@ -806,16 +805,7 @@ 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); +kvm_put_fpu (env);memset (sregs.interrupt_bitmap,0 ,sizeof (sregs.interrupt_bitmap));if (env->interrupt_injected >=0 ) {
@@ -933,7 +923,6 @@ void kvm_arch_load_regs(CPUState *env, int level)void kvm_arch_save_regs (CPUState *env) {struct kvm_regs regs; -struct kvm_fpu fpu;struct kvm_sregs sregs;struct kvm_msr_entry msrs[100 ];uint32_t hflags;
@@ -965,15 +954,7 @@ 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; +kvm_get_fpu (env);kvm_get_sregs (env, &sregs);
qemu-kvm.c +0 -10
@@ -461,16 +461,6 @@ int kvm_set_regs(CPUState *env, struct kvm_regs *regs)return kvm_vcpu_ioctl (env,KVM_SET_REGS , regs); } -int kvm_get_fpu (CPUState *env,struct kvm_fpu *fpu) -{ -return kvm_vcpu_ioctl (env,KVM_GET_FPU , fpu); -} - -int kvm_set_fpu (CPUState *env,struct kvm_fpu *fpu) -{ -return kvm_vcpu_ioctl (env,KVM_SET_FPU , fpu); -} -int kvm_get_sregs (CPUState *env,struct kvm_sregs *sregs) {return kvm_vcpu_ioctl (env,KVM_GET_SREGS , sregs);
qemu-kvm.h +0 -30
@@ -222,36 +222,6 @@ int kvm_get_regs(CPUState *env, struct kvm_regs *regs);* \return 0 on success */ int kvm_set_regs (CPUState *env,struct kvm_regs *regs); -/*! -* \brief Read VCPU fpu registers -* -* This gets the FPU registers from the VCPU and outputs them -* into a kvm_fpu structure -* -* \note This function returns a \b copy of the VCPUs registers.\n -* If you wish to modify the VCPU FPU registers, you should call kvm_set_fpu() -* -* \param kvm Pointer to the current kvm_context -* \param vcpu Which virtual CPU should get dumped -* \param fpu Pointer to a kvm_fpu which will be populated with the VCPUs -* fpu registers values -* \return 0 on success -*/ -int kvm_get_fpu (CPUState *env,struct kvm_fpu *fpu); - -/*! -* \brief Write VCPU fpu registers -* -* This sets the FPU registers on the VCPU from a kvm_fpu structure -* -* \note When this function returns, the fpu pointer and the data it points to -* can be discarded -* \param kvm Pointer to the current kvm_context -* \param vcpu Which virtual CPU should get dumped -* \param fpu Pointer to a kvm_fpu which holds the new vcpu fpu state -* \return 0 on success -*/ -int kvm_set_fpu (CPUState *env,struct kvm_fpu *fpu);/*! * \brief Read VCPU system registers
target-i386/kvm.c +4 -1
@@ -488,6 +488,7 @@ static int kvm_getput_regs(CPUState *env, int set) return ret; } +#endif /* KVM_UPSTREAM */ static int kvm_put_fpu (CPUState *env) {
@@ -507,6 +508,7 @@ static int kvm_put_fpu(CPUState *env)return kvm_vcpu_ioctl (env,KVM_SET_FPU , &fpu); } +#ifdef KVM_UPSTREAM static int kvm_put_sregs (CPUState *env) {struct kvm_sregs sregs;
@@ -605,7 +607,7 @@ static int kvm_put_msrs(CPUState *env, int level) return kvm_vcpu_ioctl(env, KVM_SET_MSRS, &msr_data); } - +#endif /* KVM_UPSTREAM */ static int kvm_get_fpu (CPUState *env) {
@@ -628,6 +630,7 @@ static int kvm_get_fpu(CPUState *env)return 0 ; } +#ifdef KVM_UPSTREAM static int kvm_get_sregs (CPUState *env) {struct kvm_sregs sregs;
Signature · 1 line
1.7.0.1
Re: [PATCH] qemu-kvm: Replace kvm_set/get_fpu() with upstream version.
Quoted 159 lines · Sheng Yang
Signed-off-by Sheng Yang <[email protected]>---
Would send out XSAVE patch after the upstream ones have been merged, since the patch would be affected by the merge.
qemu-kvm-x86.c | 23 ++--------------------- qemu-kvm.c | 10 ---------- qemu-kvm.h | 30 ------------------------------ target-i386/kvm.c | 5 ++++- 4 files changed, 6 insertions(+), 62 deletions(-)qemu-kvm-x86.c +2
-21@@ -775,7 +775,6 @@ static void get_seg(SegmentCache *lhs, const struct kvm_segment *rhs)void kvm_arch_load_regs (CPUState *env,int level) {struct kvm_regs regs; -struct kvm_fpu fpu;struct kvm_sregs sregs;struct kvm_msr_entry msrs[100 ];int rc, n, i;@@ -806,16 +805,7 @@ 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); +kvm_put_fpu (env);memset (sregs.interrupt_bitmap,0 ,sizeof (sregs.interrupt_bitmap));if (env->interrupt_injected >=0 ) {@@ -933,7 +923,6 @@ void kvm_arch_load_regs(CPUState *env, int level)void kvm_arch_save_regs (CPUState *env) {struct kvm_regs regs; -struct kvm_fpu fpu;struct kvm_sregs sregs;struct kvm_msr_entry msrs[100 ];uint32_t hflags;@@ -965,15 +954,7 @@ 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; +kvm_get_fpu (env);kvm_get_sregs (env, &sregs);qemu-kvm.c +0
-10@@ -461,16 +461,6 @@ int kvm_set_regs(CPUState *env, struct kvm_regs *regs)return kvm_vcpu_ioctl (env,KVM_SET_REGS , regs); } -int kvm_get_fpu (CPUState *env,struct kvm_fpu *fpu) -{ -return kvm_vcpu_ioctl (env,KVM_GET_FPU , fpu); -} - -int kvm_set_fpu (CPUState *env,struct kvm_fpu *fpu) -{ -return kvm_vcpu_ioctl (env,KVM_SET_FPU , fpu); -} -int kvm_get_sregs (CPUState *env,struct kvm_sregs *sregs) {return kvm_vcpu_ioctl (env,KVM_GET_SREGS , sregs);qemu-kvm.h +0
-30@@ -222,36 +222,6 @@ int kvm_get_regs(CPUState *env, struct kvm_regs *regs);* \return 0 on success */ int kvm_set_regs (CPUState *env,struct kvm_regs *regs); -/*! -* \brief Read VCPU fpu registers -* -* This gets the FPU registers from the VCPU and outputs them -* into a kvm_fpu structure -* -* \note This function returns a \b copy of the VCPUs registers.\n -* If you wish to modify the VCPU FPU registers, you should call kvm_set_fpu() -* -* \param kvm Pointer to the current kvm_context -* \param vcpu Which virtual CPU should get dumped -* \param fpu Pointer to a kvm_fpu which will be populated with the VCPUs -* fpu registers values -* \return 0 on success -*/ -int kvm_get_fpu (CPUState *env,struct kvm_fpu *fpu); - -/*! -* \brief Write VCPU fpu registers -* -* This sets the FPU registers on the VCPU from a kvm_fpu structure -* -* \note When this function returns, the fpu pointer and the data it points to -* can be discarded -* \param kvm Pointer to the current kvm_context -* \param vcpu Which virtual CPU should get dumped -* \param fpu Pointer to a kvm_fpu which holds the new vcpu fpu state -* \return 0 on success -*/ -int kvm_set_fpu (CPUState *env,struct kvm_fpu *fpu);/*! * \brief Read VCPU system registers target-i386/kvm.c +3
-1@@ -488,6 +488,7 @@ static int kvm_getput_regs(CPUState *env, int set) return ret; } +#endif /* KVM_UPSTREAM */ static int kvm_put_fpu (CPUState *env) {@@ -507,6 +508,7 @@ static int kvm_put_fpu(CPUState *env)return kvm_vcpu_ioctl (env,KVM_SET_FPU , &fpu); } +#ifdef KVM_UPSTREAM static int kvm_put_sregs (CPUState *env) {struct kvm_sregs sregs;@@ -605,7 +607,7 @@ static int kvm_put_msrs(CPUState *env, int level) return kvm_vcpu_ioctl(env, KVM_SET_MSRS, &msr_data); } - +#endif /* KVM_UPSTREAM */ static int kvm_get_fpu (CPUState *env) {
target-i386/kvm.c static int kvm_get_fpu(CPUState *env) · line 636
Quoted 7 lines
target-i386/kvm.c +1
-0@@ -628,6 +630,7 @@ static int kvm_get_fpu(CPUState *env)return 0 ; } +#ifdef KVM_UPSTREAM static int kvm_get_sregs (CPUState *env) {struct kvm_sregs sregs;
Perfect, another step forward towards upstream!
Thanks,
Jan
Signature · 2 lines
Siemens AG, Corporate Technology, CT T DE IT 1 Corporate Competence Center Embedded Linux
Marcelo Tosatti
AppliedQuoted 3 lines · Sheng Yang
Notice the first three patches applied to uq/master branch of qemu-kvm, the last one applied to qemu-kvm master branch. And the last one would only apply after the first three merged in master branch.
Applied, thanks.