qemu: kvm: Extend kvm_arch_get_supported_cpuid() to support index
PATCH 1/3 qemu: kvm: Extend kvm_arch_get_supported_cpuid() to support index
Would use it later for XSAVE related CPUID.
Signed-off-by Sheng Yang <[email protected]>
--- kvm.h | 2 +- target-i386/kvm.c | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-)
kvm.h +1 -1
@@ -152,7 +152,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
@@ -71,7 +71,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;
@@ -88,7 +89,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;
@@ -110,7 +112,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 ; }
@@ -126,7 +128,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 ; }
@@ -190,16 +193,16 @@ int kvm_arch_init_vcpu(CPUState *env)#endif - 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 2/3 qemu: Enable XSAVE related CPUID
We can support it in KVM now. The 0xd leaf is queried from KVM.
Signed-off-by Sheng Yang <[email protected]>
--- target-i386/cpuid.c | 21 +++++++++++++++++++++ 1 files changed, 21 insertions(+), 0 deletions(-)
target-i386/cpuid.c +21 -0
@@ -1081,6 +1081,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
Re: [PATCH 2/3] qemu: Enable XSAVE related CPUID
Quoted 1 line · On Thursday 10 June 2010 11:31:02 Sheng Yang wrote:
We can support it in KVM now. The
0xdleaf is queried from KVM.
Hi Marcelo & Avi
How about patch 1 and 2 in this series? They are used to enable XSAVE cpuid.
--
regards
Yang, Sheng
Quoted 38 lines
Signed-off-by Sheng Yang <[email protected]>--- target-i386/cpuid.c | 21 +++++++++++++++++++++ 1 files changed, 21 insertions(+), 0 deletions(-)target-i386/cpuid.c +21
-0@@ -1081,6 +1081,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;
Marcelo Tosatti
AppliedRe: [PATCH 2/3] qemu: Enable XSAVE related CPUID
Quoted 6 lines · Sheng Yang
Quoted 1 line · On Thursday 10 June 2010 11:31:02 Sheng Yang wrote:
We can support it in KVM now. The
0xdleaf is queried from KVM.Hi Marcelo & Avi
How about patch 1 and 2 in this series? They are used to enable XSAVE cpuid.
Applied.
PATCH 3/3 qemu: kvm: Enable XSAVE live migration support
In reply to Sheng YangSigned-off-by Sheng Yang <[email protected]>
--- qemu-kvm-x86.c | 114 ++++++++++++++++++++++++++++++++++++++++-------- qemu-kvm.c | 24 ++++++++++ qemu-kvm.h | 28 ++++++++++++ target-i386/cpu.h | 6 +++ target-i386/machine.c | 21 +++++++++ 5 files changed, 174 insertions(+), 19 deletions(-)
qemu-kvm-x86.c +95 -19
@@ -772,10 +772,20 @@ static void get_seg(SegmentCache *lhs, const struct kvm_segment *rhs) | (rhs->avl * DESC_AVL_MASK); } +#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 +void kvm_arch_load_regs (CPUState *env,int level) {struct kvm_regs regs;struct kvm_fpu fpu; +struct kvm_xsave * xsave; +struct kvm_xcrs xcrs;struct kvm_sregs sregs;struct kvm_msr_entry msrs[100 ];int rc, n, i;
@@ -806,16 +816,50 @@ 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 )) { +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; + xsave->region[XSAVE_XSTATE_BV ] = (uint32_t )env->xstate_bv; + xsave->region[XSAVE_XSTATE_BV +1 ] = + (uint32_t )(env->xstate_bv >>32 ); +memcpy (&xsave->region[XSAVE_YMMH_SPACE ], env->ymmh_regs, +sizeof env->ymmh_regs); + xsave->size = env->xsave_size; +kvm_set_xsave (env, xsave); +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); + } + }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 ) {
@@ -934,6 +978,8 @@ void kvm_arch_save_regs(CPUState *env) {struct kvm_regs regs;struct kvm_fpu fpu; +struct kvm_xsave * xsave; +struct kvm_xcrs xcrs;struct kvm_sregs sregs;struct kvm_msr_entry msrs[100 ];uint32_t hflags;
@@ -965,15 +1011,45 @@ 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 )) { +uint16_t cwd, swd, twd, fop; + xsave =qemu_memalign (4096 ,sizeof (struct kvm_xsave )); +kvm_get_xsave (env, xsave); + env->xsave_size = xsave->size; + 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 +1 ]) <<32 ) + + xsave->region[XSAVE_XSTATE_BV ]; +memcpy (env->ymmh_regs, &xsave->region[XSAVE_YMMH_SPACE ], +sizeof env->ymmh_regs); +if (kvm_check_extension (kvm_state,KVM_CAP_XCRS )) { +kvm_get_xcrs (env, &xcrs); + env->xcr0 = xcrs.xcrs[0 ].value; + } + }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 +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 *
target-i386/cpu.h +6 -0
@@ -736,6 +736,12 @@ typedef struct CPUX86State {uint16_t fpregs_format_vmstate;int kvm_vcpu_update_vapic; + +uint32_t xsave_size; +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 +21 -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,11 @@ 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_UINT32_V (xsave_size, CPUState,12 ), +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