[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] merge with xen-unstable.hg



# HG changeset patch
# User awilliam@xxxxxxxxxxxx
# Date 1174425578 21600
# Node ID 2216a45bf0582b36f7e0efb0dde0abbacdd8b895
# Parent  f74e837c3902f85f775986b8f0235daadd2eb269
# Parent  3fd9b0c71b8c687b108a8bf671c9c4fc47046a0a
merge with xen-unstable.hg
---
 patches/linux-2.6.18/crash-kernel-32-on-64.patch                               
|    9 
 Config.mk                                                                      
|    6 
 docs/xen-api/xenapi-datamodel.tex                                              
|  241 ++-
 extras/mini-os/arch/x86/mm.c                                                   
|    4 
 extras/mini-os/gnttab.c                                                        
|    2 
 extras/mini-os/hypervisor.c                                                    
|    4 
 extras/mini-os/include/wait.h                                                  
|    7 
 extras/mini-os/include/xenbus.h                                                
|    1 
 extras/mini-os/xenbus/xenbus.c                                                 
|    3 
 linux-2.6-xen-sparse/arch/i386/kernel/vsyscall-note-xen.S                      
|    2 
 linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c                                
|   14 
 linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c                                 
|    6 
 linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c                             
|   98 -
 linux-2.6-xen-sparse/drivers/xen/netback/netback.c                             
|    2 
 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c                         
|   13 
 linux-2.6-xen-sparse/include/asm-i386/kexec.h                                  
|    3 
 linux-2.6-xen-sparse/mm/Kconfig                                                
|  157 ++
 patches/linux-2.6.18/allow-i386-crash-kernels-to-handle-x86_64-dumps-fix.patch 
|   28 
 patches/linux-2.6.18/allow-i386-crash-kernels-to-handle-x86_64-dumps.patch     
|   51 
 patches/linux-2.6.18/series                                                    
|    3 
 tools/Rules.mk                                                                 
|    5 
 tools/blktap/drivers/block-qcow.c                                              
|    1 
 tools/firmware/Makefile                                                        
|    2 
 tools/firmware/hvmloader/32bitbios_support.c                                   
|  178 +-
 tools/firmware/hvmloader/acpi/build.c                                          
|    1 
 tools/firmware/hvmloader/hvmloader.c                                           
|   67 -
 tools/firmware/hvmloader/smbios.c                                              
|   48 
 tools/firmware/hvmloader/util.c                                                
|   21 
 tools/firmware/hvmloader/util.h                                                
|   12 
 tools/firmware/rombios/rombios.c                                               
|  242 +--
 tools/ioemu/target-i386-dm/exec-dm.c                                           
|   16 
 tools/ioemu/target-i386-dm/helper2.c                                           
|   15 
 tools/ioemu/xenstore.c                                                         
|  179 ++
 tools/libxc/Makefile                                                           
|    2 
 tools/libxc/xc_core.c                                                          
|    6 
 tools/libxc/xc_core_x86.c                                                      
|   24 
 tools/libxc/xc_hvm_build.c                                                     
|    7 
 tools/libxc/xc_hvm_restore.c                                                   
|   31 
 tools/libxc/xc_hvm_save.c                                                      
|   69 -
 tools/libxc/xc_private.c                                                       
|   14 
 tools/libxc/xenguest.h                                                         
|    6 
 tools/libxc/xg_private.c                                                       
|    4 
 tools/libxen/include/xen_vbd.h                                                 
|    1 
 tools/libxen/include/xen_vdi.h                                                 
|   44 
 tools/libxen/src/xen_vbd.c                                                     
|    3 
 tools/libxen/src/xen_vdi.c                                                     
|   98 +
 tools/libxen/test/test_bindings.c                                              
|    3 
 tools/python/scripts/test_hvm_create.py                                        
|    3 
 tools/python/scripts/test_vm_create.py                                         
|    6 
 tools/python/scripts/xapi.py                                                   
|   11 
 tools/python/scripts/xapi.vdicfg.py                                            
|    3 
 tools/python/xen/lowlevel/xc/xc.c                                              
|   72 -
 tools/python/xen/util/blkif.py                                                 
|   17 
 tools/python/xen/util/xmlrpclib2.py                                            
|   40 
 tools/python/xen/xend/XendAPI.py                                               
|  153 +-
 tools/python/xen/xend/XendCheckpoint.py                                        
|    4 
 tools/python/xen/xend/XendConfig.py                                            
|  107 +
 tools/python/xen/xend/XendDomain.py                                            
|    2 
 tools/python/xen/xend/XendDomainInfo.py                                        
|  108 +
 tools/python/xen/xend/XendLogging.py                                           
|   12 
 tools/python/xen/xend/XendNode.py                                              
|    3 
 tools/python/xen/xend/XendVDI.py                                               
|   27 
 tools/python/xen/xm/create.dtd                                                 
|  118 +
 tools/python/xen/xm/create.py                                                  
|   83 -
 tools/python/xen/xm/main.py                                                    
|  370 ++++-
 tools/python/xen/xm/new.py                                                     
|   13 
 tools/python/xen/xm/shutdown.py                                                
|   26 
 tools/python/xen/xm/xenapi_create.py                                           
|  636 ++++++++++
 tools/xcutils/Makefile                                                         
|    6 
 tools/xcutils/xc_save.c                                                        
|  129 +-
 tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py              
|    4 
 tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py         
|    4 
 tools/xm-test/tests/network-attach/network_utils.py                            
|   19 
 unmodified_drivers/linux-2.6/platform-pci/evtchn.c                             
|    3 
 xen/arch/x86/Rules.mk                                                          
|   18 
 xen/arch/x86/hvm/hpet.c                                                        
|   24 
 xen/arch/x86/hvm/platform.c                                                    
|   11 
 xen/arch/x86/hvm/svm/svm.c                                                     
|  100 -
 xen/arch/x86/hvm/svm/vmcb.c                                                    
|   14 
 xen/arch/x86/hvm/svm/x86_32/exits.S                                            
|   40 
 xen/arch/x86/hvm/svm/x86_64/exits.S                                            
|   34 
 xen/arch/x86/hvm/vpic.c                                                        
|    4 
 xen/arch/x86/mm.c                                                              
|    6 
 xen/arch/x86/mm/shadow/common.c                                                
|    6 
 xen/arch/x86/x86_64/asm-offsets.c                                              
|    1 
 xen/arch/x86/x86_64/compat/entry.S                                             
|    4 
 xen/arch/x86/x86_64/compat/traps.c                                             
|    4 
 xen/arch/x86/x86_64/entry.S                                                    
|   30 
 xen/arch/x86/x86_64/traps.c                                                    
|   18 
 xen/common/compat/memory.c                                                     
|    2 
 xen/common/memory.c                                                            
|   15 
 xen/common/perfc.c                                                             
|   17 
 xen/include/asm-ia64/mm.h                                                      
|    2 
 xen/include/asm-powerpc/mm.h                                                   
|    2 
 xen/include/asm-x86/domain.h                                                   
|    3 
 xen/include/asm-x86/hvm/svm/svm.h                                              
|    2 
 xen/include/asm-x86/hvm/svm/vmcb.h                                             
|    2 
 xen/include/asm-x86/mm.h                                                       
|    1 
 xen/include/asm-x86/processor.h                                                
|    6 
 xen/include/public/arch-x86/xen-x86_32.h                                       
|    2 
 xen/include/public/foreign/Makefile                                            
|    2 
 xen/include/public/memory.h                                                    
|    5 
 xen/include/xen/trace.h                                                        
|   10 
 103 files changed, 3032 insertions(+), 1085 deletions(-)

diff -r f74e837c3902 -r 2216a45bf058 Config.mk
--- a/Config.mk Tue Mar 20 10:07:11 2007 -0600
+++ b/Config.mk Tue Mar 20 15:19:38 2007 -0600
@@ -35,6 +35,12 @@ endif
 # Usage: cflags-y += $(call cc-option,$(CC),-march=winchip-c6,-march=i586)
 cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc \
               /dev/null 2>&1`"; then echo "$(2)"; else echo "$(3)"; fi ;)
+
+# cc-ver
+# Usage: ifeq ($(call cc-ver,$(CC),0x030400),y)
+cc-ver = $(shell if [ $$((`$(1) -dumpversion | awk -F. \
+           '{ printf "0x%02x%02x%02x", $$1, $$2, $$3}'`)) -ge $$(($(2))) ]; \
+           then echo y; else echo n; fi ;)
 
 ifneq ($(debug),y)
 CFLAGS += -DNDEBUG
diff -r f74e837c3902 -r 2216a45bf058 docs/xen-api/xenapi-datamodel.tex
--- a/docs/xen-api/xenapi-datamodel.tex Tue Mar 20 10:07:11 2007 -0600
+++ b/docs/xen-api/xenapi-datamodel.tex Tue Mar 20 15:19:38 2007 -0600
@@ -9359,10 +9359,10 @@ Quals & Field & Type & Description \\
 $\mathit{RO}_\mathit{run}$ &  {\tt crash\_dumps} & (crashdump ref) Set & list 
of crash dumps that refer to this disk \\
 $\mathit{RW}$ &  {\tt virtual\_size} & int & size of disk as presented to the 
guest (in bytes). Note that, depending on storage backend type, requested size 
may not be respected exactly \\
 $\mathit{RO}_\mathit{run}$ &  {\tt physical\_utilisation} & int & amount of 
physical space that the disk image is currently taking up on the storage 
repository (in bytes) \\
-$\mathit{RO}_\mathit{ins}$ &  {\tt sector\_size} & int & sector size of VDI 
(in bytes) \\
 $\mathit{RO}_\mathit{ins}$ &  {\tt type} & vdi\_type & type of the VDI \\
 $\mathit{RW}$ &  {\tt sharable} & bool & true if this disk may be shared \\
 $\mathit{RW}$ &  {\tt read\_only} & bool & true if this disk may ONLY be 
mounted read-only \\
+$\mathit{RW}$ &  {\tt other\_config} & (string $\rightarrow$ string) Map & 
additional configuration \\
 \hline
 \end{longtable}
 \subsection{RPCs associated with class: VDI}
@@ -9812,13 +9812,13 @@ value of the field
 \vspace{0.3cm}
 \vspace{0.3cm}
 \vspace{0.3cm}
-\subsubsection{RPC name:~get\_sector\_size}
-
-{\bf Overview:} 
-Get the sector\_size field of the given VDI.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} int get_sector_size (session_id s, VDI ref self)\end{verbatim}
+\subsubsection{RPC name:~get\_type}
+
+{\bf Overview:} 
+Get the type field of the given VDI.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} (vdi_type) get_type (session_id s, VDI ref self)\end{verbatim}
 
 
 \noindent{\bf Arguments:}
@@ -9836,21 +9836,21 @@ Get the sector\_size field of the given 
 
  \noindent {\bf Return Type:} 
 {\tt 
-int
-}
-
-
-value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~get\_type}
-
-{\bf Overview:} 
-Get the type field of the given VDI.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} (vdi_type) get_type (session_id s, VDI ref self)\end{verbatim}
+vdi\_type
+}
+
+
+value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~get\_sharable}
+
+{\bf Overview:} 
+Get the sharable field of the given VDI.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} bool get_sharable (session_id s, VDI ref self)\end{verbatim}
 
 
 \noindent{\bf Arguments:}
@@ -9868,21 +9868,21 @@ Get the type field of the given VDI.
 
  \noindent {\bf Return Type:} 
 {\tt 
-vdi\_type
-}
-
-
-value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~get\_sharable}
-
-{\bf Overview:} 
-Get the sharable field of the given VDI.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} bool get_sharable (session_id s, VDI ref self)\end{verbatim}
+bool
+}
+
+
+value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~set\_sharable}
+
+{\bf Overview:} 
+Set the sharable field of the given VDI.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void set_sharable (session_id s, VDI ref self, bool 
value)\end{verbatim}
 
 
 \noindent{\bf Arguments:}
@@ -9894,6 +9894,40 @@ Get the sharable field of the given VDI.
 {\bf type} & {\bf name} & {\bf description} \\ \hline
 {\tt VDI ref } & self & reference to the object \\ \hline 
 
+{\tt bool } & value & New value to set \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~get\_read\_only}
+
+{\bf Overview:} 
+Get the read\_only field of the given VDI.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} bool get_read_only (session_id s, VDI ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VDI ref } & self & reference to the object \\ \hline 
+
 \end{tabular}
 
 \vspace{0.3cm}
@@ -9908,13 +9942,13 @@ value of the field
 \vspace{0.3cm}
 \vspace{0.3cm}
 \vspace{0.3cm}
-\subsubsection{RPC name:~set\_sharable}
-
-{\bf Overview:} 
-Set the sharable field of the given VDI.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} void set_sharable (session_id s, VDI ref self, bool 
value)\end{verbatim}
+\subsubsection{RPC name:~set\_read\_only}
+
+{\bf Overview:} 
+Set the read\_only field of the given VDI.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void set_read_only (session_id s, VDI ref self, bool 
value)\end{verbatim}
 
 
 \noindent{\bf Arguments:}
@@ -9942,13 +9976,13 @@ void
 \vspace{0.3cm}
 \vspace{0.3cm}
 \vspace{0.3cm}
-\subsubsection{RPC name:~get\_read\_only}
-
-{\bf Overview:} 
-Get the read\_only field of the given VDI.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} bool get_read_only (session_id s, VDI ref self)\end{verbatim}
+\subsubsection{RPC name:~get\_other\_config}
+
+{\bf Overview:} 
+Get the other\_config field of the given VDI.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} ((string -> string) Map) get_other_config (session_id s, VDI 
ref self)\end{verbatim}
 
 
 \noindent{\bf Arguments:}
@@ -9966,21 +10000,21 @@ Get the read\_only field of the given VD
 
  \noindent {\bf Return Type:} 
 {\tt 
-bool
-}
-
-
-value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~set\_read\_only}
-
-{\bf Overview:} 
-Set the read\_only field of the given VDI.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} void set_read_only (session_id s, VDI ref self, bool 
value)\end{verbatim}
+(string $\rightarrow$ string) Map
+}
+
+
+value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~set\_other\_config}
+
+{\bf Overview:} 
+Set the other\_config field of the given VDI.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void set_other_config (session_id s, VDI ref self, (string -> 
string) Map value)\end{verbatim}
 
 
 \noindent{\bf Arguments:}
@@ -9992,7 +10026,78 @@ Set the read\_only field of the given VD
 {\bf type} & {\bf name} & {\bf description} \\ \hline
 {\tt VDI ref } & self & reference to the object \\ \hline 
 
-{\tt bool } & value & New value to set \\ \hline 
+{\tt (string $\rightarrow$ string) Map } & value & New value to set \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~add\_to\_other\_config}
+
+{\bf Overview:} 
+Add the given key-value pair to the other\_config field of the given VDI.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void add_to_other_config (session_id s, VDI ref self, string 
key, string value)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VDI ref } & self & reference to the object \\ \hline 
+
+{\tt string } & key & Key to add \\ \hline 
+
+{\tt string } & value & Value to add \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~remove\_from\_other\_config}
+
+{\bf Overview:} 
+Remove the given key and its corresponding value from the other\_config
+field of the given VDI.  If the key is not in that Map, then do nothing.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void remove_from_other_config (session_id s, VDI ref self, 
string key)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VDI ref } & self & reference to the object \\ \hline 
+
+{\tt string } & key & Key to remove \\ \hline 
 
 \end{tabular}
 
diff -r f74e837c3902 -r 2216a45bf058 extras/mini-os/arch/x86/mm.c
--- a/extras/mini-os/arch/x86/mm.c      Tue Mar 20 10:07:11 2007 -0600
+++ b/extras/mini-os/arch/x86/mm.c      Tue Mar 20 15:19:38 2007 -0600
@@ -49,7 +49,7 @@
 #endif
 
 unsigned long *phys_to_machine_mapping;
-extern char *stack;
+extern char stack[];
 extern void page_walk(unsigned long virt_addr);
 
 void new_pt_frame(unsigned long *pt_pfn, unsigned long prev_l_mfn, 
@@ -453,7 +453,7 @@ void arch_init_mm(unsigned long* start_p
     printk("  _text:        %p\n", &_text);
     printk("  _etext:       %p\n", &_etext);
     printk("  _edata:       %p\n", &_edata);
-    printk("  stack start:  %p\n", &stack);
+    printk("  stack start:  %p\n", stack);
     printk("  _end:         %p\n", &_end);
 
     /* First page follows page table pages and 3 more pages (store page etc) */
diff -r f74e837c3902 -r 2216a45bf058 extras/mini-os/gnttab.c
--- a/extras/mini-os/gnttab.c   Tue Mar 20 10:07:11 2007 -0600
+++ b/extras/mini-os/gnttab.c   Tue Mar 20 15:19:38 2007 -0600
@@ -135,7 +135,7 @@ gnttab_alloc_and_grant(void **map)
     return gref;
 }
 
-static const char *gnttabop_error_msgs[] = GNTTABOP_error_msgs;
+static const char * const gnttabop_error_msgs[] = GNTTABOP_error_msgs;
 
 const char *
 gnttabop_error(int16_t status)
diff -r f74e837c3902 -r 2216a45bf058 extras/mini-os/hypervisor.c
--- a/extras/mini-os/hypervisor.c       Tue Mar 20 10:07:11 2007 -0600
+++ b/extras/mini-os/hypervisor.c       Tue Mar 20 15:19:38 2007 -0600
@@ -35,8 +35,8 @@
 
 void do_hypervisor_callback(struct pt_regs *regs)
 {
-    u32               l1, l2;
-    unsigned int   l1i, l2i, port;
+    unsigned long  l1, l2, l1i, l2i;
+    unsigned int   port;
     int            cpu = 0;
     shared_info_t *s = HYPERVISOR_shared_info;
     vcpu_info_t   *vcpu_info = &s->vcpu_info[cpu];
diff -r f74e837c3902 -r 2216a45bf058 extras/mini-os/include/wait.h
--- a/extras/mini-os/include/wait.h     Tue Mar 20 10:07:11 2007 -0600
+++ b/extras/mini-os/include/wait.h     Tue Mar 20 15:19:38 2007 -0600
@@ -74,6 +74,13 @@ static inline void wake_up(struct wait_q
     local_irq_restore(flags);   \
 } while (0)
 
+#define remove_waiter(w) do {   \
+    unsigned long flags;        \
+    local_irq_save(flags);      \
+    remove_wait_queue(&w);      \
+    local_irq_restore(flags);   \
+} while (0)
+
 #define wait_event(wq, condition) do{             \
     unsigned long flags;                          \
     if(condition)                                 \
diff -r f74e837c3902 -r 2216a45bf058 extras/mini-os/include/xenbus.h
--- a/extras/mini-os/include/xenbus.h   Tue Mar 20 10:07:11 2007 -0600
+++ b/extras/mini-os/include/xenbus.h   Tue Mar 20 15:19:38 2007 -0600
@@ -13,6 +13,7 @@ char *xenbus_read(xenbus_transaction_t x
 char *xenbus_read(xenbus_transaction_t xbt, const char *path, char **value);
 
 char *xenbus_watch_path(xenbus_transaction_t xbt, const char *path);
+void wait_for_watch(void);
 char* xenbus_wait_for_value(const char*,const char*);
 
 /* Associates a value with a path.  Returns a malloc'd error string on
diff -r f74e837c3902 -r 2216a45bf058 extras/mini-os/xenbus/xenbus.c
--- a/extras/mini-os/xenbus/xenbus.c    Tue Mar 20 10:07:11 2007 -0600
+++ b/extras/mini-os/xenbus/xenbus.c    Tue Mar 20 15:19:38 2007 -0600
@@ -72,11 +72,12 @@ static void memcpy_from_ring(const void 
     memcpy(dest + c1, ring, c2);
 }
 
-static inline void wait_for_watch(void)
+void wait_for_watch(void)
 {
     DEFINE_WAIT(w);
     add_waiter(w,watch_queue);
     schedule();
+    remove_waiter(w);
     wake(current);
 }
 
diff -r f74e837c3902 -r 2216a45bf058 
linux-2.6-xen-sparse/arch/i386/kernel/vsyscall-note-xen.S
--- a/linux-2.6-xen-sparse/arch/i386/kernel/vsyscall-note-xen.S Tue Mar 20 
10:07:11 2007 -0600
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/vsyscall-note-xen.S Tue Mar 20 
15:19:38 2007 -0600
@@ -28,5 +28,5 @@
 #define NOTE_KERNELCAP_END ASM_ELF_NOTE_END
 
 NOTE_KERNELCAP_BEGIN(1, 1)
-NOTE_KERNELCAP(1, "nosegneg")  /* Change 1 back to 0 when glibc is fixed! */
+NOTE_KERNELCAP(0, "nosegneg")
 NOTE_KERNELCAP_END
diff -r f74e837c3902 -r 2216a45bf058 
linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c   Tue Mar 20 10:07:11 
2007 -0600
+++ b/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c   Tue Mar 20 15:19:38 
2007 -0600
@@ -256,8 +256,9 @@ void pte_free(struct page *pte)
                unsigned long va = (unsigned long)__va(pfn << PAGE_SHIFT);
 
                if (!pte_write(*virt_to_ptep(va)))
-                       BUG_ON(HYPERVISOR_update_va_mapping(
-                              va, pfn_pte(pfn, PAGE_KERNEL), 0));
+                       if (HYPERVISOR_update_va_mapping(
+                               va, pfn_pte(pfn, PAGE_KERNEL), 0))
+                               BUG();
        } else
                clear_bit(PG_pinned, &pte->flags);
 
@@ -672,14 +673,23 @@ void mm_pin_all(void)
 void mm_pin_all(void)
 {
        struct page *page;
+       unsigned long flags;
 
        if (xen_feature(XENFEAT_writable_page_tables))
                return;
 
+       /*
+        * Allow uninterrupted access to the pgd_list. Also protects
+        * __pgd_pin() by disabling preemption.
+        * All other CPUs must be at a safe point (e.g., in stop_machine
+        * or offlined entirely).
+        */
+       spin_lock_irqsave(&pgd_lock, flags);
        for (page = pgd_list; page; page = (struct page *)page->index) {
                if (!test_bit(PG_pinned, &page->flags))
                        __pgd_pin((pgd_t *)page_address(page));
        }
+       spin_unlock_irqrestore(&pgd_lock, flags);
 }
 
 void _arch_dup_mmap(struct mm_struct *mm)
diff -r f74e837c3902 -r 2216a45bf058 
linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c
--- a/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c    Tue Mar 20 10:07:11 
2007 -0600
+++ b/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c    Tue Mar 20 15:19:38 
2007 -0600
@@ -597,8 +597,10 @@ void __init xen_init_pt(void)
        early_make_page_readonly(level2_kernel_pgt,
                                 XENFEAT_writable_page_tables);
 
-       xen_pgd_pin(__pa_symbol(init_level4_pgt));
-       xen_pgd_pin(__pa_symbol(init_level4_user_pgt));
+       if (!xen_feature(XENFEAT_writable_page_tables)) {
+               xen_pgd_pin(__pa_symbol(init_level4_pgt));
+               xen_pgd_pin(__pa_symbol(init_level4_user_pgt));
+       }
 
        set_pgd((pgd_t *)(init_level4_user_pgt + 511), 
                mk_kernel_pgd(__pa_symbol(level3_user_pgt)));
diff -r f74e837c3902 -r 2216a45bf058 
linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c
--- a/linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c        Tue Mar 20 
10:07:11 2007 -0600
+++ b/linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c        Tue Mar 20 
15:19:38 2007 -0600
@@ -79,14 +79,17 @@ void mm_pin(struct mm_struct *mm)
        spin_lock(&mm->page_table_lock);
 
        mm_walk(mm, PAGE_KERNEL_RO);
-       BUG_ON(HYPERVISOR_update_va_mapping(
-                      (unsigned long)mm->pgd,
-                      pfn_pte(virt_to_phys(mm->pgd)>>PAGE_SHIFT, 
PAGE_KERNEL_RO),
-                      UVMF_TLB_FLUSH));
-       BUG_ON(HYPERVISOR_update_va_mapping(
-                      (unsigned long)__user_pgd(mm->pgd),
-                      pfn_pte(virt_to_phys(__user_pgd(mm->pgd))>>PAGE_SHIFT, 
PAGE_KERNEL_RO),
-                      UVMF_TLB_FLUSH));
+       if (HYPERVISOR_update_va_mapping(
+               (unsigned long)mm->pgd,
+               pfn_pte(virt_to_phys(mm->pgd)>>PAGE_SHIFT, PAGE_KERNEL_RO),
+               UVMF_TLB_FLUSH))
+               BUG();
+       if (HYPERVISOR_update_va_mapping(
+               (unsigned long)__user_pgd(mm->pgd),
+               pfn_pte(virt_to_phys(__user_pgd(mm->pgd))>>PAGE_SHIFT,
+                       PAGE_KERNEL_RO),
+               UVMF_TLB_FLUSH))
+               BUG();
        xen_pgd_pin(__pa(mm->pgd)); /* kernel */
        xen_pgd_pin(__pa(__user_pgd(mm->pgd))); /* user */
        mm->context.pinned = 1;
@@ -106,12 +109,15 @@ void mm_unpin(struct mm_struct *mm)
 
        xen_pgd_unpin(__pa(mm->pgd));
        xen_pgd_unpin(__pa(__user_pgd(mm->pgd)));
-       BUG_ON(HYPERVISOR_update_va_mapping(
-                      (unsigned long)mm->pgd,
-                      pfn_pte(virt_to_phys(mm->pgd)>>PAGE_SHIFT, PAGE_KERNEL), 
0));
-       BUG_ON(HYPERVISOR_update_va_mapping(
-                      (unsigned long)__user_pgd(mm->pgd),
-                      pfn_pte(virt_to_phys(__user_pgd(mm->pgd))>>PAGE_SHIFT, 
PAGE_KERNEL), 0));
+       if (HYPERVISOR_update_va_mapping(
+               (unsigned long)mm->pgd,
+               pfn_pte(virt_to_phys(mm->pgd)>>PAGE_SHIFT, PAGE_KERNEL), 0))
+               BUG();
+       if (HYPERVISOR_update_va_mapping(
+               (unsigned long)__user_pgd(mm->pgd),
+               pfn_pte(virt_to_phys(__user_pgd(mm->pgd))>>PAGE_SHIFT,
+                       PAGE_KERNEL), 0))
+               BUG();
        mm_walk(mm, PAGE_KERNEL);
        xen_tlb_flush();
        mm->context.pinned = 0;
@@ -127,43 +133,50 @@ void mm_pin_all(void)
        if (xen_feature(XENFEAT_writable_page_tables))
                return;
 
+       /*
+        * Allow uninterrupted access to the mm_unpinned list. We don't
+        * actually take the mm_unpinned_lock as it is taken inside mm_pin().
+        * All other CPUs must be at a safe point (e.g., in stop_machine
+        * or offlined entirely).
+        */
+       preempt_disable();
        while (!list_empty(&mm_unpinned))       
                mm_pin(list_entry(mm_unpinned.next, struct mm_struct,
                                  context.unpinned));
+       preempt_enable();
 }
 
 void _arch_dup_mmap(struct mm_struct *mm)
 {
-    if (!mm->context.pinned)
-        mm_pin(mm);
+       if (!mm->context.pinned)
+               mm_pin(mm);
 }
 
 void _arch_exit_mmap(struct mm_struct *mm)
 {
-    struct task_struct *tsk = current;
-
-    task_lock(tsk);
-
-    /*
-     * We aggressively remove defunct pgd from cr3. We execute unmap_vmas()
-     * *much* faster this way, as no tlb flushes means bigger wrpt batches.
-     */
-    if ( tsk->active_mm == mm )
-    {
-        tsk->active_mm = &init_mm;
-        atomic_inc(&init_mm.mm_count);
-
-        switch_mm(mm, &init_mm, tsk);
-
-        atomic_dec(&mm->mm_count);
-        BUG_ON(atomic_read(&mm->mm_count) == 0);
-    }
-
-    task_unlock(tsk);
-
-    if ( mm->context.pinned && (atomic_read(&mm->mm_count) == 1) &&
-         !mm->context.has_foreign_mappings )
-        mm_unpin(mm);
+       struct task_struct *tsk = current;
+
+       task_lock(tsk);
+
+       /*
+        * We aggressively remove defunct pgd from cr3. We execute unmap_vmas()
+        * *much* faster this way, as no tlb flushes means bigger wrpt batches.
+        */
+       if (tsk->active_mm == mm) {
+               tsk->active_mm = &init_mm;
+               atomic_inc(&init_mm.mm_count);
+
+               switch_mm(mm, &init_mm, tsk);
+
+               atomic_dec(&mm->mm_count);
+               BUG_ON(atomic_read(&mm->mm_count) == 0);
+       }
+
+       task_unlock(tsk);
+
+       if ( mm->context.pinned && (atomic_read(&mm->mm_count) == 1) &&
+            !mm->context.has_foreign_mappings )
+               mm_unpin(mm);
 }
 
 struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
@@ -183,8 +196,9 @@ void pte_free(struct page *pte)
        unsigned long va = (unsigned long)__va(page_to_pfn(pte)<<PAGE_SHIFT);
 
        if (!pte_write(*virt_to_ptep(va)))
-               BUG_ON(HYPERVISOR_update_va_mapping(
-                       va, pfn_pte(page_to_pfn(pte), PAGE_KERNEL), 0));
+               if (HYPERVISOR_update_va_mapping(
+                       va, pfn_pte(page_to_pfn(pte), PAGE_KERNEL), 0))
+                       BUG();
 
        ClearPageForeign(pte);
        init_page_count(pte);
diff -r f74e837c3902 -r 2216a45bf058 
linux-2.6-xen-sparse/drivers/xen/netback/netback.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c        Tue Mar 20 
10:07:11 2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c        Tue Mar 20 
15:19:38 2007 -0600
@@ -1267,7 +1267,7 @@ static void net_tx_action(unsigned long 
 
                /* Check the remap error code. */
                if (unlikely(netbk_tx_check_mop(skb, &mop))) {
-                       printk(KERN_ALERT "#### netback grant fails\n");
+                       DPRINTK("netback grant failed.\n");
                        skb_shinfo(skb)->nr_frags = 0;
                        kfree_skb(skb);
                        continue;
diff -r f74e837c3902 -r 2216a45bf058 
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c    Tue Mar 20 
10:07:11 2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c    Tue Mar 20 
15:19:38 2007 -0600
@@ -110,7 +110,6 @@ int xb_write(const void *data, unsigned 
                /* Read indexes, then verify. */
                cons = intf->req_cons;
                prod = intf->req_prod;
-               mb();
                if (!check_indexes(cons, prod)) {
                        intf->req_cons = intf->req_prod = 0;
                        return -EIO;
@@ -122,15 +121,18 @@ int xb_write(const void *data, unsigned 
                if (avail > len)
                        avail = len;
 
+               /* Must write data /after/ reading the consumer index. */
+               mb();
+
                memcpy(dst, data, avail);
                data += avail;
                len -= avail;
 
-               /* Other side must not see new header until data is there. */
+               /* Other side must not see new producer until data is there. */
                wmb();
                intf->req_prod += avail;
 
-               /* This implies mb() before other side sees interrupt. */
+               /* Implies mb(): other side will see the updated producer. */
                notify_remote_via_evtchn(xen_store_evtchn);
        }
 
@@ -165,7 +167,6 @@ int xb_read(void *data, unsigned len)
                /* Read indexes, then verify. */
                cons = intf->rsp_cons;
                prod = intf->rsp_prod;
-               mb();
                if (!check_indexes(cons, prod)) {
                        intf->rsp_cons = intf->rsp_prod = 0;
                        return -EIO;
@@ -177,7 +178,7 @@ int xb_read(void *data, unsigned len)
                if (avail > len)
                        avail = len;
 
-               /* We must read header before we read data. */
+               /* Must read data /after/ reading the producer index. */
                rmb();
 
                memcpy(data, src, avail);
@@ -190,7 +191,7 @@ int xb_read(void *data, unsigned len)
 
                pr_debug("Finished read of %i bytes (%i to go)\n", avail, len);
 
-               /* Implies mb(): they will see new header. */
+               /* Implies mb(): other side will see the updated consumer. */
                notify_remote_via_evtchn(xen_store_evtchn);
        }
 
diff -r f74e837c3902 -r 2216a45bf058 
linux-2.6-xen-sparse/include/asm-i386/kexec.h
--- a/linux-2.6-xen-sparse/include/asm-i386/kexec.h     Tue Mar 20 10:07:11 
2007 -0600
+++ b/linux-2.6-xen-sparse/include/asm-i386/kexec.h     Tue Mar 20 15:19:38 
2007 -0600
@@ -46,6 +46,9 @@
 
 /* The native architecture */
 #define KEXEC_ARCH KEXEC_ARCH_386
+
+/* We can also handle crash dumps from 64 bit kernel. */
+#define vmcore_elf_check_arch_cross(x) ((x)->e_machine == EM_X86_64)
 
 #define MAX_NOTE_BYTES 1024
 
diff -r f74e837c3902 -r 2216a45bf058 linux-2.6-xen-sparse/mm/Kconfig
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/linux-2.6-xen-sparse/mm/Kconfig   Tue Mar 20 15:19:38 2007 -0600
@@ -0,0 +1,157 @@
+config SELECT_MEMORY_MODEL
+       def_bool y
+       depends on EXPERIMENTAL || ARCH_SELECT_MEMORY_MODEL
+
+choice
+       prompt "Memory model"
+       depends on SELECT_MEMORY_MODEL
+       default DISCONTIGMEM_MANUAL if ARCH_DISCONTIGMEM_DEFAULT
+       default SPARSEMEM_MANUAL if ARCH_SPARSEMEM_DEFAULT
+       default FLATMEM_MANUAL
+
+config FLATMEM_MANUAL
+       bool "Flat Memory"
+       depends on !(ARCH_DISCONTIGMEM_ENABLE || ARCH_SPARSEMEM_ENABLE) || 
ARCH_FLATMEM_ENABLE
+       help
+         This option allows you to change some of the ways that
+         Linux manages its memory internally.  Most users will
+         only have one option here: FLATMEM.  This is normal
+         and a correct option.
+
+         Some users of more advanced features like NUMA and
+         memory hotplug may have different options here.
+         DISCONTIGMEM is an more mature, better tested system,
+         but is incompatible with memory hotplug and may suffer
+         decreased performance over SPARSEMEM.  If unsure between
+         "Sparse Memory" and "Discontiguous Memory", choose
+         "Discontiguous Memory".
+
+         If unsure, choose this option (Flat Memory) over any other.
+
+config DISCONTIGMEM_MANUAL
+       bool "Discontiguous Memory"
+       depends on ARCH_DISCONTIGMEM_ENABLE
+       help
+         This option provides enhanced support for discontiguous
+         memory systems, over FLATMEM.  These systems have holes
+         in their physical address spaces, and this option provides
+         more efficient handling of these holes.  However, the vast
+         majority of hardware has quite flat address spaces, and
+         can have degraded performance from extra overhead that
+         this option imposes.
+
+         Many NUMA configurations will have this as the only option.
+
+         If unsure, choose "Flat Memory" over this option.
+
+config SPARSEMEM_MANUAL
+       bool "Sparse Memory"
+       depends on ARCH_SPARSEMEM_ENABLE
+       help
+         This will be the only option for some systems, including
+         memory hotplug systems.  This is normal.
+
+         For many other systems, this will be an alternative to
+         "Discontiguous Memory".  This option provides some potential
+         performance benefits, along with decreased code complexity,
+         but it is newer, and more experimental.
+
+         If unsure, choose "Discontiguous Memory" or "Flat Memory"
+         over this option.
+
+endchoice
+
+config DISCONTIGMEM
+       def_bool y
+       depends on (!SELECT_MEMORY_MODEL && ARCH_DISCONTIGMEM_ENABLE) || 
DISCONTIGMEM_MANUAL
+
+config SPARSEMEM
+       def_bool y
+       depends on SPARSEMEM_MANUAL
+
+config FLATMEM
+       def_bool y
+       depends on (!DISCONTIGMEM && !SPARSEMEM) || FLATMEM_MANUAL
+
+config FLAT_NODE_MEM_MAP
+       def_bool y
+       depends on !SPARSEMEM
+
+#
+# Both the NUMA code and DISCONTIGMEM use arrays of pg_data_t's
+# to represent different areas of memory.  This variable allows
+# those dependencies to exist individually.
+#
+config NEED_MULTIPLE_NODES
+       def_bool y
+       depends on DISCONTIGMEM || NUMA
+
+config HAVE_MEMORY_PRESENT
+       def_bool y
+       depends on ARCH_HAVE_MEMORY_PRESENT || SPARSEMEM
+
+#
+# SPARSEMEM_EXTREME (which is the default) does some bootmem
+# allocations when memory_present() is called.  If this can not
+# be done on your architecture, select this option.  However,
+# statically allocating the mem_section[] array can potentially
+# consume vast quantities of .bss, so be careful.
+#
+# This option will also potentially produce smaller runtime code
+# with gcc 3.4 and later.
+#
+config SPARSEMEM_STATIC
+       def_bool n
+
+#
+# Architectecture platforms which require a two level mem_section in SPARSEMEM
+# must select this option. This is usually for architecture platforms with
+# an extremely sparse physical address space.
+#
+config SPARSEMEM_EXTREME
+       def_bool y
+       depends on SPARSEMEM && !SPARSEMEM_STATIC
+
+# eventually, we can have this option just 'select SPARSEMEM'
+config MEMORY_HOTPLUG
+       bool "Allow for memory hot-add"
+       depends on SPARSEMEM && HOTPLUG && !SOFTWARE_SUSPEND && 
ARCH_ENABLE_MEMORY_HOTPLUG
+       depends on (IA64 || X86 || PPC64)
+
+comment "Memory hotplug is currently incompatible with Software Suspend"
+       depends on SPARSEMEM && HOTPLUG && SOFTWARE_SUSPEND
+
+# Heavily threaded applications may benefit from splitting the mm-wide
+# page_table_lock, so that faults on different parts of the user address
+# space can be handled with less contention: split it at this NR_CPUS.
+# Default to 4 for wider testing, though 8 might be more appropriate.
+# ARM's adjust_pte (unused if VIPT) depends on mm-wide page_table_lock.
+# PA-RISC 7xxx's spinlock_t would enlarge struct page from 32 to 44 bytes.
+# XEN on x86 architecture uses the mapping field on pagetable pages to store a
+# pointer to the destructor. This conflicts with pte_lock_deinit().
+#
+config SPLIT_PTLOCK_CPUS
+       int
+       default "4096" if ARM && !CPU_CACHE_VIPT
+       default "4096" if PARISC && !PA20
+       default "4096" if X86_XEN || X86_64_XEN
+       default "4"
+
+#
+# support for page migration
+#
+config MIGRATION
+       bool "Page migration"
+       def_bool y
+       depends on NUMA
+       help
+         Allows the migration of the physical location of pages of processes
+         while the virtual addresses are not changed. This is useful for
+         example on NUMA systems to put pages nearer to the processors 
accessing
+         the page.
+
+config RESOURCES_64BIT
+       bool "64 bit Memory and IO resources (EXPERIMENTAL)" if (!64BIT && 
EXPERIMENTAL)
+       default 64BIT
+       help
+         This option allows memory and IO resources to be 64 bit.
diff -r f74e837c3902 -r 2216a45bf058 
patches/linux-2.6.18/allow-i386-crash-kernels-to-handle-x86_64-dumps-fix.patch
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ 
b/patches/linux-2.6.18/allow-i386-crash-kernels-to-handle-x86_64-dumps-fix.patch
    Tue Mar 20 15:19:38 2007 -0600
@@ -0,0 +1,30 @@
+From: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
+
+In file included from arch/i386/kernel/setup.c:46:
+include/linux/crash_dump.h:19:36: warning: extra tokens at end of #ifndef 
directive
+
+Cc: "Eric W. Biederman" <ebiederm@xxxxxxxxxxxx>
+Cc: Andi Kleen <ak@xxxxxxx>
+Cc: Horms <horms@xxxxxxxxxxxx>
+Cc: Ian Campbell <ian.campbell@xxxxxxxxxxxxx>
+Cc: Magnus Damm <magnus.damm@xxxxxxxxx>
+Cc: Vivek Goyal <vgoyal@xxxxxxxxxx>
+Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
+---
+
+ include/linux/crash_dump.h |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff -puN 
include/linux/crash_dump.h~allow-i386-crash-kernels-to-handle-x86_64-dumps-fix 
include/linux/crash_dump.h
+--- 
a/include/linux/crash_dump.h~allow-i386-crash-kernels-to-handle-x86_64-dumps-fix
++++ a/include/linux/crash_dump.h
+@@ -16,7 +16,7 @@ extern struct proc_dir_entry *proc_vmcor
+ 
+ /* Architecture code defines this if there are other possible ELF
+  * machine types, e.g. on bi-arch capable hardware. */
+-#ifndef vmcore_elf_check_arch_cross(x)
++#ifndef vmcore_elf_check_arch_cross
+ #define vmcore_elf_check_arch_cross(x) 0
+ #endif
+ 
+_
diff -r f74e837c3902 -r 2216a45bf058 
patches/linux-2.6.18/allow-i386-crash-kernels-to-handle-x86_64-dumps.patch
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ 
b/patches/linux-2.6.18/allow-i386-crash-kernels-to-handle-x86_64-dumps.patch    
    Tue Mar 20 15:19:38 2007 -0600
@@ -0,0 +1,66 @@
+From: Ian Campbell <ian.campbell@xxxxxxxxxxxxx>
+
+The specific case I am encountering is kdump under Xen with a 64 bit
+hypervisor and 32 bit kernel/userspace.  The dump created is 64 bit due to
+the hypervisor but the dump kernel is 32 bit for maximum compatibility.
+
+It's possibly less likely to be useful in a purely native scenario but I
+see no reason to disallow it.
+
+Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxxxxx>
+Acked-by: Vivek Goyal <vgoyal@xxxxxxxxxx>
+Cc: Horms <horms@xxxxxxxxxxxx>
+Cc: Magnus Damm <magnus.damm@xxxxxxxxx>
+Cc: "Eric W. Biederman" <ebiederm@xxxxxxxxxxxx>
+Cc: Andi Kleen <ak@xxxxxxx>
+Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
+---
+
+ fs/proc/vmcore.c           |    2 +-
+ include/asm-i386/kexec.h   |    3 +++
+ include/linux/crash_dump.h |    8 ++++++++
+ 3 files changed, 12 insertions(+), 1 deletion(-)
+
+diff -puN fs/proc/vmcore.c~allow-i386-crash-kernels-to-handle-x86_64-dumps 
fs/proc/vmcore.c
+--- a/fs/proc/vmcore.c~allow-i386-crash-kernels-to-handle-x86_64-dumps
++++ a/fs/proc/vmcore.c
+@@ -514,7 +514,7 @@ static int __init parse_crash_elf64_head
+       /* Do some basic Verification. */
+       if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 ||
+               (ehdr.e_type != ET_CORE) ||
+-              !elf_check_arch(&ehdr) ||
++              !vmcore_elf_check_arch(&ehdr) ||
+               ehdr.e_ident[EI_CLASS] != ELFCLASS64 ||
+               ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
+               ehdr.e_version != EV_CURRENT ||
+diff -puN 
include/asm-i386/kexec.h~allow-i386-crash-kernels-to-handle-x86_64-dumps 
include/asm-i386/kexec.h
+--- a/include/asm-i386/kexec.h~allow-i386-crash-kernels-to-handle-x86_64-dumps
++++ a/include/asm-i386/kexec.h
+@@ -47,6 +47,9 @@
+ /* The native architecture */
+ #define KEXEC_ARCH KEXEC_ARCH_386
+ 
++/* We can also handle crash dumps from 64 bit kernel. */
++#define vmcore_elf_check_arch_cross(x) ((x)->e_machine == EM_X86_64)
++
+ #define MAX_NOTE_BYTES 1024
+ 
+ /* CPU does not save ss and esp on stack if execution is already
+diff -puN 
include/linux/crash_dump.h~allow-i386-crash-kernels-to-handle-x86_64-dumps 
include/linux/crash_dump.h
+--- 
a/include/linux/crash_dump.h~allow-i386-crash-kernels-to-handle-x86_64-dumps
++++ a/include/linux/crash_dump.h
+@@ -14,5 +14,13 @@ extern ssize_t copy_oldmem_page(unsigned
+ extern const struct file_operations proc_vmcore_operations;
+ extern struct proc_dir_entry *proc_vmcore;
+ 
++/* Architecture code defines this if there are other possible ELF
++ * machine types, e.g. on bi-arch capable hardware. */
++#ifndef vmcore_elf_check_arch_cross(x)
++#define vmcore_elf_check_arch_cross(x) 0
++#endif
++
++#define vmcore_elf_check_arch(x) (elf_check_arch(x) || 
vmcore_elf_check_arch_cross(x))
++
+ #endif /* CONFIG_CRASH_DUMP */
+ #endif /* LINUX_CRASHDUMP_H */
+_
diff -r f74e837c3902 -r 2216a45bf058 
patches/linux-2.6.18/crash-kernel-32-on-64.patch
--- a/patches/linux-2.6.18/crash-kernel-32-on-64.patch  Tue Mar 20 10:07:11 
2007 -0600
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
---- pristine-linux-2.6.18/include/asm-i386/elf.h       2006-09-20 
04:42:06.000000000 +0100
-+++ linux-2.6.18-xen/include/asm-i386/elf.h    2007-03-14 16:42:30.000000000 
+0000
-@@ -36,7 +36,7 @@
-  * This is used to ensure we don't load something for the wrong architecture.
-  */
- #define elf_check_arch(x) \
--      (((x)->e_machine == EM_386) || ((x)->e_machine == EM_486))
-+      (((x)->e_machine == EM_386) || ((x)->e_machine == EM_486) || 
((x)->e_machine == EM_X86_64))
- 
- /*
-  * These are used to set parameters in the core dumps.
diff -r f74e837c3902 -r 2216a45bf058 patches/linux-2.6.18/series
--- a/patches/linux-2.6.18/series       Tue Mar 20 10:07:11 2007 -0600
+++ b/patches/linux-2.6.18/series       Tue Mar 20 15:19:38 2007 -0600
@@ -19,4 +19,5 @@ fixaddr-top.patch
 fixaddr-top.patch
 git-c06cb8b1c4d25e5b4d7a2d7c2462619de1e0dbc4.patch
 softlockup-no-idle-hz.patch
-crash-kernel-32-on-64.patch
+allow-i386-crash-kernels-to-handle-x86_64-dumps.patch
+allow-i386-crash-kernels-to-handle-x86_64-dumps-fix.patch
diff -r f74e837c3902 -r 2216a45bf058 tools/Rules.mk
--- a/tools/Rules.mk    Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/Rules.mk    Tue Mar 20 15:19:38 2007 -0600
@@ -22,6 +22,11 @@ LDFLAGS += $(shell getconf LFS_LDFLAGS)
 # 32-bit x86 does not perform well with -ve segment accesses on Xen.
 CFLAGS-$(CONFIG_X86_32) += $(call cc-option,$(CC),-mno-tls-direct-seg-refs)
 CFLAGS += $(CFLAGS-y)
+
+# Require GCC v3.4+ (to avoid issues with alignment constraints in Xen headers)
+ifeq ($(CONFIG_X86)$(call cc-ver,$(CC),0x030400),yn)
+$(error Xen tools require at least gcc-3.4)
+endif
 
 %.opic: %.c
        $(CC) $(CPPFLAGS) -DPIC $(CFLAGS) -fPIC -c -o $@ $<
diff -r f74e837c3902 -r 2216a45bf058 tools/blktap/drivers/block-qcow.c
--- a/tools/blktap/drivers/block-qcow.c Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/blktap/drivers/block-qcow.c Tue Mar 20 15:19:38 2007 -0600
@@ -1057,6 +1057,7 @@ int tdqcow_queue_write(struct disk_drive
                                                    index_in_cluster+n);
                if (!cluster_offset) {
                        DPRINTF("Ooops, no write cluster offset!\n");
+                       aio_unlock(s, sector);
                        return cb(dd, -EIO, sector, nb_sectors, id, private);
                }
 
diff -r f74e837c3902 -r 2216a45bf058 tools/firmware/Makefile
--- a/tools/firmware/Makefile   Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/firmware/Makefile   Tue Mar 20 15:19:38 2007 -0600
@@ -14,7 +14,7 @@ SUBDIRS += hvmloader
 
 .PHONY: all
 all:
-       @set -e; if [ $$((`bcc -v 2>&1 | grep version | cut -d' ' -f 3 | awk 
-F. '{ printf "0x%02x%02x%02x", $$1, $$2, $$3}'`)) -lt $$((0x00100e)) ] ; then \
+       @set -e; if [ $$((`( bcc -v 2>&1 | grep version || echo 0.0.0 ) | cut 
-d' ' -f 3 | awk -F. '{ printf "0x%02x%02x%02x", $$1, $$2, $$3}'`)) -lt 
$$((0x00100e)) ] ; then \
        echo "***********************************************************"; \
        echo "Require dev86 package version >= 0.16.14 to build firmware!"; \
        echo "(visit http://www.cix.co.uk/~mayday for more information)"; \
diff -r f74e837c3902 -r 2216a45bf058 
tools/firmware/hvmloader/32bitbios_support.c
--- a/tools/firmware/hvmloader/32bitbios_support.c      Tue Mar 20 10:07:11 
2007 -0600
+++ b/tools/firmware/hvmloader/32bitbios_support.c      Tue Mar 20 15:19:38 
2007 -0600
@@ -17,157 +17,129 @@
  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  * Place - Suite 330, Boston, MA 02111-1307 USA.
  */
+
 #include <inttypes.h>
 #include <elf.h>
 #ifdef __sun__
 #include <sys/machelf.h>
 #endif
 
-#include <xen/hvm/e820.h>
 #include "util.h"
 #include "config.h"
 
 #include "../rombios/32bit/32bitbios_flat.h"
 #include "../rombios/32bit/jumptable.h"
 
-
-/*
- * relocate ELF file of type ET_REL
- */
-static int relocate_elf(unsigned char *elfarray) {
+/* Relocate ELF file of type ET_REL */
+static void relocate_elf(char *elfarray)
+{
     Elf32_Ehdr *ehdr = (Elf32_Ehdr *)elfarray;
     Elf32_Shdr *shdr = (Elf32_Shdr *)&elfarray[ehdr->e_shoff];
-    int i;
+    Elf32_Sym  *syms, *sym;
+    Elf32_Rel  *rels;
+    char       *code;
+    uint32_t   *loc, fix;
+    int i, j;
 
-    if (ehdr->e_type != ET_REL) {
-        printf("Not a relocatable BIOS object file. Has type %d, need %d\n",
-               ehdr->e_type, ET_REL);
-        return -1;
-    }
-
-    for (i = 0; i < ehdr->e_shnum; i++)
+    for ( i = 0; i < ehdr->e_shnum; i++ )
         shdr[i].sh_addr = (Elf32_Addr)&elfarray[shdr[i].sh_offset];
 
-    for (i = 0; i < ehdr->e_shnum; i++) {
-        if (shdr[i].sh_type == SHT_REL) {
-            Elf32_Shdr *targetsec = (Elf32_Shdr *)&(shdr[shdr[i].sh_info]);
-            Elf32_Shdr *symtabsec = (Elf32_Shdr *)&(shdr[shdr[i].sh_link]);
-            Elf32_Sym  *syms      = (Elf32_Sym *)symtabsec->sh_addr;
-            Elf32_Rel  *rels      = (Elf32_Rel *)shdr[i].sh_addr;
-            unsigned char *code   = (unsigned char *)targetsec->sh_addr;
-            int j;
+    for ( i = 0; i < ehdr->e_shnum; i++ )
+    {
+        if ( shdr[i].sh_type == SHT_RELA )
+            printf("Unsupported section type SHT_RELA\n");
 
-            /* must not have been stripped */
-            if (shdr[i].sh_size == 0)
-                return -6;
+        if ( shdr[i].sh_type != SHT_REL )
+            continue;
 
-            for (j = 0; j < shdr[i].sh_size / sizeof(Elf32_Rel); j++) {
-                int idx           = ELF32_R_SYM(rels[j].r_info);
-                Elf32_Sym *symbol = &syms[idx];
-                uint32_t *loc     = (uint32_t *)&code[rels[j].r_offset];
-                uint32_t fix      = shdr[symbol->st_shndx].sh_addr +
-                                    symbol->st_value;
+        syms = (Elf32_Sym *)shdr[shdr[i].sh_link].sh_addr;
+        rels = (Elf32_Rel *)shdr[i].sh_addr;
+        code = (char      *)shdr[shdr[i].sh_info].sh_addr;
 
-                switch (ELF32_R_TYPE(rels[j].r_info)) {
-                    case R_386_PC32:
-                        *loc += (fix - (uint32_t)loc);
-                    break;
+        for ( j = 0; j < shdr[i].sh_size / sizeof(Elf32_Rel); j++ )
+        {
+            sym = &syms[ELF32_R_SYM(rels[j].r_info)];
+            loc = (uint32_t *)&code[rels[j].r_offset];
+            fix = shdr[sym->st_shndx].sh_addr + sym->st_value;
 
-                    case R_386_32:
-                        *loc += fix;
-                    break;
-                }
+            switch ( ELF32_R_TYPE(rels[j].r_info) )
+            {
+            case R_386_PC32:
+                *loc += fix - (uint32_t)loc;
+                break;
+
+            case R_386_32:
+                *loc += fix;
+                break;
             }
-        } else if (shdr[i].sh_type == SHT_RELA) {
-            return -2;
         }
     }
-    return 0;
 }
 
-/* scan the rombios for the destination of the jumptable */
-static char* get_jump_table_start(void)
+/* Scan the rombios for the destination of the jump table. */
+static char *get_jump_table_start(void)
 {
     char *bios_mem;
 
     for ( bios_mem = (char *)ROMBIOS_BEGIN;
           bios_mem != (char *)ROMBIOS_END;
-          bios_mem++ ) {
-        if (strncmp(bios_mem, "___JMPT", 7) == 0)
+          bios_mem++ )
+        if ( !strncmp(bios_mem, "___JMPT", 7) )
             return bios_mem;
-    }
 
     return NULL;
 }
 
-/* copy relocated jumptable into the rombios */
-static int copy_jumptable(unsigned char *elfarray)
+/* Copy relocated jumptable into the rombios. */
+static void copy_jumptable(char *elfarray)
 {
-    int rc = 0;
     Elf32_Ehdr *ehdr = (Elf32_Ehdr *)elfarray;
     Elf32_Shdr *shdr = (Elf32_Shdr *)&elfarray[ehdr->e_shoff];
-    Elf32_Shdr *shdr_strings = (Elf32_Shdr *)&shdr[ehdr->e_shstrndx];
-    char *secstrings = (char *)&elfarray[shdr_strings->sh_offset];
-    uint32_t *rombiosjumptable = (uint32_t *)get_jump_table_start();
-    uint32_t *biosjumptable    = NULL;
+    char *secstrings = &elfarray[shdr[ehdr->e_shstrndx].sh_offset];
+    char *jump_table = get_jump_table_start();
     int i;
 
-    if (rombiosjumptable == NULL) {
-        return -3;
+    /* Find the section with the jump table and copy to lower BIOS memory. */
+    for ( i = 0; i < ehdr->e_shnum; i++ )
+        if ( !strcmp(JUMPTABLE_SECTION_NAME, secstrings + shdr[i].sh_name) )
+            break;
+
+    if ( i == ehdr->e_shnum )
+    {
+        printf("Could not find " JUMPTABLE_SECTION_NAME " section in file.\n");
+        return;
     }
 
-     /* find the section with the jump table  and copy to lower BIOS memory */
-    for (i = 0; i < ehdr->e_shnum; i++) {
-        if (!strcmp(JUMPTABLE_SECTION_NAME, secstrings + shdr[i].sh_name)) {
-            uint32_t biosjumptableentries;
-            biosjumptable        = (uint32_t *)shdr[i].sh_addr;
-            biosjumptableentries = shdr[i].sh_size / 4;
-            for (int j = 0; j < biosjumptableentries; j++) {
-                rombiosjumptable[j] = biosjumptable[j];
-                if (biosjumptable[j] == 0 &&
-                    j < (biosjumptableentries - 1)) {
-                    printf("WARNING: jumptable entry %d is NULL!\n",j);
-                }
-            }
-            break;
-        }
+    if ( jump_table == NULL )
+    {
+        printf("Could not find jump table in file.\n");
+        return;
     }
 
-    if (biosjumptable == NULL) {
-        printf("Could not find " JUMPTABLE_SECTION_NAME " section in file.\n");
-        rc = -4;
+    memcpy(jump_table, (char *)shdr[i].sh_addr, shdr[i].sh_size);
+}
+
+static void relocate_32bitbios(char *elfarray, uint32_t elfarraysize)
+{
+    uint32_t mask = (64 * 1024) - 1;
+    char *highbiosarea;
+
+    highbiosarea = (char *)(long)
+        e820_malloc((elfarraysize + mask) & ~mask, /* round to 64kb */
+                    E820_RESERVED,
+                    (uint64_t)0xffffffff);
+    if ( highbiosarea == NULL )
+    {
+        printf("No available memory for BIOS high memory area\n");
+        return;
     }
 
-    return 0;
+    memcpy(highbiosarea, elfarray, elfarraysize);
+    relocate_elf(highbiosarea);
+    copy_jumptable(highbiosarea);
 }
 
-static int relocate_32bitbios(unsigned char *elfarray, uint32_t elfarraysize)
+void highbios_setup(void)
 {
-    int rc = 0;
-    uint32_t mask = (64 * 1024) - 1;
-    uint32_t to_malloc = (elfarraysize + mask) & ~mask; /* round to 64kb */
-    unsigned char *highbiosarea;
-
-    highbiosarea = (unsigned char *)(long)
-                           e820_malloc((uint64_t)to_malloc,
-                                       E820_RESERVED,
-                                       (uint64_t)0xffffffff);
-
-    if (highbiosarea != 0) {
-        memcpy(highbiosarea, elfarray, elfarraysize);
-        rc = relocate_elf(highbiosarea);
-        if (rc == 0) {
-            rc = copy_jumptable(highbiosarea);
-        }
-    } else {
-        rc = -5;
-    }
-
-    return rc;
+    relocate_32bitbios((char *)highbios_array, sizeof(highbios_array));
 }
-
-int highbios_setup(void)
-{
-    return relocate_32bitbios((unsigned char *)highbios_array,
-                              sizeof(highbios_array));
-}
diff -r f74e837c3902 -r 2216a45bf058 tools/firmware/hvmloader/acpi/build.c
--- a/tools/firmware/hvmloader/acpi/build.c     Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/firmware/hvmloader/acpi/build.c     Tue Mar 20 15:19:38 2007 -0600
@@ -20,7 +20,6 @@
 #include "ssdt_tpm.h"
 #include "../config.h"
 #include "../util.h"
-#include <xen/hvm/e820.h>
 
 #define align16(sz)        (((sz) + 15) & ~15)
 #define fixed_strcpy(d, s) strncpy((d), (s), sizeof(d))
diff -r f74e837c3902 -r 2216a45bf058 tools/firmware/hvmloader/hvmloader.c
--- a/tools/firmware/hvmloader/hvmloader.c      Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/firmware/hvmloader/hvmloader.c      Tue Mar 20 15:19:38 2007 -0600
@@ -29,7 +29,6 @@
 #include "pci_regs.h"
 #include <xen/version.h>
 #include <xen/hvm/params.h>
-#include <xen/hvm/e820.h>
 
 /* memory map */
 #define HYPERCALL_PHYSICAL_ADDRESS    0x00080000
@@ -297,25 +296,57 @@ static void pci_setup(void)
     }
 }
 
-static 
-int must_load_nic(void) 
-{
-    /* If the network card is in the boot order, load the Etherboot 
-     * option ROM.  Read the boot order bytes from CMOS and check 
-     * if any of them are 0x4. */
+/*
+ * If the network card is in the boot order, load the Etherboot option ROM.
+ * Read the boot order bytes from CMOS and check if any of them are 0x4.
+ */
+static int must_load_nic(void) 
+{
     uint8_t boot_order;
 
-    /* Read CMOS register 0x3d (boot choices 0 and 1) */
-    outb(0x70, 0x3d);
-    boot_order = inb(0x71);
-    if ( (boot_order & 0xf) == 0x4 || (boot_order & 0xf0) == 0x40 ) 
+    /* Read CMOS register 0x3d (boot choices 0 and 1). */
+    boot_order = cmos_inb(0x3d);
+    if ( ((boot_order & 0xf) == 0x4) || ((boot_order & 0xf0) == 0x40) ) 
         return 1;
-    /* Read CMOS register 0x38 (boot choice 2 and FDD test flag) */
-    outb(0x70, 0x38);
-    boot_order = inb(0x71);
-    if ( (boot_order & 0xf0) == 0x40 ) 
-        return 1;
-    return 0;
+
+    /* Read CMOS register 0x38 (boot choice 2 and FDD test flag). */
+    boot_order = cmos_inb(0x38);
+    return ((boot_order & 0xf0) == 0x40);
+}
+
+/* Replace possibly erroneous memory-size CMOS fields with correct values. */
+static void cmos_write_memory_size(void)
+{
+    struct e820entry *map = E820_MAP;
+    int i, nr = *E820_MAP_NR;
+    uint32_t base_mem = 640, ext_mem = 0, alt_mem = 0;
+
+    for ( i = 0; i < nr; i++ )
+        if ( (map[i].addr >= 0x100000) && (map[i].type == E820_RAM) )
+            break;
+
+    if ( i != nr )
+    {
+        alt_mem = ext_mem = map[i].addr + map[i].size;
+        ext_mem = (ext_mem > 0x0100000) ? (ext_mem - 0x0100000) >> 10 : 0;
+        if ( ext_mem > 0xffff )
+            ext_mem = 0xffff;
+        alt_mem = (alt_mem > 0x1000000) ? (alt_mem - 0x1000000) >> 16 : 0;
+    }
+
+    /* All BIOSes: conventional memory (640kB). */
+    cmos_outb(0x15, (uint8_t)(base_mem >> 0));
+    cmos_outb(0x16, (uint8_t)(base_mem >> 8));
+
+    /* All BIOSes: extended memory (1kB chunks above 1MB). */
+    cmos_outb(0x17, (uint8_t)( ext_mem >> 0));
+    cmos_outb(0x18, (uint8_t)( ext_mem >> 8));
+    cmos_outb(0x30, (uint8_t)( ext_mem >> 0));
+    cmos_outb(0x31, (uint8_t)( ext_mem >> 8));
+
+    /* Some BIOSes: alternative extended memory (64kB chunks above 16MB). */
+    cmos_outb(0x34, (uint8_t)( alt_mem >> 0));
+    cmos_outb(0x35, (uint8_t)( alt_mem >> 8));
 }
 
 int main(void)
@@ -365,6 +396,8 @@ int main(void)
         acpi_sz = acpi_build_tables((uint8_t *)ACPI_PHYSICAL_ADDRESS);
         ASSERT((ACPI_PHYSICAL_ADDRESS + acpi_sz) <= 0xF0000);
     }
+
+    cmos_write_memory_size();
 
     if ( !check_amd() )
     {
diff -r f74e837c3902 -r 2216a45bf058 tools/firmware/hvmloader/smbios.c
--- a/tools/firmware/hvmloader/smbios.c Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/firmware/hvmloader/smbios.c Tue Mar 20 15:19:38 2007 -0600
@@ -22,7 +22,6 @@
 
 #include <stdint.h>
 #include <xen/version.h>
-#include <xen/hvm/e820.h>
 #include "smbios.h"
 #include "smbios_types.h"
 #include "util.h"
@@ -129,47 +128,32 @@ write_smbios_tables(void *start,
     return (size_t)((char *)p - (char *)start);
 }
 
-/* This tries to figure out how much pseudo-physical memory (in MB)
-   is allocated to the current domU.
-
-   It iterates through the e820 table, adding up the 'usable' and
-   'reserved' entries and rounding up to the nearest MB.
-
-   The e820map is not at e820 in hvmloader, so this uses the
-   E820_MAP_* constants from e820.h to pick it up where libxenguest
-   left it.
- */
+/* Calculate how much pseudo-physical memory (in MB) is allocated to us. */
 static uint64_t
 get_memsize(void)
 {
-    struct e820entry *map = NULL;
-    uint8_t num_entries = 0;
+    struct e820entry *map = E820_MAP;
+    uint8_t num_entries = *E820_MAP_NR;
     uint64_t memsize = 0;
-    uint8_t i;
-
-    map = (struct e820entry *) (E820_MAP_PAGE + E820_MAP_OFFSET);
-    num_entries = *((uint8_t *) (E820_MAP_PAGE + E820_MAP_NR_OFFSET));
-
-    /* walk through e820map, ignoring any entries that aren't marked
-       as usable or reserved. */
-
+    int i;
+
+    /*
+     * Walk through e820map, ignoring any entries that aren't marked
+     * as usable or reserved.
+     */
     for ( i = 0; i < num_entries; i++ )
     {
-        if (map->type == E820_RAM || map->type == E820_RESERVED)
+        if ( (map->type == E820_RAM) || (map->type == E820_RESERVED) )
             memsize += map->size;
         map++;
     }
 
-    /* Round up to the nearest MB.  The user specifies domU
-       pseudo-physical memory in megabytes, so not doing this
-       could easily lead to reporting one less MB than the user
-       specified. */
-    if ( memsize & ((1<<20)-1) )
-        memsize = (memsize >> 20) + 1;
-    else
-        memsize = (memsize >> 20);
-
-    return memsize;
+    /*
+     * Round up to the nearest MB.  The user specifies domU pseudo-physical 
+     * memory in megabytes, so not doing this could easily lead to reporting 
+     * one less MB than the user specified.
+     */
+    return (memsize + (1 << 20) - 1) >> 20;
 }
 
 void
diff -r f74e837c3902 -r 2216a45bf058 tools/firmware/hvmloader/util.c
--- a/tools/firmware/hvmloader/util.c   Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/firmware/hvmloader/util.c   Tue Mar 20 15:19:38 2007 -0600
@@ -27,17 +27,17 @@
 
 void outb(uint16_t addr, uint8_t val)
 {
-    __asm__ __volatile__ ( "outb %%al, %%dx" :: "d"(addr), "a"(val) );
+    __asm__ __volatile__ ( "outb %%al, %%dx" : : "d" (addr), "a" (val) );
 }
 
 void outw(uint16_t addr, uint16_t val)
 {
-    __asm__ __volatile__ ( "outw %%ax, %%dx" :: "d"(addr), "a"(val) );
+    __asm__ __volatile__ ( "outw %%ax, %%dx" : : "d" (addr), "a" (val) );
 }
 
 void outl(uint16_t addr, uint32_t val)
 {
-    __asm__ __volatile__ ( "outl %%eax, %%dx" :: "d"(addr), "a"(val) );
+    __asm__ __volatile__ ( "outl %%eax, %%dx" : : "d" (addr), "a" (val) );
 }
 
 uint8_t inb(uint16_t addr)
@@ -59,6 +59,18 @@ uint32_t inl(uint16_t addr)
     uint32_t val;
     __asm__ __volatile__ ( "inl %%dx,%%eax" : "=a" (val) : "d" (addr) );
     return val;
+}
+
+uint8_t cmos_inb(uint8_t idx)
+{
+    outb(0x70, idx);
+    return inb(0x71);
+}
+
+void cmos_outb(uint8_t idx, uint8_t val)
+{
+    outb(0x70, idx);
+    outb(0x71, val);
 }
 
 char *itoa(char *a, unsigned int i)
@@ -280,9 +292,6 @@ uuid_to_string(char *dest, uint8_t *uuid
     *p = '\0';
 }
 
-#include <xen/hvm/e820.h>
-#define E820_MAP_NR ((unsigned char *)E820_MAP_PAGE + E820_MAP_NR_OFFSET)
-#define E820_MAP    ((struct e820entry *)(E820_MAP_PAGE + E820_MAP_OFFSET))
 uint64_t e820_malloc(uint64_t size, uint32_t type, uint64_t mask)
 {
     uint64_t addr = 0;
diff -r f74e837c3902 -r 2216a45bf058 tools/firmware/hvmloader/util.h
--- a/tools/firmware/hvmloader/util.h   Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/firmware/hvmloader/util.h   Tue Mar 20 15:19:38 2007 -0600
@@ -25,6 +25,10 @@ uint8_t  inb(uint16_t addr);
 uint8_t  inb(uint16_t addr);
 uint16_t inw(uint16_t addr);
 uint32_t inl(uint16_t addr);
+
+/* CMOS access */
+uint8_t cmos_inb(uint8_t idx);
+void cmos_outb(uint8_t idx, uint8_t val);
 
 /* APIC access */
 uint32_t ioapic_read(uint32_t reg);
@@ -78,9 +82,13 @@ int vprintf(const char *fmt, va_list ap)
 /* Allocate region of specified type in the e820 table. */
 uint64_t e820_malloc(uint64_t size, uint32_t type, uint64_t mask);
 
+/* General e820 access. */
+#include <xen/hvm/e820.h>
+#define E820_MAP_NR ((unsigned char *)E820_MAP_PAGE + E820_MAP_NR_OFFSET)
+#define E820_MAP    ((struct e820entry *)(E820_MAP_PAGE + E820_MAP_OFFSET))
+
 /* Prepare the 32bit BIOS */
-int highbios_setup(void);
-
+void highbios_setup(void);
 
 #define isdigit(c) ((c) >= '0' && (c) <= '9')
 
diff -r f74e837c3902 -r 2216a45bf058 tools/firmware/rombios/rombios.c
--- a/tools/firmware/rombios/rombios.c  Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/firmware/rombios/rombios.c  Tue Mar 20 15:19:38 2007 -0600
@@ -4196,178 +4196,86 @@ ASM_END
     case 0xe8:
         switch(regs.u.r8.al)
         {
-         case 0x20: // coded by osmaker aka K.J.
-            if(regs.u.r32.edx == 0x534D4150) /* SMAP */
-            {
-#ifdef HVMASSIST
-               if ((regs.u.r16.bx / 0x14) * 0x14 == regs.u.r16.bx) {
-                   Bit16u e820_table_size = read_word(0xe000, 0x8) * 0x14;
-
-                   if (regs.u.r16.bx + 0x14 <= e820_table_size) {
-                       memcpyb(ES, regs.u.r16.di,
-                               0xe000, 0x10 + regs.u.r16.bx, 0x14);
-                   }
-                   regs.u.r32.ebx += 0x14;
-                   if ((regs.u.r32.ebx + 0x14 - 1) > e820_table_size)
-                       regs.u.r32.ebx = 0;
-                   regs.u.r32.eax = 0x534D4150;
-                   regs.u.r32.ecx = 0x14;
-                   CLEAR_CF();
-                   return;
-               } else if (regs.u.r16.bx == 1) {
-                   extended_memory_size = inb_cmos(0x35);
-                   extended_memory_size <<= 8;
-                   extended_memory_size |= inb_cmos(0x34);
-                   extended_memory_size *= 64;
-                   if (extended_memory_size > 0x3bc000) // greater than 
EFF00000???
-                   {
-                       extended_memory_size = 0x3bc000; // everything after 
this is reserved memory until we get to 0x100000000
-                   }
-                   extended_memory_size *= 1024;
-                   extended_memory_size += 15728640; // make up for the 16mb 
of memory that is chopped off
-
-                   if (extended_memory_size <= 15728640)
-                   {
-                       extended_memory_size = inb_cmos(0x31);
-                       extended_memory_size <<= 8;
-                       extended_memory_size |= inb_cmos(0x30);
-                       extended_memory_size *= 1024;
-                   }
-
-                   write_word(ES, regs.u.r16.di, 0x0000);
-                   write_word(ES, regs.u.r16.di+2, 0x0010);
-                   write_word(ES, regs.u.r16.di+4, 0x0000);
-                   write_word(ES, regs.u.r16.di+6, 0x0000);
-
-                   write_word(ES, regs.u.r16.di+8, extended_memory_size);
-                   extended_memory_size >>= 16;
-                   write_word(ES, regs.u.r16.di+10, extended_memory_size);
-                   extended_memory_size >>= 16;
-                   write_word(ES, regs.u.r16.di+12, extended_memory_size);
-                   extended_memory_size >>= 16;
-                   write_word(ES, regs.u.r16.di+14, extended_memory_size);
-
-                   write_word(ES, regs.u.r16.di+16, 0x1);
-                   write_word(ES, regs.u.r16.di+18, 0x0);
-
-                   regs.u.r32.ebx = 0;
-                   regs.u.r32.eax = 0x534D4150;
-                   regs.u.r32.ecx = 0x14;
-                   CLEAR_CF();
-                   return;
-               } else { /* AX=E820, DX=534D4150, BX unrecognized */
-                   goto int15_unimplemented;
-               }
-#else
-                switch(regs.u.r16.bx)
-                {
-                    case 0:
-                        write_word(ES, regs.u.r16.di, 0x00);
-                        write_word(ES, regs.u.r16.di+2, 0x00);
-                        write_word(ES, regs.u.r16.di+4, 0x00);
-                        write_word(ES, regs.u.r16.di+6, 0x00);
-
-                        write_word(ES, regs.u.r16.di+8, 0xFC00);
-                        write_word(ES, regs.u.r16.di+10, 0x0009);
-                        write_word(ES, regs.u.r16.di+12, 0x0000);
-                        write_word(ES, regs.u.r16.di+14, 0x0000);
-
-                        write_word(ES, regs.u.r16.di+16, 0x1);
-                        write_word(ES, regs.u.r16.di+18, 0x0);
-
-                        regs.u.r32.ebx = 1;
-
-                        regs.u.r32.eax = 0x534D4150;
-                        regs.u.r32.ecx = 0x14;
-                        CLEAR_CF();
-                        return;
-                        break;
-                    case 1:
-                        extended_memory_size = inb_cmos(0x35);
-                        extended_memory_size <<= 8;
-                        extended_memory_size |= inb_cmos(0x34);
-                        extended_memory_size *= 64;
-                        if(extended_memory_size > 0x3bc000) // greater than 
EFF00000???
-                        {
-                            extended_memory_size = 0x3bc000; // everything 
after this is reserved memory until we get to 0x100000000
-                        }
-                        extended_memory_size *= 1024;
-                        extended_memory_size += 15728640; // make up for the 
16mb of memory that is chopped off
-
-                        if(extended_memory_size <= 15728640)
-                        {
-                            extended_memory_size = inb_cmos(0x31);
-                            extended_memory_size <<= 8;
-                            extended_memory_size |= inb_cmos(0x30);
-                            extended_memory_size *= 1024;
-                        }
-
-                        write_word(ES, regs.u.r16.di, 0x0000);
-                        write_word(ES, regs.u.r16.di+2, 0x0010);
-                        write_word(ES, regs.u.r16.di+4, 0x0000);
-                        write_word(ES, regs.u.r16.di+6, 0x0000);
-
-                        write_word(ES, regs.u.r16.di+8, extended_memory_size);
-                        extended_memory_size >>= 16;
-                        write_word(ES, regs.u.r16.di+10, extended_memory_size);
-                        extended_memory_size >>= 16;
-                        write_word(ES, regs.u.r16.di+12, extended_memory_size);
-                        extended_memory_size >>= 16;
-                        write_word(ES, regs.u.r16.di+14, extended_memory_size);
-
-                        write_word(ES, regs.u.r16.di+16, 0x1);
-                        write_word(ES, regs.u.r16.di+18, 0x0);
-
-                        regs.u.r32.ebx = 0;
-                        regs.u.r32.eax = 0x534D4150;
-                        regs.u.r32.ecx = 0x14;
-                        CLEAR_CF();
-                        return;
-                        break;
-                    default:  /* AX=E820, DX=534D4150, BX unrecognized */
-                        goto int15_unimplemented;
+        case 0x20: {
+            Bit16u e820_table_size = read_word(0xe000, 0x8) * 0x14;
+
+            if (regs.u.r32.edx != 0x534D4150) /* SMAP */
+                goto int15_unimplemented;
+
+            if ((regs.u.r16.bx / 0x14) * 0x14 == regs.u.r16.bx) {
+                if (regs.u.r16.bx + 0x14 <= e820_table_size)
+                    memcpyb(ES, regs.u.r16.di,
+                            0xe000, 0x10 + regs.u.r16.bx, 0x14);
+                regs.u.r32.ebx += 0x14;
+                if ((regs.u.r32.ebx + 0x14 - 1) > e820_table_size)
+                    regs.u.r32.ebx = 0;
+            } else if (regs.u.r16.bx == 1) {
+                Bit32u base, type;
+                Bit16u off;
+                for (off = 0; off < e820_table_size; off += 0x14) {
+                    base = read_dword(0xe000, 0x10 + off);
+                    type = read_dword(0xe000, 0x20 + off);
+                    if ((base >= 0x100000) && (type == 1))
                         break;
                 }
-#endif
-           } else {
-             // if DX != 0x534D4150)
-             goto int15_unimplemented;
-           }
+                if (off == e820_table_size) {
+                    SET_CF();
+                    break;
+                }
+                memcpyb(ES, regs.u.r16.di, 0xe000, 0x10 + off, 0x14);
+                regs.u.r32.ebx = 0;
+            } else { /* AX=E820, DX=534D4150, BX unrecognized */
+                goto int15_unimplemented;
+            }
+
+            regs.u.r32.eax = 0x534D4150;
+            regs.u.r32.ecx = 0x14;
+            CLEAR_CF();
             break;
-
-        case 0x01: 
-          // do we have any reason to fail here ?
-          CLEAR_CF();
-
-          // my real system sets ax and bx to 0
-          // this is confirmed by Ralph Brown list
-          // but syslinux v1.48 is known to behave 
-          // strangely if ax is set to 0
-          // regs.u.r16.ax = 0;
-          // regs.u.r16.bx = 0;
-
-          // Get the amount of extended memory (above 1M)
-          regs.u.r8.cl = inb_cmos(0x30);
-          regs.u.r8.ch = inb_cmos(0x31);
+        }
+
+        case 0x01: {
+            Bit16u off, e820_table_size = read_word(0xe000, 0x8) * 0x14;
+            Bit32u base, type, size;
+
+            // do we have any reason to fail here ?
+            CLEAR_CF();
+
+            // Get the amount of extended memory (above 1M)
+            regs.u.r8.cl = inb_cmos(0x30);
+            regs.u.r8.ch = inb_cmos(0x31);
           
-          // limit to 15M
-          if(regs.u.r16.cx > 0x3c00)
-          {
-            regs.u.r16.cx = 0x3c00;
-          }
-
-          // Get the amount of extended memory above 16M in 64k blocs
-          regs.u.r8.dl = inb_cmos(0x34);
-          regs.u.r8.dh = inb_cmos(0x35);
-
-          // Set configured memory equal to extended memory
-          regs.u.r16.ax = regs.u.r16.cx;
-          regs.u.r16.bx = regs.u.r16.dx;
-          break;
+            // limit to 15M
+            if (regs.u.r16.cx > (15*1024))
+                regs.u.r16.cx = 15*1024;
+
+            // Find first RAM E820 entry >= 1MB.
+            for (off = 0; off < e820_table_size; off += 0x14) {
+                base = read_dword(0xe000, 0x10 + off);
+                type = read_dword(0xe000, 0x20 + off);
+                if ((base >= 0x100000) && (type == 1))
+                    break;
+            }
+
+            // If there is RAM above 16MB, return amount in 64kB chunks.
+            regs.u.r16.dx = 0;
+            if (off != e820_table_size) {
+                size = base + read_dword(0xe000, 0x18 + off);
+                if (size > 0x1000000) {
+                    size -= 0x1000000;
+                    regs.u.r16.dx = (Bit16u)(size >> 16);
+                }
+            }
+
+            // Set configured memory equal to extended memory
+            regs.u.r16.ax = regs.u.r16.cx;
+            regs.u.r16.bx = regs.u.r16.dx;
+            break;
+        }
        default:  /* AH=0xE8?? but not implemented */
-         goto int15_unimplemented;
-       }
-       break;
+            goto int15_unimplemented;
+        }
+        break;
     int15_unimplemented:
        // fall into the default
     default:
diff -r f74e837c3902 -r 2216a45bf058 tools/ioemu/target-i386-dm/exec-dm.c
--- a/tools/ioemu/target-i386-dm/exec-dm.c      Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/ioemu/target-i386-dm/exec-dm.c      Tue Mar 20 15:19:38 2007 -0600
@@ -450,6 +450,9 @@ static inline int paddr_is_ram(target_ph
 #define phys_ram_addr(x) (phys_ram_base + (x))
 #endif
 
+extern unsigned long *logdirty_bitmap;
+extern unsigned long logdirty_bitmap_size;
+
 void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, 
                             int len, int is_write)
 {
@@ -485,9 +488,20 @@ void cpu_physical_memory_rw(target_phys_
                     l = 1;
                 }
             } else if (paddr_is_ram(addr)) {
-                /* Reading from RAM */
+                /* Writing to RAM */
                 ptr = phys_ram_addr(addr);
                 memcpy(ptr, buf, l);
+                if (logdirty_bitmap != NULL) {
+                    /* Record that we have dirtied this frame */
+                    unsigned long pfn = addr >> TARGET_PAGE_BITS;
+                    if (pfn / 8 >= logdirty_bitmap_size) {
+                        fprintf(logfile, "dirtying pfn %x >= bitmap size %x\n",
+                                pfn, logdirty_bitmap_size * 8);
+                    } else {
+                        logdirty_bitmap[pfn / HOST_LONG_BITS]
+                            |= 1UL << pfn % HOST_LONG_BITS;
+                    }
+                }
 #ifdef __ia64__
                 sync_icache(ptr, l);
 #endif 
diff -r f74e837c3902 -r 2216a45bf058 tools/ioemu/target-i386-dm/helper2.c
--- a/tools/ioemu/target-i386-dm/helper2.c      Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/ioemu/target-i386-dm/helper2.c      Tue Mar 20 15:19:38 2007 -0600
@@ -439,6 +439,18 @@ void cpu_ioreq_xor(CPUState *env, ioreq_
     req->data = tmp1;
 }
 
+void cpu_ioreq_xchg(CPUState *env, ioreq_t *req)
+{
+    unsigned long tmp1;
+
+    if (req->data_is_ptr != 0)
+        hw_error("expected scalar value");
+
+    read_physical(req->addr, req->size, &tmp1);
+    write_physical(req->addr, req->size, &req->data);
+    req->data = tmp1;
+}
+
 void __handle_ioreq(CPUState *env, ioreq_t *req)
 {
     if (!req->data_is_ptr && req->dir == IOREQ_WRITE && req->size != 4)
@@ -462,6 +474,9 @@ void __handle_ioreq(CPUState *env, ioreq
         break;
     case IOREQ_TYPE_XOR:
         cpu_ioreq_xor(env, req);
+        break;
+    case IOREQ_TYPE_XCHG:
+        cpu_ioreq_xchg(env, req);
         break;
     default:
         hw_error("Invalid ioreq type 0x%x\n", req->type);
diff -r f74e837c3902 -r 2216a45bf058 tools/ioemu/xenstore.c
--- a/tools/ioemu/xenstore.c    Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/ioemu/xenstore.c    Tue Mar 20 15:19:38 2007 -0600
@@ -11,9 +11,14 @@
 #include "vl.h"
 #include "block_int.h"
 #include <unistd.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 
 static struct xs_handle *xsh = NULL;
-static char *hd_filename[MAX_DISKS];
+static char *media_filename[MAX_DISKS];
 static QEMUTimer *insert_timer = NULL;
 
 #define UWAIT_MAX (30*1000000) /* thirty seconds */
@@ -40,10 +45,10 @@ static void insert_media(void *opaque)
     int i;
 
     for (i = 0; i < MAX_DISKS; i++) {
-       if (hd_filename[i]) {
-           do_change(bs_table[i]->device_name, hd_filename[i]);
-           free(hd_filename[i]);
-           hd_filename[i] = NULL;
+       if (media_filename[i] && bs_table[i]) {
+           do_change(bs_table[i]->device_name, media_filename[i]);
+           free(media_filename[i]);
+           media_filename[i] = NULL;
        }
     }
 }
@@ -82,7 +87,7 @@ void xenstore_parse_domain_config(int do
     unsigned int len, num, hd_index;
 
     for(i = 0; i < MAX_DISKS; i++)
-        hd_filename[i] = NULL;
+        media_filename[i] = NULL;
 
     xsh = xs_daemon_open();
     if (xsh == NULL) {
@@ -128,19 +133,12 @@ void xenstore_parse_domain_config(int do
            continue;
        free(type);
        type = xs_read(xsh, XBT_NULL, buf, &len);
-       /* read params to get the patch of the image -- read it last
-        * so that we have its path in buf when setting up the
-        * watch */
        if (pasprintf(&buf, "%s/params", bpath) == -1)
            continue;
        free(params);
        params = xs_read(xsh, XBT_NULL, buf, &len);
        if (params == NULL)
            continue;
-       if (params[0]) {
-           hd_filename[hd_index] = params;     /* strdup() */
-           params = NULL;              /* don't free params on re-use */
-       }
         /* 
          * check if device has a phantom vbd; the phantom is hooked
          * to the frontend device (for ease of cleanup), so lookup 
@@ -151,37 +149,41 @@ void xenstore_parse_domain_config(int do
            continue;
        free(fpath);
         fpath = xs_read(xsh, XBT_NULL, buf, &len);
-       if (fpath != NULL) {
+       if (fpath) {
            if (pasprintf(&buf, "%s/dev", fpath) == -1)
                continue;
+           free(params);
             params = xs_read(xsh, XBT_NULL, buf , &len);
-           if (params != NULL) {
-                free(hd_filename[hd_index]);
-                hd_filename[hd_index] = params;
-                params = NULL;              /* don't free params on re-use */
+           if (params) {
                 /* 
                  * wait for device, on timeout silently fail because we will 
                  * fail to open below
                  */
-                waitForDevice(hd_filename[hd_index]);
+                waitForDevice(params);
             }
         }
+
        bs_table[hd_index] = bdrv_new(dev);
-        /* re-establish buf */
-       if (pasprintf(&buf, "%s/params", bpath) == -1)
-           continue;
        /* check if it is a cdrom */
        if (type && !strcmp(type, "cdrom")) {
            bdrv_set_type_hint(bs_table[hd_index], BDRV_TYPE_CDROM);
-           xs_watch(xsh, buf, dev);
+           if (pasprintf(&buf, "%s/params", bpath) != -1)
+               xs_watch(xsh, buf, dev);
        }
-       if (hd_filename[hd_index]) {
-            if (bdrv_open(bs_table[hd_index], hd_filename[hd_index],
-                         0 /* snapshot */) < 0)
+       /* open device now if media present */
+       if (params[0]) {
+            if (bdrv_open(bs_table[hd_index], params, 0 /* snapshot */) < 0)
                 fprintf(stderr, "qemu: could not open hard disk image '%s'\n",
-                        hd_filename[hd_index]);
+                        params);
        }
     }
+
+    /* Set a watch for log-dirty requests from the migration tools */
+    if (pasprintf(&buf, "%s/logdirty/next-active", path) != -1) {
+        xs_watch(xsh, buf, "logdirty");
+        fprintf(logfile, "Watching %s\n", buf);
+    }
+
 
  out:
     free(type);
@@ -201,6 +203,116 @@ int xenstore_fd(void)
     return -1;
 }
 
+unsigned long *logdirty_bitmap = NULL;
+unsigned long logdirty_bitmap_size;
+extern int vga_ram_size, bios_size;
+
+void xenstore_process_logdirty_event(void)
+{
+    char *act;
+    static char *active_path = NULL;
+    static char *next_active_path = NULL;
+    static char *seg = NULL;
+    unsigned int len;
+    int i;
+
+    fprintf(logfile, "Triggered log-dirty buffer switch\n");
+
+    if (!seg) {
+        char *path, *p, *key_ascii, key_terminated[17] = {0,};
+        key_t key;
+        int shmid;
+
+        /* Find and map the shared memory segment for log-dirty bitmaps */
+        if (!(path = xs_get_domain_path(xsh, domid))) {            
+            fprintf(logfile, "Log-dirty: can't get domain path in store\n");
+            exit(1);
+        }
+        if (!(path = realloc(path, strlen(path) 
+                             + strlen("/logdirty/next-active") + 1))) {
+            fprintf(logfile, "Log-dirty: out of memory\n");
+            exit(1);
+        }
+        strcat(path, "/logdirty/");
+        p = path + strlen(path);
+        strcpy(p, "key");
+        
+        key_ascii = xs_read(xsh, XBT_NULL, path, &len);
+        if (!key_ascii) {
+            /* No key yet: wait for the next watch */
+            free(path);
+            return;
+        }
+        strncpy(key_terminated, key_ascii, 16);
+        free(key_ascii);
+        key = (key_t) strtoull(key_terminated, NULL, 16);
+
+        /* Figure out how bit the log-dirty bitmaps are */
+        logdirty_bitmap_size = ((phys_ram_size + 0x20 
+                                 - (vga_ram_size + bios_size)) 
+                                >> (TARGET_PAGE_BITS)); /* nr of bits in map*/
+        if (logdirty_bitmap_size > HVM_BELOW_4G_MMIO_START >> TARGET_PAGE_BITS)
+            logdirty_bitmap_size += 
+                HVM_BELOW_4G_MMIO_LENGTH >> TARGET_PAGE_BITS; /* still bits */
+        logdirty_bitmap_size = ((logdirty_bitmap_size + HOST_LONG_BITS - 1)
+                                / HOST_LONG_BITS); /* longs */
+        logdirty_bitmap_size *= sizeof (unsigned long); /* bytes */
+
+        /* Map the shared-memory segment */
+        if ((shmid = shmget(key, 
+                            2 * logdirty_bitmap_size, 
+                            S_IRUSR|S_IWUSR)) == -1 
+            || (seg = shmat(shmid, NULL, 0)) == (void *)-1) {
+            fprintf(logfile, "Log-dirty: can't map segment %16.16llx (%s)\n",
+                    (unsigned long long) key, strerror(errno));
+            exit(1);
+        }
+
+        fprintf(logfile, "Log-dirty: mapped segment at %p\n", seg);
+
+        /* Double-check that the bitmaps are the size we expect */
+        if (logdirty_bitmap_size != *(uint32_t *)seg) {
+            fprintf(logfile, "Log-dirty: got %lu, calc %lu\n", 
+                    *(uint32_t *)seg, logdirty_bitmap_size);
+            return;
+        }
+
+        /* Remember the paths for the next-active and active entries */
+        strcpy(p, "active");
+        if (!(active_path = strdup(path))) {
+            fprintf(logfile, "Log-dirty: out of memory\n");
+            exit(1);
+        }
+        strcpy(p, "next-active");
+        if (!(next_active_path = strdup(path))) {
+            fprintf(logfile, "Log-dirty: out of memory\n");
+            exit(1);
+        }
+        free(path);
+    }
+    
+    /* Read the required active buffer from the store */
+    act = xs_read(xsh, XBT_NULL, next_active_path, &len);
+    if (!act) {
+        fprintf(logfile, "Log-dirty: can't read next-active\n");
+        exit(1);
+    }
+
+    /* Switch buffers */
+    i = act[0] - '0';
+    if (i != 0 && i != 1) {
+        fprintf(logfile, "Log-dirty: bad next-active entry: %s\n", act);
+        exit(1);
+    }
+    logdirty_bitmap = seg + i * logdirty_bitmap_size;
+
+    /* Ack that we've switched */
+    xs_write(xsh, XBT_NULL, active_path, act, len);
+    free(act);
+}
+
+
+
 void xenstore_process_event(void *opaque)
 {
     char **vec, *image = NULL;
@@ -209,6 +321,11 @@ void xenstore_process_event(void *opaque
     vec = xs_read_watch(xsh, &num);
     if (!vec)
        return;
+
+    if (!strcmp(vec[XS_WATCH_TOKEN], "logdirty")) {
+        xenstore_process_logdirty_event();
+        goto out;
+    }
 
     if (strncmp(vec[XS_WATCH_TOKEN], "hd", 2) ||
        strlen(vec[XS_WATCH_TOKEN]) != 3)
@@ -220,13 +337,13 @@ void xenstore_process_event(void *opaque
 
     do_eject(0, vec[XS_WATCH_TOKEN]);
     bs_table[hd_index]->filename[0] = 0;
-    if (hd_filename[hd_index]) {
-       free(hd_filename[hd_index]);
-       hd_filename[hd_index] = NULL;
+    if (media_filename[hd_index]) {
+       free(media_filename[hd_index]);
+       media_filename[hd_index] = NULL;
     }
 
     if (image[0]) {
-       hd_filename[hd_index] = strdup(image);
+       media_filename[hd_index] = strdup(image);
        xenstore_check_new_media_present(5000);
     }
 
diff -r f74e837c3902 -r 2216a45bf058 tools/libxc/Makefile
--- a/tools/libxc/Makefile      Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/libxc/Makefile      Tue Mar 20 15:19:38 2007 -0600
@@ -57,7 +57,7 @@ GUEST_SRCS-$(CONFIG_IA64)    += xc_dom_c
 
 CFLAGS   += -Werror -Wmissing-prototypes
 CFLAGS   += -fno-strict-aliasing
-CFLAGS   += $(INCLUDES) -I.
+CFLAGS   += $(INCLUDES) -I. -I../xenstore
 
 # Needed for posix_fadvise64() in xc_linux.c
 CFLAGS-$(CONFIG_Linux) += -D_GNU_SOURCE
diff -r f74e837c3902 -r 2216a45bf058 tools/libxc/xc_core.c
--- a/tools/libxc/xc_core.c     Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/libxc/xc_core.c     Tue Mar 20 15:19:38 2007 -0600
@@ -349,11 +349,7 @@ xc_domain_dumpcore_via_callback(int xc_h
     /* Map the shared info frame */
     live_shinfo = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
                                        PROT_READ, info.shared_info_frame);
-    if ( !live_shinfo 
-#ifdef __ia64__
-         && !info.hvm
-#endif
-        )
+    if ( !live_shinfo && !info.hvm )
     {
         PERROR("Couldn't map live_shinfo");
         goto out;
diff -r f74e837c3902 -r 2216a45bf058 tools/libxc/xc_core_x86.c
--- a/tools/libxc/xc_core_x86.c Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/libxc/xc_core_x86.c Tue Mar 20 15:19:38 2007 -0600
@@ -21,12 +21,15 @@
 #include "xg_private.h"
 #include "xc_core.h"
 
+static int max_gpfn(int xc_handle, domid_t domid)
+{
+    return xc_memory_op(xc_handle, XENMEM_maximum_gpfn, &domid);
+}
+
 int
 xc_core_arch_auto_translated_physmap(const xc_dominfo_t *info)
 {
-    if ( info->hvm )
-        return 1;
-    return 0;
+    return info->hvm;
 }
 
 int
@@ -35,14 +38,14 @@ xc_core_arch_memory_map_get(int xc_handl
                             xc_core_memory_map_t **mapp,
                             unsigned int *nr_entries)
 {
-    unsigned long max_pfn = live_shinfo->arch.max_pfn;
-    xc_core_memory_map_t *map = NULL;
+    unsigned long max_pfn = max_gpfn(xc_handle, info->domid);
+    xc_core_memory_map_t *map;
 
     map = malloc(sizeof(*map));
-    if ( !map )
+    if ( map == NULL )
     {
         PERROR("Could not allocate memory");
-        goto out;
+        return -1;
     }
 
     map->addr = 0;
@@ -51,11 +54,6 @@ xc_core_arch_memory_map_get(int xc_handl
     *mapp = map;
     *nr_entries = 1;
     return 0;
-
-out:
-    if ( map )
-        free(map);
-    return -1;
 }
 
 int
@@ -67,7 +65,7 @@ xc_core_arch_map_p2m(int xc_handle, xc_d
     xen_pfn_t *live_p2m_frame_list_list = NULL;
     xen_pfn_t *live_p2m_frame_list = NULL;
     uint32_t dom = info->domid;
-    unsigned long max_pfn = live_shinfo->arch.max_pfn;
+    unsigned long max_pfn = max_gpfn(xc_handle, info->domid);
     int ret = -1;
     int err;
 
diff -r f74e837c3902 -r 2216a45bf058 tools/libxc/xc_hvm_build.c
--- a/tools/libxc/xc_hvm_build.c        Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/libxc/xc_hvm_build.c        Tue Mar 20 15:19:38 2007 -0600
@@ -137,6 +137,12 @@ static void build_e820map(void *e820_pag
     e820entry[nr_map].type = E820_RAM;
     nr_map++;
 
+    /* Explicitly reserve space for special pages (ioreq and xenstore). */
+    e820entry[nr_map].addr = mem_size - PAGE_SIZE * 3;
+    e820entry[nr_map].size = PAGE_SIZE * 3;
+    e820entry[nr_map].type = E820_RESERVED;
+    nr_map++;
+
     if ( extra_mem_size )
     {
         e820entry[nr_map].addr = (1ULL << 32);
@@ -280,7 +286,6 @@ static int setup_guest(int xc_handle,
     /* NB. evtchn_upcall_mask is unused: leave as zero. */
     memset(&shared_info->evtchn_mask[0], 0xff,
            sizeof(shared_info->evtchn_mask));
-    shared_info->arch.max_pfn = page_array[nr_pages - 1];
     munmap(shared_info, PAGE_SIZE);
 
     if ( v_end > HVM_BELOW_4G_RAM_END )
diff -r f74e837c3902 -r 2216a45bf058 tools/libxc/xc_hvm_restore.c
--- a/tools/libxc/xc_hvm_restore.c      Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/libxc/xc_hvm_restore.c      Tue Mar 20 15:19:38 2007 -0600
@@ -70,9 +70,6 @@ int xc_hvm_restore(int xc_handle, int io
 {
     DECLARE_DOMCTL;
 
-    /* The new domain's shared-info frame number. */
-    unsigned long shared_info_frame;
-
     /* A copy of the CPU context of the guest. */
     vcpu_guest_context_t ctxt;
 
@@ -86,8 +83,6 @@ int xc_hvm_restore(int xc_handle, int io
     uint8_t *hvm_buf = NULL;
     unsigned long long v_end, memsize;
     unsigned long shared_page_nr;
-    shared_info_t *shared_info = NULL;
-    xen_pfn_t arch_max_pfn;
 
     unsigned long pfn;
     unsigned int prev_pc, this_pc;
@@ -95,8 +90,6 @@ int xc_hvm_restore(int xc_handle, int io
 
     /* Types of the pfns in the current region */
     unsigned long region_pfn_type[MAX_BATCH_SIZE];
-
-    struct xen_add_to_physmap xatp;
 
     /* Number of pages of memory the guest has.  *Not* the same as max_pfn. */
     unsigned long nr_pages;
@@ -146,7 +139,6 @@ int xc_hvm_restore(int xc_handle, int io
         pfns[i] = i;
     for ( i = HVM_BELOW_4G_RAM_END >> PAGE_SHIFT; i < pfn_array_size; i++ )
         pfns[i] += HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT;
-    arch_max_pfn = pfns[max_pfn];/* used later */
 
     /* Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000. */
     rc = xc_domain_memory_populate_physmap(
@@ -350,29 +342,6 @@ int xc_hvm_restore(int xc_handle, int io
         goto out;
     }
 
-    /* Shared-info pfn */
-    if (!read_exact(io_fd, &(shared_info_frame), sizeof(uint32_t)) ) {
-        ERROR("reading the shared-info pfn failed!\n");
-        goto out;
-    }
-    /* Map the shared-info frame where it was before */
-    xatp.domid = dom;
-    xatp.space = XENMAPSPACE_shared_info;
-    xatp.idx   = 0;
-    xatp.gpfn  = shared_info_frame;
-    if ( (rc = xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp)) != 0 ) {
-        ERROR("setting the shared-info pfn failed!\n");
-        goto out;
-    }
-    if ( (xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp) != 0) ||
-         ((shared_info = xc_map_foreign_range(
-             xc_handle, dom, PAGE_SIZE, PROT_READ | PROT_WRITE,
-             shared_info_frame)) == NULL) )
-        goto out;
-    /* shared_info.arch.max_pfn is used by dump-core */
-    shared_info->arch.max_pfn = arch_max_pfn;
-    munmap(shared_info, PAGE_SIZE);
-
     rc = 0;
     goto out;
 
diff -r f74e837c3902 -r 2216a45bf058 tools/libxc/xc_hvm_save.c
--- a/tools/libxc/xc_hvm_save.c Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/libxc/xc_hvm_save.c Tue Mar 20 15:19:38 2007 -0600
@@ -54,6 +54,11 @@ static unsigned long hvirt_start;
 /* #levels of page tables used by the current guest */
 static unsigned int pt_levels;
 
+/* Shared-memory bitmaps for getting log-dirty bits from qemu */
+static unsigned long *qemu_bitmaps[2];
+static int qemu_active;
+static int qemu_non_active;
+
 int xc_hvm_drain_io(int handle, domid_t dom)
 {
     DECLARE_HYPERCALL;
@@ -77,7 +82,8 @@ int xc_hvm_drain_io(int handle, domid_t 
 */
 
 #define BITS_PER_LONG (sizeof(unsigned long) * 8)
-#define BITMAP_SIZE   ((pfn_array_size + BITS_PER_LONG - 1) / 8)
+#define BITS_TO_LONGS(bits) (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG)
+#define BITMAP_SIZE   (BITS_TO_LONGS(pfn_array_size) * sizeof(unsigned long))
 
 #define BITMAP_ENTRY(_nr,_bmap) \
    ((unsigned long *)(_bmap))[(_nr)/BITS_PER_LONG]
@@ -123,6 +129,7 @@ static inline int permute( int i, int nr
 
     return i;
 }
+
 
 static uint64_t tv_to_us(struct timeval *new)
 {
@@ -277,7 +284,9 @@ static int suspend_and_state(int (*suspe
 }
 
 int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
-                  uint32_t max_factor, uint32_t flags, int (*suspend)(int))
+                uint32_t max_factor, uint32_t flags, int (*suspend)(int),
+                void *(*init_qemu_maps)(int, unsigned), 
+                void (*qemu_flip_buffer)(int, int))
 {
     xc_dominfo_t info;
 
@@ -293,9 +302,6 @@ int xc_hvm_save(int xc_handle, int io_fd
     /* The size of an array big enough to contain all guest pfns */
     unsigned long pfn_array_size;
 
-    /* The new domain's shared-info frame number. */
-    unsigned long shared_info_frame;
-
     /* Other magic frames: ioreqs and xenstore comms */
     unsigned long ioreq_pfn, bufioreq_pfn, store_pfn;
 
@@ -308,9 +314,6 @@ int xc_hvm_save(int xc_handle, int io_fd
     /* A copy of hvm domain context buffer*/
     uint32_t hvm_buf_size;
     uint8_t *hvm_buf = NULL;
-
-    /* Live mapping of shared info structure */
-    shared_info_t *live_shinfo = NULL;
 
     /* base of the region in which domain memory is mapped */
     unsigned char *region_base = NULL;
@@ -363,19 +366,11 @@ int xc_hvm_save(int xc_handle, int io_fd
         ERROR("HVM:Could not get vcpu context");
         goto out;
     }
-    shared_info_frame = info.shared_info_frame;
 
     /* cheesy sanity check */
     if ((info.max_memkb >> (PAGE_SHIFT - 10)) > max_mfn) {
         ERROR("Invalid HVM state record -- pfn count out of range: %lu",
             (info.max_memkb >> (PAGE_SHIFT - 10)));
-        goto out;
-    }
-
-    /* Map the shared info frame */
-    if(!(live_shinfo = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
-                                            PROT_READ, shared_info_frame))) {
-        ERROR("HVM:Couldn't map live_shinfo");
         goto out;
     }
 
@@ -392,8 +387,6 @@ int xc_hvm_save(int xc_handle, int io_fd
             "nr_pages=0x%lx\n", info.max_memkb, max_mfn, info.nr_pages); 
 
     if (live) {
-        ERROR("hvm domain doesn't support live migration now.\n");
-        goto out;
         
         if (xc_shadow_control(xc_handle, dom,
                               XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY,
@@ -453,6 +446,15 @@ int xc_hvm_save(int xc_handle, int io_fd
     to_skip = malloc(BITMAP_SIZE);
 
 
+    if (live) {
+        /* Get qemu-dm logging dirty pages too */
+        void *seg = init_qemu_maps(dom, BITMAP_SIZE);
+        qemu_bitmaps[0] = seg;
+        qemu_bitmaps[1] = seg + BITMAP_SIZE;
+        qemu_active = 0;
+        qemu_non_active = 1;
+    }
+
     hvm_buf_size = xc_domain_hvm_getcontext(xc_handle, dom, 0, 0);
     if ( hvm_buf_size == -1 )
     {
@@ -508,13 +510,6 @@ int xc_hvm_save(int xc_handle, int io_fd
         N=0;
 
         DPRINTF("Saving HVM domain memory pages: iter %d   0%%", iter);
-
-        if (last_iter && (max_pfn != live_shinfo->arch.max_pfn)) {
-            DPRINTF("calculated max_pfn as %#lx, shinfo says %#lx\n",
-                    max_pfn, live_shinfo->arch.max_pfn);
-            ERROR("Max pfn doesn't match shared info");
-            goto out;
-        }
 
         while( N < pfn_array_size ){
 
@@ -663,8 +658,7 @@ int xc_hvm_save(int xc_handle, int io_fd
                     goto out;
                 }
 
-                DPRINTF("SUSPEND shinfo %08lx eip %08lx edx %08lx\n",
-                        info.shared_info_frame,
+                DPRINTF("SUSPEND eip %08lx edx %08lx\n",
                         (unsigned long)ctxt.user_regs.eip,
                         (unsigned long)ctxt.user_regs.edx);
             }
@@ -677,10 +671,23 @@ int xc_hvm_save(int xc_handle, int io_fd
                 goto out;
             }
 
+            /* Pull in the dirty bits from qemu too */
+            if (!last_iter) {
+                qemu_active = qemu_non_active;
+                qemu_non_active = qemu_active ? 0 : 1;
+                qemu_flip_buffer(dom, qemu_active);
+                for (j = 0; j < BITMAP_SIZE / sizeof(unsigned long); j++) {
+                    to_send[j] |= qemu_bitmaps[qemu_non_active][j];
+                    qemu_bitmaps[qemu_non_active][j] = 0;
+                }
+            } else {
+                for (j = 0; j < BITMAP_SIZE / sizeof(unsigned long); j++) 
+                    to_send[j] |= qemu_bitmaps[qemu_active][j];
+            }
+
             sent_last_iter = sent_this_iter;
 
             print_stats(xc_handle, dom, sent_this_iter, &stats, 1);
-
         }
 
 
@@ -739,12 +746,6 @@ int xc_hvm_save(int xc_handle, int io_fd
         ERROR("write HVM info failed!\n");
     }
 
-    /* Shared-info pfn */
-    if (!write_exact(io_fd, &(shared_info_frame), sizeof(uint32_t)) ) {
-        ERROR("write shared-info pfn failed!\n");
-        goto out;
-    }
- 
     /* Success! */
     rc = 0;
 
diff -r f74e837c3902 -r 2216a45bf058 tools/libxc/xc_private.c
--- a/tools/libxc/xc_private.c  Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/libxc/xc_private.c  Tue Mar 20 15:19:38 2007 -0600
@@ -263,6 +263,15 @@ int xc_memory_op(int xc_handle,
             goto out1;
         }
         break;
+    case XENMEM_current_reservation:
+    case XENMEM_maximum_reservation:
+    case XENMEM_maximum_gpfn:
+        if ( lock_pages(arg, sizeof(domid_t)) )
+        {
+            PERROR("Could not lock");
+            goto out1;
+        }
+        break;
     }
 
     ret = do_xen_hypercall(xc_handle, &hypercall);
@@ -286,6 +295,11 @@ int xc_memory_op(int xc_handle,
         break;
     case XENMEM_add_to_physmap:
         unlock_pages(arg, sizeof(struct xen_add_to_physmap));
+        break;
+    case XENMEM_current_reservation:
+    case XENMEM_maximum_reservation:
+    case XENMEM_maximum_gpfn:
+        unlock_pages(arg, sizeof(domid_t));
         break;
     }
 
diff -r f74e837c3902 -r 2216a45bf058 tools/libxc/xenguest.h
--- a/tools/libxc/xenguest.h    Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/libxc/xenguest.h    Tue Mar 20 15:19:38 2007 -0600
@@ -32,8 +32,10 @@ int xc_linux_save(int xc_handle, int io_
  * @return 0 on success, -1 on failure
  */
 int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
-                  uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */,
-                  int (*suspend)(int domid));
+                uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */,
+                int (*suspend)(int domid),  
+                void *(*init_qemu_maps)(int, unsigned), 
+                void (*qemu_flip_buffer)(int, int));
 
 /**
  * This function will restore a saved domain running Linux.
diff -r f74e837c3902 -r 2216a45bf058 tools/libxc/xg_private.c
--- a/tools/libxc/xg_private.c  Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/libxc/xg_private.c  Tue Mar 20 15:19:38 2007 -0600
@@ -201,7 +201,9 @@ __attribute__((weak))
 __attribute__((weak)) 
     int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
                     uint32_t max_factor, uint32_t flags,
-                    int (*suspend)(int domid))
+                    int (*suspend)(int domid), 
+                    void *(*init_qemu_maps)(int, unsigned), 
+                    void (*qemu_flip_buffer)(int, int))
 {
     errno = ENOSYS;
     return -1;
diff -r f74e837c3902 -r 2216a45bf058 tools/libxen/include/xen_vbd.h
--- a/tools/libxen/include/xen_vbd.h    Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/libxen/include/xen_vbd.h    Tue Mar 20 15:19:38 2007 -0600
@@ -72,7 +72,6 @@ typedef struct xen_vbd_record
     struct xen_vm_record_opt *vm;
     struct xen_vdi_record_opt *vdi;
     char *device;
-    char *image;
     bool bootable;
     enum xen_vbd_mode mode;
     enum xen_vbd_type type;
diff -r f74e837c3902 -r 2216a45bf058 tools/libxen/include/xen_vdi.h
--- a/tools/libxen/include/xen_vdi.h    Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/libxen/include/xen_vdi.h    Tue Mar 20 15:19:38 2007 -0600
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, XenSource Inc.
+ * Copyright (c) 2006-2007, XenSource Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -22,6 +22,7 @@
 #include "xen_common.h"
 #include "xen_crashdump_decl.h"
 #include "xen_sr_decl.h"
+#include "xen_string_string_map.h"
 #include "xen_vbd_decl.h"
 #include "xen_vdi_decl.h"
 #include "xen_vdi_type.h"
@@ -73,11 +74,10 @@ typedef struct xen_vdi_record
     struct xen_crashdump_record_opt_set *crash_dumps;
     int64_t virtual_size;
     int64_t physical_utilisation;
-    int64_t sector_size;
-    char *location;
     enum xen_vdi_type type;
     bool sharable;
     bool read_only;
+    xen_string_string_map *other_config;
 } xen_vdi_record;
 
 /**
@@ -251,13 +251,6 @@ xen_vdi_get_physical_utilisation(xen_ses
 
 
 /**
- * Get the sector_size field of the given VDI.
- */
-extern bool
-xen_vdi_get_sector_size(xen_session *session, int64_t *result, xen_vdi vdi);
-
-
-/**
  * Get the type field of the given VDI.
  */
 extern bool
@@ -279,6 +272,13 @@ xen_vdi_get_read_only(xen_session *sessi
 
 
 /**
+ * Get the other_config field of the given VDI.
+ */
+extern bool
+xen_vdi_get_other_config(xen_session *session, xen_string_string_map **result, 
xen_vdi vdi);
+
+
+/**
  * Set the name/label field of the given VDI.
  */
 extern bool
@@ -311,6 +311,30 @@ xen_vdi_set_sharable(xen_session *sessio
  */
 extern bool
 xen_vdi_set_read_only(xen_session *session, xen_vdi vdi, bool read_only);
+
+
+/**
+ * Set the other_config field of the given VDI.
+ */
+extern bool
+xen_vdi_set_other_config(xen_session *session, xen_vdi vdi, 
xen_string_string_map *other_config);
+
+
+/**
+ * Add the given key-value pair to the other_config field of the given
+ * VDI.
+ */
+extern bool
+xen_vdi_add_to_other_config(xen_session *session, xen_vdi vdi, char *key, char 
*value);
+
+
+/**
+ * Remove the given key and its corresponding value from the
+ * other_config field of the given VDI.  If the key is not in that Map, then
+ * do nothing.
+ */
+extern bool
+xen_vdi_remove_from_other_config(xen_session *session, xen_vdi vdi, char *key);
 
 
 /**
diff -r f74e837c3902 -r 2216a45bf058 tools/libxen/src/xen_vbd.c
--- a/tools/libxen/src/xen_vbd.c        Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/libxen/src/xen_vbd.c        Tue Mar 20 15:19:38 2007 -0600
@@ -54,9 +54,6 @@ static const struct_member xen_vbd_recor
         { .key = "device",
           .type = &abstract_type_string,
           .offset = offsetof(xen_vbd_record, device) },
-        { .key = "image",
-          .type = &abstract_type_string,
-          .offset = offsetof(xen_vbd_record, image) },
         { .key = "bootable",
           .type = &abstract_type_bool,
           .offset = offsetof(xen_vbd_record, bootable) },
diff -r f74e837c3902 -r 2216a45bf058 tools/libxen/src/xen_vdi.c
--- a/tools/libxen/src/xen_vdi.c        Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/libxen/src/xen_vdi.c        Tue Mar 20 15:19:38 2007 -0600
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, XenSource Inc.
+ * Copyright (c) 2006-2007, XenSource Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -24,6 +24,7 @@
 #include "xen_crashdump.h"
 #include "xen_internal.h"
 #include "xen_sr.h"
+#include "xen_string_string_map.h"
 #include "xen_vbd.h"
 #include "xen_vdi.h"
 #include "xen_vdi_type_internal.h"
@@ -64,12 +65,6 @@ static const struct_member xen_vdi_recor
         { .key = "physical_utilisation",
           .type = &abstract_type_int,
           .offset = offsetof(xen_vdi_record, physical_utilisation) },
-        { .key = "sector_size",
-          .type = &abstract_type_int,
-          .offset = offsetof(xen_vdi_record, sector_size) },
-        { .key = "location",
-          .type = &abstract_type_string,
-          .offset = offsetof(xen_vdi_record, location) },
         { .key = "type",
           .type = &xen_vdi_type_abstract_type_,
           .offset = offsetof(xen_vdi_record, type) },
@@ -78,7 +73,10 @@ static const struct_member xen_vdi_recor
           .offset = offsetof(xen_vdi_record, sharable) },
         { .key = "read_only",
           .type = &abstract_type_bool,
-          .offset = offsetof(xen_vdi_record, read_only) }
+          .offset = offsetof(xen_vdi_record, read_only) },
+        { .key = "other_config",
+          .type = &abstract_type_string_string_map,
+          .offset = offsetof(xen_vdi_record, other_config) }
     };
 
 const abstract_type xen_vdi_record_abstract_type_ =
@@ -105,6 +103,7 @@ xen_vdi_record_free(xen_vdi_record *reco
     xen_sr_record_opt_free(record->sr);
     xen_vbd_record_opt_set_free(record->vbds);
     xen_crashdump_record_opt_set_free(record->crash_dumps);
+    xen_string_string_map_free(record->other_config);
     free(record);
 }
 
@@ -315,22 +314,6 @@ xen_vdi_get_physical_utilisation(xen_ses
 
 
 bool
-xen_vdi_get_sector_size(xen_session *session, int64_t *result, xen_vdi vdi)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &abstract_type_string,
-              .u.string_val = vdi }
-        };
-
-    abstract_type result_type = abstract_type_int;
-
-    XEN_CALL_("VDI.get_sector_size");
-    return session->ok;
-}
-
-
-bool
 xen_vdi_get_type(xen_session *session, enum xen_vdi_type *result, xen_vdi vdi)
 {
     abstract_value param_values[] =
@@ -378,6 +361,23 @@ xen_vdi_get_read_only(xen_session *sessi
 
 
 bool
+xen_vdi_get_other_config(xen_session *session, xen_string_string_map **result, 
xen_vdi vdi)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vdi }
+        };
+
+    abstract_type result_type = abstract_type_string_string_map;
+
+    *result = NULL;
+    XEN_CALL_("VDI.get_other_config");
+    return session->ok;
+}
+
+
+bool
 xen_vdi_set_name_label(xen_session *session, xen_vdi vdi, char *label)
 {
     abstract_value param_values[] =
@@ -458,6 +458,56 @@ xen_vdi_set_read_only(xen_session *sessi
 
 
 bool
+xen_vdi_set_other_config(xen_session *session, xen_vdi vdi, 
xen_string_string_map *other_config)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vdi },
+            { .type = &abstract_type_string_string_map,
+              .u.set_val = (arbitrary_set *)other_config }
+        };
+
+    xen_call_(session, "VDI.set_other_config", param_values, 2, NULL, NULL);
+    return session->ok;
+}
+
+
+bool
+xen_vdi_add_to_other_config(xen_session *session, xen_vdi vdi, char *key, char 
*value)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vdi },
+            { .type = &abstract_type_string,
+              .u.string_val = key },
+            { .type = &abstract_type_string,
+              .u.string_val = value }
+        };
+
+    xen_call_(session, "VDI.add_to_other_config", param_values, 3, NULL, NULL);
+    return session->ok;
+}
+
+
+bool
+xen_vdi_remove_from_other_config(xen_session *session, xen_vdi vdi, char *key)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vdi },
+            { .type = &abstract_type_string,
+              .u.string_val = key }
+        };
+
+    xen_call_(session, "VDI.remove_from_other_config", param_values, 2, NULL, 
NULL);
+    return session->ok;
+}
+
+
+bool
 xen_vdi_snapshot(xen_session *session, xen_vdi *result, xen_vdi vdi)
 {
     abstract_value param_values[] =
diff -r f74e837c3902 -r 2216a45bf058 tools/libxen/test/test_bindings.c
--- a/tools/libxen/test/test_bindings.c Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/libxen/test/test_bindings.c Tue Mar 20 15:19:38 2007 -0600
@@ -421,8 +421,7 @@ static xen_vm create_new_vm(xen_session 
             .name_label = "MyRootFS",
             .name_description = "MyRootFS description",
             .sr = &sr_record,
-            .virtual_size = (1 << 21),  // 1GiB / 512 bytes/sector
-            .sector_size = 512,
+            .virtual_size = (INT64_C(1) << 30),  // 1GiB
             .type = XEN_VDI_TYPE_SYSTEM,
             .sharable = false,
             .read_only = false
diff -r f74e837c3902 -r 2216a45bf058 tools/python/scripts/test_hvm_create.py
--- a/tools/python/scripts/test_hvm_create.py   Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/python/scripts/test_hvm_create.py   Tue Mar 20 15:19:38 2007 -0600
@@ -39,14 +39,13 @@ local_vdi_cfg = {
 local_vdi_cfg = {
     'name_label': 'gentoo.hvm',
     'name_description': '',
-    'location': 'file:/root/gentoo.amd64.hvm.img',
     'virtual_size': 0,
-    'sector_size': 0,
     'type': 'system',
     'parent': '',
     'SR_name': 'Local',
     'sharable': False,
     'read_only': False,
+    'other_config': {'location': 'file:/root/gentoo.amd64.hvm.img'},
 }    
 
 local_vbd_cfg = {
diff -r f74e837c3902 -r 2216a45bf058 tools/python/scripts/test_vm_create.py
--- a/tools/python/scripts/test_vm_create.py    Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/python/scripts/test_vm_create.py    Tue Mar 20 15:19:38 2007 -0600
@@ -39,8 +39,7 @@ vdi_cfg = {
 vdi_cfg = {
     'name_label': 'API_VDI',
     'name_description': '',
-    'virtual_size': 100 * 1024 * 1024,
-    'sector_size': 1024,
+    'virtual_size': 100 * 1024 * 1024 * 1024,
     'type': 'system',
     'parent': '',
     'SR_name': 'QCoW',
@@ -60,14 +59,13 @@ local_vdi_cfg = {
 local_vdi_cfg = {
     'name_label': 'gentoo.amd64.img',
     'name_description': '',
-    'location': 'file:/root/gentoo.amd64.img',
     'virtual_size': 0,
-    'sector_size': 0,
     'type': 'system',
     'parent': '',
     'SR_name': 'Local',
     'sharable': False,
     'read_only': False,
+    'other_config': {'location': 'file:/root/gentoo.amd64.img'},
 }    
 
 local_vbd_cfg = {
diff -r f74e837c3902 -r 2216a45bf058 tools/python/scripts/xapi.py
--- a/tools/python/scripts/xapi.py      Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/python/scripts/xapi.py      Tue Mar 20 15:19:38 2007 -0600
@@ -40,8 +40,7 @@ VM_LIST_FORMAT = '%(name_label)-18s %(me
                  ' %(power_state)-10s %(uuid)-36s'
 SR_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(physical_size)-10s' \
                  '%(type)-10s'
-VDI_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(virtual_size)-8s '\
-                  '%(sector_size)-8s'
+VDI_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(virtual_size)-8s'
 VBD_LIST_FORMAT = '%(device)-6s %(uuid)-36s %(VDI)-8s'
 TASK_LIST_FORMAT = '%(name_label)-18s %(uuid)-36s %(status)-8s %(progress)-4s'
 VIF_LIST_FORMAT = '%(name)-8s %(device)-7s %(uuid)-36s %(MAC)-10s'
@@ -96,12 +95,9 @@ OPTIONS = {
     
     'vdi-create': [(('--name-label',), {'help': 'Name for VDI'}),
                    (('--name-description',), {'help': 'Description for VDI'}),
-                   (('--sector-size',), {'type': 'int',
-                                         'help': 'Sector size',
-                                         'default': 0}),
                    (('--virtual-size',), {'type': 'int',
                                           'default': 0,
-                                          'help': 'Size of VDI in sectors'}),
+                                          'help': 'Size of VDI in bytes'}),
                    (('--type',), {'choices': ['system', 'user', 'ephemeral'],
                                   'default': 'system',
                                   'help': 'VDI type'}),
@@ -569,8 +565,7 @@ def xapi_vdi_list(args, async = False):
     if not is_long:
         print VDI_LIST_FORMAT % {'name_label': 'VDI Label',
                                  'uuid' : 'UUID',
-                                 'virtual_size': 'Bytes',
-                                 'sector_size': 'Sector Size'}
+                                 'virtual_size': 'Bytes'}
         
         for vdi in vdis:
             vdi_struct = execute(server, 'VDI.get_record', (session, vdi))
diff -r f74e837c3902 -r 2216a45bf058 tools/python/scripts/xapi.vdicfg.py
--- a/tools/python/scripts/xapi.vdicfg.py       Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/python/scripts/xapi.vdicfg.py       Tue Mar 20 15:19:38 2007 -0600
@@ -1,7 +1,6 @@ name_label = 'VDI 1'
 name_label = 'VDI 1'
 name_description = ''
-virtual_size = 10 * 1024 * 1024
-sector_size = 1024
+virtual_size = 10 * 1024 * 1024 * 1024
 type = 'system'
 sharable = False
 read_only = False
diff -r f74e837c3902 -r 2216a45bf058 tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/python/xen/lowlevel/xc/xc.c Tue Mar 20 15:19:38 2007 -0600
@@ -50,17 +50,21 @@ static PyObject *pyxc_error_to_exception
     const xc_error *err = xc_get_last_error();
     const char *desc = xc_error_code_to_desc(err->code);
 
-    if (err->code == XC_ERROR_NONE)
+    if ( err->code == XC_ERROR_NONE )
         return PyErr_SetFromErrno(xc_error_obj);
 
-    if (err->message[0] != '\0')
+    if ( err->message[0] != '\0' )
        pyerr = Py_BuildValue("(iss)", err->code, desc, err->message);
     else
        pyerr = Py_BuildValue("(is)", err->code, desc);
 
     xc_clear_last_error();
 
-    PyErr_SetObject(xc_error_obj, pyerr);
+    if ( pyerr != NULL )
+    {
+        PyErr_SetObject(xc_error_obj, pyerr);
+        Py_DECREF(pyerr);
+    }
 
     return NULL;
 }
@@ -70,13 +74,13 @@ static PyObject *pyxc_domain_dumpcore(Xc
     uint32_t dom;
     char *corefile;
 
-    if (!PyArg_ParseTuple(args, "is", &dom, &corefile))
+    if ( !PyArg_ParseTuple(args, "is", &dom, &corefile) )
         return NULL;
 
     if ( (corefile == NULL) || (corefile[0] == '\0') )
         return NULL;
 
-    if (xc_domain_dumpcore(self->xc_handle, dom, corefile) != 0)
+    if ( xc_domain_dumpcore(self->xc_handle, dom, corefile) != 0 )
         return pyxc_error_to_exception();
     
     Py_INCREF(zero);
@@ -168,10 +172,10 @@ static PyObject *pyxc_domain_shutdown(Xc
 {
     uint32_t dom, reason;
 
-    if (!PyArg_ParseTuple(args, "ii", &dom, &reason))
+    if ( !PyArg_ParseTuple(args, "ii", &dom, &reason) )
       return NULL;
 
-    if (xc_domain_shutdown(self->xc_handle, dom, reason) != 0)
+    if ( xc_domain_shutdown(self->xc_handle, dom, reason) != 0 )
         return pyxc_error_to_exception();
     
     Py_INCREF(zero);
@@ -183,10 +187,10 @@ static PyObject *pyxc_domain_resume(XcOb
     uint32_t dom;
     int fast;
 
-    if (!PyArg_ParseTuple(args, "ii", &dom, &fast))
-        return NULL;
-
-    if (xc_domain_resume(self->xc_handle, dom, fast) != 0)
+    if ( !PyArg_ParseTuple(args, "ii", &dom, &fast) )
+        return NULL;
+
+    if ( xc_domain_resume(self->xc_handle, dom, fast) != 0 )
         return pyxc_error_to_exception();
 
     Py_INCREF(zero);
@@ -282,7 +286,7 @@ static PyObject *pyxc_domain_getinfo(XcO
                                      PyObject *args,
                                      PyObject *kwds)
 {
-    PyObject *list, *info_dict;
+    PyObject *list, *info_dict, *pyhandle;
 
     uint32_t first_dom = 0;
     int max_doms = 1024, nr_doms, i, j;
@@ -308,26 +312,34 @@ static PyObject *pyxc_domain_getinfo(XcO
     list = PyList_New(nr_doms);
     for ( i = 0 ; i < nr_doms; i++ )
     {
-        PyObject *pyhandle = PyList_New(sizeof(xen_domain_handle_t));
+        info_dict = Py_BuildValue(
+            "{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
+            ",s:L,s:L,s:L,s:i,s:i}",
+            "domid",           (int)info[i].domid,
+            "online_vcpus",    info[i].nr_online_vcpus,
+            "max_vcpu_id",     info[i].max_vcpu_id,
+            "hvm",             info[i].hvm,
+            "dying",           info[i].dying,
+            "crashed",         info[i].crashed,
+            "shutdown",        info[i].shutdown,
+            "paused",          info[i].paused,
+            "blocked",         info[i].blocked,
+            "running",         info[i].running,
+            "mem_kb",          (long long)info[i].nr_pages*(XC_PAGE_SIZE/1024),
+            "cpu_time",        (long long)info[i].cpu_time,
+            "maxmem_kb",       (long long)info[i].max_memkb,
+            "ssidref",         (int)info[i].ssidref,
+            "shutdown_reason", info[i].shutdown_reason);
+        pyhandle = PyList_New(sizeof(xen_domain_handle_t));
+        if ( (pyhandle == NULL) || (info_dict == NULL) )
+        {
+            Py_DECREF(list);
+            if ( pyhandle  != NULL ) { Py_DECREF(pyhandle);  }
+            if ( info_dict != NULL ) { Py_DECREF(info_dict); }
+            return NULL;
+        }
         for ( j = 0; j < sizeof(xen_domain_handle_t); j++ )
             PyList_SetItem(pyhandle, j, PyInt_FromLong(info[i].handle[j]));
-        info_dict = Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
-                                  ",s:l,s:L,s:l,s:i,s:i}",
-                                  "domid",       info[i].domid,
-                                  "online_vcpus", info[i].nr_online_vcpus,
-                                  "max_vcpu_id", info[i].max_vcpu_id,
-                                  "hvm",       info[i].hvm,
-                                  "dying",     info[i].dying,
-                                  "crashed",   info[i].crashed,
-                                  "shutdown",  info[i].shutdown,
-                                  "paused",    info[i].paused,
-                                  "blocked",   info[i].blocked,
-                                  "running",   info[i].running,
-                                  "mem_kb",    
info[i].nr_pages*(XC_PAGE_SIZE/1024),
-                                  "cpu_time",  info[i].cpu_time,
-                                  "maxmem_kb", info[i].max_memkb,
-                                  "ssidref",   info[i].ssidref,
-                                  "shutdown_reason", info[i].shutdown_reason);
         PyDict_SetItemString(info_dict, "handle", pyhandle);
         Py_DECREF(pyhandle);
         PyList_SetItem(list, i, info_dict);
diff -r f74e837c3902 -r 2216a45bf058 tools/python/xen/util/blkif.py
--- a/tools/python/xen/util/blkif.py    Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/python/xen/util/blkif.py    Tue Mar 20 15:19:38 2007 -0600
@@ -66,16 +66,23 @@ def blkdev_segment(name):
                 'type'         : 'Disk' }
     return val
 
-def blkdev_uname_to_file(uname):
-    """Take a blkdev uname and return the corresponding filename."""
-    fn = None
+def _parse_uname(uname):
+    fn = taptype = None
     if uname.find(":") != -1:
         (typ, fn) = uname.split(":", 1)
         if typ == "phy" and not fn.startswith("/"):
             fn = "/dev/%s" %(fn,)
         if typ == "tap":
-            (typ, fn) = fn.split(":", 1)
-    return fn
+            (taptype, fn) = fn.split(":", 1)
+    return (fn, taptype)
+
+def blkdev_uname_to_file(uname):
+    """Take a blkdev uname and return the corresponding filename."""
+    return _parse_uname(uname)[0]
+
+def blkdev_uname_to_taptype(uname):
+    """Take a blkdev uname and return the blktap type."""
+    return _parse_uname(uname)[1]
 
 def mount_mode(name):
     mode = None
diff -r f74e837c3902 -r 2216a45bf058 tools/python/xen/util/xmlrpclib2.py
--- a/tools/python/xen/util/xmlrpclib2.py       Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/python/xen/util/xmlrpclib2.py       Tue Mar 20 15:19:38 2007 -0600
@@ -227,24 +227,30 @@ class TCPXMLRPCServer(SocketServer.Threa
             response = xmlrpclib.dumps(response,
                                        methodresponse=1,
                                        allow_none=1)
-        except xmlrpclib.Fault, fault:
-            response = xmlrpclib.dumps(fault)
         except Exception, exn:
-            if self.xenapi:
-                if _is_not_supported(exn):
-                    errdesc = ['MESSAGE_METHOD_UNKNOWN', method]
+            try:
+                if self.xenapi:
+                    if _is_not_supported(exn):
+                         errdesc = ['MESSAGE_METHOD_UNKNOWN', method]
+                    else:
+                         log.exception('Internal error handling %s', method)
+                         errdesc = ['INTERNAL_ERROR', str(exn)]
+
+                    response = xmlrpclib.dumps(
+                          ({ "Status": "Failure",
+                             "ErrorDescription": errdesc },),
+                          methodresponse = 1)
                 else:
-                    log.exception('Internal error handling %s', method)
-                    errdesc = ['INTERNAL_ERROR', str(exn)]
-                response = xmlrpclib.dumps(
-                    ({ "Status": "Failure",
-                       "ErrorDescription": errdesc },),
-                    methodresponse = 1)
-            else:
-                log.exception('Internal error handling %s', method)
-                import xen.xend.XendClient
-                response = xmlrpclib.dumps(
-                    xmlrpclib.Fault(xen.xend.XendClient.ERROR_INTERNAL, 
str(exn)))
+                    import xen.xend.XendClient
+                    if isinstance(exn, xmlrpclib.Fault):
+                        response = xmlrpclib.dumps(exn)
+                    else:
+                        log.exception('Internal error handling %s', method)
+                        response = xmlrpclib.dumps(
+                            
xmlrpclib.Fault(xen.xend.XendClient.ERROR_INTERNAL, str(exn)))
+            except:
+                log.exception('Internal error handling error')
+
         return response
 
 
@@ -253,7 +259,7 @@ def _is_not_supported(exn):
     try:
         m = notSupportedRE.search(exn[0])
         return m is not None
-    except TypeError, e:
+    except:
         return False
 
 
diff -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xend/XendAPI.py
--- a/tools/python/xen/xend/XendAPI.py  Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/python/xen/xend/XendAPI.py  Tue Mar 20 15:19:38 2007 -0600
@@ -35,6 +35,9 @@ from xen.xend.XendVMMetrics import XendV
 
 from xen.xend.XendAPIConstants import *
 from xen.util.xmlrpclib2 import stringify
+
+from xen.util.blkif import blkdev_name_to_number
+
 
 AUTH_NONE = 'none'
 AUTH_PAM = 'pam'
@@ -662,7 +665,8 @@ class XendAPI(object):
                     ('add_to_other_config', None),
                     ('remove_from_other_config', None),
                     ('dmesg', 'String'),
-                    ('get_log', 'String')]
+                    ('get_log', 'String'),
+                    ('send_debug_keys', None)]
     
     host_funcs = [('get_by_name_label', 'Set(host)')]
 
@@ -748,6 +752,11 @@ class XendAPI(object):
         log_file = open(XendLogging.getLogFilename())
         log_buffer = log_file.read()
         return xen_api_success(log_buffer)
+
+    def host_send_debug_keys(self, _, host_ref, keys):
+        node = XendNode.instance()
+        node.send_debug_keys(keys)
+        return xen_api_success_void()
 
     def host_get_record(self, session, host_ref):
         node = XendNode.instance()
@@ -1070,6 +1079,7 @@ class XendAPI(object):
                   ('hard_reboot', None),
                   ('suspend', None),
                   ('resume', None),
+                  ('send_sysrq', None),
                   ('add_to_HVM_boot_params', None),
                   ('remove_from_HVM_boot_params', None),
                   ('add_to_VCPUs_params', None),
@@ -1077,7 +1087,8 @@ class XendAPI(object):
                   ('add_to_platform', None),
                   ('remove_from_platform', None),
                   ('add_to_other_config', None),
-                  ('remove_from_other_config', None)]
+                  ('remove_from_other_config', None),
+                  ('send_trigger', None)]
     
     VM_funcs  = [('create', 'VM'),
                  ('get_by_name_label', 'Set(VM)')]
@@ -1513,6 +1524,24 @@ class XendAPI(object):
         return XendTask.log_progress(0, 100, do_vm_func,
                                      "domain_unpause", vm_ref)
 
+    def VM_send_sysrq(self, _, vm_ref, req):
+        xeninfo = XendDomain.instance().get_vm_by_uuid(vm_ref)
+        if xeninfo.state != XEN_API_VM_POWER_STATE_RUNNING:
+            return xen_api_error(
+                ['VM_BAD_POWER_STATE', vm_ref,
+                 XendDomain.POWER_STATE_NAMES[XEN_API_VM_POWER_STATE_RUNNING],
+                 XendDomain.POWER_STATE_NAMES[xeninfo.state]])
+        xeninfo.send_sysrq(req)
+        return xen_api_success_void()
+
+
+    def VM_send_trigger(self, _, vm_ref, trigger, vcpu):
+        xendom = XendDomain.instance()
+        xeninfo = xendom.get_vm_by_uuid(vm_ref)
+        xendom.domain_send_trigger(xeninfo.getDomid(), trigger, vcpu)
+        return xen_api_success_void()
+        
+
     # Xen API: Class VM_metrics
     # ----------------------------------------------------------------
 
@@ -1538,12 +1567,13 @@ class XendAPI(object):
         return xen_api_success(self._VM_metrics_get(ref).get_vcpus_number())
 
     def VM_metrics_get_vcpus_utilisation(self, _, ref):
-        return 
xen_api_success(self._VM_metrics_get(ref).get_metrics_get_vcpus_utilisation())
+        return 
xen_api_success(self._VM_metrics_get(ref).get_vcpus_utilisation())
 
     # Xen API: Class VBD
     # ----------------------------------------------------------------
 
-    VBD_attr_ro = ['metrics']
+    VBD_attr_ro = ['metrics',
+                   'runtime_properties']
     VBD_attr_rw = ['VM',
                    'VDI',
                    'device',
@@ -1584,23 +1614,28 @@ class XendAPI(object):
     # class methods
     def VBD_create(self, session, vbd_struct):
         xendom = XendDomain.instance()
+        xennode = XendNode.instance()
+        
         if not xendom.is_valid_vm(vbd_struct['VM']):
             return xen_api_error(['HANDLE_INVALID', 'VM', vbd_struct['VM']])
         
         dom = xendom.get_vm_by_uuid(vbd_struct['VM'])
-        vbd_ref = ''
+        vdi = xennode.get_vdi_by_uuid(vbd_struct['VDI'])
+        if not vdi:
+            return xen_api_error(['HANDLE_INVALID', 'VDI', vdi_ref])
+
+        # new VBD via VDI/SR
+        vdi_image = vdi.get_location()
+
         try:
-            # new VBD via VDI/SR
-            vdi_ref = vbd_struct.get('VDI')
-            vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
-            if not vdi:
-                return xen_api_error(['HANDLE_INVALID', 'VDI', vdi_ref])
-            vdi_image = vdi.get_location()
             vbd_ref = XendTask.log_progress(0, 100,
                                             dom.create_vbd,
                                             vbd_struct, vdi_image)
-        except XendError:
-            return xen_api_todo()
+        except XendError, e:
+            log.exception("Error in VBD_create")
+            return xen_api_error(['INTERNAL_ERROR', str(e)]) 
+            
+        vdi.addVBD(vbd_ref)
 
         xendom.managed_config_save(dom)
         return xen_api_success(vbd_ref)
@@ -1612,7 +1647,14 @@ class XendAPI(object):
         if not vm:
             return xen_api_error(['HANDLE_INVALID', 'VBD', vbd_ref])
 
+        vdi_ref = XendDomain.instance()\
+                  .get_dev_property_by_uuid('vbd', vbd_ref, "VDI")
+        vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
+
         XendTask.log_progress(0, 100, vm.destroy_vbd, vbd_ref)
+
+        vdi.removeVBD(vbd_ref)
+        
         return xen_api_success_void()
 
     def _VBD_get(self, vbd_ref, prop):
@@ -1623,6 +1665,24 @@ class XendAPI(object):
     # attributes (ro)
     def VBD_get_metrics(self, _, vbd_ref):
         return xen_api_success(vbd_ref)
+
+    def VBD_get_runtime_properties(self, _, vbd_ref):
+        xendom = XendDomain.instance()
+        dominfo = xendom.get_vm_with_dev_uuid('vbd', vbd_ref)
+        device = dominfo.get_dev_config_by_uuid('vbd', vbd_ref)
+
+        try:
+            devid = int(device['id'])
+            device_sxps = dominfo.getDeviceSxprs('vbd')
+            device_dicts  = [dict(device_sxp[1][1:]) for device_sxp in 
device_sxps]
+            device_dict = [device_dict
+                           for device_dict in device_dicts
+                           if int(device_dict['virtual-device']) == devid][0]
+
+            return xen_api_success(device_dict)
+        except Exception, exn:
+            log.exception(exn)
+            return xen_api_success({})
 
     # attributes (rw)
     def VBD_get_VM(self, session, vbd_ref):
@@ -1684,7 +1744,8 @@ class XendAPI(object):
     # Xen API: Class VIF
     # ----------------------------------------------------------------
 
-    VIF_attr_ro = ['metrics']
+    VIF_attr_ro = ['metrics',
+                   'runtime_properties']
     VIF_attr_rw = ['device',
                    'network',
                    'VM',
@@ -1721,18 +1782,17 @@ class XendAPI(object):
     # class methods
     def VIF_create(self, session, vif_struct):
         xendom = XendDomain.instance()
-        if xendom.is_valid_vm(vif_struct['VM']):
-            dom = xendom.get_vm_by_uuid(vif_struct['VM'])
-            try:
-                vif_ref = dom.create_vif(vif_struct)
-                xendom.managed_config_save(dom)                
-                return xen_api_success(vif_ref)
-            except XendError:
-                return xen_api_error(XEND_ERROR_TODO)
-        else:
+        if not xendom.is_valid_vm(vif_struct['VM']):
             return xen_api_error(['HANDLE_INVALID', 'VM', vif_struct['VM']])
 
-
+        dom = xendom.get_vm_by_uuid(vif_struct['VM'])
+        try:
+            vif_ref = dom.create_vif(vif_struct)
+            xendom.managed_config_save(dom)
+            return xen_api_success(vif_ref)
+        except XendError:
+            return xen_api_error(XEND_ERROR_TODO)
+          
     def VIF_destroy(self, session, vif_ref):
         xendom = XendDomain.instance()
         vm = xendom.get_vm_with_dev_uuid('vif', vif_ref)
@@ -1770,6 +1830,27 @@ class XendAPI(object):
         vifs = reduce(lambda x, y: x + y, vifs)
         return xen_api_success(vifs)
 
+    def VIF_get_runtime_properties(self, _, vif_ref):
+        xendom = XendDomain.instance()
+        dominfo = xendom.get_vm_with_dev_uuid('vif', vif_ref)
+        device = dominfo.get_dev_config_by_uuid('vif', vif_ref)
+        
+        try:
+            devid = int(device['id'])
+        
+            device_sxps = dominfo.getDeviceSxprs('vif')
+            device_dicts = [dict(device_sxp[1][1:])
+                            for device_sxp in device_sxps]
+            
+            device_dict = [device_dict
+                       for device_dict in device_dicts
+                       if int(device_dict['handle']) == devid][0]
+            
+            return xen_api_success(device_dict)
+        
+        except Exception, exn:
+            log.exception(exn)
+            return xen_api_success({})
     
     # Xen API: Class VIF_metrics
     # ----------------------------------------------------------------
@@ -1799,13 +1880,13 @@ class XendAPI(object):
     VDI_attr_ro = ['SR',
                    'VBDs',
                    'physical_utilisation',
-                   'sector_size',
                    'type']
     VDI_attr_rw = ['name_label',
                    'name_description',
                    'virtual_size',
                    'sharable',
-                   'read_only']
+                   'read_only',
+                   'other_config']
     VDI_attr_inst = VDI_attr_ro + VDI_attr_rw
 
     VDI_methods = [('snapshot', 'VDI')]
@@ -1816,14 +1897,12 @@ class XendAPI(object):
         return XendNode.instance().get_vdi_by_uuid(ref)
     
     def VDI_get_VBDs(self, session, vdi_ref):
-        return xen_api_todo()
+        vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref)
+        return xen_api_success(vdi.getVBDs())
     
     def VDI_get_physical_utilisation(self, session, vdi_ref):
         return xen_api_success(self._get_VDI(vdi_ref).
-                               get_physical_utilisation())        
-    
-    def VDI_get_sector_size(self, session, vdi_ref):
-        return xen_api_success(self._get_VDI(vdi_ref).sector_size)        
+                               get_physical_utilisation())              
     
     def VDI_get_type(self, session, vdi_ref):
         return xen_api_success(self._get_VDI(vdi_ref).type)
@@ -1863,6 +1942,14 @@ class XendAPI(object):
     
     def VDI_set_read_only(self, session, vdi_ref, value):
         self._get_VDI(vdi_ref).read_only = bool(value)
+        return xen_api_success_void()
+
+    def VDI_get_other_config(self, session, vdi_ref):
+        return xen_api_success(
+            self._get_VDI(vdi_ref).other_config)
+
+    def VDI_set_other_config(self, session, vdi_ref, other_config):
+        self._get_VDI(vdi_ref).other_config = other_config
         return xen_api_success_void()
 
     # Object Methods
@@ -1881,13 +1968,13 @@ class XendAPI(object):
             'name_label': image.name_label,
             'name_description': image.name_description,
             'SR': image.sr_uuid,
-            'VBDs': [], # TODO
+            'VBDs': image.getVBDs(),
             'virtual_size': image.virtual_size,
             'physical_utilisation': image.physical_utilisation,
-            'sector_size': image.sector_size,
             'type': image.type,
             'sharable': image.sharable,
             'read_only': image.read_only,
+            'other_config': image.other_config
             })
 
     # Class Functions    
diff -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xend/XendCheckpoint.py
--- a/tools/python/xen/xend/XendCheckpoint.py   Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/python/xen/xend/XendCheckpoint.py   Tue Mar 20 15:19:38 2007 -0600
@@ -193,8 +193,8 @@ def restore(xd, fd, dominfo = None, paus
     is_hvm = dominfo.info.is_hvm()
     if is_hvm:
         hvm  = dominfo.info['memory_static_min']
-        apic = dominfo.info['platform'].get('apic', 0)
-        pae  = dominfo.info['platform'].get('pae',  0)
+        apic = int(dominfo.info['platform'].get('apic', 0))
+        pae  = int(dominfo.info['platform'].get('pae',  0))
         log.info("restore hvm domain %d, mem=%d, apic=%d, pae=%d",
                  dominfo.domid, hvm, apic, pae)
     else:
diff -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py       Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/python/xen/xend/XendConfig.py       Tue Mar 20 15:19:38 2007 -0600
@@ -28,7 +28,7 @@ from xen.xend.XendConstants import DOM_S
 from xen.xend.XendConstants import DOM_STATE_HALTED
 
 log = logging.getLogger("xend.XendConfig")
-log.setLevel(logging.DEBUG)
+log.setLevel(logging.WARN)
 
 
 """
@@ -105,8 +105,6 @@ XENAPI_CFG_TO_LEGACY_CFG = {
     'uuid': 'uuid',
     'vcpus_number': 'vcpus',
     'cpus': 'cpus',
-    'memory_static_min': 'memory',
-    'memory_static_max': 'maxmem',
     'name_label': 'name',
     'actions_after_shutdown': 'on_poweroff',
     'actions_after_reboot': 'on_reboot',
@@ -136,11 +134,10 @@ XENAPI_CFG_TYPES = {
     'user_version': str,
     'is_a_template': bool0,
     'resident_on': str,
-    'memory_static_min': int,
+    'memory_static_min': int,  # note these are stored in bytes, not KB!
     'memory_static_max': int,
     'memory_dynamic_min': int,
     'memory_dynamic_max': int,
-    'memory_actual': int,
     'cpus': list,
     'vcpus_policy': str,
     'vcpus_params': dict,
@@ -314,7 +311,6 @@ class XendConfig(dict):
             'shadow_memory': 0,
             'memory_static_max': 0,
             'memory_dynamic_max': 0,
-            'memory_actual': 0,
             'devices': {},
             'security': None,
             'on_xend_start': 'ignore',
@@ -334,20 +330,39 @@ class XendConfig(dict):
         
         return defaults
 
+    #
+    # Here we assume these values exist in the dict.
+    # If they don't we have a bigger problem, lets not
+    # try and 'fix it up' but acutually fix the cause ;-)
+    #
     def _memory_sanity_check(self):
-        if self['memory_static_min'] == 0:
-            self['memory_static_min'] = self['memory_dynamic_min']
-
-        # If the static max is not set, let's set it to dynamic max.
-        # If the static max is smaller than static min, then fix it!
-        self['memory_static_max'] = max(self['memory_static_max'],
-                                        self['memory_dynamic_max'],
-                                        self['memory_static_min'])
-
-        for mem_type in ('memory_static_min', 'memory_static_max'):
-            if self[mem_type] <= 0:
-                raise XendConfigError('Memory value too low for %s: %d' %
-                                      (mem_type, self[mem_type]))
+        log.debug("_memory_sanity_check memory_static_min: %s, "
+                      "memory_static_max: %i, "
+                      "memory_dynamic_min: %i, " 
+                      "memory_dynamic_max: %i",
+                      self["memory_static_min"],
+                      self["memory_static_max"],
+                      self["memory_dynamic_min"],
+                      self["memory_dynamic_max"])
+        
+        if not self["memory_static_min"] <= self["memory_static_max"]:
+            raise XendConfigError("memory_static_min must be less " \
+                                  "than or equal to memory_static_max") 
+        if not self["memory_dynamic_min"] <= self["memory_dynamic_max"]:
+            raise XendConfigError("memory_dynamic_min must be less " \
+                                  "than or equal to memory_dynamic_max")
+        if not self["memory_static_min"] <= self["memory_dynamic_min"]:
+            raise XendConfigError("memory_static_min must be less " \
+                                  "than or equal to memory_dynamic_min")
+        if not self["memory_dynamic_max"] <= self["memory_static_max"]:
+            raise XendConfigError("memory_dynamic_max must be less " \
+                                  "than or equal to memory_static_max")
+        if not self["memory_dynamic_max"] > 0:
+            raise XendConfigError("memory_dynamic_max must be greater " \
+                                  "than zero")
+        if not self["memory_static_max"] > 0:
+            raise XendConfigError("memory_static_max must be greater " \
+                                  "than zero")
 
     def _actions_sanity_check(self):
         for event in ['shutdown', 'reboot', 'crash']:
@@ -392,8 +407,12 @@ class XendConfig(dict):
         self['domid'] = dominfo['domid']
         self['online_vcpus'] = dominfo['online_vcpus']
         self['vcpus_number'] = dominfo['max_vcpu_id'] + 1
-        self['memory_dynamic_min'] = (dominfo['mem_kb'] + 1023)/1024
-        self['memory_dynamic_max'] = (dominfo['maxmem_kb'] + 1023)/1024
+
+        self['memory_dynamic_min'] = dominfo['mem_kb'] * 1024
+        self['memory_dynamic_max'] = dominfo['mem_kb'] * 1024
+        self['memory_static_min'] = 0
+        self['memory_static_max'] = dominfo['maxmem_kb'] * 1024
+
         self['cpu_time'] = dominfo['cpu_time']/1e9
         # TODO: i don't know what the security stuff expects here
         if dominfo.get('ssidref'):
@@ -447,6 +466,13 @@ class XendConfig(dict):
                 log.warn('Ignoring unrecognised value for deprecated option:'
                          'restart = \'%s\'', restart)
 
+        # Handle memory, passed in as MiB
+
+        if sxp.child_value(sxp_cfg, "memory") != None:
+            cfg["memory"] = int(sxp.child_value(sxp_cfg, "memory"))
+        if sxp.child_value(sxp_cfg, "maxmem") != None:
+            cfg["maxmem"] = int(sxp.child_value(sxp_cfg, "maxmem"))
+            
         # Only extract options we know about.
         extract_keys = LEGACY_UNSUPPORTED_BY_XENAPI_CFG
         extract_keys += XENAPI_CFG_TO_LEGACY_CFG.values()
@@ -616,6 +642,21 @@ class XendConfig(dict):
             except KeyError:
                 pass
 
+        # Lets try and handle memory correctly
+
+        MiB = 1024 * 1024
+
+        if "memory" in cfg:
+            self["memory_static_min"] = 0
+            self["memory_static_max"] = int(cfg["memory"]) * MiB
+            self["memory_dynamic_min"] = int(cfg["memory"]) * MiB
+            self["memory_dynamic_max"] = int(cfg["memory"]) * MiB
+            
+            if "maxmem" in cfg:
+                self["memory_static_max"] = int(cfg["maxmem"]) * MiB
+
+        self._memory_sanity_check()
+
         def update_with(n, o):
             if not self.get(n):
                 self[n] = cfg.get(o, '')
@@ -631,13 +672,6 @@ class XendConfig(dict):
         for key in XENAPI_PLATFORM_CFG:
             if key in cfg:
                 self['platform'][key] = cfg[key]
-
-        # make sure a sane maximum is set
-        if self['memory_static_max'] <= 0:
-            self['memory_static_max'] = self['memory_static_min']
-            
-        self['memory_dynamic_max'] = self['memory_static_max']
-        self['memory_dynamic_min'] = self['memory_static_min']
 
         # set device references in the configuration
         self['devices'] = cfg.get('devices', {})
@@ -812,6 +846,21 @@ class XendConfig(dict):
                 else:
                     sxpr.append([legacy, self[xenapi]])
 
+        MiB = 1024*1024
+
+        sxpr.append(["maxmem", int(self["memory_static_max"])/MiB])
+        sxpr.append(["memory", int(self["memory_dynamic_max"])/MiB])
+
+        if not legacy_only:
+            sxpr.append(['memory_dynamic_min',
+                     int(self.get('memory_dynamic_min'))])
+            sxpr.append(['memory_dynamic_max',
+                     int(self.get('memory_dynamic_max'))])
+            sxpr.append(['memory_static_max',
+                     int(self.get('memory_static_max'))])
+            sxpr.append(['memory_static_min',
+                     int(self.get('memory_static_min'))])
+
         for legacy in LEGACY_UNSUPPORTED_BY_XENAPI_CFG:
             if legacy in ('domid', 'uuid'): # skip these
                 continue
@@ -820,8 +869,6 @@ class XendConfig(dict):
 
         sxpr.append(['image', self.image_sxpr()])
         sxpr.append(['status', domain.state])
-        sxpr.append(['memory_dynamic_min',  self.get('memory_dynamic_min')])
-        sxpr.append(['memory_dynamic_max',  self.get('memory_dynamic_max')])
 
         if domain.getDomid() is not None:
             sxpr.append(['state', self._get_old_state_string()])
diff -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xend/XendDomain.py
--- a/tools/python/xen/xend/XendDomain.py       Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/python/xen/xend/XendDomain.py       Tue Mar 20 15:19:38 2007 -0600
@@ -674,7 +674,7 @@ class XendDomain:
                 else:
                     return domid
             
-            raise XendInvalidDomain("Domain does not exist")
+            raise XendInvalidDomain(vm_uuid)
         finally:
             self.domains_lock.release()
         
diff -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/python/xen/xend/XendDomainInfo.py   Tue Mar 20 15:19:38 2007 -0600
@@ -34,7 +34,7 @@ from types import StringTypes
 
 import xen.lowlevel.xc
 from xen.util import asserts
-from xen.util.blkif import blkdev_uname_to_file
+from xen.util.blkif import blkdev_uname_to_file, blkdev_uname_to_taptype
 from xen.util import security
 
 from xen.xend import balloon, sxp, uuid, image, arch, osdep
@@ -576,12 +576,14 @@ class XendDomainInfo:
         if target <= 0:
             raise XendError('Invalid memory size')
         
-        self.info['memory_static_min'] = target
+        MiB = 1024 * 1024
+        self.info['memory_dynamic_min'] = target * MiB
+        self.info['memory_dynamic_max'] = target * MiB
+
         if self.domid >= 0:
             self.storeVm("memory", target)
             self.storeDom("memory/target", target << 10)
         else:
-            self.info['memory_dynamic_min'] = target
             xen.xend.XendDomain.instance().managed_config_save(self)
 
     def setMemoryMaximum(self, limit):
@@ -664,6 +666,10 @@ class XendDomainInfo:
                 if arg in XendConfig.LEGACY_CFG_TO_XENAPI_CFG:
                     xapiarg = XendConfig.LEGACY_CFG_TO_XENAPI_CFG[arg]
                     self.info[xapiarg] = val
+                elif arg == "memory":
+                    self.info["static_memory_min"] = val
+                elif arg == "maxmem":
+                    self.info["static_memory_max"] = val
                 else:
                     self.info[arg] = val
 
@@ -780,7 +786,7 @@ class XendDomainInfo:
             'vm':                 self.vmpath,
             'name':               self.info['name_label'],
             'console/limit':      str(xoptions.get_console_limit() * 1024),
-            'memory/target':      str(self.info['memory_static_min'] * 1024),
+            'memory/target':      str(self.info['memory_dynamic_max'] / 1024),
             }
 
         def f(n, v):
@@ -864,7 +870,15 @@ class XendDomainInfo:
                 xapiarg = XendConfig.LEGACY_CFG_TO_XENAPI_CFG[arg]
                 if val != None and val != self.info[xapiarg]:
                     self.info[xapiarg] = val
-                    changed= True
+                    changed = True
+            elif arg == "memory":
+                if val != None and val != self.info["static_memory_min"]:
+                    self.info["static_memory_min"] = val
+                    changed = True
+            elif arg == "maxmem":
+                if val != None and val != self.info["static_memory_max"]:
+                    self.info["static_memory_max"] = val
+                    changed = True
 
         # Check whether image definition has been updated
         image_sxp = self._readVm('image')
@@ -969,11 +983,12 @@ class XendDomainInfo:
 
     def getMemoryTarget(self):
         """Get this domain's target memory size, in KB."""
-        return self.info['memory_static_min'] * 1024
+        return self.info['memory_dynamic_max'] / 1024
 
     def getMemoryMaximum(self):
         """Get this domain's maximum memory size, in KB."""
-        return self.info['memory_static_max'] * 1024
+        # remember, info now stores memory in bytes
+        return self.info['memory_static_max'] / 1024
 
     def getResume(self):
         return str(self._resume)
@@ -1455,13 +1470,14 @@ class XendDomainInfo:
             # Use architecture- and image-specific calculations to determine
             # the various headrooms necessary, given the raw configured
             # values. maxmem, memory, and shadow are all in KiB.
+            # but memory_static_max etc are all stored in bytes now.
             memory = self.image.getRequiredAvailableMemory(
-                self.info['memory_static_min'] * 1024)
+                self.info['memory_dynamic_max'] / 1024)
             maxmem = self.image.getRequiredAvailableMemory(
-                self.info['memory_static_max'] * 1024)
+                self.info['memory_static_max'] / 1024)
             shadow = self.image.getRequiredShadowMemory(
-                self.info['shadow_memory'] * 1024,
-                self.info['memory_static_max'] * 1024)
+                self.info['shadow_memory'] / 1024,
+                self.info['memory_static_max'] / 1024)
 
             log.debug("_initDomain:shadow_memory=0x%x, memory_static_max=0x%x, 
memory_static_min=0x%x.", self.info['shadow_memory'], 
self.info['memory_static_max'], self.info['memory_static_min'],)
             # Round shadow up to a multiple of a MiB, as shadow_mem_control
@@ -1650,7 +1666,18 @@ class XendDomainInfo:
             log.exception("XendDomainInfo.destroy: xc.domain_destroy failed.")
 
         from xen.xend import XendDomain
-        XendDomain.instance().remove_domain(self)
+
+        if "transient" in self.info["other_config"]\
+           and bool(self.info["other_config"]["transient"]):
+            xendDomainInstance = XendDomain.instance()
+            
+            xendDomainInstance.domains_lock.acquire()
+            xendDomainInstance._refresh(refresh_shutdown = False)
+            xendDomainInstance.domains_lock.release()
+            
+            xendDomainInstance.domain_delete(self.info["name_label"])
+        else:
+            XendDomain.instance().remove_domain(self)
 
         self.cleanupDomain()
         self._cleanup_phantom_devs(paths)
@@ -1759,7 +1786,8 @@ class XendDomainInfo:
             disk = devinfo[1]['uname']
 
             fn = blkdev_uname_to_file(disk)
-            mounted = devtype == 'tap' and not os.stat(fn).st_rdev
+            taptype = blkdev_uname_to_taptype(disk)
+            mounted = devtype == 'tap' and taptype != 'aio' and taptype != 
'sync' and not os.stat(fn).st_rdev
             if mounted:
                 # This is a file, not a device.  pygrub can cope with a
                 # file if it's raw, but if it's QCOW or other such formats
@@ -1775,7 +1803,7 @@ class XendDomainInfo:
 
                 from xen.xend import XendDomain
                 dom0 = XendDomain.instance().privilegedDomain()
-                dom0._waitForDeviceUUID(dom0.create_vbd(vbd, fn))
+                dom0._waitForDeviceUUID(dom0.create_vbd(vbd, disk))
                 fn = BOOTLOADER_LOOPBACK_DEVICE
 
             try:
@@ -1833,7 +1861,7 @@ class XendDomainInfo:
             # 1MB per vcpu plus 4Kib/Mib of RAM.  This is higher than 
             # the minimum that Xen would allocate if no value were given.
             overhead_kb = self.info['vcpus_number'] * 1024 + \
-                          self.info['memory_static_max'] * 4
+                          (self.info['memory_static_max'] / 1024 / 1024) * 4
             overhead_kb = ((overhead_kb + 1023) / 1024) * 1024
             # The domain might already have some shadow memory
             overhead_kb -= xc.shadow_mem_control(self.domid) * 1024
@@ -1898,6 +1926,11 @@ class XendDomainInfo:
             info_key = XendConfig.LEGACY_CFG_TO_XENAPI_CFG.get(key, key)
             if self._infoIsSet(info_key):
                 to_store[key] = str(self.info[info_key])
+
+        if self._infoIsSet("static_memory_min"):
+            to_store["memory"] = str(self.info["static_memory_min"])
+        if self._infoIsSet("static_memory_max"):
+            to_store["maxmem"] = str(self.info["static_memory_max"])
 
         image_sxpr = self.info.image_sxpr()
         if image_sxpr:
@@ -1988,7 +2021,11 @@ class XendDomainInfo:
             info = dom_get(self.domid)
             if not info:
                 return
-            
+
+        if info["maxmem_kb"] < 0:
+            info["maxmem_kb"] = XendNode.instance() \
+                                .physinfo_dict()['total_memory'] * 1024
+
         #manually update ssidref / security fields
         if security.on() and info.has_key('ssidref'):
             if (info['ssidref'] != 0) and self.info.has_key('security'):
@@ -2249,8 +2286,6 @@ class XendDomainInfo:
         @return: uuid of the device
         """
         xenapi_vbd['image'] = vdi_image_path
-        log.debug('create_vbd: %s' % xenapi_vbd)
-        dev_uuid = ''
         if vdi_image_path.startswith('tap'):
             dev_uuid = self.info.device_add('tap', cfg_xenapi = xenapi_vbd)
         else:
@@ -2260,16 +2295,25 @@ class XendDomainInfo:
             raise XendError('Failed to create device')
 
         if self.state == XEN_API_VM_POWER_STATE_RUNNING:
+            
             _, config = self.info['devices'][dev_uuid]
-            dev_control = None
             
             if vdi_image_path.startswith('tap'):
-                dev_control =  self.getDeviceController('tap')
+                dev_control = self.getDeviceController('tap')
             else:
                 dev_control = self.getDeviceController('vbd')
-                
-            config['devid'] = dev_control.createDevice(config)
-
+
+            try:
+                devid = dev_control.createDevice(config)
+                dev_control.waitForDevice(devid)
+                self.info.device_update(dev_uuid,
+                                        cfg_xenapi = {'devid': devid})
+            except Exception, exn:
+                log.exception(exn)
+                del self.info['devices'][dev_uuid]
+                self.info['vbd_refs'].remove(dev_uuid)
+                raise
+            
         return dev_uuid
 
     def create_phantom_vbd_with_vdi(self, xenapi_vbd, vdi_image_path):
@@ -2303,9 +2347,21 @@ class XendDomainInfo:
             raise XendError('Failed to create device')
         
         if self.state == XEN_API_VM_POWER_STATE_RUNNING:
+
             _, config = self.info['devices'][dev_uuid]
-            config['devid'] = 
self.getDeviceController('vif').createDevice(config)
-
+            dev_control = self.getDeviceController('vif')
+
+            try:
+                devid = dev_control.createDevice(config)
+                dev_control.waitForDevice(devid)
+                self.info.device_update(dev_uuid,
+                                        cfg_xenapi = {'devid': devid})
+            except Exception, exn:
+                log.exception(exn)
+                del self.info['devices'][dev_uuid]
+                self.info['vif_refs'].remove(dev_uuid)
+                raise            
+ 
         return dev_uuid
 
     def create_vtpm(self, xenapi_vtpm):
@@ -2372,7 +2428,7 @@ class XendDomainInfo:
     def __str__(self):
         return '<domain id=%s name=%s memory=%s state=%s>' % \
                (str(self.domid), self.info['name_label'],
-                str(self.info['memory_static_min']), DOM_STATES[self.state])
+                str(self.info['memory_dynamic_max']), DOM_STATES[self.state])
 
     __repr__ = __str__
 
diff -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xend/XendLogging.py
--- a/tools/python/xen/xend/XendLogging.py      Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/python/xen/xend/XendLogging.py      Tue Mar 20 15:19:38 2007 -0600
@@ -58,6 +58,18 @@ if 'TRACE' not in logging.__dict__:
                 else:
                     return filename, frame[2]
     logging.Logger.findCaller = findCaller
+
+    # Work around a bug in Python's inspect module: findsource is supposed to
+    # raise IOError if it fails, with other functions in that module coping
+    # with that, but some people are seeing IndexError raised from there.
+    if hasattr(inspect, 'findsource'):
+        real_findsource = getattr(inspect, 'findsource')
+        def findsource(*args, **kwargs):
+            try:
+                return real_findsource(*args, **kwargs)
+            except IndexError, exn:
+                raise IOError(exn)
+        inspect.findsource = findsource
 
 
 log = logging.getLogger("xend")
diff -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xend/XendNode.py
--- a/tools/python/xen/xend/XendNode.py Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/python/xen/xend/XendNode.py Tue Mar 20 15:19:38 2007 -0600
@@ -530,7 +530,8 @@ class XendNode:
                            info['cores_per_socket'] *
                            info['threads_per_core'])
         info['cpu_mhz'] = info['cpu_khz'] / 1000
-        # physinfo is in KiB
+        
+        # physinfo is in KiB, need it in MiB
         info['total_memory'] = info['total_memory'] / 1024
         info['free_memory']  = info['free_memory'] / 1024
 
diff -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xend/XendVDI.py
--- a/tools/python/xen/xend/XendVDI.py  Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/python/xen/xend/XendVDI.py  Tue Mar 20 15:19:38 2007 -0600
@@ -54,7 +54,6 @@ class XendVDI(AutoSaveObject):
     
     SAVED_CFG = ['name_label',
                  'name_description',
-                 'sector_size',
                  'virtual_size',
                  'physical_utilisation',
                  'sharable',
@@ -67,13 +66,22 @@ class XendVDI(AutoSaveObject):
         self.sr_uuid = sr_uuid
         self.name_label = ""
         self.name_description = ""
-        self.sector_size = 1024
         self.virtual_size = 0
         self.physical_utilisation = 0
         self.sharable = False
         self.read_only = False
         self.type = "system"
-        self.location = ''
+        self.other_config = {}
+        self.vbds = []
+
+    def addVBD(self, vbd_ref):
+        self.vbds.append(vbd_ref)
+
+    def removeVBD(self, vbd_ref):
+        self.vbds.remove(vbd_ref)
+
+    def getVBDs(self):
+        return self.vbds
 
     def load_config_dict(self, cfg):
         """Loads configuration into the object from a dict.
@@ -144,11 +152,10 @@ class XendVDI(AutoSaveObject):
                 'name_description': self.name_description,
                 'virtual_size': self.virtual_size,
                 'physical_utilisation': self.physical_utilisation,
-                'sector_size': self.sector_size,
                 'sharable': False,
                 'readonly': False,
                 'SR': self.sr_uuid,
-                'location': self.get_location(),
+                'other_config': self.other_config,
                 'VBDs': []}
 
     def get_location(self):
@@ -163,12 +170,11 @@ class XendQCoWVDI(XendVDI):
         self.cfg_path = cfg_path
         self.physical_utilisation = psize
         self.virtual_size = vsize
-        self.sector_size = 512
         self.auto_save = True
-        self.location = 'tap:qcow:%s' % self.qcow_path
+        self.other_config['location'] = 'tap:qcow:%s' % self.qcow_path
 
     def get_location(self):
-        return self.location
+        return self.other_config['location']
 
 class XendLocalVDI(XendVDI):
     def __init__(self, vdi_struct):
@@ -182,11 +188,10 @@ class XendLocalVDI(XendVDI):
         self.name_description = vdi_struct.get('name_description', '')
         self.physical_utilisation = 0
         self.virtual_size = 0
-        self.sector_size = 0
         self.type = vdi_struct.get('type', '')
         self.sharable = vdi_struct.get('sharable', False)
         self.read_only = vdi_struct.get('read_only', False)
-        self.location = vdi_struct.get('location', 'file:/dev/null')
+        self.other_config = vdi_struct.get('other_config', {})
 
     def get_location(self):
-        return self.location
+        return self.other_config['location']
diff -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xm/create.dtd
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/python/xen/xm/create.dtd    Tue Mar 20 15:19:38 2007 -0600
@@ -0,0 +1,118 @@
+<!ENTITY % HTMLlat1 PUBLIC 
+   "-//W3C//ENTITIES Latin 1 for XHTML//EN" 
+   "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent";> 
+%HTMLlat1; 
+<!ENTITY % HTMLsymbol PUBLIC 
+   "-//W3C//ENTITIES Symbols for XHTML//EN" 
+   "http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent";> 
+%HTMLsymbol; 
+<!ENTITY % HTMLspecial PUBLIC 
+   "-//W3C//ENTITIES Special for XHTML//EN" 
+   "http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent";> 
+%HTMLspecial; 
+<!-- a Uniform Resource Identifier, see [RFC2396] --> 
+<!ENTITY % URI "CDATA"> 
+<!ENTITY % NAMEID "name ID #REQUIRED"> 
+<!ENTITY % CRASH_BEHAVIOUR "( destroy 
+                            | coredump_and_destroy
+                            | restart
+                            | coredump_and_restart
+                            | preserve
+                            | rename_restart )">
+<!ENTITY % NORMAL_EXIT     "( destroy | restart )">
+<!ENTITY % VDI_TYPE        "( system
+                            | user
+                            | ephemeral
+                            | suspend
+                            | crashdump )">
+
+<!ELEMENT xm (vm*, 
+              vdi*)> 
+
+<!ELEMENT version (#PCDATA)>
+ 
+<!ELEMENT vm    (name,
+                 version,
+                 (pv|hvm), 
+                 memory,
+                 vbd*,
+                 vif*,
+                 vcpu_param*,
+                 other_config*)> 
+<!ATTLIST vm     is_a_template          CDATA #REQUIRED
+                 auto_power_on          CDATA #REQUIRED
+                 vcpus_max              CDATA #REQUIRED
+                 vcpus_at_startup       CDATA #REQUIRED
+                 actions_after_shutdown %NORMAL_EXIT; #REQUIRED 
+                 actions_after_reboot   %NORMAL_EXIT; #REQUIRED
+                 actions_after_crash    %CRASH_BEHAVIOUR; #REQUIRED
+                 platform_std_VGA       CDATA #REQUIRED
+                 platform_serial        CDATA #REQUIRED
+                 platform_localtime     CDATA #REQUIRED 
+                 platform_clock_offet   CDATA #REQUIRED
+                 platform_enable_audio  CDATA #REQUIRED
+                 PCI_bus                CDATA #REQUIRED> 
+
+<!ELEMENT memory EMPTY> 
+<!ATTLIST memory static_min      CDATA #REQUIRED
+                 static_max      CDATA #REQUIRED
+                 dynamic_min     CDATA #REQUIRED 
+                 dynamic_max     CDATA #REQUIRED> 
+
+<!ELEMENT vbd    (qos_algorithm_param*)> 
+<!ATTLIST vbd    %NAMEID; 
+                 mode            (RO | RW)   #REQUIRED 
+                 vdi             IDREF       #REQUIRED
+                 device          CDATA       #REQUIRED
+                 bootable        CDATA       #REQUIRED
+                 type            (CD | disk) #REQUIRED
+                 qos_algorithm_type CDATA #REQUIRED> 
+
+<!ELEMENT vif    (qos_algorithm_param*)>
+<!ATTLIST vif    %NAMEID; 
+                 mac             CDATA       #REQUIRED 
+                 mtu             CDATA       #REQUIRED
+                 device          CDATA       #REQUIRED
+                 qos_algorithm_type CDATA    #REQUIRED
+                 bridge          CDATA       #IMPLIED
+                 network         CDATA       #IMPLIED> 
+
+<!ELEMENT pv     EMPTY>
+<!ATTLIST pv     kernel          CDATA #REQUIRED
+                 bootloader      CDATA #REQUIRED
+                 ramdisk         CDATA #REQUIRED
+                 args            CDATA #REQUIRED
+                 bootloader_args CDATA #REQUIRED>
+
+<!ELEMENT hvm    (boot_param*)>
+<!ATTLIST hvm    boot_policy     CDATA #REQUIRED>
+
+<!ELEMENT boot_param EMPTY>
+<!ATTLIST boot_param key         CDATA #REQUIRED
+                     value       CDATA #REQUIRED>
+
+<!ELEMENT vdi    (name)> 
+<!ATTLIST vdi    %NAMEID; 
+                 src             %URI; #REQUIRED
+                 type            %VDI_TYPE; #REQUIRED
+                 size            CDATA #REQUIRED
+                 shareable       CDATA #REQUIRED
+                 read_only       CDATA #REQUIRED>
+
+<!ELEMENT name   (label, 
+                  description)> 
+
+<!ELEMENT label  (#PCDATA)> 
+<!ELEMENT description (#PCDATA)>
+
+<!ELEMENT vcpu_param EMPTY>
+<!ATTLIST vcpu_param key   CDATA #REQUIRED
+                     value CDATA #REQUIRED>
+
+<!ELEMENT other_config EMPTY>
+<!ATTLIST other_config key   CDATA #REQUIRED
+                      value CDATA #REQUIRED>
+
+<!ELEMENT qos_algorithm_param EMPTY>
+<!ATTLIST qos_algorithm_param key   CDATA #REQUIRED
+                              value CDATA #REQUIRED>
diff -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py     Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/python/xen/xm/create.py     Tue Mar 20 15:19:38 2007 -0600
@@ -28,12 +28,13 @@ import xmlrpclib
 import xmlrpclib
 
 from xen.xend import sxp
-from xen.xend import PrettyPrint
+from xen.xend import PrettyPrint as SXPPrettyPrint
 from xen.xend import osdep
 import xen.xend.XendClient
 from xen.xend.XendBootloader import bootloader
 from xen.util import blkif
 from xen.util import security
+from xen.xm.main import serverType, SERVER_XEN_API, get_single_vm
 
 from xen.xm.opts import *
 
@@ -96,6 +97,11 @@ gopts.opt('dryrun', short='n',
 gopts.opt('dryrun', short='n',
           fn=set_true, default=0,
           use="Dry run - prints the resulting configuration in SXP but "
+          "does not create the domain.")
+
+gopts.opt('xmldryrun', short='x',
+          fn=set_true, default=0,
+          use="XML dry run - prints the resulting configuration in XML but "
           "does not create the domain.")
 
 gopts.opt('paused', short='p',
@@ -1241,34 +1247,59 @@ def main(argv):
         except IOError, exn:
             raise OptionError("Cannot read file %s: %s" % (config, exn[1]))
 
+    if serverType == SERVER_XEN_API:
+        from xen.xm.xenapi_create import sxp2xml
+        sxp2xml_inst = sxp2xml()
+        doc = sxp2xml_inst.convert_sxp_to_xml(config, transient=True)
+
     if opts.vals.dryrun:
-        PrettyPrint.prettyprint(config)
+        SXPPrettyPrint.prettyprint(config)
+
+    if opts.vals.xmldryrun and serverType == SERVER_XEN_API:
+        from xml.dom.ext import PrettyPrint as XMLPrettyPrint
+        XMLPrettyPrint(doc)
+
+    if opts.vals.dryrun or opts.vals.xmldryrun:
+        return                                               
+
+    if opts.vals.console_autoconnect:
+        do_console(sxp.child_value(config, 'name', -1))
+    
+    if serverType == SERVER_XEN_API:        
+        from xen.xm.xenapi_create import xenapi_create
+        xenapi_create_inst = xenapi_create()
+        vm_refs = xenapi_create_inst.create(document = doc)
+
+        map(lambda vm_ref: server.xenapi.VM.start(vm_ref, 0), vm_refs)
     else:
         if not create_security_check(config):
-            raise security.ACMError('Security Configuration prevents domain 
from starting')
-        else:
-            if opts.vals.console_autoconnect:
-                cpid = os.fork() 
-                if cpid != 0:
-                    for i in range(10):
-                        # Catch failure of the create process 
-                        time.sleep(1)
-                        (p, rv) = os.waitpid(cpid, os.WNOHANG)
-                        if os.WIFEXITED(rv):
-                            if os.WEXITSTATUS(rv) != 0:
-                                sys.exit(os.WEXITSTATUS(rv))
-                        try:
-                            # Acquire the console of the created dom
-                            name = sxp.child_value(config, 'name', -1)
-                            dom = server.xend.domain(name)
-                            domid = int(sxp.child_value(dom, 'domid', '-1'))
-                            console.execConsole(domid)
-                        except:
-                            pass
-                    print("Could not start console\n");
-                    sys.exit(0)
-            dom = make_domain(opts, config)
-
+            raise security.ACMError(
+                'Security Configuration prevents domain from starting')
+        dom = make_domain(opts, config)
+        
+def do_console(domain_name):
+    cpid = os.fork() 
+    if cpid != 0:
+        for i in range(10):
+            # Catch failure of the create process 
+            time.sleep(1)
+            (p, rv) = os.waitpid(cpid, os.WNOHANG)
+            if os.WIFEXITED(rv):
+                if os.WEXITSTATUS(rv) != 0:
+                    sys.exit(os.WEXITSTATUS(rv))
+            try:
+                # Acquire the console of the created dom
+                if serverType == SERVER_XEN_API:
+                    domid = server.xenapi.VM.get_domid(
+                               get_single_vm(domain_name))
+                else:
+                    dom = server.xend.domain(domain_name)
+                    domid = int(sxp.child_value(dom, 'domid', '-1'))
+                console.execConsole(domid)
+            except:
+                pass
+        print("Could not start console\n");
+        sys.exit(0)
 
 if __name__ == '__main__':
     main(sys.argv)
diff -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py       Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/python/xen/xm/main.py       Tue Mar 20 15:19:38 2007 -0600
@@ -33,11 +33,11 @@ import socket
 import socket
 import traceback
 import xmlrpclib
-import traceback
 import time
 import datetime
 from select import select
 import xml.dom.minidom
+from xen.util.blkif import blkdev_name_to_number
 
 import warnings
 warnings.filterwarnings('ignore', category=FutureWarning)
@@ -49,10 +49,10 @@ from xen.xend.XendConstants import *
 
 from xen.xm.opts import OptionError, Opts, wrap, set_true
 from xen.xm import console
-from xen.util import security
 from xen.util.xmlrpclib2 import ServerProxy
 
 import XenAPI
+
 
 # getopt.gnu_getopt is better, but only exists in Python 2.3+.  Use
 # getopt.getopt if gnu_getopt is not available.  This will mean that options
@@ -60,7 +60,8 @@ if not hasattr(getopt, 'gnu_getopt'):
 if not hasattr(getopt, 'gnu_getopt'):
     getopt.gnu_getopt = getopt.getopt
 
-XM_CONFIG_FILE = '/etc/xen/xm-config.xml'
+XM_CONFIG_FILE_ENVVAR = 'XM_CONFIG_FILE'
+XM_CONFIG_FILE_DEFAULT = '/etc/xen/xm-config.xml'
 
 # Supported types of server
 SERVER_LEGACY_XMLRPC = 'LegacyXMLRPC'
@@ -351,13 +352,14 @@ all_commands = (domain_commands + host_c
 # Configuration File Parsing
 ##
 
+xmConfigFile = os.getenv(XM_CONFIG_FILE_ENVVAR, XM_CONFIG_FILE_DEFAULT)
 config = None
-if os.path.isfile(XM_CONFIG_FILE):
+if os.path.isfile(xmConfigFile):
     try:
-        config = xml.dom.minidom.parse(XM_CONFIG_FILE)
+        config = xml.dom.minidom.parse(xmConfigFile)
     except:
         print >>sys.stderr, ('Ignoring invalid configuration file %s.' %
-                             XM_CONFIG_FILE)
+                             xmConfigFile)
 
 def parseServer():
     if config:
@@ -491,6 +493,18 @@ def usage(cmd = None):
 #
 ####################################################################
 
+def get_default_SR():
+    return [sr_ref
+            for sr_ref in server.xenapi.SR.get_all()
+            if server.xenapi.SR.get_type(sr_ref) == "local"][0]
+
+def get_default_Network():
+    return [network_ref
+            for network_ref in server.xenapi.network.get_all()][0]
+
+def map2sxp(m):
+    return [[k, m[k]] for k in m.keys()]
+
 def arg_check(args, name, lo, hi = -1):
     n = len([i for i in args if i != '--'])
     
@@ -673,10 +687,41 @@ def xm_restore(args):
 
 
 def getDomains(domain_names, state, full = 0):
-    if domain_names:
-        return [server.xend.domain(dom, full) for dom in domain_names]
-    else:
-        return server.xend.domains_with_state(True, state, full)
+    if serverType == SERVER_XEN_API:
+        doms_sxp = []
+        doms_dict = []
+        dom_refs = server.xenapi.VM.get_all()
+        for dom_ref in dom_refs:
+            dom_rec = server.xenapi.VM.get_record(dom_ref)
+            dom_metrics_ref = server.xenapi.VM.get_metrics(dom_ref)
+            dom_metrics = server.xenapi.VM_metrics.get_record(dom_metrics_ref)
+            dom_rec.update({'name':     dom_rec['name_label'],
+                            'memory_actual': 
int(dom_metrics['memory_actual'])/1024,
+                            'vcpus':    dom_metrics['vcpus_number'],
+                            'state':    '-----',
+                            'cpu_time': dom_metrics['vcpus_utilisation']})
+                       
+            doms_sxp.append(['domain'] + map2sxp(dom_rec))
+            doms_dict.append(dom_rec)
+            
+        if domain_names:
+            doms = [['domain'] + map2sxp(dom) for dom in doms_dict
+                    if dom["name"] in domain_names]
+            
+            if len(doms) > 0:
+                return doms
+            else:
+                print "Error: no domain%s named %s" % \
+                      (len(domain_names) > 1 and 's' or '',
+                       ', '.join(domain_names))
+                sys.exit(-1)
+        else:
+            return doms_sxp
+    else:
+        if domain_names:
+            return [server.xend.domain(dom, full) for dom in domain_names]
+        else:
+            return server.xend.domains_with_state(True, state, full)
 
 
 def xm_list(args):
@@ -735,19 +780,38 @@ def parse_doms_info(info):
     else:
         up_time = time.time() - start_time
 
-    return {
+    parsed_info = {
         'domid'    : get_info('domid',              str,   ''),
         'name'     : get_info('name',               str,   '??'),
-        'mem'      : get_info('memory_dynamic_min', int,   0),
         'state'    : get_info('state',              str,   ''),
-        'cpu_time' : get_info('cpu_time',           float, 0.0),
+
         # VCPUs is the number online when the VM is up, or the number
         # configured otherwise.
         'vcpus'    : get_info('online_vcpus', int,
                               get_info('vcpus', int, 0)),
-        'up_time'  : up_time,
-        'seclabel' : security.get_security_printlabel(info),
+        'up_time'  : up_time
         }
+
+    # We're not supporting security stuff just yet via XenAPI
+
+    if serverType != SERVER_XEN_API:
+        from xen.util import security
+        parsed_info['seclabel'] = security.get_security_printlabel(info)
+    else:
+        parsed_info['seclabel'] = ""
+
+    if serverType == SERVER_XEN_API:
+        parsed_info['mem'] = get_info('memory_actual', int, 0) / 1024
+        cpu_times = get_info('cpu_time', lambda x : (x), 0.0)
+        if sum(cpu_times.values()) > 0:
+            parsed_info['cpu_time'] = sum(cpu_times.values()) / 
float(len(cpu_times.values()))
+        else:
+            parsed_info['cpu_time'] = 0
+    else:
+        parsed_info['mem'] = get_info('memory', int,0)
+        parsed_info['cpu_time'] = get_info('cpu_time', float, 0.0)
+
+    return parsed_info
 
 def check_sched_type(sched):
     if serverType == SERVER_XEN_API:
@@ -797,17 +861,22 @@ def xm_label_list(doms):
     output = []
     format = '%(name)-32s %(domid)3s %(mem)5d %(vcpus)5d %(state)10s ' \
              '%(cpu_time)8.1f %(seclabel)9s'
-    
-    for dom in doms:
-        d = parse_doms_info(dom)
-        if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
-            if not d['seclabel']:
-                d['seclabel'] = 'ERROR'
-        elif security.active_policy in ['DEFAULT']:
-            d['seclabel'] = 'DEFAULT'
-        else:
-            d['seclabel'] = 'INACTIVE'
-        output.append((format % d, d['seclabel']))
+
+    if serverType != SERVER_XEN_API:
+        from xen.util import security
+        
+        for dom in doms:
+            d = parse_doms_info(dom)
+
+            if security.active_policy not in ['INACTIVE', 'NULL', 'DEFAULT']:
+                if not d['seclabel']:
+                    d['seclabel'] = 'ERROR'
+                elif security.active_policy in ['DEFAULT']:
+                    d['seclabel'] = 'DEFAULT'
+                else:
+                    d['seclabel'] = 'INACTIVE'
+
+            output.append((format % d, d['seclabel']))
         
     #sort by labels
     output.sort(lambda x,y: cmp( x[1].lower(), y[1].lower()))
@@ -816,7 +885,6 @@ def xm_label_list(doms):
 
 
 def xm_vcpu_list(args):
-
     if args:
         dominfo = map(server.xend.domain.getVCPUInfo, args)
     else:
@@ -1112,7 +1180,7 @@ def xm_mem_set(args):
     dom = args[0]
 
     if serverType == SERVER_XEN_API:
-        mem_target = int_unit(args[1], 'k') * 1024
+        mem_target = int_unit(args[1], 'm') * 1024 * 1024
         server.xenapi.VM.set_memory_dynamic_max(get_single_vm(dom), mem_target)
         server.xenapi.VM.set_memory_dynamic_min(get_single_vm(dom), mem_target)
     else:
@@ -1464,7 +1532,10 @@ def xm_sysrq(args):
     arg_check(args, "sysrq", 2)
     dom = args[0]
     req = args[1]
-    server.xend.domain.send_sysrq(dom, req)    
+    if serverType == SERVER_XEN_API:
+        server.xenapi.VM.send_sysrq(get_single_vm(dom), req)
+    else:
+        server.xend.domain.send_sysrq(dom, req)
 
 def xm_trigger(args):
     vcpu = 0
@@ -1474,12 +1545,23 @@ def xm_trigger(args):
     trigger = args[1]
     if len(args) == 3:
         vcpu = int(args[2])
-    
-    server.xend.domain.send_trigger(dom, trigger, vcpu)
+        
+    if serverType == SERVER_XEN_API:
+        server.xenapi.VM.send_trigger(get_single_vm(dom), trigger, vcpu)
+    else:
+        server.xend.domain.send_trigger(dom, trigger, vcpu)
 
 def xm_debug_keys(args):
     arg_check(args, "debug-keys", 1)
-    server.xend.node.send_debug_keys(str(args[0]))
+
+    keys = str(args[0])
+    
+    if serverType == SERVER_XEN_API:
+        server.xenapi.host.send_debug_keys(
+            server.xenapi.session.get_this_host(),
+            keys)
+    else:
+        server.xend.node.send_debug_keys(keys)
 
 def xm_top(args):
     arg_check(args, "top", 0)
@@ -1605,12 +1687,21 @@ def xm_network_list(args):
     (use_long, params) = arg_check_for_resource_list(args, "network-list")
 
     dom = params[0]
+
+    if serverType == SERVER_XEN_API:
+        vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
+        vif_properties = \
+            map(server.xenapi.VIF.get_runtime_properties, vif_refs)
+        devs = map(lambda (handle, properties): [handle, map2sxp(properties)],
+                   zip(range(len(vif_properties)), vif_properties))
+    else:
+        devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
+        
     if use_long:
-        devs = server.xend.domain.getDeviceSxprs(dom, 'vif')
         map(PrettyPrint.prettyprint, devs)
     else:
         hdr = 0
-        for x in server.xend.domain.getDeviceSxprs(dom, 'vif'):
+        for x in devs:
             if hdr == 0:
                 print 'Idx BE     MAC Addr.     handle state evt-ch 
tx-/rx-ring-ref BE-path'
                 hdr = 1
@@ -1630,12 +1721,25 @@ def xm_block_list(args):
     (use_long, params) = arg_check_for_resource_list(args, "block-list")
 
     dom = params[0]
+
+    if serverType == SERVER_XEN_API:
+        vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
+        vbd_properties = \
+            map(server.xenapi.VBD.get_runtime_properties, vbd_refs)
+        vbd_devs = \
+            map(server.xenapi.VBD.get_device, vbd_refs)
+        vbd_devids = \
+            map(blkdev_name_to_number, vbd_devs)
+        devs = map(lambda (devid, prop): [devid, map2sxp(prop)],
+                   zip(vbd_devids, vbd_properties))
+    else:
+        devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
+
     if use_long:
-        devs = server.xend.domain.getDeviceSxprs(dom, 'vbd')
         map(PrettyPrint.prettyprint, devs)
     else:
         hdr = 0
-        for x in server.xend.domain.getDeviceSxprs(dom, 'vbd'):
+        for x in devs:
             if hdr == 0:
                 print 'Vdev  BE handle state evt-ch ring-ref BE-path'
                 hdr = 1
@@ -1690,13 +1794,17 @@ def parse_block_configuration(args):
     if len(args) == 5:
         vbd.append(['backend', args[4]])
 
-    # verify that policy permits attaching this resource
-    if security.on():
-        dominfo = server.xend.domain(dom)
-        label = security.get_security_printlabel(dominfo)
-    else:
-        label = None
-    security.res_security_check(args[1], label)
+    if serverType != SERVER_XEN_API:
+        # verify that policy permits attaching this resource
+        from xen.util import security
+    
+        if security.on():
+            dominfo = server.xend.domain(dom)
+            label = security.get_security_printlabel(dominfo)
+        else:
+            label = None
+
+        security.res_security_check(args[1], label)
 
     return (dom, vbd)
 
@@ -1704,8 +1812,45 @@ def xm_block_attach(args):
 def xm_block_attach(args):
     arg_check(args, 'block-attach', 4, 5)
 
-    (dom, vbd) = parse_block_configuration(args)
-    server.xend.domain.device_create(dom, vbd)
+    if serverType == SERVER_XEN_API:
+        dom   = args[0]
+        uname = args[1]
+        dev   = args[2]
+        mode  = args[3]
+
+        # First create new VDI
+        vdi_record = {
+            "name_label":       "vdi" + str(uname.__hash__()),   
+            "name_description": "",
+            "SR":               get_default_SR(),
+            "virtual_size":     0,
+            "sector_size":      512,
+            "type":             "system",
+            "sharable":         False,
+            "read_only":        mode!="w",
+            "other_config":     {"location": uname}
+        }
+
+        vdi_ref = server.xenapi.VDI.create(vdi_record)
+
+        # Now create new VBD
+
+        vbd_record = {
+            "VM":               get_single_vm(dom),
+            "VDI":              vdi_ref,
+            "device":           dev,
+            "bootable":         True,
+            "mode":             mode=="w" and "RW" or "RO",
+            "type":             "Disk",
+            "qos_algorithm_type": "",
+            "qos_algorithm_params": {}
+        }
+
+        server.xenapi.VBD.create(vbd_record)
+        
+    else:
+        (dom, vbd) = parse_block_configuration(args)
+        server.xend.domain.device_create(dom, vbd)
 
 
 def xm_block_configure(args):
@@ -1723,15 +1868,65 @@ def xm_network_attach(args):
     vif_params = ['type', 'mac', 'bridge', 'ip', 'script', \
                   'backend', 'vifname', 'rate', 'model']
 
-    for a in args[1:]:
-        vif_param = a.split("=")
-        if len(vif_param) != 2 or vif_param[1] == '' or \
-           vif_param[0] not in vif_params:
-            err("Invalid argument: %s" % a)
-            usage('network-attach')
-        vif.append(vif_param)
-
-    server.xend.domain.device_create(dom, vif)
+    if serverType == SERVER_XEN_API:     
+        vif_record = {
+            "device":               "eth0",
+            "network":              get_default_Network(),
+            "VM":                   get_single_vm(dom),
+            "MAC":                  "",
+            "MTU":                  "",
+            "qos_algorithm_type":   "",
+            "qos_algorithm_params": {},
+            "other_config":         {}
+            }
+
+        def set(keys, val):
+            record = vif_record
+            for key in keys[:-1]:
+                record = record[key]
+            record[keys[-1]] = val 
+         
+        vif_conv = {
+            'type':
+                lambda x: None,
+            'mac':
+                lambda x: set(['MAC'], x),
+            'bridge':
+                lambda x: set(['network'], get_net_from_bridge(x)),
+            'ip':
+                lambda x: set(['other_config', 'ip'], x),
+            'script':
+                lambda x: set(['other_config', 'script'], x),
+            'backend':
+                lambda x: set(['other_config', 'backend'], x),
+            'vifname':
+                lambda x: set(['device'], x),
+            'rate':
+                lambda x: set(['qos_algorithm_params', 'rate'], x),
+            'model':
+                lambda x: None
+            }
+            
+        for a in args[1:]:
+            vif_param = a.split("=")
+            if len(vif_param) != 2 or vif_param[1] == '' or \
+                   vif_param[0] not in vif_params:
+                err("Invalid argument: %s" % a)
+                usage('network-attach')   
+            else:
+                vif_conv[vif_param[0]](vif_param[1])
+
+        print str(vif_record)
+        server.xenapi.VIF.create(vif_record)
+    else:
+        for a in args[1:]:
+            vif_param = a.split("=")
+            if len(vif_param) != 2 or vif_param[1] == '' or \
+                   vif_param[0] not in vif_params:
+                err("Invalid argument: %s" % a)
+                usage('network-attach')
+            vif.append(vif_param)
+        server.xend.domain.device_create(dom, vif)
 
 
 def detach(args, command, deviceClass):
@@ -1751,16 +1946,49 @@ def detach(args, command, deviceClass):
 
 
 def xm_block_detach(args):
-    try:
-        detach(args, 'block-detach', 'vbd')
-        return
-    except:
-        pass
-    detach(args, 'block-detach', 'tap')
-
+    if serverType == SERVER_XEN_API:
+        arg_check(args, "xm_block_detach", 2, 3)
+        dom = args[0]
+        dev = args[1]
+        vbd_refs = server.xenapi.VM.get_VBDs(get_single_vm(dom))
+        vbd_refs = [vbd_ref for vbd_ref in vbd_refs
+                    if server.xenapi.VBD.get_device(vbd_ref) == dev]
+        if len(vbd_refs) > 0:
+            vbd_ref = vbd_refs[0]
+            vdi_ref = server.xenapi.VBD.get_VDI(vbd_ref)
+
+            server.xenapi.VBD.destroy(vbd_ref)
+
+            if len(server.xenapi.VDI.get_VBDs(vdi_ref)) <= 0:
+                server.xenapi.VDI.destroy(vdi_ref)
+        else:
+            raise OptionError("Cannot find device '%s' in domain '%s'"
+                              % (dev,dom))
+    else:
+        try:
+            detach(args, 'block-detach', 'vbd')
+            return
+        except:
+            pass
+        detach(args, 'block-detach', 'tap')
 
 def xm_network_detach(args):
-    detach(args, 'network-detach', 'vif')
+    if serverType == SERVER_XEN_API:
+        arg_check(args, "xm_block_detach", 2, 3)
+        dom = args[0]
+        devid = args[1]
+        vif_refs = server.xenapi.VM.get_VIFs(get_single_vm(dom))
+        vif_refs = [vif_ref for vif_ref in vif_refs
+                    if server.xenapi.VIF.\
+                    get_runtime_properties(vif_ref)["handle"] == devid]
+        if len(vif_refs) > 0:
+            vif_ref = vif_refs[0]
+            
+            server.xenapi.VIF.destroy(vif_ref)
+        else:
+            print "Cannot find device '%s' in domain '%s'" % (devid,dom)
+    else:
+        detach(args, 'network-detach', 'vif')
 
 
 def xm_vnet_list(args):
@@ -2001,13 +2229,17 @@ def _run_cmd(cmd, cmd_name, args):
         err(str(e))
         _usage(cmd_name)
         print e.usage
-    except security.ACMError, e:
-        err(str(e))
-    except:
-        print "Unexpected error:", sys.exc_info()[0]
-        print
-        print "Please report to xen-devel@xxxxxxxxxxxxxxxxxxx"
-        raise
+    except Exception, e:
+        if serverType != SERVER_XEN_API:
+           from xen.util import security
+           if isinstance(e, security.ACMError):
+               err(str(e))
+               return False, 1
+        else:
+            print "Unexpected error:", sys.exc_info()[0]
+            print
+            print "Please report to xen-devel@xxxxxxxxxxxxxxxxxxx"
+            raise
 
     return False, 1
 
diff -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xm/new.py
--- a/tools/python/xen/xm/new.py        Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/python/xen/xm/new.py        Tue Mar 20 15:19:38 2007 -0600
@@ -21,6 +21,9 @@ from xen.xend import PrettyPrint
 from xen.xend import PrettyPrint
 from xen.xend import sxp
 from xen.xend import XendClient
+
+from xen.xm.main import serverType, SERVER_XEN_API
+from xen.xm.xenapi_create import *
 
 from opts import *
 from create import *
@@ -65,7 +68,15 @@ def main(argv):
 
     if opts.vals.dryrun:
         PrettyPrint.prettyprint(config)
-    else:
+        return
+    
+    if serverType == SERVER_XEN_API:
+        sxp2xml_inst = sxp2xml()
+        doc = sxp2xml_inst.convert_sxp_to_xml(config) 
+        
+        xenapi_create_inst = xenapi_create()
+        vm_refs = xenapi_create_inst.create(document = doc)
+    else:       
         make_unstarted_domain(opts, config)
         
 if __name__ == '__main__':
diff -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xm/shutdown.py
--- a/tools/python/xen/xm/shutdown.py   Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/python/xen/xm/shutdown.py   Tue Mar 20 15:19:38 2007 -0600
@@ -51,7 +51,7 @@ gopts.opt('reboot', short='R',
 
 def wait_reboot(opts, doms, rcs):
     if serverType == SERVER_XEN_API:
-           opts.err("Cannot wait for reboot w/ XenAPI (yet)")
+        opts.err("Cannot wait for reboot w/ XenAPI (yet)")
 
     while doms:
         alive = server.xend.domains(0)
@@ -73,7 +73,7 @@ def wait_shutdown(opts, doms):
 def wait_shutdown(opts, doms):
     while doms:
         if serverType == SERVER_XEN_API:
-                   alive = [dom for dom in server.xenapi.VM.get_all()
+            alive = [dom for dom in server.xenapi.VM.get_all()
                      if server.xenapi.VM.get_power_state(dom) ==
                      XEN_API_VM_POWER_STATE[XEN_API_VM_POWER_STATE_RUNNING]]
         else:
@@ -91,16 +91,16 @@ def shutdown(opts, doms, mode, wait):
 def shutdown(opts, doms, mode, wait):
     rcs = {}
     for d in doms:
-               if serverType == SERVER_XEN_API:
-                       if mode == 'halt':
-                               server.xenapi.VM.clean_shutdown(d)
-                       if mode == 'reboot':
-                               server.xenapi.VM.clean_reboot(d)
-                       if mode == 'poweroff':
-                               server.xenapi.VM.clean_shutdown(d)              
                
-               else:
-                       rcs[d] = server.xend.domain.getRestartCount(d)
-                       server.xend.domain.shutdown(d, mode)
+        if serverType == SERVER_XEN_API:
+            if mode == 'halt':
+                server.xenapi.VM.clean_shutdown(d)
+            if mode == 'reboot':
+                server.xenapi.VM.clean_reboot(d)
+            if mode == 'poweroff':
+                server.xenapi.VM.clean_shutdown(d)
+        else:
+            rcs[d] = server.xend.domain.getRestartCount(d)
+            server.xend.domain.shutdown(d, mode)
 
     if wait:
         if mode == 'reboot':
@@ -135,7 +135,7 @@ def main_dom(opts, args):
     if len(args) >  1: opts.err('No multiple domain parameters allowed')
     dom = args[0]
     if serverType == SERVER_XEN_API:
-               dom = get_single_vm(dom)
+        dom = get_single_vm(dom)
     mode = shutdown_mode(opts)  
     shutdown(opts, [ dom ], mode, opts.vals.wait)
     
diff -r f74e837c3902 -r 2216a45bf058 tools/python/xen/xm/xenapi_create.py
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/python/xen/xm/xenapi_create.py      Tue Mar 20 15:19:38 2007 -0600
@@ -0,0 +1,636 @@
+#!/usr/bin/python
+#============================================================================
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#============================================================================
+# Copyright (C) 2007 Tom Wilkie <tom.wilkie@xxxxxxxxx>
+#============================================================================
+"""Domain creation using new XenAPI
+"""
+
+from xen.xm.main import server, get_default_SR
+from xml.dom.minidom import parse, getDOMImplementation
+from xml.dom.ext import PrettyPrint
+from xml.parsers.xmlproc import xmlproc, xmlval, xmldtd
+from xen.xend import sxp
+from xen.xend.XendAPIConstants import XEN_API_ON_NORMAL_EXIT, \
+     XEN_API_ON_CRASH_BEHAVIOUR
+
+
+import sys
+import os
+import traceback
+
+def log(_, msg):
+    #print "> " + msg
+    pass
+
+DEBUG = 0
+
+def get_name_label(node):
+    name_node = node.getElementsByTagName("name")[0]
+    label_node = name_node.getElementsByTagName("label")[0]
+    return " ".join([child.nodeValue for child in label_node.childNodes])
+
+def get_name_description(node):
+    name_node = node.getElementsByTagName("name")[0]
+    description_node = name_node.getElementsByTagName("description")[0]
+    return " ".join([child.nodeValue for child in description_node.childNodes])
+
+def get_text_in_child_node(node, child):
+    tag_node = node.getElementsByTagName(child)[0]
+    return tag_node.nodeValue
+
+def get_child_node_attribute(node, child, attribute):
+    tag_node = node.getElementsByTagName(child)[0]
+    return tag_node.attributes[attribute].value
+
+def get_child_nodes_as_dict(node, child_name,
+                            key_attribute_name,
+                            value_attribute_name):
+    return dict([(child.attributes[key_attribute_name].value,
+                  child.attributes[value_attribute_name].value)
+                 for child in node.getElementsByTagName(child_name)])
+
+def try_quietly(fn, *args):
+    try:
+        return fn(*args)
+    except:
+        return None
+
+class xenapi_create:
+
+    def __init__(self):
+        self.DEFAULT_STORAGE_REPOSITORY = get_default_SR()
+
+        self.dtd = "/usr/lib/python/xen/xm/create.dtd"
+
+    def create(self, filename=None, document=None):
+        """
+        Create a domain from an XML file or DOM tree
+        """
+        if filename is not None:
+            self.check_dtd(file)
+            document = parse(file)
+        elif document is not None:
+            self.check_dom_against_dtd(document)
+
+        self.check_doc(document)
+
+        vdis = document.getElementsByTagName("vdi")
+        vdi_refs_dict = self.create_vdis(vdis)
+        
+        try:    
+            vms = document.getElementsByTagName("vm")
+            return self.create_vms(vms, vdi_refs_dict)
+        except Exception, exn:
+            try_quietly(self.cleanup_vdis(vdi_refs_dict))
+            raise exn
+
+    # Methods to check xml file
+    # try to use dtd to check where possible
+    def check_dtd(self, file):
+        """
+        Check file against DTD.
+        Use this if possible as it gives nice
+        error messages
+        """
+        dtd = xmldtd.load_dtd(self.dtd)
+        parser = xmlproc.XMLProcessor()
+        parser.set_application(xmlval.ValidatingApp(dtd, parser))
+        parser.dtd = dtd
+        parser.ent = dtd
+        parser.parse_resource(file)
+
+    def check_dom_against_dtd(self, dom):
+        """
+        Check DOM again DTD.
+        Doesn't give as nice error messages.
+        (no location info)
+        """
+        dtd = xmldtd.load_dtd(self.dtd)
+        app = xmlval.ValidatingApp(dtd, self)
+        app.set_locator(self)
+        self.dom2sax(dom, app)
+
+    # Get errors back from ValidatingApp       
+    def report_error(self, number, args=None):
+        self.errors = xmlproc.errors.english
+        try:
+            msg = self.errors[number]
+            if args != None:
+                msg = msg % args
+        except KeyError:
+            msg = self.errors[4002] % number # Unknown err msg :-)
+        print msg 
+        sys.exit(-1)
+
+    # Here for compatibility with ValidatingApp
+    def get_line(self):
+        return -1
+
+    def get_column(self):
+        return -1
+
+    def dom2sax(self, dom, app):
+        """
+        Take a dom tree and tarverse it,
+        issuing SAX calls to app.
+        """
+        for child in dom.childNodes:
+            if child.nodeType == child.TEXT_NODE:
+                data = child.nodeValue
+                app.handle_data(data, 0, len(data))
+            else:
+                app.handle_start_tag(
+                    child.nodeName,
+                    self.attrs_to_dict(child.attributes))
+                self.dom2sax(child, app)
+                app.handle_end_tag(child.nodeName)
+
+    def attrs_to_dict(self, attrs):
+        return dict(attrs.items())     
+
+    #
+    # Checks which cannot be done with dtd
+    #
+    def check_doc(self, doc):
+        vms = doc.getElementsByTagName("vm")
+        self.check_vms(vms)
+
+    def check_vms(self, vms):
+        map(self.check_vm, vms)
+
+    def check_vm(self, vm):
+        vifs = vm.getElementsByTagName("vif")
+        self.check_vifs(vifs)
+
+    def check_vifs(self, vifs):
+        map(self.check_vif, vifs)
+
+    def check_vif(self, vif):
+        """
+        Check that the vif has
+        either a bridge or network
+        name but not both
+        """
+        if "bridge" in vif.attributes.keys() \
+               and "network" in vif.attributes.keys():
+            raise "You cannot specify both a bridge and\
+                   a network name."
+
+    # Cleanup methods here
+    def cleanup_vdis(self, vdi_refs_dict):
+        map(self.cleanup_vdi, vdi_refs_dict.values())
+
+    def cleanup_vdi(self, vdi_ref):
+        server.xenapi.VDI.destroy(vdi_ref)
+
+    def cleanup_vms(self, vm_refs):
+        map(self.cleanup_vm, vm_refs)
+
+    def cleanup_vm(self, vm_ref):
+        server.xenapi.VM.destroy(vm_ref)
+
+    # Create methods here
+    def create_vdis(self, vdis):
+        log(DEBUG, "create_vdis")
+        return dict(map(self.create_vdi, vdis))
+
+    def create_vdi(self, vdi):
+        log(DEBUG, "create_vdi")
+
+        vdi_record = {
+            "name_label":       get_name_label(vdi),
+            "name_description": get_name_description(vdi),
+            "SR":               self.DEFAULT_STORAGE_REPOSITORY,  
+            "virtual_size":     vdi.attributes["size"].value,
+            "type":             vdi.attributes["type"].value,
+            "shareable":        vdi.attributes["shareable"].value,
+            "read_only":        vdi.attributes["read_only"].value,
+            "other_config":     {"location":
+                vdi.attributes["src"].value}
+            }
+
+        key = vdi.attributes["name"].value
+        value = server.xenapi.VDI.create(vdi_record)
+        
+        return (key, value)
+
+    def create_vms(self, vms, vdis):
+        log(DEBUG, "create_vms")
+        return map(lambda vm: self.create_vm(vm, vdis), vms)
+
+    def create_vm(self, vm, vdis):
+        log(DEBUG, "create_vm")
+
+        vm_record = {
+            "name_label":
+                get_name_label(vm),
+            "name_description":
+                get_name_description(vm),
+            "user_version":
+                get_text_in_child_node(vm, "version"),
+            "is_a_template":
+                vm.attributes["is_a_template"].value,
+            "auto_power_on":
+                vm.attributes["auto_power_on"].value,
+            "memory_static_max":
+                get_child_node_attribute(vm, "memory", "static_max"),
+            "memory_static_min":
+                get_child_node_attribute(vm, "memory", "static_min"),
+            "memory_dynamic_max":
+                get_child_node_attribute(vm, "memory", "dynamic_max"),
+            "memory_dynamic_min":
+                get_child_node_attribute(vm, "memory", "dynamic_min"),
+            "vcpus_params":
+                get_child_nodes_as_dict(vm, "vcpu_param", "key", "value"),
+            "vcpus_max":
+                vm.attributes["vcpus_max"].value,
+            "vcpus_at_startup":
+                vm.attributes["vcpus_at_startup"].value,
+            "actions_after_shutdown":
+                vm.attributes["actions_after_shutdown"].value,
+            "actions_after_reboot":
+                vm.attributes["actions_after_reboot"].value,
+            "actions_after_crash":
+                vm.attributes["actions_after_crash"].value,
+            "platform_std_VGA":
+                vm.attributes["platform_std_VGA"].value,
+            "platform_serial":
+                vm.attributes["platform_serial"].value,
+            "platform_localtime":
+                vm.attributes["platform_localtime"].value,
+            "platform_clock_offet":
+                vm.attributes["platform_clock_offet"].value,
+            "platform_enable_audio":
+                vm.attributes["platform_enable_audio"].value,
+            "PCI_bus":
+                vm.attributes["platform_enable_audio"].value,
+            "other_config":
+                get_child_nodes_as_dict(vm, "other_config", "key", "value")
+            }
+
+        if len(vm.getElementsByTagName("pv")) > 0:
+            vm_record.update({
+                "PV_bootloader":
+                    get_child_node_attribute(vm, "pv", "bootloader"),
+                "PV_kernel":
+                    get_child_node_attribute(vm, "pv", "kernel"),
+                "PV_ramdisk":
+                    get_child_node_attribute(vm, "pv", "ramdisk"),
+                "PV_args":
+                    get_child_node_attribute(vm, "pv", "args"),
+                "PV_bootloader_args":
+                    get_child_node_attribute(vm, "pv", "bootloader_args")
+                })
+        else:
+            hvm = vm.getElementsByTagName("hvm")[0]
+            vm_record.update({
+                "HVM_boot_policy":
+                    get_child_node_attribute(vm, "hvm", "boot_policy"),
+                "HVM_boot_params":
+                    get_child_nodes_as_dict(hvm, "boot_params", "key", "value")
+                })
+        try:
+            vm_ref = server.xenapi.VM.create(vm_record)
+        except:
+            traceback.print_exc()
+            sys.exit(-1)
+
+        # Now create vbds
+
+        vbds = vm.getElementsByTagName("vbd")
+
+        self.create_vbds(vm_ref, vbds, vdis)
+
+        # Now create vifs
+
+        vifs = vm.getElementsByTagName("vif")
+
+        self.create_vifs(vm_ref, vifs)
+
+        return vm_ref
+        
+    def create_vbds(self, vm_ref, vbds, vdis):
+        log(DEBUG, "create_vbds")
+        return map(lambda vbd: self.create_vbd(vm_ref, vbd, vdis), vbds)
+
+    def create_vbd(self, vm_ref, vbd, vdis):
+        log(DEBUG, "create_vbd")
+
+        vbd_record = {
+            "VM":
+                vm_ref,
+            "VDI":
+                vdis[vbd.attributes["vdi"].value],
+            "device":
+                vbd.attributes["device"].value,
+            "bootable":
+                vbd.attributes["bootable"].value,
+            "mode":
+                vbd.attributes["mode"].value,
+            "type":
+                vbd.attributes["type"].value,
+            "qos_algorithm_type":
+                vbd.attributes["qos_algorithm_type"].value,
+            "qos_algorithm_params":
+                get_child_nodes_as_dict(vbd,
+                  "qos_algorithm_param", "key", "value")
+            }
+
+        return server.xenapi.VBD.create(vbd_record)
+
+    def create_vifs(self, vm_ref, vifs):
+        log(DEBUG, "create_vifs")
+        return map(lambda vif: self.create_vif(vm_ref, vif), vifs)
+
+    def create_vif(self, vm_ref, vif):
+        log(DEBUG, "create_vif")
+
+        if "bridge" in vif.attributes.keys():
+            raise "Not allowed to add by bridge just yet"
+        elif "network" in vif.attributes.keys():
+            network = [network_ref
+                for network_ref in server.xenapi.network.get_all()
+                if server.xenapi.network.get_name_label(network_ref)
+                       == vif.attributes["network"].value][0]
+        else:
+            network = self._get_network_ref()
+
+        vif_record = {
+            "device":
+                vif.attributes["device"].value,
+            "network":
+                network,
+            "VM":
+                vm_ref,
+            "MAC":
+                vif.attributes["mac"].value,
+            "MTU":
+                vif.attributes["mtu"].value,
+            "qos_algorithm_type":
+                vif.attributes["qos_algorithm_type"].value,
+            "qos_algorithm_params":
+                get_child_nodes_as_dict(vif,
+                    "qos_algorithm_param", "key", "value")
+        }
+
+        return server.xenapi.VIF.create(vif_record)
+
+    _network_refs = []
+
+    def _get_network_ref(self):
+        try:
+            return self._network_refs.pop(0)
+        except IndexError:
+            self._network_refs = server.xenapi.network.get_all()
+            return self._network_refs.pop(0)
+
+def get_child_by_name(exp, childname, default = None):
+    try:
+        return [child for child in sxp.children(exp)
+                if child[0] == childname][0][1]
+    except:
+        return default
+
+# Convert old sxp into new xml
+
+class sxp2xml:
+
+    def convert_sxp_to_xml(self, config, transient=False):
+       
+        devices = [child for child in sxp.children(config)
+                   if len(child) > 0 and child[0] == "device"]
+                   
+        vbds_sxp = map(lambda x: x[1], [device for device in devices
+                                        if device[1][0] == "vbd"])
+
+        vifs_sxp = map(lambda x: x[1], [device for device in devices
+                                        if device[1][0] == "vif"])
+        # Create XML Document
+        
+        impl = getDOMImplementation()
+
+        document = impl.createDocument(None, "xm", None)
+
+        # Lets make the VM tag..
+
+        vm = document.createElement("vm")
+
+        # Some string compatibility
+
+        actions_after_shutdown \
+            = get_child_by_name(config, "on_poweroff", "destroy")
+        actions_after_reboot \
+            = get_child_by_name(config, "on_reboot", "restart")
+        actions_after_crash \
+            = get_child_by_name(config, "on_crash", "restart")
+
+        def conv_chk(val, vals):
+            val.replace("-", "_")
+            if val not in vals:
+                raise "Invalid value: " + val
+            else:
+                return val
+
+        actions_after_shutdown = conv_chk(actions_after_shutdown,\
+                                          XEN_API_ON_NORMAL_EXIT)
+        actions_after_reboot   = conv_chk(actions_after_reboot, \
+                                          XEN_API_ON_NORMAL_EXIT)
+        actions_after_crash    = conv_chk(actions_after_crash, \
+                                          XEN_API_ON_CRASH_BEHAVIOUR)
+        # Flesh out tag attributes            
+
+        vm.attributes["is_a_template"] = "false"
+        vm.attributes["auto_power_on"] = "false"
+        vm.attributes["actions_after_shutdown"] \
+            = actions_after_shutdown              
+        vm.attributes["actions_after_reboot"] \
+            = actions_after_reboot
+        vm.attributes["actions_after_crash"] \
+            = actions_after_crash
+        vm.attributes["platform_std_VGA"] = "false"
+        vm.attributes["platform_serial"] = ""
+        vm.attributes["platform_localtime"] = ""
+        vm.attributes["platform_clock_offet"] = ""
+        vm.attributes["platform_enable_audio"] = ""
+        vm.attributes["PCI_bus"] = ""
+
+        vm.attributes["vcpus_max"] \
+            = str(get_child_by_name(config, "vcpus", 1))
+        vm.attributes["vcpus_at_startup"] \
+            = str(get_child_by_name(config, "vcpus", 1))
+
+        # Make the name tag
+
+        vm.appendChild(self.make_name_tag(
+            get_child_by_name(config, "name"), document))
+
+        # Make version tag
+
+        version = document.createElement("version")
+        version.appendChild(document.createTextNode("1.0"))
+        vm.appendChild(version)
+        
+        # Make pv or hvm tag
+
+        image = get_child_by_name(config, "image")
+
+        if image[0] == "linux":
+            pv = document.createElement("pv")
+            pv.attributes["kernel"] \
+                = get_child_by_name(image, "kernel", "")
+            pv.attributes["bootloader"] = ""
+            pv.attributes["ramdisk"] \
+                = get_child_by_name(image, "ramdisk", "")
+            pv.attributes["args"] \
+                = "root=" + get_child_by_name(image, "root", "") \
+                + " " + get_child_by_name(image, "args", "")
+            pv.attributes["bootloader_args"] = ""
+
+            vm.appendChild(pv)
+        elif image[0] == "hvm":
+            hvm = document.createElement("hvm")
+            hvm.attributes["boot_policy"] = ""
+
+            vm.appendChild(hvm)
+
+        # Make memory tag
+
+        memory = document.createElement("memory")
+
+        memory_str = str(int(
+            get_child_by_name(config, "memory"))*1024*1024)
+
+        memory.attributes["static_min"] = str(0)
+        memory.attributes["static_max"] = memory_str
+        memory.attributes["dynamic_min"] = memory_str
+        memory.attributes["dynamic_max"] = memory_str
+
+        if get_child_by_name(config, "maxmem"):
+            memory.attributes["static_max"] = \
+               str(int(get_child_by_name(config, "maxmem")*1024*1024))
+
+        vm.appendChild(memory)
+
+        # And now the vbds
+
+        vbds = map(lambda vbd: self.extract_vbd(vbd, document), vbds_sxp)
+
+        map(vm.appendChild, vbds)
+
+        # And now the vifs
+
+        vifs = map(lambda vif: self.extract_vif(vif, document), vifs_sxp)
+
+        map(vm.appendChild, vifs)
+
+        # transient?
+
+        if transient:
+            other_config = document.createElement("other_config")
+            other_config.attributes["key"] = "transient"
+            other_config.attributes["value"] = "True"
+            vm.appendChild(other_config)
+        
+        # Add it to doc_root
+
+        document.documentElement.appendChild(vm)
+        
+        # We want to pull out vdis
+
+        vdis = map(lambda vdb: self.extract_vdi(vdb, document), vbds_sxp)
+
+        map(document.documentElement.appendChild, vdis)
+
+        return document
+
+    def make_name_tag(self, label_text, document):
+        name = document.createElement("name")
+
+        label = document.createElement("label")
+        label.appendChild(document.createTextNode(str(label_text)))
+        name.appendChild(label)
+
+        description = document.createElement("description")
+        description.appendChild(document.createTextNode(" "))
+        name.appendChild(description)
+
+        return name
+
+    def extract_vbd(self, vbd_sxp, document):
+        src = get_child_by_name(vbd_sxp, "uname")
+        name = str(src.__hash__())
+
+        vbd = document.createElement("vbd")
+
+        vbd.attributes["name"] = "vdb" + name
+        vbd.attributes["vdi"] = "vdi" + name
+        vbd.attributes["mode"] \
+            = get_child_by_name(vbd_sxp, "mode") != "w" \
+              and "RO" or "RW"
+        vbd.attributes["device"] \
+            = get_child_by_name(vbd_sxp, "dev")
+        vbd.attributes["bootable"] = "1"
+        vbd.attributes["type"] = "disk"
+        vbd.attributes["qos_algorithm_type"] = ""
+
+        return vbd
+
+    def extract_vdi(self, vbd_sxp, document):
+        src = get_child_by_name(vbd_sxp, "uname")
+        name = "vdi" + str(src.__hash__())
+        path = src[src.find(":")+1:]
+
+        vdi = document.createElement("vdi")
+
+        vdi.attributes["src"] = src
+        vdi.attributes["read_only"] \
+            = (get_child_by_name(vbd_sxp, "mode") != "w") \
+               and "true" or "false"
+        vdi.attributes["size"] \
+            = str(os.path.getsize(path))
+        vdi.attributes["type"] = "system"
+        vdi.attributes["shareable"] = "false"
+        vdi.attributes["name"] = name
+
+        vdi.appendChild(self.make_name_tag(name, document))
+
+        return vdi
+
+    def extract_vif(self, vif_sxp, document):
+
+        vif = document.createElement("vif")
+
+        dev = get_child_by_name(vif_sxp, "vifname", "eth0")
+
+        vif.attributes["name"] \
+            = "vif" + str(dev.__hash__())
+        vif.attributes["mac"] \
+            = get_child_by_name(vif_sxp, "mac", "")               
+        vif.attributes["mtu"] \
+            = get_child_by_name(vif_sxp, "mtu", "")  
+        vif.attributes["device"] = dev
+        vif.attributes["qos_algorithm_type"] = ""
+
+        if get_child_by_name(vif_sxp, "bridge") is not None:
+            vif.attributes["bridge"] \
+                = get_child_by_name(vif_sxp, "bridge")
+        
+        return vif
+
+
+
+
+
diff -r f74e837c3902 -r 2216a45bf058 tools/xcutils/Makefile
--- a/tools/xcutils/Makefile    Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/xcutils/Makefile    Tue Mar 20 15:19:38 2007 -0600
@@ -13,7 +13,7 @@ include $(XEN_ROOT)/tools/Rules.mk
 
 PROGRAMS_INSTALL_DIR = /usr/$(LIBDIR)/xen/bin
 
-INCLUDES += -I $(XEN_LIBXC)
+INCLUDES += -I $(XEN_LIBXC) -I $(XEN_XENSTORE)
 
 CFLAGS += -Werror -fno-strict-aliasing
 CFLAGS += $(INCLUDES)
@@ -22,9 +22,9 @@ CFLAGS += -Wp,-MD,.$(@F).d
 CFLAGS += -Wp,-MD,.$(@F).d
 PROG_DEP = .*.d
 
-PROGRAMS               = xc_restore xc_save readnotes
+PROGRAMS = xc_restore xc_save readnotes
 
-LDLIBS                 = -L$(XEN_LIBXC) -lxenguest -lxenctrl
+LDLIBS   = -L$(XEN_LIBXC) -L$(XEN_XENSTORE) -lxenguest -lxenctrl -lxenstore
 
 .PHONY: all
 all: build
diff -r f74e837c3902 -r 2216a45bf058 tools/xcutils/xc_save.c
--- a/tools/xcutils/xc_save.c   Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/xcutils/xc_save.c   Tue Mar 20 15:19:38 2007 -0600
@@ -12,7 +12,13 @@
 #include <stdint.h>
 #include <string.h>
 #include <stdio.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 
+#include <xs.h>
 #include <xenctrl.h>
 #include <xenguest.h>
 
@@ -29,6 +35,123 @@ static int suspend(int domid)
 
     return (fgets(ans, sizeof(ans), stdin) != NULL &&
             !strncmp(ans, "done\n", 5));
+}
+
+/* For HVM guests, there are two sources of dirty pages: the Xen shadow
+ * log-dirty bitmap, which we get with a hypercall, and qemu's version.
+ * The protocol for getting page-dirtying data from qemu uses a
+ * double-buffered shared memory interface directly between xc_save and
+ * qemu-dm. 
+ *
+ * xc_save calculates the size of the bitmaps and notifies qemu-dm 
+ * through the store that it wants to share the bitmaps.  qemu-dm then 
+ * starts filling in the 'active' buffer. 
+ *
+ * To change the buffers over, xc_save writes the other buffer number to
+ * the store and waits for qemu to acknowledge that it is now writing to
+ * the new active buffer.  xc_save can then process and clear the old
+ * active buffer. */
+
+static char *qemu_active_path;
+static char *qemu_next_active_path;
+static struct xs_handle *xs;
+
+/* Get qemu to change buffers. */
+static void qemu_flip_buffer(int domid, int next_active)
+{
+    char digit = '0' + next_active;
+    unsigned int len;
+    char *active_str, **watch;
+    struct timeval tv;
+    fd_set fdset;
+
+    /* Tell qemu that we want it to start writing log-dirty bits to the
+     * other buffer */
+    if (!xs_write(xs, XBT_NULL, qemu_next_active_path, &digit, 1)) {
+        errx(1, "can't write next-active to store path (%s)\n", 
+              qemu_next_active_path);
+        exit(1);
+    }
+
+    /* Wait a while for qemu to signal that it has switched to the new 
+     * active buffer */
+ read_again: 
+    tv.tv_sec = 5;
+    tv.tv_usec = 0;
+    FD_ZERO(&fdset);
+    FD_SET(xs_fileno(xs), &fdset);
+    if ((select(xs_fileno(xs) + 1, &fdset, NULL, NULL, &tv)) != 1) {
+        errx(1, "timed out waiting for qemu to switch buffers\n");
+        exit(1);
+    }
+    watch = xs_read_watch(xs, &len);
+    free(watch);
+    
+    active_str = xs_read(xs, XBT_NULL, qemu_active_path, &len);
+    if (active_str == NULL || active_str[0] - '0' != next_active) 
+        /* Watch fired but value is not yet right */
+        goto read_again;
+}
+
+static void * init_qemu_maps(int domid, unsigned int bitmap_size)
+{
+    key_t key;
+    char key_ascii[17] = {0,};
+    int shmid = -1;
+    void *seg; 
+    char *path, *p;
+
+    /* Make a shared-memory segment */
+    while (shmid == -1)
+    {
+        key = rand(); /* No security, just a sequence of numbers */
+        shmid = shmget(key, 2 * bitmap_size, 
+                       IPC_CREAT|IPC_EXCL|S_IRUSR|S_IWUSR);
+        if (shmid == -1 && errno != EEXIST)
+            errx(1, "can't get shmem to talk to qemu-dm");
+    }
+
+    /* Map it into our address space */
+    seg = shmat(shmid, NULL, 0);
+    if (seg == (void *) -1) 
+        errx(1, "can't map shmem to talk to qemu-dm");
+    memset(seg, 0, 2 * bitmap_size);
+
+    /* Write the size of it into the first 32 bits */
+    *(uint32_t *)seg = bitmap_size;
+
+    /* Tell qemu about it */
+    if ((xs = xs_daemon_open()) == NULL)
+        errx(1, "Couldn't contact xenstore");
+    if (!(path = xs_get_domain_path(xs, domid)))
+        errx(1, "can't get domain path in store");
+    if (!(path = realloc(path, strlen(path) 
+                         + strlen("/logdirty/next-active") + 1))) 
+        errx(1, "no memory for constructing xenstore path");
+    strcat(path, "/logdirty/");
+    p = path + strlen(path);
+
+    strcpy(p, "key");
+    snprintf(key_ascii, 17, "%16.16llx", (unsigned long long) key);
+    if (!xs_write(xs, XBT_NULL, path, key_ascii, 16))
+        errx(1, "can't write key (%s) to store path (%s)\n", key_ascii, path);
+
+    /* Watch for qemu's indication of the active buffer, and request it 
+     * to start writing to buffer 0 */
+    strcpy(p, "active");
+    if (!xs_watch(xs, path, "qemu-active-buffer"))
+        errx(1, "can't set watch in store (%s)\n", path);
+    if (!(qemu_active_path = strdup(path)))
+        errx(1, "no memory for copying xenstore path");
+
+    strcpy(p, "next-active");
+    if (!(qemu_next_active_path = strdup(path)))
+        errx(1, "no memory for copying xenstore path");
+
+    qemu_flip_buffer(domid, 0);
+
+    free(path);
+    return seg;
 }
 
 
@@ -52,9 +175,11 @@ main(int argc, char **argv)
     flags = atoi(argv[5]);
 
     if (flags & XCFLAGS_HVM)
-        ret = xc_hvm_save(xc_fd, io_fd, domid, maxit, max_f, flags, &suspend);
+        ret = xc_hvm_save(xc_fd, io_fd, domid, maxit, max_f, flags, 
+                          &suspend, &init_qemu_maps, &qemu_flip_buffer);
     else 
-        ret = xc_linux_save(xc_fd, io_fd, domid, maxit, max_f, flags, 
&suspend);
+        ret = xc_linux_save(xc_fd, io_fd, domid, maxit, max_f, flags, 
+                            &suspend);
 
     xc_interface_close(xc_fd);
 
diff -r f74e837c3902 -r 2216a45bf058 
tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py
--- a/tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py Tue Mar 
20 10:07:11 2007 -0600
+++ b/tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py Tue Mar 
20 15:19:38 2007 -0600
@@ -32,10 +32,10 @@ except ConsoleError, e:
 
 status, output = traceCommand("xm block-attach %s phy:NOT-EXIST xvda1 w" % 
domain.getName())
 eyecatcher = "Error"
-where = output.find(eyecatcher)
+where = re.compile(eyecatcher, re.IGNORECASE).search(output)
 if status == 0:
     FAIL("xm block-attach returned bad status, expected non 0, status is: %i" 
% status )
-elif where == -1:
+elif where is None:
     FAIL("xm block-attach returned bad output, expected Error, output is: %s" 
% output )
 
 try:
diff -r f74e837c3902 -r 2216a45bf058 
tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py
--- a/tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py    
Tue Mar 20 10:07:11 2007 -0600
+++ b/tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py    
Tue Mar 20 15:19:38 2007 -0600
@@ -31,10 +31,10 @@ except ConsoleError, e:
 
 status, output = traceCommand("xm block-attach %s file:/dev/NOT-EXIST xvda1 w" 
% domain.getName())
 eyecatcher = "Error"
-where = output.find(eyecatcher)
+where = re.compile(eyecatcher, re.IGNORECASE).search(output)
 if status == 0:
     FAIL("xm block-attach returned bad status, expected non 0, status is: %i" 
% status )
-elif where == -1:
+elif where is None:
     FAIL("xm block-attach returned bad output, expected Error, output is: %s" 
% output )
     
 try:
diff -r f74e837c3902 -r 2216a45bf058 
tools/xm-test/tests/network-attach/network_utils.py
--- a/tools/xm-test/tests/network-attach/network_utils.py       Tue Mar 20 
10:07:11 2007 -0600
+++ b/tools/xm-test/tests/network-attach/network_utils.py       Tue Mar 20 
15:19:38 2007 -0600
@@ -11,6 +11,18 @@ def count_eth(console):
     except ConsoleError, e:
         FAIL(str(e))
     return len(run['output'].splitlines())
+
+def get_state(domain_name, number):
+    s, o = traceCommand("xm network-list %s | awk '/^%d/ {print $5}'" %
+                        (domain_name, number))
+    print o
+    
+    if s != 0:
+        FAIL("network-list failed")
+    if o == "":
+        return 0
+    else:
+        return int(o)
 
 def network_attach(domain_name, console):
     eths_before = count_eth(console)
@@ -30,6 +42,13 @@ def network_detach(domain_name, console,
     if status != 0:
         return -1, "xm network-detach returned invalid %i != 0" % status
 
+    for i in range(10):
+        if get_state(domain_name, num) == 0:
+            break
+        time.sleep(1)
+    else:
+        FAIL("network-detach failed: device did not disappear")
+
     eths_after = count_eth(console)
     if eths_after != (eths_before-1):
        return -2, "Network device was not actually disconnected from domU"
diff -r f74e837c3902 -r 2216a45bf058 
unmodified_drivers/linux-2.6/platform-pci/evtchn.c
--- a/unmodified_drivers/linux-2.6/platform-pci/evtchn.c        Tue Mar 20 
10:07:11 2007 -0600
+++ b/unmodified_drivers/linux-2.6/platform-pci/evtchn.c        Tue Mar 20 
15:19:38 2007 -0600
@@ -167,7 +167,8 @@ irqreturn_t evtchn_interrupt(int irq, vo
 irqreturn_t evtchn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        unsigned int l1i, port;
-       int cpu = smp_processor_id();
+       /* XXX: All events are bound to vcpu0 but irq may be redirected. */
+       int cpu = 0; /*smp_processor_id();*/
        irqreturn_t(*handler) (int, void *, struct pt_regs *);
        shared_info_t *s = shared_info_area;
        vcpu_info_t *v = &s->vcpu_info[cpu];
diff -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/Rules.mk
--- a/xen/arch/x86/Rules.mk     Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/arch/x86/Rules.mk     Tue Mar 20 15:19:38 2007 -0600
@@ -58,19 +58,7 @@ HDRS += $(wildcard $(BASEDIR)/include/as
 HDRS += $(wildcard $(BASEDIR)/include/asm-x86/hvm/svm/*.h)
 HDRS += $(wildcard $(BASEDIR)/include/asm-x86/hvm/vmx/*.h)
 
-# Test for at least GCC v3.2.x.
-gcc-ver = $(shell $(CC) -dumpversion | sed -e 's/^\(.\)\.\(.\)\.\(.\)/\$(1)/')
-ifeq ($(call gcc-ver,1),1)
-$(error gcc-1.x.x unsupported - upgrade to at least gcc-3.2.x)
+# Require GCC v3.4+ (to avoid issues with alignment constraints in Xen headers)
+ifneq ($(call cc-ver,$(CC),0x030400),y)
+$(error Xen requires at least gcc-3.4)
 endif
-ifeq ($(call gcc-ver,1),2)
-$(error gcc-2.x.x unsupported - upgrade to at least gcc-3.2.x)
-endif
-ifeq ($(call gcc-ver,1),3)
-ifeq ($(call gcc-ver,2),0)
-$(error gcc-3.0.x unsupported - upgrade to at least gcc-3.2.x)
-endif
-ifeq ($(call gcc-ver,2),1)
-$(error gcc-3.1.x unsupported - upgrade to at least gcc-3.2.x)
-endif
-endif
diff -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/hvm/hpet.c
--- a/xen/arch/x86/hvm/hpet.c   Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/arch/x86/hvm/hpet.c   Tue Mar 20 15:19:38 2007 -0600
@@ -29,6 +29,10 @@
 #define S_TO_NS  1000000000ULL           /* 1s  = 10^9  ns */
 #define S_TO_FS  1000000000000000ULL     /* 1s  = 10^15 fs */
 
+/* Frequency_of_TSC / frequency_of_HPET = 32 */
+#define TSC_PER_HPET_TICK 32
+#define guest_time_hpet(v) (hvm_get_guest_time(v) / TSC_PER_HPET_TICK)
+
 #define HPET_ID         0x000
 #define HPET_PERIOD     0x004
 #define HPET_CFG        0x010
@@ -67,7 +71,9 @@
 #define HPET_TN_INT_ROUTE_CAP_MASK (0xffffffffULL \
                     << HPET_TN_INT_ROUTE_CAP_SHIFT)
 
-#define hpet_tick_to_ns(h, tick) ((s_time_t)(tick)*S_TO_NS/h->tsc_freq)
+#define hpet_tick_to_ns(h, tick) ((s_time_t)(tick)* \
+                                  (S_TO_NS*TSC_PER_HPET_TICK)/h->tsc_freq)
+
 #define timer_config(h, n)       (h->hpet.timers[n].config)
 #define timer_enabled(h, n)      (timer_config(h, n) & HPET_TN_ENABLE)
 #define timer_is_periodic(h, n)  (timer_config(h, n) & HPET_TN_PERIODIC)
@@ -108,7 +114,7 @@ static inline uint64_t hpet_read_maincou
 static inline uint64_t hpet_read_maincounter(HPETState *h)
 {
     if ( hpet_enabled(h) )
-        return hvm_get_guest_time(h->vcpu) + h->mc_offset;
+        return guest_time_hpet(h->vcpu) + h->mc_offset;
     else 
         return h->hpet.mc64;
 }
@@ -144,7 +150,7 @@ static void hpet_stop_timer(HPETState *h
 
 /* the number of HPET tick that stands for
  * 1/(2^10) second, namely, 0.9765625 milliseconds */
-#define  HPET_TINY_TIME_SPAN  (h->tsc_freq >> 10)
+#define  HPET_TINY_TIME_SPAN  ((h->tsc_freq >> 10) / TSC_PER_HPET_TICK)
 
 static void hpet_set_timer(HPETState *h, unsigned int tn)
 {
@@ -225,14 +231,14 @@ static void hpet_write(
         if ( !(old_val & HPET_CFG_ENABLE) && (new_val & HPET_CFG_ENABLE) )
         {
             /* Enable main counter and interrupt generation. */
-            h->mc_offset = h->hpet.mc64 - hvm_get_guest_time(h->vcpu);
+            h->mc_offset = h->hpet.mc64 - guest_time_hpet(h->vcpu);
             for ( i = 0; i < HPET_TIMER_NUM; i++ )
                 hpet_set_timer(h, i); 
         }
         else if ( (old_val & HPET_CFG_ENABLE) && !(new_val & HPET_CFG_ENABLE) )
         {
             /* Halt main counter and disable interrupt generation. */
-            h->hpet.mc64 = h->mc_offset + hvm_get_guest_time(h->vcpu);
+            h->hpet.mc64 = h->mc_offset + guest_time_hpet(h->vcpu);
             for ( i = 0; i < HPET_TIMER_NUM; i++ )
                 hpet_stop_timer(h, i);
         }
@@ -384,7 +390,7 @@ static int hpet_save(struct domain *d, h
     HPETState *hp = &d->arch.hvm_domain.pl_time.vhpet;
 
     /* Write the proper value into the main counter */
-    hp->hpet.mc64 = hp->mc_offset + hvm_get_guest_time(hp->vcpu);
+    hp->hpet.mc64 = hp->mc_offset + guest_time_hpet(hp->vcpu);
 
     /* Save the HPET registers */
     return hvm_save_entry(HPET, 0, h, &hp->hpet);
@@ -400,7 +406,7 @@ static int hpet_load(struct domain *d, h
         return -EINVAL;
     
     /* Recalculate the offset between the main counter and guest time */
-    hp->mc_offset = hp->hpet.mc64 - hvm_get_guest_time(hp->vcpu);
+    hp->mc_offset = hp->hpet.mc64 - guest_time_hpet(hp->vcpu);
                 
     /* Restart the timers */
     for ( i = 0; i < HPET_TIMER_NUM; i++ )
@@ -425,8 +431,8 @@ void hpet_init(struct vcpu *v)
     h->hpet.capability = 0x8086A201ULL;
 
     /* This is the number of femptoseconds per HPET tick. */
-    /* Here we define HPET's frequency to be the same as the TSC's. */
-    h->hpet.capability |= ((S_TO_FS/h->tsc_freq) << 32);
+    /* Here we define HPET's frequency to be 1/32 of the TSC's */
+    h->hpet.capability |= ((S_TO_FS*TSC_PER_HPET_TICK/h->tsc_freq) << 32);
 
     for ( i = 0; i < HPET_TIMER_NUM; i++ )
     {
diff -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/hvm/platform.c
--- a/xen/arch/x86/hvm/platform.c       Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/arch/x86/hvm/platform.c       Tue Mar 20 15:19:38 2007 -0600
@@ -415,6 +415,17 @@ static int mmio_decode(int address_bytes
         GET_OP_SIZE_FOR_NONEBYTE(*op_size);
         return mem_reg(*op_size, opcode, mmio_op, rex);
 
+    case 0x08: /* or r8, m8 */ 
+        mmio_op->instr = INSTR_OR;
+        *op_size = BYTE;
+        GET_OP_SIZE_FOR_BYTE(size_reg);
+        return reg_mem(size_reg, opcode, mmio_op, rex);
+
+    case 0x09: /* or r32/16, m32/16 */
+        mmio_op->instr = INSTR_OR;
+        GET_OP_SIZE_FOR_NONEBYTE(*op_size);
+        return reg_mem(*op_size, opcode, mmio_op, rex);
+
     case 0x0A: /* or m8, r8 */
         mmio_op->instr = INSTR_OR;
         *op_size = BYTE;
diff -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/arch/x86/hvm/svm/svm.c        Tue Mar 20 15:19:38 2007 -0600
@@ -449,6 +449,9 @@ int svm_vmcb_restore(struct vcpu *v, str
     vmcb->rflags = c->eflags;
 
     v->arch.hvm_svm.cpu_shadow_cr0 = c->cr0;
+    vmcb->cr0 = c->cr0 | X86_CR0_WP | X86_CR0_ET;
+    if ( !paging_mode_hap(v->domain) ) 
+        vmcb->cr0 |= X86_CR0_PG;
 
 #ifdef HVM_DEBUG_SUSPEND
     printk("%s: cr3=0x%"PRIx64", cr0=0x%"PRIx64", cr4=0x%"PRIx64".\n",
@@ -482,7 +485,6 @@ int svm_vmcb_restore(struct vcpu *v, str
          * first.
          */
         HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 c->cr3 = %"PRIx64"", c->cr3);
-        /* current!=vcpu as not called by arch_vmx_do_launch */
         mfn = gmfn_to_mfn(v->domain, c->cr3 >> PAGE_SHIFT);
         if( !mfn_valid(mfn) || !get_page(mfn_to_page(mfn), v->domain) ) 
             goto bad_cr3;
@@ -566,7 +568,7 @@ void svm_save_cpu_state(struct vcpu *v, 
     data->msr_star         = vmcb->star;
     data->msr_cstar        = vmcb->cstar;
     data->msr_syscall_mask = vmcb->sfmask;
-    data->msr_efer         = vmcb->efer;
+    data->msr_efer         = v->arch.hvm_svm.cpu_shadow_efer;
 
     data->tsc = hvm_get_guest_time(v);
 }
@@ -581,7 +583,12 @@ void svm_load_cpu_state(struct vcpu *v, 
     vmcb->star       = data->msr_star;
     vmcb->cstar      = data->msr_cstar;
     vmcb->sfmask     = data->msr_syscall_mask;
-    vmcb->efer       = data->msr_efer;
+    v->arch.hvm_svm.cpu_shadow_efer = data->msr_efer;
+    vmcb->efer       = data->msr_efer | EFER_SVME;
+    /* VMCB's EFER.LME isn't set unless we're actually in long mode
+     * (see long_mode_do_msr_write()) */
+    if ( !(vmcb->efer & EFER_LMA) )
+        vmcb->efer &= ~EFER_LME;
 
     hvm_set_guest_time(v, data->tsc);
 }
@@ -741,6 +748,14 @@ static void svm_init_ap_context(
 static void svm_init_ap_context(
     struct vcpu_guest_context *ctxt, int vcpuid, int trampoline_vector)
 {
+    struct vcpu *v;
+    cpu_user_regs_t *regs;
+    u16 cs_sel;
+
+    /* We know this is safe because hvm_bringup_ap() does it */
+    v = current->domain->vcpu[vcpuid];
+    regs = &v->arch.guest_context.user_regs;
+
     memset(ctxt, 0, sizeof(*ctxt));
 
     /*
@@ -748,8 +763,19 @@ static void svm_init_ap_context(
      * passed to us is page alligned and is the physicall frame number for
      * the code. We will execute this code in real mode. 
      */
+    cs_sel = trampoline_vector << 8;
     ctxt->user_regs.eip = 0x0;
-    ctxt->user_regs.cs = (trampoline_vector << 8);
+    ctxt->user_regs.cs = cs_sel;
+
+    /*
+     * This is the launch of an AP; set state so that we begin executing
+     * the trampoline code in real-mode.
+     */
+    svm_do_vmmcall_reset_to_realmode(v, regs);  
+    /* Adjust the vmcb's hidden register state. */
+    v->arch.hvm_svm.vmcb->rip = 0;
+    v->arch.hvm_svm.vmcb->cs.sel = cs_sel;
+    v->arch.hvm_svm.vmcb->cs.base = (cs_sel << 4);
 }
 
 static void svm_init_hypercall_page(struct domain *d, void *hypercall_page)
@@ -894,32 +920,6 @@ static void svm_load_cpu_guest_regs(
     svm_load_cpu_user_regs(v, regs);
 }
 
-static void arch_svm_do_launch(struct vcpu *v) 
-{
-    svm_do_launch(v);
-
-    if ( paging_mode_hap(v->domain) ) {
-        v->arch.hvm_svm.vmcb->h_cr3 = 
pagetable_get_paddr(v->domain->arch.phys_table);
-    }
-
-    if ( v->vcpu_id != 0 )
-    {
-        cpu_user_regs_t *regs = &current->arch.guest_context.user_regs;
-        u16 cs_sel = regs->cs;
-        /*
-         * This is the launch of an AP; set state so that we begin executing
-         * the trampoline code in real-mode.
-         */
-        svm_do_vmmcall_reset_to_realmode(v, regs);  
-        /* Adjust the state to execute the trampoline code.*/
-        v->arch.hvm_svm.vmcb->rip = 0;
-        v->arch.hvm_svm.vmcb->cs.sel= cs_sel;
-        v->arch.hvm_svm.vmcb->cs.base = (cs_sel << 4);
-    }
-      
-    reset_stack_and_jump(svm_asm_do_launch);
-}
-
 static void svm_ctxt_switch_from(struct vcpu *v)
 {
     svm_save_dr(v);
@@ -941,15 +941,29 @@ static void svm_ctxt_switch_to(struct vc
     svm_restore_dr(v);
 }
 
+static void arch_svm_do_resume(struct vcpu *v) 
+{
+    if ( v->arch.hvm_svm.launch_core != smp_processor_id() )
+    {
+        v->arch.hvm_svm.launch_core = smp_processor_id();
+        hvm_migrate_timers(v);
+    }
+
+    hvm_do_resume(v);
+    reset_stack_and_jump(svm_asm_do_resume);
+}
+
 static int svm_vcpu_initialise(struct vcpu *v)
 {
     int rc;
 
-    v->arch.schedule_tail    = arch_svm_do_launch;
+    v->arch.schedule_tail    = arch_svm_do_resume;
     v->arch.ctxt_switch_from = svm_ctxt_switch_from;
     v->arch.ctxt_switch_to   = svm_ctxt_switch_to;
 
     v->arch.hvm_svm.saved_irq_vector = -1;
+
+    v->arch.hvm_svm.launch_core = -1;
 
     if ( (rc = svm_create_vmcb(v)) != 0 )
     {
@@ -1014,10 +1028,12 @@ void svm_npt_detect(void)
 
     /* check CPUID for nested paging support */
     cpuid(0x8000000A, &eax, &ebx, &ecx, &edx);
-    if ( edx & 0x01 ) { /* nested paging */
+    if ( edx & 0x01 ) /* nested paging */
+    {
         hap_capable_system = 1;
     }
-    else if ( opt_hap_enabled ) {
+    else if ( opt_hap_enabled )
+    {
         printk(" nested paging is not supported by this CPU.\n");
         hap_capable_system = 0; /* no nested paging, we disable flag. */
     }
@@ -1073,24 +1089,6 @@ int start_svm(void)
     hvm_enable(&svm_function_table);
 
     return 1;
-}
-
-void arch_svm_do_resume(struct vcpu *v) 
-{
-    /* pinning VCPU to a different core? */
-    if ( v->arch.hvm_svm.launch_core == smp_processor_id()) {
-        hvm_do_resume( v );
-        reset_stack_and_jump( svm_asm_do_resume );
-    }
-    else {
-        if (svm_dbg_on)
-            printk("VCPU core pinned: %d to %d\n", 
-                   v->arch.hvm_svm.launch_core, smp_processor_id() );
-        v->arch.hvm_svm.launch_core = smp_processor_id();
-        hvm_migrate_timers( v );
-        hvm_do_resume( v );
-        reset_stack_and_jump( svm_asm_do_resume );
-    }
 }
 
 static int svm_do_nested_pgfault(paddr_t gpa, struct cpu_user_regs *regs)
diff -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/hvm/svm/vmcb.c
--- a/xen/arch/x86/hvm/svm/vmcb.c       Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/arch/x86/hvm/svm/vmcb.c       Tue Mar 20 15:19:38 2007 -0600
@@ -196,11 +196,13 @@ static int construct_vmcb(struct vcpu *v
 
     arch_svm->vmcb->exception_intercepts = MONITOR_DEFAULT_EXCEPTION_BITMAP;
 
-    if ( paging_mode_hap(v->domain) ) {
+    if ( paging_mode_hap(v->domain) )
+    {
         vmcb->cr0 = arch_svm->cpu_shadow_cr0;
         vmcb->np_enable = 1; /* enable nested paging */
         vmcb->g_pat = 0x0007040600070406ULL; /* guest PAT */
         vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_PG;
+        vmcb->h_cr3 = pagetable_get_paddr(v->domain->arch.phys_table);
     }
 
     return 0;
@@ -245,16 +247,6 @@ void svm_destroy_vmcb(struct vcpu *v)
     }
 
     arch_svm->vmcb = NULL;
-}
-
-void svm_do_launch(struct vcpu *v)
-{
-    hvm_stts(v);
-
-    /* current core is the one we intend to perform the VMRUN on */
-    v->arch.hvm_svm.launch_core = smp_processor_id();
-
-    v->arch.schedule_tail = arch_svm_do_resume;
 }
 
 static void svm_dump_sel(char *name, svm_segment_register_t *s)
diff -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/hvm/svm/x86_32/exits.S
--- a/xen/arch/x86/hvm/svm/x86_32/exits.S       Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/arch/x86/hvm/svm/x86_32/exits.S       Tue Mar 20 15:19:38 2007 -0600
@@ -80,15 +80,24 @@
         popl %eax;  \
         addl $(NR_SKIPPED_REGS*4), %esp
 
-        ALIGN
-
 #define VMRUN  .byte 0x0F,0x01,0xD8
 #define VMLOAD .byte 0x0F,0x01,0xDA
 #define VMSAVE .byte 0x0F,0x01,0xDB
 #define STGI   .byte 0x0F,0x01,0xDC
 #define CLGI   .byte 0x0F,0x01,0xDD
 
-ENTRY(svm_asm_do_launch)
+ENTRY(svm_asm_do_resume)
+        GET_CURRENT(%ebx)
+        xorl %ecx,%ecx
+        notl %ecx
+        cli                             # tests must not race interrupts
+        movl VCPU_processor(%ebx),%eax
+        shl  $IRQSTAT_shift,%eax
+        test %ecx,irq_stat(%eax,1)
+        jnz  svm_process_softirqs
+        call svm_intr_assist
+        call svm_load_cr2
+
         CLGI                
         sti
         GET_CURRENT(%ebx)
@@ -135,30 +144,7 @@ svm_stgi_label:
         jmp  svm_asm_do_resume
 
         ALIGN
-
-ENTRY(svm_asm_do_resume)
-svm_test_all_events:
-        GET_CURRENT(%ebx)
-/*test_all_events:*/
-        xorl %ecx,%ecx
-        notl %ecx
-        cli                             # tests must not race interrupts
-/*test_softirqs:*/  
-        movl VCPU_processor(%ebx),%eax
-        shl  $IRQSTAT_shift,%eax
-        test %ecx,irq_stat(%eax,1)
-        jnz  svm_process_softirqs
-svm_restore_all_guest:
-        call svm_intr_assist
-        call svm_load_cr2
-        /* 
-         * Check if we are going back to AMD-V based VM
-         * By this time, all the setups in the VMCB must be complete.
-         */
-        jmp svm_asm_do_launch
-
-        ALIGN
 svm_process_softirqs:
         sti       
         call do_softirq
-        jmp  svm_test_all_events
+        jmp  svm_asm_do_resume
diff -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/hvm/svm/x86_64/exits.S
--- a/xen/arch/x86/hvm/svm/x86_64/exits.S       Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/arch/x86/hvm/svm/x86_64/exits.S       Tue Mar 20 15:19:38 2007 -0600
@@ -98,7 +98,17 @@
 #define STGI   .byte 0x0F,0x01,0xDC
 #define CLGI   .byte 0x0F,0x01,0xDD
 
-ENTRY(svm_asm_do_launch)
+ENTRY(svm_asm_do_resume)
+        GET_CURRENT(%rbx)
+        cli                             # tests must not race interrupts
+        movl VCPU_processor(%rbx),%eax
+        shl  $IRQSTAT_shift, %rax
+        leaq irq_stat(%rip), %rdx
+        testl $~0, (%rdx, %rax, 1)
+        jnz  svm_process_softirqs
+        call svm_intr_assist
+        call svm_load_cr2
+
         CLGI                
         sti
         GET_CURRENT(%rbx)
@@ -150,28 +160,8 @@ svm_stgi_label:
         call svm_vmexit_handler
         jmp  svm_asm_do_resume
 
-ENTRY(svm_asm_do_resume)
-svm_test_all_events:
-        GET_CURRENT(%rbx)
-/*test_all_events:*/
-        cli                             # tests must not race interrupts
-/*test_softirqs:*/
-        movl  VCPU_processor(%rbx),%eax
-        shl   $IRQSTAT_shift, %rax
-        leaq  irq_stat(%rip), %rdx
-        testl $~0, (%rdx, %rax, 1)
-        jnz   svm_process_softirqs
-svm_restore_all_guest:
-        call svm_intr_assist
-        call svm_load_cr2
-        /*
-         * Check if we are going back to AMD-V based VM
-         * By this time, all the setups in the VMCB must be complete.
-         */
-        jmp svm_asm_do_launch
-
         ALIGN
 svm_process_softirqs:
         sti
         call do_softirq
-        jmp  svm_test_all_events
+        jmp  svm_asm_do_resume
diff -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/hvm/vpic.c
--- a/xen/arch/x86/hvm/vpic.c   Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/arch/x86/hvm/vpic.c   Tue Mar 20 15:19:38 2007 -0600
@@ -54,8 +54,8 @@ static int vpic_get_priority(struct hvm_
     if ( mask == 0 )
         return VPIC_PRIO_NONE;
 
-    /* prio = ffs(mask ROL vpic->priority_add); */
-    asm ( "rol %%cl,%b1 ; bsf %1,%0"
+    /* prio = ffs(mask ROR vpic->priority_add); */
+    asm ( "ror %%cl,%b1 ; bsf %1,%0"
           : "=r" (prio) : "r" ((uint32_t)mask), "c" (vpic->priority_add) );
     return prio;
 }
diff -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/arch/x86/mm.c Tue Mar 20 15:19:38 2007 -0600
@@ -108,6 +108,7 @@
 #include <asm/x86_emulate.h>
 #include <asm/e820.h>
 #include <asm/hypercall.h>
+#include <asm/shared.h>
 #include <public/memory.h>
 
 #define MEM_LOG(_f, _a...) gdprintk(XENLOG_WARNING , _f "\n" , ## _a)
@@ -244,6 +245,11 @@ int memory_is_conventional_ram(paddr_t p
     }
 
     return 0;
+}
+
+unsigned long domain_get_maximum_gpfn(struct domain *d)
+{
+    return is_hvm_domain(d) ? d->arch.p2m.max_mapped_pfn : arch_get_max_pfn(d);
 }
 
 void share_xen_page_with_guest(
diff -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/mm/shadow/common.c
--- a/xen/arch/x86/mm/shadow/common.c   Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/arch/x86/mm/shadow/common.c   Tue Mar 20 15:19:38 2007 -0600
@@ -36,7 +36,6 @@
 #include <asm/current.h>
 #include <asm/flushtlb.h>
 #include <asm/shadow.h>
-#include <asm/shared.h>
 #include "private.h"
 
 
@@ -2672,7 +2671,7 @@ sh_alloc_log_dirty_bitmap(struct domain 
 {
     ASSERT(d->arch.paging.shadow.dirty_bitmap == NULL);
     d->arch.paging.shadow.dirty_bitmap_size =
-        (arch_get_max_pfn(d) + (BITS_PER_LONG - 1)) &
+        (domain_get_maximum_gpfn(d) + (BITS_PER_LONG - 1)) &
         ~(BITS_PER_LONG - 1);
     d->arch.paging.shadow.dirty_bitmap =
         xmalloc_array(unsigned long,
@@ -2682,7 +2681,8 @@ sh_alloc_log_dirty_bitmap(struct domain 
         d->arch.paging.shadow.dirty_bitmap_size = 0;
         return -ENOMEM;
     }
-    memset(d->arch.paging.shadow.dirty_bitmap, 0, 
d->arch.paging.shadow.dirty_bitmap_size/8);
+    memset(d->arch.paging.shadow.dirty_bitmap, 0,
+           d->arch.paging.shadow.dirty_bitmap_size/8);
 
     return 0;
 }
diff -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/x86_64/asm-offsets.c
--- a/xen/arch/x86/x86_64/asm-offsets.c Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/arch/x86/x86_64/asm-offsets.c Tue Mar 20 15:19:38 2007 -0600
@@ -59,6 +59,7 @@ void __dummy__(void)
     OFFSET(VCPU_domain, struct vcpu, domain);
     OFFSET(VCPU_vcpu_info, struct vcpu, vcpu_info);
     OFFSET(VCPU_trap_bounce, struct vcpu, arch.trap_bounce);
+    OFFSET(VCPU_int80_bounce, struct vcpu, arch.int80_bounce);
     OFFSET(VCPU_thread_flags, struct vcpu, arch.flags);
     OFFSET(VCPU_event_addr, struct vcpu,
            arch.guest_context.event_callback_eip);
diff -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/x86_64/compat/entry.S
--- a/xen/arch/x86/x86_64/compat/entry.S        Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/arch/x86/x86_64/compat/entry.S        Tue Mar 20 15:19:38 2007 -0600
@@ -186,6 +186,10 @@ ENTRY(compat_post_handle_exception)
         jz    compat_test_all_events
         call  compat_create_bounce_frame
         jmp   compat_test_all_events
+
+ENTRY(compat_int80_direct_trap)
+        call  compat_create_bounce_frame
+        jmp   compat_restore_all_guest
 
 /* CREATE A BASIC EXCEPTION FRAME ON GUEST OS (RING-1) STACK:            */
 /*   {[ERRCODE,] EIP, CS, EFLAGS, [ESP, SS]}                             */
diff -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/x86_64/compat/traps.c
--- a/xen/arch/x86/x86_64/compat/traps.c        Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/arch/x86/x86_64/compat/traps.c        Tue Mar 20 15:19:38 2007 -0600
@@ -1,6 +1,7 @@
 #ifdef CONFIG_COMPAT
 
 #include <xen/event.h>
+#include <asm/regs.h>
 #include <compat/callback.h>
 #include <compat/arch-x86_32.h>
 
@@ -291,6 +292,9 @@ int compat_set_trap_table(XEN_GUEST_HAND
 
         XLAT_trap_info(dst + cur.vector, &cur);
 
+        if ( cur.vector == 0x80 )
+            init_int80_direct_trap(current);
+
         guest_handle_add_offset(traps, 1);
     }
 
diff -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/x86_64/entry.S
--- a/xen/arch/x86/x86_64/entry.S       Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/arch/x86/x86_64/entry.S       Tue Mar 20 15:19:38 2007 -0600
@@ -221,6 +221,35 @@ bad_hypercall:
 bad_hypercall:
         movq $-ENOSYS,UREGS_rax(%rsp)
         jmp  test_all_events
+
+ENTRY(int80_direct_trap)
+        pushq $0
+        SAVE_ALL
+
+        GET_CURRENT(%rbx)
+
+        /* Check that the callback is non-null. */
+        leaq  VCPU_int80_bounce(%rbx),%rdx
+        cmp   $0, TRAPBOUNCE_flags(%rdx)
+        jz    int80_slow_path
+
+        movq  VCPU_domain(%rbx),%rax
+        btl   $_DOMF_compat,DOMAIN_domain_flags(%rax)
+        jc    compat_int80_direct_trap
+
+        call  create_bounce_frame
+        jmp   restore_all_guest
+
+int80_slow_path:
+        /* 
+         * Setup entry vector and error code as if this was a GPF caused by an
+         * IDT entry with DPL==0.
+         */
+        movl  $((0x80 << 3) | 0x2),UREGS_error_code(%rsp)
+        movl  $TRAP_gp_fault,UREGS_entry_vector(%rsp)
+        /* A GPF wouldn't have incremented the instruction pointer. */
+        sub   $2,UREGS_rip(%rsp)
+        jmp   handle_exception_saved
 
 /* CREATE A BASIC EXCEPTION FRAME ON GUEST OS STACK:                     */
 /*   { RCX, R11, [DS-GS,] [CR2,] [ERRCODE,] RIP, CS, RFLAGS, RSP, SS }   */
@@ -359,6 +388,7 @@ ENTRY(ret_from_intr)
 /* No special register assumptions. */
 ENTRY(handle_exception)
         SAVE_ALL
+handle_exception_saved:
         testb $X86_EFLAGS_IF>>8,UREGS_eflags+1(%rsp)
         jz    exception_with_ints_disabled
         sti
diff -r f74e837c3902 -r 2216a45bf058 xen/arch/x86/x86_64/traps.c
--- a/xen/arch/x86/x86_64/traps.c       Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/arch/x86/x86_64/traps.c       Tue Mar 20 15:19:38 2007 -0600
@@ -247,6 +247,7 @@ unsigned long do_iret(void)
 
 asmlinkage void syscall_enter(void);
 asmlinkage void compat_hypercall(void);
+asmlinkage void int80_direct_trap(void);
 void __init percpu_traps_init(void)
 {
     char *stack_bottom, *stack;
@@ -262,6 +263,7 @@ void __init percpu_traps_init(void)
 #ifdef CONFIG_COMPAT
         /* The hypercall entry vector is only accessible from ring 1. */
         _set_gate(idt_table+HYPERCALL_VECTOR, 15, 1, &compat_hypercall);
+        _set_gate(idt_table+0x80, 15, 3, &int80_direct_trap);
 #endif
     }
 
@@ -344,6 +346,22 @@ void __init percpu_traps_init(void)
 
     wrmsr(MSR_STAR, 0, (FLAT_RING3_CS32<<16) | __HYPERVISOR_CS);
     wrmsr(MSR_SYSCALL_MASK, EF_VM|EF_RF|EF_NT|EF_DF|EF_IE|EF_TF, 0U);
+}
+
+void init_int80_direct_trap(struct vcpu *v)
+{
+    struct trap_info *ti = &v->arch.guest_context.trap_ctxt[0x80];
+    struct trap_bounce *tb = &v->arch.int80_bounce;
+
+    if ( !guest_gate_selector_okay(v->domain, ti->cs) )
+         return;
+
+    tb->flags = TBF_EXCEPTION;
+    tb->cs    = ti->cs;
+    tb->eip   = ti->address;
+
+    if ( null_trap_bounce(v, tb) )
+        tb->flags = 0;
 }
 
 static long register_guest_callback(struct callback_register *reg)
diff -r f74e837c3902 -r 2216a45bf058 xen/common/compat/memory.c
--- a/xen/common/compat/memory.c        Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/common/compat/memory.c        Tue Mar 20 15:19:38 2007 -0600
@@ -170,6 +170,7 @@ int compat_memory_op(unsigned int cmd, X
 
         case XENMEM_current_reservation:
         case XENMEM_maximum_reservation:
+        case XENMEM_maximum_gpfn:
         {
 #define xen_domid_t domid_t
 #define compat_domid_t domid_compat_t
@@ -325,6 +326,7 @@ int compat_memory_op(unsigned int cmd, X
         case XENMEM_maximum_ram_page:
         case XENMEM_current_reservation:
         case XENMEM_maximum_reservation:
+        case XENMEM_maximum_gpfn:
             break;
 
         case XENMEM_translate_gpfn_list:
diff -r f74e837c3902 -r 2216a45bf058 xen/common/memory.c
--- a/xen/common/memory.c       Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/common/memory.c       Tue Mar 20 15:19:38 2007 -0600
@@ -584,6 +584,7 @@ long do_memory_op(unsigned long cmd, XEN
 
     case XENMEM_current_reservation:
     case XENMEM_maximum_reservation:
+    case XENMEM_maximum_gpfn:
         if ( copy_from_guest(&domid, arg, 1) )
             return -EFAULT;
 
@@ -594,7 +595,19 @@ long do_memory_op(unsigned long cmd, XEN
         else if ( (d = rcu_lock_domain_by_id(domid)) == NULL )
             return -ESRCH;
 
-        rc = (op == XENMEM_current_reservation) ? d->tot_pages : d->max_pages;
+        switch ( op )
+        {
+        case XENMEM_current_reservation:
+            rc = d->tot_pages;
+            break;
+        case XENMEM_maximum_reservation:
+            rc = d->max_pages;
+            break;
+        default:
+            ASSERT(op == XENMEM_maximum_gpfn);
+            rc = domain_get_maximum_gpfn(d);
+            break;
+        }
 
         if ( unlikely(domid != DOMID_SELF) )
             rcu_unlock_domain(d);
diff -r f74e837c3902 -r 2216a45bf058 xen/common/perfc.c
--- a/xen/common/perfc.c        Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/common/perfc.c        Tue Mar 20 15:19:38 2007 -0600
@@ -136,8 +136,8 @@ static xen_sysctl_perfc_val_t *perfc_val
 static xen_sysctl_perfc_val_t *perfc_vals;
 static int               perfc_nbr_vals;
 static int               perfc_init = 0;
-static int perfc_copy_info(XEN_GUEST_HANDLE(xen_sysctl_perfc_desc_t) desc,
-                           XEN_GUEST_HANDLE(xen_sysctl_perfc_val_t) val)
+static int perfc_copy_info(XEN_GUEST_HANDLE_64(xen_sysctl_perfc_desc_t) desc,
+                           XEN_GUEST_HANDLE_64(xen_sysctl_perfc_val_t) val)
 {
     unsigned int i, j;
     unsigned int v = 0;
@@ -217,29 +217,20 @@ int perfc_control(xen_sysctl_perfc_op_t 
 int perfc_control(xen_sysctl_perfc_op_t *pc)
 {
     static DEFINE_SPINLOCK(lock);
-    XEN_GUEST_HANDLE(xen_sysctl_perfc_desc_t) desc;
-    XEN_GUEST_HANDLE(xen_sysctl_perfc_val_t) val;
     int rc;
 
-    /*
-     * 64 bit guest handles cannot be passed as parameters to
-     * functions so cast to a regular guest handle.
-     */
-    desc = guest_handle_cast(pc->desc, xen_sysctl_perfc_desc_t);
-    val = guest_handle_cast(pc->val, xen_sysctl_perfc_val_t);
-
     spin_lock(&lock);
 
     switch ( pc->cmd )
     {
     case XEN_SYSCTL_PERFCOP_reset:
-        perfc_copy_info(desc, val);
+        perfc_copy_info(pc->desc, pc->val);
         perfc_reset(0);
         rc = 0;
         break;
 
     case XEN_SYSCTL_PERFCOP_query:
-        perfc_copy_info(desc, val);
+        perfc_copy_info(pc->desc, pc->val);
         rc = 0;
         break;
 
diff -r f74e837c3902 -r 2216a45bf058 xen/include/asm-ia64/mm.h
--- a/xen/include/asm-ia64/mm.h Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/include/asm-ia64/mm.h Tue Mar 20 15:19:38 2007 -0600
@@ -511,4 +511,6 @@ int steal_page(
 
 #define domain_clamp_alloc_bitsize(d, b) (b)
 
+#define domain_get_maximum_gpfn(d) (-ENOSYS)
+
 #endif /* __ASM_IA64_MM_H__ */
diff -r f74e837c3902 -r 2216a45bf058 xen/include/asm-powerpc/mm.h
--- a/xen/include/asm-powerpc/mm.h      Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/include/asm-powerpc/mm.h      Tue Mar 20 15:19:38 2007 -0600
@@ -278,4 +278,6 @@ extern int steal_page(struct domain *d, 
 
 #define domain_clamp_alloc_bitsize(d, b) (b)
 
+#define domain_get_maximum_gpfn(d) (-ENOSYS)
+
 #endif
diff -r f74e837c3902 -r 2216a45bf058 xen/include/asm-x86/domain.h
--- a/xen/include/asm-x86/domain.h      Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/include/asm-x86/domain.h      Tue Mar 20 15:19:38 2007 -0600
@@ -248,6 +248,9 @@ struct arch_vcpu
 #ifdef CONFIG_X86_32
     struct desc_struct int80_desc;
 #endif
+#ifdef CONFIG_X86_64
+    struct trap_bounce int80_bounce;
+#endif
 
     /* Virtual Machine Extensions */
     struct hvm_vcpu hvm_vcpu;
diff -r f74e837c3902 -r 2216a45bf058 xen/include/asm-x86/hvm/svm/svm.h
--- a/xen/include/asm-x86/hvm/svm/svm.h Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/include/asm-x86/hvm/svm/svm.h Tue Mar 20 15:19:38 2007 -0600
@@ -29,8 +29,6 @@
 #include <asm/i387.h>
 
 extern void svm_dump_vmcb(const char *from, struct vmcb_struct *vmcb);
-extern void svm_do_launch(struct vcpu *v);
-extern void arch_svm_do_resume(struct vcpu *v);
 
 extern u64 root_vmcb_pa[NR_CPUS];
 
diff -r f74e837c3902 -r 2216a45bf058 xen/include/asm-x86/hvm/svm/vmcb.h
--- a/xen/include/asm-x86/hvm/svm/vmcb.h        Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/include/asm-x86/hvm/svm/vmcb.h        Tue Mar 20 15:19:38 2007 -0600
@@ -447,7 +447,7 @@ struct arch_svm_struct {
     u32                 *msrpm;
     u64                 vmexit_tsc; /* tsc read at #VMEXIT. for TSC_OFFSET */
     int                 saved_irq_vector;
-    u32                 launch_core;
+    int                 launch_core;
     
     unsigned long       flags;            /* VMCB flags */
     unsigned long       cpu_shadow_cr0;   /* Guest value for CR0 */
diff -r f74e837c3902 -r 2216a45bf058 xen/include/asm-x86/mm.h
--- a/xen/include/asm-x86/mm.h  Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/include/asm-x86/mm.h  Tue Mar 20 15:19:38 2007 -0600
@@ -404,5 +404,6 @@ unsigned int domain_clamp_alloc_bitsize(
 # define domain_clamp_alloc_bitsize(d, b) (b)
 #endif
 
+unsigned long domain_get_maximum_gpfn(struct domain *d);
 
 #endif /* __ASM_X86_MM_H__ */
diff -r f74e837c3902 -r 2216a45bf058 xen/include/asm-x86/processor.h
--- a/xen/include/asm-x86/processor.h   Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/include/asm-x86/processor.h   Tue Mar 20 15:19:38 2007 -0600
@@ -455,16 +455,16 @@ extern idt_entry_t *idt_tables[];
 
 extern struct tss_struct init_tss[NR_CPUS];
 
-#ifdef CONFIG_X86_32
-
 extern void init_int80_direct_trap(struct vcpu *v);
+
+#if defined(CONFIG_X86_32)
+
 #define set_int80_direct_trap(_ed)                  \
     (memcpy(idt_tables[(_ed)->processor] + 0x80,    \
             &((_ed)->arch.int80_desc), 8))
 
 #else
 
-#define init_int80_direct_trap(_ed) ((void)0)
 #define set_int80_direct_trap(_ed)  ((void)0)
 
 #endif
diff -r f74e837c3902 -r 2216a45bf058 xen/include/public/arch-x86/xen-x86_32.h
--- a/xen/include/public/arch-x86/xen-x86_32.h  Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/include/public/arch-x86/xen-x86_32.h  Tue Mar 20 15:19:38 2007 -0600
@@ -103,7 +103,7 @@
          (hnd).p = val;                                     \
     } while ( 0 )
 #define uint64_aligned_t uint64_t __attribute__((aligned(8)))
-#define XEN_GUEST_HANDLE_64(name) __guest_handle_64_ ## name 
__attribute__((aligned(8)))
+#define XEN_GUEST_HANDLE_64(name) __guest_handle_64_ ## name
 #endif
 
 #ifndef __ASSEMBLY__
diff -r f74e837c3902 -r 2216a45bf058 xen/include/public/foreign/Makefile
--- a/xen/include/public/foreign/Makefile       Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/include/public/foreign/Makefile       Tue Mar 20 15:19:38 2007 -0600
@@ -18,7 +18,7 @@ check-headers: checker
        ./checker > $(XEN_TARGET_ARCH).size
        diff -u reference.size $(XEN_TARGET_ARCH).size
 checker: checker.c $(headers)
-       $(HOSTCC) $(CFLAGS) -o $@ $<
+       $(HOSTCC) $(HOSTCFLAGS) -o $@ $<
 else
 check-headers:
        @echo "cross build: skipping check"
diff -r f74e837c3902 -r 2216a45bf058 xen/include/public/memory.h
--- a/xen/include/public/memory.h       Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/include/public/memory.h       Tue Mar 20 15:19:38 2007 -0600
@@ -129,6 +129,11 @@ DEFINE_XEN_GUEST_HANDLE(xen_memory_excha
 #define XENMEM_maximum_reservation  4
 
 /*
+ * Returns the maximum GPFN in use by the guest, or -ve errcode on failure.
+ */
+#define XENMEM_maximum_gpfn         14
+
+/*
  * Returns a list of MFN bases of 2MB extents comprising the machine_to_phys
  * mapping table. Architectures which do not have a m2p table do not implement
  * this command.
diff -r f74e837c3902 -r 2216a45bf058 xen/include/xen/trace.h
--- a/xen/include/xen/trace.h   Tue Mar 20 10:07:11 2007 -0600
+++ b/xen/include/xen/trace.h   Tue Mar 20 15:19:38 2007 -0600
@@ -41,11 +41,11 @@ void trace(u32 event, unsigned long d1, 
     do {                                 \
         if ( unlikely(tb_init_done) )    \
             trace(e,                     \
-                 (unsigned long)d1,      \
-                 (unsigned long)d2,      \
-                 (unsigned long)d3,      \
-                 (unsigned long)d4,      \
-                 (unsigned long)d5);     \
+                  (unsigned long)(d1),   \
+                  (unsigned long)(d2),   \
+                  (unsigned long)(d3),   \
+                  (unsigned long)(d4),   \
+                  (unsigned long)(d5));  \
     } while ( 0 )
 
 /* Convenience macros for calling the trace function. */

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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.