qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v4 0/4] XSAVE enabling in QEmu
@ 2010-06-17  7:18 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
                   ` (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, Sheng Yang, kvm, qemu-devel

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

* [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] [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, &regs);
 
+#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 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] 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, &regs);
>  
> +#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] [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 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, &regs);
> > 
> > +#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, &regs);
>>>
>>> +#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] 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] [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, &regs);
 
-    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 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] 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, &regs);
>  
> -    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

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 [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 ` [Qemu-devel] [PATCH 3/4] qemu: kvm: Enable XSAVE live migration support Sheng Yang
2010-06-17  7:40   ` [Qemu-devel] " Jan Kiszka
2010-06-17  8:26     ` [Qemu-devel] " Sheng Yang
2010-06-17  8:57       ` [Qemu-devel] " Jan Kiszka
2010-06-17  9:53         ` [Qemu-devel] " Sheng Yang
2010-06-17 13:25           ` [Qemu-devel] " Jan Kiszka
2010-06-17  7:18 ` [Qemu-devel] [PATCH 4/4] qemu-kvm: " Sheng Yang
2010-06-17  7:41   ` [Qemu-devel] " Jan Kiszka
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
2010-06-17 13:27           ` [Qemu-devel] " Jan Kiszka
2010-06-18 19:26 ` [Qemu-devel] Re: [PATCH v4 0/4] XSAVE enabling in QEmu Marcelo Tosatti

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).