Re: [Qemu-devel] [PATCH v2 0/2] Use kvm64/kvm32 when running under KVM

2010-08-25 Thread Sheng Yang
On Wednesday 28 July 2010 20:42:22 jes.soren...@redhat.com wrote:
 From: Jes Sorensen jes.soren...@redhat.com
 
 This set of patches adds default CPU types to the PC compat
 definitions, and patch #2 sets the CPU type to kvm64/kvm32 when
 running under KVM.
 
 Long term we might want to qdev'ify the CPUs but I think it is better
 to keep it simple for 0.13.
 
Looks good to me.

Some Windows guest wouldn't enable MSI if it think the processor is too old. So 
we 
need this patchset.

--
regards
Yang, Sheng


 Jes Sorensen (2):
   Set a default CPU type for compat PC machine defs.
   Use kvm32/kvm64 as default CPUs when running under KVM.
 
  hw/boards.h  |1 +
  hw/pc.c  |   13 +++--
  hw/pc_piix.c |   15 +++
  vl.c |2 ++
  4 files changed, 29 insertions(+), 2 deletions(-)



[Qemu-devel] Re: KVM vs. PCI-E Function Level Reset (FLR) ...

2010-07-15 Thread Sheng Yang
On Thursday 15 July 2010 23:39:36 Casey Leedom wrote:
 | From: Sheng Yang sh...@linux.intel.com
 | Date: Wednesday, July 14, 2010 06:31 pm
 | 
 | On Thursday 15 July 2010 02:01:29 Casey Leedom wrote:
 |  | From: Sheng Yang sh...@linux.intel.com
 |  | Date: Tuesday, July 13, 2010 05:53 pm
 | 
 | (Please use reply to all next time.)
 
   Sorry, old habit.
 
 |  | On Wednesday 14 July 2010 04:41:01 Casey Leedom wrote:
 |Hhrrmmm, this seems like a semantic error.  Resetting the Vm should
 |  
 |  be morally equivalent to resetting a real physical machine.  And when
 |  a real physical machine is reset, all of its buses, etc. get reset
 |  which propagates to Device Resets on those buses ...  I think that
 |  Assigned Devices should be reset for reboots and power off/on ...
 | 
 | Yes, it should be done when reset. And power on/off should be there,
 | because that's means the create and destroy the guest.
 
   Okay, cool.  I've looked through the kernel code and I don't see any
 likely places for putting such a VM Reboot/Reset feature in so I assume
 that this is also controlled by QEmu and it would need to be responsible
 for either doing a KVM_DEASSIGN_PCI_DEVICE/KVM_ASSIGN_PCI_DEVICE ioctl()
 pair for each assigned device or issuing a new
 KVM_RESET_ASSIGNED_PCI_DEVICE ioctl() for Reboot/Reset ...

Yeah, the detection of reset is not that straightforward... Maybe we need an 
ioctl 
for reset event in qemu-kvm kvm_reset_vcpu().

We don't need assign/deassign device when reboot/reset, we only need to notify 
KVM 
that the reset is happening, then KVM know what's to do.
 
 |  Assigned Devices.  For PCI-E SR-IOV Virtual Functions which are
 |  assigned to a VM, they need to be reset at reboot/power off/power on
 |  and the Configuration Space emulation needs to support the Guest OS/VM
 |  Device Driver issuing an FLR ...
 | 
 | You can add the FLR support for your device if you need to call it in the
 | guest. But I don't quite understand why you need to call it in the guest.
 | KVM should has already done that, and it's not necessary for native
 | device.
 
   This was mostly for device driver load/unload support.  I.e. being able
 to issue a Function Level Reset to a PCI Device Function (regardless of it
 being an SR-IOV Virtual Function or not) is a nice way to zap the device
 back to a canonical state.

OK.
 
 | So you want to issue FLR(rather than probing the feature) when
 | driver-probe() called? Current seems KVM is the only user of
 | pci_reset_function(), so I think we can update it after your driver
 | posted to the mailing list. Also I am not sure why you want to reset
 | function when probing. KVM should cover them all I think.
 
   Remember, the probe _argument_ in pci_dev_reset() has nothing to do
 with whether it's being called from a device driver's probe() routine. 
 The probe _argument_ in pci_dev_reset() is used for the two-stage effort
 in
 pci_reset_function() which does:
 
  1. try to see if it's possible to reset this function by itself
 Call pci_dev_reset(dev, probe=1);
 
  2. go ahead and do the function reset
 Call pci_dev_reset(dev, probe=0);
 
   And yes, I'd noticed that KVM was the only current subscriber of the
 kernel interface but, as I noted above, it is useful for resetting the
 device function into a known state -- or at least it _was_ useful till the
 deadlock got introduced in 2.6.31 ... :-(  And again, the use of this
 actually has no dependency on KVM: I would want to be able to call
 pci_reset_function() in any device driver's probe() routine ...  It just
 happens that I ran into this need (and unfortunate 2.6.31 deadlock) with
 our PCI-E SR-IOV Virtual Function Driver.

What I meant was, before your driver, there is no such requirement in the code. 
And no one can predict every usage of the code in the future, so it's quite 
reasonable you called the deadlock is there. And I can't say it's a 
deadlock 
because there is no code in the current tree make it deadlock IIUR. 

So now you have this requirement, you can modify it to fit your need. That's 
quite 
straightforward...
 
   Oh, and the driver has been posted to net-next.  I'm guessing that it
 _should_ get merged into 2.6.35 ... or maybe 2.6.36 ... I'm really not
 sure of how the merge schedule between net-next and the core kernel runs
 ...

That's good. So you can modify the function to provide a lockless version. That 
make sense now. :)

--
regards
Yang, Sheng

 
 Casey



[Qemu-devel] [PATCH 2/4] qemu: Enable XSAVE related CPUID

2010-06-17 Thread Sheng Yang
We can support it in KVM now. The 0xd leaf is queried from KVM.

Signed-off-by: Sheng Yang sh...@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 0x8000:
 *eax = env-cpuid_xlevel;
 *ebx = env-cpuid_vendor1;
-- 
1.7.0.1




[Qemu-devel] [PATCH 3/4] qemu: kvm: Enable XSAVE live migration support

2010-06-17 Thread Sheng Yang

Signed-off-by: Sheng Yang sh...@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_SPACE8
+#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

[Qemu-devel] [PATCH 1/4] qemu: kvm: Extend kvm_arch_get_supported_cpuid() to support index

2010-06-17 Thread Sheng Yang
Would use it later for XSAVE related CPUID.

Signed-off-by: Sheng Yang sh...@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, 0x8001,
- R_EDX);
+ 0, R_EDX);
 env-cpuid_ext3_features = kvm_arch_get_supported_cpuid(env, 0x8001,
- R_ECX);
+ 0, R_ECX);
 
 cpuid_i = 0;
 
-- 
1.7.0.1




[Qemu-devel] [PATCH v4 0/4] XSAVE enabling in QEmu

2010-06-17 Thread Sheng Yang
Notice the first three patches applied to uq/master branch of qemu-kvm, the 
last one
applied to qemu-kvm master branch. And the last one would only apply after the
first three merged in master branch.



[Qemu-devel] [PATCH 4/4] qemu-kvm: Enable XSAVE live migration support

2010-06-17 Thread Sheng Yang
Based on upstream xsave related fields.

Signed-off-by: Sheng Yang sh...@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_SPACE8
+#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

[Qemu-devel] [PATCH 3/4] qemu: kvm: Enable XSAVE live migration support

2010-06-17 Thread Sheng Yang

Signed-off-by: Sheng Yang sh...@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_SPACE8
+#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

[Qemu-devel] Re: [PATCH 4/4] qemu-kvm: Enable XSAVE live migration support

2010-06-17 Thread Sheng Yang
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 sh...@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_SPACE8
  +#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

[Qemu-devel] [PATCH 3/4] qemu: kvm: Enable XSAVE live migration support

2010-06-17 Thread Sheng Yang

Signed-off-by: Sheng Yang sh...@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_SPACE8
+#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

[Qemu-devel] [PATCH] qemu-kvm: Replace kvm_set/get_fpu() with upstream version.

2010-06-17 Thread Sheng Yang

Signed-off-by: Sheng Yang sh...@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




[Qemu-devel] Re: [PATCH 2/3] qemu: Enable XSAVE related CPUID

2010-06-16 Thread Sheng Yang
On Thursday 10 June 2010 11:31:02 Sheng Yang wrote:
 We can support it in KVM now. The 0xd leaf is queried from KVM.

Hi Marcelo  Avi

How about patch 1 and 2 in this series? They are used to enable XSAVE cpuid.

--
regards
Yang, Sheng


 
 Signed-off-by: Sheng Yang sh...@linux.intel.com
 ---
  target-i386/cpuid.c |   21 +
  1 files changed, 21 insertions(+), 0 deletions(-)
 
 diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
 index fb78061..26e4054 100644
 --- a/target-i386/cpuid.c
 +++ b/target-i386/cpuid.c
 @@ -1081,6 +1081,27 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index,
 uint32_t count, *ecx = 0;
  *edx = 0;
  break;
 +case 0xD:
 +/* Processor Extended State */
 +if (!(env-cpuid_ext_features  CPUID_EXT_XSAVE)) {
 +*eax = 0;
 +*ebx = 0;
 +*ecx = 0;
 +*edx = 0;
 +break;
 +}
 +if (kvm_enabled()) {
 +*eax = kvm_arch_get_supported_cpuid(env, 0xd, count, R_EAX);
 +*ebx = kvm_arch_get_supported_cpuid(env, 0xd, count, R_EBX);
 +*ecx = kvm_arch_get_supported_cpuid(env, 0xd, count, R_ECX);
 +*edx = kvm_arch_get_supported_cpuid(env, 0xd, count, R_EDX);
 +} else {
 +*eax = 0;
 +*ebx = 0;
 +*ecx = 0;
 +*edx = 0;
 +}
 +break;
  case 0x8000:
  *eax = env-cpuid_xlevel;
  *ebx = env-cpuid_vendor1;



[Qemu-devel] Re: [PATCH v3] qemu: kvm: Enable XSAVE live migration support

2010-06-16 Thread Sheng Yang
On Thursday 17 June 2010 00:05:44 Marcelo Tosatti wrote:
 On Wed, Jun 16, 2010 at 05:48:46PM +0200, Jan Kiszka wrote:
  Marcelo Tosatti wrote:
   On Fri, Jun 11, 2010 at 12:36:49PM +0800, Sheng Yang wrote:
   Signed-off-by: Sheng Yang sh...@linux.intel.com
   ---
   
qemu-kvm-x86.c|  109
- qemu-kvm.c
   |   24 +++
qemu-kvm.h|   28 +
target-i386/cpu.h |5 ++
target-i386/kvm.c |2 +
target-i386/machine.c |   20 +
6 files changed, 169 insertions(+), 19 deletions(-)
   
   Applied, thanks.
  
  Oops, late remark: Why introducing this feature against qemu-kvm instead
  of upstream? Doesn't this just generate additional conversion work and
  the risk of divergence to upstream in the migration protocol?

Hi Jan

You're late... Hope you could raise the comment earlier next time so we can 
work 
together more efficient.
 
 Thats true. Sheng, can you add save/restore support to uq/master to
 avoid these problems?

Yes, there is divergence risk, would send an upstream version as well.

But I think as long as qemu-kvm and qemu upstream use different LM path, the 
duplicate code/work can't be avoid. 
 
 Then the cpuid bits can be also merged upstream.

--
regards
Yang, Sheng



[Qemu-devel] [PATCH v3] qemu: kvm: Enable XSAVE live migration support

2010-06-10 Thread Sheng Yang

Signed-off-by: Sheng Yang sh...@linux.intel.com
---
 qemu-kvm-x86.c|  109 -
 qemu-kvm.c|   24 +++
 qemu-kvm.h|   28 +
 target-i386/cpu.h |5 ++
 target-i386/kvm.c |2 +
 target-i386/machine.c |   20 +
 6 files changed, 169 insertions(+), 19 deletions(-)

diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c
index 3c33e64..4f0b1d0 100644
--- a/qemu-kvm-x86.c
+++ b/qemu-kvm-x86.c
@@ -772,10 +772,20 @@ static void get_seg(SegmentCache *lhs, const struct 
kvm_segment *rhs)
| (rhs-avl * DESC_AVL_MASK);
 }
 
+#define XSAVE_CWD_RIP 2
+#define XSAVE_CWD_RDP 4
+#define XSAVE_MXCSR   6
+#define XSAVE_ST_SPACE8
+#define XSAVE_XMM_SPACE   40
+#define XSAVE_XSTATE_BV   128
+#define XSAVE_YMMH_SPACE  144
+
 void kvm_arch_load_regs(CPUState *env, int level)
 {
 struct kvm_regs regs;
 struct kvm_fpu fpu;
+struct kvm_xsave* xsave;
+struct kvm_xcrs xcrs;
 struct kvm_sregs sregs;
 struct kvm_msr_entry msrs[100];
 int rc, n, i;
@@ -806,16 +816,47 @@ 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);
+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);
+if (kvm_check_extension(kvm_state, KVM_CAP_XCRS)) {
+xcrs.nr_xcrs = 1;
+xcrs.flags = 0;
+xcrs.xcrs[0].xcr = 0;
+xcrs.xcrs[0].value = env-xcr0;
+kvm_set_xcrs(env, xcrs);
+}
+} else {
+memset(fpu, 0, sizeof fpu);
+fpu.fsw = env-fpus  ~(7  11);
+fpu.fsw |= (env-fpstt  7)  11;
+fpu.fcw = env-fpuc;
+for (i = 0; i  8; ++i)
+fpu.ftwx |= (!env-fptags[i])  i;
+memcpy(fpu.fpr, env-fpregs, sizeof env-fpregs);
+memcpy(fpu.xmm, env-xmm_regs, sizeof env-xmm_regs);
+fpu.mxcsr = env-mxcsr;
+kvm_set_fpu(env, fpu);
+}
 
 memset(sregs.interrupt_bitmap, 0, sizeof(sregs.interrupt_bitmap));
 if (env-interrupt_injected = 0) {
@@ -934,6 +975,8 @@ void kvm_arch_save_regs(CPUState *env)
 {
 struct kvm_regs regs;
 struct kvm_fpu fpu;
+struct kvm_xsave* xsave;
+struct kvm_xcrs xcrs;
 struct kvm_sregs sregs;
 struct kvm_msr_entry msrs[100];
 uint32_t hflags;
@@ -965,15 +1008,43 @@ void kvm_arch_save_regs(CPUState *env)
 env-eflags = regs.rflags;
 env-eip = regs.rip;
 
-kvm_get_fpu(env, fpu);
-env-fpstt = (fpu.fsw  11)  7;
-env-fpus = fpu.fsw;
-env-fpuc = fpu.fcw;
-for (i = 0; i  8; ++i)
-   env-fptags[i] = !((fpu.ftwx  i)  1);
-memcpy(env-fpregs, fpu.fpr, sizeof env-fpregs);
-memcpy(env-xmm_regs, fpu.xmm, sizeof env-xmm_regs);
-env-mxcsr = fpu.mxcsr;
+if (kvm_check_extension(kvm_state, KVM_CAP_XSAVE)) {
+uint16_t cwd, swd, twd, fop;
+xsave = qemu_memalign(4096, sizeof(struct kvm_xsave));
+kvm_get_xsave(env, xsave);
+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

[Qemu-devel] [PATCH 2/3] qemu: Enable XSAVE related CPUID

2010-06-09 Thread Sheng Yang
We can support it in KVM now. The 0xd leaf is queried from KVM.

Signed-off-by: Sheng Yang sh...@linux.intel.com
---
 target-i386/cpuid.c |   21 +
 1 files changed, 21 insertions(+), 0 deletions(-)

diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index fb78061..26e4054 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -1081,6 +1081,27 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, 
uint32_t count,
 *ecx = 0;
 *edx = 0;
 break;
+case 0xD:
+/* Processor Extended State */
+if (!(env-cpuid_ext_features  CPUID_EXT_XSAVE)) {
+*eax = 0;
+*ebx = 0;
+*ecx = 0;
+*edx = 0;
+break;
+}
+if (kvm_enabled()) {
+*eax = kvm_arch_get_supported_cpuid(env, 0xd, count, R_EAX);
+*ebx = kvm_arch_get_supported_cpuid(env, 0xd, count, R_EBX);
+*ecx = kvm_arch_get_supported_cpuid(env, 0xd, count, R_ECX);
+*edx = kvm_arch_get_supported_cpuid(env, 0xd, count, R_EDX);
+} else {
+*eax = 0;
+*ebx = 0;
+*ecx = 0;
+*edx = 0;
+}
+break;
 case 0x8000:
 *eax = env-cpuid_xlevel;
 *ebx = env-cpuid_vendor1;
-- 
1.7.0.1




[Qemu-devel] [PATCH 1/3] qemu: kvm: Extend kvm_arch_get_supported_cpuid() to support index

2010-06-09 Thread Sheng Yang
Would use it later for XSAVE related CPUID.

Signed-off-by: Sheng Yang sh...@linux.intel.com
---
 kvm.h |2 +-
 target-i386/kvm.c |   19 +++
 2 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/kvm.h b/kvm.h
index aab5118..16b06a4 100644
--- a/kvm.h
+++ b/kvm.h
@@ -152,7 +152,7 @@ bool kvm_arch_stop_on_emulation_error(CPUState *env);
 int kvm_check_extension(KVMState *s, unsigned int extension);
 
 uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
-  int reg);
+  uint32_t index, int reg);
 void kvm_cpu_synchronize_state(CPUState *env);
 void kvm_cpu_synchronize_post_reset(CPUState *env);
 void kvm_cpu_synchronize_post_init(CPUState *env);
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 9cb9cf4..f0f3252 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -71,7 +71,8 @@ static struct kvm_cpuid2 *try_get_cpuid(KVMState *s, int max)
 return cpuid;
 }
 
-uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function, int 
reg)
+uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
+  uint32_t index, int reg)
 {
 struct kvm_cpuid2 *cpuid;
 int i, max;
@@ -88,7 +89,8 @@ uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t 
function, int reg)
 }
 
 for (i = 0; i  cpuid-nent; ++i) {
-if (cpuid-entries[i].function == function) {
+if (cpuid-entries[i].function == function 
+cpuid-entries[i].index == index) {
 switch (reg) {
 case R_EAX:
 ret = cpuid-entries[i].eax;
@@ -110,7 +112,7 @@ uint32_t kvm_arch_get_supported_cpuid(CPUState *env, 
uint32_t function, int reg)
 /* On Intel, kvm returns cpuid according to the Intel spec,
  * so add missing bits according to the AMD spec:
  */
-cpuid_1_edx = kvm_arch_get_supported_cpuid(env, 1, R_EDX);
+cpuid_1_edx = kvm_arch_get_supported_cpuid(env, 1, 0, 
R_EDX);
 ret |= cpuid_1_edx  0x183f7ff;
 break;
 }
@@ -126,7 +128,8 @@ uint32_t kvm_arch_get_supported_cpuid(CPUState *env, 
uint32_t function, int reg)
 
 #else
 
-uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function, int 
reg)
+uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
+  uint32_t index, int reg)
 {
 return -1U;
 }
@@ -190,16 +193,16 @@ int kvm_arch_init_vcpu(CPUState *env)
 
 #endif
 
-env-cpuid_features = kvm_arch_get_supported_cpuid(env, 1, R_EDX);
+env-cpuid_features = kvm_arch_get_supported_cpuid(env, 1, 0, R_EDX);
 
 i = env-cpuid_ext_features  CPUID_EXT_HYPERVISOR;
-env-cpuid_ext_features = kvm_arch_get_supported_cpuid(env, 1, R_ECX);
+env-cpuid_ext_features = kvm_arch_get_supported_cpuid(env, 1, 0, R_ECX);
 env-cpuid_ext_features |= i;
 
 env-cpuid_ext2_features = kvm_arch_get_supported_cpuid(env, 0x8001,
- R_EDX);
+ 0, R_EDX);
 env-cpuid_ext3_features = kvm_arch_get_supported_cpuid(env, 0x8001,
- R_ECX);
+ 0, R_ECX);
 
 cpuid_i = 0;
 
-- 
1.7.0.1




[Qemu-devel] [PATCH 3/3] qemu: kvm: Enable XSAVE live migration support

2010-06-09 Thread Sheng Yang

Signed-off-by: Sheng Yang sh...@linux.intel.com
---
 qemu-kvm-x86.c|  114 
 qemu-kvm.c|   24 ++
 qemu-kvm.h|   28 
 target-i386/cpu.h |6 +++
 target-i386/machine.c |   21 +
 5 files changed, 174 insertions(+), 19 deletions(-)

diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c
index 3c33e64..b6396c6 100644
--- a/qemu-kvm-x86.c
+++ b/qemu-kvm-x86.c
@@ -772,10 +772,20 @@ static void get_seg(SegmentCache *lhs, const struct 
kvm_segment *rhs)
| (rhs-avl * DESC_AVL_MASK);
 }
 
+#define XSAVE_CWD_RIP 2
+#define XSAVE_CWD_RDP 4
+#define XSAVE_MXCSR   6
+#define XSAVE_ST_SPACE8
+#define XSAVE_XMM_SPACE   40
+#define XSAVE_XSTATE_BV   128
+#define XSAVE_YMMH_SPACE  144
+
 void kvm_arch_load_regs(CPUState *env, int level)
 {
 struct kvm_regs regs;
 struct kvm_fpu fpu;
+struct kvm_xsave* xsave;
+struct kvm_xcrs xcrs;
 struct kvm_sregs sregs;
 struct kvm_msr_entry msrs[100];
 int rc, n, i;
@@ -806,16 +816,50 @@ void kvm_arch_load_regs(CPUState *env, int level)
 
 kvm_set_regs(env, 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);
+if (kvm_check_extension(kvm_state, KVM_CAP_XSAVE)) {
+uint16_t cwd, swd, twd, fop;
+
+xsave = qemu_memalign(4096, sizeof(struct kvm_xsave));
+memset(xsave, 0, sizeof(struct kvm_xsave));
+cwd = swd = twd = fop = 0;
+swd = env-fpus  ~(7  11);
+swd |= (env-fpstt  7)  11;
+cwd = env-fpuc;
+for (i = 0; i  8; ++i)
+twd |= (!env-fptags[i])  i;
+xsave-region[0] = (uint32_t)(swd  16) + cwd;
+xsave-region[1] = (uint32_t)(fop  16) + twd;
+memcpy(xsave-region[XSAVE_ST_SPACE], env-fpregs,
+sizeof env-fpregs);
+memcpy(xsave-region[XSAVE_XMM_SPACE], env-xmm_regs,
+sizeof env-xmm_regs);
+xsave-region[XSAVE_MXCSR] = env-mxcsr;
+xsave-region[XSAVE_XSTATE_BV] = (uint32_t)env-xstate_bv;
+xsave-region[XSAVE_XSTATE_BV + 1] =
+(uint32_t)(env-xstate_bv  32);
+memcpy(xsave-region[XSAVE_YMMH_SPACE], env-ymmh_regs,
+sizeof env-ymmh_regs);
+xsave-size = env-xsave_size;
+kvm_set_xsave(env, xsave);
+if (kvm_check_extension(kvm_state, KVM_CAP_XCRS)) {
+xcrs.nr_xcrs = 1;
+xcrs.flags = 0;
+xcrs.xcrs[0].xcr = 0;
+xcrs.xcrs[0].value = env-xcr0;
+kvm_set_xcrs(env, xcrs);
+}
+} else {
+memset(fpu, 0, sizeof fpu);
+fpu.fsw = env-fpus  ~(7  11);
+fpu.fsw |= (env-fpstt  7)  11;
+fpu.fcw = env-fpuc;
+for (i = 0; i  8; ++i)
+fpu.ftwx |= (!env-fptags[i])  i;
+memcpy(fpu.fpr, env-fpregs, sizeof env-fpregs);
+memcpy(fpu.xmm, env-xmm_regs, sizeof env-xmm_regs);
+fpu.mxcsr = env-mxcsr;
+kvm_set_fpu(env, fpu);
+}
 
 memset(sregs.interrupt_bitmap, 0, sizeof(sregs.interrupt_bitmap));
 if (env-interrupt_injected = 0) {
@@ -934,6 +978,8 @@ void kvm_arch_save_regs(CPUState *env)
 {
 struct kvm_regs regs;
 struct kvm_fpu fpu;
+struct kvm_xsave* xsave;
+struct kvm_xcrs xcrs;
 struct kvm_sregs sregs;
 struct kvm_msr_entry msrs[100];
 uint32_t hflags;
@@ -965,15 +1011,45 @@ void kvm_arch_save_regs(CPUState *env)
 env-eflags = regs.rflags;
 env-eip = regs.rip;
 
-kvm_get_fpu(env, fpu);
-env-fpstt = (fpu.fsw  11)  7;
-env-fpus = fpu.fsw;
-env-fpuc = fpu.fcw;
-for (i = 0; i  8; ++i)
-   env-fptags[i] = !((fpu.ftwx  i)  1);
-memcpy(env-fpregs, fpu.fpr, sizeof env-fpregs);
-memcpy(env-xmm_regs, fpu.xmm, sizeof env-xmm_regs);
-env-mxcsr = fpu.mxcsr;
+if (kvm_check_extension(kvm_state, KVM_CAP_XSAVE)) {
+uint16_t cwd, swd, twd, fop;
+xsave = qemu_memalign(4096, sizeof(struct kvm_xsave));
+kvm_get_xsave(env, xsave);
+env-xsave_size = xsave-size;
+cwd = (uint16_t)xsave-region[0];
+swd = (uint16_t)(xsave-region[0]  16);
+twd = (uint16_t)xsave-region[1];
+fop = (uint16_t)(xsave-region[1]  16);
+env-fpstt = (swd  11)  7;
+env-fpus = swd;
+env-fpuc = cwd;
+for (i = 0; i  8; ++i)
+env-fptags[i] = !((twd  i)  1);
+env-mxcsr = xsave-region[XSAVE_MXCSR];
+memcpy(env-fpregs, xsave-region[XSAVE_ST_SPACE],
+sizeof env-fpregs);
+memcpy(env-xmm_regs, xsave-region[XSAVE_XMM_SPACE],
+sizeof env-xmm_regs);
+env-xstate_bv =
+((uint64_t)(xsave

[Qemu-devel] Re: [PATCH] qemu: Enable XSAVE related CPUID

2010-05-27 Thread Sheng Yang
On Thursday 27 May 2010 20:56:17 Avi Kivity wrote:
 On 05/27/2010 12:50 PM, Sheng Yang wrote:
  We can support it in KVM now. The initial values are the minimal
  requirement of XSAVE capable processor.
  
  Signed-off-by: Sheng Yangsh...@linux.intel.com
  ---
  
target-i386/cpuid.c |   32 
1 files changed, 32 insertions(+), 0 deletions(-)
  
  diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
  index eebf038..cbf5595 100644
  --- a/target-i386/cpuid.c
  +++ b/target-i386/cpuid.c
  @@ -1067,6 +1067,38 @@ 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 (count == 0) {
  +*eax = 0x7; /* FP | SSE | YMM */
  +*ebx = 0x340; /* FP + SSE + YMM size */
  +*ecx = 0x340; /* FP + SSE + YMM size */
 
 For -cpu host, we should pick these from KVM_GET_SUPPORTED_CPUID.  For
 canned cpu types (e.g. qemu64), we need to return what we always did.

Yes, I also prefer this way. didn't do this because it's somehow out of current 
QEmu CPUID setting mechanism.
 
 We can also add a new cpu type that has them built in (there's no cpu on
 the market with avx, right?)

Right... Let's use -cpu host now.

 
  +*edx = 0;
  +} else if (count == 1) {
  +/* eax = 1, so we can continue with others */
  +*eax = 1;
  +*ebx = 0;
  +*ecx = 0;
  +*edx = 0;
  +} else if (count == 2) {
  +*eax = 0x100; /* YMM size */
  +*ebx = 0x240; /* YMM offset */
  +*ecx = 0;
  +*edx = 0;
 
 These, too.

Sure.

--
regards
Yang, Sheng

 
  +} else {
  +*eax = 0;
  +*ebx = 0;
  +*ecx = 0;
  +*edx = 0;
  +}
  +break;
  
case 0x8000:
*eax = env-cpuid_xlevel;
*ebx = env-cpuid_vendor1;



[Qemu-devel] [PATCH v5] KVM: VMX: Enable XSAVE/XRSTORE for guest

2010-05-26 Thread Sheng Yang
From: Dexuan Cui dexuan@intel.com

This patch enable guest to use XSAVE/XRSTORE instructions.

We assume that host_xcr0 would use all possible bits that OS supported.

And we loaded xcr0 in the same way we handled fpu - do it as late as we can.

Signed-off-by: Dexuan Cui dexuan@intel.com
Signed-off-by: Sheng Yang sh...@linux.intel.com
---

I've done a prototype of LM support, would send out tomorrow. But the test
case in QEmu side seems got something wrong. I always got an segfault at:
qemu-kvm/hw/fw_cfg.c:223
223 s-entries[arch][key].data = data;

Haven't looked into it yet. But maybe someone knows the reason...

 arch/x86/include/asm/kvm_host.h |3 +
 arch/x86/include/asm/vmx.h  |1 +
 arch/x86/kvm/kvm_cache_regs.h   |6 ++
 arch/x86/kvm/vmx.c  |   26 ++
 arch/x86/kvm/x86.c  |  101 ---
 include/linux/kvm_host.h|2 +-
 6 files changed, 131 insertions(+), 8 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index d08bb4a..532b220 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -302,6 +302,7 @@ struct kvm_vcpu_arch {
} update_pte;
 
struct fpu guest_fpu;
+   u64 xcr0;
 
gva_t mmio_fault_cr2;
struct kvm_pio_request pio;
@@ -564,6 +565,8 @@ u8 kvm_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t 
gfn);
 
 extern bool tdp_enabled;
 
+extern u64 host_xcr0;
+
 enum emulation_result {
EMULATE_DONE,   /* no further processing */
EMULATE_DO_MMIO,  /* kvm_run filled with mmio request */
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
index 9e6779f..346ea66 100644
--- a/arch/x86/include/asm/vmx.h
+++ b/arch/x86/include/asm/vmx.h
@@ -266,6 +266,7 @@ enum vmcs_field {
 #define EXIT_REASON_EPT_VIOLATION   48
 #define EXIT_REASON_EPT_MISCONFIG   49
 #define EXIT_REASON_WBINVD 54
+#define EXIT_REASON_XSETBV 55
 
 /*
  * Interruption-information format
diff --git a/arch/x86/kvm/kvm_cache_regs.h b/arch/x86/kvm/kvm_cache_regs.h
index d2a98f8..6491ac8 100644
--- a/arch/x86/kvm/kvm_cache_regs.h
+++ b/arch/x86/kvm/kvm_cache_regs.h
@@ -71,4 +71,10 @@ static inline ulong kvm_read_cr4(struct kvm_vcpu *vcpu)
return kvm_read_cr4_bits(vcpu, ~0UL);
 }
 
+static inline u64 kvm_read_edx_eax(struct kvm_vcpu *vcpu)
+{
+   return (kvm_register_read(vcpu, VCPU_REGS_RAX)  -1u)
+   | ((u64)(kvm_register_read(vcpu, VCPU_REGS_RDX)  -1u)  32);
+}
+
 #endif
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 99ae513..a946841 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -36,6 +36,8 @@
 #include asm/vmx.h
 #include asm/virtext.h
 #include asm/mce.h
+#include asm/i387.h
+#include asm/xcr.h
 
 #include trace.h
 
@@ -3354,6 +3356,29 @@ static int handle_wbinvd(struct kvm_vcpu *vcpu)
return 1;
 }
 
+static int handle_xsetbv(struct kvm_vcpu *vcpu)
+{
+   u64 new_bv = kvm_read_edx_eax(vcpu);
+
+   if (kvm_register_read(vcpu, VCPU_REGS_RCX) != 0)
+   goto err;
+   if (vmx_get_cpl(vcpu) != 0)
+   goto err;
+   if (!(new_bv  XSTATE_FP))
+   goto err;
+   if ((new_bv  XSTATE_YMM)  !(new_bv  XSTATE_SSE))
+   goto err;
+   if (new_bv  ~host_xcr0)
+   goto err;
+   vcpu-arch.xcr0 = new_bv;
+   xsetbv(XCR_XFEATURE_ENABLED_MASK, vcpu-arch.xcr0);
+   skip_emulated_instruction(vcpu);
+   return 1;
+err:
+   kvm_inject_gp(vcpu, 0);
+   return 1;
+}
+
 static int handle_apic_access(struct kvm_vcpu *vcpu)
 {
return emulate_instruction(vcpu, 0, 0, 0) == EMULATE_DONE;
@@ -3632,6 +3657,7 @@ static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu 
*vcpu) = {
[EXIT_REASON_TPR_BELOW_THRESHOLD] = handle_tpr_below_threshold,
[EXIT_REASON_APIC_ACCESS] = handle_apic_access,
[EXIT_REASON_WBINVD]  = handle_wbinvd,
+   [EXIT_REASON_XSETBV]  = handle_xsetbv,
[EXIT_REASON_TASK_SWITCH] = handle_task_switch,
[EXIT_REASON_MCE_DURING_VMENTRY]  = handle_machine_check,
[EXIT_REASON_EPT_VIOLATION]   = handle_ept_violation,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 7be1d36..c04d3cb 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -64,6 +64,7 @@
(~(unsigned long)(X86_CR4_VME | X86_CR4_PVI | X86_CR4_TSD | X86_CR4_DE\
  | X86_CR4_PSE | X86_CR4_PAE | X86_CR4_MCE \
  | X86_CR4_PGE | X86_CR4_PCE | X86_CR4_OSFXSR  \
+ | X86_CR4_OSXSAVE \
  | X86_CR4_OSXMMEXCPT | X86_CR4_VMXE))
 
 #define CR8_RESERVED_BITS (~(unsigned long)X86_CR8_TPR)
@@ -149,6 +150,14 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
{ NULL }
 };
 
+u64 __read_mostly host_xcr0;
+EXPORT_SYMBOL_GPL

[Qemu-devel] [PATCH] qemu-kvm: Enable xsave related CPUID

2010-05-19 Thread Sheng Yang

Signed-off-by: Sheng Yang sh...@linux.intel.com
---
 target-i386/cpuid.c |   32 
 1 files changed, 32 insertions(+), 0 deletions(-)

diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index eebf038..21e94f3 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -1067,6 +1067,38 @@ 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 (count == 0) {
+*eax = 0x7;
+*ebx = 0x340;
+*ecx = 0x340;
+*edx = 0;
+} else if (count == 1) {
+/* eax = 1, so we can continue with others */
+*eax = 1;
+*ebx = 0;
+*ecx = 0;
+*edx = 0;
+} else if (count == 2) {
+*eax = 0x100;
+*ebx = 0x240;
+*ecx = 0;
+*edx = 0;
+} else {
+*eax = 0;
+*ebx = 0;
+*ecx = 0;
+*edx = 0;
+}
+break;
 case 0x8000:
 *eax = env-cpuid_xlevel;
 *ebx = env-cpuid_vendor1;
-- 
1.7.0.1




[Qemu-devel] [PATCH v2] KVM: VMX: Enable XSAVE/XRSTORE for guest

2010-05-19 Thread Sheng Yang
From: Dexuan Cui dexuan@intel.com

Enable XSAVE/XRSTORE for guest.

Change from V1:

1. Use FPU API.
2. Fix CPUID issue.
3. Save/restore all possible guest xstate fields when switching. Because we
don't know which fields guest has already touched.

Signed-off-by: Dexuan Cui dexuan@intel.com
Signed-off-by: Sheng Yang sh...@linux.intel.com
---
 arch/x86/include/asm/kvm_host.h |1 +
 arch/x86/include/asm/vmx.h  |1 +
 arch/x86/kvm/vmx.c  |   28 +
 arch/x86/kvm/x86.c  |   85 +++---
 4 files changed, 108 insertions(+), 7 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index d08bb4a..78d7b06 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -302,6 +302,7 @@ struct kvm_vcpu_arch {
} update_pte;
 
struct fpu guest_fpu;
+   uint64_t xcr0, host_xcr0;
 
gva_t mmio_fault_cr2;
struct kvm_pio_request pio;
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
index 9e6779f..346ea66 100644
--- a/arch/x86/include/asm/vmx.h
+++ b/arch/x86/include/asm/vmx.h
@@ -266,6 +266,7 @@ enum vmcs_field {
 #define EXIT_REASON_EPT_VIOLATION   48
 #define EXIT_REASON_EPT_MISCONFIG   49
 #define EXIT_REASON_WBINVD 54
+#define EXIT_REASON_XSETBV 55
 
 /*
  * Interruption-information format
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 99ae513..2ee8ff6 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -36,6 +36,8 @@
 #include asm/vmx.h
 #include asm/virtext.h
 #include asm/mce.h
+#include asm/i387.h
+#include asm/xcr.h
 
 #include trace.h
 
@@ -2616,6 +2618,8 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
vmx-vcpu.arch.cr4_guest_owned_bits = KVM_CR4_GUEST_OWNED_BITS;
if (enable_ept)
vmx-vcpu.arch.cr4_guest_owned_bits |= X86_CR4_PGE;
+   if (cpu_has_xsave)
+   vmx-vcpu.arch.cr4_guest_owned_bits |= X86_CR4_OSXSAVE;
vmcs_writel(CR4_GUEST_HOST_MASK, ~vmx-vcpu.arch.cr4_guest_owned_bits);
 
tsc_base = vmx-vcpu.kvm-arch.vm_init_tsc;
@@ -3354,6 +3358,29 @@ static int handle_wbinvd(struct kvm_vcpu *vcpu)
return 1;
 }
 
+static int handle_xsetbv(struct kvm_vcpu *vcpu)
+{
+   u64 new_bv = ((u64)(kvm_register_read(vcpu, VCPU_REGS_RDX)  32)) |
+   kvm_register_read(vcpu, VCPU_REGS_RAX);
+
+   if (kvm_register_read(vcpu, VCPU_REGS_RCX) != 0)
+   goto err;
+   if (vmx_get_cpl(vcpu) != 0)
+   goto err;
+   if (!(new_bv  XSTATE_FP) ||
+(new_bv  ~vcpu-arch.host_xcr0))
+   goto err;
+   if ((new_bv  XSTATE_YMM)  !(new_bv  XSTATE_SSE))
+   goto err;
+   vcpu-arch.xcr0 = new_bv;
+   xsetbv(XCR_XFEATURE_ENABLED_MASK, vcpu-arch.xcr0);
+   skip_emulated_instruction(vcpu);
+   return 1;
+err:
+   kvm_inject_gp(vcpu, 0);
+   return 1;
+}
+
 static int handle_apic_access(struct kvm_vcpu *vcpu)
 {
return emulate_instruction(vcpu, 0, 0, 0) == EMULATE_DONE;
@@ -3632,6 +3659,7 @@ static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu 
*vcpu) = {
[EXIT_REASON_TPR_BELOW_THRESHOLD] = handle_tpr_below_threshold,
[EXIT_REASON_APIC_ACCESS] = handle_apic_access,
[EXIT_REASON_WBINVD]  = handle_wbinvd,
+   [EXIT_REASON_XSETBV]  = handle_xsetbv,
[EXIT_REASON_TASK_SWITCH] = handle_task_switch,
[EXIT_REASON_MCE_DURING_VMENTRY]  = handle_machine_check,
[EXIT_REASON_EPT_VIOLATION]   = handle_ept_violation,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 7be1d36..5e20f37 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -64,6 +64,7 @@
(~(unsigned long)(X86_CR4_VME | X86_CR4_PVI | X86_CR4_TSD | X86_CR4_DE\
  | X86_CR4_PSE | X86_CR4_PAE | X86_CR4_MCE \
  | X86_CR4_PGE | X86_CR4_PCE | X86_CR4_OSFXSR  \
+ | X86_CR4_OSXSAVE \
  | X86_CR4_OSXMMEXCPT | X86_CR4_VMXE))
 
 #define CR8_RESERVED_BITS (~(unsigned long)X86_CR8_TPR)
@@ -149,6 +150,11 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
{ NULL }
 };
 
+static inline u32 bit(int bitno)
+{
+   return 1  (bitno  31);
+}
+
 static void kvm_on_user_return(struct user_return_notifier *urn)
 {
unsigned slot;
@@ -473,6 +479,17 @@ void kvm_lmsw(struct kvm_vcpu *vcpu, unsigned long msw)
 }
 EXPORT_SYMBOL_GPL(kvm_lmsw);
 
+static bool guest_cpuid_has_xsave(struct kvm_vcpu *vcpu)
+{
+   struct kvm_cpuid_entry2 *best;
+
+   best = kvm_find_cpuid_entry(vcpu, 1, 0);
+   if (best-ecx  bit(X86_FEATURE_XSAVE))
+   return true;
+
+   return false;
+}
+
 int __kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 {
unsigned long old_cr4 = kvm_read_cr4(vcpu);
@@ -481,6 +498,9 @@ int

[Qemu-devel] Re: Completing big real mode emulation

2010-03-24 Thread Sheng Yang
On Saturday 20 March 2010 23:00:49 Alexander Graf wrote:
 Am 20.03.2010 um 15:02 schrieb Mohammed Gamal m.gamal...@gmail.com:
  On Sat, Mar 20, 2010 at 3:18 PM, Avi Kivity a...@redhat.com wrote:
  On 03/20/2010 10:55 AM, Alexander Graf wrote:
  I'd say that a GSoC project would rather focus on making a guest
  OS work
  than working on generic big real mode. Having Windows 98 support
  is way more
  visible to the users. And hopefully more fun to implement too,
  as it's a
  visible goal :-).
 
  Big real mode allows you to boot various OSes, such as that old
  Ubuntu/SuSE boot loader which triggered the whole thing.
 
  I thought legacy Windows uses it too?
 
  IIRC even current Windows (last I checked was XP, but it's probably
  true for
  newer) invokes big real mode inadvertently.  All it takes is not to
  clear fs
  and gs while switching to real mode.  It works because the real
  mode code
  never uses gs and fs (i.e. while we are technically in big real
  mode, the
  guest never relies on this), and because there are enough hacks in
  vmx.c to
  make it work (restoring fs and gs after the switch back).  IIRC
  there are
  other cases of invalid guest state that we hack into place during
  mode
  switches.
 
  Either way - then we should make the goal of the project to
  support those
  old boot loaders. IMHO it should contain visibility. Doing
  theoretical stuff
  is just less fun for all parties. Or does that stuff work already?
 
  Mostly those old guests aged beyond usefulness.  They are still
  broken, but
  nobody installs new images.  Old images installed via workarounds
  work.
 
  Goals for this task could include:
 
   - get those older guests working
   - get emulate_invalid_guest_state=1 to work on all supported guests
   - switch to emulate_invalid_guest_state=1 as the default
   - drop the code supporting emulate_invalid_guest_state=0 eventually
 
  To this end I guess the next logical step is to compile a list of
  guests that are currently not working/work with hacks only, and get
  them working. Here are some suggestions:
  - MINIX 3.1.6 (developers have been recently filing bug reports
  because of boot failures)
  - Win XP with emulation enabled
  - FreeDOS with memory extenders
 
  Any other guests you'd like to see on this list?
 
 I remember old openSUSE iso bootloaders had issues. I think it was
 around 10.3, but might have been earlier.
 
At least 10u2 installer has trouble. I had spent some time on it, finally 
found it's due to ISOLINUX.

The basic issue is it assume that SS selector/base is unchanged when 
enter/exit protect mode. At that time, I've cooked a hack workaround for it, 
but didn't think it's proper to upstream.

-- 
regards
Yang, Sheng




[Qemu-devel] Re: [PATCH] qemu-img: avoid preprocessor directives in a printf call

2010-02-04 Thread Sheng Yang
On Thursday 04 February 2010 21:29:40 Paolo Bonzini wrote:
 Other choices include using (printf), but this one is not bad in
 terms of readability.

This works well. :)

Acked-by: Sheng Yang sh...@linux.intel.com
 
 Signed-off-by: Paolo Bonzini pbonz...@redhat.com

And there is two more...

One is:

readline.c:31:1: error: printf redefined
In file included from /usr/include/stdio.h:844,
 from qemu-common.h:21,
 from readline.h:4,
 from readline.c:24:
/usr/include/bits/stdio2.h:65:1: error: this is the location of the previous 
definition
make: *** [readline.o] Error 1

Of course, what you can see in readline.c is:

#define printf do_not_use_printf

I guess it's OK to remove this?

And there is last one in help() of vl.c...

After resolve these three, the build is fine now.

Paolo, could you address the other two issues as well in your patch? Thanks!

-- 
regards
Yang, Sheng





[Qemu-devel] Re: [PATCH 0/4] Fix printf calls embedding preprocessor directives

2010-02-04 Thread Sheng Yang
On Thursday 04 February 2010 23:49:55 Paolo Bonzini wrote:
 Patch 1 is the same I sent earlier.  Patches 2 and 3/4 fix the
 other two problems by Sheng (tip: next time use make -k and
 report all problems in a single message).
 
 Paolo Bonzini (4):
   qemu-img: avoid preprocessor directives in a printf call
   cope with printf macro definition in readline.c
   do not interpolate % from vl.c to qemu-options.h
   vl.c: avoid preprocessor directives in a printf call
 
  qemu-img.c  |9 +
  qemu-options.hx |   15 ---
  readline.c  |1 +
  vl.c|   23 +--
  4 files changed, 23 insertions(+), 25 deletions(-)
 
Works fine with me. Thanks. :)

But:

diff --git a/vl.c b/vl.c
index 39833fc..3d2de7b 100644
--- a/vl.c
+++ b/vl.c
@@ -4041,14 +4041,7 @@ static void help(int exitcode)
\n
When using -nographic, press 'ctrl-a h' to get some help.\n
,
-   qemu,
-   DEFAULT_RAM_SIZE,
-#ifndef _WIN32
-   DEFAULT_NETWORK_SCRIPT,
-   DEFAULT_NETWORK_DOWN_SCRIPT,
-#endif
-   DEFAULT_GDBSTUB_PORT,
-   /tmp/qemu.log);
+   qemu);
 exit(exitcode);
 }

Is it proper to remove #ifndef _WIN32 there?

-- 
regards
Yang, Sheng




Re: [Qemu-devel] [PATCH v2 resend 2/4] qemu-img: Fix qemu-img can't create qcow image based on read-only image

2010-02-04 Thread Sheng Yang
On Friday 05 February 2010 06:04:27 Naphtali Sprei wrote:
 Open image file read-only where possible
 Patch originally written by Sheng Yang sh...@linux.intel.com
 

Signed-off-by: Sheng Yang sh...@linux.intel.com

 Signed-off-by: Naphtali Sprei nsp...@redhat.com

-- 
regards
Yang, Sheng
 ---
  qemu-img.c |   15 ++-
  1 files changed, 10 insertions(+), 5 deletions(-)
 
 diff --git a/qemu-img.c b/qemu-img.c
 index cbba4fc..b0ac9eb 100644
 --- a/qemu-img.c
 +++ b/qemu-img.c
 @@ -188,11 +188,13 @@ static int read_password(char *buf, int buf_size)
  #endif
 
  static BlockDriverState *bdrv_new_open(const char *filename,
 -   const char *fmt)
 +   const char *fmt,
 +   int readonly)
  {
  BlockDriverState *bs;
  BlockDriver *drv;
  char password[256];
 +int flags = BRDV_O_FLAGS;
 
  bs = bdrv_new();
  if (!bs)
 @@ -204,7 +206,10 @@ static BlockDriverState *bdrv_new_open(const char
  *filename, } else {
  drv = NULL;
  }
 -if (bdrv_open2(bs, filename, BRDV_O_FLAGS | BDRV_O_RDWR, drv)  0) {
 +if (!readonly) {
 +flags |= BDRV_O_RDWR;
 +}
 +if (bdrv_open2(bs, filename, flags, drv)  0) {
  error(Could not open '%s', filename);
  }
  if (bdrv_is_encrypted(bs)) {
 @@ -343,7 +348,7 @@ static int img_create(int argc, char **argv)
  }
  }
 
 -bs = bdrv_new_open(backing_file-value.s, fmt);
 +bs = bdrv_new_open(backing_file-value.s, fmt, 1);
  bdrv_get_geometry(bs, size);
  size *= 512;
  bdrv_delete(bs);
 @@ -627,7 +632,7 @@ static int img_convert(int argc, char **argv)
 
  total_sectors = 0;
  for (bs_i = 0; bs_i  bs_n; bs_i++) {
 -bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt);
 +bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, 1);
  if (!bs[bs_i])
  error(Could not open '%s', argv[optind + bs_i]);
  bdrv_get_geometry(bs[bs_i], bs_sectors);
 @@ -685,7 +690,7 @@ static int img_convert(int argc, char **argv)
  }
  }
 
 -out_bs = bdrv_new_open(out_filename, out_fmt);
 +out_bs = bdrv_new_open(out_filename, out_fmt, 0);
 
  bs_i = 0;
  bs_offset = 0;
 




Re: [Qemu-devel] [PATCH v2 resend 0/4] block: more read-only changes, related to backing files

2010-02-04 Thread Sheng Yang
On Friday 05 February 2010 06:04:25 Naphtali Sprei wrote:
 This is version 2. The change between previous patch (only 3/4) is the
  order of closing/re-opening the image.
 
 Naphtali Sprei (4):
   Add open_flags to BlockDriverState Will be used later
   qemu-img: Fix qemu-img can't create qcow image based on read-only
 image
   Block: readonly changes
   Open backing file read-only also for snapshot mode
 
(CC to the original reviewers...)

-- 
regards
Yang, Sheng




[Qemu-devel] Enable _FORTIFY_SOURCE=2 result in building failure for qemu-img.c

2010-02-03 Thread Sheng Yang
Got this building failure:

In file included from qemu-img.c:68:


qemu-img-cmds.h:22:1: error: unterminated argument list invoking macro 
printf
 
cc1: warnings being treated as errors
qemu-img.c: In function ‘help’:
qemu-img.c:95: warning: statement with no effect
qemu-img.c:71: error: expected ‘;’ before string constant
qemu-img.c:95: error: expected statement before ‘)’ token
make: *** [qemu-img.o] Error 1

And git bisect figure out the commit: 84958305, Enable _FORTIFY_SOURCE=2.

And the code is here:

printf(qemu-img version  QEMU_VERSION , Copyright (c) 2004-2008 Fabrice 
Bellard\n
   usage: qemu-img command [command options]\n
   QEMU disk image utility\n
   \n
   Command syntax:\n
#define DEF(option, callback, arg_string)\
  arg_string \n
#include qemu-img-cmds.h
#undef DEF
#undef GEN_DOCS


Seems gcc take printf as a marco. I added a #undef printf before the line, 
then it works...

So any clue on what's happened and how to fix?

GCC version is 4.1.2.

-- 
regards
Yang, Sheng




Re: [Qemu-devel] [PATCH] Fix qemu-img can't create qcow image based on read-only image

2010-01-28 Thread Sheng Yang
On Thursday 28 January 2010 17:17:22 Kevin Wolf wrote:
 Am 28.01.2010 06:22, schrieb Sheng Yang:
  Commit 03cbdac7 Disable fall-back to read-only when cannot open drive's
  file for read-write result in read-only image can't be used as backed
  image in qemu-img.
 
  CC: Naphtali Sprei nsp...@redhat.com
  Signed-off-by: Sheng Yang sh...@linux.intel.com
  ---
 
  This issue blocked our QA's KVM nightly test. But in fact, I don't like
  this patch, feeling uncomfortable to change long existed interface... Any
  alternative? Add a readonly command line would change the default
  behavior(I don't think fall back to readonly looks like a bug); or even
  revert the commit? What's the story behind it?
 
   qemu-img.c |   15 ++-
   1 files changed, 10 insertions(+), 5 deletions(-)
 
  diff --git a/qemu-img.c b/qemu-img.c
  index 3cea8ce..f8be5cb 100644
  --- a/qemu-img.c
  +++ b/qemu-img.c
  @@ -188,11 +188,13 @@ static int read_password(char *buf, int buf_size)
   #endif
 
   static BlockDriverState *bdrv_new_open(const char *filename,
  -   const char *fmt)
  +   const char *fmt,
  +   int readonly)
   {
   BlockDriverState *bs;
   BlockDriver *drv;
   char password[256];
  +int flags = BRDV_O_FLAGS;
 
   bs = bdrv_new();
   if (!bs)
  @@ -204,7 +206,10 @@ static BlockDriverState *bdrv_new_open(const char
  *filename, } else {
   drv = NULL;
   }
  -if (bdrv_open2(bs, filename, BRDV_O_FLAGS | BDRV_O_RDWR, drv)  0) {
  +if (!readonly) {
  +flags |= BDRV_O_RDWR;
  +}
  +if (bdrv_open2(bs, filename, flags, drv)  0) {
   error(Could not open '%s', filename);
   }
   if (bdrv_is_encrypted(bs)) {
  @@ -343,7 +348,7 @@ static int img_create(int argc, char **argv)
   }
   }
 
  -bs = bdrv_new_open(backing_file-value.s, fmt);
  +bs = bdrv_new_open(backing_file-value.s, fmt, 1);
   bdrv_get_geometry(bs, size);
   size *= 512;
   bdrv_delete(bs);
  @@ -627,7 +632,7 @@ static int img_convert(int argc, char **argv)
 
   total_sectors = 0;
   for (bs_i = 0; bs_i  bs_n; bs_i++) {
  -bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt);
  +bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, 0);
 
 Shouldn't it be read-only here, too?
 
Yes. 

Seems you guys are OK with this solution(and I think it's reasonable to remove 
the fall back). I would update the patch, hopefully it can be applied soon and 
picked up by Marcelo to resolve our block issue...

-- 
regards
Yang, Sheng




[Qemu-devel] [PATCH v2] qemu-img: Fix qemu-img can't create qcow image based on read-only image

2010-01-28 Thread Sheng Yang
Commit 03cbdac7 Disable fall-back to read-only when cannot open drive's
file for read-write result in read-only image can't be used as backed
image in qemu-img.

Cc: Naphtali Sprei nsp...@redhat.com
Signed-off-by: Sheng Yang sh...@linux.intel.com
---
 qemu-img.c |   15 ++-
 1 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/qemu-img.c b/qemu-img.c
index 3cea8ce..ac4d15e 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -188,11 +188,13 @@ static int read_password(char *buf, int buf_size)
 #endif
 
 static BlockDriverState *bdrv_new_open(const char *filename,
-   const char *fmt)
+   const char *fmt,
+   int readonly)
 {
 BlockDriverState *bs;
 BlockDriver *drv;
 char password[256];
+int flags = BRDV_O_FLAGS;
 
 bs = bdrv_new();
 if (!bs)
@@ -204,7 +206,10 @@ static BlockDriverState *bdrv_new_open(const char 
*filename,
 } else {
 drv = NULL;
 }
-if (bdrv_open2(bs, filename, BRDV_O_FLAGS | BDRV_O_RDWR, drv)  0) {
+if (!readonly) {
+flags |= BDRV_O_RDWR;
+}
+if (bdrv_open2(bs, filename, flags, drv)  0) {
 error(Could not open '%s', filename);
 }
 if (bdrv_is_encrypted(bs)) {
@@ -343,7 +348,7 @@ static int img_create(int argc, char **argv)
 }
 }
 
-bs = bdrv_new_open(backing_file-value.s, fmt);
+bs = bdrv_new_open(backing_file-value.s, fmt, 1);
 bdrv_get_geometry(bs, size);
 size *= 512;
 bdrv_delete(bs);
@@ -627,7 +632,7 @@ static int img_convert(int argc, char **argv)
 
 total_sectors = 0;
 for (bs_i = 0; bs_i  bs_n; bs_i++) {
-bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt);
+bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, 1);
 if (!bs[bs_i])
 error(Could not open '%s', argv[optind + bs_i]);
 bdrv_get_geometry(bs[bs_i], bs_sectors);
@@ -685,7 +690,7 @@ static int img_convert(int argc, char **argv)
 }
 }
 
-out_bs = bdrv_new_open(out_filename, out_fmt);
+out_bs = bdrv_new_open(out_filename, out_fmt, 0);
 
 bs_i = 0;
 bs_offset = 0;
-- 
1.5.4.5





[Qemu-devel] [PATCH] Fix qemu-img can't create qcow image based on read-only image

2010-01-27 Thread Sheng Yang
Commit 03cbdac7 Disable fall-back to read-only when cannot open drive's
file for read-write result in read-only image can't be used as backed
image in qemu-img.

CC: Naphtali Sprei nsp...@redhat.com
Signed-off-by: Sheng Yang sh...@linux.intel.com
---

This issue blocked our QA's KVM nightly test. But in fact, I don't like this
patch, feeling uncomfortable to change long existed interface... Any
alternative? Add a readonly command line would change the default behavior(I
don't think fall back to readonly looks like a bug); or even revert the
commit? What's the story behind it?

 qemu-img.c |   15 ++-
 1 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/qemu-img.c b/qemu-img.c
index 3cea8ce..f8be5cb 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -188,11 +188,13 @@ static int read_password(char *buf, int buf_size)
 #endif
 
 static BlockDriverState *bdrv_new_open(const char *filename,
-   const char *fmt)
+   const char *fmt,
+   int readonly)
 {
 BlockDriverState *bs;
 BlockDriver *drv;
 char password[256];
+int flags = BRDV_O_FLAGS;
 
 bs = bdrv_new();
 if (!bs)
@@ -204,7 +206,10 @@ static BlockDriverState *bdrv_new_open(const char 
*filename,
 } else {
 drv = NULL;
 }
-if (bdrv_open2(bs, filename, BRDV_O_FLAGS | BDRV_O_RDWR, drv)  0) {
+if (!readonly) {
+flags |= BDRV_O_RDWR;
+}
+if (bdrv_open2(bs, filename, flags, drv)  0) {
 error(Could not open '%s', filename);
 }
 if (bdrv_is_encrypted(bs)) {
@@ -343,7 +348,7 @@ static int img_create(int argc, char **argv)
 }
 }
 
-bs = bdrv_new_open(backing_file-value.s, fmt);
+bs = bdrv_new_open(backing_file-value.s, fmt, 1);
 bdrv_get_geometry(bs, size);
 size *= 512;
 bdrv_delete(bs);
@@ -627,7 +632,7 @@ static int img_convert(int argc, char **argv)
 
 total_sectors = 0;
 for (bs_i = 0; bs_i  bs_n; bs_i++) {
-bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt);
+bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, 0);
 if (!bs[bs_i])
 error(Could not open '%s', argv[optind + bs_i]);
 bdrv_get_geometry(bs[bs_i], bs_sectors);
@@ -685,7 +690,7 @@ static int img_convert(int argc, char **argv)
 }
 }
 
-out_bs = bdrv_new_open(out_filename, out_fmt);
+out_bs = bdrv_new_open(out_filename, out_fmt, 0);
 
 bs_i = 0;
 bs_offset = 0;
-- 
1.5.4.5





[Qemu-devel] [PATCH v2][uqmaster] kvm: Flush coalesced MMIO buffer periodly

2010-01-26 Thread Sheng Yang
The default action of coalesced MMIO is, cache the writing in buffer, until:
1. The buffer is full.
2. Or the exit to QEmu due to other reasons.

But this would result in a very late writing in some condition.
1. The each time write to MMIO content is small.
2. The writing interval is big.
3. No need for input or accessing other devices frequently.

This issue was observed in a experimental embbed system. The test image
simply print test every 1 seconds. The output in QEmu meets expectation,
but the output in KVM is delayed for seconds.

Per Avi's suggestion, I hooked flushing coalesced MMIO buffer in VGA update
handler. By this way, We don't need vcpu explicit exit to QEmu to
handle this issue.

Signed-off-by: Sheng Yang sh...@linux.intel.com
---
 cpu-all.h |2 ++
 exec.c|6 ++
 kvm-all.c |   21 +
 kvm.h |1 +
 vl.c  |2 ++
 5 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/cpu-all.h b/cpu-all.h
index 57b69f8..1ccc9a8 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -915,6 +915,8 @@ void qemu_register_coalesced_mmio(target_phys_addr_t addr, 
ram_addr_t size);
 
 void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size);
 
+void qemu_flush_coalesced_mmio_buffer(void);
+
 /***/
 /* host CPU ticks (if available) */
 
diff --git a/exec.c b/exec.c
index 1190591..6875370 100644
--- a/exec.c
+++ b/exec.c
@@ -2406,6 +2406,12 @@ void qemu_unregister_coalesced_mmio(target_phys_addr_t 
addr, ram_addr_t size)
 kvm_uncoalesce_mmio_region(addr, size);
 }
 
+void qemu_flush_coalesced_mmio_buffer(void)
+{
+if (kvm_enabled())
+kvm_flush_coalesced_mmio_buffer();
+}
+
 ram_addr_t qemu_ram_alloc(ram_addr_t size)
 {
 RAMBlock *new_block;
diff --git a/kvm-all.c b/kvm-all.c
index 15ec38e..889fc42 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -59,6 +59,7 @@ struct KVMState
 int vmfd;
 int regs_modified;
 int coalesced_mmio;
+struct kvm_coalesced_mmio_ring *coalesced_mmio_ring;
 int broken_set_mem_region;
 int migration_log;
 int vcpu_events;
@@ -200,6 +201,12 @@ int kvm_init_vcpu(CPUState *env)
 goto err;
 }
 
+#ifdef KVM_CAP_COALESCED_MMIO
+if (s-coalesced_mmio  !s-coalesced_mmio_ring)
+s-coalesced_mmio_ring = (void *) env-kvm_run +
+   s-coalesced_mmio * PAGE_SIZE;
+#endif
+
 ret = kvm_arch_init_vcpu(env);
 if (ret == 0) {
 qemu_register_reset(kvm_reset_vcpu, env);
@@ -466,10 +473,10 @@ int kvm_init(int smp_cpus)
 goto err;
 }
 
+s-coalesced_mmio = 0;
+s-coalesced_mmio_ring = NULL;
 #ifdef KVM_CAP_COALESCED_MMIO
 s-coalesced_mmio = kvm_check_extension(s, KVM_CAP_COALESCED_MMIO);
-#else
-s-coalesced_mmio = 0;
 #endif
 
 s-broken_set_mem_region = 1;
@@ -544,14 +551,12 @@ static int kvm_handle_io(uint16_t port, void *data, int 
direction, int size,
 return 1;
 }
 
-static void kvm_run_coalesced_mmio(CPUState *env, struct kvm_run *run)
+void kvm_flush_coalesced_mmio_buffer(void)
 {
 #ifdef KVM_CAP_COALESCED_MMIO
 KVMState *s = kvm_state;
-if (s-coalesced_mmio) {
-struct kvm_coalesced_mmio_ring *ring;
-
-ring = (void *)run + (s-coalesced_mmio * TARGET_PAGE_SIZE);
+if (s-coalesced_mmio_ring) {
+struct kvm_coalesced_mmio_ring *ring = s-coalesced_mmio_ring;
 while (ring-first != ring-last) {
 struct kvm_coalesced_mmio *ent;
 
@@ -609,7 +614,7 @@ int kvm_cpu_exec(CPUState *env)
 abort();
 }
 
-kvm_run_coalesced_mmio(env, run);
+kvm_flush_coalesced_mmio_buffer();
 
 ret = 0; /* exit loop */
 switch (run-exit_reason) {
diff --git a/kvm.h b/kvm.h
index 1c93ac5..59cba18 100644
--- a/kvm.h
+++ b/kvm.h
@@ -53,6 +53,7 @@ void kvm_setup_guest_memory(void *start, size_t size);
 
 int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size);
 int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size);
+void kvm_flush_coalesced_mmio_buffer(void);
 
 int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
   target_ulong len, int type);
diff --git a/vl.c b/vl.c
index 2b0b653..1f0c536 100644
--- a/vl.c
+++ b/vl.c
@@ -3193,6 +3193,7 @@ static void gui_update(void *opaque)
 DisplayState *ds = opaque;
 DisplayChangeListener *dcl = ds-listeners;
 
+qemu_flush_coalesced_mmio_buffer();
 dpy_refresh(ds);
 
 while (dcl != NULL) {
@@ -3208,6 +3209,7 @@ static void nographic_update(void *opaque)
 {
 uint64_t interval = GUI_REFRESH_INTERVAL;
 
+qemu_flush_coalesced_mmio_buffer();
 qemu_mod_timer(nographic_timer, interval + qemu_get_clock(rt_clock));
 }
 
-- 
1.5.4.5





[Qemu-devel] Re: [PATCH v2][uqmaster] kvm: Flush coalesced MMIO buffer periodly

2010-01-26 Thread Sheng Yang
On Tue, Jan 26, 2010 at 10:59:17AM +0100, Alexander Graf wrote:
 
 On 26.01.2010, at 10:41, Sheng Yang wrote:
 
  --- a/kvm-all.c
  +++ b/kvm-all.c
  @@ -59,6 +59,7 @@ struct KVMState
  int vmfd;
  int regs_modified;
  int coalesced_mmio;
  +struct kvm_coalesced_mmio_ring *coalesced_mmio_ring;
 
 I guess this needs to be guarded by an #ifdef?

Oh, yes. Thanks for reminder. :)

-- 
regards
Yang, Sheng




[Qemu-devel] [PATCH v3][uqmaster] kvm: Flush coalesced MMIO buffer periodly

2010-01-26 Thread Sheng Yang
The default action of coalesced MMIO is, cache the writing in buffer, until:
1. The buffer is full.
2. Or the exit to QEmu due to other reasons.

But this would result in a very late writing in some condition.
1. The each time write to MMIO content is small.
2. The writing interval is big.
3. No need for input or accessing other devices frequently.

This issue was observed in a experimental embbed system. The test image
simply print test every 1 seconds. The output in QEmu meets expectation,
but the output in KVM is delayed for seconds.

Per Avi's suggestion, I hooked flushing coalesced MMIO buffer in VGA update
handler. By this way, We don't need vcpu explicit exit to QEmu to
handle this issue.

Signed-off-by: Sheng Yang sh...@linux.intel.com
---
 cpu-all.h |2 ++
 exec.c|6 ++
 kvm-all.c |   23 +++
 kvm.h |1 +
 vl.c  |2 ++
 5 files changed, 26 insertions(+), 8 deletions(-)

diff --git a/cpu-all.h b/cpu-all.h
index 57b69f8..1ccc9a8 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -915,6 +915,8 @@ void qemu_register_coalesced_mmio(target_phys_addr_t addr, 
ram_addr_t size);
 
 void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size);
 
+void qemu_flush_coalesced_mmio_buffer(void);
+
 /***/
 /* host CPU ticks (if available) */
 
diff --git a/exec.c b/exec.c
index 1190591..6875370 100644
--- a/exec.c
+++ b/exec.c
@@ -2406,6 +2406,12 @@ void qemu_unregister_coalesced_mmio(target_phys_addr_t 
addr, ram_addr_t size)
 kvm_uncoalesce_mmio_region(addr, size);
 }
 
+void qemu_flush_coalesced_mmio_buffer(void)
+{
+if (kvm_enabled())
+kvm_flush_coalesced_mmio_buffer();
+}
+
 ram_addr_t qemu_ram_alloc(ram_addr_t size)
 {
 RAMBlock *new_block;
diff --git a/kvm-all.c b/kvm-all.c
index 15ec38e..f8350c9 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -59,6 +59,9 @@ struct KVMState
 int vmfd;
 int regs_modified;
 int coalesced_mmio;
+#ifdef KVM_CAP_COALESCED_MMIO
+struct kvm_coalesced_mmio_ring *coalesced_mmio_ring;
+#endif
 int broken_set_mem_region;
 int migration_log;
 int vcpu_events;
@@ -200,6 +203,12 @@ int kvm_init_vcpu(CPUState *env)
 goto err;
 }
 
+#ifdef KVM_CAP_COALESCED_MMIO
+if (s-coalesced_mmio  !s-coalesced_mmio_ring)
+s-coalesced_mmio_ring = (void *) env-kvm_run +
+   s-coalesced_mmio * PAGE_SIZE;
+#endif
+
 ret = kvm_arch_init_vcpu(env);
 if (ret == 0) {
 qemu_register_reset(kvm_reset_vcpu, env);
@@ -466,10 +475,10 @@ int kvm_init(int smp_cpus)
 goto err;
 }
 
+s-coalesced_mmio = 0;
 #ifdef KVM_CAP_COALESCED_MMIO
 s-coalesced_mmio = kvm_check_extension(s, KVM_CAP_COALESCED_MMIO);
-#else
-s-coalesced_mmio = 0;
+s-coalesced_mmio_ring = NULL;
 #endif
 
 s-broken_set_mem_region = 1;
@@ -544,14 +553,12 @@ static int kvm_handle_io(uint16_t port, void *data, int 
direction, int size,
 return 1;
 }
 
-static void kvm_run_coalesced_mmio(CPUState *env, struct kvm_run *run)
+void kvm_flush_coalesced_mmio_buffer(void)
 {
 #ifdef KVM_CAP_COALESCED_MMIO
 KVMState *s = kvm_state;
-if (s-coalesced_mmio) {
-struct kvm_coalesced_mmio_ring *ring;
-
-ring = (void *)run + (s-coalesced_mmio * TARGET_PAGE_SIZE);
+if (s-coalesced_mmio_ring) {
+struct kvm_coalesced_mmio_ring *ring = s-coalesced_mmio_ring;
 while (ring-first != ring-last) {
 struct kvm_coalesced_mmio *ent;
 
@@ -609,7 +616,7 @@ int kvm_cpu_exec(CPUState *env)
 abort();
 }
 
-kvm_run_coalesced_mmio(env, run);
+kvm_flush_coalesced_mmio_buffer();
 
 ret = 0; /* exit loop */
 switch (run-exit_reason) {
diff --git a/kvm.h b/kvm.h
index 1c93ac5..59cba18 100644
--- a/kvm.h
+++ b/kvm.h
@@ -53,6 +53,7 @@ void kvm_setup_guest_memory(void *start, size_t size);
 
 int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size);
 int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size);
+void kvm_flush_coalesced_mmio_buffer(void);
 
 int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
   target_ulong len, int type);
diff --git a/vl.c b/vl.c
index 2b0b653..1f0c536 100644
--- a/vl.c
+++ b/vl.c
@@ -3193,6 +3193,7 @@ static void gui_update(void *opaque)
 DisplayState *ds = opaque;
 DisplayChangeListener *dcl = ds-listeners;
 
+qemu_flush_coalesced_mmio_buffer();
 dpy_refresh(ds);
 
 while (dcl != NULL) {
@@ -3208,6 +3209,7 @@ static void nographic_update(void *opaque)
 {
 uint64_t interval = GUI_REFRESH_INTERVAL;
 
+qemu_flush_coalesced_mmio_buffer();
 qemu_mod_timer(nographic_timer, interval + qemu_get_clock(rt_clock));
 }
 
-- 
1.5.4.5