From fd106bc530d58442daf5e9c2961b91a341833765 Mon Sep 17 00:00:00 2001
From: Alex Williamson <alex.williamson@redhat.com>
Date: Mon, 13 Feb 2012 17:46:35 +0100
Subject: [PATCH 98/99] kvm: x86: Avoid runtime allocation of xsave buffer

RH-Author: Alex Williamson <alex.williamson@redhat.com>
Message-id: <20120213174625.14789.71975.stgit@bling.home>
Patchwork-id: 37188
O-Subject: [RHEL6.3 qemu-kvm PATCH v2 2/2] kvm: x86: Avoid runtime allocation of xsave buffer
Bugzilla: 789417
RH-Acked-by: Marcelo Tosatti <mtosatti@redhat.com>
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
RH-Acked-by: Markus Armbruster <armbru@redhat.com>

Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=789417
Brew: https://brewweb.devel.redhat.com/taskinfo?taskID=4034963
Upstream: based on commit fabacc0f79ccfe9b8b34e6b9ed35ffd17415c918
RHEL Note: As kvm_xsave_buf will be NULL without the exported
           extension, use that to avoid extension ioctl without
           needing kvm_has_xsave

Keep a per-VCPU xsave buffer for kvm_put/get_xsave instead of
continuously allocating and freeing it on state sync.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 qemu-kvm-x86.c    |   16 ++++++++--------
 target-i386/cpu.h |    1 +
 2 files changed, 9 insertions(+), 8 deletions(-)

Signed-off-by: Michal Novotny <minovotn@redhat.com>
---
 qemu-kvm-x86.c    |   16 ++++++++--------
 target-i386/cpu.h |    1 +
 2 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c
index a04521c..54c9102 100644
--- a/qemu-kvm-x86.c
+++ b/qemu-kvm-x86.c
@@ -935,7 +935,7 @@ void kvm_arch_load_regs(CPUState *env)
 {
     struct kvm_regs regs;
     struct kvm_fpu fpu;
-    struct kvm_xsave* xsave;
+    struct kvm_xsave* xsave = env->kvm_xsave_buf;
     struct kvm_xcrs xcrs;
     struct kvm_sregs sregs;
     struct kvm_msr_entry msrs[100];
@@ -965,10 +965,9 @@ void kvm_arch_load_regs(CPUState *env)
 
     kvm_set_regs(env, &regs);
 
-    if (kvm_check_extension(kvm_state, KVM_CAP_XSAVE)) {
+    if (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);
@@ -994,7 +993,6 @@ void kvm_arch_load_regs(CPUState *env)
             xcrs.xcrs[0].value = env->xcr0;
             kvm_set_xcrs(env, &xcrs);
         }
-        qemu_free(xsave);
     } else {
         memset(&fpu, 0, sizeof fpu);
         fpu.fsw = env->fpus & ~(7 << 11);
@@ -1140,7 +1138,7 @@ void kvm_arch_save_regs(CPUState *env)
 {
     struct kvm_regs regs;
     struct kvm_fpu fpu;
-    struct kvm_xsave* xsave;
+    struct kvm_xsave* xsave = env->kvm_xsave_buf;
     struct kvm_xcrs xcrs;
     struct kvm_sregs sregs;
     struct kvm_msr_entry msrs[100];
@@ -1171,9 +1169,8 @@ void kvm_arch_save_regs(CPUState *env)
     env->eflags = regs.rflags;
     env->eip = regs.rip;
 
-    if (kvm_check_extension(kvm_state, KVM_CAP_XSAVE)) {
+    if (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);
@@ -1197,7 +1194,6 @@ void kvm_arch_save_regs(CPUState *env)
             if (xcrs.xcrs[0].xcr == 0)
                 env->xcr0 = xcrs.xcrs[0].value;
         }
-        qemu_free(xsave);
     } else {
         kvm_get_fpu(env, &fpu);
         env->fpstt = (fpu.fsw >> 11) & 7;
@@ -1490,6 +1486,10 @@ int kvm_arch_init_vcpu(CPUState *cenv)
 
     qemu_add_vm_change_state_handler(cpu_update_state, cenv);
 
+    if (kvm_check_extension(kvm_state, KVM_CAP_XSAVE)) {
+        cenv->kvm_xsave_buf = qemu_memalign(4096, sizeof(struct kvm_xsave));
+    }
+
     return 0;
 }
 
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 7ada730..09ba354 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -720,6 +720,7 @@ typedef struct CPUX86State {
     uint32_t sipi_vector;
     uint32_t cpuid_kvm_features;
     bool tsc_valid;
+    void *kvm_xsave_buf;
 
     /* in order to simplify APIC support, we leave this pointer to the
        user */
-- 
1.7.7.5

