* [Qemu-devel] [PATCH 1/4] qemu: kvm: Extend kvm_arch_get_supported_cpuid() to support index
2010-06-17 7:18 [Qemu-devel] [PATCH v4 0/4] XSAVE enabling in QEmu Sheng Yang
@ 2010-06-17 7:18 ` Sheng Yang
2010-06-17 7:18 ` [Qemu-devel] [PATCH 2/4] qemu: Enable XSAVE related CPUID Sheng Yang
` (3 subsequent siblings)
4 siblings, 0 replies; 16+ messages in thread
From: Sheng Yang @ 2010-06-17 7:18 UTC (permalink / raw)
To: Marcelo Tosatti, Avi Kivity; +Cc: Jan Kiszka, Sheng Yang, kvm, qemu-devel
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 a28e7aa..7975e87 100644
--- a/kvm.h
+++ b/kvm.h
@@ -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);
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 5a088a7..bb6a12f 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -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;
--
1.7.0.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] [PATCH 2/4] qemu: Enable XSAVE related CPUID
2010-06-17 7:18 [Qemu-devel] [PATCH v4 0/4] XSAVE enabling in QEmu Sheng Yang
2010-06-17 7:18 ` [Qemu-devel] [PATCH 1/4] qemu: kvm: Extend kvm_arch_get_supported_cpuid() to support index Sheng Yang
@ 2010-06-17 7:18 ` Sheng Yang
2010-06-17 7:18 ` [Qemu-devel] [PATCH 3/4] qemu: kvm: Enable XSAVE live migration support Sheng Yang
` (2 subsequent siblings)
4 siblings, 0 replies; 16+ messages in thread
From: Sheng Yang @ 2010-06-17 7:18 UTC (permalink / raw)
To: Marcelo Tosatti, Avi Kivity; +Cc: Jan Kiszka, Sheng Yang, kvm, qemu-devel
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 99d1f44..ab6536b 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -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;
--
1.7.0.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] [PATCH 3/4] qemu: kvm: Enable XSAVE live migration support
2010-06-17 7:18 [Qemu-devel] [PATCH v4 0/4] XSAVE enabling in QEmu Sheng Yang
2010-06-17 7:18 ` [Qemu-devel] [PATCH 1/4] qemu: kvm: Extend kvm_arch_get_supported_cpuid() to support index Sheng Yang
2010-06-17 7:18 ` [Qemu-devel] [PATCH 2/4] qemu: Enable XSAVE related CPUID Sheng Yang
@ 2010-06-17 7:18 ` Sheng Yang
2010-06-17 7:40 ` [Qemu-devel] " Jan Kiszka
2010-06-17 7:18 ` [Qemu-devel] [PATCH 4/4] qemu-kvm: " Sheng Yang
2010-06-18 19:26 ` [Qemu-devel] Re: [PATCH v4 0/4] XSAVE enabling in QEmu Marcelo Tosatti
4 siblings, 1 reply; 16+ messages in thread
From: Sheng Yang @ 2010-06-17 7:18 UTC (permalink / raw)
To: Marcelo Tosatti, Avi Kivity; +Cc: Jan Kiszka, Sheng Yang, kvm, qemu-devel
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
target-i386/cpu.h | 5 ++
target-i386/kvm.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++
target-i386/machine.c | 20 +++++++
3 files changed, 159 insertions(+), 0 deletions(-)
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 548ab80..75070d3 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -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);
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index bb6a12f..90ff323 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -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);
+#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
ret = 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)
diff --git a/target-i386/machine.c b/target-i386/machine.c
index b547e2a..5f8376c 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,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! */
}
--
1.7.0.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] Re: [PATCH 3/4] qemu: kvm: Enable XSAVE live migration support
2010-06-17 7:18 ` [Qemu-devel] [PATCH 3/4] qemu: kvm: Enable XSAVE live migration support Sheng Yang
@ 2010-06-17 7:40 ` Jan Kiszka
2010-06-17 8:26 ` [Qemu-devel] " Sheng Yang
0 siblings, 1 reply; 16+ messages in thread
From: Jan Kiszka @ 2010-06-17 7:40 UTC (permalink / raw)
To: Sheng Yang; +Cc: qemu-devel, Marcelo Tosatti, Avi Kivity, kvm
[-- Attachment #1: Type: text/plain, Size: 8120 bytes --]
Sheng Yang wrote:
> Signed-off-by: Sheng Yang <sheng@linux.intel.com>
> ---
> target-i386/cpu.h | 5 ++
> target-i386/kvm.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++
> target-i386/machine.c | 20 +++++++
> 3 files changed, 159 insertions(+), 0 deletions(-)
>
> diff --git a/target-i386/cpu.h b/target-i386/cpu.h
> index 548ab80..75070d3 100644
> --- a/target-i386/cpu.h
> +++ b/target-i386/cpu.h
> @@ -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);
> diff --git a/target-i386/kvm.c b/target-i386/kvm.c
> index bb6a12f..90ff323 100644
> --- a/target-i386/kvm.c
> +++ b/target-i386/kvm.c
> @@ -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);
> +#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.
>
> ret = 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)
> diff --git a/target-i386/machine.c b/target-i386/machine.c
> index b547e2a..5f8376c 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,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
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 257 bytes --]
^ permalink raw reply [flat|nested] 16+ messages in thread
* [Qemu-devel] [PATCH 3/4] qemu: kvm: Enable XSAVE live migration support
2010-06-17 7:40 ` [Qemu-devel] " Jan Kiszka
@ 2010-06-17 8:26 ` Sheng Yang
2010-06-17 8:57 ` [Qemu-devel] " Jan Kiszka
0 siblings, 1 reply; 16+ messages in thread
From: Sheng Yang @ 2010-06-17 8:26 UTC (permalink / raw)
To: Jan Kiszka; +Cc: Marcelo Tosatti, Sheng Yang, Avi Kivity, kvm, qemu-devel
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
target-i386/cpu.h | 7 ++-
target-i386/kvm.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++-
target-i386/machine.c | 20 +++++++
3 files changed, 163 insertions(+), 3 deletions(-)
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 548ab80..680eed1 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -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
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index bb6a12f..e490c0a 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -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_check_extension(env->kvm_state, KVM_CAP_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_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;
diff --git a/target-i386/machine.c b/target-i386/machine.c
index b547e2a..5f8376c 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,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! */
}
--
1.7.0.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] Re: [PATCH 3/4] qemu: kvm: Enable XSAVE live migration support
2010-06-17 8:26 ` [Qemu-devel] " Sheng Yang
@ 2010-06-17 8:57 ` Jan Kiszka
2010-06-17 9:53 ` [Qemu-devel] " Sheng Yang
0 siblings, 1 reply; 16+ messages in thread
From: Jan Kiszka @ 2010-06-17 8:57 UTC (permalink / raw)
To: Sheng Yang; +Cc: Marcelo Tosatti, Avi Kivity, kvm, qemu-devel
Sheng Yang wrote:
> Signed-off-by: Sheng Yang <sheng@linux.intel.com>
> ---
> target-i386/cpu.h | 7 ++-
> target-i386/kvm.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++-
> target-i386/machine.c | 20 +++++++
> 3 files changed, 163 insertions(+), 3 deletions(-)
>
> diff --git a/target-i386/cpu.h b/target-i386/cpu.h
> index 548ab80..680eed1 100644
> --- a/target-i386/cpu.h
> +++ b/target-i386/cpu.h
> @@ -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
> diff --git a/target-i386/kvm.c b/target-i386/kvm.c
> index bb6a12f..e490c0a 100644
> --- a/target-i386/kvm.c
> +++ b/target-i386/kvm.c
> @@ -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_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.
> + 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;
>
> diff --git a/target-i386/machine.c b/target-i386/machine.c
> index b547e2a..5f8376c 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,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
--
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux
^ permalink raw reply [flat|nested] 16+ messages in thread
* [Qemu-devel] [PATCH 3/4] qemu: kvm: Enable XSAVE live migration support
2010-06-17 8:57 ` [Qemu-devel] " Jan Kiszka
@ 2010-06-17 9:53 ` Sheng Yang
2010-06-17 13:25 ` [Qemu-devel] " Jan Kiszka
0 siblings, 1 reply; 16+ messages in thread
From: Sheng Yang @ 2010-06-17 9:53 UTC (permalink / raw)
To: Jan Kiszka; +Cc: Marcelo Tosatti, Sheng Yang, Avi Kivity, kvm, qemu-devel
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
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(-)
diff --git a/kvm-all.c b/kvm-all.c
index 43704b8..343c06e 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -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()) {
diff --git a/kvm.h b/kvm.h
index 7975e87..50c4192 100644
--- a/kvm.h
+++ b/kvm.h
@@ -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);
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 548ab80..680eed1 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -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
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index bb6a12f..db1f21d 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -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;
diff --git a/target-i386/machine.c b/target-i386/machine.c
index b547e2a..5f8376c 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,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! */
}
--
1.7.0.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] Re: [PATCH 3/4] qemu: kvm: Enable XSAVE live migration support
2010-06-17 9:53 ` [Qemu-devel] " Sheng Yang
@ 2010-06-17 13:25 ` Jan Kiszka
0 siblings, 0 replies; 16+ messages in thread
From: Jan Kiszka @ 2010-06-17 13:25 UTC (permalink / raw)
To: Sheng Yang
Cc: Marcelo Tosatti, Avi Kivity, kvm@vger.kernel.org,
qemu-devel@nongnu.org
Sheng Yang wrote:
> Signed-off-by: Sheng Yang <sheng@linux.intel.com>
> ---
> 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(-)
>
> diff --git a/kvm-all.c b/kvm-all.c
> index 43704b8..343c06e 100644
> --- a/kvm-all.c
> +++ b/kvm-all.c
> @@ -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()) {
> diff --git a/kvm.h b/kvm.h
> index 7975e87..50c4192 100644
> --- a/kvm.h
> +++ b/kvm.h
> @@ -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);
> diff --git a/target-i386/cpu.h b/target-i386/cpu.h
> index 548ab80..680eed1 100644
> --- a/target-i386/cpu.h
> +++ b/target-i386/cpu.h
> @@ -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
> diff --git a/target-i386/kvm.c b/target-i386/kvm.c
> index bb6a12f..db1f21d 100644
> --- a/target-i386/kvm.c
> +++ b/target-i386/kvm.c
> @@ -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;
>
> diff --git a/target-i386/machine.c b/target-i386/machine.c
> index b547e2a..5f8376c 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,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
--
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux
^ permalink raw reply [flat|nested] 16+ messages in thread
* [Qemu-devel] [PATCH 4/4] qemu-kvm: Enable XSAVE live migration support
2010-06-17 7:18 [Qemu-devel] [PATCH v4 0/4] XSAVE enabling in QEmu Sheng Yang
` (2 preceding siblings ...)
2010-06-17 7:18 ` [Qemu-devel] [PATCH 3/4] qemu: kvm: Enable XSAVE live migration support Sheng Yang
@ 2010-06-17 7:18 ` Sheng Yang
2010-06-17 7:41 ` [Qemu-devel] " Jan Kiszka
2010-06-18 19:26 ` [Qemu-devel] Re: [PATCH v4 0/4] XSAVE enabling in QEmu Marcelo Tosatti
4 siblings, 1 reply; 16+ messages in thread
From: Sheng Yang @ 2010-06-17 7:18 UTC (permalink / raw)
To: Marcelo Tosatti, Avi Kivity; +Cc: Jan Kiszka, Sheng Yang, kvm, qemu-devel
Based on upstream xsave related fields.
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
qemu-kvm-x86.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
qemu-kvm.c | 24 ++++++++++++++
qemu-kvm.h | 28 ++++++++++++++++
3 files changed, 146 insertions(+), 1 deletions(-)
diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c
index 3c33e64..dcef8b5 100644
--- a/qemu-kvm-x86.c
+++ b/qemu-kvm-x86.c
@@ -772,10 +772,26 @@ static void get_seg(SegmentCache *lhs, const 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);
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
*
--
1.7.0.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] Re: [PATCH 4/4] qemu-kvm: Enable XSAVE live migration support
2010-06-17 7:18 ` [Qemu-devel] [PATCH 4/4] qemu-kvm: " Sheng Yang
@ 2010-06-17 7:41 ` Jan Kiszka
2010-06-17 8:32 ` Sheng Yang
0 siblings, 1 reply; 16+ messages in thread
From: Jan Kiszka @ 2010-06-17 7:41 UTC (permalink / raw)
To: Sheng Yang; +Cc: qemu-devel, Marcelo Tosatti, Avi Kivity, kvm
[-- Attachment #1: Type: text/plain, Size: 7760 bytes --]
Sheng Yang wrote:
> Based on upstream xsave related fields.
>
> Signed-off-by: Sheng Yang <sheng@linux.intel.com>
> ---
> qemu-kvm-x86.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> qemu-kvm.c | 24 ++++++++++++++
> qemu-kvm.h | 28 ++++++++++++++++
> 3 files changed, 146 insertions(+), 1 deletions(-)
>
> diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c
> index 3c33e64..dcef8b5 100644
> --- a/qemu-kvm-x86.c
> +++ b/qemu-kvm-x86.c
> @@ -772,10 +772,26 @@ static void get_seg(SegmentCache *lhs, const 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 */
Why not reusing kvm_put/get_xsave as defined for upstream? There should
be enough examples for that pattern. The result will be a tiny qemu-kvm
patch.
Jan
> memset(&fpu, 0, sizeof fpu);
> fpu.fsw = 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);
>
> 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
> *
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 257 bytes --]
^ permalink raw reply [flat|nested] 16+ messages in thread
* [Qemu-devel] Re: [PATCH 4/4] qemu-kvm: Enable XSAVE live migration support
2010-06-17 7:41 ` [Qemu-devel] " Jan Kiszka
@ 2010-06-17 8:32 ` Sheng Yang
2010-06-17 8:44 ` Jan Kiszka
0 siblings, 1 reply; 16+ messages in thread
From: Sheng Yang @ 2010-06-17 8:32 UTC (permalink / raw)
To: Jan Kiszka; +Cc: qemu-devel, Marcelo Tosatti, Avi Kivity, kvm
On Thursday 17 June 2010 15:41:43 Jan Kiszka wrote:
> Sheng Yang wrote:
> > Based on upstream xsave related fields.
> >
> > Signed-off-by: Sheng Yang <sheng@linux.intel.com>
> > ---
> >
> > qemu-kvm-x86.c | 95
> > +++++++++++++++++++++++++++++++++++++++++++++++++++++++- qemu-kvm.c
> > | 24 ++++++++++++++
> > qemu-kvm.h | 28 ++++++++++++++++
> > 3 files changed, 146 insertions(+), 1 deletions(-)
> >
> > diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c
> > index 3c33e64..dcef8b5 100644
> > --- a/qemu-kvm-x86.c
> > +++ b/qemu-kvm-x86.c
> > @@ -772,10 +772,26 @@ static void get_seg(SegmentCache *lhs, const 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 */
>
> 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
>
> Jan
>
> > 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);
> >
> > 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
> > *
^ permalink raw reply [flat|nested] 16+ messages in thread
* [Qemu-devel] Re: [PATCH 4/4] qemu-kvm: Enable XSAVE live migration support
2010-06-17 8:32 ` Sheng Yang
@ 2010-06-17 8:44 ` Jan Kiszka
2010-06-17 10:00 ` [Qemu-devel] [PATCH] qemu-kvm: Replace kvm_set/get_fpu() with upstream version Sheng Yang
0 siblings, 1 reply; 16+ messages in thread
From: Jan Kiszka @ 2010-06-17 8:44 UTC (permalink / raw)
To: Sheng Yang; +Cc: qemu-devel, Marcelo Tosatti, Avi Kivity, kvm
[-- Attachment #1: Type: text/plain, Size: 3572 bytes --]
Sheng Yang wrote:
> On Thursday 17 June 2010 15:41:43 Jan Kiszka wrote:
>> Sheng Yang wrote:
>>> Based on upstream xsave related fields.
>>>
>>> Signed-off-by: Sheng Yang <sheng@linux.intel.com>
>>> ---
>>>
>>> qemu-kvm-x86.c | 95
>>> +++++++++++++++++++++++++++++++++++++++++++++++++++++++- qemu-kvm.c
>>> | 24 ++++++++++++++
>>> qemu-kvm.h | 28 ++++++++++++++++
>>> 3 files changed, 146 insertions(+), 1 deletions(-)
>>>
>>> diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c
>>> index 3c33e64..dcef8b5 100644
>>> --- a/qemu-kvm-x86.c
>>> +++ b/qemu-kvm-x86.c
>>> @@ -772,10 +772,26 @@ static void get_seg(SegmentCache *lhs, const 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 */
>> 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.
That we still have some legacy here is no good reason to increase it.
Just check how debugregs were introduced.
Jan
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 257 bytes --]
^ permalink raw reply [flat|nested] 16+ messages in thread
* [Qemu-devel] [PATCH] qemu-kvm: Replace kvm_set/get_fpu() with upstream version.
2010-06-17 8:44 ` Jan Kiszka
@ 2010-06-17 10:00 ` Sheng Yang
2010-06-17 13:27 ` [Qemu-devel] " Jan Kiszka
0 siblings, 1 reply; 16+ messages in thread
From: Sheng Yang @ 2010-06-17 10:00 UTC (permalink / raw)
To: Jan Kiszka; +Cc: Marcelo Tosatti, Sheng Yang, Avi Kivity, kvm, qemu-devel
Signed-off-by: Sheng Yang <sheng@linux.intel.com>
---
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(-)
diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c
index 3c33e64..49218ae 100644
--- a/qemu-kvm-x86.c
+++ b/qemu-kvm-x86.c
@@ -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);
diff --git a/qemu-kvm.c b/qemu-kvm.c
index 96d458c..114cb5e 100644
--- a/qemu-kvm.c
+++ b/qemu-kvm.c
@@ -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);
diff --git a/qemu-kvm.h b/qemu-kvm.h
index 6f6c6d8..ebe7893 100644
--- a/qemu-kvm.h
+++ b/qemu-kvm.h
@@ -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
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 9cb9cf4..9c13f62 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -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;
--
1.7.0.1
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [Qemu-devel] Re: [PATCH] qemu-kvm: Replace kvm_set/get_fpu() with upstream version.
2010-06-17 10:00 ` [Qemu-devel] [PATCH] qemu-kvm: Replace kvm_set/get_fpu() with upstream version Sheng Yang
@ 2010-06-17 13:27 ` Jan Kiszka
0 siblings, 0 replies; 16+ messages in thread
From: Jan Kiszka @ 2010-06-17 13:27 UTC (permalink / raw)
To: Sheng Yang
Cc: Marcelo Tosatti, Avi Kivity, kvm@vger.kernel.org,
qemu-devel@nongnu.org
Sheng Yang wrote:
> Signed-off-by: Sheng Yang <sheng@linux.intel.com>
> ---
>
> 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(-)
>
> diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c
> index 3c33e64..49218ae 100644
> --- a/qemu-kvm-x86.c
> +++ b/qemu-kvm-x86.c
> @@ -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);
>
> diff --git a/qemu-kvm.c b/qemu-kvm.c
> index 96d458c..114cb5e 100644
> --- a/qemu-kvm.c
> +++ b/qemu-kvm.c
> @@ -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);
> diff --git a/qemu-kvm.h b/qemu-kvm.h
> index 6f6c6d8..ebe7893 100644
> --- a/qemu-kvm.h
> +++ b/qemu-kvm.h
> @@ -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
> diff --git a/target-i386/kvm.c b/target-i386/kvm.c
> index 9cb9cf4..9c13f62 100644
> --- a/target-i386/kvm.c
> +++ b/target-i386/kvm.c
> @@ -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;
Perfect, another step forward towards upstream!
Thanks,
Jan
--
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux
^ permalink raw reply [flat|nested] 16+ messages in thread
* [Qemu-devel] Re: [PATCH v4 0/4] XSAVE enabling in QEmu
2010-06-17 7:18 [Qemu-devel] [PATCH v4 0/4] XSAVE enabling in QEmu Sheng Yang
` (3 preceding siblings ...)
2010-06-17 7:18 ` [Qemu-devel] [PATCH 4/4] qemu-kvm: " Sheng Yang
@ 2010-06-18 19:26 ` Marcelo Tosatti
4 siblings, 0 replies; 16+ messages in thread
From: Marcelo Tosatti @ 2010-06-18 19:26 UTC (permalink / raw)
To: Sheng Yang; +Cc: qemu-devel, Jan Kiszka, Avi Kivity, kvm
On Thu, Jun 17, 2010 at 03:18:12PM +0800, Sheng Yang wrote:
> 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.
^ permalink raw reply [flat|nested] 16+ messages in thread