* [PATCH v4 0/4] XSAVE enabling in QEmu
@ 2010-06-17 7:18 Sheng Yang
2010-06-17 7:18 ` [PATCH 1/4] qemu: kvm: Extend kvm_arch_get_supported_cpuid() to support index Sheng Yang
` (4 more replies)
0 siblings, 5 replies; 16+ messages in thread
From: Sheng Yang @ 2010-06-17 7:18 UTC (permalink / raw)
To: Marcelo Tosatti, Avi Kivity
Cc: Jan Kiszka, Anthony Liguori, kvm, qemu-devel, Sheng Yang
Notice the first three patches applied to uq/master branch of qemu-kvm, the last one
applied to qemu-kvm master branch. And the last one would only apply after the
first three merged in master branch.
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 1/4] qemu: kvm: Extend kvm_arch_get_supported_cpuid() to support index
2010-06-17 7:18 [PATCH v4 0/4] XSAVE enabling in QEmu Sheng Yang
@ 2010-06-17 7:18 ` Sheng Yang
2010-06-17 7:18 ` [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, Anthony Liguori, 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 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
* [PATCH 2/4] qemu: Enable XSAVE related CPUID
2010-06-17 7:18 [PATCH v4 0/4] XSAVE enabling in QEmu Sheng Yang
2010-06-17 7:18 ` [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 ` [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, Anthony Liguori, 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 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
* [PATCH 3/4] qemu: kvm: Enable XSAVE live migration support
2010-06-17 7:18 [PATCH v4 0/4] XSAVE enabling in QEmu Sheng Yang
2010-06-17 7:18 ` [PATCH 1/4] qemu: kvm: Extend kvm_arch_get_supported_cpuid() to support index Sheng Yang
2010-06-17 7:18 ` [PATCH 2/4] qemu: Enable XSAVE related CPUID Sheng Yang
@ 2010-06-17 7:18 ` Sheng Yang
2010-06-17 7:40 ` Jan Kiszka
2010-06-17 7:18 ` [PATCH 4/4] qemu-kvm: " Sheng Yang
2010-06-18 19:26 ` [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, Anthony Liguori, kvm, qemu-devel, Sheng Yang
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
* [PATCH 4/4] qemu-kvm: Enable XSAVE live migration support
2010-06-17 7:18 [PATCH v4 0/4] XSAVE enabling in QEmu Sheng Yang
` (2 preceding siblings ...)
2010-06-17 7:18 ` [PATCH 3/4] qemu: kvm: Enable XSAVE live migration support Sheng Yang
@ 2010-06-17 7:18 ` Sheng Yang
2010-06-17 7:41 ` Jan Kiszka
2010-06-18 19:26 ` [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, Anthony Liguori, kvm, qemu-devel, Sheng Yang
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
* Re: [PATCH 3/4] qemu: kvm: Enable XSAVE live migration support
2010-06-17 7:18 ` [PATCH 3/4] qemu: kvm: Enable XSAVE live migration support Sheng Yang
@ 2010-06-17 7:40 ` Jan Kiszka
2010-06-17 8:26 ` 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: Marcelo Tosatti, Avi Kivity, Anthony Liguori, kvm, qemu-devel
[-- 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
* Re: [PATCH 4/4] qemu-kvm: Enable XSAVE live migration support
2010-06-17 7:18 ` [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: Marcelo Tosatti, Avi Kivity, Anthony Liguori, kvm, qemu-devel
[-- 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
* [PATCH 3/4] qemu: kvm: Enable XSAVE live migration support
2010-06-17 7:40 ` Jan Kiszka
@ 2010-06-17 8:26 ` Sheng Yang
2010-06-17 8:57 ` 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, Avi Kivity, kvm, qemu-devel, Sheng Yang
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
* Re: [PATCH 4/4] qemu-kvm: Enable XSAVE live migration support
2010-06-17 7:41 ` 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: Marcelo Tosatti, Avi Kivity, Anthony Liguori, kvm, qemu-devel
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
* 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 ` [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: Marcelo Tosatti, Avi Kivity, Anthony Liguori, kvm, qemu-devel
[-- 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
* Re: [PATCH 3/4] qemu: kvm: Enable XSAVE live migration support
2010-06-17 8:26 ` Sheng Yang
@ 2010-06-17 8:57 ` Jan Kiszka
2010-06-17 9:53 ` 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
* [PATCH 3/4] qemu: kvm: Enable XSAVE live migration support
2010-06-17 8:57 ` Jan Kiszka
@ 2010-06-17 9:53 ` Sheng Yang
2010-06-17 13:25 ` 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, Avi Kivity, kvm, qemu-devel, Sheng Yang
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
* [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 ` 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, Avi Kivity, kvm, qemu-devel, Sheng Yang
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
* Re: [PATCH 3/4] qemu: kvm: Enable XSAVE live migration support
2010-06-17 9:53 ` 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
* Re: [PATCH] qemu-kvm: Replace kvm_set/get_fpu() with upstream version.
2010-06-17 10:00 ` [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
* Re: [PATCH v4 0/4] XSAVE enabling in QEmu
2010-06-17 7:18 [PATCH v4 0/4] XSAVE enabling in QEmu Sheng Yang
` (3 preceding siblings ...)
2010-06-17 7:18 ` [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: Avi Kivity, Jan Kiszka, Anthony Liguori, kvm, qemu-devel
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
end of thread, other threads:[~2010-06-18 19:31 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-06-17 7:18 [PATCH v4 0/4] XSAVE enabling in QEmu Sheng Yang
2010-06-17 7:18 ` [PATCH 1/4] qemu: kvm: Extend kvm_arch_get_supported_cpuid() to support index Sheng Yang
2010-06-17 7:18 ` [PATCH 2/4] qemu: Enable XSAVE related CPUID Sheng Yang
2010-06-17 7:18 ` [PATCH 3/4] qemu: kvm: Enable XSAVE live migration support Sheng Yang
2010-06-17 7:40 ` Jan Kiszka
2010-06-17 8:26 ` Sheng Yang
2010-06-17 8:57 ` Jan Kiszka
2010-06-17 9:53 ` Sheng Yang
2010-06-17 13:25 ` Jan Kiszka
2010-06-17 7:18 ` [PATCH 4/4] qemu-kvm: " Sheng Yang
2010-06-17 7:41 ` Jan Kiszka
2010-06-17 8:32 ` Sheng Yang
2010-06-17 8:44 ` Jan Kiszka
2010-06-17 10:00 ` [PATCH] qemu-kvm: Replace kvm_set/get_fpu() with upstream version Sheng Yang
2010-06-17 13:27 ` Jan Kiszka
2010-06-18 19:26 ` [PATCH v4 0/4] XSAVE enabling in QEmu Marcelo Tosatti
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.