WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] merge

# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 5e5ae834095691ec677fcaaf11e9b16fcaeb76ed
# Parent  4e1031ce3bc203badf97c75fa124178e485ca028
# Parent  081b326162bcabd1c1245e16c14c8427f33b1b5e
merge

diff -r 4e1031ce3bc2 -r 5e5ae8340956 .hgignore
--- a/.hgignore Mon Sep 26 17:15:55 2005
+++ b/.hgignore Wed Sep 28 20:06:49 2005
@@ -158,6 +158,7 @@
 ^tools/xenstore/xs_dom0_test$
 ^tools/xenstore/xs_random$
 ^tools/xenstore/xs_stress$
+^tools/xenstore/xs_tdb_dump$
 ^tools/xenstore/xs_test$
 ^tools/xenstore/xs_watch_stress$
 ^tools/xentrace/xenctx$
diff -r 4e1031ce3bc2 -r 5e5ae8340956 
linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32
--- a/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32        Mon Sep 
26 17:15:55 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32        Wed Sep 
28 20:06:49 2005
@@ -2684,7 +2684,7 @@
 #
 # File systems
 #
-CONFIG_EXT2_FS=m
+CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 CONFIG_EXT2_FS_SECURITY=y
@@ -2913,7 +2913,7 @@
 # CONFIG_KEYS_DEBUG_PROC_KEYS is not set
 CONFIG_SECURITY=y
 # CONFIG_SECURITY_NETWORK is not set
-CONFIG_SECURITY_CAPABILITIES=m
+CONFIG_SECURITY_CAPABILITIES=y
 CONFIG_SECURITY_ROOTPLUG=m
 CONFIG_SECURITY_SECLVL=m
 CONFIG_SECURITY_SELINUX=y
diff -r 4e1031ce3bc2 -r 5e5ae8340956 
linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c       Mon Sep 26 
17:15:55 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/process.c       Wed Sep 28 
20:06:49 2005
@@ -112,6 +112,10 @@
 
 #ifdef CONFIG_HOTPLUG_CPU
 #include <asm/nmi.h>
+#ifdef CONFIG_SMP
+extern void smp_suspend(void);
+extern void smp_resume(void);
+#endif
 /* We don't actually take CPU down, just spin without interrupts. */
 static inline void play_dead(void)
 {
@@ -120,6 +124,13 @@
                HYPERVISOR_yield();
 
        __flush_tlb_all();
+   /* 
+    * Restore IPI/IRQ mappings before marking online to prevent 
+    * race between pending interrupts and restoration of handler. 
+    */
+#ifdef CONFIG_SMP
+       smp_resume();
+#endif
        cpu_set(smp_processor_id(), cpu_online_map);
 }
 #else
@@ -135,10 +146,6 @@
  * low exit latency (ie sit in a loop waiting for
  * somebody to say that they'd like to reschedule)
  */
-#ifdef CONFIG_SMP
-extern void smp_suspend(void);
-extern void smp_resume(void);
-#endif
 void cpu_idle (void)
 {
        int cpu = _smp_processor_id();
@@ -166,9 +173,6 @@
                                HYPERVISOR_vcpu_down(cpu);
 #endif
                                play_dead();
-#ifdef CONFIG_SMP
-                               smp_resume();
-#endif
                                local_irq_enable();
                        }
 
diff -r 4e1031ce3bc2 -r 5e5ae8340956 
linux-2.6-xen-sparse/arch/xen/i386/mm/fault.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/mm/fault.c     Mon Sep 26 17:15:55 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/fault.c     Wed Sep 28 20:06:49 2005
@@ -209,7 +209,10 @@
 {
        unsigned long *p, page;
 
-        page = __pa(per_cpu(cur_pgd, smp_processor_id()));
+       preempt_disable();
+       page = __pa(per_cpu(cur_pgd, smp_processor_id()));
+       preempt_enable();
+
        p  = (unsigned long *)__va(page);
        p += (address >> 30) * 2;
        printk(KERN_ALERT "%08lx -> *pde = %08lx:%08lx\n", page, p[1], p[0]);
@@ -237,7 +240,12 @@
 {
        unsigned long page;
 
+       preempt_disable();
        page = ((unsigned long *) per_cpu(cur_pgd, smp_processor_id()))
+           [address >> 22];
+       preempt_enable();
+
+       page = ((unsigned long *) per_cpu(cur_pgd, get_cpu()))
            [address >> 22];
        printk(KERN_ALERT "*pde = ma %08lx pa %08lx\n", page,
               machine_to_phys(page));
@@ -567,7 +575,9 @@
                pmd_t *pmd, *pmd_k;
                pte_t *pte_k;
 
+               preempt_disable();
                pgd = index + per_cpu(cur_pgd, smp_processor_id());
+               preempt_enable();
                pgd_k = init_mm.pgd + index;
 
                if (!pgd_present(*pgd_k))
diff -r 4e1031ce3bc2 -r 5e5ae8340956 
linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c     Mon Sep 26 17:15:55 2005
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c     Wed Sep 28 20:06:49 2005
@@ -1,13 +1,10 @@
 /******************************************************************************
  * gnttab.c
  * 
- * Two sets of functionality:
- * 1. Granting foreign access to our memory reservation.
- * 2. Accessing others' memory reservations via grant references.
- * (i.e., mechanisms for both sender and recipient of grant references)
+ * Granting foreign access to our memory reservation.
  * 
  * Copyright (c) 2005, Christopher Clark
- * Copyright (c) 2004, K A Fraser
+ * Copyright (c) 2004-2005, K A Fraser
  */
 
 #include <linux/config.h>
@@ -23,15 +20,15 @@
 #include <asm/synch_bitops.h>
 
 #if 1
-#define ASSERT(_p) \
-    if ( !(_p) ) { printk(KERN_ALERT"Assertion '%s': line %d, file %s\n", \
-    #_p , __LINE__, __FILE__); *(int*)0=0; }
+#define ASSERT(_p)                                                           \
+       if ( !(_p) ) { printk(KERN_ALERT"Assertion '%s': line %d, file %s\n", \
+       #_p , __LINE__, __FILE__); *(int*)0=0; }
 #else
 #define ASSERT(_p) ((void)0)
 #endif
 
-#define WPRINTK(fmt, args...) \
-    printk(KERN_WARNING "xen_grant: " fmt, ##args)
+#define WPRINTK(fmt, args...)                          \
+       printk(KERN_WARNING "xen_grant: " fmt, ##args)
 
 
 EXPORT_SYMBOL(gnttab_grant_foreign_access);
@@ -49,11 +46,14 @@
 EXPORT_SYMBOL(gnttab_grant_foreign_access_ref);
 EXPORT_SYMBOL(gnttab_grant_foreign_transfer_ref);
 
+/* External tools reserve first few grant table entries. */
+#define NR_RESERVED_ENTRIES 8
+
 #define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t))
 #define GNTTAB_LIST_END (NR_GRANT_ENTRIES + 1)
 
 static grant_ref_t gnttab_list[NR_GRANT_ENTRIES];
-static int gnttab_free_count = NR_GRANT_ENTRIES;
+static int gnttab_free_count;
 static grant_ref_t gnttab_free_head;
 static spinlock_t gnttab_list_lock = SPIN_LOCK_UNLOCKED;
 
@@ -64,22 +64,22 @@
 static int
 get_free_entries(int count)
 {
-    unsigned long flags;
-    int ref;
-    grant_ref_t head;
-    spin_lock_irqsave(&gnttab_list_lock, flags);
-    if (gnttab_free_count < count) {
+       unsigned long flags;
+       int ref;
+       grant_ref_t head;
+       spin_lock_irqsave(&gnttab_list_lock, flags);
+       if (gnttab_free_count < count) {
+               spin_unlock_irqrestore(&gnttab_list_lock, flags);
+               return -1;
+       }
+       ref = head = gnttab_free_head;
+       gnttab_free_count -= count;
+       while (count-- > 1)
+               head = gnttab_list[head];
+       gnttab_free_head = gnttab_list[head];
+       gnttab_list[head] = GNTTAB_LIST_END;
        spin_unlock_irqrestore(&gnttab_list_lock, flags);
-       return -1;
-    }
-    ref = head = gnttab_free_head;
-    gnttab_free_count -= count;
-    while (count-- > 1)
-       head = gnttab_list[head];
-    gnttab_free_head = gnttab_list[head];
-    gnttab_list[head] = GNTTAB_LIST_END;
-    spin_unlock_irqrestore(&gnttab_list_lock, flags);
-    return ref;
+       return ref;
 }
 
 #define get_free_entry() get_free_entries(1)
@@ -87,38 +87,41 @@
 static void
 do_free_callbacks(void)
 {
-    struct gnttab_free_callback *callback = gnttab_free_callback_list, *next;
-    gnttab_free_callback_list = NULL;
-    while (callback) {
-       next = callback->next;
-       if (gnttab_free_count >= callback->count) {
-           callback->next = NULL;
-           callback->fn(callback->arg);
-       } else {
-           callback->next = gnttab_free_callback_list;
-           gnttab_free_callback_list = callback;
-       }
-       callback = next;
-    }
+       struct gnttab_free_callback *callback, *next;
+
+       callback = gnttab_free_callback_list;
+       gnttab_free_callback_list = NULL;
+
+       while (callback != NULL) {
+               next = callback->next;
+               if (gnttab_free_count >= callback->count) {
+                       callback->next = NULL;
+                       callback->fn(callback->arg);
+               } else {
+                       callback->next = gnttab_free_callback_list;
+                       gnttab_free_callback_list = callback;
+               }
+               callback = next;
+       }
 }
 
 static inline void
 check_free_callbacks(void)
 {
-    if (unlikely(gnttab_free_callback_list))
-       do_free_callbacks();
+       if (unlikely(gnttab_free_callback_list))
+               do_free_callbacks();
 }
 
 static void
 put_free_entry(grant_ref_t ref)
 {
-    unsigned long flags;
-    spin_lock_irqsave(&gnttab_list_lock, flags);
-    gnttab_list[ref] = gnttab_free_head;
-    gnttab_free_head = ref;
-    gnttab_free_count++;
-    check_free_callbacks();
-    spin_unlock_irqrestore(&gnttab_list_lock, flags);
+       unsigned long flags;
+       spin_lock_irqsave(&gnttab_list_lock, flags);
+       gnttab_list[ref] = gnttab_free_head;
+       gnttab_free_head = ref;
+       gnttab_free_count++;
+       check_free_callbacks();
+       spin_unlock_irqrestore(&gnttab_list_lock, flags);
 }
 
 /*
@@ -128,187 +131,189 @@
 int
 gnttab_grant_foreign_access(domid_t domid, unsigned long frame, int readonly)
 {
-    int ref;
+       int ref;
     
-    if ( unlikely((ref = get_free_entry()) == -1) )
-        return -ENOSPC;
-
-    shared[ref].frame = frame;
-    shared[ref].domid = domid;
-    wmb();
-    shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0);
-
-    return ref;
+       if (unlikely((ref = get_free_entry()) == -1))
+               return -ENOSPC;
+
+       shared[ref].frame = frame;
+       shared[ref].domid = domid;
+       wmb();
+       shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0);
+
+       return ref;
 }
 
 void
 gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
                                unsigned long frame, int readonly)
 {
-    shared[ref].frame = frame;
-    shared[ref].domid = domid;
-    wmb();
-    shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0);
+       shared[ref].frame = frame;
+       shared[ref].domid = domid;
+       wmb();
+       shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0);
 }
 
 
 int
 gnttab_query_foreign_access(grant_ref_t ref)
 {
-    u16 nflags;
-
-    nflags = shared[ref].flags;
-
-    return ( nflags & (GTF_reading|GTF_writing) );
+       u16 nflags;
+
+       nflags = shared[ref].flags;
+
+       return (nflags & (GTF_reading|GTF_writing));
 }
 
 void
 gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly)
 {
-    u16 flags, nflags;
-
-    nflags = shared[ref].flags;
-    do {
-        if ( (flags = nflags) & (GTF_reading|GTF_writing) )
-            printk(KERN_ALERT "WARNING: g.e. still in use!\n");
-    }
-    while ( (nflags = synch_cmpxchg(&shared[ref].flags, flags, 0)) != flags );
+       u16 flags, nflags;
+
+       nflags = shared[ref].flags;
+       do {
+               if ( (flags = nflags) & (GTF_reading|GTF_writing) )
+                       printk(KERN_ALERT "WARNING: g.e. still in use!\n");
+       }
+       while ((nflags = synch_cmpxchg(&shared[ref].flags, flags, 0)) !=
+              flags);
 }
 
 void
 gnttab_end_foreign_access(grant_ref_t ref, int readonly)
 {
-    gnttab_end_foreign_access_ref(ref, readonly);
-    put_free_entry(ref);
+       gnttab_end_foreign_access_ref(ref, readonly);
+       put_free_entry(ref);
 }
 
 int
 gnttab_grant_foreign_transfer(domid_t domid)
 {
-    int ref;
-
-    if ( unlikely((ref = get_free_entry()) == -1) )
-        return -ENOSPC;
-
-    shared[ref].frame = 0;
-    shared[ref].domid = domid;
-    wmb();
-    shared[ref].flags = GTF_accept_transfer;
-
-    return ref;
+       int ref;
+
+       if (unlikely((ref = get_free_entry()) == -1))
+               return -ENOSPC;
+
+       shared[ref].frame = 0;
+       shared[ref].domid = domid;
+       wmb();
+       shared[ref].flags = GTF_accept_transfer;
+
+       return ref;
 }
 
 void
 gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid)
 {
-    shared[ref].frame = 0;
-    shared[ref].domid = domid;
-    wmb();
-    shared[ref].flags = GTF_accept_transfer;
+       shared[ref].frame = 0;
+       shared[ref].domid = domid;
+       wmb();
+       shared[ref].flags = GTF_accept_transfer;
 }
 
 unsigned long
 gnttab_end_foreign_transfer_ref(grant_ref_t ref)
 {
-    unsigned long frame = 0;
-    u16           flags;
-
-    flags = shared[ref].flags;
-
-    /*
-     * If a transfer is committed then wait for the frame address to appear.
-     * Otherwise invalidate the grant entry against future use.
-     */
-    if ( likely(flags != GTF_accept_transfer) ||
-         (synch_cmpxchg(&shared[ref].flags, flags, 0) != GTF_accept_transfer) )
-        while ( unlikely((frame = shared[ref].frame) == 0) )
-            cpu_relax();
-
-    return frame;
+       unsigned long frame = 0;
+       u16           flags;
+
+       flags = shared[ref].flags;
+
+       /*
+        * If a transfer is committed then wait for the frame address to
+        * appear. Otherwise invalidate the grant entry against future use.
+        */
+       if (likely(flags != GTF_accept_transfer) ||
+           (synch_cmpxchg(&shared[ref].flags, flags, 0) !=
+            GTF_accept_transfer))
+               while (unlikely((frame = shared[ref].frame) == 0))
+                       cpu_relax();
+
+       return frame;
 }
 
 unsigned long
 gnttab_end_foreign_transfer(grant_ref_t ref)
 {
-    unsigned long frame = gnttab_end_foreign_transfer_ref(ref);
-    put_free_entry(ref);
-    return frame;
+       unsigned long frame = gnttab_end_foreign_transfer_ref(ref);
+       put_free_entry(ref);
+       return frame;
 }
 
 void
 gnttab_free_grant_reference(grant_ref_t ref)
 {
 
-    put_free_entry(ref);
+       put_free_entry(ref);
 }
 
 void
 gnttab_free_grant_references(grant_ref_t head)
 {
-    grant_ref_t ref;
-    unsigned long flags;
-    int count = 1;
-    if (head == GNTTAB_LIST_END)
-       return;
-    spin_lock_irqsave(&gnttab_list_lock, flags);
-    ref = head;
-    while (gnttab_list[ref] != GNTTAB_LIST_END) {
-       ref = gnttab_list[ref];
-       count++;
-    }
-    gnttab_list[ref] = gnttab_free_head;
-    gnttab_free_head = head;
-    gnttab_free_count += count;
-    check_free_callbacks();
-    spin_unlock_irqrestore(&gnttab_list_lock, flags);
+       grant_ref_t ref;
+       unsigned long flags;
+       int count = 1;
+       if (head == GNTTAB_LIST_END)
+               return;
+       spin_lock_irqsave(&gnttab_list_lock, flags);
+       ref = head;
+       while (gnttab_list[ref] != GNTTAB_LIST_END) {
+               ref = gnttab_list[ref];
+               count++;
+       }
+       gnttab_list[ref] = gnttab_free_head;
+       gnttab_free_head = head;
+       gnttab_free_count += count;
+       check_free_callbacks();
+       spin_unlock_irqrestore(&gnttab_list_lock, flags);
 }
 
 int
 gnttab_alloc_grant_references(u16 count, grant_ref_t *head)
 {
-    int h = get_free_entries(count);
-
-    if (h == -1)
-       return -ENOSPC;
-
-    *head = h;
-
-    return 0;
+       int h = get_free_entries(count);
+
+       if (h == -1)
+               return -ENOSPC;
+
+       *head = h;
+
+       return 0;
 }
 
 int
 gnttab_claim_grant_reference(grant_ref_t *private_head)
 {
-    grant_ref_t g = *private_head;
-    if (unlikely(g == GNTTAB_LIST_END))
-        return -ENOSPC;
-    *private_head = gnttab_list[g];
-    return g;
+       grant_ref_t g = *private_head;
+       if (unlikely(g == GNTTAB_LIST_END))
+               return -ENOSPC;
+       *private_head = gnttab_list[g];
+       return g;
 }
 
 void
 gnttab_release_grant_reference(grant_ref_t *private_head, grant_ref_t  release)
 {
-    gnttab_list[release] = *private_head;
-    *private_head = release;
+       gnttab_list[release] = *private_head;
+       *private_head = release;
 }
 
 void
 gnttab_request_free_callback(struct gnttab_free_callback *callback,
                             void (*fn)(void *), void *arg, u16 count)
 {
-    unsigned long flags;
-    spin_lock_irqsave(&gnttab_list_lock, flags);
-    if (callback->next)
-       goto out;
-    callback->fn = fn;
-    callback->arg = arg;
-    callback->count = count;
-    callback->next = gnttab_free_callback_list;
-    gnttab_free_callback_list = callback;
-    check_free_callbacks();
+       unsigned long flags;
+       spin_lock_irqsave(&gnttab_list_lock, flags);
+       if (callback->next)
+               goto out;
+       callback->fn = fn;
+       callback->arg = arg;
+       callback->count = count;
+       callback->next = gnttab_free_callback_list;
+       gnttab_free_callback_list = callback;
+       check_free_callbacks();
  out:
-    spin_unlock_irqrestore(&gnttab_list_lock, flags);
+       spin_unlock_irqrestore(&gnttab_list_lock, flags);
 }
 
 /*
@@ -323,79 +328,83 @@
 grant_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
            unsigned long data)
 {
-    int                     ret;
-    privcmd_hypercall_t     hypercall;
-
-    /* XXX Need safety checks here if using for anything other
-     *     than debugging */
-    return -ENOSYS;
-
-    if ( cmd != IOCTL_PRIVCMD_HYPERCALL )
-        return -ENOSYS;
-
-    if ( copy_from_user(&hypercall, (void *)data, sizeof(hypercall)) )
-        return -EFAULT;
-
-    if ( hypercall.op != __HYPERVISOR_grant_table_op )
-        return -ENOSYS;
-
-    /* hypercall-invoking asm taken from privcmd.c */
-    __asm__ __volatile__ (
-        "pushl %%ebx; pushl %%ecx; pushl %%edx; pushl %%esi; pushl %%edi; "
-        "movl  4(%%eax),%%ebx ;"
-        "movl  8(%%eax),%%ecx ;"
-        "movl 12(%%eax),%%edx ;"
-        "movl 16(%%eax),%%esi ;"
-        "movl 20(%%eax),%%edi ;"
-        "movl   (%%eax),%%eax ;"
-        TRAP_INSTR "; "
-        "popl %%edi; popl %%esi; popl %%edx; popl %%ecx; popl %%ebx"
-        : "=a" (ret) : "0" (&hypercall) : "memory" );
-
-    return ret;
+       int                     ret;
+       privcmd_hypercall_t     hypercall;
+
+       /*
+        * XXX Need safety checks here if using for anything other
+        *     than debugging.
+        */
+       return -ENOSYS;
+
+       if ( cmd != IOCTL_PRIVCMD_HYPERCALL )
+               return -ENOSYS;
+
+       if ( copy_from_user(&hypercall, (void *)data, sizeof(hypercall)) )
+               return -EFAULT;
+
+       if ( hypercall.op != __HYPERVISOR_grant_table_op )
+               return -ENOSYS;
+
+       /* hypercall-invoking asm taken from privcmd.c */
+       __asm__ __volatile__ (
+               "pushl %%ebx; pushl %%ecx; pushl %%edx; "
+               "pushl %%esi; pushl %%edi; "
+               "movl  4(%%eax),%%ebx ;"
+               "movl  8(%%eax),%%ecx ;"
+               "movl 12(%%eax),%%edx ;"
+               "movl 16(%%eax),%%esi ;"
+               "movl 20(%%eax),%%edi ;"
+               "movl   (%%eax),%%eax ;"
+               TRAP_INSTR "; "
+               "popl %%edi; popl %%esi; popl %%edx; popl %%ecx; popl %%ebx"
+               : "=a" (ret) : "0" (&hypercall) : "memory" );
+
+       return ret;
 }
 
 static struct file_operations grant_file_ops = {
-    ioctl:  grant_ioctl,
+       ioctl:  grant_ioctl,
 };
 
 static int
 grant_read(char *page, char **start, off_t off, int count, int *eof,
           void *data)
 {
-    int             len;
-    unsigned int    i;
-    grant_entry_t  *gt;
-
-    gt = (grant_entry_t *)shared;
-    len = 0;
-
-    for ( i = 0; i < NR_GRANT_ENTRIES; i++ )
-        /* TODO: safety catch here until this can handle >PAGE_SIZE output */
-        if (len > (PAGE_SIZE - 200))
-        {
-            len += sprintf( page + len, "Truncated.\n");
-            break;
-        }
-
-        if ( gt[i].flags )
-            len += sprintf( page + len,
-                    "Grant: ref (0x%x) flags (0x%hx) dom (0x%hx) frame 
(0x%x)\n", 
-                    i,
-                    gt[i].flags,
-                    gt[i].domid,
-                    gt[i].frame );
-
-    *eof = 1;
-    return len;
+       int             len;
+       unsigned int    i;
+       grant_entry_t  *gt;
+
+       gt = (grant_entry_t *)shared;
+       len = 0;
+
+       for (i = 0; i < NR_GRANT_ENTRIES; i++) {
+               if (len > (PAGE_SIZE - 200)) {
+                       len += sprintf( page + len, "Truncated.\n");
+                       break;
+               }
+       }
+
+       if (gt[i].flags) {
+               len += sprintf(page + len,
+                              "Grant: ref (0x%x) flags (0x%hx) "
+                              "dom (0x%hx) frame (0x%x)\n", 
+                              i,
+                              gt[i].flags,
+                              gt[i].domid,
+                              gt[i].frame );
+       }
+
+       *eof = 1;
+       return len;
 }
 
 static int
 grant_write(struct file *file, const char __user *buffer, unsigned long count,
            void *data)
 {
-    /* TODO: implement this */
-    return -ENOSYS;
+       /* TODO: implement this */
+       return -ENOSYS;
 }
 
 #endif /* CONFIG_PROC_FS */
@@ -403,70 +412,81 @@
 int
 gnttab_resume(void)
 {
-    gnttab_setup_table_t setup;
-    unsigned long        frames[NR_GRANT_FRAMES];
-    int                  i;
-
-    setup.dom        = DOMID_SELF;
-    setup.nr_frames  = NR_GRANT_FRAMES;
-    setup.frame_list = frames;
-
-    BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1) != 0);
-    BUG_ON(setup.status != 0);
-
-    for ( i = 0; i < NR_GRANT_FRAMES; i++ )
-        set_fixmap(FIX_GNTTAB_END - i, frames[i] << PAGE_SHIFT);
-
-    return 0;
+       gnttab_setup_table_t setup;
+       unsigned long        frames[NR_GRANT_FRAMES];
+       int                  i;
+
+       setup.dom        = DOMID_SELF;
+       setup.nr_frames  = NR_GRANT_FRAMES;
+       setup.frame_list = frames;
+
+       BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1));
+       BUG_ON(setup.status != 0);
+
+       for (i = 0; i < NR_GRANT_FRAMES; i++)
+               set_fixmap(FIX_GNTTAB_END - i, frames[i] << PAGE_SHIFT);
+
+       return 0;
 }
 
 int
 gnttab_suspend(void)
 {
-    int i;
-
-    for ( i = 0; i < NR_GRANT_FRAMES; i++ )
-       clear_fixmap(FIX_GNTTAB_END - i);
-
-    return 0;
+       int i;
+
+       for (i = 0; i < NR_GRANT_FRAMES; i++)
+               clear_fixmap(FIX_GNTTAB_END - i);
+
+       return 0;
 }
 
 static int __init
 gnttab_init(void)
 {
-    int i;
-
-    if (xen_init() < 0)
-        return -ENODEV;
-
-    BUG_ON(gnttab_resume());
-
-    shared = (grant_entry_t *)fix_to_virt(FIX_GNTTAB_END);
-
-    for ( i = 0; i < NR_GRANT_ENTRIES; i++ )
-        gnttab_list[i] = i + 1;
-    
+       int i;
+
+       if (xen_init() < 0)
+               return -ENODEV;
+
+       BUG_ON(gnttab_resume());
+
+       shared = (grant_entry_t *)fix_to_virt(FIX_GNTTAB_END);
+
+       for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++)
+               gnttab_list[i] = i + 1;
+       gnttab_free_count = NR_GRANT_ENTRIES - NR_RESERVED_ENTRIES;
+       gnttab_free_head  = NR_RESERVED_ENTRIES;
+
 #ifdef CONFIG_PROC_FS
-    /*
-     *  /proc/xen/grant : used by libxc to access grant tables
-     */
-    if ( (grant_pde = create_xen_proc_entry("grant", 0600)) == NULL )
-    {
-        WPRINTK("Unable to create grant xen proc entry\n");
-        return -1;
-    }
-
-    grant_file_ops.read   = grant_pde->proc_fops->read;
-    grant_file_ops.write  = grant_pde->proc_fops->write;
-
-    grant_pde->proc_fops  = &grant_file_ops;
-
-    grant_pde->read_proc  = &grant_read;
-    grant_pde->write_proc = &grant_write;
+       /*
+        *  /proc/xen/grant : used by libxc to access grant tables
+        */
+       if ((grant_pde = create_xen_proc_entry("grant", 0600)) == NULL) {
+               WPRINTK("Unable to create grant xen proc entry\n");
+               return -1;
+       }
+
+       grant_file_ops.read   = grant_pde->proc_fops->read;
+       grant_file_ops.write  = grant_pde->proc_fops->write;
+
+       grant_pde->proc_fops  = &grant_file_ops;
+
+       grant_pde->read_proc  = &grant_read;
+       grant_pde->write_proc = &grant_write;
 #endif
 
-    printk("Grant table initialized\n");
-    return 0;
+       printk("Grant table initialized\n");
+       return 0;
 }
 
 __initcall(gnttab_init);
+
+/*
+ * Local variables:
+ *  c-file-style: "linux"
+ *  indent-tabs-mode: t
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff -r 4e1031ce3bc2 -r 5e5ae8340956 
linux-2.6-xen-sparse/arch/xen/x86_64/mm/fault.c
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/mm/fault.c   Mon Sep 26 17:15:55 2005
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/mm/fault.c   Wed Sep 28 20:06:49 2005
@@ -149,7 +149,9 @@
        pmd_t *pmd;
        pte_t *pte;
 
+       preempt_disable();
        pgd = (pgd_t *)per_cpu(cur_pgd, smp_processor_id());
+       preempt_enable();
        pgd += pgd_index(address);
 
        printk("PGD %lx ", pgd_val(*pgd));
@@ -252,7 +254,9 @@
 
        /* On Xen the line below does not always work. Needs investigating! */
        /*pgd = pgd_offset(current->mm ?: &init_mm, address);*/
+       preempt_disable();
        pgd = (pgd_t *)per_cpu(cur_pgd, smp_processor_id());
+       preempt_enable();
        pgd += pgd_index(address);
 
        pgd_ref = pgd_offset_k(address);
diff -r 4e1031ce3bc2 -r 5e5ae8340956 
linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Mon Sep 26 17:15:55 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Wed Sep 28 20:06:49 2005
@@ -80,6 +80,15 @@
                return;
        }
 
+       /* Map the shared frame, irq etc. */
+       err = blkif_map(be->blkif, ring_ref, evtchn);
+       if (err) {
+               xenbus_dev_error(be->dev, err, "mapping ring-ref %lu port %u",
+                                ring_ref, evtchn);
+               return;
+       }
+       /* XXX From here on should 'blkif_unmap' on error. */
+
 again:
        /* Supply the information about the device the frontend needs */
        err = xenbus_transaction_start();
@@ -109,14 +118,6 @@
        if (err) {
                xenbus_dev_error(be->dev, err, "writing %s/sector-size",
                                 be->dev->nodename);
-               goto abort;
-       }
-
-       /* Map the shared frame, irq etc. */
-       err = blkif_map(be->blkif, ring_ref, evtchn);
-       if (err) {
-               xenbus_dev_error(be->dev, err, "mapping ring-ref %lu port %u",
-                                ring_ref, evtchn);
                goto abort;
        }
 
diff -r 4e1031ce3bc2 -r 5e5ae8340956 
linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c      Mon Sep 26 
17:15:55 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c      Wed Sep 28 
20:06:49 2005
@@ -57,10 +57,7 @@
 
 #define MAXIMUM_OUTSTANDING_BLOCK_REQS \
     (BLKIF_MAX_SEGMENTS_PER_REQUEST * BLKIF_RING_SIZE)
-#define GRANTREF_INVALID (1<<15)
-#define GRANT_INVALID_REF      (0xFFFF)
-
-static int recovery = 0; /* Recovery in progress: protected by blkif_io_lock */
+#define GRANT_INVALID_REF      0
 
 static void kick_pending_request_queues(struct blkfront_info *info);
 
@@ -82,18 +79,6 @@
        info->shadow[id].req.id  = info->shadow_free;
        info->shadow[id].request = 0;
        info->shadow_free = id;
-}
-
-static inline void pickle_request(struct blk_shadow *s, blkif_request_t *r)
-{
-
-       s->req = *r;
-}
-
-static inline void unpickle_request(blkif_request_t *r, struct blk_shadow *s)
-{
-
-       *r = s->req;
 }
 
 static inline void flush_requests(struct blkfront_info *info)
@@ -235,7 +220,7 @@
                                rq_data_dir(req) );
 
                        info->shadow[id].frame[ring_req->nr_segments] =
-                               buffer_mfn;
+                               mfn_to_pfn(buffer_mfn);
 
                        ring_req->frame_and_sects[ring_req->nr_segments] =
                                blkif_fas_from_gref(ref, fsect, lsect);
@@ -247,7 +232,7 @@
        info->ring.req_prod_pvt++;
 
        /* Keep a private copy so we can reissue requests when recovering. */
-       pickle_request(&info->shadow[id], ring_req);
+       info->shadow[id].req = *ring_req;
 
        gnttab_free_grant_references(gref_head);
 
@@ -312,7 +297,7 @@
 
        spin_lock_irqsave(&blkif_io_lock, flags);
 
-       if (unlikely(info->connected != BLKIF_STATE_CONNECTED || recovery)) {
+       if (unlikely(info->connected != BLKIF_STATE_CONNECTED)) {
                spin_unlock_irqrestore(&blkif_io_lock, flags);
                return IRQ_HANDLED;
        }
@@ -401,36 +386,30 @@
                if (copy[i].request == 0)
                        continue;
 
-               /* Grab a request slot and unpickle shadow state into it. */
+               /* Grab a request slot and copy shadow state into it. */
                req = RING_GET_REQUEST(
                        &info->ring, info->ring.req_prod_pvt);
-               unpickle_request(req, &copy[i]);
+               *req = copy[i].req;
 
                /* We get a new request id, and must reset the shadow state. */
                req->id = GET_ID_FROM_FREELIST(info);
                memcpy(&info->shadow[req->id], &copy[i], sizeof(copy[i]));
 
                /* Rewrite any grant references invalidated by susp/resume. */
-               for (j = 0; j < req->nr_segments; j++) {
-                       if ( req->frame_and_sects[j] & GRANTREF_INVALID )
-                               gnttab_grant_foreign_access_ref(
-                                       blkif_gref_from_fas(
-                                               req->frame_and_sects[j]),
-                                       info->backend_id,
-                                       info->shadow[req->id].frame[j],
-                                       rq_data_dir(
-                                               (struct request *)
-                                               info->shadow[req->id].request));
-                       req->frame_and_sects[j] &= ~GRANTREF_INVALID;
-               }
+               for (j = 0; j < req->nr_segments; j++)
+                       gnttab_grant_foreign_access_ref(
+                               blkif_gref_from_fas(req->frame_and_sects[j]),
+                               info->backend_id,
+                               pfn_to_mfn(info->shadow[req->id].frame[j]),
+                               rq_data_dir(
+                                       (struct request *)
+                                       info->shadow[req->id].request));
                info->shadow[req->id].req = *req;
 
                info->ring.req_prod_pvt++;
        }
 
        kfree(copy);
-
-       recovery = 0;
 
        /* info->ring->req_prod will be set when we flush_requests().*/
        wmb();
@@ -438,7 +417,7 @@
        /* Kicks things back into life. */
        flush_requests(info);
 
-       /* Now safe to left other people use the interface. */
+       /* Now safe to let other people use the interface. */
        info->connected = BLKIF_STATE_CONNECTED;
 }
 
@@ -591,17 +570,6 @@
                goto abort_transaction;
        }
 
-       info->backend = backend;
-       backend = NULL;
-
-       info->watch.node = info->backend;
-       info->watch.callback = watch_for_status;
-       err = register_xenbus_watch(&info->watch);
-       if (err) {
-               message = "registering watch on backend";
-               goto abort_transaction;
-       }
-
        err = xenbus_transaction_end(0);
        if (err) {
                if (err == -EAGAIN)
@@ -610,10 +578,17 @@
                goto destroy_blkring;
        }
 
- out:
-       if (backend)
-               kfree(backend);
-       return err;
+       info->watch.node = backend;
+       info->watch.callback = watch_for_status;
+       err = register_xenbus_watch(&info->watch);
+       if (err) {
+               message = "registering watch on backend";
+               goto destroy_blkring;
+       }
+
+       info->backend = backend;
+
+       return 0;
 
  abort_transaction:
        xenbus_transaction_end(1);
@@ -621,7 +596,10 @@
        xenbus_dev_error(dev, err, "%s", message);
  destroy_blkring:
        blkif_free(info);
-       goto out;
+ out:
+       if (backend)
+               kfree(backend);
+       return err;
 }
 
 /* Setup supplies the backend dir, virtual device.
@@ -702,7 +680,6 @@
        kfree(info->backend);
        info->backend = NULL;
 
-       recovery = 1;
        blkif_free(info);
 
        return 0;
diff -r 4e1031ce3bc2 -r 5e5ae8340956 
linux-2.6-xen-sparse/drivers/xen/netback/common.h
--- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h Mon Sep 26 17:15:55 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h Wed Sep 28 20:06:49 2005
@@ -21,8 +21,6 @@
 #include <asm-xen/xen-public/grant_table.h>
 #include <asm-xen/gnttab.h>
 #include <asm-xen/driver_util.h>
-
-#define GRANT_INVALID_REF (0xFFFF)
 
 #if 0
 #define ASSERT(_p) \
diff -r 4e1031ce3bc2 -r 5e5ae8340956 
linux-2.6-xen-sparse/drivers/xen/netback/netback.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c        Mon Sep 26 
17:15:55 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c        Wed Sep 28 
20:06:49 2005
@@ -434,7 +434,6 @@
                gop->host_addr    = MMAP_VADDR(pending_idx);
                gop->dev_bus_addr = 0;
                gop->handle       = grant_tx_ref[pending_idx];
-               grant_tx_ref[pending_idx] = GRANT_INVALID_REF;
                gop++;
        }
        BUG_ON(HYPERVISOR_grant_table_op(
diff -r 4e1031ce3bc2 -r 5e5ae8340956 
linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c      Mon Sep 26 
17:15:55 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c      Wed Sep 28 
20:06:49 2005
@@ -1,7 +1,7 @@
 /******************************************************************************
  * Virtual network driver for conversing with remote driver backends.
  * 
- * Copyright (c) 2002-2004, K A Fraser
+ * Copyright (c) 2002-2005, K A Fraser
  * 
  * This file may be distributed separately from the Linux kernel, or
  * incorporated into other software packages, subject to the following license:
@@ -57,7 +57,7 @@
 #include <asm-xen/xen-public/grant_table.h>
 #include <asm-xen/gnttab.h>
 
-#define GRANT_INVALID_REF      (0xFFFF)
+#define GRANT_INVALID_REF      0
 
 #ifndef __GFP_NOWARN
 #define __GFP_NOWARN 0
@@ -700,6 +700,7 @@
        struct net_private *np;
        int i, requeue_idx;
        netif_tx_request_t *tx;
+       struct sk_buff *skb;
 
        np = netdev_priv(dev);
        spin_lock_irq(&np->tx_lock);
@@ -711,7 +712,8 @@
        np->rx_resp_cons = np->tx_resp_cons = np->tx_full = 0;
        np->rx->event = np->tx->event = 1;
 
-       /* Step 2: Rebuild the RX and TX ring contents.
+       /*
+        * Step 2: Rebuild the RX and TX ring contents.
         * NB. We could just free the queued TX packets now but we hope
         * that sending them out might do some good.  We have to rebuild
         * the RX ring because some of our pages are currently flipped out
@@ -722,49 +724,52 @@
         * them.
         */
 
-       /* Rebuild the TX buffer freelist and the TX ring itself.
+       /*
+        * Rebuild the TX buffer freelist and the TX ring itself.
         * NB. This reorders packets.  We could keep more private state
         * to avoid this but maybe it doesn't matter so much given the
         * interface has been down.
         */
        for (requeue_idx = 0, i = 1; i <= NETIF_TX_RING_SIZE; i++) {
-               if ((unsigned long)np->tx_skbs[i] >= __PAGE_OFFSET) {
-                       struct sk_buff *skb = np->tx_skbs[i];
-
-                       tx = &np->tx->ring[requeue_idx++].req;
-
-                       tx->id   = i;
-                       gnttab_grant_foreign_access_ref(
-                               np->grant_tx_ref[i], np->backend_id, 
-                               virt_to_mfn(np->tx_skbs[i]->data),
-                               GNTMAP_readonly); 
-                       tx->gref = np->grant_tx_ref[i];
-                       tx->offset = (unsigned long)skb->data & ~PAGE_MASK;
-                       tx->size = skb->len;
-
-                       np->stats.tx_bytes += skb->len;
-                       np->stats.tx_packets++;
-               }
+               if ((unsigned long)np->tx_skbs[i] < __PAGE_OFFSET)
+                       continue;
+
+               skb = np->tx_skbs[i];
+
+               tx = &np->tx->ring[requeue_idx++].req;
+
+               tx->id = i;
+               gnttab_grant_foreign_access_ref(
+                       np->grant_tx_ref[i], np->backend_id, 
+                       virt_to_mfn(np->tx_skbs[i]->data),
+                       GNTMAP_readonly); 
+               tx->gref = np->grant_tx_ref[i];
+               tx->offset = (unsigned long)skb->data & ~PAGE_MASK;
+               tx->size = skb->len;
+               tx->csum_blank = (skb->ip_summed == CHECKSUM_HW);
+
+               np->stats.tx_bytes += skb->len;
+               np->stats.tx_packets++;
        }
        wmb();
        np->tx->req_prod = requeue_idx;
 
        /* Rebuild the RX buffer freelist and the RX ring itself. */
        for (requeue_idx = 0, i = 1; i <= NETIF_RX_RING_SIZE; i++) { 
-               if ((unsigned long)np->rx_skbs[i] >= __PAGE_OFFSET) {
-                       gnttab_grant_foreign_transfer_ref(
-                               np->grant_rx_ref[i], np->backend_id);
-                       np->rx->ring[requeue_idx].req.gref =
-                               np->grant_rx_ref[i];
-                       np->rx->ring[requeue_idx].req.id = i;
-                       requeue_idx++; 
-               }
-       }
-
+               if ((unsigned long)np->rx_skbs[i] < __PAGE_OFFSET)
+                       continue;
+               gnttab_grant_foreign_transfer_ref(
+                       np->grant_rx_ref[i], np->backend_id);
+               np->rx->ring[requeue_idx].req.gref =
+                       np->grant_rx_ref[i];
+               np->rx->ring[requeue_idx].req.id = i;
+               requeue_idx++; 
+       }
        wmb();                
        np->rx->req_prod = requeue_idx;
 
-       /* Step 3: All public and private state should now be sane.  Get
+       /*
+        * Step 3: All public and private state should now be sane.  Get
         * ready to start sending and receiving packets and give the driver
         * domain a kick because we've probably just requeued some
         * packets.
@@ -798,7 +803,8 @@
 #endif
 }
 
-/* Move the vif into connected state.
+/*
+ * Move the vif into connected state.
  * Sets the mac and event channel from the message.
  * Binds the irq to the event channel.
  */
@@ -1053,8 +1059,7 @@
        info->evtchn = 0;
 }
 
-/* Stop network device and free tx/rx queues and irq.
- */
+/* Stop network device and free tx/rx queues and irq. */
 static void shutdown_device(struct net_private *np)
 {
        /* Stop old i/f to prevent errors whilst we rebuild the state. */
@@ -1148,17 +1153,6 @@
                goto abort_transaction;
        }
 
-       info->backend = backend;
-       backend = NULL;
-
-       info->watch.node = info->backend;
-       info->watch.callback = watch_for_status;
-       err = register_xenbus_watch(&info->watch);
-       if (err) {
-               message = "registering watch on backend";
-               goto abort_transaction;
-       }
-
        err = xenbus_transaction_end(0);
        if (err) {
                if (err == -EAGAIN)
@@ -1167,12 +1161,19 @@
                goto destroy_ring;
        }
 
+       info->watch.node = backend;
+       info->watch.callback = watch_for_status;
+       err = register_xenbus_watch(&info->watch);
+       if (err) {
+               message = "registering watch on backend";
+               goto destroy_ring;
+       }
+
+       info->backend = backend;
+
        netif_state = NETIF_STATE_CONNECTED;
 
- out:
-       if (backend)
-               kfree(backend);
-       return err;
+       return 0;
 
  abort_transaction:
        xenbus_transaction_end(1);
@@ -1180,13 +1181,17 @@
        xenbus_dev_error(dev, err, "%s", message);
  destroy_ring:
        shutdown_device(info);
-       goto out;
-}
-
-/* Setup supplies the backend dir, virtual device.
-
-   We place an event channel and shared frame entries.
-   We watch backend to wait if it's ok. */
+ out:
+       if (backend)
+               kfree(backend);
+       return err;
+}
+
+/*
+ * Setup supplies the backend dir, virtual device.
+ * We place an event channel and shared frame entries.
+ * We watch backend to wait if it's ok.
+ */
 static int netfront_probe(struct xenbus_device *dev,
                          const struct xenbus_device_id *id)
 {
diff -r 4e1031ce3bc2 -r 5e5ae8340956 
linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Mon Sep 26 17:15:55 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Wed Sep 28 20:06:49 2005
@@ -88,6 +88,26 @@
                return;
        }
 
+       err = tpmif_map(be->tpmif, ringref, evtchn);
+       if (err) {
+               xenbus_dev_error(be->dev, err,
+                                "mapping shared-frame %lu port %u",
+                                ringref, evtchn);
+               return;
+       }
+
+       err = tpmif_vtpm_open(be->tpmif,
+                             be->frontend_id,
+                             be->instance);
+       if (err) {
+               xenbus_dev_error(be->dev, err,
+                                "queueing vtpm open packet");
+               /*
+                * Should close down this device and notify FE
+                * about closure.
+                */
+               return;
+       }
 
        /*
         * Tell the front-end that we are ready to go -
@@ -104,27 +124,6 @@
                            "ready", "%lu", ready);
        if (err) {
                xenbus_dev_error(be->dev, err, "writing 'ready'");
-               goto abort;
-       }
-
-       err = tpmif_map(be->tpmif, ringref, evtchn);
-       if (err) {
-               xenbus_dev_error(be->dev, err,
-                                "mapping shared-frame %lu port %u",
-                                ringref, evtchn);
-               goto abort;
-       }
-
-       err = tpmif_vtpm_open(be->tpmif,
-                             be->frontend_id,
-                             be->instance);
-       if (err) {
-               xenbus_dev_error(be->dev, err,
-                                "queueing vtpm open packet");
-               /*
-                * Should close down this device and notify FE
-                * about closure.
-                */
                goto abort;
        }
 
diff -r 4e1031ce3bc2 -r 5e5ae8340956 
linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c      Mon Sep 26 
17:15:55 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c      Wed Sep 28 
20:06:49 2005
@@ -352,17 +352,6 @@
                goto abort_transaction;
        }
 
-       info->backend = backend;
-       backend = NULL;
-
-       info->watch.node = info->backend;
-       info->watch.callback = watch_for_status;
-       err = register_xenbus_watch(&info->watch);
-       if (err) {
-               message = "registering watch on backend";
-               goto abort_transaction;
-       }
-
        err = xenbus_transaction_end(0);
        if (err == -EAGAIN)
                goto again;
@@ -371,10 +360,17 @@
                goto destroy_tpmring;
        }
 
-out:
-       if (backend)
-               kfree(backend);
-       return err;
+       info->watch.node = backend;
+       info->watch.callback = watch_for_status;
+       err = register_xenbus_watch(&info->watch);
+       if (err) {
+               message = "registering watch on backend";
+               goto destroy_tpmring;
+       }
+
+       info->backend = backend;
+
+       return 0;
 
 abort_transaction:
        xenbus_transaction_end(1);
@@ -382,7 +378,10 @@
        xenbus_dev_error(dev, err, "%s", message);
 destroy_tpmring:
        destroy_tpmring(info, &my_private);
-       goto out;
+out:
+       if (backend)
+               kfree(backend);
+       return err;
 }
 
 
diff -r 4e1031ce3bc2 -r 5e5ae8340956 tools/console/daemon/io.c
--- a/tools/console/daemon/io.c Mon Sep 26 17:15:55 2005
+++ b/tools/console/daemon/io.c Wed Sep 28 20:06:49 2005
@@ -399,7 +399,7 @@
 
        while (xc_domain_getinfo(xc, domid, 1, &dominfo) == 1) {
                dom = lookup_domain(dominfo.domid);
-               if (dominfo.dying || dominfo.crashed || dominfo.shutdown) {
+               if (dominfo.dying) {
                        if (dom)
                                shutdown_domain(dom);
                } else {
diff -r 4e1031ce3bc2 -r 5e5ae8340956 tools/firmware/vmxassist/gen.c
--- a/tools/firmware/vmxassist/gen.c    Mon Sep 26 17:15:55 2005
+++ b/tools/firmware/vmxassist/gen.c    Wed Sep 28 20:06:49 2005
@@ -23,7 +23,7 @@
 #include <vm86.h>
 
 int
-main()
+main(void)
 {
        printf("/* MACHINE GENERATED; DO NOT EDIT */\n");
        printf("#define VMX_ASSIST_CTX_GS_SEL   0x%x\n",
diff -r 4e1031ce3bc2 -r 5e5ae8340956 tools/firmware/vmxassist/head.S
--- a/tools/firmware/vmxassist/head.S   Mon Sep 26 17:15:55 2005
+++ b/tools/firmware/vmxassist/head.S   Wed Sep 28 20:06:49 2005
@@ -110,6 +110,10 @@
 _start:
        cli
 
+       /* save register parameters to C land */
+       movl    %edx, booting_cpu
+       movl    %ebx, booting_vector
+
        /* clear bss */
        cld
        xorb    %al, %al
@@ -128,7 +132,6 @@
        /* go ... */
        call    main
        jmp     halt
-
 
 /*
  * Something bad happened, print invoking %eip and loop forever
diff -r 4e1031ce3bc2 -r 5e5ae8340956 tools/firmware/vmxassist/setup.c
--- a/tools/firmware/vmxassist/setup.c  Mon Sep 26 17:15:55 2005
+++ b/tools/firmware/vmxassist/setup.c  Wed Sep 28 20:06:49 2005
@@ -29,6 +29,9 @@
 
 #define        min(a, b)       ((a) > (b) ? (b) : (a))
 
+/* Which CPU are we booting, and what is the initial CS segment? */
+int booting_cpu, booting_vector;
+
 unsigned long long gdt[] __attribute__ ((aligned(32))) = {
        0x0000000000000000ULL,          /* 0x00: reserved */
        0x0000890000000000ULL,          /* 0x08: 32-bit TSS */
@@ -201,12 +204,17 @@
                initialize_real_mode = 0;
                regs->eflags |= EFLAGS_VM | 0x02;
                regs->ves = regs->vds = regs->vfs = regs->vgs = 0xF000;
-               regs->cs = 0xF000; /* ROM BIOS POST entry point */
-#ifdef TEST
-               regs->eip = 0xFFE0;
+               if (booting_cpu == 0) {
+                       regs->cs = 0xF000; /* ROM BIOS POST entry point */
+#ifdef TEST
+                       regs->eip = 0xFFE0;
 #else
-               regs->eip = 0xFFF0;
-#endif
+                       regs->eip = 0xFFF0;
+#endif
+               } else {
+                       regs->cs = booting_vector << 8; /* AP entry point */
+                       regs->eip = 0;
+               }
                regs->uesp = 0;
                regs->uss = 0;
                printf("Starting emulated 16-bit real-mode: ip=%04x:%04x\n",
@@ -215,8 +223,8 @@
                mode = VM86_REAL; /* becomes previous mode */
                set_mode(regs, VM86_REAL);
 
-                /* this should get us into 16-bit mode */
-                return;
+               /* this should get us into 16-bit mode */
+               return;
        } else {
                /* go from protected to real mode */
                regs->eflags |= EFLAGS_VM;
@@ -334,7 +342,12 @@
 {
        unsigned long cr0;
 
-       printf("Start BIOS ...\n");
+       if (booting_cpu == 0)
+               printf("Start BIOS ...\n");
+       else
+               printf("Start AP %d from %08x ...\n",
+                      booting_cpu, booting_vector << 12);
+
        initialize_real_mode = 1;
        cr0 = get_cr0();
 #ifndef TEST
@@ -345,20 +358,28 @@
 }
 
 int
-main()
-{
-       banner();
+main(void)
+{
+       if (booting_cpu == 0)
+               banner();
+
 #ifdef TEST
        setup_paging();
 #endif
+
        setup_gdt();
        setup_idt();
+
 #ifndef        TEST
-       set_cr4(get_cr4() | CR4_VME); 
-#endif
+       set_cr4(get_cr4() | CR4_VME);
+#endif
+
        setup_ctx();
-       setup_pic();
+
+       if (booting_cpu == 0)
+               setup_pic();
+
        start_bios();
+
        return 0;
 }
-
diff -r 4e1031ce3bc2 -r 5e5ae8340956 tools/firmware/vmxassist/vm86.c
--- a/tools/firmware/vmxassist/vm86.c   Mon Sep 26 17:15:55 2005
+++ b/tools/firmware/vmxassist/vm86.c   Wed Sep 28 20:06:49 2005
@@ -752,6 +752,9 @@
                                        goto invalid;
                                }
                                break;
+                       case 0x09: /* wbinvd */
+                               asm volatile ( "wbinvd" );
+                               return OPC_EMULATED;
                        case 0x20: /* mov Rd, Cd (1h) */
                        case 0x22:
                                if (!movcr(regs, prefix, opc))
diff -r 4e1031ce3bc2 -r 5e5ae8340956 tools/firmware/vmxassist/vmxloader.c
--- a/tools/firmware/vmxassist/vmxloader.c      Mon Sep 26 17:15:55 2005
+++ b/tools/firmware/vmxassist/vmxloader.c      Wed Sep 28 20:06:49 2005
@@ -132,11 +132,12 @@
                 memcpy((void *)ACPI_PHYSICAL_ADDRESS, acpi, sizeof(acpi));
        }
 #endif
-                       
+
        puts("Loading VMXAssist ...\n");
        memcpy((void *)TEXTADDR, vmxassist, sizeof(vmxassist));
+
        puts("Go ...\n");
-       ((void (*)())TEXTADDR)();
+       asm volatile ( "jmp *%%eax" : : "a" (TEXTADDR), "d" (0) );
+
        return 0;
 }
-
diff -r 4e1031ce3bc2 -r 5e5ae8340956 tools/ioemu/vl.c
--- a/tools/ioemu/vl.c  Mon Sep 26 17:15:55 2005
+++ b/tools/ioemu/vl.c  Wed Sep 28 20:06:49 2005
@@ -2385,7 +2385,8 @@
 setup_mapping(int xc_handle, u32 dom, unsigned long toptab, unsigned long  
*mem_page_array, unsigned long *page_table_array, unsigned long v_start, 
unsigned long v_end)
 {
     l1_pgentry_t *vl1tab=NULL, *vl1e=NULL;
-    l2_pgentry_t *vl2tab[4], *vl2e=NULL, *vl2_table = NULL;
+    l2_pgentry_t *vl2tab[4] = {NULL, NULL, NULL, NULL};
+    l2_pgentry_t *vl2e=NULL, *vl2_table = NULL;
     unsigned long l1tab;
     unsigned long ppt_alloc = 0;
     unsigned long count;
diff -r 4e1031ce3bc2 -r 5e5ae8340956 tools/python/xen/web/SrvBase.py
--- a/tools/python/xen/web/SrvBase.py   Mon Sep 26 17:15:55 2005
+++ b/tools/python/xen/web/SrvBase.py   Wed Sep 28 20:06:49 2005
@@ -81,7 +81,14 @@
             req.write("Operation not implemented: " + op)
             return ''
         else:
-            return op_method(op, req)
+            try:
+                return op_method(op, req)
+            except Exception, exn:
+                log.exception("Request %s failed.", op)
+                if req.useSxp():
+                    return ['xend.err', "Exception: " + str(exn)]
+                else:
+                    return "<p>%s</p>" % str(exn)
 
     def print_path(self, req):
         """Print the path with hyperlinks.
diff -r 4e1031ce3bc2 -r 5e5ae8340956 tools/python/xen/web/http.py
--- a/tools/python/xen/web/http.py      Mon Sep 26 17:15:55 2005
+++ b/tools/python/xen/web/http.py      Wed Sep 28 20:06:49 2005
@@ -22,6 +22,7 @@
 from  mimetools import Message
 from cStringIO import StringIO
 import math
+import socket
 import time
 import cgi
 
diff -r 4e1031ce3bc2 -r 5e5ae8340956 tools/python/xen/xend/PrettyPrint.py
--- a/tools/python/xen/xend/PrettyPrint.py      Mon Sep 26 17:15:55 2005
+++ b/tools/python/xen/xend/PrettyPrint.py      Wed Sep 28 20:06:49 2005
@@ -39,9 +39,9 @@
         print '***PrettyItem>output>', self
         pass
 
-    def prettyprint(self, _, width):
+    def prettyprint(self, _):
         print '***PrettyItem>prettyprint>', self
-        return width
+        return self.width
 
 class PrettyString(PrettyItem):
 
@@ -52,7 +52,7 @@
     def output(self, out):
         out.write(self.value)
 
-    def prettyprint(self, line, _):
+    def prettyprint(self, line):
         line.output(self)
 
     def show(self, out):
@@ -63,7 +63,7 @@
     def output(self, out):
         out.write(' ' * self.width)
 
-    def prettyprint(self, line, _):
+    def prettyprint(self, line):
         line.output(self)
 
     def show(self, out):
@@ -80,7 +80,7 @@
     def output(self, out):
         out.write(' ' * self.width)
 
-    def prettyprint(self, line, _):
+    def prettyprint(self, line):
         if line.breaks(self.space):
             self.active = 1
             line.newline(self.indent)
@@ -97,7 +97,7 @@
         block.newline()
         block.addtoline(self)
 
-    def prettyprint(self, line, _):
+    def prettyprint(self, line):
         line.newline(0)
         line.output(self)
 
@@ -127,7 +127,7 @@
             lastbreak.space = (width - lastwidth)
         self.width = width
  
-    def prettyprint(self, line, _):
+    def prettyprint(self, line):
         for x in self.content:
             x.prettyprint(line)
 
@@ -168,7 +168,7 @@
     def addtoline(self, x):
         self.lines[-1].write(x)
 
-    def prettyprint(self, line, _):
+    def prettyprint(self, line):
         self.indent = line.used
         line.block = self
         if not line.fits(self.width):
@@ -252,7 +252,7 @@
         self.block = self.block.parent
 
     def prettyprint(self, out=sys.stdout):
-        self.top.prettyprint(Line(out, self.width), self.width)
+        self.top.prettyprint(Line(out, self.width))
 
 class SXPPrettyPrinter(PrettyPrinter):
     """An SXP prettyprinter.
diff -r 4e1031ce3bc2 -r 5e5ae8340956 tools/python/xen/xend/XendCheckpoint.py
--- a/tools/python/xen/xend/XendCheckpoint.py   Mon Sep 26 17:15:55 2005
+++ b/tools/python/xen/xend/XendCheckpoint.py   Wed Sep 28 20:06:49 2005
@@ -10,8 +10,12 @@
 import sxp
 from string import join
 from struct import pack, unpack, calcsize
+
 from xen.util.xpopen import xPopen3
+
 import xen.lowlevel.xc
+
+import XendDomainInfo
 from xen.xend.xenstore.xsutil import IntroduceDomain
 
 from XendError import XendError
@@ -74,7 +78,7 @@
                 if l.rstrip() == "suspend":
                     log.info("suspending %d" % dominfo.domid)
                     xd.domain_shutdown(dominfo.domid, reason='suspend')
-                    dominfo.state_wait("suspended")
+                    dominfo.state_wait(XendDomainInfo.STATE_VM_SUSPENDED)
                     log.info("suspend %d done" % dominfo.domid)
                     child.tochild.write("done\n")
                     child.tochild.flush()
diff -r 4e1031ce3bc2 -r 5e5ae8340956 tools/python/xen/xend/XendClient.py
--- a/tools/python/xen/xend/XendClient.py       Mon Sep 26 17:15:55 2005
+++ b/tools/python/xen/xend/XendClient.py       Wed Sep 28 20:06:49 2005
@@ -302,12 +302,6 @@
                              {'op'      : 'devices',
                               'type'    : type })
 
-    def xend_domain_device(self, id, type, idx):
-        return self.xendPost(self.domainurl(id),
-                             {'op'      : 'device',
-                              'type'    : type,
-                              'idx'     : idx })
-    
     def xend_domain_device_create(self, id, config):
         return self.xendPost(self.domainurl(id),
                              {'op'      : 'device_create',
diff -r 4e1031ce3bc2 -r 5e5ae8340956 tools/python/xen/xend/XendDomain.py
--- a/tools/python/xen/xend/XendDomain.py       Mon Sep 26 17:15:55 2005
+++ b/tools/python/xen/xend/XendDomain.py       Wed Sep 28 20:06:49 2005
@@ -28,16 +28,11 @@
 from xen.xend import sxp
 from xen.xend import XendRoot
 from xen.xend import XendCheckpoint
-from xen.xend.XendDomainInfo import XendDomainInfo, shutdown_reason
+from xen.xend.XendDomainInfo import XendDomainInfo
 from xen.xend import EventServer
 from xen.xend.XendError import XendError
 from xen.xend.XendLogging import log
-from xen.xend import scheduler
 from xen.xend.server import relocate
-from xen.xend.uuid import getUuid
-from xen.xend.xenstore import XenNode, DBMap
-from xen.xend.xenstore.xstransact import xstransact
-from xen.xend.xenstore.xsutil import GetDomainPath
 
 
 xc = xen.lowlevel.xc.new()
@@ -47,14 +42,7 @@
 
 __all__ = [ "XendDomain" ]
 
-SHUTDOWN_TIMEOUT = 30
-PRIV_DOMAIN      =  0
-
-def is_dead(dom):
-    return dom['crashed'] or dom['shutdown'] or (
-        dom['dying'] and not(dom['running'] or dom['paused'] or
-                             dom['blocked']))
-
+PRIV_DOMAIN = 0
 
 class XendDomainDict(dict):
     def get_by_name(self, name):
@@ -77,11 +65,8 @@
         # So we stuff the XendDomain instance (self) into xroot's components.
         xroot.add_component("xen.xend.XendDomain", self)
         self.domains = XendDomainDict()
-        self.domroot = "/domain"
-        self.vmroot = "/domain"
-        self.dbmap = DBMap(db=XenNode(self.vmroot))
         self.watchReleaseDomain()
-        self.initial_refresh()
+        self.refresh()
         self.dom0_setup()
 
     def list(self):
@@ -110,9 +95,7 @@
         return map(lambda x: x.getName(), doms)
 
     def onReleaseDomain(self):
-        self.reap()
         self.refresh()
-        self.domain_restarts()
 
     def watchReleaseDomain(self):
         from xen.xend.xenstore.xswatch import xswatch
@@ -141,43 +124,22 @@
             dominfo = dominfo[0]
         return dominfo
 
-    def initial_refresh(self):
-        """Refresh initial domain info from db.
-        """
-        doms = self.xen_domains()
-        self.dbmap.readDB()             # XXX only needed for "xend"
-        for dom in doms.values():
-            domid = dom['dom']
-            dompath = GetDomainPath(domid)
-            if not dompath:
-                continue
-            vmpath = xstransact.Read(dompath, "vm")
-            if not vmpath:
-                continue
-            uuid = xstransact.Read(vmpath, "uuid")
-            if not uuid:
-                continue
-            log.info("recreating domain %d, uuid %s" % (domid, uuid))
-            dompath = "/".join(dompath.split("/")[0:-1])
-            try:
-                dominfo = XendDomainInfo.recreate(uuid, dompath, domid, dom)
-            except Exception, ex:
-                log.exception("Error recreating domain info: id=%d", domid)
-                continue
-            self._add_domain(dominfo)
-        self.reap()
-        self.refresh()
-        self.domain_restarts()
+
+    def recreate_domain(self, xeninfo):
+        """Refresh initial domain info from db."""
+
+        dominfo = XendDomainInfo.recreate(xeninfo)
+        self._add_domain(dominfo)
+        return dominfo
+
 
     def dom0_setup(self):
         dom0 = self.domain_lookup(PRIV_DOMAIN)
         if not dom0:
-            dom0 = self.dom0_unknown()
-        dom0.dom0_init_store()    
+            dom0 = self.recreate_domain(self.xen_domain(PRIV_DOMAIN))
+        dom0.dom0_init_store()
         dom0.dom0_enforce_vcpus()
 
-    def close(self):
-        pass
 
     def _add_domain(self, info, notify=True):
         """Add a domain entry to the tables.
@@ -193,70 +155,45 @@
             eserver.inject('xend.domain.create', [info.getName(),
                                                   info.getDomid()])
 
-    def _delete_domain(self, id, notify=True):
+    def _delete_domain(self, domid, notify=True):
         """Remove a domain from the tables.
 
         @param id:     domain id
         @param notify: send a domain died event if true
         """
-        info = self.domains.get(id)
+        info = self.domains.get(domid)
         if info:
-            del self.domains[id]
+            del self.domains[domid]
             info.cleanup()
             info.delete()
             if notify:
                 eserver.inject('xend.domain.died', [info.getName(),
                                                     info.getDomid()])
-        # XXX this should not be needed
-        for domdb in self.dbmap.values():
-            if not domdb.has_key("xend"):
-                continue
-            db = domdb.addChild("xend")
-            try:
-                domid = int(domdb["domid"].getData())
-            except:
-                domid = None
-            if (domid is None) or (domid == id):
-                domdb.delete()
-
-    def reap(self):
-        """Look for domains that have crashed or stopped.
-        Tidy them up.
-        """
-        doms = self.xen_domains()
-        for d in doms.values():
-            if not is_dead(d):
-                continue
-            domid = d['dom']
-            dominfo = self.domains.get(domid)
-            if not dominfo or dominfo.is_terminated():
-                continue
-            log.debug('domain died name=%s domid=%d', dominfo.getName(), domid)
-            if d['crashed'] and xroot.get_enable_dump():
-                self.domain_dumpcore(domid)
-            if d['shutdown']:
-                reason = shutdown_reason(d['shutdown_reason'])
-                log.debug('shutdown name=%s id=%d reason=%s',
-                          dominfo.getName(), domid, reason)
-                if reason == 'suspend':
-                    dominfo.state_set("suspended")
-                    continue
-                if reason in ['poweroff', 'reboot']:
-                    self.domain_restart_schedule(domid, reason)
-            dominfo.destroy()
+
 
     def refresh(self):
         """Refresh domain list from Xen.
         """
         doms = self.xen_domains()
-        # Remove entries for domains that no longer exist.
-        # Update entries for existing domains.
         for d in self.domains.values():
             info = doms.get(d.getDomid())
             if info:
                 d.update(info)
-            elif not d.restart_pending():
+            else:
                 self._delete_domain(d.getDomid())
+        for d in doms:
+            if d not in self.domains:
+                try:
+                    self.recreate_domain(doms[d])
+                except:
+                    log.exception(
+                        "Failed to recreate information for domain %d.  "
+                        "Destroying it in the hope of recovery.", d)
+                    try:
+                        xc.domain_destroy(dom = d)
+                    except:
+                        log.exception('Destruction of %d failed.', d)
+
 
     def update_domain(self, id):
         """Update information for a single domain.
@@ -277,32 +214,8 @@
         @param config: configuration
         @return: domain
         """
-        dominfo = XendDomainInfo.create(self.dbmap.getPath(), config)
+        dominfo = XendDomainInfo.create(config)
         self._add_domain(dominfo)
-        return dominfo
-
-    def domain_restart(self, dominfo):
-        """Restart a domain.
-
-        @param dominfo: domain object
-        """
-        log.info("Restarting domain: name=%s id=%s", dominfo.getName(),
-                 dominfo.getDomid())
-        eserver.inject("xend.domain.restart",
-                       [dominfo.getName(), dominfo.getDomid(), "begin"])
-        try:
-            dominfo.restart()
-            log.info('Restarted domain name=%s id=%s', dominfo.getName(),
-                     dominfo.getDomid())
-            eserver.inject("xend.domain.restart",
-                           [dominfo.getName(), dominfo.getDomid(),
-                            "success"])
-            self.domain_unpause(dominfo.getDomid())
-        except Exception, ex:
-            log.exception("Exception restarting domain: name=%s id=%s",
-                          dominfo.getName(), dominfo.getDomid())
-            eserver.inject("xend.domain.restart",
-                           [dominfo.getName(), dominfo.getDomid(), "fail"])
         return dominfo
 
     def domain_configure(self, config):
@@ -318,13 +231,12 @@
         nested = sxp.child_value(config, 'config')
         if nested:
             config = nested
-        return XendDomainInfo.restore(self.dbmap.getPath(), config)
-
-    def domain_restore(self, src, progress=False):
+        return XendDomainInfo.restore(config)
+
+    def domain_restore(self, src):
         """Restore a domain from file.
 
         @param src:      source file
-        @param progress: output progress if true
         """
 
         try:
@@ -345,33 +257,7 @@
         self.update_domain(id)
         return self.domains.get(id)
 
-    def dom0_unknown(self):
-        dom0 = PRIV_DOMAIN
-        uuid = None
-        info = self.xen_domain(dom0)
-        dompath = GetDomainPath(dom0)
-        if dompath:
-            vmpath = xstransact.Read(dompath, "vm")
-            if vmpath:
-                uuid = xstransact.Read(vmpath, "uuid")
-            if not uuid:
-                uuid = dompath.split("/")[-1]
-            dompath = "/".join(dompath.split("/")[0:-1])
-        if not uuid:
-            uuid = getUuid()
-            dompath = self.domroot
-        log.info("Creating entry for unknown xend domain: id=%d uuid=%s",
-                 dom0, uuid)
-        try:
-            dominfo = XendDomainInfo.recreate(uuid, dompath, dom0, info)
-            self._add_domain(dominfo)
-            return dominfo
-        except Exception, exn:
-            log.exception(exn)
-            raise XendError("Error recreating xend domain info: id=%d: %s" %
-                            (dom0, str(exn)))
-
-        
+
     def domain_lookup(self, id):
         return self.domains.get(id)
 
@@ -410,8 +296,9 @@
             return xc.domain_pause(dom=dominfo.getDomid())
         except Exception, ex:
             raise XendError(str(ex))
-    
-    def domain_shutdown(self, id, reason='poweroff'):
+
+
+    def domain_shutdown(self, domid, reason='poweroff'):
         """Shutdown domain (nicely).
          - poweroff: restart according to exit code and restart mode
          - reboot:   restart on exit
@@ -422,89 +309,13 @@
         @param id:     domain id
         @param reason: shutdown type: poweroff, reboot, suspend, halt
         """
-        dominfo = self.domain_lookup(id)
-        self.domain_restart_schedule(dominfo.getDomid(), reason, force=True)
-        eserver.inject('xend.domain.shutdown', [dominfo.getName(),
-                                                dominfo.getDomid(), reason])
-        if reason == 'halt':
-            reason = 'poweroff'
-        val = dominfo.shutdown(reason)
-        if not reason in ['suspend']:
-            self.domain_shutdowns()
-        return val
-
-
-    def domain_sysrq(self, id, key):
+        self.callInfo(domid, XendDomainInfo.shutdown, reason)
+
+
+    def domain_sysrq(self, domid, key):
         """Send a SysRq to the specified domain."""
-        return self.callInfo(id, XendDomainInfo.send_sysrq, key)
-
-
-    def domain_shutdowns(self):
-        """Process pending domain shutdowns.
-        Destroys domains whose shutdowns have timed out.
-        """
-        timeout = SHUTDOWN_TIMEOUT + 1
-        for dominfo in self.domains.values():
-            if not dominfo.shutdown_pending:
-                # domain doesn't need shutdown
-                continue
-            id = dominfo.getDomid()
-            left = dominfo.shutdown_time_left(SHUTDOWN_TIMEOUT)
-            if left <= 0:
-                # Shutdown expired - destroy domain.
-                try:
-                    log.info("Domain shutdown timeout expired: name=%s id=%s",
-                             dominfo.getName(), id)
-                    self.domain_destroy(id, reason=
-                                        dominfo.shutdown_pending['reason'])
-                except Exception:
-                    pass
-            else:
-                # Shutdown still pending.
-                timeout = min(timeout, left)
-        if timeout <= SHUTDOWN_TIMEOUT:
-            # Pending shutdowns remain - reschedule.
-            scheduler.later(timeout, self.domain_shutdowns)
-
-    def domain_restart_schedule(self, id, reason, force=False):
-        """Schedule a restart for a domain if it needs one.
-
-        @param id:     domain id
-        @param reason: shutdown reason
-        """
-        log.debug('domain_restart_schedule> %d %s %d', id, reason, force)
-        dominfo = self.domain_lookup(id)
-        if not dominfo:
-            return
-        restart = (force and reason == 'reboot') or 
dominfo.restart_needed(reason)
-        if restart:
-            log.info('Scheduling restart for domain: name=%s id=%s',
-                     dominfo.getName(), dominfo.getDomid())
-            eserver.inject("xend.domain.restart",
-                           [dominfo.getName(), dominfo.getDomid(),
-                            "schedule"])
-            dominfo.restarting()
-        else:
-            log.info('Cancelling restart for domain: name=%s id=%s',
-                     dominfo.getName(), dominfo.getDomid())
-            eserver.inject("xend.domain.restart",
-                           [dominfo.getName(), dominfo.getDomid(), "cancel"])
-            dominfo.restart_cancel()
-
-    def domain_restarts(self):
-        """Execute any scheduled domain restarts for domains that have gone.
-        """
-        doms = self.xen_domains()
-        for dominfo in self.domains.values():
-            if not dominfo.restart_pending():
-                continue
-            info = doms.get(dominfo.getDomid())
-            if info:
-                # Don't execute restart for domains still running.
-                continue
-            # Remove it from the restarts.
-            log.info('restarting: %s' % dominfo.getName())
-            self.domain_restart(dominfo)
+        return self.callInfo(domid, XendDomainInfo.send_sysrq, key)
+
 
     def domain_destroy(self, domid, reason='halt'):
         """Terminate domain immediately.
@@ -517,7 +328,6 @@
         if domid == PRIV_DOMAIN:
             raise XendError("Cannot destroy privileged domain %i" % domid)
         
-        self.domain_restart_schedule(domid, reason, force=True)
         dominfo = self.domain_lookup(domid)
         if dominfo:
             val = dominfo.destroy()
@@ -554,12 +364,11 @@
         
         return None
 
-    def domain_save(self, id, dst, progress=False):
+    def domain_save(self, id, dst):
         """Start saving a domain to file.
 
         @param id:       domain id
         @param dst:      destination file
-        @param progress: output progress if true
         """
 
         try:
@@ -659,14 +468,6 @@
     def domain_devtype_ls(self, domid, devtype):
         """Get list of device sxprs for the specified domain."""
         return self.callInfo(domid, XendDomainInfo.getDeviceSxprs, devtype)
-
-
-    def domain_devtype_get(self, domid, devtype, devid):
-        """Get a device from a domain.
-        
-        @return: device object (or None)
-        """
-        return self.callInfo(domid, XendDomainInfo.getDevice, devtype, devid)
 
 
     def domain_vif_limit_set(self, id, vif, credit, period):
@@ -730,10 +531,16 @@
     ## private:
 
     def callInfo(self, domid, fn, *args, **kwargs):
-        self.refresh()
-        dominfo = self.domains.get(domid)
-        if dominfo:
-            return fn(dominfo, *args, **kwargs)
+        try:
+            self.refresh()
+            dominfo = self.domains.get(domid)
+            if dominfo:
+                return fn(dominfo, *args, **kwargs)
+        except XendError:
+            raise
+        except Exception, exn:
+            log.exception("")
+            raise XendError(str(exn))
 
 
 def instance():
diff -r 4e1031ce3bc2 -r 5e5ae8340956 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Mon Sep 26 17:15:55 2005
+++ b/tools/python/xen/xend/XendDomainInfo.py   Wed Sep 28 20:06:49 2005
@@ -35,7 +35,9 @@
 from xen.xend.server.channel import EventChannel
 
 from xen.xend import image
+from xen.xend import scheduler
 from xen.xend import sxp
+from xen.xend import XendRoot
 from xen.xend.XendBootloader import bootloader
 from xen.xend.XendLogging import log
 from xen.xend.XendError import XendError, VmError
@@ -43,7 +45,7 @@
 
 from xen.xend.uuid import getUuid
 from xen.xend.xenstore.xstransact import xstransact
-from xen.xend.xenstore.xsutil import IntroduceDomain
+from xen.xend.xenstore.xsutil import GetDomainPath, IntroduceDomain
 
 """Shutdown code for poweroff."""
 DOMAIN_POWEROFF = 0
@@ -75,9 +77,6 @@
     RESTART_NEVER,
     ]
 
-STATE_RESTART_PENDING = 'pending'
-STATE_RESTART_BOOTING = 'booting'
-
 STATE_VM_OK         = "ok"
 STATE_VM_TERMINATED = "terminated"
 STATE_VM_SUSPENDED  = "suspended"
@@ -92,7 +91,29 @@
 SIF_TPM_BE_DOMAIN = (1<<7)
 
 
+SHUTDOWN_TIMEOUT = 30
+
+
+DOMROOT = '/domain'
+VMROOT  = '/domain'
+
+
 xc = xen.lowlevel.xc.new()
+xroot = XendRoot.instance()
+
+
+## Configuration entries that we expect to round-trip -- be read from the
+# config file or xc, written to save-files (i.e. through sxpr), and reused as
+# config on restart or restore, all without munging.  Some configuration
+# entries are munged for backwards compatibility reasons, or because they
+# don't come out of xc in the same form as they are specified in the config
+# file, so those are handled separately.
+ROUNDTRIPPING_CONFIG_ENTRIES = [
+        ('name',         str),
+        ('ssidref',      int),
+        ('cpu_weight',   float),
+        ('bootloader',   str)
+    ]
 
 
 def domain_exists(name):
@@ -133,47 +154,64 @@
     MINIMUM_RESTART_TIME = 20
 
 
-    def create(cls, dompath, config):
+    def create(cls, config):
         """Create a VM from a configuration.
 
-        @param dompath:   The path to all domain information
         @param config    configuration
         @raise: VmError for invalid configuration
         """
 
-        log.debug("XendDomainInfo.create(%s, ...)", dompath)
+        log.debug("XendDomainInfo.create(...)")
         
-        vm = cls(getUuid(), dompath, cls.parseConfig(config))
+        vm = cls(getUuid(), cls.parseConfig(config))
         vm.construct()
+        vm.refreshShutdown()
         return vm
 
     create = classmethod(create)
 
 
-    def recreate(cls, uuid, dompath, domid, info):
-        """Create the VM object for an existing domain.
-
-        @param dompath:   The path to all domain information
-        @param info:      domain info from xc
-        """
-
-        log.debug("XendDomainInfo.recreate(%s, %s, %s, %s)", uuid, dompath,
-                  domid, info)
-
-        return cls(uuid, dompath, info, domid, True)
+    def recreate(cls, xeninfo):
+        """Create the VM object for an existing domain."""
+
+        log.debug("XendDomainInfo.recreate(%s)", xeninfo)
+
+        domid = xeninfo['dom']
+        try:
+            dompath = GetDomainPath(domid)
+            if not dompath:
+                raise XendError(
+                    'No domain path in store for existing domain %d' % domid)
+            vmpath = xstransact.Read(dompath, "vm")
+            if not vmpath:
+                raise XendError(
+                    'No vm path in store for existing domain %d' % domid)
+            uuid = xstransact.Read(vmpath, "uuid")
+            if not uuid:
+                raise XendError(
+                    'No vm/uuid path in store for existing domain %d' % domid)
+
+        except Exception, exn:
+            log.warn(str(exn))
+            uuid = getUuid()
+
+        log.info("Recreating domain %d, uuid %s", domid, uuid)
+
+        vm = cls(uuid, xeninfo, domid, True)
+        vm.refreshShutdown(xeninfo)
+        return vm
 
     recreate = classmethod(recreate)
 
 
-    def restore(cls, dompath, config, uuid = None):
+    def restore(cls, config, uuid = None):
         """Create a domain and a VM object to do a restore.
 
-        @param dompath:   The path to all domain information
         @param config:    domain configuration
         @param uuid:      uuid to use
         """
         
-        log.debug("XendDomainInfo.restore(%s, %s, %s)", dompath, config, uuid)
+        log.debug("XendDomainInfo.restore(%s, %s)", config, uuid)
 
         if not uuid:
             uuid = getUuid()
@@ -183,14 +221,12 @@
         except TypeError, exn:
             raise VmError('Invalid ssidref in config: %s' % exn)
 
-        log.debug('restoring with ssidref = %d' % ssidref)
-
-        vm = cls(uuid, dompath, cls.parseConfig(config),
+        vm = cls(uuid, cls.parseConfig(config),
                  xc.domain_create(ssidref = ssidref))
-        vm.clear_shutdown()
         vm.create_channel()
         vm.configure()
         vm.exportToDB()
+        vm.refreshShutdown()
         return vm
 
     restore = classmethod(restore)
@@ -214,33 +250,28 @@
         log.debug("parseConfig: config is %s" % str(config))
 
         result = {}
-        imagecfg = "()"
-
-        result['name']         = get_cfg('name')
-        result['ssidref']      = get_cfg('ssidref',    int)
+
+        for e in ROUNDTRIPPING_CONFIG_ENTRIES:
+            result[e[0]] = get_cfg(e[0], e[1])
+
         result['memory']       = get_cfg('memory',     int)
         result['mem_kb']       = get_cfg('mem_kb',     int)
         result['maxmem']       = get_cfg('maxmem',     int)
         result['maxmem_kb']    = get_cfg('maxmem_kb',  int)
         result['cpu']          = get_cfg('cpu',        int)
-        result['cpu_weight']   = get_cfg('cpu_weight', float)
-        result['bootloader']   = get_cfg('bootloader')
         result['restart_mode'] = get_cfg('restart')
+        result['image']        = get_cfg('image')
 
         try:
-            imagecfg = get_cfg('image')
-
-            if imagecfg:
-                result['image'] = imagecfg
-                result['vcpus'] = int(sxp.child_value(imagecfg, 'vcpus',
-                                                      1))
+            if result['image']:
+                result['vcpus'] = int(sxp.child_value(result['image'],
+                                                      'vcpus', 1))
             else:
                 result['vcpus'] = 1
         except TypeError, exn:
             raise VmError(
                 'Invalid configuration setting: vcpus = %s: %s' %
-                (sxp.child_value(imagecfg, 'vcpus', 1),
-                 str(exn)))
+                (sxp.child_value(result['image'], 'vcpus', 1), str(exn)))
 
         result['backend'] = []
         for c in sxp.children(config, 'backend'):
@@ -258,12 +289,12 @@
     parseConfig = classmethod(parseConfig)
 
     
-    def __init__(self, uuid, parentpath, info, domid = None, augment = False):
+    def __init__(self, uuid, info, domid = None, augment = False):
 
         self.uuid = uuid
         self.info = info
 
-        self.path = parentpath + "/" + uuid
+        self.path = DOMROOT + "/" + uuid
 
         if domid:
             self.domid = domid
@@ -283,26 +314,26 @@
         self.store_mfn = None
         self.console_channel = None
         self.console_mfn = None
-        
-        #todo: state: running, suspended
+
         self.state = STATE_VM_OK
         self.state_updated = threading.Condition()
-        self.shutdown_pending = None
-
-        self.restart_state = None
-        self.restart_time = None
-        self.restart_count = 0
-        
+
         self.writeVm("uuid", self.uuid)
         self.storeDom("vm", self.path)
 
 
     def augmentInfo(self):
+        """Augment self.info, as given to us through {@link #recreate}, with
+        values taken from the store.  This recovers those values known to xend
+        but not to the hypervisor.
+        """
         def useIfNeeded(name, val):
             if not self.infoIsSet(name) and val is not None:
                 self.info[name] = val
 
         params = (("name", str),
+                  ("restart-mode", str),
+                  ("image",        str),
                   ("start-time", float))
 
         from_store = self.gatherVm(*params)
@@ -322,12 +353,17 @@
             defaultInfo('name',         lambda: "Domain-%d" % self.domid)
             defaultInfo('ssidref',      lambda: 0)
             defaultInfo('restart_mode', lambda: RESTART_ONREBOOT)
+            defaultInfo('cpu',          lambda: None)
             defaultInfo('cpu_weight',   lambda: 1.0)
             defaultInfo('bootloader',   lambda: None)
             defaultInfo('backend',      lambda: [])
             defaultInfo('device',       lambda: [])
+            defaultInfo('image',        lambda: None)
 
             self.check_name(self.info['name'])
+
+            if isinstance(self.info['image'], str):
+                self.info['image'] = sxp.from_string(self.info['image'])
 
             # Internally, we keep only maxmem_KiB, and not maxmem or maxmem_kb
             # (which come from outside, and are in MiB and KiB respectively).
@@ -451,17 +487,16 @@
             'domid':              str(self.domid),
             'uuid':               self.uuid,
 
-            'restart_time':       str(self.restart_time),
-
-            'xend/state':         self.state,
-            'xend/restart_count': str(self.restart_count),
             'xend/restart_mode':  str(self.info['restart_mode']),
 
             'memory/target':      str(self.info['memory_KiB'])
             }
 
         for (k, v) in self.info.items():
-            to_store[k] = str(v)
+            if v:
+                to_store[k] = str(v)
+
+        to_store['image'] = sxp.to_string(self.info['image'])
 
         log.debug("Storing %s" % str(to_store))
 
@@ -511,6 +546,88 @@
     def getBackendFlags(self):
         return reduce(lambda x, y: x | backendFlags[y],
                       self.info['backend'], 0)
+
+
+    def refreshShutdown(self, xeninfo = None):
+        if xeninfo is None:
+            xeninfo = dom_get(self.domid)
+            if xeninfo is None:
+                # The domain no longer exists.  This will occur if we have
+                # scheduled a timer to check for shutdown timeouts and the
+                # shutdown succeeded.
+                return
+
+        if xeninfo['dying']:
+            # Dying means that a domain has been destroyed, but has not yet
+            # been cleaned up by Xen.  This could persist indefinitely if,
+            # for example, another domain has some of its pages mapped.
+            # We might like to diagnose this problem in the future, but for
+            # now all we can sensibly do is ignore it.
+            pass
+
+        elif xeninfo['crashed']:
+            log.warn('Domain has crashed: name=%s id=%d.',
+                     self.info['name'], self.domid)
+
+            if xroot.get_enable_dump():
+                self.dumpCore()
+
+            self.maybeRestart('crashed')
+
+        elif xeninfo['shutdown']:
+            reason = shutdown_reason(xeninfo['shutdown_reason'])
+
+            log.info('Domain has shutdown: name=%s id=%d reason=%s.',
+                     self.info['name'], self.domid, reason)
+
+            self.clearRestart()
+
+            if reason == 'suspend':
+                self.state_set(STATE_VM_SUSPENDED)
+                # Don't destroy the domain.  XendCheckpoint will do this once
+                # it has finished.
+            elif reason in ['poweroff', 'reboot']:
+                self.maybeRestart(reason)
+            else:
+                self.destroy()
+
+        else:
+            # Domain is alive.  If we are shutting it down, then check
+            # the timeout on that, and destroy it if necessary.
+
+            sst = self.readVm('xend/shutdown_start_time')
+            if sst:
+                sst = float(sst)
+                timeout = SHUTDOWN_TIMEOUT - time.time() + sst
+                if timeout < 0:
+                    log.info(
+                        "Domain shutdown timeout expired: name=%s id=%s",
+                        self.info['name'], self.domid)
+                    self.destroy()
+                else:
+                    log.debug(
+                        "Scheduling refreshShutdown on domain %d in %ds.",
+                        self.domid, timeout)
+                    scheduler.later(timeout, self.refreshShutdown)
+
+
+    def shutdown(self, reason):
+        if not reason in shutdown_reasons.values():
+            raise XendError('invalid reason:' + reason)
+        self.storeVm("control/shutdown", reason)
+        if not reason == 'suspend':
+            self.storeVm('xend/shutdown_start_time', time.time())
+
+
+    def clearRestart(self):
+        self.removeVm("xend/shutdown_start_time")
+
+
+    def maybeRestart(self, reason):
+        if self.restart_needed(reason):
+            self.restart()
+        else:
+            self.destroy()
 
 
     def dumpCore(self):
@@ -526,18 +643,32 @@
                       self.domid, self.info['name'], str(exn))
 
 
+    def closeChannel(self, channel, entry):
+        """Close the given channel, if set, and remove the given entry in the
+        store.  Nothrow guarantee."""
+        
+        try:
+            try:
+                if channel:
+                    channel.close()
+            finally:
+                self.removeDom(entry)
+        except Exception, exn:
+            log.exception(exn)
+        
+
     def closeStoreChannel(self):
         """Close the store channel, if any.  Nothrow guarantee."""
-        
-        try:
-            if self.store_channel:
-                try:
-                    self.store_channel.close()
-                    self.removeDom("store/port")
-                finally:
-                    self.store_channel = None
-        except Exception, exn:
-            log.exception(exn)
+
+        self.closeChannel(self.store_channel, "store/port")
+        self.store_channel = None
+
+
+    def closeConsoleChannel(self):
+        """Close the console channel, if any.  Nothrow guarantee."""
+
+        self.closeChannel(self.console_channel, "console/port")
+        self.console_channel = None
 
 
     def setConsoleRef(self, ref):
@@ -566,10 +697,13 @@
             
         self.info.update(info)
         self.validateInfo()
+        self.refreshShutdown(info)
 
         log.debug("XendDomainInfo.update done on domain %d: %s", self.domid,
                   self.info)
 
+
+    ## private:
 
     def state_set(self, state):
         self.state_updated.acquire()
@@ -577,13 +711,16 @@
             self.state = state
             self.state_updated.notifyAll()
         self.state_updated.release()
-        self.exportToDB()
+
+
+    ## public:
 
     def state_wait(self, state):
         self.state_updated.acquire()
         while self.state != state:
             self.state_updated.wait()
         self.state_updated.release()
+
 
     def __str__(self):
         s = "<domain"
@@ -597,6 +734,25 @@
     __repr__ = __str__
 
 
+    def createDevice(self, deviceClass, devconfig):
+        return self.getDeviceController(deviceClass).createDevice(devconfig)
+
+
+    def configureDevice(self, deviceClass, devid, devconfig):
+        return self.getDeviceController(deviceClass).configureDevice(
+            devid, devconfig)
+
+
+    def destroyDevice(self, deviceClass, devid):
+        return self.getDeviceController(deviceClass).destroyDevice(devid)
+
+
+    def getDeviceSxprs(self, deviceClass):
+        return self.getDeviceController(deviceClass).sxprs()
+
+
+    ## private:
+
     def getDeviceController(self, name):
         if name not in controllerClasses:
             raise XendError("unknown device type: " + str(name))
@@ -604,62 +760,53 @@
         return controllerClasses[name](self)
 
 
-    def createDevice(self, deviceClass, devconfig):
-        return self.getDeviceController(deviceClass).createDevice(devconfig)
-
-
-    def configureDevice(self, deviceClass, devid, devconfig):
-        return self.getDeviceController(deviceClass).configureDevice(
-            devid, devconfig)
-
-
-    def destroyDevice(self, deviceClass, devid):
-        return self.getDeviceController(deviceClass).destroyDevice(devid)
-
+    ## public:
 
     def sxpr(self):
         sxpr = ['domain',
-                ['domid', self.domid],
-                ['name', self.info['name']],
-                ['memory', self.info['memory_KiB'] / 1024],
-                ['ssidref', self.info['ssidref']]]
-        if self.uuid:
-            sxpr.append(['uuid', self.uuid])
-        if self.info:
-            sxpr.append(['maxmem', self.info['maxmem_KiB'] / 1024])
-
-            if self.infoIsSet('device'):
-                for (_, c) in self.info['device']:
-                    sxpr.append(['device', c])
-
-            def stateChar(name):
-                if name in self.info:
-                    if self.info[name]:
-                        return name[0]
-                    else:
-                        return '-'
+                ['domid',   self.domid],
+                ['uuid',    self.uuid],
+                ['memory',  self.info['memory_KiB'] / 1024]]
+
+        for e in ROUNDTRIPPING_CONFIG_ENTRIES:
+            if self.infoIsSet(e[0]):
+                sxpr.append([e[0], self.info[e[0]]])
+        
+        sxpr.append(['maxmem', self.info['maxmem_KiB'] / 1024])
+
+        if self.infoIsSet('image'):
+            sxpr.append(['image', self.info['image']])
+
+        if self.infoIsSet('device'):
+            for (_, c) in self.info['device']:
+                sxpr.append(['device', c])
+
+        def stateChar(name):
+            if name in self.info:
+                if self.info[name]:
+                    return name[0]
                 else:
-                    return '?'
-
-            state = reduce(
-                lambda x, y: x + y,
-                map(stateChar,
-                    ['running', 'blocked', 'paused', 'shutdown', 'crashed']))
-
-            sxpr.append(['state', state])
-            if self.infoIsSet('shutdown'):
-                reason = shutdown_reason(self.info['shutdown_reason'])
-                sxpr.append(['shutdown_reason', reason])
-            if self.infoIsSet('cpu_time'):
-                sxpr.append(['cpu_time', self.info['cpu_time']/1e9])    
-            sxpr.append(['vcpus', self.info['vcpus']])
-            sxpr.append(['cpumap', self.info['cpumap']])
-            if self.infoIsSet('vcpu_to_cpu'):
-                sxpr.append(['cpu', self.info['vcpu_to_cpu'][0]])
-                # build a string, using '|' to separate items, show only up
-                # to number of vcpus in domain, and trim the trailing '|'
-                sxpr.append(['vcpu_to_cpu', ''.join(map(lambda x: str(x)+'|',
-                            
self.info['vcpu_to_cpu'][0:self.info['vcpus']]))[:-1]])
+                    return '-'
+            else:
+                return '?'
+
+        state = reduce(
+            lambda x, y: x + y,
+            map(stateChar,
+                ['running', 'blocked', 'paused', 'shutdown', 'crashed',
+                 'dying']))
+
+        sxpr.append(['state', state])
+        if self.infoIsSet('shutdown'):
+            reason = shutdown_reason(self.info['shutdown_reason'])
+            sxpr.append(['shutdown_reason', reason])
+        if self.infoIsSet('cpu_time'):
+            sxpr.append(['cpu_time', self.info['cpu_time']/1e9])
+        sxpr.append(['vcpus', self.info['vcpus']])
+        sxpr.append(['cpumap', self.info['cpumap']])
+        if self.infoIsSet('vcpu_to_cpu'):
+            sxpr.append(['cpu', self.info['vcpu_to_cpu'][0]])
+            sxpr.append(['vcpu_to_cpu', self.prettyVCpuMap()])
             
         if self.infoIsSet('start_time'):
             up_time =  time.time() - self.info['start_time']
@@ -674,13 +821,16 @@
             sxpr.append(['console_channel', self.console_channel.sxpr()])
         if self.console_mfn:
             sxpr.append(['console_mfn', self.console_mfn])
-        if self.restart_count:
-            sxpr.append(['restart_count', self.restart_count])
-        if self.restart_state:
-            sxpr.append(['restart_state', self.restart_state])
-        if self.restart_time:
-            sxpr.append(['restart_time', str(self.restart_time)])
+
         return sxpr
+
+
+    ## private:
+
+    def prettyVCpuMap(self):
+        return '|'.join(map(str,
+                            self.info['vcpu_to_cpu'][0:self.info['vcpus']]))
+
 
     def check_name(self, name):
         """Check if a vm name is valid. Valid names contain alphabetic 
characters,
@@ -719,11 +869,19 @@
         @param config: configuration
         @raise: VmError on error
         """
-        # todo - add support for scheduling params?
+
+        log.debug('XendDomainInfo.construct: %s %s',
+                  str(self.domid),
+                  str(self.info['ssidref']))
+
+        self.domid = xc.domain_create(dom = 0, ssidref = self.info['ssidref'])
+
+        if self.domid <= 0:
+            raise VmError('Creating domain failed: name=%s' %
+                          self.info['name'])
+
         try:
             self.initDomain()
-
-            # Create domain devices.
             self.construct_image()
             self.configure()
             self.exportToDB()
@@ -737,30 +895,23 @@
 
 
     def initDomain(self):
-        log.debug('XendDomainInfo.initDomain: %s %s %s %s)',
+        log.debug('XendDomainInfo.initDomain: %s %s %s',
                   str(self.domid),
                   str(self.info['memory_KiB']),
-                  str(self.info['ssidref']),
                   str(self.info['cpu_weight']))
 
-        self.domid = xc.domain_create(dom = self.domid or 0,
-                                      ssidref = self.info['ssidref'])
-
-        if 'image' not in self.info:
+        if not self.infoIsSet('image'):
             raise VmError('Missing image in configuration')
 
         self.image = image.create(self,
                                   self.info['image'],
                                   self.info['device'])
 
-        if self.domid <= 0:
-            raise VmError('Creating domain failed: name=%s' %
-                          self.info['name'])
-
         if self.info['bootloader']:
             self.image.handleBootloading()
 
         xc.domain_setcpuweight(self.domid, self.info['cpu_weight'])
+        # XXX Merge with configure_maxmem?
         m = self.image.getDomainMemory(self.info['memory_KiB'])
         xc.domain_setmaxmem(self.domid, m)
         xc.domain_memory_increase_reservation(self.domid, m, 0, 0)
@@ -794,6 +945,8 @@
         self.configure_vcpus(self.info['vcpus'])
 
 
+    ## public:
+
     def delete(self):
         """Delete the vm's db.
         """
@@ -803,48 +956,46 @@
             log.warning("error in domain db delete: %s", ex)
 
 
-    def destroy_domain(self):
-        """Destroy the vm's domain.
-        The domain will not finally go away unless all vm
-        devices have been released.
-        """
-        if self.domid is None:
-            return
-        try:
-            xc.domain_destroy(dom=self.domid)
-        except Exception, err:
-            log.exception("Domain destroy failed: %s", self.info['name'])
-
     def cleanup(self):
-        """Cleanup vm resources: release devices.
-        """
-        self.state = STATE_VM_TERMINATED
+        """Cleanup vm resources: release devices.  Nothrow guarantee."""
+
+        self.state_set(STATE_VM_TERMINATED)
         self.release_devices()
         self.closeStoreChannel()
-        if self.console_channel:
-            # notify processes using this console?
-            try:
-                self.console_channel.close()
-                self.console_channel = None
-            except:
-                pass
+        self.closeConsoleChannel()
+
         if self.image:
             try:
                 self.image.destroy()
-                self.image = None
             except:
-                pass
+                log.exception(
+                    "XendDomainInfo.cleanup: image.destroy() failed.")
+            self.image = None
+
 
     def destroy(self):
-        """Cleanup vm and destroy domain.
-        """
-
-        log.debug("XendDomainInfo.destroy")
-
-        self.destroy_domain()
+        """Cleanup vm and destroy domain.  Nothrow guarantee."""
+
+        log.debug("XendDomainInfo.destroy: domid=%s", str(self.domid))
+
         self.cleanup()
-        self.exportToDB()
-        return 0
+
+        try:
+            self.removeVm()
+        except Exception:
+            log.exception("Removing VM path failed.")
+
+        try:
+            self.removeDom()
+        except Exception:
+            log.exception("Removing domain path failed.")
+
+        try:
+            if self.domid is not None:
+                xc.domain_destroy(dom=self.domid)
+        except Exception:
+            log.exception("XendDomainInfo.destroy: xc.domain_destroy failed.")
+
 
     def is_terminated(self):
         """Check if a domain has been terminated.
@@ -852,8 +1003,7 @@
         return self.state == STATE_VM_TERMINATED
 
     def release_devices(self):
-        """Release all vm devices.
-        """
+        """Release all vm devices.  Nothrow guarantee."""
 
         while True:
             t = xstransact("%s/device" % self.path)
@@ -865,8 +1015,8 @@
                         # Log and swallow any exceptions in removal --
                         # there's nothing more we can do.
                         log.exception(
-                           "Device release failed: %s; %s; %s; %s" %
-                            (self.info['name'], n, d, str(ex)))
+                           "Device release failed: %s; %s; %s",
+                           self.info['name'], n, d)
             if t.commit():
                 break
 
@@ -902,8 +1052,7 @@
 
         @raise: VmError for invalid devices
         """
-        if not self.rebooting():
-            self.create_configured_devices()
+        self.create_configured_devices()
         if self.image:
             self.image.createDeviceModel()
 
@@ -942,23 +1091,6 @@
             return reason == 'reboot'
         return False
 
-    def restart_cancel(self):
-        """Cancel a vm restart.
-        """
-        self.restart_state = None
-
-    def restarting(self):
-        """Put the vm into restart mode.
-        """
-        self.restart_state = STATE_RESTART_PENDING
-
-    def restart_pending(self):
-        """Test if the vm has a pending restart.
-        """
-        return self.restart_state == STATE_RESTART_PENDING
-
-    def rebooting(self):
-        return self.restart_state == STATE_RESTART_BOOTING
 
     def restart_check(self):
         """Check if domain restart is OK.
@@ -976,23 +1108,37 @@
         self.restart_time = tnow
         self.restart_count += 1
 
+
     def restart(self):
-        """Restart the domain after it has exited.
-        Reuses the domain id
-
-        """
+        """Restart the domain after it has exited. """
+
+        #            self.restart_check()
+        self.cleanup()
+
+        config = self.sxpr()
+
+        if self.readVm('xend/restart_in_progress'):
+            log.error('Xend failed during restart of domain %d.  '
+                      'Refusing to restart to avoid loops.',
+                      self.domid)
+            self.destroy()
+            return
+
+        self.writeVm('xend/restart_in_progress', 'True')
+
         try:
-            self.clear_shutdown()
-            self.state = STATE_VM_OK
-            self.shutdown_pending = None
-            self.restart_check()
-            self.exportToDB()
-            self.restart_state = STATE_RESTART_BOOTING
-            self.configure_bootloader()
-            self.construct()
-            self.exportToDB()
+            self.destroy()
+            try:
+                xd = get_component('xen.xend.XendDomain')
+                xd.domain_unpause(xd.domain_create(config).getDomid())
+            except Exception, exn:
+                log.exception('Failed to restart domain %d.', self.domid)
         finally:
-            self.restart_state = None
+            self.removeVm('xend/restart_in_progress')
+            
+        # self.configure_bootloader()
+        #        self.exportToDB()
+
 
     def configure_bootloader(self):
         if not self.info['bootloader']:
@@ -1006,7 +1152,8 @@
         if dev:
             disk = sxp.child_value(dev, "uname")
             fn = blkdev_uname_to_file(disk)
-            blcfg = bootloader(self.info['bootloader'], fn, 1, 
self.info['vcpus'])
+            blcfg = bootloader(self.info['bootloader'], fn, 1,
+                               self.info['vcpus'])
         if blcfg is None:
             msg = "Had a bootloader specified, but can't find disk"
             log.error(msg)
@@ -1023,7 +1170,9 @@
 
 
     def configure_maxmem(self):
-        xc.domain_setmaxmem(self.domid, maxmem_kb = self.info['maxmem_KiB'])
+        if self.image:
+            m = self.image.getDomainMemory(self.info['memory_KiB'])
+            xc.domain_setmaxmem(self.domid, maxmem_kb = m)
 
 
     def vcpu_hotplug(self, vcpu, state):
@@ -1038,23 +1187,8 @@
             availability = "online"
         self.storeVm("cpu/%d/availability" % vcpu, availability)
 
-    def shutdown(self, reason):
-        if not reason in shutdown_reasons.values():
-            raise XendError('invalid reason:' + reason)
-        self.storeVm("control/shutdown", reason)
-        if not reason in ['suspend']:
-            self.shutdown_pending = {'start':time.time(), 'reason':reason}
-
-    def clear_shutdown(self):
-        self.removeVm("control/shutdown")
-
     def send_sysrq(self, key=0):
         self.storeVm("control/sysrq", '%c' % key)
-
-    def shutdown_time_left(self, timeout):
-        if not self.shutdown_pending:
-            return 0
-        return timeout - (time.time() - self.shutdown_pending['start'])
 
     def dom0_init_store(self):
         if not self.store_channel:
@@ -1078,8 +1212,6 @@
     def dom0_enforce_vcpus(self):
         dom = 0
         # get max number of vcpus to use for dom0 from config
-        from xen.xend import XendRoot
-        xroot = XendRoot.instance()
         target = int(xroot.get_dom0_vcpus())
         log.debug("number of vcpus to use is %d" % (target))
    
diff -r 4e1031ce3bc2 -r 5e5ae8340956 
tools/python/xen/xend/server/DevController.py
--- a/tools/python/xen/xend/server/DevController.py     Mon Sep 26 17:15:55 2005
+++ b/tools/python/xen/xend/server/DevController.py     Wed Sep 28 20:06:49 2005
@@ -81,6 +81,13 @@
         xstransact.Remove(backpath)
 
 
+    def sxprs(self):
+        """@return an s-expression describing all the devices of this
+        controller's device-class.
+        """
+        return xstransact.ListRecursive(self.frontendRoot())
+
+
     def sxpr(self, devid):
         """@return an s-expression describing the specified device.
         """
@@ -126,8 +133,8 @@
         compulsory to use it; subclasses may prefer to allocate IDs based upon
         the device configuration instead.
         """
+        path = self.frontendMiscPath()
         while True:
-            path = self.frontendMiscPath()
             t = xstransact(path)
             try:
                 result = t.read("nextDeviceID")
@@ -196,8 +203,11 @@
 
 
     def frontendPath(self, devid):
-        return "%s/device/%s/%d" % (self.vm.getPath(), self.deviceClass,
-                                    devid)
+        return "%s/%d" % (self.frontendRoot(), devid)
+
+
+    def frontendRoot(self):
+        return "%s/device/%s" % (self.vm.getPath(), self.deviceClass)
 
 
     def frontendMiscPath(self):
diff -r 4e1031ce3bc2 -r 5e5ae8340956 tools/python/xen/xend/server/SrvDaemon.py
--- a/tools/python/xen/xend/server/SrvDaemon.py Mon Sep 26 17:15:55 2005
+++ b/tools/python/xen/xend/server/SrvDaemon.py Wed Sep 28 20:06:49 2005
@@ -9,25 +9,23 @@
 import sys
 import threading
 import linecache
-import socket
 import pwd
 import re
-import StringIO
 import traceback
-import time
-import glob
-
-from xen.xend import sxp
-from xen.xend import PrettyPrint
-from xen.xend import EventServer; eserver = EventServer.instance()
-from xen.xend.XendError import XendError
+
+from xen.xend import EventServer
 from xen.xend.server import SrvServer
 from xen.xend.XendLogging import log
-from xen.xend import XendRoot; xroot = XendRoot.instance()
+from xen.xend import XendRoot
 
 import event
 import relocate
 from params import *
+
+
+eserver = EventServer.instance()
+xroot = XendRoot.instance()
+
 
 class Daemon:
     """The xend daemon.
@@ -233,7 +231,7 @@
             except:
                 pass
 
-    def print_trace(self, str):
+    def print_trace(self, string):
         for i in range(self.traceindent):
             ch = " "
             if (i % 5):
@@ -241,7 +239,7 @@
             else:
                 ch = '|'
             self.tracefile.write(ch)
-        self.tracefile.write(str)
+        self.tracefile.write(string)
             
     def trace(self, frame, event, arg):
         if not self.traceon:
@@ -289,7 +287,7 @@
         try:
             os.setuid(pwd.getpwnam(XEND_USER)[2])
             return 0
-        except KeyError, error:
+        except KeyError:
             print >>sys.stderr, "Error: no such user '%s'" % XEND_USER
             return 1
 
diff -r 4e1031ce3bc2 -r 5e5ae8340956 tools/python/xen/xend/server/SrvDmesg.py
--- a/tools/python/xen/xend/server/SrvDmesg.py  Mon Sep 26 17:15:55 2005
+++ b/tools/python/xen/xend/server/SrvDmesg.py  Wed Sep 28 20:06:49 2005
@@ -13,14 +13,14 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #============================================================================
 # Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx>
+# Copyright (C) 2005 XenSource Ltd
 #============================================================================
 
-import os
 
-from xen.xend import sxp
 from xen.xend import XendDmesg
 
 from xen.web.SrvDir import SrvDir
+
 
 class SrvDmesg(SrvDir):
     """Xen Dmesg output.
@@ -47,6 +47,6 @@
     def info(self):
         return self.xd.info()
 
-    def op_clear(self, op, req):
+    def op_clear(self, _1, _2):
         self.xd.clear()
         return 0
diff -r 4e1031ce3bc2 -r 5e5ae8340956 tools/python/xen/xend/server/SrvDomain.py
--- a/tools/python/xen/xend/server/SrvDomain.py Mon Sep 26 17:15:55 2005
+++ b/tools/python/xen/xend/server/SrvDomain.py Wed Sep 28 20:06:49 2005
@@ -150,17 +150,6 @@
         val = fn(req.args, {'dom': self.dom.domid})
         return val
 
-    def op_device(self, op, req):
-        fn = FormFn(self.xd.domain_devtype_get,
-                    [['dom',    'int'],
-                     ['type',   'str'],
-                     ['idx',    'int']])
-        val = fn(req.args, {'dom': self.dom.domid})
-        if val:
-            return val.sxpr()
-        else:
-            raise XendError("invalid device")
-
     def op_device_create(self, op, req):
         fn = FormFn(self.xd.domain_device_create,
                     [['dom',    'int'],
@@ -172,7 +161,7 @@
         fn = FormFn(self.xd.domain_device_refresh,
                     [['dom',  'int'],
                      ['type', 'str'],
-                     ['idx',  'str']])
+                     ['idx',  'int']])
         val = fn(req.args, {'dom': self.dom.domid})
         return val
 
@@ -180,7 +169,7 @@
         fn = FormFn(self.xd.domain_device_destroy,
                     [['dom',  'int'],
                      ['type', 'str'],
-                     ['idx',  'str']])
+                     ['idx',  'int']])
         val = fn(req.args, {'dom': self.dom.domid})
         return val
                 
@@ -188,7 +177,7 @@
         fn = FormFn(self.xd.domain_device_configure,
                     [['dom',    'int'],
                      ['config', 'sxpr'],
-                     ['idx',    'str']])
+                     ['idx',    'int']])
         val = fn(req.args, {'dom': self.dom.domid})
         return val
 
@@ -230,10 +219,6 @@
             self.print_path(req)
             #self.ls()
             req.write('<p>%s</p>' % self.dom)
-            if self.dom.config:
-                req.write("<code><pre>")
-                PrettyPrint.prettyprint(self.dom.config, out=req)
-                req.write("</pre></code>")
             self.form(req)
             req.write('</body></html>')
         return ''
diff -r 4e1031ce3bc2 -r 5e5ae8340956 
tools/python/xen/xend/server/SrvDomainDir.py
--- a/tools/python/xen/xend/server/SrvDomainDir.py      Mon Sep 26 17:15:55 2005
+++ b/tools/python/xen/xend/server/SrvDomainDir.py      Wed Sep 28 20:06:49 2005
@@ -38,19 +38,17 @@
         self.xd = XendDomain.instance()
 
     def domain(self, x):
-        val = None
         dom = self.xd.domain_lookup_by_name(x)
         if not dom:
             raise XendError('No such domain ' + str(x))
-        val = SrvDomain(dom)
-        return val
+        return SrvDomain(dom)
 
     def get(self, x):
         v = SrvDir.get(self, x)
         if v is not None:
             return v
-        v = self.domain(x)
-        return v
+        else:
+            return self.domain(x)
 
     def op_create(self, op, req):
         """Create a domain.
@@ -152,11 +150,11 @@
             domains = self.xd.list_sorted()
             req.write('<ul>')
             for d in domains:
-                req.write('<li><a href="%s%s"> Domain %s</a>'
-                          % (url, d.getName(), d.getName()))
-                req.write('id=%s' % d.getDomain())
-                req.write('memory=%d'% d.getMemoryTarget())
-                req.write('ssidref=%d'% d.getSsidref())
+                req.write(
+                    '<li><a href="%s%s">Domain %s</a>: id = %s, memory = %d, '
+                    'ssidref = %d.'
+                    % (url, d.getName(), d.getName(), d.getDomid(),
+                       d.getMemoryTarget(), d.getSsidref()))
                 req.write('</li>')
             req.write('</ul>')
 
diff -r 4e1031ce3bc2 -r 5e5ae8340956 tools/python/xen/xend/server/SrvNode.py
--- a/tools/python/xen/xend/server/SrvNode.py   Mon Sep 26 17:15:55 2005
+++ b/tools/python/xen/xend/server/SrvNode.py   Wed Sep 28 20:06:49 2005
@@ -62,7 +62,7 @@
             for d in self.info():
                 req.write('<li> %10s: %s' % (d[0], str(d[1])))
             req.write('<li><a href="%sdmesg">Xen dmesg output</a>' % url)
-            req.write('<li><a href="%slog>Xend log</a>' % url)
+            req.write('<li><a href="%slog">Xend log</a>' % url)
             req.write('</ul>')
             req.write('</body></html>')
             
diff -r 4e1031ce3bc2 -r 5e5ae8340956 
tools/python/xen/xend/xenstore/xstransact.py
--- a/tools/python/xen/xend/xenstore/xstransact.py      Mon Sep 26 17:15:55 2005
+++ b/tools/python/xen/xend/xenstore/xstransact.py      Wed Sep 28 20:06:49 2005
@@ -1,4 +1,5 @@
 # Copyright (C) 2005 Christian Limpach <Christian.Limpach@xxxxxxxxxxxx>
+# Copyright (C) 2005 XenSource Ltd
 
 # This file is subject to the terms and conditions of the GNU General
 # Public License.  See the file "COPYING" in the main directory of
@@ -8,6 +9,7 @@
 import threading
 from xen.lowlevel import xs
 from xen.xend.xenstore.xsutil import xshandle
+
 
 class xstransact:
 
@@ -40,8 +42,15 @@
                                '%s, while reading %s' % (ex.args[1], path))
 
     def read(self, *args):
-        if len(args) == 0:
-            raise TypeError
+        """If no arguments are given, return the value at this transaction's
+        path.  If one argument is given, treat that argument as a subpath to
+        this transaction's path, and return the value at that path.
+        Otherwise, treat each argument as a subpath to this transaction's
+        path, and return a list composed of the values at each of those
+        instead.
+        """
+        if len(args) == 0:
+            return xshandle().read(self.path)
         if len(args) == 1:
             return self._read(args[0])
         ret = []
@@ -105,12 +114,49 @@
         return []
 
     def list(self, *args):
-        if len(args) == 0:
-            raise TypeError
+        """If no arguments are given, list this transaction's path, returning
+        the entries therein, or the empty list if no entries are found.
+        Otherwise, treat each argument as a subpath to this transaction's
+        path, and return the cumulative listing of each of those instead.
+        """
+        if len(args) == 0:
+            ret = xshandle().ls(self.path)
+            if ret is None:
+                return []
+            else:
+                return ret
+        else:
+            ret = []
+            for key in args:
+                ret.extend(self._list(key))
+            return ret
+
+
+    def list_recursive_(self, subdir, keys):
         ret = []
-        for key in args:
-            ret.extend(self._list(key))
+        for key in keys:
+            new_subdir = subdir + "/" + key
+            l = xshandle().ls(new_subdir)
+            if l:
+                ret.append([key, self.list_recursive_(new_subdir, l)])
+            else:
+                ret.append([key, xshandle().read(new_subdir)])
         return ret
+
+
+    def list_recursive(self, *args):
+        """If no arguments are given, list this transaction's path, returning
+        the entries therein, or the empty list if no entries are found.
+        Otherwise, treat each argument as a subpath to this transaction's
+        path, and return the cumulative listing of each of those instead.
+        """
+        if len(args) == 0:
+            args = self.list()
+            if args is None or len(args) == 0:
+                return []
+
+        return self.list_recursive_(self.path, args)
+
 
     def gather(self, *args):
         if len(args) and type(args[0]) != tuple:
@@ -163,6 +209,13 @@
 
 
     def Read(cls, path, *args):
+        """If only one argument is given (path), return the value stored at
+        that path.  If two arguments are given, treat the second argument as a
+        subpath within the first, and return the value at the composed path.
+        Otherwise, treat each argument after the first as a subpath to the
+        given path, and return a list composed of the values at each of those
+        instead.  This operation is performed inside a transaction.
+        """
         while True:
             t = cls(path)
             try:
@@ -206,6 +259,12 @@
     Remove = classmethod(Remove)
 
     def List(cls, path, *args):
+        """If only one argument is given (path), list its contents, returning
+        the entries therein, or the empty list if no entries are found.
+        Otherwise, treat each further argument as a subpath to the given path,
+        and return the cumulative listing of each of those instead.  This
+        operation is performed inside a transaction.
+        """
         while True:
             t = cls(path)
             try:
@@ -218,6 +277,25 @@
 
     List = classmethod(List)
 
+    def ListRecursive(cls, path, *args):
+        """If only one argument is given (path), list its contents
+        recursively, returning the entries therein, or the empty list if no
+        entries are found.  Otherwise, treat each further argument as a
+        subpath to the given path, and return the cumulative listing of each
+        of those instead.  This operation is performed inside a transaction.
+        """
+        while True:
+            t = cls(path)
+            try:
+                v = t.list_recursive(*args)
+                if t.commit():
+                    return v
+            except:
+                t.abort()
+                raise
+
+    ListRecursive = classmethod(ListRecursive)
+
     def Gather(cls, path, *args):
         while True:
             t = cls(path)
diff -r 4e1031ce3bc2 -r 5e5ae8340956 tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py       Mon Sep 26 17:15:55 2005
+++ b/tools/python/xen/xm/main.py       Wed Sep 28 20:06:49 2005
@@ -175,6 +175,10 @@
 
     dom = args[0] # TODO: should check if this exists
     savefile = os.path.abspath(args[1])
+
+    if not os.access(os.path.dirname(savefile), os.W_OK):
+        err("xm save: Unable to create file %s" % savefile)
+        sys.exit(1)
     
     from xen.xend.XendClient import server
     server.xend_domain_save(dom, savefile)
@@ -183,6 +187,10 @@
     arg_check(args,1,"restore")
 
     savefile = os.path.abspath(args[0])
+
+    if not os.access(savefile, os.R_OK):
+        err("xm restore: Unable to read file %s" % savefile)
+        sys.exit(1)
 
     from xen.xend.XendClient import server
     info = server.xend_domain_restore(savefile)
diff -r 4e1031ce3bc2 -r 5e5ae8340956 tools/xenstore/xenstored_domain.c
--- a/tools/xenstore/xenstored_domain.c Mon Sep 26 17:15:55 2005
+++ b/tools/xenstore/xenstored_domain.c Wed Sep 28 20:06:49 2005
@@ -63,6 +63,8 @@
        /* The connection associated with this. */
        struct connection *conn;
 
+       /* Have we noticed that this domain is shutdown? */
+       int shutdown;
 };
 
 static LIST_HEAD(domains);
@@ -222,19 +224,25 @@
 {
        xc_dominfo_t dominfo;
        struct domain *domain, *tmp;
-       int released = 0;
+       int notify = 0;
 
        list_for_each_entry_safe(domain, tmp, &domains, list) {
                if (xc_domain_getinfo(*xc_handle, domain->domid, 1,
                                      &dominfo) == 1 &&
-                   dominfo.domid == domain->domid &&
-                   !dominfo.dying && !dominfo.crashed && !dominfo.shutdown)
-                       continue;
+                   dominfo.domid == domain->domid) {
+                       if ((dominfo.crashed || dominfo.shutdown)
+                           && !domain->shutdown) {
+                               domain->shutdown = 1;
+                               notify = 1;
+                       }
+                       if (!dominfo.dying)
+                               continue;
+               }
                talloc_free(domain->conn);
-               released++;
-       }
-
-       if (released)
+               notify = 1;
+       }
+
+       if (notify)
                fire_watches(NULL, "@releaseDomain", false);
 }
 
@@ -272,6 +280,7 @@
        struct domain *domain;
        domain = talloc(context, struct domain);
        domain->port = 0;
+       domain->shutdown = 0;
        domain->domid = domid;
        domain->path = talloc_strdup(domain, path);
        domain->page = xc_map_foreign_range(*xc_handle, domain->domid,
diff -r 4e1031ce3bc2 -r 5e5ae8340956 xen/arch/x86/shadow32.c
--- a/xen/arch/x86/shadow32.c   Mon Sep 26 17:15:55 2005
+++ b/xen/arch/x86/shadow32.c   Wed Sep 28 20:06:49 2005
@@ -755,9 +755,13 @@
 
     /*
      * Then free monitor_table.
+     * Note: for VMX guest, only BSP need do this free.
      */
-    mfn = pagetable_get_pfn(v->arch.monitor_table);
-    free_domheap_page(&frame_table[mfn]);
+    if (!(VMX_DOMAIN(v) && v->vcpu_id)) {
+        mfn = pagetable_get_pfn(v->arch.monitor_table);
+        unmap_domain_page(v->arch.monitor_vtable);
+        free_domheap_page(&frame_table[mfn]);
+    }
 
     v->arch.monitor_table = mk_pagetable(0);
     v->arch.monitor_vtable = 0;
diff -r 4e1031ce3bc2 -r 5e5ae8340956 xen/arch/x86/shadow_public.c
--- a/xen/arch/x86/shadow_public.c      Mon Sep 26 17:15:55 2005
+++ b/xen/arch/x86/shadow_public.c      Wed Sep 28 20:06:49 2005
@@ -256,14 +256,15 @@
 {
     unsigned long mfn;
 
-//    ASSERT( pagetable_val(v->arch.monitor_table) );
     /*
      * free monitor_table.
+     * Note: for VMX guest, only BSP need do this free.
      */
-    //mfn = (pagetable_val(v->arch.monitor_table)) >> PAGE_SHIFT;
-    mfn = pagetable_get_pfn(v->arch.monitor_table);
-    unmap_domain_page(v->arch.monitor_vtable);
-    free_domheap_page(&frame_table[mfn]);
+    if (!(VMX_DOMAIN(v) && v->vcpu_id)) {
+        mfn = pagetable_get_pfn(v->arch.monitor_table);
+        unmap_domain_page(v->arch.monitor_vtable);
+        free_domheap_page(&frame_table[mfn]);
+    }
     v->arch.monitor_table = mk_pagetable(0);
     v->arch.monitor_vtable = 0;
 }
@@ -358,9 +359,13 @@
 
     /*
      * Then free monitor_table.
+     * Note: for VMX guest, only BSP need do this free.
      */
-    mfn = pagetable_get_pfn(v->arch.monitor_table);
-    free_domheap_page(&frame_table[mfn]);
+    if (!(VMX_DOMAIN(v) && v->vcpu_id)) {
+        mfn = pagetable_get_pfn(v->arch.monitor_table);
+        unmap_domain_page(v->arch.monitor_vtable);
+        free_domheap_page(&frame_table[mfn]);
+    }
 
     v->arch.monitor_table = mk_pagetable(0);
     v->arch.monitor_vtable = 0;
diff -r 4e1031ce3bc2 -r 5e5ae8340956 xen/arch/x86/vmx_platform.c
--- a/xen/arch/x86/vmx_platform.c       Mon Sep 26 17:15:55 2005
+++ b/xen/arch/x86/vmx_platform.c       Wed Sep 28 20:06:49 2005
@@ -667,6 +667,7 @@
     mpcip->instr = inst->instr;
     mpcip->operand[0] = inst->operand[0]; /* source */
     mpcip->operand[1] = inst->operand[1]; /* destination */
+    mpcip->immediate = inst->immediate;
 
     if (inst->operand[0] & REGISTER) { /* dest is memory */
         index = operand_index(inst->operand[0]);
@@ -833,12 +834,16 @@
         mmio_operands(IOREQ_TYPE_XOR, gpa, &mmio_inst, mpcip, regs);
         break;
 
-    case INSTR_CMP:
-        mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs);
-        break;
-
+    case INSTR_CMP:        /* Pass through */
     case INSTR_TEST:
-        mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mpcip, regs);
+        mpcip->flags = mmio_inst.flags;
+        mpcip->instr = mmio_inst.instr;
+        mpcip->operand[0] = mmio_inst.operand[0]; /* source */
+        mpcip->operand[1] = mmio_inst.operand[1]; /* destination */
+        mpcip->immediate = mmio_inst.immediate;
+
+        /* send the request and wait for the value */
+        send_mmio_req(IOREQ_TYPE_COPY, gpa, 1, mmio_inst.op_size, 0, 
IOREQ_READ, 0);
         break;
 
     default:

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>