diff --git a/vl.c b/vl.c
index 85adc54..36b5ed4 100644
--- a/vl.c
+++ b/vl.c
@@ -273,6 +273,9 @@ static QEMUTimer *icount_rt_timer;
 static QEMUTimer *icount_vm_timer;
 static QEMUTimer *nographic_timer;
 
+/* Kemari */
+volatile int kemari_enabled = 0;
+
 uint8_t qemu_uuid[16];
 
 #include "xen-vl-extra.c"
diff --git a/xen-config-host.h b/xen-config-host.h
index 5b1f4d7..eada77c 100644
--- a/xen-config-host.h
+++ b/xen-config-host.h
@@ -44,6 +44,7 @@ void xenstore_store_serial_port_info(int i, struct CharDriverState *chr,
 
 extern unsigned long *logdirty_bitmap;
 extern unsigned long logdirty_bitmap_size;
+extern volatile int kemari_enabled;
 
 #ifdef CONFIG_STUBDOM
 #undef HAVE_IOVEC
diff --git a/xenstore.c b/xenstore.c
index 9360771..94a24dc 100644
--- a/xenstore.c
+++ b/xenstore.c
@@ -33,6 +33,7 @@
 struct xs_handle *xsh = NULL;
 static char *media_filename[MAX_DRIVES+1];
 static QEMUTimer *insert_timer = NULL;
+static int xce = 0;
 
 #define UWAIT_MAX (30*1000000) /* thirty seconds */
 #define UWAIT     (100000)     /* 1/10th second  */
@@ -301,6 +302,42 @@ static const char *xenstore_get_guest_uuid(void)
     return already_computed;
 }
 
+/* prototype of xenstore_process_logdirty_event */
+static void xenstore_process_logdirty_event(void);
+
+static int get_kemari_port(void)
+{
+    static int kemari_port = -1;
+    if (kemari_port > 0)
+        return kemari_port;
+
+    kemari_port = xc_evtchn_bind_unbound_port(xce, DOMID_SELF);
+    return kemari_port;
+}
+
+static void kemari_handler(void *dummy)
+{
+    int port;
+
+    port = xc_evtchn_pending(xce);
+    if (port < 0) {
+        fprintf(logfile, "xc_evtchn_pending failed");
+        return;
+    }
+
+    if (port == get_kemari_port()) {
+        kemari_enabled = 1; /* QEMU will run in kemari mode */
+        xenstore_process_logdirty_event();
+    } else {
+        fprintf(logfile, "unexpected port %d fired", port);
+    }
+
+    if (xc_evtchn_unmask(xce, port) < 0) {
+        fprintf(logfile, "xc_evtchn_unmask failed");
+        return;
+    }
+}
+
 #define DIRECT_PCI_STR_LEN 512
 #define PT_PCI_MSITRANSLATE_DEFAULT 1
 #define PT_PCI_POWER_MANAGEMENT_DEFAULT 0
@@ -328,6 +365,12 @@ void xenstore_parse_domain_config(int hvm_domid)
 
     xenstore_get_guest_uuid();
 
+    xce = xc_evtchn_open();
+    if (xce < 0) {
+        fprintf(logfile, "Could not open event channel\n");
+        return;
+    }
+
     xsh = xs_daemon_open();
     if (xsh == NULL) {
         fprintf(logfile, "Could not contact xenstore for domain config\n");
@@ -365,6 +408,27 @@ void xenstore_parse_domain_config(int hvm_domid)
             break;
         }
     }
+
+    /* kemari */
+    {
+        int port;
+        char port_string[128];
+        port = get_kemari_port();
+        if (port < 0) {
+            fprintf(stderr, "failed to get kemari port\n");
+            goto out;
+        }
+        snprintf(port_string, sizeof(port_string), "%d", port);
+    
+        if (pasprintf(&buf, "/local/domain/%u/kemari/event-channel",
+                hvm_domid) == -1)
+            goto out;
+
+        xs_write(xsh, XBT_NULL, buf, port_string, strlen(port_string));
+        qemu_set_fd_handler2(xc_evtchn_fd(xce),
+            NULL, kemari_handler, NULL, NULL);
+        fprintf(stderr, "Kemari port is enabled: %d\n", port);
+    }
         
     for (i = 0; i < num; i++) {
 	format = NULL; /* don't know what the format is yet */
@@ -692,6 +756,8 @@ static void xenstore_process_logdirty_event(void)
     static char *active_path = NULL;
     static char *next_active_path = NULL;
     static char *seg = NULL;
+    static char *kemari_qemu_info = NULL;
+    static char *qemu_file = NULL;
     unsigned int len;
     int i;
 
@@ -758,6 +824,8 @@ static void xenstore_process_logdirty_event(void)
             seg = NULL;
             return;
         }
+        kemari_qemu_info = seg + logdirty_bitmap_size * 2;
+        asprintf(&qemu_file, "/dev/shm/qemu-save.%d", domid); /* use tmpfs */
 #endif
 
         /* Remember the paths for the next-active and active entries */
@@ -775,6 +843,30 @@ static void xenstore_process_logdirty_event(void)
         }
     }
 
+#ifndef CONFIG_STUBDOM
+    if (kemari_enabled) {
+        while (kemari_qemu_info[1])
+            xen_rmb();
+
+        /* Switch buffers */
+        i = kemari_qemu_info[0];
+        if (i != 0 && i != 1) {
+            fprintf(logfile, "Log-dirty: bad next-active entry: %d\n", i);
+            exit(1);
+        }
+        logdirty_bitmap = (unsigned long *)(seg + i * logdirty_bitmap_size);
+        kemari_qemu_info[1] = 1;
+        xen_wmb();
+
+        /* Save QEMU status */
+        while (kemari_qemu_info[2])
+            xen_rmb();
+        do_savevm(qemu_file);
+        kemari_qemu_info[2] = 1;
+        xen_wmb();
+        return;
+    }
+#endif /* !CONFIG_STUBDOM */
     fprintf(logfile, "Triggered log-dirty buffer switch\n");
     
     /* Read the required active buffer from the store */

