WARNING - OLD ARCHIVES

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

xen-changelog

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

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] merge with xen-unstable.hg
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 23 Mar 2007 05:30:42 -0700
Delivery-date: Fri, 23 Mar 2007 06:46:34 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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