<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://purl.org/rss/1.0/" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:syn="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/">
  <channel rdf:about="http://blog.gmane.org/gmane.comp.emulators.kvm.devel">
    <title>gmane.comp.emulators.kvm.devel</title>
    <link>http://blog.gmane.org/gmane.comp.emulators.kvm.devel</link>
    <description/>
    <syn:updatePeriod>hourly</syn:updatePeriod>
    <syn:updateFrequency>1</syn:updateFrequency>
    <syn:updateBase>1901-01-01T00:00+00:00</syn:updateBase>
    <items>
      <rdf:Seq>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25408"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25407"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25406"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25405"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25404"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25403"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25402"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25401"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25400"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25399"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25398"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25397"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25396"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25395"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25393"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25392"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25391"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25390"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25389"/>
        <rdf:li rdf:resource="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25388"/>
      </rdf:Seq>
    </items>
    <image rdf:resource="http://gmane.org/img/gmane-25t.png"/>
    <textinput rdf:resource=""/>
  </channel>
  <image rdf:about="http://gmane.org/img/gmane-25t.png">
    <title>Gmane</title>
    <url>http://gmane.org/img/gmane-25t.png</url>
    <link>http://gmane.org</link>
  </image>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25408">
    <title>[PATCH] Kvm: Qemu: save nvram</title>
    <link>http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25408</link>
    <description>This patch to save the nvram. It save the nvram by specify the arg of -name.And the saved file named by the arg. If do not specify the arg,it will not save the nvram

From d3e31cda03ef67efc860eaec2f93153e5535d744 Mon Sep 17 00:00:00 2001
From: Yang Zhang &lt;yang.zhang&lt; at &gt;intel.com&gt;
Date: Tue, 2 Dec 2008 10:02:00 +0800
Subject: [PATCH] Kvm: Qemu: save nvram

support to save nvram to the file

Signed-off-by: Yang Zhang &lt;yang.zhang&lt; at &gt;intel.com&gt;
---
 qemu/hw/ipf.c               |   15 ++++++-
 qemu/target-ia64/firmware.c |  107 +++++++++++++++++++++++++++++++++++++++++--
 qemu/target-ia64/firmware.h |   22 ++++++++-
 3 files changed, 135 insertions(+), 9 deletions(-)

diff --git a/qemu/hw/ipf.c b/qemu/hw/ipf.c
index 337c854..cdbd4e0 100644
--- a/qemu/hw/ipf.c
+++ b/qemu/hw/ipf.c
&lt; at &gt;&lt; at &gt; -51,6 +51,7 &lt; at &gt;&lt; at &gt;
 static fdctrl_t *floppy_controller;
 static RTCState *rtc_state;
 static PCIDevice *i440fx_state;
+uint8_t *g_fw_start;
 
 static uint32_t ipf_to_legacy_io(target_phys_addr_t addr)
 {
&lt; at &gt;&lt; at &gt; -454,9 +455,12 &lt; at &gt;&lt; at &gt; static void ipf_init1(ram_addr_t ram_size, int vga_ram_size,
         unsigned long  image_size;
         char *image = NULL;
         uint8_t *fw_image_start;
+        unsigned long nvram_addr = 0;
+        unsigned long nvram_fd = 0;
         ram_addr_t fw_offset = qemu_ram_alloc(GFW_SIZE);
         uint8_t *fw_start = phys_ram_base + fw_offset;
 
+        g_fw_start = fw_start;        
         snprintf(buf, sizeof(buf), "%s/%s", bios_dir, FW_FILENAME);
         image = read_image(buf, &amp;image_size );
         if (NULL == image || !image_size) {
&lt; at &gt;&lt; at &gt; -472,7 +476,16 &lt; at &gt;&lt; at &gt; static void ipf_init1(ram_addr_t ram_size, int vga_ram_size,
         free(image);
         flush_icache_range((unsigned long)fw_image_start,
                            (unsigned long)fw_image_start + image_size);
-        kvm_ia64_build_hob(ram_size + above_4g_mem_size, smp_cpus, fw_start);
+        if (qemu_name) {
+            nvram_addr = NVRAM_START;
+            if((nvram_fd = kvm_ia64_nvram_init()) != -1) {
+                kvm_ia64_copy_from_nvram_to_GFW(nvram_fd,g_fw_start);
+                close(nvram_fd);
+            }
+            atexit(kvm_ia64_copy_from_GFW_to_nvram);
+        }
+        kvm_ia64_build_hob(ram_size + above_4g_mem_size,smp_cpus,fw_start,
+                           nvram_addr);
     }
 
     /*Register legacy io address space, size:64M*/
diff --git a/qemu/target-ia64/firmware.c b/qemu/target-ia64/firmware.c
index bac2721..39c8361 100644
--- a/qemu/target-ia64/firmware.c
+++ b/qemu/target-ia64/firmware.c
&lt; at &gt;&lt; at &gt; -31,6 +31,8 &lt; at &gt;&lt; at &gt;
 
 #include "firmware.h"
 
+#include "qemu-common.h"
+#include "sysemu.h"
 typedef struct {
     unsigned long signature;
     unsigned int  type;
&lt; at &gt;&lt; at &gt; -85,14 +87,16 &lt; at &gt;&lt; at &gt; static int hob_init(void  *buffer ,unsigned long buf_size);
 static int add_pal_hob(void* hob_buf);
 static int add_mem_hob(void* hob_buf, unsigned long dom_mem_size);
 static int add_vcpus_hob(void* hob_buf, unsigned long nr_vcpu);
+static int add_nvram_hob(void *hob_buf, unsigned long nvram_addr);
 static int build_hob(void* hob_buf, unsigned long hob_buf_size,
-                     unsigned long dom_mem_size, unsigned long vcpus);
+                     unsigned long dom_mem_size, unsigned long vcpus
+ , unsigned long nvram_addr);
 static int load_hob(void *hob_buf,
                     unsigned long dom_mem_size, void* hob_start);
 
 int
-kvm_ia64_build_hob(unsigned long memsize,
-                   unsigned long vcpus, uint8_t* fw_start)
+kvm_ia64_build_hob(unsigned long memsize, unsigned long vcpus,
+                   uint8_t* fw_start,unsigned long nvram_addr)
 {
     char   *hob_buf;
 
&lt; at &gt;&lt; at &gt; -102,7 +106,7 &lt; at &gt;&lt; at &gt; kvm_ia64_build_hob(unsigned long memsize,
         return -1;
     }
 
-    if (build_hob(hob_buf, GFW_HOB_SIZE, memsize, vcpus) &lt; 0) {
+    if (build_hob(hob_buf, GFW_HOB_SIZE, memsize, vcpus,nvram_addr) &lt; 0) {
         free(hob_buf);
         Hob_Output("Could not build hob");
         return -1;
&lt; at &gt;&lt; at &gt; -206,7 +210,7 &lt; at &gt;&lt; at &gt; add_max_hob_entry(void* hob_buf)
 
 static int
 build_hob(void* hob_buf, unsigned long hob_buf_size,
-          unsigned long dom_mem_size, unsigned long vcpus)
+          unsigned long dom_mem_size, unsigned long vcpus,unsigned long nvram_addr)
 {
     //Init HOB List
     if (hob_init(hob_buf, hob_buf_size) &lt; 0) {
&lt; at &gt;&lt; at &gt; -229,6 +233,11 &lt; at &gt;&lt; at &gt; build_hob(void* hob_buf, unsigned long hob_buf_size,
         goto err_out;
     }
 
+    if (add_nvram_hob(hob_buf, nvram_addr) &lt; 0) {
+    Hob_Output("Add nvram hob failed, buffer too small");
+    goto err_out;
+}
+
     if (add_max_hob_entry(hob_buf) &lt; 0) {
         Hob_Output("Add max hob entry failed, buffer too small");
         goto err_out;
&lt; at &gt;&lt; at &gt; -285,6 +294,12 &lt; at &gt;&lt; at &gt; add_vcpus_hob(void* hob_buf, unsigned long vcpus)
     return hob_add(hob_buf, HOB_TYPE_NR_VCPU, &amp;vcpus, sizeof(vcpus));
 }
 
+static int
+add_nvram_hob(void *hob_buf, unsigned long nvram_addr)
+{
+    return hob_add(hob_buf, HOB_TYPE_NR_NVRAM, &amp;nvram_addr, sizeof(nvram_addr));
+}
+
 static const unsigned char config_pal_bus_get_features_data[24] = {
     0, 0, 0, 32, 0, 0, 240, 189, 0, 0, 0, 0, 0, 0,
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0
&lt; at &gt;&lt; at &gt; -581,6 +596,88 &lt; at &gt;&lt; at &gt; out_1:
     return NULL;
 }
 
+int kvm_ia64_nvram_init()
+{
+    unsigned long nvram_fd;
+    char nvram_path[PATH_MAX] = NVRAM_DIR;
+    char  name[21] ;
+
+    if(access(nvram_path, R_OK|W_OK|X_OK) == -1)
+    {
+        if(errno != ENOENT)
+        {
+            goto out;
+        }
+        if(mkdir(nvram_path, 0755) == -1)
+        {
+            goto out;
+        }
+        else
+        {
+            if(access(nvram_path, R_OK|W_OK|X_OK) == -1)
+            {    
+                errno = EACCES;
+                goto out;
+            }
+        }
+    }
+    if(strlen(qemu_name) &gt; PATH_MAX)
+    {
+        goto out;
+    }
+    strcat(nvram_path, qemu_name);
+    strcat(nvram_path, ".data");
+    if((nvram_fd = open(nvram_path,O_CREAT|O_RDWR,0644)) &lt; 0)
+    {
+        goto out;
+    }
+    if(VALIDATE_NVRAM_FD(nvram_fd) == (uint64_t)(-1))
+    {
+        close(nvram_fd);
+        goto out;
+    }
+    return nvram_fd;
+out:
+    return -1;
+}
+
+int
+kvm_ia64_copy_from_nvram_to_GFW(unsigned long nvram_fd,const uint8_t * fw_start)
+{
+    struct stat file_stat;
+    if (( fstat(nvram_fd, &amp;file_stat) &lt; 0 )||( NVRAM_SIZE  != file_stat.st_size)
+        ||(read(nvram_fd, fw_start + NVRAM_OFFSET, NVRAM_SIZE) != NVRAM_SIZE ))
+    {
+        return -1;
+    }
+    return 0;
+}
+
+int
+kvm_ia64_copy_from_GFW_to_nvram()
+{
+    unsigned long nvram_fd;
+    unsigned long * nvram_addr = (unsigned long *)(g_fw_start + NVRAM_OFFSET);
+    if((nvram_fd = kvm_ia64_nvram_init()) == -1)
+        goto out;
+    if(((struct nvram_save_addr *)nvram_addr)-&gt;signature != NVRAM_VALID_SIG)
+    {
+        close(nvram_fd);
+        goto out;
+    }
+    lseek(nvram_fd, 0, SEEK_SET);
+    if(write(nvram_fd, ((void *)(((struct nvram_save_addr *)nvram_addr)-&gt;addr + 
+                        (char *)phys_ram_base)), NVRAM_SIZE) != NVRAM_SIZE )
+    {
+        close(nvram_fd);
+        goto out;
+    }
+    close(nvram_fd);
+    return 0;
+out:
+    return -1;
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/qemu/target-ia64/firmware.h b/qemu/target-ia64/firmware.h
index 553a9f9..71aef2a 100644
--- a/qemu/target-ia64/firmware.h
+++ b/qemu/target-ia64/firmware.h
&lt; at &gt;&lt; at &gt; -34,11 +34,27 &lt; at &gt;&lt; at &gt;
 #define GFW_HOB_START           ((4UL&lt;&lt;30) - (14UL&lt;&lt;20))    // 4G - 14M
 #define GFW_HOB_SIZE            (1UL&lt;&lt;20)                 // 1M
 #define HOB_OFFSET              (GFW_HOB_START-GFW_START)
-
 #define Hob_Output(s)           fprintf(stderr, s)
 
-extern int kvm_ia64_build_hob(unsigned long memsize,
-                              unsigned long vcpus, uint8_t* fw_start);
+#define NVRAM_START  (GFW_START + NVRAM_OFFSET)
+#define NVRAM_OFFSET (10 * (1UL &lt;&lt; 20))
+#define NVRAM_SIZE    (64 * (1UL &lt;&lt; 10))
+#define NVRAM_VALID_SIG  0x4650494e45584948 /* "HIXENIPF" */
+#define NVRAM_DIR "/usr/local/share/qemu/nvram/"
+#define VALIDATE_NVRAM_FD(x) ((1UL&lt;&lt;(sizeof(x)*8 - 1)) | x)
+#define IS_VALID_NVRAM_FD(x) ((uint64_t)x &gt;&gt; (sizeof(x)*8 - 1))
+
+struct nvram_save_addr {
+    unsigned long addr;
+    unsigned long signature;
+};
+
+extern uint8_t *g_fw_start; 
+extern int kvm_ia64_build_hob(unsigned long memsize, unsigned long vcpus,
+                       uint8_t* fw_start,unsigned long nvram_addr);
 extern char *read_image(const char *filename, unsigned long *size);
 
+extern int kvm_ia64_nvram_init();
+extern int kvm_ia64_copy_from_nvram_to_GFW(unsigned long nvram_fd,const uint8_t * fw_start);
+extern int kvm_ia64_copy_from_GFW_to_nvram();
 #endif //__FIRM_WARE_
</description>
    <dc:creator>Zhang, Yang</dc:creator>
    <dc:date>2008-12-02T02:25:49</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25407">
    <title>RE: [PATCH] KVM: Qemu: push_nmi should be only used by I386 Arch.</title>
    <link>http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25407</link>
    <description>Oops, seems we introduced the issue together. 

Acked-by Xiantao Zhang &lt;xiantao.zhang&lt; at &gt;intel.com&gt;

-----Original Message-----
From: jan.kiszka&lt; at &gt;web.de [mailto:jan.kiszka&lt; at &gt;web.de] 
Sent: Tuesday, December 02, 2008 7:03 AM
To: Hollis Blanchard
Cc: Avi Kivity; Zhang, Xiantao; kvm&lt; at &gt;vger.kernel.org; kvm-ia64&lt; at &gt;vger.kernel.org
Subject: Re: [PATCH] KVM: Qemu: push_nmi should be only used by I386 Arch.

Hollis Blanchard wrote:

Ouch - I'm sorry.


Here is a patch that reverts change and fixes the root of the issue.

-----------

Subject: Fix non-x86 NMI hooks

My previous x86-only change to the NMI push hook broke PPC and IA64.
This is a proper fix plus a cleanup of the #ifdef-based approach to
solve the breakage.

Signed-off-by: Jan Kiszka &lt;jan.kiszka&lt; at &gt;siemens.com&gt;
---

 qemu/qemu-kvm-ia64.c    |    3 +--
 qemu/qemu-kvm-powerpc.c |    3 +--
 qemu/qemu-kvm.c         |    4 ----
 3 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/qemu/qemu-kvm-ia64.c b/qemu/qemu-kvm-ia64.c
index 8380f39..a6b17af 100644
--- a/qemu/qemu-kvm-ia64.c
+++ b/qemu/qemu-kvm-ia64.c
&lt; at &gt;&lt; at &gt; -57,9 +57,8 &lt; at &gt;&lt; at &gt; int kvm_arch_try_push_interrupts(void *opaque)
     return 1;
 }
 
-int kvm_arch_try_push_nmi(void *opaque)
+void kvm_arch_push_nmi(void *opaque)
 {
-    return 1;
 }
 
 void kvm_arch_update_regs_for_sipi(CPUState *env)
diff --git a/qemu/qemu-kvm-powerpc.c b/qemu/qemu-kvm-powerpc.c
index 19fde40..fa534ed 100644
--- a/qemu/qemu-kvm-powerpc.c
+++ b/qemu/qemu-kvm-powerpc.c
&lt; at &gt;&lt; at &gt; -188,12 +188,11 &lt; at &gt;&lt; at &gt; int kvm_arch_try_push_interrupts(void *opaque)
     return 0;
 }
 
-int kvm_arch_try_push_nmi(void *opaque)
+void kvm_arch_push_nmi(void *opaque)
 {
 /* no nmi irq, so discard that call for now and return success.
  * This might later get mapped to something on powerpc too if we want
  *  to support the nmi monitor command somwhow */
-return 0;
 }
 
 void kvm_arch_update_regs_for_sipi(CPUState *env)
diff --git a/qemu/qemu-kvm.c b/qemu/qemu-kvm.c
index b6c8288..cf0e85d 100644
--- a/qemu/qemu-kvm.c
+++ b/qemu/qemu-kvm.c
&lt; at &gt;&lt; at &gt; -154,12 +154,10 &lt; at &gt;&lt; at &gt; static int try_push_interrupts(void *opaque)
     return kvm_arch_try_push_interrupts(opaque);
 }
 
-#ifdef TARGET_I386
 static void push_nmi(void *opaque)
 {
     kvm_arch_push_nmi(opaque);
 }
-#endif
 
 static void post_kvm_run(void *opaque, void *data)
 {
&lt; at &gt;&lt; at &gt; -744,9 +742,7 &lt; at &gt;&lt; at &gt; static struct kvm_callbacks qemu_kvm_ops = {
     .shutdown = kvm_shutdown,
     .io_window = kvm_io_window,
     .try_push_interrupts = try_push_interrupts,
-#ifdef TARGET_I386
     .push_nmi = push_nmi,
-#endif
     .post_kvm_run = post_kvm_run,
     .pre_kvm_run = pre_kvm_run,
 #ifdef TARGET_I386

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo&lt; at &gt;vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

</description>
    <dc:creator>Zhang, Xiantao</dc:creator>
    <dc:date>2008-12-02T02:01:41</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25406">
    <title>Re: [Qemu-devel] qemu-img commit -- is there a limit on file sizes?</title>
    <link>http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25406</link>
    <description>

On Mon, 1 Dec 2008, Avi Kivity wrote:


FWIW, I must apologize for giving you incorrect data.  I'm seeing problems
now that have nothing to do with the size of the commit, and I'm beginning
to suspect that the commit step has nothing to do with the problem.  I'll
summarize my evidence because it seems potentially very important:

I installed WinXP on qcow2, which went perfectly.  I rebooted multiple times
with no problems and changed settings for my desktop and taskbar, rebooted
again with no problems.

Now, I make a new, fresh [what's the opposite of a backing file?] like this:
$qemu-img create -f qcow2 -b kvmXP kvmXP.delta

All I do is boot XP again like this:
$qemu-system-x86_64 -m 1000 kvmXP.delta

My shock is that one of the taskbar settings I changed has disappeared!
I can boot the original kvmXP qcow2 image and verify that my changes are
still there in the original, but not when I boot kvmXP.delta.

In case someone wants to try to reproduce it, the specific change I made
to the task bar is to display the animated network activity icon in the
system tray.  That icon never appears when I boot from kvmXP.delta.

In other words, from the instant I boot kvmXP.delta, the image of XP that
gets loaded into memory is not an accurate reflection of what's in the
backing file.  If that's true, then it's not surprising that the commit
step causes trouble.

Does my reasoning seem reasonable? :o)




--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo&lt; at &gt;vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

</description>
    <dc:creator>walt</dc:creator>
    <dc:date>2008-12-02T00:47:55</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25405">
    <title>[patch 2/4] KVM: MMU: collapse remote TLB flushes on root sync</title>
    <link>http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25405</link>
    <description>Collapse remote TLB flushes on root sync.

kernbench is 2.7% faster on 4-way guest. Improvements have been seen
with other loads such as AIM7.

Signed-off-by: Marcelo Tosatti &lt;mtosatti&lt; at &gt;redhat.com&gt;

Index: kvm/arch/x86/kvm/mmu.c
===================================================================
--- kvm.orig/arch/x86/kvm/mmu.c
+++ kvm/arch/x86/kvm/mmu.c
&lt; at &gt;&lt; at &gt; -621,7 +621,7 &lt; at &gt;&lt; at &gt; static u64 *rmap_next(struct kvm *kvm, u
 return NULL;
 }
 
-static void rmap_write_protect(struct kvm *kvm, u64 gfn)
+static int rmap_write_protect(struct kvm *kvm, u64 gfn)
 {
 unsigned long *rmapp;
 u64 *spte;
&lt; at &gt;&lt; at &gt; -667,8 +667,7 &lt; at &gt;&lt; at &gt; static void rmap_write_protect(struct kv
 spte = rmap_next(kvm, rmapp, spte);
 }
 
-if (write_protected)
-kvm_flush_remote_tlbs(kvm);
+return write_protected;
 }
 
 static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp)
&lt; at &gt;&lt; at &gt; -1083,7 +1082,8 &lt; at &gt;&lt; at &gt; static int kvm_sync_page(struct kvm_vcpu
 return 1;
 }
 
-rmap_write_protect(vcpu-&gt;kvm, sp-&gt;gfn);
+if (rmap_write_protect(vcpu-&gt;kvm, sp-&gt;gfn))
+kvm_flush_remote_tlbs(vcpu-&gt;kvm);
 kvm_unlink_unsync_page(vcpu-&gt;kvm, sp);
 if (vcpu-&gt;arch.mmu.sync_page(vcpu, sp)) {
 kvm_mmu_zap_page(vcpu-&gt;kvm, sp);
&lt; at &gt;&lt; at &gt; -1162,6 +1162,14 &lt; at &gt;&lt; at &gt; static void mmu_sync_children(struct kvm
 
 kvm_mmu_pages_init(parent, &amp;parents, &amp;pages);
 while (mmu_unsync_walk(parent, &amp;pages)) {
+int protected = 0;
+
+for_each_sp(pages, sp, parents, i)
+protected |= rmap_write_protect(vcpu-&gt;kvm, sp-&gt;gfn);
+
+if (protected)
+kvm_flush_remote_tlbs(vcpu-&gt;kvm);
+
 for_each_sp(pages, sp, parents, i) {
 kvm_sync_page(vcpu, sp);
 mmu_pages_clear_parents(&amp;parents);
&lt; at &gt;&lt; at &gt; -1226,7 +1234,8 &lt; at &gt;&lt; at &gt; static struct kvm_mmu_page *kvm_mmu_get_
 sp-&gt;role = role;
 hlist_add_head(&amp;sp-&gt;hash_link, bucket);
 if (!metaphysical) {
-rmap_write_protect(vcpu-&gt;kvm, gfn);
+if (rmap_write_protect(vcpu-&gt;kvm, gfn))
+kvm_flush_remote_tlbs(vcpu-&gt;kvm);
 account_shadowed(vcpu-&gt;kvm, gfn);
 }
 if (shadow_trap_nonpresent_pte != shadow_notrap_nonpresent_pte)

</description>
    <dc:creator>Marcelo Tosatti</dc:creator>
    <dc:date>2008-12-02T00:32:03</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25404">
    <title>[patch 0/4] oos shadow optimizations v2</title>
    <link>http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25404</link>
    <description>Addressing comments from previous version.

</description>
    <dc:creator>Marcelo Tosatti</dc:creator>
    <dc:date>2008-12-02T00:32:01</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25403">
    <title>[patch 4/4] KVM: MMU: prepopulate the shadow on invlpg</title>
    <link>http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25403</link>
    <description>If the guest executes invlpg, peek into the pagetable and attempt to
prepopulate the shadow entry.

Also stop dirty fault updates from interfering with the fork detector.

2% improvement on RHEL3/AIM7.

Signed-off-by: Marcelo Tosatti &lt;mtosatti&lt; at &gt;redhat.com&gt;

Index: kvm/arch/x86/kvm/mmu.c
===================================================================
--- kvm.orig/arch/x86/kvm/mmu.c
+++ kvm/arch/x86/kvm/mmu.c
&lt; at &gt;&lt; at &gt; -2441,7 +2441,8 &lt; at &gt;&lt; at &gt; static void kvm_mmu_access_page(struct k
 }
 
 void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
-       const u8 *new, int bytes)
+       const u8 *new, int bytes,
+       bool guest_initiated)
 {
 gfn_t gfn = gpa &gt;&gt; PAGE_SHIFT;
 struct kvm_mmu_page *sp;
&lt; at &gt;&lt; at &gt; -2467,15 +2468,17 &lt; at &gt;&lt; at &gt; void kvm_mmu_pte_write(struct kvm_vcpu *
 kvm_mmu_free_some_pages(vcpu);
 ++vcpu-&gt;kvm-&gt;stat.mmu_pte_write;
 kvm_mmu_audit(vcpu, "pre pte write");
-if (gfn == vcpu-&gt;arch.last_pt_write_gfn
-    &amp;&amp; !last_updated_pte_accessed(vcpu)) {
-++vcpu-&gt;arch.last_pt_write_count;
-if (vcpu-&gt;arch.last_pt_write_count &gt;= 3)
-flooded = 1;
-} else {
-vcpu-&gt;arch.last_pt_write_gfn = gfn;
-vcpu-&gt;arch.last_pt_write_count = 1;
-vcpu-&gt;arch.last_pte_updated = NULL;
+if (guest_initiated) {
+if (gfn == vcpu-&gt;arch.last_pt_write_gfn
+    &amp;&amp; !last_updated_pte_accessed(vcpu)) {
+++vcpu-&gt;arch.last_pt_write_count;
+if (vcpu-&gt;arch.last_pt_write_count &gt;= 3)
+flooded = 1;
+} else {
+vcpu-&gt;arch.last_pt_write_gfn = gfn;
+vcpu-&gt;arch.last_pt_write_count = 1;
+vcpu-&gt;arch.last_pte_updated = NULL;
+}
 }
 index = kvm_page_table_hashfn(gfn);
 bucket = &amp;vcpu-&gt;kvm-&gt;arch.mmu_page_hash[index];
&lt; at &gt;&lt; at &gt; -2615,9 +2618,7 &lt; at &gt;&lt; at &gt; EXPORT_SYMBOL_GPL(kvm_mmu_page_fault);
 
 void kvm_mmu_invlpg(struct kvm_vcpu *vcpu, gva_t gva)
 {
-spin_lock(&amp;vcpu-&gt;kvm-&gt;mmu_lock);
 vcpu-&gt;arch.mmu.invlpg(vcpu, gva);
-spin_unlock(&amp;vcpu-&gt;kvm-&gt;mmu_lock);
 kvm_mmu_flush_tlb(vcpu);
 ++vcpu-&gt;stat.invlpg;
 }
Index: kvm/arch/x86/kvm/paging_tmpl.h
===================================================================
--- kvm.orig/arch/x86/kvm/paging_tmpl.h
+++ kvm/arch/x86/kvm/paging_tmpl.h
&lt; at &gt;&lt; at &gt; -82,6 +82,7 &lt; at &gt;&lt; at &gt; struct shadow_walker {
 int *ptwrite;
 pfn_t pfn;
 u64 *sptep;
+gpa_t pte_gpa;
 };
 
 static gfn_t gpte_to_gfn(pt_element_t gpte)
&lt; at &gt;&lt; at &gt; -222,7 +223,7 &lt; at &gt;&lt; at &gt; walk:
 if (ret)
 goto walk;
 pte |= PT_DIRTY_MASK;
-kvm_mmu_pte_write(vcpu, pte_gpa, (u8 *)&amp;pte, sizeof(pte));
+kvm_mmu_pte_write(vcpu, pte_gpa, (u8 *)&amp;pte, sizeof(pte), 0);
 walker-&gt;ptes[walker-&gt;level - 1] = pte;
 }
 
&lt; at &gt;&lt; at &gt; -468,8 +469,15 &lt; at &gt;&lt; at &gt; static int FNAME(shadow_invlpg_entry)(st
       struct kvm_vcpu *vcpu, u64 addr,
       u64 *sptep, int level)
 {
+struct shadow_walker *sw =
+container_of(_sw, struct shadow_walker, walker);
 
 if (level == PT_PAGE_TABLE_LEVEL) {
+struct kvm_mmu_page *sp = page_header(__pa(sptep));
+
+sw-&gt;pte_gpa = (sp-&gt;gfn &lt;&lt; PAGE_SHIFT);
+sw-&gt;pte_gpa += (sptep - sp-&gt;spt) * sizeof(pt_element_t);
+
 if (is_shadow_present_pte(*sptep))
 rmap_remove(vcpu-&gt;kvm, sptep);
 set_shadow_pte(sptep, shadow_trap_nonpresent_pte);
&lt; at &gt;&lt; at &gt; -482,11 +490,26 &lt; at &gt;&lt; at &gt; static int FNAME(shadow_invlpg_entry)(st
 
 static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva)
 {
+pt_element_t gpte;
 struct shadow_walker walker = {
 .walker = { .entry = FNAME(shadow_invlpg_entry), },
+.pte_gpa = -1,
 };
 
+spin_lock(&amp;vcpu-&gt;kvm-&gt;mmu_lock);
 walk_shadow(&amp;walker.walker, vcpu, gva);
+spin_unlock(&amp;vcpu-&gt;kvm-&gt;mmu_lock);
+if (walker.pte_gpa == -1)
+return;
+if (kvm_read_guest_atomic(vcpu-&gt;kvm, walker.pte_gpa, &amp;gpte,
+  sizeof(pt_element_t)))
+return;
+if (is_present_pte(gpte) &amp;&amp; (gpte &amp; PT_ACCESSED_MASK)) {
+if (mmu_topup_memory_caches(vcpu))
+return;
+kvm_mmu_pte_write(vcpu, walker.pte_gpa, (const u8 *)&amp;gpte,
+  sizeof(pt_element_t), 0);
+}
 }
 
 static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr)
Index: kvm/arch/x86/kvm/x86.c
===================================================================
--- kvm.orig/arch/x86/kvm/x86.c
+++ kvm/arch/x86/kvm/x86.c
&lt; at &gt;&lt; at &gt; -2046,7 +2046,7 &lt; at &gt;&lt; at &gt; int emulator_write_phys(struct kvm_vcpu 
 ret = kvm_write_guest(vcpu-&gt;kvm, gpa, val, bytes);
 if (ret &lt; 0)
 return 0;
-kvm_mmu_pte_write(vcpu, gpa, val, bytes);
+kvm_mmu_pte_write(vcpu, gpa, val, bytes, 1);
 return 1;
 }
 
Index: kvm/arch/x86/include/asm/kvm_host.h
===================================================================
--- kvm.orig/arch/x86/include/asm/kvm_host.h
+++ kvm/arch/x86/include/asm/kvm_host.h
&lt; at &gt;&lt; at &gt; -602,7 +602,8 &lt; at &gt;&lt; at &gt; unsigned long segment_base(u16 selector)
 
 void kvm_mmu_flush_tlb(struct kvm_vcpu *vcpu);
 void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
-       const u8 *new, int bytes);
+       const u8 *new, int bytes,
+       bool guest_initiated);
 int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva);
 void __kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu);
 int kvm_mmu_load(struct kvm_vcpu *vcpu);

</description>
    <dc:creator>Marcelo Tosatti</dc:creator>
    <dc:date>2008-12-02T00:32:05</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25402">
    <title>[patch 1/4] KVM: MMU: use page array in unsync walk</title>
    <link>http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25402</link>
    <description>Instead of invoking the handler directly collect pages into 
an array so the caller can work with it.

Simplifies TLB flush collapsing.

Signed-off-by: Marcelo Tosatti &lt;mtosatti&lt; at &gt;redhat.com&gt;

Index: kvm/arch/x86/kvm/mmu.c
===================================================================
--- kvm.orig/arch/x86/kvm/mmu.c
+++ kvm/arch/x86/kvm/mmu.c
&lt; at &gt;&lt; at &gt; -908,8 +908,9 &lt; at &gt;&lt; at &gt; static void kvm_mmu_update_unsync_bitmap
 struct kvm_mmu_page *sp = page_header(__pa(spte));
 
 index = spte - sp-&gt;spt;
-__set_bit(index, sp-&gt;unsync_child_bitmap);
-sp-&gt;unsync_children = 1;
+if (!__test_and_set_bit(index, sp-&gt;unsync_child_bitmap))
+sp-&gt;unsync_children++;
+WARN_ON(!sp-&gt;unsync_children);
 }
 
 static void kvm_mmu_update_parents_unsync(struct kvm_mmu_page *sp)
&lt; at &gt;&lt; at &gt; -936,7 +937,6 &lt; at &gt;&lt; at &gt; static void kvm_mmu_update_parents_unsyn
 
 static int unsync_walk_fn(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
 {
-sp-&gt;unsync_children = 1;
 kvm_mmu_update_parents_unsync(sp);
 return 1;
 }
&lt; at &gt;&lt; at &gt; -967,18 +967,41 &lt; at &gt;&lt; at &gt; static void nonpaging_invlpg(struct kvm_
 {
 }
 
+#define KVM_PAGE_ARRAY_NR 16
+
+struct kvm_mmu_pages {
+struct mmu_page_and_offset {
+struct kvm_mmu_page *sp;
+unsigned int idx;
+} page[KVM_PAGE_ARRAY_NR];
+unsigned int nr;
+};
+
 #define for_each_unsync_children(bitmap, idx)\
 for (idx = find_first_bit(bitmap, 512);\
      idx &lt; 512;\
      idx = find_next_bit(bitmap, 512, idx+1))
 
-static int mmu_unsync_walk(struct kvm_mmu_page *sp,
-   struct kvm_unsync_walk *walker)
+int mmu_pages_add(struct kvm_mmu_pages *pvec, struct kvm_mmu_page *sp,
+   int idx)
 {
-int i, ret;
+int i;
 
-if (!sp-&gt;unsync_children)
-return 0;
+if (sp-&gt;unsync)
+for (i=0; i &lt; pvec-&gt;nr; i++)
+if (pvec-&gt;page[i].sp == sp)
+return 0;
+
+pvec-&gt;page[pvec-&gt;nr].sp = sp;
+pvec-&gt;page[pvec-&gt;nr].idx = idx;
+pvec-&gt;nr++;
+return (pvec-&gt;nr == KVM_PAGE_ARRAY_NR);
+}
+
+static int __mmu_unsync_walk(struct kvm_mmu_page *sp,
+   struct kvm_mmu_pages *pvec)
+{
+int i, ret, nr_unsync_leaf = 0;
 
 for_each_unsync_children(sp-&gt;unsync_child_bitmap, i) {
 u64 ent = sp-&gt;spt[i];
&lt; at &gt;&lt; at &gt; -988,17 +1011,22 &lt; at &gt;&lt; at &gt; static int mmu_unsync_walk(struct kvm_mm
 child = page_header(ent &amp; PT64_BASE_ADDR_MASK);
 
 if (child-&gt;unsync_children) {
-ret = mmu_unsync_walk(child, walker);
-if (ret)
+if (mmu_pages_add(pvec, child, i))
+return -ENOSPC;
+
+ret = __mmu_unsync_walk(child, pvec);
+if (!ret)
+__clear_bit(i, sp-&gt;unsync_child_bitmap);
+else if (ret &gt; 0)
+nr_unsync_leaf += ret;
+else
 return ret;
-__clear_bit(i, sp-&gt;unsync_child_bitmap);
 }
 
 if (child-&gt;unsync) {
-ret = walker-&gt;entry(child, walker);
-__clear_bit(i, sp-&gt;unsync_child_bitmap);
-if (ret)
-return ret;
+nr_unsync_leaf++;
+if (mmu_pages_add(pvec, child, i))
+return -ENOSPC;
 }
 }
 }
&lt; at &gt;&lt; at &gt; -1006,7 +1034,17 &lt; at &gt;&lt; at &gt; static int mmu_unsync_walk(struct kvm_mm
 if (find_first_bit(sp-&gt;unsync_child_bitmap, 512) == 512)
 sp-&gt;unsync_children = 0;
 
-return 0;
+return nr_unsync_leaf;
+}
+
+static int mmu_unsync_walk(struct kvm_mmu_page *sp,
+   struct kvm_mmu_pages *pvec)
+{
+if (!sp-&gt;unsync_children)
+return 0;
+
+mmu_pages_add(pvec, sp, 0);
+return __mmu_unsync_walk(sp, pvec);
 }
 
 static struct kvm_mmu_page *kvm_mmu_lookup_page(struct kvm *kvm, gfn_t gfn)
&lt; at &gt;&lt; at &gt; -1056,30 +1094,81 &lt; at &gt;&lt; at &gt; static int kvm_sync_page(struct kvm_vcpu
 return 0;
 }
 
-struct sync_walker {
-struct kvm_vcpu *vcpu;
-struct kvm_unsync_walk walker;
+struct mmu_page_path {
+struct kvm_mmu_page *parent[PT64_ROOT_LEVEL-1];
+unsigned int idx[PT64_ROOT_LEVEL-1];
 };
 
-static int mmu_sync_fn(struct kvm_mmu_page *sp, struct kvm_unsync_walk *walk)
+#define for_each_sp(pvec, sp, parents, i)\
+for (i = mmu_pages_next(&amp;pvec, &amp;parents, -1),\
+sp = pvec.page[i].sp;\
+i &lt; pvec.nr &amp;&amp; ({ sp = pvec.page[i].sp; 1;});\
+i = mmu_pages_next(&amp;pvec, &amp;parents, i))
+
+int mmu_pages_next(struct kvm_mmu_pages *pvec, struct mmu_page_path *parents,
+   int i)
 {
-struct sync_walker *sync_walk = container_of(walk, struct sync_walker,
-     walker);
-struct kvm_vcpu *vcpu = sync_walk-&gt;vcpu;
+int n;
+
+for (n = i+1; n &lt; pvec-&gt;nr; n++) {
+struct kvm_mmu_page *sp = pvec-&gt;page[n].sp;
+
+if (sp-&gt;role.level == PT_PAGE_TABLE_LEVEL) {
+parents-&gt;idx[0] = pvec-&gt;page[n].idx;
+return n;
+}
 
-kvm_sync_page(vcpu, sp);
-return (need_resched() || spin_needbreak(&amp;vcpu-&gt;kvm-&gt;mmu_lock));
+parents-&gt;parent[sp-&gt;role.level-2] = sp;
+parents-&gt;idx[sp-&gt;role.level-1] = pvec-&gt;page[n].idx;
+}
+
+return n;
 }
 
-static void mmu_sync_children(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
+void mmu_pages_clear_parents(struct mmu_page_path *parents)
 {
-struct sync_walker walker = {
-.walker = { .entry = mmu_sync_fn, },
-.vcpu = vcpu,
-};
+struct kvm_mmu_page *sp;
+unsigned int level = 0;
+
+do {
+unsigned int idx = parents-&gt;idx[level];
+
+sp = parents-&gt;parent[level];
+if (!sp)
+return;
 
-while (mmu_unsync_walk(sp, &amp;walker.walker))
+--sp-&gt;unsync_children;
+WARN_ON((int)sp-&gt;unsync_children &lt; 0);
+__clear_bit(idx, sp-&gt;unsync_child_bitmap);
+level++;
+} while (level &lt; PT64_ROOT_LEVEL-1 &amp;&amp; !sp-&gt;unsync_children);
+}
+
+static void kvm_mmu_pages_init(struct kvm_mmu_page *parent,
+       struct mmu_page_path *parents,
+       struct kvm_mmu_pages *pvec)
+{
+parents-&gt;parent[parent-&gt;role.level-1] = NULL;
+pvec-&gt;nr = 0;
+}
+
+static void mmu_sync_children(struct kvm_vcpu *vcpu,
+      struct kvm_mmu_page *parent)
+{
+int i;
+struct kvm_mmu_page *sp;
+struct mmu_page_path parents;
+struct kvm_mmu_pages pages;
+
+kvm_mmu_pages_init(parent, &amp;parents, &amp;pages);
+while (mmu_unsync_walk(parent, &amp;pages)) {
+for_each_sp(pages, sp, parents, i) {
+kvm_sync_page(vcpu, sp);
+mmu_pages_clear_parents(&amp;parents);
+}
 cond_resched_lock(&amp;vcpu-&gt;kvm-&gt;mmu_lock);
+kvm_mmu_pages_init(parent, &amp;parents, &amp;pages);
+}
 }
 
 static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
&lt; at &gt;&lt; at &gt; -1245,33 +1334,29 &lt; at &gt;&lt; at &gt; static void kvm_mmu_unlink_parents(struc
 }
 }
 
-struct zap_walker {
-struct kvm_unsync_walk walker;
-struct kvm *kvm;
-int zapped;
-};
-
-static int mmu_zap_fn(struct kvm_mmu_page *sp, struct kvm_unsync_walk *walk)
-{
-struct zap_walker *zap_walk = container_of(walk, struct zap_walker,
-     walker);
-kvm_mmu_zap_page(zap_walk-&gt;kvm, sp);
-zap_walk-&gt;zapped = 1;
-return 0;
-}
-
-static int mmu_zap_unsync_children(struct kvm *kvm, struct kvm_mmu_page *sp)
+static int mmu_zap_unsync_children(struct kvm *kvm,
+   struct kvm_mmu_page *parent)
 {
-struct zap_walker walker = {
-.walker = { .entry = mmu_zap_fn, },
-.kvm = kvm,
-.zapped = 0,
-};
+int i, zapped = 0;
+struct mmu_page_path parents;
+struct kvm_mmu_pages pages;
 
-if (sp-&gt;role.level == PT_PAGE_TABLE_LEVEL)
+if (parent-&gt;role.level == PT_PAGE_TABLE_LEVEL)
 return 0;
-mmu_unsync_walk(sp, &amp;walker.walker);
-return walker.zapped;
+
+kvm_mmu_pages_init(parent, &amp;parents, &amp;pages);
+while (mmu_unsync_walk(parent, &amp;pages)) {
+struct kvm_mmu_page *sp;
+
+for_each_sp(pages, sp, parents, i) {
+kvm_mmu_zap_page(kvm, sp);
+mmu_pages_clear_parents(&amp;parents);
+}
+zapped += pages.nr;
+kvm_mmu_pages_init(parent, &amp;parents, &amp;pages);
+}
+
+return zapped;
 }
 
 static int kvm_mmu_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp)
Index: kvm/arch/x86/include/asm/kvm_host.h
===================================================================
--- kvm.orig/arch/x86/include/asm/kvm_host.h
+++ kvm/arch/x86/include/asm/kvm_host.h
&lt; at &gt;&lt; at &gt; -200,7 +200,7 &lt; at &gt;&lt; at &gt; struct kvm_mmu_page {
 int multimapped;         /* More than one parent_pte? */
 int root_count;          /* Currently serving as active root */
 bool unsync;
-bool unsync_children;
+unsigned int unsync_children;
 union {
 u64 *parent_pte;               /* !multimapped */
 struct hlist_head parent_ptes; /* multimapped, kvm_pte_chain */

</description>
    <dc:creator>Marcelo Tosatti</dc:creator>
    <dc:date>2008-12-02T00:32:02</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25401">
    <title>[patch 3/4] KVM: MMU: skip global pgtables on sync due to cr3 switch</title>
    <link>http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25401</link>
    <description>Skip syncing global pages on cr3 switch (but not on cr4/cr0). This is
important for Linux 32-bit guests with PAE, where the kmap page is
marked as global.

Signed-off-by: Marcelo Tosatti &lt;mtosatti&lt; at &gt;redhat.com&gt;

Index: kvm/arch/x86/include/asm/kvm_host.h
===================================================================
--- kvm.orig/arch/x86/include/asm/kvm_host.h
+++ kvm/arch/x86/include/asm/kvm_host.h
&lt; at &gt;&lt; at &gt; -182,6 +182,8 &lt; at &gt;&lt; at &gt; struct kvm_mmu_page {
 struct list_head link;
 struct hlist_node hash_link;
 
+struct list_head oos_link;
+
 /*
  * The following two entries are used to key the shadow page in the
  * hash table.
&lt; at &gt;&lt; at &gt; -200,6 +202,7 &lt; at &gt;&lt; at &gt; struct kvm_mmu_page {
 int multimapped;         /* More than one parent_pte? */
 int root_count;          /* Currently serving as active root */
 bool unsync;
+bool global;
 unsigned int unsync_children;
 union {
 u64 *parent_pte;               /* !multimapped */
&lt; at &gt;&lt; at &gt; -356,6 +359,7 &lt; at &gt;&lt; at &gt; struct kvm_arch{
  */
 struct list_head active_mmu_pages;
 struct list_head assigned_dev_head;
+struct list_head oos_global_pages;
 struct dmar_domain *intel_iommu_domain;
 struct kvm_pic *vpic;
 struct kvm_ioapic *vioapic;
&lt; at &gt;&lt; at &gt; -385,6 +389,7 &lt; at &gt;&lt; at &gt; struct kvm_vm_stat {
 u32 mmu_recycled;
 u32 mmu_cache_miss;
 u32 mmu_unsync;
+u32 mmu_unsync_global;
 u32 remote_tlb_flush;
 u32 lpages;
 };
&lt; at &gt;&lt; at &gt; -603,6 +608,7 &lt; at &gt;&lt; at &gt; void __kvm_mmu_free_some_pages(struct kv
 int kvm_mmu_load(struct kvm_vcpu *vcpu);
 void kvm_mmu_unload(struct kvm_vcpu *vcpu);
 void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu);
+void kvm_mmu_sync_global(struct kvm_vcpu *vcpu);
 
 int kvm_emulate_hypercall(struct kvm_vcpu *vcpu);
 
Index: kvm/arch/x86/kvm/mmu.c
===================================================================
--- kvm.orig/arch/x86/kvm/mmu.c
+++ kvm/arch/x86/kvm/mmu.c
&lt; at &gt;&lt; at &gt; -793,9 +793,11 &lt; at &gt;&lt; at &gt; static struct kvm_mmu_page *kvm_mmu_allo
 sp-&gt;gfns = mmu_memory_cache_alloc(&amp;vcpu-&gt;arch.mmu_page_cache, PAGE_SIZE);
 set_page_private(virt_to_page(sp-&gt;spt), (unsigned long)sp);
 list_add(&amp;sp-&gt;link, &amp;vcpu-&gt;kvm-&gt;arch.active_mmu_pages);
+INIT_LIST_HEAD(&amp;sp-&gt;oos_link);
 ASSERT(is_empty_shadow_page(sp-&gt;spt));
 bitmap_zero(sp-&gt;slot_bitmap, KVM_MEMORY_SLOTS + KVM_PRIVATE_MEM_SLOTS);
 sp-&gt;multimapped = 0;
+sp-&gt;global = 1;
 sp-&gt;parent_pte = parent_pte;
 --vcpu-&gt;kvm-&gt;arch.n_free_mmu_pages;
 return sp;
&lt; at &gt;&lt; at &gt; -1066,10 +1068,18 &lt; at &gt;&lt; at &gt; static struct kvm_mmu_page *kvm_mmu_look
 return NULL;
 }
 
+static void kvm_unlink_unsync_global(struct kvm *kvm, struct kvm_mmu_page *sp)
+{
+list_del(&amp;sp-&gt;oos_link);
+--kvm-&gt;stat.mmu_unsync_global;
+}
+
 static void kvm_unlink_unsync_page(struct kvm *kvm, struct kvm_mmu_page *sp)
 {
 WARN_ON(!sp-&gt;unsync);
 sp-&gt;unsync = 0;
+if (sp-&gt;global)
+kvm_unlink_unsync_global(kvm, sp);
 --kvm-&gt;stat.mmu_unsync;
 }
 
&lt; at &gt;&lt; at &gt; -1615,9 +1625,15 &lt; at &gt;&lt; at &gt; static int kvm_unsync_page(struct kvm_vc
 if (s-&gt;role.word != sp-&gt;role.word)
 return 1;
 }
-kvm_mmu_mark_parents_unsync(vcpu, sp);
 ++vcpu-&gt;kvm-&gt;stat.mmu_unsync;
 sp-&gt;unsync = 1;
+
+if (sp-&gt;global) {
+list_add(&amp;sp-&gt;oos_link, &amp;vcpu-&gt;kvm-&gt;arch.oos_global_pages);
+++vcpu-&gt;kvm-&gt;stat.mmu_unsync_global;
+} else
+kvm_mmu_mark_parents_unsync(vcpu, sp);
+
 mmu_convert_notrap(sp);
 return 0;
 }
&lt; at &gt;&lt; at &gt; -1643,12 +1659,21 &lt; at &gt;&lt; at &gt; static int mmu_need_write_protect(struct
 static int set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
     unsigned pte_access, int user_fault,
     int write_fault, int dirty, int largepage,
-    gfn_t gfn, pfn_t pfn, bool speculative,
+    int global, gfn_t gfn, pfn_t pfn, bool speculative,
     bool can_unsync)
 {
 u64 spte;
 int ret = 0;
 u64 mt_mask = shadow_mt_mask;
+struct kvm_mmu_page *sp = page_header(__pa(shadow_pte));
+
+if (!global &amp;&amp; sp-&gt;global) {
+sp-&gt;global = 0;
+if (sp-&gt;unsync) {
+kvm_unlink_unsync_global(vcpu-&gt;kvm, sp);
+kvm_mmu_mark_parents_unsync(vcpu, sp);
+}
+}
 
 /*
  * We don't set the accessed bit, since we sometimes want to see
&lt; at &gt;&lt; at &gt; -1717,8 +1742,8 &lt; at &gt;&lt; at &gt; set_pte:
 static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
  unsigned pt_access, unsigned pte_access,
  int user_fault, int write_fault, int dirty,
- int *ptwrite, int largepage, gfn_t gfn,
- pfn_t pfn, bool speculative)
+ int *ptwrite, int largepage, int global,
+ gfn_t gfn, pfn_t pfn, bool speculative)
 {
 int was_rmapped = 0;
 int was_writeble = is_writeble_pte(*shadow_pte);
&lt; at &gt;&lt; at &gt; -1751,7 +1776,7 &lt; at &gt;&lt; at &gt; static void mmu_set_spte(struct kvm_vcpu
 }
 }
 if (set_spte(vcpu, shadow_pte, pte_access, user_fault, write_fault,
-      dirty, largepage, gfn, pfn, speculative, true)) {
+      dirty, largepage, global, gfn, pfn, speculative, true)) {
 if (write_fault)
 *ptwrite = 1;
 kvm_x86_ops-&gt;tlb_flush(vcpu);
&lt; at &gt;&lt; at &gt; -1808,7 +1833,7 &lt; at &gt;&lt; at &gt; static int direct_map_entry(struct kvm_s
     || (walk-&gt;largepage &amp;&amp; level == PT_DIRECTORY_LEVEL)) {
 mmu_set_spte(vcpu, sptep, ACC_ALL, ACC_ALL,
      0, walk-&gt;write, 1, &amp;walk-&gt;pt_write,
-     walk-&gt;largepage, gfn, walk-&gt;pfn, false);
+     walk-&gt;largepage, 0, gfn, walk-&gt;pfn, false);
 ++vcpu-&gt;stat.pf_fixed;
 return 1;
 }
&lt; at &gt;&lt; at &gt; -1995,6 +2020,15 &lt; at &gt;&lt; at &gt; static void mmu_sync_roots(struct kvm_vc
 }
 }
 
+static void mmu_sync_global(struct kvm_vcpu *vcpu)
+{
+struct kvm *kvm = vcpu-&gt;kvm;
+struct kvm_mmu_page *sp, *n;
+
+list_for_each_entry_safe(sp, n, &amp;kvm-&gt;arch.oos_global_pages, oos_link)
+kvm_sync_page(vcpu, sp);
+}
+
 void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu)
 {
 spin_lock(&amp;vcpu-&gt;kvm-&gt;mmu_lock);
&lt; at &gt;&lt; at &gt; -2002,6 +2036,13 &lt; at &gt;&lt; at &gt; void kvm_mmu_sync_roots(struct kvm_vcpu 
 spin_unlock(&amp;vcpu-&gt;kvm-&gt;mmu_lock);
 }
 
+void kvm_mmu_sync_global(struct kvm_vcpu *vcpu)
+{
+spin_lock(&amp;vcpu-&gt;kvm-&gt;mmu_lock);
+mmu_sync_global(vcpu);
+spin_unlock(&amp;vcpu-&gt;kvm-&gt;mmu_lock);
+}
+
 static gpa_t nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, gva_t vaddr)
 {
 return vaddr;
Index: kvm/arch/x86/kvm/paging_tmpl.h
===================================================================
--- kvm.orig/arch/x86/kvm/paging_tmpl.h
+++ kvm/arch/x86/kvm/paging_tmpl.h
&lt; at &gt;&lt; at &gt; -274,7 +274,8 &lt; at &gt;&lt; at &gt; static void FNAME(update_pte)(struct kvm
 return;
 kvm_get_pfn(pfn);
 mmu_set_spte(vcpu, spte, page-&gt;role.access, pte_access, 0, 0,
-     gpte &amp; PT_DIRTY_MASK, NULL, largepage, gpte_to_gfn(gpte),
+     gpte &amp; PT_DIRTY_MASK, NULL, largepage,
+     gpte &amp; PT_GLOBAL_MASK, gpte_to_gfn(gpte),
      pfn, true);
 }
 
&lt; at &gt;&lt; at &gt; -301,8 +302,9 &lt; at &gt;&lt; at &gt; static int FNAME(shadow_walk_entry)(stru
 mmu_set_spte(vcpu, sptep, access, gw-&gt;pte_access &amp; access,
      sw-&gt;user_fault, sw-&gt;write_fault,
      gw-&gt;ptes[gw-&gt;level-1] &amp; PT_DIRTY_MASK,
-     sw-&gt;ptwrite, sw-&gt;largepage, gw-&gt;gfn, sw-&gt;pfn,
-     false);
+     sw-&gt;ptwrite, sw-&gt;largepage,
+     gw-&gt;ptes[gw-&gt;level-1] &amp; PT_GLOBAL_MASK,
+     gw-&gt;gfn, sw-&gt;pfn, false);
 sw-&gt;sptep = sptep;
 return 1;
 }
&lt; at &gt;&lt; at &gt; -580,7 +582,7 &lt; at &gt;&lt; at &gt; static int FNAME(sync_page)(struct kvm_v
 nr_present++;
 pte_access = sp-&gt;role.access &amp; FNAME(gpte_access)(vcpu, gpte);
 set_spte(vcpu, &amp;sp-&gt;spt[i], pte_access, 0, 0,
- is_dirty_pte(gpte), 0, gfn,
+ is_dirty_pte(gpte), 0, gpte &amp; PT_GLOBAL_MASK, gfn,
  spte_to_pfn(sp-&gt;spt[i]), true, false);
 }
 
Index: kvm/arch/x86/kvm/x86.c
===================================================================
--- kvm.orig/arch/x86/kvm/x86.c
+++ kvm/arch/x86/kvm/x86.c
&lt; at &gt;&lt; at &gt; -104,6 +104,7 &lt; at &gt;&lt; at &gt; struct kvm_stats_debugfs_item debugfs_en
 { "mmu_recycled", VM_STAT(mmu_recycled) },
 { "mmu_cache_miss", VM_STAT(mmu_cache_miss) },
 { "mmu_unsync", VM_STAT(mmu_unsync) },
+{ "mmu_unsync_global", VM_STAT(mmu_unsync_global) },
 { "remote_tlb_flush", VM_STAT(remote_tlb_flush) },
 { "largepages", VM_STAT(lpages) },
 { NULL }
&lt; at &gt;&lt; at &gt; -315,6 +316,7 &lt; at &gt;&lt; at &gt; void kvm_set_cr0(struct kvm_vcpu *vcpu, 
 kvm_x86_ops-&gt;set_cr0(vcpu, cr0);
 vcpu-&gt;arch.cr0 = cr0;
 
+kvm_mmu_sync_global(vcpu);
 kvm_mmu_reset_context(vcpu);
 return;
 }
&lt; at &gt;&lt; at &gt; -358,6 +360,7 &lt; at &gt;&lt; at &gt; void kvm_set_cr4(struct kvm_vcpu *vcpu, 
 }
 kvm_x86_ops-&gt;set_cr4(vcpu, cr4);
 vcpu-&gt;arch.cr4 = cr4;
+kvm_mmu_sync_global(vcpu);
 kvm_mmu_reset_context(vcpu);
 }
 EXPORT_SYMBOL_GPL(kvm_set_cr4);
&lt; at &gt;&lt; at &gt; -4113,6 +4116,7 &lt; at &gt;&lt; at &gt; struct  kvm *kvm_arch_create_vm(void)
 return ERR_PTR(-ENOMEM);
 
 INIT_LIST_HEAD(&amp;kvm-&gt;arch.active_mmu_pages);
+INIT_LIST_HEAD(&amp;kvm-&gt;arch.oos_global_pages);
 INIT_LIST_HEAD(&amp;kvm-&gt;arch.assigned_dev_head);
 
 /* Reserve bit 0 of irq_sources_bitmap for userspace irq source */

</description>
    <dc:creator>Marcelo Tosatti</dc:creator>
    <dc:date>2008-12-02T00:32:04</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25400">
    <title>RE: [PATCH 1/2] [v2] VT-d: Support multiple device assignment for KVM</title>
    <link>http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25400</link>
    <description>It's fine. You only needs to change the APIs to generic APIs. I will update it soon.

Regards,
Weidong

Joerg Roedel wrote:

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo&lt; at &gt;vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

</description>
    <dc:creator>Han, Weidong</dc:creator>
    <dc:date>2008-12-02T00:31:11</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25399">
    <title>Re: [PATCH] KVM: Qemu: push_nmi should be only used by I386 Arch.</title>
    <link>http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25399</link>
    <description>
Well, it happens, but I do wish that more people would use cscope or
even grep to find all users of a symbol.

I also wish that Avi would get his PPC box working so he could catch
build breaks like these. Cross-compilers would do as well.

I would also like a pony.


Acked-by: Hollis Blanchard &lt;hollisb&lt; at &gt;us.ibm.com&gt;

</description>
    <dc:creator>Hollis Blanchard</dc:creator>
    <dc:date>2008-12-01T23:18:06</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25398">
    <title>Re: [PATCH] KVM: Qemu: push_nmi should be only used by I386 Arch.</title>
    <link>http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25398</link>
    <description>
Ouch - I'm sorry.


Here is a patch that reverts change and fixes the root of the issue.

-----------

Subject: Fix non-x86 NMI hooks

My previous x86-only change to the NMI push hook broke PPC and IA64.
This is a proper fix plus a cleanup of the #ifdef-based approach to
solve the breakage.

Signed-off-by: Jan Kiszka &lt;jan.kiszka&lt; at &gt;siemens.com&gt;
---

 qemu/qemu-kvm-ia64.c    |    3 +--
 qemu/qemu-kvm-powerpc.c |    3 +--
 qemu/qemu-kvm.c         |    4 ----
 3 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/qemu/qemu-kvm-ia64.c b/qemu/qemu-kvm-ia64.c
index 8380f39..a6b17af 100644
--- a/qemu/qemu-kvm-ia64.c
+++ b/qemu/qemu-kvm-ia64.c
&lt; at &gt;&lt; at &gt; -57,9 +57,8 &lt; at &gt;&lt; at &gt; int kvm_arch_try_push_interrupts(void *opaque)
     return 1;
 }
 
-int kvm_arch_try_push_nmi(void *opaque)
+void kvm_arch_push_nmi(void *opaque)
 {
-    return 1;
 }
 
 void kvm_arch_update_regs_for_sipi(CPUState *env)
diff --git a/qemu/qemu-kvm-powerpc.c b/qemu/qemu-kvm-powerpc.c
index 19fde40..fa534ed 100644
--- a/qemu/qemu-kvm-powerpc.c
+++ b/qemu/qemu-kvm-powerpc.c
&lt; at &gt;&lt; at &gt; -188,12 +188,11 &lt; at &gt;&lt; at &gt; int kvm_arch_try_push_interrupts(void *opaque)
     return 0;
 }
 
-int kvm_arch_try_push_nmi(void *opaque)
+void kvm_arch_push_nmi(void *opaque)
 {
 /* no nmi irq, so discard that call for now and return success.
  * This might later get mapped to something on powerpc too if we want
  *  to support the nmi monitor command somwhow */
-return 0;
 }
 
 void kvm_arch_update_regs_for_sipi(CPUState *env)
diff --git a/qemu/qemu-kvm.c b/qemu/qemu-kvm.c
index b6c8288..cf0e85d 100644
--- a/qemu/qemu-kvm.c
+++ b/qemu/qemu-kvm.c
&lt; at &gt;&lt; at &gt; -154,12 +154,10 &lt; at &gt;&lt; at &gt; static int try_push_interrupts(void *opaque)
     return kvm_arch_try_push_interrupts(opaque);
 }
 
-#ifdef TARGET_I386
 static void push_nmi(void *opaque)
 {
     kvm_arch_push_nmi(opaque);
 }
-#endif
 
 static void post_kvm_run(void *opaque, void *data)
 {
&lt; at &gt;&lt; at &gt; -744,9 +742,7 &lt; at &gt;&lt; at &gt; static struct kvm_callbacks qemu_kvm_ops = {
     .shutdown = kvm_shutdown,
     .io_window = kvm_io_window,
     .try_push_interrupts = try_push_interrupts,
-#ifdef TARGET_I386
     .push_nmi = push_nmi,
-#endif
     .post_kvm_run = post_kvm_run,
     .pre_kvm_run = pre_kvm_run,
 #ifdef TARGET_I386

</description>
    <dc:creator>Jan Kiszka</dc:creator>
    <dc:date>2008-12-01T23:02:37</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25397">
    <title>Re: 1-1 mapping of devices without VT-d</title>
    <link>http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25397</link>
    <description>But of course
No, just might take a some time to go to mainline. Patches need further 
polishing and we
also need wider demand for it.
Actually pvdma can help vt-d so we won't have to make all the guest 
memory unswappable.

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo&lt; at &gt;vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

</description>
    <dc:creator>Dor Laor</dc:creator>
    <dc:date>2008-12-01T23:01:07</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25396">
    <title>Re: STOP error with virtio on KVM-79/2.6.18/Win2k3 x64 guest</title>
    <link>http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25396</link>
    <description>What driver version are you using? Version 2 is obsolete.
I posted ver 3 few months ago, Avi can you please upload it to sourceforge.
My old public space was blocked so I'll send you a private attachment to 
test.

Dor.

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo&lt; at &gt;vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

</description>
    <dc:creator>Dor Laor</dc:creator>
    <dc:date>2008-12-01T22:26:40</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25395">
    <title>Re: 1-1 mapping of devices without VT-d</title>
    <link>http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25395</link>
    <description>[]

Hmm.  Well, as time goes by, most hosts will be 64 bit or more.
But it does not mean that there's no need to maintain 32bits
arch anymore...  i hope anyway :)

Are you saying that PCI passthrough without hardware support will
not be available in (standard) kvm, even if patches exists for that?

/mjt
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo&lt; at &gt;vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

</description>
    <dc:creator>Michael Tokarev</dc:creator>
    <dc:date>2008-12-01T21:09:16</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25393">
    <title>Re: [Qemu-devel] [PATCH 2/2] Virtio block device support</title>
    <link>http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25393</link>
    <description>
I don't disagree.


Yeah, I think the virtio stuff could use some love but I'd like to avoid 
that until we have something in tree and merged against kvm-userspace.

Regards,

Anthony Liguori


--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo&lt; at &gt;vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

</description>
    <dc:creator>Anthony Liguori</dc:creator>
    <dc:date>2008-12-01T20:22:42</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25392">
    <title>Re: [PATCH] extboot: properly set int 0x13 return value</title>
    <link>http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25392</link>
    <description>
Good catch!


Acked-by: Anthony Liguori &lt;aliguori&lt; at &gt;us.ibm.com&gt;

Regards,

Anthony Liguori
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo&lt; at &gt;vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

</description>
    <dc:creator>Anthony Liguori</dc:creator>
    <dc:date>2008-12-01T20:20:43</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25391">
    <title>Re: [Qemu-devel] [PATCH 2/2] Virtio block device support</title>
    <link>http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25391</link>
    <description>
This shouldn't be in pc.h. I don't know if you'd consider virtio.h to be
a layering violation, but the virtio layers are already being compressed
in these patches...

</description>
    <dc:creator>Hollis Blanchard</dc:creator>
    <dc:date>2008-12-01T20:20:28</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25390">
    <title>Re: 1-1 mapping of devices without VT-d</title>
    <link>http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25390</link>
    <description>Although it had worked for us out of tree, there is no immediate need to 
pursue it.
If anyone would like to nurture these patches he is more than welcome.
ps: you also have pv-dma option for Linux guests (same status though).
As time goes by most host will have either vt-d or amd iommu.

Regards,
Dor


--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo&lt; at &gt;vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

</description>
    <dc:creator>Dor Laor</dc:creator>
    <dc:date>2008-12-01T20:13:37</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25389">
    <title>[PATCH] extboot: properly set int 0x13 return value</title>
    <link>http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25389</link>
    <description>Callers of int 0x13 usually rely on the carry flag being
clear/set to indicate the status of the interrupt execution.

However, our current code clear or set the flags register,
which is totally useless. Whichever value it has, will
be overwritten by the flags value _before_ the interrupt, due to
the iret instruction.

This fixes a bug that prevents slackware (and possibly win2k, untested)
to boot.

Signed-off-by: Glauber Costa &lt;glommer&lt; at &gt;redhat.com&gt;
---
 extboot/extboot.S |   52 ++++++++++++++++++++++++++--------------------------
 1 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/extboot/extboot.S b/extboot/extboot.S
index 2630abb..e3d1adf 100644
--- a/extboot/extboot.S
+++ b/extboot/extboot.S
&lt; at &gt;&lt; at &gt; -99,24 +99,24 &lt; at &gt;&lt; at &gt; int19_handler:
 
 #define FLAGS_CF0x01
 
-.macro clc
-push %ax
-pushf
-pop %ax
-and $(~FLAGS_CF), %ax
-push %ax
-popf
-pop %ax
+/* The two macro below clear/set the carry flag to indicate the status
+ * of the interrupt execution. It is not enough to issue a clc/stc instruction,
+ * since the value of the flags register will be overwritten by whatever is
+ * in the stack frame
+ */
+.macro clc_stack
+push %bp
+mov %sp, %bp
+/* 8 = 2 (bp, just pushed) + 2 (ip) + 3 (real mode interrupt frame) */
+and $(~FLAGS_CF), 8(%bp)
+pop %bp
 .endm
 
-.macro stc
-push %ax
-pushf
-pop %ax
-or $(FLAGS_CF), %ax
-push %ax
-popf
-pop %ax
+.macro stc_stack
+push %bp
+/* 8 = 2 (bp, just pushed) + 2 (ip) + 3 (real mode interrupt frame) */
+or $(FLAGS_CF), 8(%bp)
+pop %bp
 .endm
 
 /* we clobber %bx */
&lt; at &gt;&lt; at &gt; -292,7 +292,7 &lt; at &gt;&lt; at &gt; mul32:  /* lo,      hi,     lo,     hi */
 
 disk_reset:
 movb $0, %ah
-clc
+clc_stack
 ret
 
 /* this really should be a function, not a macro but i'm lazy */
&lt; at &gt;&lt; at &gt; -395,7 +395,7 &lt; at &gt;&lt; at &gt; disk_reset:
 pop %ax
 
 mov $0, %ah
-clc
+clc_stack
 ret
 .endm
 
&lt; at &gt;&lt; at &gt; -454,12 +454,12 &lt; at &gt;&lt; at &gt; read_disk_drive_parameters:
 pop %bx
 
 /* do this last since it's the most sensitive */
-clc
+clc_stack
 ret
 
 alternate_disk_reset:
 movb $0, %ah
-clc
+clc_stack
 ret
 
 read_disk_drive_size:
&lt; at &gt;&lt; at &gt; -498,21 +498,21 &lt; at &gt;&lt; at &gt; read_disk_drive_size:
 freea
 pop %bx
 
-clc
+clc_stack
 ret
 
 check_if_extensions_present:
 mov $0x30, %ah
 mov $0xAA55, %bx
 mov $0x07, %cx
-clc
+clc_stack
 ret
 
 .macro extended_read_write_sectors cmd
 cmpb $10, 0(%si)
 jg 1f
 mov $1, %ah
-stc
+stc_stack
 ret
 1:
 push %ax
&lt; at &gt;&lt; at &gt; -544,7 +544,7 &lt; at &gt;&lt; at &gt; check_if_extensions_present:
 pop %ax
 
 mov $0, %ah
-clc
+clc_stack
 ret
 .endm
 
&lt; at &gt;&lt; at &gt; -612,12 +612,12 &lt; at &gt;&lt; at &gt; get_extended_drive_parameters:
 pop %ax
 
 mov $0, %ah
-clc
+clc_stack
 ret
 
 terminate_disk_emulation:
 mov $1, %ah
-stc
+stc_stack
 ret
 
 int13_handler:
</description>
    <dc:creator>Glauber Costa</dc:creator>
    <dc:date>2008-12-01T20:01:32</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25388">
    <title>[PATCH] extboot: properly set int 0x13 return value</title>
    <link>http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25388</link>
    <description>Callers of int 0x13 usually rely on the carry flag being
clear/set to indicate the status of the interrupt execution.

However, our current code clear or set the flags register,
which is totally useless. Whichever value it has, will
be overwritten by the flags value _before_ the interrupt, due to
the iret instruction.

This fixes a bug that prevents slackware (and possibly win2k, untested)
to boot.

Signed-off-by: Glauber Costa &lt;glommer&lt; at &gt;redhat.com&gt;
---
 extboot/extboot.S |   52 ++++++++++++++++++++++++++--------------------------
 1 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/extboot/extboot.S b/extboot/extboot.S
index 2630abb..4cbfe11 100644
--- a/extboot/extboot.S
+++ b/extboot/extboot.S
&lt; at &gt;&lt; at &gt; -99,24 +99,24 &lt; at &gt;&lt; at &gt; int19_handler:
 
 #define FLAGS_CF0x01
 
-.macro clc
-push %ax
-pushf
-pop %ax
-and $(~FLAGS_CF), %ax
-push %ax
-popf
-pop %ax
+/* The two macro below clear/set the carry flag to indicate the status
+ * of the interrupt execution. It is not enough to issue a clc/stc instruction, 
+ * since the value of the flags register will be overwritten by whatever is
+ * in the stack frame
+ */
+.macro clc_stack
+push %bp
+mov %sp, %bp
+/* 8 = 2 (bp, just pushed) + 2 (ip) + 3 (real mode interrupt frame)
+and $(~FLAGS_CF), 8(%bp)
+pop %bp
 .endm
 
-.macro stc
-push %ax
-pushf
-pop %ax
-or $(FLAGS_CF), %ax
-push %ax
-popf
-pop %ax
+.macro stc_stack
+push %bp
+/* 8 = 2 (bp, just pushed) + 2 (ip) + 3 (real mode interrupt frame)
+or $(FLAGS_CF), 8(%bp)
+pop %bp
 .endm
 
 /* we clobber %bx */
&lt; at &gt;&lt; at &gt; -292,7 +292,7 &lt; at &gt;&lt; at &gt; mul32:  /* lo,      hi,     lo,     hi */
 
 disk_reset:
 movb $0, %ah
-clc
+clc_stack
 ret
 
 /* this really should be a function, not a macro but i'm lazy */
&lt; at &gt;&lt; at &gt; -395,7 +395,7 &lt; at &gt;&lt; at &gt; disk_reset:
 pop %ax
 
 mov $0, %ah
-clc
+clc_stack
 ret
 .endm
 
&lt; at &gt;&lt; at &gt; -454,12 +454,12 &lt; at &gt;&lt; at &gt; read_disk_drive_parameters:
 pop %bx
 
 /* do this last since it's the most sensitive */
-clc
+clc_stack
 ret
 
 alternate_disk_reset:
 movb $0, %ah
-clc
+clc_stack
 ret
 
 read_disk_drive_size:
&lt; at &gt;&lt; at &gt; -498,21 +498,21 &lt; at &gt;&lt; at &gt; read_disk_drive_size:
 freea
 pop %bx
 
-clc
+clc_stack
 ret
 
 check_if_extensions_present:
 mov $0x30, %ah
 mov $0xAA55, %bx
 mov $0x07, %cx
-clc
+clc_stack
 ret
 
 .macro extended_read_write_sectors cmd
 cmpb $10, 0(%si)
 jg 1f
 mov $1, %ah
-stc
+stc_stack
 ret
 1:
 push %ax
&lt; at &gt;&lt; at &gt; -544,7 +544,7 &lt; at &gt;&lt; at &gt; check_if_extensions_present:
 pop %ax
 
 mov $0, %ah
-clc
+clc_stack
 ret
 .endm
 
&lt; at &gt;&lt; at &gt; -612,12 +612,12 &lt; at &gt;&lt; at &gt; get_extended_drive_parameters:
 pop %ax
 
 mov $0, %ah
-clc
+clc_stack
 ret
 
 terminate_disk_emulation:
 mov $1, %ah
-stc
+stc_stack
 ret
 
 int13_handler:
</description>
    <dc:creator>Glauber Costa</dc:creator>
    <dc:date>2008-12-01T19:41:10</dc:date>
  </item>
  <item rdf:about="http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25387">
    <title>splice() based interguest networking</title>
    <link>http://permalink.gmane.org/gmane.comp.emulators.kvm.devel/25387</link>
    <description>Here's a random thought I had after seeing the new Xen netchannel2 tree 
had fast-path support for guest&lt;=&gt;guest communication.

With virtio, we could do really fast interguest networking in 
userspace.  We have a few requirements though:

1) There should be a minimal number of copies, just one in almost all cases.
2) The copy should occur on the receiving end since the receiver is most 
likely going to be accessing the data in the future
3) The copy should be done in the kernel so that in the future it could 
be accelerated with a generic DMA engine.

So far, all the approaches required mmap()'ing the guest memory in both 
QEMU instances which makes it much less useful.  I think splice solves 
this problem though and gets us most of the above for free.

If we have two shared pipes() between the two QEMU processes, then:

1) On TX, we vmsplice() from the sg buffer to one pipe.  This will end 
up being vmsplice_to_pipe() in the kernel which is zero-copy.

2) The pipe becomes readable which will result in an RX notification in 
the other process, we see if we have any buffers available in the 
receive queue.  If so, we vmsplice() from the pipe to the sg buffer.  
This will result in a copy via vmsplice_to_user().  In the future, 
vmsplice_to_user() would be an obvious candidate for IO-AT acceleration.

Since the copy is happening in the kernel, assuming you're not in a 
highmem situation, no page table manipulation is required.

We still have to address feature negotation and such.

Regards,

Anthony Liguori
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo&lt; at &gt;vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

</description>
    <dc:creator>Anthony Liguori</dc:creator>
    <dc:date>2008-12-01T19:33:13</dc:date>
  </item>
  <textinput rdf:about="http://search.gmane.org/?group=$group=gmane.comp.emulators.kvm.devel">
    <title>Search Engine</title>
    <description>Search the mailing list at Gmane</description>
    <name>query</name>
    <link>http://search.gmane.org/?group=$group=gmane.comp.emulators.kvm.devel</link>
  </textinput>
</rdf:RDF>
