* [PATCH 1/3] qemu: kvm: Extend kvm_arch_get_supported_cpuid() to support index @ 2010-06-10 3:31 ` Sheng Yang 0 siblings, 0 replies; 10+ messages in thread From: Sheng Yang @ 2010-06-10 3:31 UTC (permalink / raw) To: Avi Kivity, Marcelo Tosatti, Anthony Liguori; +Cc: kvm, qemu-devel, Sheng Yang Would use it later for XSAVE related CPUID. Signed-off-by: Sheng Yang <sheng@linux.intel.com> --- kvm.h | 2 +- target-i386/kvm.c | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/kvm.h b/kvm.h index aab5118..16b06a4 100644 --- a/kvm.h +++ b/kvm.h @@ -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); diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 9cb9cf4..f0f3252 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -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; -- 1.7.0.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 1/3] qemu: kvm: Extend kvm_arch_get_supported_cpuid() to support index @ 2010-06-10 3:31 ` Sheng Yang 0 siblings, 0 replies; 10+ messages in thread From: Sheng Yang @ 2010-06-10 3:31 UTC (permalink / raw) To: Avi Kivity, Marcelo Tosatti, Anthony Liguori; +Cc: qemu-devel, kvm, Sheng Yang Would use it later for XSAVE related CPUID. Signed-off-by: Sheng Yang <sheng@linux.intel.com> --- kvm.h | 2 +- target-i386/kvm.c | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/kvm.h b/kvm.h index aab5118..16b06a4 100644 --- a/kvm.h +++ b/kvm.h @@ -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); diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 9cb9cf4..f0f3252 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -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; -- 1.7.0.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/3] qemu: Enable XSAVE related CPUID 2010-06-10 3:31 ` [Qemu-devel] " Sheng Yang @ 2010-06-10 3:31 ` Sheng Yang -1 siblings, 0 replies; 10+ messages in thread From: Sheng Yang @ 2010-06-10 3:31 UTC (permalink / raw) To: Avi Kivity, Marcelo Tosatti, Anthony Liguori; +Cc: kvm, qemu-devel, Sheng Yang We can support it in KVM now. The 0xd leaf is queried from KVM. Signed-off-by: Sheng Yang <sheng@linux.intel.com> --- target-i386/cpuid.c | 21 +++++++++++++++++++++ 1 files changed, 21 insertions(+), 0 deletions(-) diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c index fb78061..26e4054 100644 --- a/target-i386/cpuid.c +++ b/target-i386/cpuid.c @@ -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; -- 1.7.0.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 2/3] qemu: Enable XSAVE related CPUID @ 2010-06-10 3:31 ` Sheng Yang 0 siblings, 0 replies; 10+ messages in thread From: Sheng Yang @ 2010-06-10 3:31 UTC (permalink / raw) To: Avi Kivity, Marcelo Tosatti, Anthony Liguori; +Cc: qemu-devel, kvm, Sheng Yang We can support it in KVM now. The 0xd leaf is queried from KVM. Signed-off-by: Sheng Yang <sheng@linux.intel.com> --- target-i386/cpuid.c | 21 +++++++++++++++++++++ 1 files changed, 21 insertions(+), 0 deletions(-) diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c index fb78061..26e4054 100644 --- a/target-i386/cpuid.c +++ b/target-i386/cpuid.c @@ -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; -- 1.7.0.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 2/3] qemu: Enable XSAVE related CPUID 2010-06-10 3:31 ` [Qemu-devel] " Sheng Yang @ 2010-06-16 14:59 ` Sheng Yang -1 siblings, 0 replies; 10+ messages in thread From: Sheng Yang @ 2010-06-16 14:59 UTC (permalink / raw) To: Marcelo Tosatti; +Cc: Avi Kivity, Anthony Liguori, kvm, qemu-devel On Thursday 10 June 2010 11:31:02 Sheng Yang wrote: > We can support it in KVM now. The 0xd leaf 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 > > Signed-off-by: Sheng Yang <sheng@linux.intel.com> > --- > target-i386/cpuid.c | 21 +++++++++++++++++++++ > 1 files changed, 21 insertions(+), 0 deletions(-) > > diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c > index fb78061..26e4054 100644 > --- a/target-i386/cpuid.c > +++ b/target-i386/cpuid.c > @@ -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; ^ permalink raw reply [flat|nested] 10+ messages in thread
* [Qemu-devel] Re: [PATCH 2/3] qemu: Enable XSAVE related CPUID @ 2010-06-16 14:59 ` Sheng Yang 0 siblings, 0 replies; 10+ messages in thread From: Sheng Yang @ 2010-06-16 14:59 UTC (permalink / raw) To: Marcelo Tosatti; +Cc: qemu-devel, Avi Kivity, kvm On Thursday 10 June 2010 11:31:02 Sheng Yang wrote: > We can support it in KVM now. The 0xd leaf 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 > > Signed-off-by: Sheng Yang <sheng@linux.intel.com> > --- > target-i386/cpuid.c | 21 +++++++++++++++++++++ > 1 files changed, 21 insertions(+), 0 deletions(-) > > diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c > index fb78061..26e4054 100644 > --- a/target-i386/cpuid.c > +++ b/target-i386/cpuid.c > @@ -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; ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/3] qemu: Enable XSAVE related CPUID 2010-06-16 14:59 ` [Qemu-devel] " Sheng Yang @ 2010-06-16 16:41 ` Marcelo Tosatti -1 siblings, 0 replies; 10+ messages in thread From: Marcelo Tosatti @ 2010-06-16 16:41 UTC (permalink / raw) To: Sheng Yang; +Cc: Avi Kivity, Anthony Liguori, kvm, qemu-devel On Wed, Jun 16, 2010 at 10:59:07PM +0800, Sheng Yang wrote: > On Thursday 10 June 2010 11:31:02 Sheng Yang wrote: > > We can support it in KVM now. The 0xd leaf is queried from KVM. > > Hi Marcelo & Avi > > How about patch 1 and 2 in this series? They are used to enable XSAVE cpuid. Applied. ^ permalink raw reply [flat|nested] 10+ messages in thread
* [Qemu-devel] Re: [PATCH 2/3] qemu: Enable XSAVE related CPUID @ 2010-06-16 16:41 ` Marcelo Tosatti 0 siblings, 0 replies; 10+ messages in thread From: Marcelo Tosatti @ 2010-06-16 16:41 UTC (permalink / raw) To: Sheng Yang; +Cc: qemu-devel, Avi Kivity, kvm On Wed, Jun 16, 2010 at 10:59:07PM +0800, Sheng Yang wrote: > On Thursday 10 June 2010 11:31:02 Sheng Yang wrote: > > We can support it in KVM now. The 0xd leaf is queried from KVM. > > Hi Marcelo & Avi > > How about patch 1 and 2 in this series? They are used to enable XSAVE cpuid. Applied. ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 3/3] qemu: kvm: Enable XSAVE live migration support 2010-06-10 3:31 ` [Qemu-devel] " Sheng Yang @ 2010-06-10 3:31 ` Sheng Yang -1 siblings, 0 replies; 10+ messages in thread From: Sheng Yang @ 2010-06-10 3:31 UTC (permalink / raw) To: Avi Kivity, Marcelo Tosatti, Anthony Liguori; +Cc: kvm, qemu-devel, Sheng Yang Signed-off-by: Sheng Yang <sheng@linux.intel.com> --- 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(-) diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c index 3c33e64..b6396c6 100644 --- a/qemu-kvm-x86.c +++ b/qemu-kvm-x86.c @@ -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); 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_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; 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_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 * diff --git a/target-i386/cpu.h b/target-i386/cpu.h index e989040..f7d2470 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -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); diff --git a/target-i386/machine.c b/target-i386/machine.c index b547e2a..92caee4 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -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! */ } -- 1.7.0.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH 3/3] qemu: kvm: Enable XSAVE live migration support @ 2010-06-10 3:31 ` Sheng Yang 0 siblings, 0 replies; 10+ messages in thread From: Sheng Yang @ 2010-06-10 3:31 UTC (permalink / raw) To: Avi Kivity, Marcelo Tosatti, Anthony Liguori; +Cc: qemu-devel, kvm, Sheng Yang Signed-off-by: Sheng Yang <sheng@linux.intel.com> --- 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(-) diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c index 3c33e64..b6396c6 100644 --- a/qemu-kvm-x86.c +++ b/qemu-kvm-x86.c @@ -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); 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_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; 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_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 * diff --git a/target-i386/cpu.h b/target-i386/cpu.h index e989040..f7d2470 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -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); diff --git a/target-i386/machine.c b/target-i386/machine.c index b547e2a..92caee4 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -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! */ } -- 1.7.0.1 ^ permalink raw reply related [flat|nested] 10+ messages in thread
end of thread, other threads:[~2010-06-16 17:35 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2010-06-10 3:31 [PATCH 1/3] qemu: kvm: Extend kvm_arch_get_supported_cpuid() to support index Sheng Yang 2010-06-10 3:31 ` [Qemu-devel] " Sheng Yang 2010-06-10 3:31 ` [PATCH 2/3] qemu: Enable XSAVE related CPUID Sheng Yang 2010-06-10 3:31 ` [Qemu-devel] " Sheng Yang 2010-06-16 14:59 ` Sheng Yang 2010-06-16 14:59 ` [Qemu-devel] " Sheng Yang 2010-06-16 16:41 ` Marcelo Tosatti 2010-06-16 16:41 ` [Qemu-devel] " Marcelo Tosatti 2010-06-10 3:31 ` [PATCH 3/3] qemu: kvm: Enable XSAVE live migration support Sheng Yang 2010-06-10 3:31 ` [Qemu-devel] " Sheng Yang
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.