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: Mon, 09 Apr 2007 12:30:29 -0700
Delivery-date: Mon, 09 Apr 2007 12:29:52 -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 Alex Williamson <alex.williamson@xxxxxx>
# Date 1175875710 21600
# Node ID eb3e430242ac8732d665b0a1f929bc324bc9fcdd
# Parent  9ec7dadc98ba1eadca8fe9c38ae6d6dd41d6d29d
# Parent  ef33477324f669037a1b35b719fa0a01e98ec2f3
merge with xen-unstable.hg
---
 tools/libxc/xc_hvm_restore.c                                        |  360 ---
 tools/libxc/xc_linux_restore.c                                      |  962 
--------
 .hgignore                                                           |    1 
 docs/Docs.mk                                                        |    1 
 docs/xen-api/Makefile                                               |    3 
 docs/xen-api/coversheet.tex                                         |   24 
 docs/xen-api/presentation.tex                                       |    2 
 docs/xen-api/vm-lifecycle.tex                                       |    2 
 docs/xen-api/wire-protocol.tex                                      |    2 
 docs/xen-api/xenapi-coversheet.tex                                  |   16 
 docs/xen-api/xenapi-datamodel-graph.dot                             |   55 
 docs/xen-api/xenapi-datamodel.tex                                   |  261 --
 docs/xen-api/xenapi.tex                                             |   10 
 extras/mini-os/xenbus/xenbus.c                                      |    2 
 linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S                    |    8 
 linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c                    |    2 
 linux-2.6-xen-sparse/arch/i386/mach-xen/setup.c                     |    4 
 linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c                      |   12 
 linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S                 |   61 
 linux-2.6-xen-sparse/arch/x86_64/kernel/head-xen.S                  |   11 
 linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c                      |    4 
 linux-2.6-xen-sparse/drivers/xen/Kconfig                            |   13 
 linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c                  |   38 
 linux-2.6-xen-sparse/drivers/xen/balloon/sysfs.c                    |    6 
 linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c                |    5 
 linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c               |    1 
 linux-2.6-xen-sparse/drivers/xen/core/reboot.c                      |    4 
 linux-2.6-xen-sparse/drivers/xen/core/xen_proc.c                    |    5 
 linux-2.6-xen-sparse/drivers/xen/fbfront/xenfb.c                    |    1 
 linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c                |    6 
 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h      |    8 
 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h     |   16 
 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/maddr.h          |    2 
 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/page.h           |   14 
 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-2level.h |   32 
 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-3level.h |   60 
 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable.h        |  107 
 linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h                  |    2 
 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h    |    8 
 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/maddr.h        |    2 
 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/page.h         |   12 
 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h      |  163 -
 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h  |    4 
 linux-2.6-xen-sparse/include/xen/hvm.h                              |    1 
 linux-2.6-xen-sparse/include/xen/hypercall.h                        |   24 
 tools/ioemu/hw/xen_platform.c                                       |    8 
 tools/ioemu/target-i386-dm/exec-dm.c                                |   10 
 tools/ioemu/target-i386-dm/helper2.c                                |   70 
 tools/ioemu/vl.c                                                    |   84 
 tools/ioemu/xenstore.c                                              |   14 
 tools/libxc/Makefile                                                |    4 
 tools/libxc/ia64/xc_ia64_linux_restore.c                            |   25 
 tools/libxc/xc_domain_restore.c                                     | 1086 
++++++++++
 tools/libxc/xc_hvm_save.c                                           |  407 +--
 tools/libxc/xenguest.h                                              |   27 
 tools/libxc/xg_private.c                                            |   15 
 tools/libxen/include/xen_host.h                                     |    7 
 tools/libxen/include/xen_sr.h                                       |   36 
 tools/libxen/include/xen_vdi.h                                      |   15 
 tools/libxen/src/xen_common.c                                       |   45 
 tools/libxen/src/xen_host.c                                         |   12 
 tools/libxen/src/xen_sr.c                                           |  105 
 tools/libxen/src/xen_vdi.c                                          |   33 
 tools/libxen/test/test_bindings.c                                   |   43 
 tools/python/xen/xend/XendAPI.py                                    |  132 -
 tools/python/xen/xend/XendCheckpoint.py                             |   21 
 tools/python/xen/xend/XendLocalStorageRepo.py                       |   17 
 tools/python/xen/xend/XendNode.py                                   |   39 
 tools/python/xen/xend/XendPBD.py                                    |   79 
 tools/python/xen/xend/XendQCoWStorageRepo.py                        |   23 
 tools/python/xen/xend/XendStateStore.py                             |    2 
 tools/python/xen/xend/XendStorageRepository.py                      |   13 
 tools/python/xen/xend/XendTask.py                                   |   10 
 tools/python/xen/xend/image.py                                      |    9 
 tools/python/xen/xm/main.py                                         |    2 
 tools/xcutils/xc_restore.c                                          |   34 
 unmodified_drivers/linux-2.6/Makefile                               |    1 
 unmodified_drivers/linux-2.6/balloon/Kbuild                         |    9 
 unmodified_drivers/linux-2.6/balloon/Makefile                       |    3 
 unmodified_drivers/linux-2.6/compat-include/xen/platform-compat.h   |   22 
 unmodified_drivers/linux-2.6/mkbuildtree                            |    3 
 unmodified_drivers/linux-2.6/overrides.mk                           |    3 
 unmodified_drivers/linux-2.6/platform-pci/platform-pci.c            |   10 
 unmodified_drivers/linux-2.6/platform-pci/xen_support.c             |    9 
 xen/arch/x86/hvm/hvm.c                                              |  113 -
 xen/arch/x86/hvm/io.c                                               |  227 +-
 xen/arch/x86/hvm/irq.c                                              |   15 
 xen/arch/x86/hvm/platform.c                                         |   32 
 xen/arch/x86/hvm/svm/svm.c                                          |  143 -
 xen/arch/x86/hvm/svm/vmcb.c                                         |    8 
 xen/arch/x86/hvm/vmx/vmx.c                                          |   18 
 xen/common/domain.c                                                 |    8 
 xen/common/memory.c                                                 |   11 
 xen/common/schedule.c                                               |    4 
 xen/drivers/char/ns16550.c                                          |    2 
 xen/include/asm-ia64/xentypes.h                                     |    5 
 xen/include/asm-powerpc/types.h                                     |    4 
 xen/include/asm-x86/event.h                                         |    7 
 xen/include/asm-x86/hvm/hvm.h                                       |   14 
 xen/include/asm-x86/hvm/io.h                                        |    3 
 xen/include/asm-x86/hvm/support.h                                   |    5 
 xen/include/asm-x86/types.h                                         |    4 
 xen/include/public/acm.h                                            |   16 
 xen/include/public/foreign/Makefile                                 |    2 
 xen/include/public/hvm/hvm_op.h                                     |    8 
 xen/include/public/hvm/ioreq.h                                      |    1 
 xen/include/xen/types.h                                             |    2 
 107 files changed, 2671 insertions(+), 2805 deletions(-)

diff -r 9ec7dadc98ba -r eb3e430242ac .hgignore
--- a/.hgignore Fri Apr 06 10:06:30 2007 -0600
+++ b/.hgignore Fri Apr 06 10:08:30 2007 -0600
@@ -14,6 +14,7 @@
 .*\.orig$
 .*\.rej$
 .*/a\.out$
+.*/Modules\.symvers$
 .*/cscope\..*$
 ^cscope.*$
 ^[^/]*\.bz2$
diff -r 9ec7dadc98ba -r eb3e430242ac docs/Docs.mk
--- a/docs/Docs.mk      Fri Apr 06 10:06:30 2007 -0600
+++ b/docs/Docs.mk      Fri Apr 06 10:08:30 2007 -0600
@@ -6,6 +6,7 @@ DOXYGEN         := doxygen
 DOXYGEN                := doxygen
 POD2MAN                := pod2man
 DOT            := dot
+NEATO          := neato
 
 pkgdocdir      := /usr/share/doc/xen
 mandir         := /usr/share/man
diff -r 9ec7dadc98ba -r eb3e430242ac docs/xen-api/Makefile
--- a/docs/xen-api/Makefile     Fri Apr 06 10:06:30 2007 -0600
+++ b/docs/xen-api/Makefile     Fri Apr 06 10:08:30 2007 -0600
@@ -37,6 +37,9 @@ xenapi.dvi: $(TEX) $(EPS) $(EPSDOT)
 %.eps: %.dot
        $(DOT) -Tps $< >$@
 
+xenapi-datamodel-graph.eps: xenapi-datamodel-graph.dot
+       $(NEATO) -Goverlap=false -Tps $< >$@
+
 .PHONY: clean
 clean:
        rm -f *.pdf *.ps *.dvi *.aux *.log $(EPSDOT)
diff -r 9ec7dadc98ba -r eb3e430242ac docs/xen-api/coversheet.tex
--- a/docs/xen-api/coversheet.tex       Fri Apr 06 10:06:30 2007 -0600
+++ b/docs/xen-api/coversheet.tex       Fri Apr 06 10:08:30 2007 -0600
@@ -1,5 +1,5 @@
 %
-% Copyright (c) 2006 XenSource, Inc.
+% Copyright (c) 2006-2007 XenSource, Inc.
 %
 % Permission is granted to copy, distribute and/or modify this document under
 % the terms of the GNU Free Documentation License, Version 1.2 or any later
@@ -20,7 +20,7 @@
 \begin{center}
 \resizebox{8cm}{!}{\includegraphics{\coversheetlogo}}
 
-\vspace{3cm}
+\vspace{2cm}
 
 \begin{Huge}
   \doctitle{}
@@ -37,9 +37,27 @@ Date: \datestring{}
 \begin{tabular}{rl}
 \docauthors{}
 \end{tabular}
-
 \end{Large}
 \end{center}
+\vspace{.5cm}
+\begin{large}
+\textbf{Contributors:}
+\begin{multicols}{2}{
+Stefan Berger, IBM \\
+Daniel Berrang\'e, Red Hat \\
+Gareth Bestor, IBM \\
+Hollis Blanchard, IBM \\
+Mike Day, IBM \\
+Jim Fehlig, Novell \\
+Jon Harrop, XenSource \\
+Vincent Hanquez, XenSource \\
+John Levon, Sun Microsystems \\
+Jon Ludlam, XenSource \\
+Alastair Tse, XenSource \\
+Daniel Veillard, Red Hat \\
+Tom Wilkie, University of Cambridge}
+\end{multicols}
+\end{large}
 
 \vfill
 
diff -r 9ec7dadc98ba -r eb3e430242ac docs/xen-api/presentation.tex
--- a/docs/xen-api/presentation.tex     Fri Apr 06 10:06:30 2007 -0600
+++ b/docs/xen-api/presentation.tex     Fri Apr 06 10:08:30 2007 -0600
@@ -1,5 +1,5 @@
 %
-% Copyright (c) 2006 XenSource, Inc.
+% Copyright (c) 2006-2007 XenSource, Inc.
 %
 % Permission is granted to copy, distribute and/or modify this document under
 % the terms of the GNU Free Documentation License, Version 1.2 or any later
diff -r 9ec7dadc98ba -r eb3e430242ac docs/xen-api/vm-lifecycle.tex
--- a/docs/xen-api/vm-lifecycle.tex     Fri Apr 06 10:06:30 2007 -0600
+++ b/docs/xen-api/vm-lifecycle.tex     Fri Apr 06 10:08:30 2007 -0600
@@ -1,5 +1,5 @@
 %
-% Copyright (c) 2006 XenSource, Inc.
+% Copyright (c) 2006-2007 XenSource, Inc.
 %
 % Permission is granted to copy, distribute and/or modify this document under
 % the terms of the GNU Free Documentation License, Version 1.2 or any later
diff -r 9ec7dadc98ba -r eb3e430242ac docs/xen-api/wire-protocol.tex
--- a/docs/xen-api/wire-protocol.tex    Fri Apr 06 10:06:30 2007 -0600
+++ b/docs/xen-api/wire-protocol.tex    Fri Apr 06 10:08:30 2007 -0600
@@ -1,5 +1,5 @@
 %
-% Copyright (c) 2006 XenSource, Inc.
+% Copyright (c) 2006-2007 XenSource, Inc.
 %
 % Permission is granted to copy, distribute and/or modify this document under
 % the terms of the GNU Free Documentation License, Version 1.2 or any later
diff -r 9ec7dadc98ba -r eb3e430242ac docs/xen-api/xenapi-coversheet.tex
--- a/docs/xen-api/xenapi-coversheet.tex        Fri Apr 06 10:06:30 2007 -0600
+++ b/docs/xen-api/xenapi-coversheet.tex        Fri Apr 06 10:08:30 2007 -0600
@@ -1,5 +1,5 @@
 %
-% Copyright (c) 2006 XenSource, Inc.
+% Copyright (c) 2006-2007 XenSource, Inc.
 %
 % Permission is granted to copy, distribute and/or modify this document under
 % the terms of the GNU Free Documentation License, Version 1.2 or any later
@@ -12,26 +12,24 @@
 %
 
 %% Document title
-\newcommand{\doctitle}{Xen Management API Draft}
+\newcommand{\doctitle}{Xen Management API}
 
 \newcommand{\coversheetlogo}{xen.eps}
 
 %% Document date
-\newcommand{\datestring}{25th August 2006}
+\newcommand{\datestring}{5th April 2007}
 
-\newcommand{\releasestatement}{Open Preview Release\\Comments are welcome!}
+\newcommand{\releasestatement}{Candidate for Release\\Comments are welcome!}
 
 %% Document revision
-\newcommand{\revstring}{API Revision 0.4.3 (Draft for discussion)}
+\newcommand{\revstring}{API Revision 0.9.0}
 
 %% Document authors
 \newcommand{\docauthors}{
 Ewan Mellor: & {\tt ewan@xxxxxxxxxxxxx} \\
 Richard Sharp: & {\tt richard.sharp@xxxxxxxxxxxxx} \\
-David Scott: & {\tt david.scott@xxxxxxxxxxxxx} \\
-Jon Harrop: & {\tt jon.harrop@xxxxxxxxxxxxx}
-}
-\newcommand{\legalnotice}{Copyright \copyright{} 2006 XenSource, Inc.\\ \\
+David Scott: & {\tt david.scott@xxxxxxxxxxxxx}}
+\newcommand{\legalnotice}{Copyright \copyright{} 2006-2007 XenSource, Inc.\\ \\
 Permission is granted to copy, distribute and/or modify this document under
 the terms of the GNU Free Documentation License, Version 1.2 or any later
 version published by the Free Software Foundation; with no Invariant Sections,
diff -r 9ec7dadc98ba -r eb3e430242ac docs/xen-api/xenapi-datamodel-graph.dot
--- a/docs/xen-api/xenapi-datamodel-graph.dot   Fri Apr 06 10:06:30 2007 -0600
+++ b/docs/xen-api/xenapi-datamodel-graph.dot   Fri Apr 06 10:08:30 2007 -0600
@@ -1,18 +1,39 @@ digraph g{
-digraph g{
-node [ shape=box ]; session [ URL="session.html" ] task [ URL="task.html" ] VM 
[ URL="VM.html" ] host [ URL="host.html" ] host_cpu [ URL="host_cpu.html" ] 
network [ URL="network.html" ] VIF [ URL="VIF.html" ] PIF [ URL="PIF.html" ] SR 
[ URL="SR.html" ] VDI [ URL="VDI.html" ] VBD [ URL="VBD.html" ] VTPM [ 
URL="VTPM.html" ] console [ URL="console.html" ] user [ URL="user.html" ] debug 
[ URL="debug.html" ];
-session -> host [ label="this_host(1)" ]
-session -> user [ label="this_user(1)" ]
-host -> VM [ color="blue", arrowhead="crow", arrowtail="none" ]
-host -> host_cpu [ color="blue", arrowhead="crow", arrowtail="none" ]
-VIF -> VM [ color="blue", arrowhead="none", arrowtail="crow" ]
-VIF -> network [ color="blue", arrowhead="none", arrowtail="crow" ]
-PIF -> host [ color="blue", arrowhead="none", arrowtail="crow" ]
-PIF -> network [ color="blue", arrowhead="none", arrowtail="crow" ]
-SR -> VDI [ color="blue", arrowhead="crow", arrowtail="none" ]
-VDI -> VBD [ color="blue", arrowhead="crow", arrowtail="none" ]
-VDI -> VDI [ color="blue", arrowhead="none", arrowtail="crow" ]
-VBD -> VM [ color="blue", arrowhead="none", arrowtail="crow" ]
-VTPM -> VM [ label="backend(1)" ]
-VTPM -> VM [ color="blue", arrowhead="none", arrowtail="crow" ]
-console -> VM [ color="blue", arrowhead="none", arrowtail="crow" ]
+#
+# Copyright (c) 2006-2007 XenSource, Inc.
+#
+# Permission is granted to copy, distribute and/or modify this document under
+# the terms of the GNU Free Documentation License, Version 1.2 or any later
+# version published by the Free Software Foundation; with no Invariant
+# Sections, no Front-Cover Texts and no Back-Cover Texts.  A copy of the
+# license is included in the section entitled
+# "GNU Free Documentation License" or the file fdl.tex.
+#
+
+digraph "Xen-API Class Diagram" {
+fontname="Verdana";
+
+node [ shape=box ]; session VM host network VIF PIF SR VDI VBD PBD user;
+node [shape=ellipse]; PIF_metrics VIF_metrics VM_metrics VBD_metrics 
PBD_metrics VM_guest_metrics host_metrics;
+node [shape=box]; host_cpu console
+session -> host [ arrowhead="none" ]
+session -> user [ arrowhead="none" ]
+VM -> VM_metrics [ arrowhead="none" ]
+VM -> VM_guest_metrics [ arrowhead="none" ]
+VM -> console [ arrowhead="crow" ]
+host -> PBD [ arrowhead="crow", arrowtail="none" ]
+host -> host_metrics [ arrowhead="none" ]
+host -> host_cpu [ arrowhead="none" ]
+VIF -> VM [ arrowhead="none", arrowtail="crow" ]
+VIF -> network [ arrowhead="none", arrowtail="crow" ]
+VIF -> VIF_metrics [ arrowhead="none" ]
+PIF -> host [ arrowhead="none", arrowtail="crow" ]
+PIF -> network [ arrowhead="none", arrowtail="crow" ]
+PIF -> PIF_metrics [ arrowhead="none" ]
+SR -> PBD [ arrowhead="crow", arrowtail="none" ]
+PBD -> PBD_metrics [ arrowhead="none" ]
+SR -> VDI [ arrowhead="crow", arrowtail="none" ]
+VDI -> VBD [ arrowhead="crow", arrowtail="none" ]
+VBD -> VM [ arrowhead="none", arrowtail="crow" ]
+VTPM -> VM [ arrowhead="none", arrowtail="crow" ]
+VBD -> VBD_metrics [ arrowhead="none" ]
 }
diff -r 9ec7dadc98ba -r eb3e430242ac docs/xen-api/xenapi-datamodel.tex
--- a/docs/xen-api/xenapi-datamodel.tex Fri Apr 06 10:06:30 2007 -0600
+++ b/docs/xen-api/xenapi-datamodel.tex Fri Apr 06 10:08:30 2007 -0600
@@ -1,5 +1,5 @@
 %
-% Copyright (c) 2006 XenSource, Inc.
+% Copyright (c) 2006-2007 XenSource, Inc.
 %
 % Permission is granted to copy, distribute and/or modify this document under
 % the terms of the GNU Free Documentation License, Version 1.2 or any later
@@ -512,7 +512,6 @@ Quals & Field & Type & Description \\
 $\mathit{RO}_\mathit{run}$ &  {\tt progress} & int & if the task is still 
pending, this field contains the estimated percentage complete (0-100). If task 
has completed (successfully or unsuccessfully) this should be 100. \\
 $\mathit{RO}_\mathit{run}$ &  {\tt type} & string & if the task has completed 
successfully, this field contains the type of the encoded result (i.e. name of 
the class whose reference is in the result field). Undefined otherwise. \\
 $\mathit{RO}_\mathit{run}$ &  {\tt result} & string & if the task has 
completed successfully, this field contains the result value (either Void or an 
object reference). Undefined otherwise. \\
-$\mathit{RO}_\mathit{run}$ &  {\tt error\_code} & int & if the task has 
failed, this field contains the error code. Undefined otherwise. \\
 $\mathit{RO}_\mathit{run}$ &  {\tt error\_info} & string Set & if the task has 
failed, this field contains the set of associated error strings. Undefined 
otherwise. \\
 $\mathit{RO}_\mathit{run}$ &  {\tt allowed\_operations} & 
(task\_allowed\_operations) Set & Operations allowed on this task \\
 \hline
@@ -826,38 +825,6 @@ Get the result field of the given task.
  \noindent {\bf Return Type:} 
 {\tt 
 string
-}
-
-
-value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~get\_error\_code}
-
-{\bf Overview:} 
-Get the error\_code field of the given task.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} int get_error_code (session_id s, task 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 task ref } & self & reference to the object \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-int
 }
 
 
@@ -4952,6 +4919,27 @@ dmesg string
 \vspace{0.3cm}
 \vspace{0.3cm}
 \vspace{0.3cm}
+\subsubsection{RPC name:~list\_methods}
+
+{\bf Overview:} 
+List all supported methods.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} (string Set) list_methods (session_id s)\end{verbatim}
+
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+string Set
+}
+
+
+The name of every supported method.
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
 \subsubsection{RPC name:~get\_all}
 
 {\bf Overview:} 
@@ -9190,51 +9178,35 @@ Quals & Field & Type & Description \\
 $\mathit{RO}_\mathit{run}$ &  {\tt physical\_utilisation} & int & physical 
space currently utilised on this storage repository (in bytes). Note that for 
sparse disk formats, physical\_utilisation may be less than virtual\_allocation 
\\
 $\mathit{RO}_\mathit{ins}$ &  {\tt physical\_size} & int & total physical size 
of the repository (in bytes) \\
 $\mathit{RO}_\mathit{ins}$ &  {\tt type} & string & type of the storage 
repository \\
-$\mathit{RO}_\mathit{ins}$ &  {\tt location} & string & a string that uniquely 
determines the location of the storage repository; the format of this string 
depends on the repository's type \\
+$\mathit{RO}_\mathit{ins}$ &  {\tt content\_type} & string & the type of the 
SR's content, if required (e.g. ISOs) \\
 \hline
 \end{longtable}
 \subsection{RPCs associated with class: SR}
-\subsubsection{RPC name:~clone}
-
-{\bf Overview:} 
-Take an exact copy of the Storage Repository;
-        the cloned storage repository has the same type as its parent
-
- \noindent {\bf Signature:} 
-\begin{verbatim} (SR ref) clone (session_id s, SR ref sr, string loc, string 
name)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt SR ref } & sr & The Storage Repository to clone \\ \hline 
-
-{\tt string } & loc & The location string that defines where the new storage 
repository will be located \\ \hline 
-
-{\tt string } & name & The name of the new storage repository \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-SR ref
-}
-
-
-The ID of the newly created Storage Repository.
+\subsubsection{RPC name:~get\_supported\_types}
+
+{\bf Overview:} 
+Return a set of all the SR types supported by the system.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} (string Set) get_supported_types (session_id s)\end{verbatim}
+
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+string Set
+}
+
+
+the supported SR types
 \vspace{0.3cm}
 \vspace{0.3cm}
 \vspace{0.3cm}
 \subsubsection{RPC name:~get\_all}
 
 {\bf Overview:} 
-Return a list of all the Storage Repositories known to the system
+Return a list of all the SRs known to the system.
 
  \noindent {\bf Signature:} 
 \begin{verbatim} ((SR ref) Set) get_all (session_id s)\end{verbatim}
@@ -9248,7 +9220,7 @@ Return a list of all the Storage Reposit
 }
 
 
-A list of all the IDs of all the Storage Repositories
+references to all objects
 \vspace{0.3cm}
 \vspace{0.3cm}
 \vspace{0.3cm}
@@ -9608,13 +9580,13 @@ value of the field
 \vspace{0.3cm}
 \vspace{0.3cm}
 \vspace{0.3cm}
-\subsubsection{RPC name:~get\_location}
-
-{\bf Overview:} 
-Get the location field of the given SR.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} string get_location (session_id s, SR ref self)\end{verbatim}
+\subsubsection{RPC name:~get\_content\_type}
+
+{\bf Overview:} 
+Get the content\_type field of the given SR.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} string get_content_type (session_id s, SR ref 
self)\end{verbatim}
 
 
 \noindent{\bf Arguments:}
@@ -9637,70 +9609,6 @@ string
 
 
 value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~create}
-
-{\bf Overview:} 
-Create a new SR instance, and return its handle.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} (SR ref) create (session_id s, SR record args)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt SR record } & args & All constructor arguments \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-SR ref
-}
-
-
-reference to the newly created object
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~destroy}
-
-{\bf Overview:} 
-Destroy the specified SR instance.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} void destroy (session_id s, SR 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 SR ref } & self & reference to the object \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-void
-}
-
-
-
 \vspace{0.3cm}
 \vspace{0.3cm}
 \vspace{0.3cm}
@@ -9828,73 +9736,6 @@ Quals & Field & Type & Description \\
 \hline
 \end{longtable}
 \subsection{RPCs associated with class: VDI}
-\subsubsection{RPC name:~snapshot}
-
-{\bf Overview:} 
-Take an exact copy of the VDI; the snapshot lives in the same Storage
-Repository as its parent.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} (VDI ref) snapshot (session_id s, VDI ref vdi)\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 } & vdi & The VDI to snapshot \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-VDI ref
-}
-
-
-The ID of the newly created VDI.
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~resize}
-
-{\bf Overview:} 
-Resize the vdi to the size.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} void resize (session_id s, VDI ref vdi, int 
size)\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 } & vdi & The VDI to resize \\ \hline 
-
-{\tt int } & size & The new size of the VDI \\ \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\_all}
 
 {\bf Overview:} 
@@ -11988,7 +11829,7 @@ Quals & Field & Type & Description \\
 $\mathit{RO}_\mathit{run}$ &  {\tt uuid} & string & unique identifier/object 
reference \\
 $\mathit{RO}_\mathit{ins}$ &  {\tt host} & host ref & physical machine on 
which the pbd is available \\
 $\mathit{RO}_\mathit{ins}$ &  {\tt SR} & SR ref & the storage repository that 
the pbd realises \\
-$\mathit{RO}_\mathit{ins}$ &  {\tt device\_config} & (string $\rightarrow$ 
string) Map & a config string that is provided to the host's SR-backend-driver 
\\
+$\mathit{RO}_\mathit{ins}$ &  {\tt device\_config} & (string $\rightarrow$ 
string) Map & a config string to string map that is provided to the host's 
SR-backend-driver \\
 $\mathit{RO}_\mathit{run}$ &  {\tt currently\_attached} & bool & is the SR 
currently attached on this host? \\
 \hline
 \end{longtable}
diff -r 9ec7dadc98ba -r eb3e430242ac docs/xen-api/xenapi.tex
--- a/docs/xen-api/xenapi.tex   Fri Apr 06 10:06:30 2007 -0600
+++ b/docs/xen-api/xenapi.tex   Fri Apr 06 10:08:30 2007 -0600
@@ -1,5 +1,5 @@
 %
-% Copyright (c) 2006 XenSource, Inc.
+% Copyright (c) 2006-2007 XenSource, Inc.
 %
 % Permission is granted to copy, distribute and/or modify this document under
 % the terms of the GNU Free Documentation License, Version 1.2 or any later
@@ -17,6 +17,7 @@
 \usepackage{graphics}
 \usepackage{longtable}
 \usepackage{fancyhdr}
+\usepackage{multicol}
 
 \setlength\topskip{0cm}
 \setlength\topmargin{0cm}
@@ -40,17 +41,10 @@ remotely configuring and controlling vir
 remotely configuring and controlling virtualised guests running on a
 Xen-enabled host. 
 
-~
-
-{\bf \large This document is an early draft for discussion purposes only.}
-
-~
-
 \input{presentation}
 
 \include{wire-protocol}
 \include{vm-lifecycle}
-\include{todo}
 \include{xenapi-datamodel}
 \include{fdl}
 
diff -r 9ec7dadc98ba -r eb3e430242ac extras/mini-os/xenbus/xenbus.c
--- a/extras/mini-os/xenbus/xenbus.c    Fri Apr 06 10:06:30 2007 -0600
+++ b/extras/mini-os/xenbus/xenbus.c    Fri Apr 06 10:08:30 2007 -0600
@@ -178,6 +178,7 @@ static void release_xenbus_id(int id)
 {
     BUG_ON(!req_info[id].in_use);
     spin_lock(&req_lock);
+    req_info[id].in_use = 0;
     nr_live_reqs--;
     req_info[id].in_use = 0;
     if (nr_live_reqs == NR_REQS - 1)
@@ -335,6 +336,7 @@ xenbus_msg_reply(int type,
     xb_write(type, id, trans, io, nr_reqs);
 
     schedule();
+    remove_waiter(w);
     wake(current);
 
     rep = req_info[id].reply;
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S
--- a/linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S  Fri Apr 06 10:06:30 
2007 -0600
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S  Fri Apr 06 10:08:30 
2007 -0600
@@ -142,7 +142,7 @@ ENTRY(cpu_gdt_table)
        .quad 0x0000000000000000        /* 0xf0 - unused */
        .quad 0x0000000000000000        /* 0xf8 - GDT entry 31: double-fault 
TSS */
 
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
 /*
  * __xen_guest information
  */
@@ -180,18 +180,18 @@ ENTRY(cpu_gdt_table)
 #endif
        .ascii  ",LOADER=generic"
        .byte   0
-#endif /* CONFIG_XEN_COMPAT_030002 */
+#endif /* CONFIG_XEN_COMPAT <= 0x030002 */
 
 
        ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS,       .asciz, "linux")       
        ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION,  .asciz, "2.6")
        ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION,    .asciz, "xen-3.0")
        ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE,      .long,  __PAGE_OFFSET)
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
        ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .long,  __PAGE_OFFSET)
 #else
        ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .long,  0)
-#endif /* !CONFIG_XEN_COMPAT_030002 */
+#endif
        ELFNOTE(Xen, XEN_ELFNOTE_ENTRY,          .long,  startup_32)
        ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, .long,  hypercall_page)
        ELFNOTE(Xen, XEN_ELFNOTE_HV_START_LOW,   .long,  HYPERVISOR_VIRT_START)
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c  Fri Apr 06 10:06:30 
2007 -0600
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c  Fri Apr 06 10:08:30 
2007 -0600
@@ -1010,7 +1010,7 @@ static void stop_hz_timer(void)
        singleshot.timeout_abs_ns = jiffies_to_st(j);
        singleshot.flags = 0;
        rc = HYPERVISOR_vcpu_op(VCPUOP_set_singleshot_timer, cpu, &singleshot);
-#ifdef CONFIG_XEN_COMPAT_030004
+#if CONFIG_XEN_COMPAT <= 0x030004
        if (rc) {
                BUG_ON(rc != -ENOSYS);
                rc = HYPERVISOR_set_timer_op(singleshot.timeout_abs_ns);
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/arch/i386/mach-xen/setup.c
--- a/linux-2.6-xen-sparse/arch/i386/mach-xen/setup.c   Fri Apr 06 10:06:30 
2007 -0600
+++ b/linux-2.6-xen-sparse/arch/i386/mach-xen/setup.c   Fri Apr 06 10:08:30 
2007 -0600
@@ -114,7 +114,7 @@ void __init machine_specific_arch_setup(
        ret = HYPERVISOR_callback_op(CALLBACKOP_register, &event);
        if (ret == 0)
                ret = HYPERVISOR_callback_op(CALLBACKOP_register, &failsafe);
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
        if (ret == -ENOSYS)
                ret = HYPERVISOR_set_callbacks(
                        event.address.cs, event.address.eip,
@@ -123,7 +123,7 @@ void __init machine_specific_arch_setup(
        BUG_ON(ret);
 
        ret = HYPERVISOR_callback_op(CALLBACKOP_register, &nmi_cb);
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
        if (ret == -ENOSYS) {
                static struct xennmi_callback __initdata cb = {
                        .handler_address = (unsigned long)nmi
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c
--- a/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c    Fri Apr 06 10:06:30 
2007 -0600
+++ b/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c    Fri Apr 06 10:08:30 
2007 -0600
@@ -303,7 +303,7 @@ int xen_create_contiguous_region(
                set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i,
                        INVALID_P2M_ENTRY);
        }
-       if (HYPERVISOR_multicall(cr_mcl, i))
+       if (HYPERVISOR_multicall_check(cr_mcl, i, NULL))
                BUG();
 
        /* 2. Get a new contiguous memory extent. */
@@ -312,7 +312,7 @@ int xen_create_contiguous_region(
        success = (exchange.nr_exchanged == (1UL << order));
        BUG_ON(!success && ((exchange.nr_exchanged != 0) || (rc == 0)));
        BUG_ON(success && (rc != 0));
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
        if (unlikely(rc == -ENOSYS)) {
                /* Compatibility when XENMEM_exchange is unsupported. */
                if (HYPERVISOR_memory_op(XENMEM_decrease_reservation,
@@ -342,7 +342,7 @@ int xen_create_contiguous_region(
        cr_mcl[i - 1].args[MULTI_UVMFLAGS_INDEX] = order
                                                   ? UVMF_TLB_FLUSH|UVMF_ALL
                                                   : UVMF_INVLPG|UVMF_ALL;
-       if (HYPERVISOR_multicall(cr_mcl, i))
+       if (HYPERVISOR_multicall_check(cr_mcl, i, NULL))
                BUG();
 
        if (success)
@@ -400,7 +400,7 @@ void xen_destroy_contiguous_region(unsig
                        INVALID_P2M_ENTRY);
                out_frames[i] = (__pa(vstart) >> PAGE_SHIFT) + i;
        }
-       if (HYPERVISOR_multicall(cr_mcl, i))
+       if (HYPERVISOR_multicall_check(cr_mcl, i, NULL))
                BUG();
 
        /* 3. Do the exchange for non-contiguous MFNs. */
@@ -408,7 +408,7 @@ void xen_destroy_contiguous_region(unsig
        success = (exchange.nr_exchanged == 1);
        BUG_ON(!success && ((exchange.nr_exchanged != 0) || (rc == 0)));
        BUG_ON(success && (rc != 0));
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
        if (unlikely(rc == -ENOSYS)) {
                /* Compatibility when XENMEM_exchange is unsupported. */
                if (HYPERVISOR_memory_op(XENMEM_decrease_reservation,
@@ -432,7 +432,7 @@ void xen_destroy_contiguous_region(unsig
        cr_mcl[i - 1].args[MULTI_UVMFLAGS_INDEX] = order
                                                   ? UVMF_TLB_FLUSH|UVMF_ALL
                                                   : UVMF_INVLPG|UVMF_ALL;
-       if (HYPERVISOR_multicall(cr_mcl, i))
+       if (HYPERVISOR_multicall_check(cr_mcl, i, NULL))
                BUG();
 
        balloon_unlock(flags);
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S
--- a/linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S       Fri Apr 06 
10:06:30 2007 -0600
+++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S       Fri Apr 06 
10:08:30 2007 -0600
@@ -201,6 +201,19 @@ END(ret_from_fork)
 END(ret_from_fork)
 
 /*
+ * initial frame state for interrupts and exceptions
+ */
+       .macro _frame ref
+       CFI_STARTPROC simple
+       CFI_DEF_CFA rsp,SS+8-\ref
+       /*CFI_REL_OFFSET ss,SS-\ref*/
+       CFI_REL_OFFSET rsp,RSP-\ref
+       /*CFI_REL_OFFSET rflags,EFLAGS-\ref*/
+       /*CFI_REL_OFFSET cs,CS-\ref*/
+       CFI_REL_OFFSET rip,RIP-\ref
+       .endm
+
+/*
  * System call entry. Upto 6 arguments in registers are supported.
  *
  * SYSCALL does not save anything on the stack and does not change the
@@ -232,10 +245,7 @@ END(ret_from_fork)
  */                                    
 
 ENTRY(system_call)
-       CFI_STARTPROC   simple
-       CFI_DEF_CFA     rsp,PDA_STACKOFFSET
-       CFI_REGISTER    rip,rcx
-       /*CFI_REGISTER  rflags,r11*/
+       _frame (RIP-0x10)
        SAVE_ARGS -8,0
        movq  %rax,ORIG_RAX-ARGOFFSET(%rsp) 
        /*
@@ -273,9 +283,7 @@ sysret_check:
         */
        TRACE_IRQS_ON
         XEN_UNBLOCK_EVENTS(%rsi)                
-       CFI_REGISTER    rip,rcx
        RESTORE_ARGS 0,8,0
-       /*CFI_REGISTER  rflags,r11*/
         HYPERVISOR_IRET VGCF_IN_SYSCALL
 
        /* Handle reschedules */
@@ -505,24 +513,16 @@ ENTRY(stub_rt_sigreturn)
        CFI_ENDPROC
 END(stub_rt_sigreturn)
 
-/*
- * initial frame state for interrupts and exceptions
- */
-       .macro _frame ref
-       CFI_STARTPROC simple
-       CFI_DEF_CFA rsp,SS+8-\ref
-       /*CFI_REL_OFFSET ss,SS-\ref*/
-       CFI_REL_OFFSET rsp,RSP-\ref
-       /*CFI_REL_OFFSET rflags,EFLAGS-\ref*/
-       /*CFI_REL_OFFSET cs,CS-\ref*/
-       CFI_REL_OFFSET rip,RIP-\ref
-       .endm
-
 /* initial frame state for interrupts (and exceptions without error code) */
-#define INTR_FRAME _frame RIP
+#define INTR_FRAME _frame (RIP-0x10); \
+       CFI_REL_OFFSET rcx,0; \
+       CFI_REL_OFFSET r11,8
+
 /* initial frame state for exceptions with error code (and interrupts with
    vector already pushed) */
-#define XCPT_FRAME _frame ORIG_RAX
+#define XCPT_FRAME _frame (RIP-0x18); \
+       CFI_REL_OFFSET rcx,0; \
+       CFI_REL_OFFSET r11,8
 
 /* 
  * Interrupt exit.
@@ -599,8 +599,9 @@ retint_kernel:
 #endif 
 
        CFI_ENDPROC
-END(common_interrupt)
-       
+END(retint_check)
+       
+#ifndef CONFIG_XEN
 /*
  * APIC interrupts.
  */            
@@ -613,7 +614,6 @@ END(common_interrupt)
        CFI_ENDPROC
        .endm
 
-#ifndef CONFIG_XEN
 ENTRY(thermal_interrupt)
        apicinterrupt THERMAL_APIC_VECTOR,smp_thermal_interrupt
 END(thermal_interrupt)
@@ -668,12 +668,16 @@ END(spurious_interrupt)
        .macro zeroentry sym
        INTR_FRAME
         movq (%rsp),%rcx
+       CFI_RESTORE rcx
         movq 8(%rsp),%r11
+       CFI_RESTORE r11
         addq $0x10,%rsp /* skip rcx and r11 */
+       CFI_ADJUST_CFA_OFFSET -0x10
        pushq $0        /* push error code/oldrax */ 
        CFI_ADJUST_CFA_OFFSET 8
        pushq %rax      /* push real oldrax to the rdi slot */ 
        CFI_ADJUST_CFA_OFFSET 8
+       CFI_REL_OFFSET rax,0
        leaq  \sym(%rip),%rax
        jmp error_entry
        CFI_ENDPROC
@@ -682,10 +686,14 @@ END(spurious_interrupt)
        .macro errorentry sym
        XCPT_FRAME
         movq (%rsp),%rcx
+       CFI_RESTORE rcx
         movq 8(%rsp),%r11
+       CFI_RESTORE r11
         addq $0x10,%rsp /* rsp points to the error code */
+       CFI_ADJUST_CFA_OFFSET -0x10
        pushq %rax
        CFI_ADJUST_CFA_OFFSET 8
+       CFI_REL_OFFSET rax,0
        leaq  \sym(%rip),%rax
        jmp error_entry
        CFI_ENDPROC
@@ -799,6 +807,7 @@ paranoid_schedule\trace:
  */                                            
 ENTRY(error_entry)
        _frame RDI
+       CFI_REL_OFFSET rax,0
        /* rdi slot contains rax, oldrax contains error code */
        cld     
        subq  $14*8,%rsp
@@ -806,6 +815,7 @@ ENTRY(error_entry)
        movq %rsi,13*8(%rsp)
        CFI_REL_OFFSET  rsi,RSI
        movq 14*8(%rsp),%rsi    /* load rax from rdi slot */
+       CFI_REGISTER    rax,rsi
        movq %rdx,12*8(%rsp)
        CFI_REL_OFFSET  rdx,RDX
        movq %rcx,11*8(%rsp)
@@ -839,6 +849,7 @@ ENTRY(error_entry)
 #endif        
 error_call_handler:
        movq %rdi, RDI(%rsp)            
+       CFI_REL_OFFSET  rdi,RDI
        movq %rsp,%rdi
        movq ORIG_RAX(%rsp),%rsi        # get error code 
        movq $-1,ORIG_RAX(%rsp)
@@ -1186,7 +1197,7 @@ END(int3)
 
 ENTRY(overflow)
        zeroentry do_overflow
-END(debug)
+END(overflow)
 
 ENTRY(bounds)
        zeroentry do_bounds
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/arch/x86_64/kernel/head-xen.S
--- a/linux-2.6-xen-sparse/arch/x86_64/kernel/head-xen.S        Fri Apr 06 
10:06:30 2007 -0600
+++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/head-xen.S        Fri Apr 06 
10:08:30 2007 -0600
@@ -33,9 +33,6 @@ startup_64:
 startup_64:
 ENTRY(_start)
        movq $(init_thread_union+THREAD_SIZE-8),%rsp
-       /* zero EFLAGS after setting rsp */
-       pushq $0
-       popfq
 
        /* rsi is pointer to startup info structure.
           pass it to C */
@@ -155,7 +152,7 @@ ENTRY(empty_zero_page)
 ENTRY(empty_zero_page)
        .skip PAGE_SIZE
 
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
 /*
  * __xen_guest information
  */
@@ -187,17 +184,17 @@ ENTRY(empty_zero_page)
        .ascii           "|supervisor_mode_kernel"
        .ascii  ",LOADER=generic"
        .byte   0
-#endif /* CONFIG_XEN_COMPAT_030002 */
+#endif /* CONFIG_XEN_COMPAT <= 0x030002 */
        
        ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS,       .asciz, "linux")
        ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION,  .asciz, "2.6")
        ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION,    .asciz, "xen-3.0")
        ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE,      .quad,  __START_KERNEL_map)
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
        ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .quad,  __START_KERNEL_map)
 #else
        ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .quad,  0)
-#endif /* !CONFIG_XEN_COMPAT_030002 */
+#endif
        ELFNOTE(Xen, XEN_ELFNOTE_ENTRY,          .quad,  startup_64)
        ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, .quad,  hypercall_page)
        ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID,   .quad,  
_PAGE_PRESENT,_PAGE_PRESENT)
diff -r 9ec7dadc98ba -r eb3e430242ac 
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    Fri Apr 06 10:06:30 
2007 -0600
+++ b/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c    Fri Apr 06 10:08:30 
2007 -0600
@@ -54,7 +54,7 @@ struct dma_mapping_ops* dma_ops;
 struct dma_mapping_ops* dma_ops;
 EXPORT_SYMBOL(dma_ops);
 
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
 unsigned int __kernel_page_user;
 EXPORT_SYMBOL(__kernel_page_user);
 #endif
@@ -551,7 +551,7 @@ void __init xen_init_pt(void)
        addr = page[pud_index(__START_KERNEL_map)];
        addr_to_page(addr, page);
 
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
        /* On Xen 3.0.2 and older we may need to explicitly specify _PAGE_USER
           in kernel PTEs. We check that here. */
        if (HYPERVISOR_xen_version(XENVER_version, NULL) <= 0x30000) {
diff -r 9ec7dadc98ba -r eb3e430242ac linux-2.6-xen-sparse/drivers/xen/Kconfig
--- a/linux-2.6-xen-sparse/drivers/xen/Kconfig  Fri Apr 06 10:06:30 2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/Kconfig  Fri Apr 06 10:08:30 2007 -0600
@@ -235,13 +235,12 @@ choice
 
 endchoice
 
-config XEN_COMPAT_030002
-       bool
-       default XEN_COMPAT_030002_AND_LATER
-
-config XEN_COMPAT_030004
-       bool
-       default XEN_COMPAT_030002_AND_LATER || XEN_COMPAT_030004_AND_LATER
+config XEN_COMPAT
+       hex
+       default 0xffffff if XEN_COMPAT_LATEST_ONLY
+       default 0x030004 if XEN_COMPAT_030004_AND_LATER
+       default 0x030002 if XEN_COMPAT_030002_AND_LATER
+       default 0
 
 endmenu
 
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c
--- a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c        Fri Apr 06 
10:06:30 2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c        Fri Apr 06 
10:08:30 2007 -0600
@@ -48,13 +48,20 @@
 #include <asm/hypervisor.h>
 #include <xen/balloon.h>
 #include <xen/interface/memory.h>
+#include <asm/maddr.h>
+#include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
 #include <asm/tlb.h>
+#include <linux/highmem.h>
 #include <linux/list.h>
 #include <xen/xenbus.h>
 #include "common.h"
+
+#ifdef HAVE_XEN_PLATFORM_COMPAT_H
+#include <xen/platform-compat.h>
+#endif
 
 #ifdef CONFIG_PROC_FS
 static struct proc_dir_entry *balloon_pde;
@@ -217,6 +224,7 @@ static int increase_reservation(unsigned
 
                set_phys_to_machine(pfn, frame_list[i]);
 
+#ifdef CONFIG_XEN
                /* Link back into the page tables if not highmem. */
                if (pfn < max_low_pfn) {
                        int ret;
@@ -226,6 +234,7 @@ static int increase_reservation(unsigned
                                0);
                        BUG_ON(ret);
                }
+#endif
 
                /* Relinquish the page back to the allocator. */
                ClearPageReserved(page);
@@ -271,9 +280,11 @@ static int decrease_reservation(unsigned
                if (!PageHighMem(page)) {
                        v = phys_to_virt(pfn << PAGE_SHIFT);
                        scrub_pages(v, 1);
+#ifdef CONFIG_XEN
                        ret = HYPERVISOR_update_va_mapping(
                                (unsigned long)v, __pte_ma(0), 0);
                        BUG_ON(ret);
+#endif
                }
 #ifdef CONFIG_XEN_SCRUB_PAGES
                else {
@@ -284,9 +295,11 @@ static int decrease_reservation(unsigned
 #endif
        }
 
+#ifdef CONFIG_XEN
        /* Ensure that ballooned highmem pages don't have kmaps. */
        kmap_flush_unused();
        flush_tlb_all();
+#endif
 
        balloon_lock(flags);
 
@@ -446,7 +459,7 @@ static struct notifier_block xenstore_no
 
 static int __init balloon_init(void)
 {
-#ifdef CONFIG_X86
+#if defined(CONFIG_X86) && defined(CONFIG_XEN) 
        unsigned long pfn;
        struct page *page;
 #endif
@@ -456,8 +469,12 @@ static int __init balloon_init(void)
 
        IPRINTK("Initialising balloon driver.\n");
 
+#ifdef CONFIG_XEN
        bs.current_pages = min(xen_start_info->nr_pages, max_pfn);
        totalram_pages   = bs.current_pages;
+#else 
+       bs.current_pages = totalram_pages; 
+#endif
        bs.target_pages  = bs.current_pages;
        bs.balloon_low   = 0;
        bs.balloon_high  = 0;
@@ -479,7 +496,7 @@ static int __init balloon_init(void)
 #endif
        balloon_sysfs_init();
 
-#ifdef CONFIG_X86
+#if defined(CONFIG_X86) && defined(CONFIG_XEN) 
        /* Initialise the balloon with excess memory space. */
        for (pfn = xen_start_info->nr_pages; pfn < max_pfn; pfn++) {
                page = pfn_to_page(pfn);
@@ -498,6 +515,14 @@ static int __init balloon_init(void)
 
 subsys_initcall(balloon_init);
 
+static void balloon_exit(void) 
+{
+    /* XXX - release balloon here */
+    return; 
+}
+
+module_exit(balloon_exit); 
+
 void balloon_update_driver_allowance(long delta)
 {
        unsigned long flags;
@@ -507,6 +532,7 @@ void balloon_update_driver_allowance(lon
        balloon_unlock(flags);
 }
 
+#ifdef CONFIG_XEN
 static int dealloc_pte_fn(
        pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
 {
@@ -524,6 +550,7 @@ static int dealloc_pte_fn(
        BUG_ON(ret != 1);
        return 0;
 }
+#endif
 
 struct page **alloc_empty_pages_and_pagevec(int nr_pages)
 {
@@ -559,8 +586,13 @@ struct page **alloc_empty_pages_and_page
                        if (ret == 1)
                                ret = 0; /* success */
                } else {
+#ifdef CONFIG_XEN
                        ret = apply_to_page_range(&init_mm, vaddr, PAGE_SIZE,
                                                  dealloc_pte_fn, NULL);
+#else
+                       /* Cannot handle non-auto translate mode. */
+                       ret = 1;
+#endif
                }
 
                if (ret != 0) {
@@ -576,7 +608,9 @@ struct page **alloc_empty_pages_and_page
 
  out:
        schedule_work(&balloon_worker);
+#ifdef CONFIG_XEN
        flush_tlb_all();
+#endif
        return pagevec;
 
  err:
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/drivers/xen/balloon/sysfs.c
--- a/linux-2.6-xen-sparse/drivers/xen/balloon/sysfs.c  Fri Apr 06 10:06:30 
2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/balloon/sysfs.c  Fri Apr 06 10:08:30 
2007 -0600
@@ -29,9 +29,15 @@
  */
 
 #include <linux/capability.h>
+#include <linux/errno.h>
 #include <linux/stat.h>
+#include <linux/string.h>
 #include <linux/sysdev.h>
 #include "common.h"
+
+#ifdef HAVE_XEN_PLATFORM_COMPAT_H
+#include <xen/platform-compat.h>
+#endif
 
 #define BALLOON_CLASS_NAME "memory"
 
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c      Fri Apr 06 
10:06:30 2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c      Fri Apr 06 
10:08:30 2007 -0600
@@ -661,9 +661,10 @@ void do_blkif_request(request_queue_t *r
                if (RING_FULL(&info->ring))
                        goto wait;
 
-               DPRINTK("do_blk_req %p: cmd %p, sec %lx, "
+               DPRINTK("do_blk_req %p: cmd %p, sec %llx, "
                        "(%u/%li) buffer:%p [%s]\n",
-                       req, req->cmd, req->sector, req->current_nr_sectors,
+                       req, req->cmd, (long long)req->sector,
+                       req->current_nr_sectors,
                        req->nr_sectors, req->buffer,
                        rq_data_dir(req) ? "write" : "read");
 
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c
--- a/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c     Fri Apr 06 
10:06:30 2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c     Fri Apr 06 
10:08:30 2007 -0600
@@ -7,7 +7,6 @@
 #include <xen/interface/kexec.h>
 #include <linux/mm.h>
 #include <linux/bootmem.h>
-#include <asm/hypercall.h>
 
 extern void machine_kexec_setup_load_arg(xen_kexec_image_t *xki, 
                                         struct kimage *image);
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/drivers/xen/core/reboot.c
--- a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c    Fri Apr 06 10:06:30 
2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c    Fri Apr 06 10:08:30 
2007 -0600
@@ -8,6 +8,10 @@
 #include <asm/hypervisor.h>
 #include <xen/xenbus.h>
 #include <linux/kthread.h>
+
+#ifdef HAVE_XEN_PLATFORM_COMPAT_H
+#include <xen/platform-compat.h>
+#endif
 
 MODULE_LICENSE("Dual BSD/GPL");
 
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/drivers/xen/core/xen_proc.c
--- a/linux-2.6-xen-sparse/drivers/xen/core/xen_proc.c  Fri Apr 06 10:06:30 
2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/core/xen_proc.c  Fri Apr 06 10:08:30 
2007 -0600
@@ -1,4 +1,5 @@
 
+#include <linux/module.h>
 #include <linux/proc_fs.h>
 #include <xen/xen_proc.h>
 
@@ -12,7 +13,11 @@ struct proc_dir_entry *create_xen_proc_e
        return create_proc_entry(name, mode, xen_base);
 }
 
+EXPORT_SYMBOL_GPL(create_xen_proc_entry); 
+
 void remove_xen_proc_entry(const char *name)
 {
        remove_proc_entry(name, xen_base);
 }
+
+EXPORT_SYMBOL_GPL(remove_xen_proc_entry); 
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/drivers/xen/fbfront/xenfb.c
--- a/linux-2.6-xen-sparse/drivers/xen/fbfront/xenfb.c  Fri Apr 06 10:06:30 
2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/fbfront/xenfb.c  Fri Apr 06 10:08:30 
2007 -0600
@@ -24,6 +24,7 @@
 #include <linux/module.h>
 #include <linux/vmalloc.h>
 #include <linux/mm.h>
+#include <linux/mutex.h>
 #include <asm/hypervisor.h>
 #include <xen/evtchn.h>
 #include <xen/interface/io/fbif.h>
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c      Fri Apr 06 
10:06:30 2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c      Fri Apr 06 
10:08:30 2007 -0600
@@ -1511,7 +1511,7 @@ static void netif_release_rx_bufs(struct
        struct sk_buff *skb;
        unsigned long mfn;
        int xfer = 0, noxfer = 0, unused = 0;
-       int id, ref;
+       int id, ref, rc;
 
        if (np->copying_receiver) {
                WPRINTK("%s: fix me for copying receiver.\n", __FUNCTION__);
@@ -1579,7 +1579,9 @@ static void netif_release_rx_bufs(struct
                        mcl->args[2] = 0;
                        mcl->args[3] = DOMID_SELF;
                        mcl++;
-                       HYPERVISOR_multicall(np->rx_mcl, mcl - np->rx_mcl);
+                       rc = HYPERVISOR_multicall_check(
+                               np->rx_mcl, mcl - np->rx_mcl, NULL);
+                       BUG_ON(rc);
                }
        }
 
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h    Fri Apr 
06 10:06:30 2007 -0600
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h    Fri Apr 
06 10:08:30 2007 -0600
@@ -238,7 +238,7 @@ HYPERVISOR_memory_op(
 
 static inline int
 HYPERVISOR_multicall(
-       void *call_list, int nr_calls)
+       multicall_entry_t *call_list, int nr_calls)
 {
        return _hypercall2(int, multicall, call_list, nr_calls);
 }
@@ -261,7 +261,7 @@ HYPERVISOR_event_channel_op(
 {
        int rc = _hypercall2(int, event_channel_op, cmd, arg);
 
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
        if (unlikely(rc == -ENOSYS)) {
                struct evtchn_op op;
                op.cmd = cmd;
@@ -301,7 +301,7 @@ HYPERVISOR_physdev_op(
 {
        int rc = _hypercall2(int, physdev_op, cmd, arg);
 
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
        if (unlikely(rc == -ENOSYS)) {
                struct physdev_op op;
                op.cmd = cmd;
@@ -358,7 +358,7 @@ HYPERVISOR_suspend(
        int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown,
                             &sched_shutdown, srec);
 
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
        if (rc == -ENOSYS)
                rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown,
                                 SHUTDOWN_suspend, srec);
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h   Fri Apr 
06 10:06:30 2007 -0600
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h   Fri Apr 
06 10:08:30 2007 -0600
@@ -122,7 +122,13 @@ void xen_destroy_contiguous_region(
 /* Turn jiffies into Xen system time. */
 u64 jiffies_to_st(unsigned long jiffies);
 
-#include <asm/hypercall.h>
+#ifdef CONFIG_XEN_SCRUB_PAGES
+#define scrub_pages(_p,_n) memset((void *)(_p), 0, (_n) << PAGE_SHIFT)
+#else
+#define scrub_pages(_p,_n) ((void)0)
+#endif
+
+#include <xen/hypercall.h>
 
 #if defined(CONFIG_X86_64)
 #define MULTI_UVMFLAGS_INDEX 2
@@ -140,7 +146,7 @@ HYPERVISOR_yield(
 {
        int rc = HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
 
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
        if (rc == -ENOSYS)
                rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0);
 #endif
@@ -154,7 +160,7 @@ HYPERVISOR_block(
 {
        int rc = HYPERVISOR_sched_op(SCHEDOP_block, NULL);
 
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
        if (rc == -ENOSYS)
                rc = HYPERVISOR_sched_op_compat(SCHEDOP_block, 0);
 #endif
@@ -172,7 +178,7 @@ HYPERVISOR_shutdown(
 
        int rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
 
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
        if (rc == -ENOSYS)
                rc = HYPERVISOR_sched_op_compat(SCHEDOP_shutdown, reason);
 #endif
@@ -192,7 +198,7 @@ HYPERVISOR_poll(
        set_xen_guest_handle(sched_poll.ports, ports);
 
        rc = HYPERVISOR_sched_op(SCHEDOP_poll, &sched_poll);
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
        if (rc == -ENOSYS)
                rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0);
 #endif
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/maddr.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/maddr.h        Fri Apr 
06 10:06:30 2007 -0600
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/maddr.h        Fri Apr 
06 10:08:30 2007 -0600
@@ -158,7 +158,7 @@ static inline paddr_t pte_machine_to_phy
 #define pfn_to_mfn(pfn) (pfn)
 #define mfn_to_pfn(mfn) (mfn)
 #define mfn_to_local_pfn(mfn) (mfn)
-#define set_phys_to_machine(pfn, mfn) BUG_ON((pfn) != (mfn))
+#define set_phys_to_machine(pfn, mfn) ((void)0)
 #define phys_to_machine_mapping_valid(pfn) (1)
 #define phys_to_machine(phys) ((maddr_t)(phys))
 #define machine_to_phys(mach) ((paddr_t)(mach))
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/page.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/page.h Fri Apr 06 
10:06:30 2007 -0600
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/page.h Fri Apr 06 
10:08:30 2007 -0600
@@ -44,12 +44,6 @@
        foreign;                                \
 })
 #define HAVE_ARCH_FREE_PAGE
-
-#ifdef CONFIG_XEN_SCRUB_PAGES
-#define scrub_pages(_p,_n) memset((void *)(_p), 0, (_n) << PAGE_SHIFT)
-#else
-#define scrub_pages(_p,_n) ((void)0)
-#endif
 
 #ifdef CONFIG_X86_USE_3DNOW
 
@@ -108,7 +102,7 @@ static inline unsigned long long pmd_val
 static inline unsigned long long pmd_val(pmd_t x)
 {
        unsigned long long ret = x.pmd;
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
        if (ret) ret = pte_machine_to_phys(ret) | _PAGE_PRESENT;
 #else
        if (ret & _PAGE_PRESENT) ret = pte_machine_to_phys(ret);
@@ -140,7 +134,7 @@ static inline unsigned long pgd_val(pgd_
 static inline unsigned long pgd_val(pgd_t x)
 {
        unsigned long ret = x.pgd;
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
        if (ret) ret = machine_to_phys(ret) | _PAGE_PRESENT;
 #else
        if (ret & _PAGE_PRESENT) ret = machine_to_phys(ret);
@@ -203,10 +197,10 @@ extern int page_is_ram(unsigned long pag
 #endif
 #define __KERNEL_START         (__PAGE_OFFSET + __PHYSICAL_START)
 
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
 #undef LOAD_OFFSET
 #define LOAD_OFFSET            0
-#endif /* CONFIG_XEN_COMPAT_030002 */
+#endif
 
 #define PAGE_OFFSET            ((unsigned long)__PAGE_OFFSET)
 #define VMALLOC_RESERVE                ((unsigned long)__VMALLOC_RESERVE)
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-2level.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-2level.h       
Fri Apr 06 10:06:30 2007 -0600
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-2level.h       
Fri Apr 06 10:08:30 2007 -0600
@@ -36,8 +36,37 @@
 #define pte_clear(mm,addr,xp)  do { set_pte_at(mm, addr, xp, __pte(0)); } 
while (0)
 #define pmd_clear(xp)  do { set_pmd(xp, __pmd(0)); } while (0)
 
-#define ptep_get_and_clear(mm,addr,xp) __pte_ma(xchg(&(xp)->pte_low, 0))
+#define pte_none(x) (!(x).pte_low)
+
+static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long 
addr, pte_t *ptep)
+{
+       pte_t pte = *ptep;
+       if (!pte_none(pte)) {
+               if (mm != &init_mm)
+                       pte = __pte_ma(xchg(&ptep->pte_low, 0));
+               else
+                       HYPERVISOR_update_va_mapping(addr, __pte(0), 0);
+       }
+       return pte;
+}
+
+#define ptep_clear_flush(vma, addr, ptep)                      \
+({                                                             \
+       pte_t *__ptep = (ptep);                                 \
+       pte_t __res = *__ptep;                                  \
+       if (!pte_none(__res) &&                                 \
+           ((vma)->vm_mm != current->mm ||                     \
+            HYPERVISOR_update_va_mapping(addr, __pte(0),       \
+                       (unsigned long)(vma)->vm_mm->cpu_vm_mask.bits| \
+                               UVMF_INVLPG|UVMF_MULTI))) {     \
+               __ptep->pte_low = 0;                            \
+               flush_tlb_page(vma, addr);                      \
+       }                                                       \
+       __res;                                                  \
+})
+
 #define pte_same(a, b)         ((a).pte_low == (b).pte_low)
+
 #define __pte_mfn(_pte) ((_pte).pte_low >> PAGE_SHIFT)
 #define pte_mfn(_pte) ((_pte).pte_low & _PAGE_PRESENT ? \
        __pte_mfn(_pte) : pfn_to_mfn(__pte_mfn(_pte)))
@@ -46,7 +75,6 @@
 
 #define pte_page(_pte) pfn_to_page(pte_pfn(_pte))
 
-#define pte_none(x)            (!(x).pte_low)
 #define pfn_pte(pfn, prot)     __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
 #define pfn_pmd(pfn, prot)     __pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
 
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-3level.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-3level.h       
Fri Apr 06 10:06:30 2007 -0600
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-3level.h       
Fri Apr 06 10:08:30 2007 -0600
@@ -99,6 +99,11 @@ static inline void pud_clear (pud_t * pu
 #define pmd_offset(pud, address) ((pmd_t *) pud_page(*(pud)) + \
                        pmd_index(address))
 
+static inline int pte_none(pte_t pte)
+{
+       return !(pte.pte_low | pte.pte_high);
+}
+
 /*
  * For PTEs and PDEs, we must clear the P-bit first when clearing a page table
  * entry, so clear the bottom half first and enforce ordering with a compiler
@@ -106,24 +111,50 @@ static inline void pud_clear (pud_t * pu
  */
 static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t 
*ptep)
 {
-       ptep->pte_low = 0;
-       smp_wmb();
-       ptep->pte_high = 0;
+       if ((mm != current->mm && mm != &init_mm)
+           || HYPERVISOR_update_va_mapping(addr, __pte(0), 0)) {
+               ptep->pte_low = 0;
+               smp_wmb();
+               ptep->pte_high = 0;
+       }
 }
 
 #define pmd_clear(xp)  do { set_pmd(xp, __pmd(0)); } while (0)
 
 static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long 
addr, pte_t *ptep)
 {
-       pte_t res;
-
-       /* xchg acts as a barrier before the setting of the high bits */
-       res.pte_low = xchg(&ptep->pte_low, 0);
-       res.pte_high = ptep->pte_high;
-       ptep->pte_high = 0;
-
-       return res;
-}
+       pte_t pte = *ptep;
+       if (!pte_none(pte)) {
+               if (mm != &init_mm) {
+                       uint64_t val = pte_val_ma(pte);
+                       if (__cmpxchg64(ptep, val, 0) != val) {
+                               /* xchg acts as a barrier before the setting of 
the high bits */
+                               pte.pte_low = xchg(&ptep->pte_low, 0);
+                               pte.pte_high = ptep->pte_high;
+                               ptep->pte_high = 0;
+                       }
+               } else
+                       HYPERVISOR_update_va_mapping(addr, __pte(0), 0);
+       }
+       return pte;
+}
+
+#define ptep_clear_flush(vma, addr, ptep)                      \
+({                                                             \
+       pte_t *__ptep = (ptep);                                 \
+       pte_t __res = *__ptep;                                  \
+       if (!pte_none(__res) &&                                 \
+           ((vma)->vm_mm != current->mm ||                     \
+            HYPERVISOR_update_va_mapping(addr, __pte(0),       \
+                       (unsigned long)(vma)->vm_mm->cpu_vm_mask.bits| \
+                               UVMF_INVLPG|UVMF_MULTI))) {     \
+               __ptep->pte_low = 0;                            \
+               smp_wmb();                                      \
+               __ptep->pte_high = 0;                           \
+               flush_tlb_page(vma, addr);                      \
+       }                                                       \
+       __res;                                                  \
+})
 
 static inline int pte_same(pte_t a, pte_t b)
 {
@@ -131,11 +162,6 @@ static inline int pte_same(pte_t a, pte_
 }
 
 #define pte_page(x)    pfn_to_page(pte_pfn(x))
-
-static inline int pte_none(pte_t pte)
-{
-       return !pte.pte_low && !pte.pte_high;
-}
 
 #define __pte_mfn(_pte) (((_pte).pte_low >> PAGE_SHIFT) | \
                         ((_pte).pte_high << (32-PAGE_SHIFT)))
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable.h      Fri Apr 
06 10:06:30 2007 -0600
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable.h      Fri Apr 
06 10:08:30 2007 -0600
@@ -210,9 +210,13 @@ extern unsigned long pg0[];
 
 /* To avoid harmful races, pmd_none(x) should check only the lower when PAE */
 #define pmd_none(x)    (!(unsigned long)pmd_val(x))
+#ifdef CONFIG_XEN_COMPAT_030002
 /* pmd_present doesn't just test the _PAGE_PRESENT bit since wr.p.t.
    can temporarily clear it. */
 #define pmd_present(x) (pmd_val(x))
+#else
+#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
+#endif
 #define pmd_bad(x)     ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER & 
~_PAGE_PRESENT)) != (_KERNPG_TABLE & ~_PAGE_PRESENT))
 
 
@@ -252,36 +256,47 @@ static inline pte_t pte_mkhuge(pte_t pte
 # include <asm/pgtable-2level.h>
 #endif
 
-static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, 
unsigned long addr, pte_t *ptep)
-{
-       if (!pte_dirty(*ptep))
-               return 0;
-       return test_and_clear_bit(_PAGE_BIT_DIRTY, &ptep->pte_low);
-}
-
-static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, 
unsigned long addr, pte_t *ptep)
-{
-       if (!pte_young(*ptep))
-               return 0;
-       return test_and_clear_bit(_PAGE_BIT_ACCESSED, &ptep->pte_low);
-}
-
-static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned 
long addr, pte_t *ptep, int full)
-{
-       pte_t pte;
-       if (full) {
-               pte = *ptep;
-               pte_clear(mm, addr, ptep);
-       } else {
-               pte = ptep_get_and_clear(mm, addr, ptep);
-       }
-       return pte;
-}
+#define ptep_test_and_clear_dirty(vma, addr, ptep)                     \
+({                                                                     \
+       pte_t __pte = *(ptep);                                          \
+       int __ret = pte_dirty(__pte);                                   \
+       if (__ret) {                                                    \
+               __pte = pte_mkclean(__pte);                             \
+               if ((vma)->vm_mm != current->mm ||                      \
+                   HYPERVISOR_update_va_mapping(addr, __pte, 0))       \
+                       (ptep)->pte_low = __pte.pte_low;                \
+       }                                                               \
+       __ret;                                                          \
+})
+
+#define ptep_test_and_clear_young(vma, addr, ptep)                     \
+({                                                                     \
+       pte_t __pte = *(ptep);                                          \
+       int __ret = pte_young(__pte);                                   \
+       if (__ret)                                                      \
+               __pte = pte_mkold(__pte);                               \
+               if ((vma)->vm_mm != current->mm ||                      \
+                   HYPERVISOR_update_va_mapping(addr, __pte, 0))       \
+                       (ptep)->pte_low = __pte.pte_low;                \
+       __ret;                                                          \
+})
+
+#define ptep_get_and_clear_full(mm, addr, ptep, full)                  \
+       ((full) ? ({                                                    \
+               pte_t __res = *(ptep);                                  \
+               if (test_bit(PG_pinned, &virt_to_page((mm)->pgd)->flags)) \
+                       xen_l1_entry_update(ptep, __pte(0));            \
+               else                                                    \
+                       *(ptep) = __pte(0);                             \
+               __res;                                                  \
+        }) :                                                           \
+        ptep_get_and_clear(mm, addr, ptep))
 
 static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long 
addr, pte_t *ptep)
 {
-       if (pte_write(*ptep))
-               clear_bit(_PAGE_BIT_RW, &ptep->pte_low);
+       pte_t pte = *ptep;
+       if (pte_write(pte))
+               set_pte_at(mm, addr, ptep, pte_wrprotect(pte));
 }
 
 /*
@@ -418,6 +433,20 @@ extern void noexec_setup(const char *str
 #define pte_unmap_nested(pte) do { } while (0)
 #endif
 
+#define __HAVE_ARCH_PTEP_ESTABLISH
+#define ptep_establish(vma, address, ptep, pteval)                     \
+       do {                                                            \
+               if ( likely((vma)->vm_mm == current->mm) ) {            \
+                       BUG_ON(HYPERVISOR_update_va_mapping(address,    \
+                               pteval,                                 \
+                               (unsigned long)(vma)->vm_mm->cpu_vm_mask.bits| \
+                                       UVMF_INVLPG|UVMF_MULTI));       \
+               } else {                                                \
+                       xen_l1_entry_update(ptep, pteval);              \
+                       flush_tlb_page(vma, address);                   \
+               }                                                       \
+       } while (0)
+
 /*
  * The i386 doesn't have any external MMU info: the kernel page
  * tables contain all the necessary information.
@@ -430,26 +459,11 @@ extern void noexec_setup(const char *str
  */
 #define update_mmu_cache(vma,address,pte) do { } while (0)
 #define  __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
-#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
-       do {                                                              \
-               if (__dirty) {                                            \
-                       if ( likely((__vma)->vm_mm == current->mm) ) {    \
-                               BUG_ON(HYPERVISOR_update_va_mapping(__address, \
-                                       __entry,                          \
-                                       (unsigned 
long)(__vma)->vm_mm->cpu_vm_mask.bits| \
-                                       UVMF_INVLPG|UVMF_MULTI));         \
-                       } else {                                          \
-                               xen_l1_entry_update(__ptep, __entry);     \
-                               flush_tlb_page(__vma, __address);         \
-                       }                                                 \
-               }                                                         \
+#define ptep_set_access_flags(vma, address, ptep, entry, dirty)                
\
+       do {                                                            \
+               if (dirty)                                              \
+                       ptep_establish(vma, address, ptep, entry);      \
        } while (0)
-
-#define __HAVE_ARCH_PTEP_ESTABLISH
-#define ptep_establish(__vma, __address, __ptep, __entry)              \
-do {                                                                   \
-       ptep_set_access_flags(__vma, __address, __ptep, __entry, 1);    \
-} while (0)
 
 #include <xen/features.h>
 void make_lowmem_page_readonly(void *va, unsigned int feature);
@@ -508,6 +522,7 @@ direct_remap_pfn_range(vma,from,pfn,size
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
+#define __HAVE_ARCH_PTEP_CLEAR_FLUSH
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
 #define __HAVE_ARCH_PTE_SAME
 #include <asm-generic/pgtable.h>
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h
--- a/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h        Fri Apr 06 
10:06:30 2007 -0600
+++ b/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h        Fri Apr 06 
10:08:30 2007 -0600
@@ -55,7 +55,7 @@ extern int running_on_xen;
 #include <xen/interface/event_channel.h>
 #include <xen/interface/physdev.h>
 #include <xen/interface/sched.h>
-#include <asm/hypercall.h>
+#include <xen/hypercall.h>
 #include <asm/ptrace.h>
 #include <asm/page.h>
 
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h
--- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h  Fri Apr 
06 10:06:30 2007 -0600
+++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h  Fri Apr 
06 10:08:30 2007 -0600
@@ -241,7 +241,7 @@ HYPERVISOR_memory_op(
 
 static inline int
 HYPERVISOR_multicall(
-       void *call_list, int nr_calls)
+       multicall_entry_t *call_list, int nr_calls)
 {
        return _hypercall2(int, multicall, call_list, nr_calls);
 }
@@ -259,7 +259,7 @@ HYPERVISOR_event_channel_op(
 {
        int rc = _hypercall2(int, event_channel_op, cmd, arg);
 
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
        if (unlikely(rc == -ENOSYS)) {
                struct evtchn_op op;
                op.cmd = cmd;
@@ -299,7 +299,7 @@ HYPERVISOR_physdev_op(
 {
        int rc = _hypercall2(int, physdev_op, cmd, arg);
 
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
        if (unlikely(rc == -ENOSYS)) {
                struct physdev_op op;
                op.cmd = cmd;
@@ -359,7 +359,7 @@ HYPERVISOR_suspend(
        int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown,
                             &sched_shutdown, srec);
 
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
        if (rc == -ENOSYS)
                rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown,
                                 SHUTDOWN_suspend, srec);
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/maddr.h
--- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/maddr.h      Fri Apr 
06 10:06:30 2007 -0600
+++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/maddr.h      Fri Apr 
06 10:08:30 2007 -0600
@@ -140,7 +140,7 @@ static inline paddr_t pte_machine_to_phy
 #define pfn_to_mfn(pfn) (pfn)
 #define mfn_to_pfn(mfn) (mfn)
 #define mfn_to_local_pfn(mfn) (mfn)
-#define set_phys_to_machine(pfn, mfn) BUG_ON((pfn) != (mfn))
+#define set_phys_to_machine(pfn, mfn) ((void)0)
 #define phys_to_machine_mapping_valid(pfn) (1)
 #define phys_to_machine(phys) ((maddr_t)(phys))
 #define machine_to_phys(mach) ((paddr_t)(mach))
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/page.h
--- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/page.h       Fri Apr 
06 10:06:30 2007 -0600
+++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/page.h       Fri Apr 
06 10:08:30 2007 -0600
@@ -23,12 +23,6 @@
        foreign;                                \
 })
 #define HAVE_ARCH_FREE_PAGE
-
-#ifdef CONFIG_XEN_SCRUB_PAGES
-#define scrub_pages(_p,_n) memset((void *)(_p), 0, (_n) << PAGE_SHIFT)
-#else
-#define scrub_pages(_p,_n) ((void)0)
-#endif
 
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT     12
@@ -110,7 +104,7 @@ static inline unsigned long pmd_val(pmd_
 static inline unsigned long pmd_val(pmd_t x)
 {
        unsigned long ret = x.pmd;
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
        if (ret) ret = pte_machine_to_phys(ret) | _PAGE_PRESENT;
 #else
        if (ret & _PAGE_PRESENT) ret = pte_machine_to_phys(ret);
@@ -172,10 +166,10 @@ static inline pgd_t __pgd(unsigned long 
 #define __PAGE_OFFSET           0xffff880000000000
 #endif /* !__ASSEMBLY__ */
 
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
 #undef LOAD_OFFSET
 #define LOAD_OFFSET            0
-#endif /* CONFIG_XEN_COMPAT_030002 */
+#endif
 
 /* to align the pointer to the (next) page boundary */
 #define PAGE_ALIGN(addr)       (((addr)+PAGE_SIZE-1)&PAGE_MASK)
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h
--- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h    Fri Apr 
06 10:06:30 2007 -0600
+++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h    Fri Apr 
06 10:08:30 2007 -0600
@@ -93,11 +93,6 @@ extern unsigned long empty_zero_page[PAG
 #define pgd_none(x)    (!pgd_val(x))
 #define pud_none(x)    (!pud_val(x))
 
-#define set_pte_batched(pteptr, pteval) \
-       queue_l1_entry_update(pteptr, (pteval))
-
-extern inline int pud_present(pud_t pud)       { return !pud_none(pud); }
-
 static inline void set_pte(pte_t *dst, pte_t val)
 {
        *dst = val;
@@ -122,41 +117,6 @@ static inline void pgd_clear (pgd_t * pg
 
 #define pud_page(pud) \
     ((unsigned long) __va(pud_val(pud) & PHYSICAL_PAGE_MASK))
-
-/*
- * A note on implementation of this atomic 'get-and-clear' operation.
- * This is actually very simple because Xen Linux can only run on a single
- * processor. Therefore, we cannot race other processors setting the 'accessed'
- * or 'dirty' bits on a page-table entry.
- * Even if pages are shared between domains, that is not a problem because
- * each domain will have separate page tables, with their own versions of
- * accessed & dirty state.
- */
-#define ptep_get_and_clear(mm,addr,xp) __pte_ma(xchg(&(xp)->pte, 0))
-
-#if 0
-static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long 
addr, pte_t *xp)
-{
-        pte_t pte = *xp;
-        if (pte.pte)
-                set_pte(xp, __pte_ma(0));
-        return pte;
-}
-#endif
-
-struct mm_struct;
-
-static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned 
long addr, pte_t *ptep, int full)
-{
-       pte_t pte;
-       if (full) {
-               pte = *ptep;
-               *ptep = __pte(0);
-       } else {
-               pte = ptep_get_and_clear(mm, addr, ptep);
-       }
-       return pte;
-}
 
 #define pte_same(a, b)         ((a).pte == (b).pte)
 
@@ -205,7 +165,7 @@ static inline pte_t ptep_get_and_clear_f
 #define _PAGE_PROTNONE 0x080   /* If not present */
 #define _PAGE_NX        (1UL<<_PAGE_BIT_NX)
 
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
 extern unsigned int __kernel_page_user;
 #else
 #define __kernel_page_user 0
@@ -318,6 +278,46 @@ static inline pte_t pfn_pte(unsigned lon
        return __pte(pte);
 }
 
+static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long 
addr, pte_t *ptep)
+{
+       pte_t pte = *ptep;
+       if (!pte_none(pte)) {
+               if (mm != &init_mm)
+                       pte = __pte_ma(xchg(&ptep->pte, 0));
+               else
+                       HYPERVISOR_update_va_mapping(addr, __pte(0), 0);
+       }
+       return pte;
+}
+
+static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned 
long addr, pte_t *ptep, int full)
+{
+       if (full) {
+               pte_t pte = *ptep;
+               if (mm->context.pinned)
+                       xen_l1_entry_update(ptep, __pte(0));
+               else
+                       *ptep = __pte(0);
+               return pte;
+       }
+       return ptep_get_and_clear(mm, addr, ptep);
+}
+
+#define ptep_clear_flush(vma, addr, ptep)                      \
+({                                                             \
+       pte_t *__ptep = (ptep);                                 \
+       pte_t __res = *__ptep;                                  \
+       if (!pte_none(__res) &&                                 \
+           ((vma)->vm_mm != current->mm ||                     \
+            HYPERVISOR_update_va_mapping(addr, __pte(0),       \
+                       (unsigned long)(vma)->vm_mm->cpu_vm_mask.bits| \
+                               UVMF_INVLPG|UVMF_MULTI))) {     \
+               __ptep->pte = 0;                                \
+               flush_tlb_page(vma, addr);                      \
+       }                                                       \
+       __res;                                                  \
+})
+
 /*
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
@@ -346,31 +346,29 @@ static inline pte_t pte_mkwrite(pte_t pt
 static inline pte_t pte_mkwrite(pte_t pte)     { __pte_val(pte) |= _PAGE_RW; 
return pte; }
 static inline pte_t pte_mkhuge(pte_t pte)      { __pte_val(pte) |= _PAGE_PSE; 
return pte; }
 
-struct vm_area_struct;
-
-static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, 
unsigned long addr, pte_t *ptep)
-{
-       pte_t pte = *ptep;
-       int ret = pte_dirty(pte);
-       if (ret)
-               set_pte(ptep, pte_mkclean(pte));
-       return ret;
-}
-
-static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, 
unsigned long addr, pte_t *ptep)
-{
-       pte_t pte = *ptep;
-       int ret = pte_young(pte);
-       if (ret)
-               set_pte(ptep, pte_mkold(pte));
-       return ret;
-}
+#define ptep_test_and_clear_dirty(vma, addr, ptep)                     \
+({                                                                     \
+       pte_t __pte = *(ptep);                                          \
+       int __ret = pte_dirty(__pte);                                   \
+       if (__ret)                                                      \
+               set_pte_at((vma)->vm_mm, addr, ptep, pte_mkclean(__pte)); \
+       __ret;                                                          \
+})
+
+#define ptep_test_and_clear_young(vma, addr, ptep)                     \
+({                                                                     \
+       pte_t __pte = *(ptep);                                          \
+       int __ret = pte_young(__pte);                                   \
+       if (__ret)                                                      \
+               set_pte_at((vma)->vm_mm, addr, ptep, pte_mkold(__pte)); \
+       __ret;                                                          \
+})
 
 static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long 
addr, pte_t *ptep)
 {
        pte_t pte = *ptep;
        if (pte_write(pte))
-               set_pte(ptep, pte_wrprotect(pte));
+               set_pte_at(mm, addr, ptep, pte_wrprotect(pte));
 }
 
 /*
@@ -403,6 +401,7 @@ static inline int pmd_large(pmd_t pte) {
 /* to find an entry in a page-table-directory. */
 #define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
 #define pud_offset(pgd, address) ((pud_t *) pgd_page(*(pgd)) + 
pud_index(address))
+#define pud_present(pud) (pud_val(pud) & _PAGE_PRESENT)
 
 /* PMD  - Level 2 access */
 #define pmd_page_kernel(pmd) ((unsigned long) __va(pmd_val(pmd) & PTE_MASK))
@@ -412,9 +411,13 @@ static inline int pmd_large(pmd_t pte) {
 #define pmd_offset(dir, address) ((pmd_t *) pud_page(*(dir)) + \
                                   pmd_index(address))
 #define pmd_none(x)    (!pmd_val(x))
+#ifdef CONFIG_XEN_COMPAT_030002
 /* pmd_present doesn't just test the _PAGE_PRESENT bit since wr.p.t.
    can temporarily clear it. */
 #define pmd_present(x) (pmd_val(x))
+#else
+#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
+#endif
 #define pmd_clear(xp)  do { set_pmd(xp, __pmd(0)); } while (0)
 #define pmd_bad(x) ((pmd_val(x) & ~(PTE_MASK | _PAGE_USER | _PAGE_PRESENT)) \
                    != (_KERNPG_TABLE & ~(_PAGE_USER | _PAGE_PRESENT)))
@@ -468,25 +471,34 @@ static inline pte_t pte_modify(pte_t pte
 
 #define update_mmu_cache(vma,address,pte) do { } while (0)
 
+/*
+ * Rules for using ptep_establish: the pte MUST be a user pte, and
+ * must be a present->present transition.
+ */
+#define __HAVE_ARCH_PTEP_ESTABLISH
+#define ptep_establish(vma, address, ptep, pteval)                     \
+       do {                                                            \
+               if ( likely((vma)->vm_mm == current->mm) ) {            \
+                       BUG_ON(HYPERVISOR_update_va_mapping(address,    \
+                               pteval,                                 \
+                               (unsigned long)(vma)->vm_mm->cpu_vm_mask.bits| \
+                                       UVMF_INVLPG|UVMF_MULTI));       \
+               } else {                                                \
+                       xen_l1_entry_update(ptep, pteval);              \
+                       flush_tlb_page(vma, address);                   \
+               }                                                       \
+       } while (0)
+
 /* We only update the dirty/accessed state if we set
  * the dirty bit by hand in the kernel, since the hardware
  * will do the accessed bit for us, and we don't want to
  * race with other CPU's that might be updating the dirty
  * bit at the same time. */
 #define  __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
-#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
-       do {                                                              \
-               if (__dirty) {                                            \
-                       if ( likely((__vma)->vm_mm == current->mm) ) {    \
-                               BUG_ON(HYPERVISOR_update_va_mapping(__address, \
-                                       __entry,                          \
-                                       (unsigned 
long)(__vma)->vm_mm->cpu_vm_mask.bits| \
-                                               UVMF_INVLPG|UVMF_MULTI)); \
-                       } else {                                          \
-                               xen_l1_entry_update(__ptep, __entry);     \
-                               flush_tlb_page(__vma, __address);         \
-                       }                                                 \
-               }                                                         \
+#define ptep_set_access_flags(vma, address, ptep, entry, dirty)                
\
+       do {                                                            \
+               if (dirty)                                              \
+                       ptep_establish(vma, address, ptep, entry);      \
        } while (0)
 
 /* Encode and de-code a swap entry */
@@ -506,6 +518,8 @@ extern int kern_addr_valid(unsigned long
 
 #define DOMID_LOCAL (0xFFFFU)
 
+struct vm_area_struct;
+
 int direct_remap_pfn_range(struct vm_area_struct *vma,
                             unsigned long address,
                             unsigned long mfn,
@@ -551,6 +565,7 @@ int touch_pte_range(struct mm_struct *mm
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
+#define __HAVE_ARCH_PTEP_CLEAR_FLUSH
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
 #define __HAVE_ARCH_PTE_SAME
 #include <asm-generic/pgtable.h>
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h
--- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h        
Fri Apr 06 10:06:30 2007 -0600
+++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h        
Fri Apr 06 10:08:30 2007 -0600
@@ -39,7 +39,7 @@ static void __init machine_specific_arch
                ret = HYPERVISOR_callback_op(CALLBACKOP_register, &failsafe);
        if (ret == 0)
                ret = HYPERVISOR_callback_op(CALLBACKOP_register, &syscall);
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
        if (ret == -ENOSYS)
                ret = HYPERVISOR_set_callbacks(
                        event.address,
@@ -50,7 +50,7 @@ static void __init machine_specific_arch
 
 #ifdef CONFIG_X86_LOCAL_APIC
        ret = HYPERVISOR_callback_op(CALLBACKOP_register, &nmi_cb);
-#ifdef CONFIG_XEN_COMPAT_030002
+#if CONFIG_XEN_COMPAT <= 0x030002
        if (ret == -ENOSYS) {
                static struct xennmi_callback __initdata cb = {
                        .handler_address = (unsigned long)nmi
diff -r 9ec7dadc98ba -r eb3e430242ac linux-2.6-xen-sparse/include/xen/hvm.h
--- a/linux-2.6-xen-sparse/include/xen/hvm.h    Fri Apr 06 10:06:30 2007 -0600
+++ b/linux-2.6-xen-sparse/include/xen/hvm.h    Fri Apr 06 10:08:30 2007 -0600
@@ -3,7 +3,6 @@
 #define XEN_HVM_H__
 
 #include <xen/interface/hvm/params.h>
-#include <asm/hypercall.h>
 
 static inline unsigned long hvm_get_parameter(int idx)
 {
diff -r 9ec7dadc98ba -r eb3e430242ac 
linux-2.6-xen-sparse/include/xen/hypercall.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/linux-2.6-xen-sparse/include/xen/hypercall.h      Fri Apr 06 10:08:30 
2007 -0600
@@ -0,0 +1,24 @@
+#ifndef __XEN_HYPERCALL_H__
+#define __XEN_HYPERCALL_H__
+
+#include <asm/hypercall.h>
+
+static inline int
+HYPERVISOR_multicall_check(
+       multicall_entry_t *call_list, int nr_calls,
+       const unsigned long *rc_list)
+{
+       int rc = HYPERVISOR_multicall(call_list, nr_calls);
+
+       if (unlikely(rc < 0))
+               return rc;
+       BUG_ON(rc);
+
+       for ( ; nr_calls > 0; --nr_calls, ++call_list)
+               if (unlikely(call_list->result != (rc_list ? *rc_list++ : 0)))
+                       return nr_calls;
+
+       return 0;
+}
+
+#endif /* __XEN_HYPERCALL_H__ */
diff -r 9ec7dadc98ba -r eb3e430242ac tools/ioemu/hw/xen_platform.c
--- a/tools/ioemu/hw/xen_platform.c     Fri Apr 06 10:06:30 2007 -0600
+++ b/tools/ioemu/hw/xen_platform.c     Fri Apr 06 10:08:30 2007 -0600
@@ -29,16 +29,10 @@
 
 extern FILE *logfile;
 
-static void platform_ioport_write(void *opaque, uint32_t addr, uint32_t val)
-{
-    if (val == 0)
-        qemu_invalidate_map_cache();
-}
-
 static void platform_ioport_map(PCIDevice *pci_dev, int region_num,
                                 uint32_t addr, uint32_t size, int type)
 {
-    register_ioport_write(addr, 1, 1, platform_ioport_write, NULL);
+    /* nothing yet */
 }
 
 static uint32_t platform_mmio_read(void *opaque, target_phys_addr_t addr)
diff -r 9ec7dadc98ba -r eb3e430242ac tools/ioemu/target-i386-dm/exec-dm.c
--- a/tools/ioemu/target-i386-dm/exec-dm.c      Fri Apr 06 10:06:30 2007 -0600
+++ b/tools/ioemu/target-i386-dm/exec-dm.c      Fri Apr 06 10:08:30 2007 -0600
@@ -431,14 +431,8 @@ static inline int paddr_is_ram(target_ph
 {
     /* Is this guest physical address RAM-backed? */
 #if defined(CONFIG_DM) && (defined(__i386__) || defined(__x86_64__))
-    if (ram_size <= HVM_BELOW_4G_RAM_END)
-        /* RAM is contiguous */
-        return (addr < ram_size);
-    else
-        /* There is RAM below and above the MMIO hole */
-        return ((addr < HVM_BELOW_4G_MMIO_START) ||
-                ((addr >= HVM_BELOW_4G_MMIO_START + HVM_BELOW_4G_MMIO_LENGTH)
-                 && (addr < ram_size + HVM_BELOW_4G_MMIO_LENGTH)));
+    return ((addr < HVM_BELOW_4G_MMIO_START) ||
+            (addr >= HVM_BELOW_4G_MMIO_START + HVM_BELOW_4G_MMIO_LENGTH));
 #else
     return (addr < ram_size);
 #endif
diff -r 9ec7dadc98ba -r eb3e430242ac tools/ioemu/target-i386-dm/helper2.c
--- a/tools/ioemu/target-i386-dm/helper2.c      Fri Apr 06 10:06:30 2007 -0600
+++ b/tools/ioemu/target-i386-dm/helper2.c      Fri Apr 06 10:08:30 2007 -0600
@@ -135,9 +135,6 @@ void cpu_reset(CPUX86State *env)
 {
     int xcHandle;
     int sts;
-
-    /* pause domain first, to avoid repeated reboot request*/
-    xc_domain_pause(xc_handle, domid);
 
     xcHandle = xc_interface_open();
     if (xcHandle < 0)
@@ -509,8 +506,11 @@ void __handle_ioreq(CPUState *env, ioreq
         cpu_ioreq_xchg(env, req);
         break;
     case IOREQ_TYPE_TIMEOFFSET:
-       cpu_ioreq_timeoffset(env, req);
-       break;
+        cpu_ioreq_timeoffset(env, req);
+        break;
+    case IOREQ_TYPE_INVALIDATE:
+        qemu_invalidate_map_cache();
+        break;
     default:
         hw_error("Invalid ioreq type 0x%x\n", req->type);
     }
@@ -597,6 +597,7 @@ int main_loop(void)
     extern int suspend_requested;
     CPUState *env = cpu_single_env;
     int evtchn_fd = xc_evtchn_fd(xce_handle);
+    char qemu_file[20];
 
     buffered_io_timer = qemu_new_timer(rt_clock, handle_buffered_io,
                                       cpu_single_env);
@@ -604,52 +605,23 @@ int main_loop(void)
 
     qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, env);
 
-    while (1) {
-        if (vm_running) {
-            if (shutdown_requested)
-                break;
-            if (reset_requested) {
-                qemu_system_reset();
-                reset_requested = 0;
-            }
-            if (suspend_requested) {
-                fprintf(logfile, "device model received suspend signal!\n");
-                break;
-            }
-        }
-
+    while (!(vm_running && suspend_requested))
         /* Wait up to 10 msec. */
         main_loop_wait(10);
-    }
-    if (!suspend_requested)
-        destroy_hvm_domain();
-    else {
-        char qemu_file[20];
-        ioreq_t *req;
-        int rc;
-
-        sprintf(qemu_file, "/tmp/xen.qemu-dm.%d", domid);
-        xc_domain_pause(xc_handle, domid);
-
-        /* Pull all outstanding ioreqs through the system */
-        handle_buffered_io(env);
-        main_loop_wait(1); /* For the select() on events */
-        
-        /* Stop the IDE thread */
-        ide_stop_dma_thread();
-
-        /* Make sure that all outstanding IO responses are handled too */ 
-        if ( xc_hvm_drain_io(xc_handle, domid) != 0 )
-        {
-            fprintf(stderr, "error clearing ioreq rings (%s)\n", 
-                    strerror(errno));
-            return -1;
-        }
-
-        /* Save the device state */
-        if (qemu_savevm(qemu_file) < 0)
-            fprintf(stderr, "qemu save fail.\n");
-    }
+
+    fprintf(logfile, "device model received suspend signal!\n");
+
+    /* Pull all outstanding ioreqs through the system */
+    handle_buffered_io(env);
+    main_loop_wait(1); /* For the select() on events */
+
+    /* Stop the IDE thread */
+    ide_stop_dma_thread();
+
+    /* Save the device state */
+    sprintf(qemu_file, "/tmp/xen.qemu-dm.%d", domid);
+    if (qemu_savevm(qemu_file) < 0)
+        fprintf(stderr, "qemu save fail.\n");
 
     return 0;
 }
diff -r 9ec7dadc98ba -r eb3e430242ac tools/ioemu/vl.c
--- a/tools/ioemu/vl.c  Fri Apr 06 10:06:30 2007 -0600
+++ b/tools/ioemu/vl.c  Fri Apr 06 10:08:30 2007 -0600
@@ -88,6 +88,7 @@
 
 #include "exec-all.h"
 
+#include <xen/hvm/params.h>
 #define DEFAULT_NETWORK_SCRIPT "/etc/xen/qemu-ifup"
 #define DEFAULT_BRIDGE "xenbr0"
 
@@ -5886,7 +5887,8 @@ int set_mm_mapping(int xc_handle, uint32
 
 void suspend(int sig)
 {
-   fprintf(logfile, "suspend sig handler called with requested=%d!\n", 
suspend_requested);
+    fprintf(logfile, "suspend sig handler called with requested=%d!\n",
+            suspend_requested);
     if (sig != SIGUSR1)
         fprintf(logfile, "suspend signal dismatch, get sig=%d!\n", sig);
     suspend_requested = 1;
@@ -5900,32 +5902,28 @@ static unsigned long last_address_index 
 static unsigned long last_address_index = ~0UL;
 static uint8_t      *last_address_vaddr;
 
-static int qemu_map_cache_init(unsigned long nr_pages)
-{
-    unsigned long max_pages = MAX_MCACHE_SIZE >> PAGE_SHIFT;
-    int i;
-
-    if (nr_pages < max_pages)
-        max_pages = nr_pages;
-
-    nr_buckets   = max_pages + (1UL << (MCACHE_BUCKET_SHIFT - PAGE_SHIFT)) - 1;
-    nr_buckets >>= (MCACHE_BUCKET_SHIFT - PAGE_SHIFT);
+static int qemu_map_cache_init(void)
+{
+    unsigned long size;
+
+    nr_buckets = (((MAX_MCACHE_SIZE >> PAGE_SHIFT) +
+                   (1UL << (MCACHE_BUCKET_SHIFT - PAGE_SHIFT)) - 1) >>
+                  (MCACHE_BUCKET_SHIFT - PAGE_SHIFT));
     fprintf(logfile, "qemu_map_cache_init nr_buckets = %lx\n", nr_buckets);
 
-    mapcache_entry = malloc(nr_buckets * sizeof(struct map_cache));
-    if (mapcache_entry == NULL) {
+    /*
+     * Use mmap() directly: lets us allocate a big hash table with no up-front
+     * cost in storage space. The OS will allocate memory only for the buckets
+     * that we actually use. All others will contain all zeroes.
+     */
+    size = nr_buckets * sizeof(struct map_cache);
+    size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
+    mapcache_entry = mmap(NULL, size, PROT_READ|PROT_WRITE,
+                          MAP_SHARED|MAP_ANONYMOUS, 0, 0);
+    if (mapcache_entry == MAP_FAILED) {
         errno = ENOMEM;
         return -1;
     }
-
-    memset(mapcache_entry, 0, nr_buckets * sizeof(struct map_cache));
-
-    /*
-     * To avoid ENOMEM from xc_map_foreign_batch() at runtime, we
-     * pre-fill all the map caches in advance.
-     */
-    for (i = 0; i < nr_buckets; i++)
-       (void)qemu_map_cache(((target_phys_addr_t)i) << MCACHE_BUCKET_SHIFT);
 
     return 0;
 }
@@ -6038,11 +6036,14 @@ int main(int argc, char **argv)
     QEMUMachine *machine;
     char usb_devices[MAX_USB_CMDLINE][128];
     int usb_devices_index;
-    unsigned long nr_pages, tmp_nr_pages, shared_page_nr;
-    xen_pfn_t *page_array;
+    unsigned long ioreq_pfn;
     extern void *shared_page;
     extern void *buffered_io_page;
+#ifdef __ia64__
+    unsigned long nr_pages;
+    xen_pfn_t *page_array;
     extern void *buffered_pio_page;
+#endif
 
     char qemu_dm_logfilename[64];
 
@@ -6592,47 +6593,36 @@ int main(int argc, char **argv)
 
     xc_handle = xc_interface_open();
 
-    nr_pages = ram_size/PAGE_SIZE;
-    tmp_nr_pages = nr_pages;
-
 #if defined(__i386__) || defined(__x86_64__)
-    if (ram_size > HVM_BELOW_4G_RAM_END) {
-        tmp_nr_pages += HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT;
-        shared_page_nr = (HVM_BELOW_4G_RAM_END >> PAGE_SHIFT) - 1;
-    } else
-        shared_page_nr = nr_pages - 1;
-#endif
-
-#if defined(__i386__) || defined(__x86_64__)
-
-    if ( qemu_map_cache_init(tmp_nr_pages) )
-    {
+
+    if (qemu_map_cache_init()) {
         fprintf(logfile, "qemu_map_cache_init returned: error %d\n", errno);
         exit(-1);
     }
 
+    xc_get_hvm_param(xc_handle, domid, HVM_PARAM_IOREQ_PFN, &ioreq_pfn);
+    fprintf(logfile, "shared page at pfn %lx\n", ioreq_pfn);
     shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
-                                       PROT_READ|PROT_WRITE, shared_page_nr);
+                                       PROT_READ|PROT_WRITE, ioreq_pfn);
     if (shared_page == NULL) {
         fprintf(logfile, "map shared IO page returned error %d\n", errno);
         exit(-1);
     }
 
-    fprintf(logfile, "shared page at pfn:%lx\n", shared_page_nr);
-
+    xc_get_hvm_param(xc_handle, domid, HVM_PARAM_BUFIOREQ_PFN, &ioreq_pfn);
+    fprintf(logfile, "buffered io page at pfn %lx\n", ioreq_pfn);
     buffered_io_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
-                                            PROT_READ|PROT_WRITE,
-                                            shared_page_nr - 2);
+                                            PROT_READ|PROT_WRITE, ioreq_pfn);
     if (buffered_io_page == NULL) {
         fprintf(logfile, "map buffered IO page returned error %d\n", errno);
         exit(-1);
     }
 
-    fprintf(logfile, "buffered io page at pfn:%lx\n", shared_page_nr - 2);
-
 #elif defined(__ia64__)
 
-    page_array = (xen_pfn_t *)malloc(tmp_nr_pages * sizeof(xen_pfn_t));
+    nr_pages = ram_size/PAGE_SIZE;
+
+    page_array = (xen_pfn_t *)malloc(nr_pages * sizeof(xen_pfn_t));
     if (page_array == NULL) {
         fprintf(logfile, "malloc returned error %d\n", errno);
         exit(-1);
@@ -6650,7 +6640,7 @@ int main(int argc, char **argv)
                                        PROT_READ|PROT_WRITE,
                                        BUFFER_PIO_PAGE_START >> PAGE_SHIFT);
 
-    for (i = 0; i < tmp_nr_pages; i++)
+    for (i = 0; i < nr_pages; i++)
         page_array[i] = i;
        
     /* VTI will not use memory between 3G~4G, so we just pass a legal pfn
diff -r 9ec7dadc98ba -r eb3e430242ac tools/ioemu/xenstore.c
--- a/tools/ioemu/xenstore.c    Fri Apr 06 10:06:30 2007 -0600
+++ b/tools/ioemu/xenstore.c    Fri Apr 06 10:08:30 2007 -0600
@@ -248,12 +248,8 @@ void xenstore_process_logdirty_event(voi
         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 = xc_memory_op(xc_handle, 
+                                            XENMEM_maximum_gpfn, &domid) + 1;
         logdirty_bitmap_size = ((logdirty_bitmap_size + HOST_LONG_BITS - 1)
                                 / HOST_LONG_BITS); /* longs */
         logdirty_bitmap_size *= sizeof (unsigned long); /* bytes */
@@ -272,7 +268,7 @@ void xenstore_process_logdirty_event(voi
 
         /* 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", 
+            fprintf(logfile, "Log-dirty: got %u, calc %lu\n", 
                     *(uint32_t *)seg, logdirty_bitmap_size);
             return;
         }
@@ -304,7 +300,7 @@ void xenstore_process_logdirty_event(voi
         fprintf(logfile, "Log-dirty: bad next-active entry: %s\n", act);
         exit(1);
     }
-    logdirty_bitmap = seg + i * logdirty_bitmap_size;
+    logdirty_bitmap = (unsigned long *)(seg + i * logdirty_bitmap_size);
 
     /* Ack that we've switched */
     xs_write(xsh, XBT_NULL, active_path, act, len);
@@ -612,7 +608,7 @@ int xenstore_vm_write(int domid, char *k
 
     path = xs_get_domain_path(xsh, domid);
     if (path == NULL) {
-       fprintf(logfile, "xs_get_domain_path(%d): error\n");
+       fprintf(logfile, "xs_get_domain_path: error\n");
        goto out;
     }
 
diff -r 9ec7dadc98ba -r eb3e430242ac tools/libxc/Makefile
--- a/tools/libxc/Makefile      Fri Apr 06 10:06:30 2007 -0600
+++ b/tools/libxc/Makefile      Fri Apr 06 10:08:30 2007 -0600
@@ -26,8 +26,8 @@ CTRL_SRCS-$(CONFIG_X86_Linux) += xc_ptra
 
 GUEST_SRCS-y :=
 GUEST_SRCS-y += xg_private.c
-GUEST_SRCS-$(CONFIG_MIGRATE) += xc_linux_restore.c xc_linux_save.c
-GUEST_SRCS-$(CONFIG_HVM) += xc_hvm_build.c xc_hvm_restore.c xc_hvm_save.c
+GUEST_SRCS-$(CONFIG_MIGRATE) += xc_domain_restore.c xc_linux_save.c
+GUEST_SRCS-$(CONFIG_HVM) += xc_hvm_build.c xc_hvm_save.c
 
 # symlink libelf from xen/common/libelf/
 LIBELF_SRCS := libelf-tools.c libelf-loader.c
diff -r 9ec7dadc98ba -r eb3e430242ac tools/libxc/ia64/xc_ia64_linux_restore.c
--- a/tools/libxc/ia64/xc_ia64_linux_restore.c  Fri Apr 06 10:06:30 2007 -0600
+++ b/tools/libxc/ia64/xc_ia64_linux_restore.c  Fri Apr 06 10:08:30 2007 -0600
@@ -20,9 +20,6 @@ static unsigned long p2m_size;
 /* number of 'in use' pfns in the guest (i.e. #P2M entries with a valid mfn) */
 static unsigned long nr_pfns;
 
-/* largest possible value of nr_pfns (i.e. domain's maximum memory size) */
-static unsigned long max_nr_pfns;
-
 static ssize_t
 read_exact(int fd, void *buf, size_t count)
 {
@@ -62,10 +59,10 @@ read_page(int xc_handle, int io_fd, uint
 }
 
 int
-xc_linux_restore(int xc_handle, int io_fd, uint32_t dom,
-                 unsigned long p2msize, unsigned long maxnrpfns,
+xc_domain_restore(int xc_handle, int io_fd, uint32_t dom,
                  unsigned int store_evtchn, unsigned long *store_mfn,
-                 unsigned int console_evtchn, unsigned long *console_mfn)
+                 unsigned int console_evtchn, unsigned long *console_mfn,
+                 unsigned int hvm, unsigned int pae)
 {
     DECLARE_DOMCTL;
     int rc = 1, i;
@@ -85,12 +82,19 @@ xc_linux_restore(int xc_handle, int io_f
     /* A temporary mapping of the guest's start_info page. */
     start_info_t *start_info;
 
-    p2m_size = p2msize;
-    max_nr_pfns = maxnrpfns;
+    if (hvm) {
+        ERROR("HVM Restore is unsupported");
+        goto out;
+    }
 
     /* For info only */
     nr_pfns = 0;
 
+    if ( !read_exact(io_fd, &p2m_size, sizeof(unsigned long)) )
+    {
+        ERROR("read: p2m_size");
+        goto out;
+    }
     DPRINTF("xc_linux_restore start: p2m_size = %lx\n", p2m_size);
 
     if (!read_exact(io_fd, &ver, sizeof(unsigned long))) {
@@ -106,11 +110,6 @@ xc_linux_restore(int xc_handle, int io_f
         /* needed for build domctl, but might as well do early */
         ERROR("Unable to mlock ctxt");
         return 1;
-    }
-
-    if (xc_domain_setmaxmem(xc_handle, dom, PFN_TO_KB(max_nr_pfns)) != 0) {
-        errno = ENOMEM;
-        goto out;
     }
 
     /* Get pages.  */
diff -r 9ec7dadc98ba -r eb3e430242ac tools/libxc/xc_domain_restore.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxc/xc_domain_restore.c   Fri Apr 06 10:08:30 2007 -0600
@@ -0,0 +1,1086 @@
+/******************************************************************************
+ * xc_domain_restore.c
+ *
+ * Restore the state of a guest session.
+ *
+ * Copyright (c) 2003, K A Fraser.
+ * Copyright (c) 2006, Intel Corporation
+ * Copyright (c) 2007, XenSource Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "xg_private.h"
+#include "xg_save_restore.h"
+#include "xc_dom.h"
+
+#include <xen/hvm/ioreq.h>
+#include <xen/hvm/params.h>
+
+/* max mfn of the current host machine */
+static unsigned long max_mfn;
+
+/* virtual starting address of the hypervisor */
+static unsigned long hvirt_start;
+
+/* #levels of page tables used by the current guest */
+static unsigned int pt_levels;
+
+/* number of pfns this guest has (i.e. number of entries in the P2M) */
+static unsigned long p2m_size;
+
+/* number of 'in use' pfns in the guest (i.e. #P2M entries with a valid mfn) */
+static unsigned long nr_pfns;
+
+/* Live mapping of the table mapping each PFN to its current MFN. */
+static xen_pfn_t *live_p2m = NULL;
+
+/* A table mapping each PFN to its new MFN. */
+static xen_pfn_t *p2m = NULL;
+
+/* A table of P2M mappings in the current region */
+static xen_pfn_t *p2m_batch = NULL;
+
+static ssize_t
+read_exact(int fd, void *buf, size_t count)
+{
+    int r = 0, s;
+    unsigned char *b = buf;
+
+    while (r < count) {
+        s = read(fd, &b[r], count - r);
+        if ((s == -1) && (errno == EINTR))
+            continue;
+        if (s <= 0) {
+            break;
+        }
+        r += s;
+    }
+
+    return (r == count) ? 1 : 0;
+}
+
+/*
+** In the state file (or during transfer), all page-table pages are
+** converted into a 'canonical' form where references to actual mfns
+** are replaced with references to the corresponding pfns.
+** This function inverts that operation, replacing the pfn values with
+** the (now known) appropriate mfn values.
+*/
+static int uncanonicalize_pagetable(int xc_handle, uint32_t dom, 
+                                    unsigned long type, void *page)
+{
+    int i, pte_last;
+    unsigned long pfn;
+    uint64_t pte;
+    int nr_mfns = 0; 
+
+    pte_last = PAGE_SIZE / ((pt_levels == 2)? 4 : 8);
+
+    /* First pass: work out how many (if any) MFNs we need to alloc */
+    for(i = 0; i < pte_last; i++) {
+        
+        if(pt_levels == 2)
+            pte = ((uint32_t *)page)[i];
+        else
+            pte = ((uint64_t *)page)[i];
+        
+        /* XXX SMH: below needs fixing for PROT_NONE etc */
+        if(!(pte & _PAGE_PRESENT))
+            continue; 
+        
+        pfn = (pte >> PAGE_SHIFT) & MFN_MASK_X86;
+        
+        if(pfn >= p2m_size) {
+            /* This "page table page" is probably not one; bail. */
+            ERROR("Frame number in type %lu page table is out of range: "
+                  "i=%d pfn=0x%lx p2m_size=%lu",
+                  type >> 28, i, pfn, p2m_size);
+            return 0;
+        }
+        
+        if(p2m[pfn] == INVALID_P2M_ENTRY) {
+            /* Have a 'valid' PFN without a matching MFN - need to alloc */
+            p2m_batch[nr_mfns++] = pfn; 
+        }
+    }
+    
+    
+    /* Allocate the requistite number of mfns */
+    if (nr_mfns && xc_domain_memory_populate_physmap(
+            xc_handle, dom, nr_mfns, 0, 0, p2m_batch) != 0) { 
+        ERROR("Failed to allocate memory for batch.!\n"); 
+        errno = ENOMEM;
+        return 0; 
+    }
+    
+    /* Second pass: uncanonicalize each present PTE */
+    nr_mfns = 0;
+    for(i = 0; i < pte_last; i++) {
+
+        if(pt_levels == 2)
+            pte = ((uint32_t *)page)[i];
+        else
+            pte = ((uint64_t *)page)[i];
+        
+        /* XXX SMH: below needs fixing for PROT_NONE etc */
+        if(!(pte & _PAGE_PRESENT))
+            continue;
+        
+        pfn = (pte >> PAGE_SHIFT) & MFN_MASK_X86;
+        
+        if(p2m[pfn] == INVALID_P2M_ENTRY)
+            p2m[pfn] = p2m_batch[nr_mfns++];
+
+        pte &= ~MADDR_MASK_X86;
+        pte |= (uint64_t)p2m[pfn] << PAGE_SHIFT;
+
+        if(pt_levels == 2)
+            ((uint32_t *)page)[i] = (uint32_t)pte;
+        else
+            ((uint64_t *)page)[i] = (uint64_t)pte;
+    }
+
+    return 1;
+}
+
+
+/* Load the p2m frame list, plus potential extended info chunk */
+static xen_pfn_t * load_p2m_frame_list(int io_fd, int *pae_extended_cr3)
+{
+    xen_pfn_t *p2m_frame_list;
+    vcpu_guest_context_t ctxt;
+
+    if (!(p2m_frame_list = malloc(P2M_FL_SIZE))) {
+        ERROR("Couldn't allocate p2m_frame_list array");
+        return NULL;
+    }
+    
+    /* Read first entry of P2M list, or extended-info signature (~0UL). */
+    if (!read_exact(io_fd, p2m_frame_list, sizeof(long))) {
+            ERROR("read extended-info signature failed");
+            return NULL;
+        }
+    
+    if (p2m_frame_list[0] == ~0UL) {
+        uint32_t tot_bytes;
+        
+        /* Next 4 bytes: total size of following extended info. */
+        if (!read_exact(io_fd, &tot_bytes, sizeof(tot_bytes))) {
+            ERROR("read extended-info size failed");
+            return NULL;
+        }
+        
+        while (tot_bytes) {
+            uint32_t chunk_bytes;
+            char     chunk_sig[4];
+            
+            /* 4-character chunk signature + 4-byte remaining chunk size. */
+            if (!read_exact(io_fd, chunk_sig, sizeof(chunk_sig)) ||
+                !read_exact(io_fd, &chunk_bytes, sizeof(chunk_bytes))) {
+                ERROR("read extended-info chunk signature failed");
+                return NULL;
+            }
+            tot_bytes -= 8;
+            
+            /* VCPU context structure? */
+            if (!strncmp(chunk_sig, "vcpu", 4)) {
+                if (!read_exact(io_fd, &ctxt, sizeof(ctxt))) {
+                    ERROR("read extended-info vcpu context failed");
+                    return NULL;
+                }
+                tot_bytes   -= sizeof(struct vcpu_guest_context);
+                chunk_bytes -= sizeof(struct vcpu_guest_context);
+                
+                if (ctxt.vm_assist & (1UL << VMASST_TYPE_pae_extended_cr3))
+                    *pae_extended_cr3 = 1;
+            }
+            
+            /* Any remaining bytes of this chunk: read and discard. */
+            while (chunk_bytes) {
+                unsigned long sz = chunk_bytes;
+                if ( sz > P2M_FL_SIZE )
+                    sz = P2M_FL_SIZE;
+                if (!read_exact(io_fd, p2m_frame_list, sz)) {
+                    ERROR("read-and-discard extended-info chunk bytes failed");
+                    return NULL;
+                }
+                chunk_bytes -= sz;
+                tot_bytes   -= sz;
+            }
+        }
+        
+        /* Now read the real first entry of P2M list. */
+        if (!read_exact(io_fd, p2m_frame_list, sizeof(long))) {
+            ERROR("read first entry of p2m_frame_list failed");
+            return NULL;
+        }
+    }
+    
+    /* First entry is already read into the p2m array. */
+    if (!read_exact(io_fd, &p2m_frame_list[1], P2M_FL_SIZE - sizeof(long))) {
+            ERROR("read p2m_frame_list failed");
+            return NULL;
+    }
+    
+    return p2m_frame_list;
+}
+
+
+
+int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom,
+                      unsigned int store_evtchn, unsigned long *store_mfn,
+                      unsigned int console_evtchn, unsigned long *console_mfn,
+                      unsigned int hvm, unsigned int pae)
+{
+    DECLARE_DOMCTL;
+    int rc = 1, i, j, n, m, pae_extended_cr3 = 0;
+    unsigned long mfn, pfn;
+    unsigned int prev_pc, this_pc;
+    int verify = 0;
+    int nraces = 0;
+
+    /* The new domain's shared-info frame number. */
+    unsigned long shared_info_frame;
+    unsigned char shared_info_page[PAGE_SIZE]; /* saved contents from file */
+    shared_info_t *shared_info = (shared_info_t *)shared_info_page;
+
+    /* A copy of the CPU context of the guest. */
+    vcpu_guest_context_t ctxt;
+
+    /* A table containing the type of each PFN (/not/ MFN!). */
+    unsigned long *pfn_type = NULL;
+
+    /* A table of MFNs to map in the current region */
+    xen_pfn_t *region_mfn = NULL;
+
+    /* Types of the pfns in the current region */
+    unsigned long region_pfn_type[MAX_BATCH_SIZE];
+
+    /* A temporary mapping, and a copy, of one frame of guest memory. */
+    unsigned long *page = NULL;
+
+    /* A copy of the pfn-to-mfn table frame list. */
+    xen_pfn_t *p2m_frame_list = NULL;
+    
+    /* A temporary mapping of the guest's start_info page. */
+    start_info_t *start_info;
+
+    /* Our mapping of the current region (batch) */
+    char *region_base;
+
+    xc_mmu_t *mmu = NULL;
+
+    /* used by debug verify code */
+    unsigned long buf[PAGE_SIZE/sizeof(unsigned long)];
+
+    struct mmuext_op pin[MAX_PIN_BATCH];
+    unsigned int nr_pins;
+
+    uint64_t vcpumap = 1ULL;
+    unsigned int max_vcpu_id = 0;
+    int new_ctxt_format = 0;
+
+    /* Magic frames in HVM guests: ioreqs and xenstore comms. */
+    uint64_t magic_pfns[3]; /* ioreq_pfn, bufioreq_pfn, store_pfn */
+
+    /* Buffer for holding HVM context */
+    uint8_t *hvm_buf = NULL;
+
+    /* For info only */
+    nr_pfns = 0;
+
+    if ( !read_exact(io_fd, &p2m_size, sizeof(unsigned long)) )
+    {
+        ERROR("read: p2m_size");
+        goto out;
+    }
+    DPRINTF("xc_domain_restore start: p2m_size = %lx\n", p2m_size);
+
+    if ( !hvm )
+    {
+        /*
+         * XXX For now, 32bit dom0's can only save/restore 32bit domUs
+         * on 64bit hypervisors.
+         */
+        memset(&domctl, 0, sizeof(domctl));
+        domctl.domain = dom;
+        domctl.cmd    = XEN_DOMCTL_set_address_size;
+        domctl.u.address_size.size = sizeof(unsigned long) * 8;
+        rc = do_domctl(xc_handle, &domctl);
+        if ( rc != 0 ) {
+            ERROR("Unable to set guest address size.");
+            goto out;
+        }
+        rc = 1;
+    }
+
+    if(!get_platform_info(xc_handle, dom,
+                          &max_mfn, &hvirt_start, &pt_levels)) {
+        ERROR("Unable to get platform info.");
+        return 1;
+    }
+
+    if (lock_pages(&ctxt, sizeof(ctxt))) {
+        /* needed for build domctl, but might as well do early */
+        ERROR("Unable to lock ctxt");
+        return 1;
+    }
+
+    /* Load the p2m frame list, plus potential extended info chunk */
+    if ( !hvm ) 
+    {
+        p2m_frame_list = load_p2m_frame_list(io_fd, &pae_extended_cr3);
+        if ( !p2m_frame_list )
+            goto out;
+    }
+
+    /* We want zeroed memory so use calloc rather than malloc. */
+    p2m        = calloc(p2m_size, sizeof(xen_pfn_t));
+    pfn_type   = calloc(p2m_size, sizeof(unsigned long));
+    region_mfn = calloc(MAX_BATCH_SIZE, sizeof(xen_pfn_t));
+    p2m_batch  = calloc(MAX_BATCH_SIZE, sizeof(xen_pfn_t));
+
+    if ((p2m == NULL) || (pfn_type == NULL) ||
+        (region_mfn == NULL) || (p2m_batch == NULL)) {
+        ERROR("memory alloc failed");
+        errno = ENOMEM;
+        goto out;
+    }
+
+    if (lock_pages(region_mfn, sizeof(xen_pfn_t) * MAX_BATCH_SIZE)) {
+        ERROR("Could not lock region_mfn");
+        goto out;
+    }
+
+    if (lock_pages(p2m_batch, sizeof(xen_pfn_t) * MAX_BATCH_SIZE)) {
+        ERROR("Could not lock p2m_batch");
+        goto out;
+    }
+
+    /* Get the domain's shared-info frame. */
+    domctl.cmd = XEN_DOMCTL_getdomaininfo;
+    domctl.domain = (domid_t)dom;
+    if (xc_domctl(xc_handle, &domctl) < 0) {
+        ERROR("Could not get information on new domain");
+        goto out;
+    }
+    shared_info_frame = domctl.u.getdomaininfo.shared_info_frame;
+
+    /* Mark all PFNs as invalid; we allocate on demand */
+    for ( pfn = 0; pfn < p2m_size; pfn++ )
+        p2m[pfn] = INVALID_P2M_ENTRY;
+
+    if(!(mmu = xc_init_mmu_updates(xc_handle, dom))) {
+        ERROR("Could not initialise for MMU updates");
+        goto out;
+    }
+
+    DPRINTF("Reloading memory pages:   0%%\n");
+
+    /*
+     * Now simply read each saved frame into its new machine frame.
+     * We uncanonicalise page tables as we go.
+     */
+    prev_pc = 0;
+
+    n = m = 0;
+    while (1) {
+
+        int j, nr_mfns = 0; 
+
+        this_pc = (n * 100) / p2m_size;
+        if ( (this_pc - prev_pc) >= 5 )
+        {
+            PPRINTF("\b\b\b\b%3d%%", this_pc);
+            prev_pc = this_pc;
+        }
+
+        if (!read_exact(io_fd, &j, sizeof(int))) {
+            ERROR("Error when reading batch size");
+            goto out;
+        }
+
+        PPRINTF("batch %d\n",j);
+
+        if (j == -1) {
+            verify = 1;
+            DPRINTF("Entering page verify mode\n");
+            continue;
+        }
+
+        if (j == -2) {
+            new_ctxt_format = 1;
+            if (!read_exact(io_fd, &max_vcpu_id, sizeof(int)) ||
+                (max_vcpu_id >= 64) ||
+                !read_exact(io_fd, &vcpumap, sizeof(uint64_t))) {
+                ERROR("Error when reading max_vcpu_id");
+                goto out;
+            }
+            continue;
+        }
+
+        if (j == 0)
+            break;  /* our work here is done */
+
+        if (j > MAX_BATCH_SIZE) {
+            ERROR("Max batch size exceeded. Giving up.");
+            goto out;
+        }
+
+        if (!read_exact(io_fd, region_pfn_type, j*sizeof(unsigned long))) {
+            ERROR("Error when reading region pfn types");
+            goto out;
+        }
+
+        /* First pass for this batch: work out how much memory to alloc */
+        nr_mfns = 0; 
+        for ( i = 0; i < j; i++ )
+        {
+            unsigned long pfn, pagetype;
+            pfn      = region_pfn_type[i] & ~XEN_DOMCTL_PFINFO_LTAB_MASK;
+            pagetype = region_pfn_type[i] &  XEN_DOMCTL_PFINFO_LTAB_MASK;
+
+            if ( (pagetype != XEN_DOMCTL_PFINFO_XTAB) && 
+                 (p2m[pfn] == INVALID_P2M_ENTRY) )
+            {
+                /* Have a live PFN which hasn't had an MFN allocated */
+                p2m_batch[nr_mfns++] = pfn; 
+            }
+        } 
+
+
+        /* Now allocate a bunch of mfns for this batch */
+        if (nr_mfns && xc_domain_memory_populate_physmap(
+                xc_handle, dom, nr_mfns, 0, 0, p2m_batch) != 0) { 
+            ERROR("Failed to allocate memory for batch.!\n"); 
+            errno = ENOMEM;
+            goto out;
+        }
+
+        /* Second pass for this batch: update p2m[] and region_mfn[] */
+        nr_mfns = 0; 
+        for ( i = 0; i < j; i++ )
+        {
+            unsigned long pfn, pagetype;
+            pfn      = region_pfn_type[i] & ~XEN_DOMCTL_PFINFO_LTAB_MASK;
+            pagetype = region_pfn_type[i] &  XEN_DOMCTL_PFINFO_LTAB_MASK;
+
+            if ( pagetype == XEN_DOMCTL_PFINFO_XTAB)
+                region_mfn[i] = ~0UL; /* map will fail but we don't care */
+            else 
+            {
+                if (p2m[pfn] == INVALID_P2M_ENTRY) {
+                    /* We just allocated a new mfn above; update p2m */
+                    p2m[pfn] = p2m_batch[nr_mfns++]; 
+                    nr_pfns++; 
+                }
+
+                /* setup region_mfn[] for batch map.
+                 * For HVM guests, this interface takes PFNs, not MFNs */
+                region_mfn[i] = hvm ? pfn : p2m[pfn]; 
+            }
+        } 
+
+        /* Map relevant mfns */
+        region_base = xc_map_foreign_batch(
+            xc_handle, dom, PROT_WRITE, region_mfn, j);
+
+        if ( region_base == NULL )
+        {
+            ERROR("map batch failed");
+            goto out;
+        }
+
+        for ( i = 0; i < j; i++ )
+        {
+            void *page;
+            unsigned long pagetype;
+
+            pfn      = region_pfn_type[i] & ~XEN_DOMCTL_PFINFO_LTAB_MASK;
+            pagetype = region_pfn_type[i] &  XEN_DOMCTL_PFINFO_LTAB_MASK;
+
+            if ( pagetype == XEN_DOMCTL_PFINFO_XTAB )
+                /* a bogus/unmapped page: skip it */
+                continue;
+
+            if ( pfn > p2m_size )
+            {
+                ERROR("pfn out of range");
+                goto out;
+            }
+
+            pfn_type[pfn] = pagetype;
+
+            mfn = p2m[pfn];
+
+            /* In verify mode, we use a copy; otherwise we work in place */
+            page = verify ? (void *)buf : (region_base + i*PAGE_SIZE);
+
+            if (!read_exact(io_fd, page, PAGE_SIZE)) {
+                ERROR("Error when reading page (type was %lx)", pagetype);
+                goto out;
+            }
+
+            pagetype &= XEN_DOMCTL_PFINFO_LTABTYPE_MASK;
+
+            if ( (pagetype >= XEN_DOMCTL_PFINFO_L1TAB) && 
+                 (pagetype <= XEN_DOMCTL_PFINFO_L4TAB) )
+            {
+                /*
+                ** A page table page - need to 'uncanonicalize' it, i.e.
+                ** replace all the references to pfns with the corresponding
+                ** mfns for the new domain.
+                **
+                ** On PAE we need to ensure that PGDs are in MFNs < 4G, and
+                ** so we may need to update the p2m after the main loop.
+                ** Hence we defer canonicalization of L1s until then.
+                */
+                if ((pt_levels != 3) ||
+                    pae_extended_cr3 ||
+                    (pagetype != XEN_DOMCTL_PFINFO_L1TAB)) {
+
+                    if (!uncanonicalize_pagetable(xc_handle, dom, 
+                                                  pagetype, page)) {
+                        /*
+                        ** Failing to uncanonicalize a page table can be ok
+                        ** under live migration since the pages type may have
+                        ** changed by now (and we'll get an update later).
+                        */
+                        DPRINTF("PT L%ld race on pfn=%08lx mfn=%08lx\n",
+                                pagetype >> 28, pfn, mfn);
+                        nraces++;
+                        continue;
+                    } 
+                }
+            }
+            else if ( pagetype != XEN_DOMCTL_PFINFO_NOTAB )
+            {
+                ERROR("Bogus page type %lx page table is out of range: "
+                    "i=%d p2m_size=%lu", pagetype, i, p2m_size);
+                goto out;
+
+            }
+
+
+            if (verify) {
+
+                int res = memcmp(buf, (region_base + i*PAGE_SIZE), PAGE_SIZE);
+
+                if (res) {
+
+                    int v;
+
+                    DPRINTF("************** pfn=%lx type=%lx gotcs=%08lx "
+                            "actualcs=%08lx\n", pfn, pfn_type[pfn],
+                            csum_page(region_base + i*PAGE_SIZE),
+                            csum_page(buf));
+
+                    for (v = 0; v < 4; v++) {
+
+                        unsigned long *p = (unsigned long *)
+                            (region_base + i*PAGE_SIZE);
+                        if (buf[v] != p[v])
+                            DPRINTF("    %d: %08lx %08lx\n", v, buf[v], p[v]);
+                    }
+                }
+            }
+
+            if (!hvm 
+                && xc_add_mmu_update(xc_handle, mmu,
+                                     (((unsigned long long)mfn) << PAGE_SHIFT)
+                                     | MMU_MACHPHYS_UPDATE, pfn)) {
+                ERROR("failed machpys update mfn=%lx pfn=%lx", mfn, pfn);
+                goto out;
+            }
+        } /* end of 'batch' for loop */
+
+        munmap(region_base, j*PAGE_SIZE);
+        n+= j; /* crude stats */
+
+        /* 
+         * Discard cache for portion of file read so far up to last
+         *  page boundary every 16MB or so.
+         */
+        m += j;
+        if ( m > MAX_PAGECACHE_USAGE )
+        {
+            discard_file_cache(io_fd, 0 /* no flush */);
+            m = 0;
+        }
+    }
+
+    /*
+     * Ensure we flush all machphys updates before potential PAE-specific
+     * reallocations below.
+     */
+    if (!hvm && xc_finish_mmu_updates(xc_handle, mmu)) {
+        ERROR("Error doing finish_mmu_updates()");
+        goto out;
+    }
+
+    DPRINTF("Received all pages (%d races)\n", nraces);
+
+    if ( hvm ) 
+    {
+        uint32_t rec_len;
+
+        /* Set HVM-specific parameters */
+        if ( !read_exact(io_fd, magic_pfns, sizeof(magic_pfns)) )
+        {
+            ERROR("error reading magic page addresses");
+            goto out;
+        }
+        
+        /* These comms pages need to be zeroed at the start of day */
+        if ( xc_clear_domain_page(xc_handle, dom, magic_pfns[0]) ||
+             xc_clear_domain_page(xc_handle, dom, magic_pfns[1]) ||
+             xc_clear_domain_page(xc_handle, dom, magic_pfns[2]) )
+        {
+            ERROR("error zeroing magic pages");
+            goto out;
+        }
+        
+        xc_set_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN, magic_pfns[0]);
+        xc_set_hvm_param(xc_handle, dom, HVM_PARAM_BUFIOREQ_PFN, 
magic_pfns[1]);
+        xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, magic_pfns[2]);
+        xc_set_hvm_param(xc_handle, dom, HVM_PARAM_PAE_ENABLED, pae);
+        xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_EVTCHN, store_evtchn);
+        *store_mfn = magic_pfns[2];
+
+        /* Read vcpu contexts */
+        for (i = 0; i <= max_vcpu_id; i++) 
+        {
+            if (!(vcpumap & (1ULL << i)))
+                continue;
+
+            if ( !read_exact(io_fd, &(ctxt), sizeof(ctxt)) )
+            {
+                ERROR("error read vcpu context.\n");
+                goto out;
+            }
+            
+            if ( (rc = xc_vcpu_setcontext(xc_handle, dom, i, &ctxt)) )
+            {
+                ERROR("Could not set vcpu context, rc=%d", rc);
+                goto out;
+            }
+            rc = 1;
+        }
+
+        /* Read HVM context */
+        if ( !read_exact(io_fd, &rec_len, sizeof(uint32_t)) )
+        {
+            ERROR("error read hvm context size!\n");
+            goto out;
+        }
+        
+        hvm_buf = malloc(rec_len);
+        if ( hvm_buf == NULL )
+        {
+            ERROR("memory alloc for hvm context buffer failed");
+            errno = ENOMEM;
+            goto out;
+        }
+        
+        if ( !read_exact(io_fd, hvm_buf, rec_len) )
+        {
+            ERROR("error loading the HVM context");
+            goto out;
+        }
+        
+        rc = xc_domain_hvm_setcontext(xc_handle, dom, hvm_buf, rec_len);
+        if ( rc ) 
+            ERROR("error setting the HVM context");
+       
+        goto out;
+    }
+
+    /* Non-HVM guests only from here on */
+
+    if ((pt_levels == 3) && !pae_extended_cr3) {
+
+        /*
+        ** XXX SMH on PAE we need to ensure PGDs are in MFNs < 4G. This
+        ** is a little awkward and involves (a) finding all such PGDs and
+        ** replacing them with 'lowmem' versions; (b) upating the p2m[]
+        ** with the new info; and (c) canonicalizing all the L1s using the
+        ** (potentially updated) p2m[].
+        **
+        ** This is relatively slow (and currently involves two passes through
+        ** the pfn_type[] array), but at least seems to be correct. May wish
+        ** to consider more complex approaches to optimize this later.
+        */
+
+        int j, k;
+        
+        /* First pass: find all L3TABs current in > 4G mfns and get new mfns */
+        for ( i = 0; i < p2m_size; i++ )
+        {
+            if ( ((pfn_type[i] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK) ==
+                  XEN_DOMCTL_PFINFO_L3TAB) &&
+                 (p2m[i] > 0xfffffUL) )
+            {
+                unsigned long new_mfn;
+                uint64_t l3ptes[4];
+                uint64_t *l3tab;
+
+                l3tab = (uint64_t *)
+                    xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
+                                         PROT_READ, p2m[i]);
+
+                for(j = 0; j < 4; j++)
+                    l3ptes[j] = l3tab[j];
+
+                munmap(l3tab, PAGE_SIZE);
+
+                if (!(new_mfn=xc_make_page_below_4G(xc_handle, dom, p2m[i]))) {
+                    ERROR("Couldn't get a page below 4GB :-(");
+                    goto out;
+                }
+
+                p2m[i] = new_mfn;
+                if (xc_add_mmu_update(xc_handle, mmu,
+                                      (((unsigned long long)new_mfn)
+                                       << PAGE_SHIFT) |
+                                      MMU_MACHPHYS_UPDATE, i)) {
+                    ERROR("Couldn't m2p on PAE root pgdir");
+                    goto out;
+                }
+
+                l3tab = (uint64_t *)
+                    xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
+                                         PROT_READ | PROT_WRITE, p2m[i]);
+
+                for(j = 0; j < 4; j++)
+                    l3tab[j] = l3ptes[j];
+
+                munmap(l3tab, PAGE_SIZE);
+
+            }
+        }
+
+        /* Second pass: find all L1TABs and uncanonicalize them */
+        j = 0;
+
+        for ( i = 0; i < p2m_size; i++ )
+        {
+            if ( ((pfn_type[i] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK) ==
+                  XEN_DOMCTL_PFINFO_L1TAB) )
+            {
+                region_mfn[j] = p2m[i];
+                j++;
+            }
+
+            if(i == (p2m_size-1) || j == MAX_BATCH_SIZE) {
+
+                if (!(region_base = xc_map_foreign_batch(
+                          xc_handle, dom, PROT_READ | PROT_WRITE,
+                          region_mfn, j))) {
+                    ERROR("map batch failed");
+                    goto out;
+                }
+
+                for(k = 0; k < j; k++) {
+                    if(!uncanonicalize_pagetable(xc_handle, dom, 
+                                                 XEN_DOMCTL_PFINFO_L1TAB,
+                                                 region_base + k*PAGE_SIZE)) {
+                        ERROR("failed uncanonicalize pt!");
+                        goto out;
+                    }
+                }
+
+                munmap(region_base, j*PAGE_SIZE);
+                j = 0;
+            }
+        }
+
+        if (xc_finish_mmu_updates(xc_handle, mmu)) {
+            ERROR("Error doing finish_mmu_updates()");
+            goto out;
+        }
+    }
+
+    /*
+     * Pin page tables. Do this after writing to them as otherwise Xen
+     * will barf when doing the type-checking.
+     */
+    nr_pins = 0;
+    for ( i = 0; i < p2m_size; i++ )
+    {
+        if ( (pfn_type[i] & XEN_DOMCTL_PFINFO_LPINTAB) == 0 )
+            continue;
+
+        switch ( pfn_type[i] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK )
+        {
+        case XEN_DOMCTL_PFINFO_L1TAB:
+            pin[nr_pins].cmd = MMUEXT_PIN_L1_TABLE;
+            break;
+
+        case XEN_DOMCTL_PFINFO_L2TAB:
+            pin[nr_pins].cmd = MMUEXT_PIN_L2_TABLE;
+            break;
+
+        case XEN_DOMCTL_PFINFO_L3TAB:
+            pin[nr_pins].cmd = MMUEXT_PIN_L3_TABLE;
+            break;
+
+        case XEN_DOMCTL_PFINFO_L4TAB:
+            pin[nr_pins].cmd = MMUEXT_PIN_L4_TABLE;
+            break;
+
+        default:
+            continue;
+        }
+
+        pin[nr_pins].arg1.mfn = p2m[i];
+        nr_pins++;
+
+        /* Batch full? Then flush. */
+        if (nr_pins == MAX_PIN_BATCH) {
+            if (xc_mmuext_op(xc_handle, pin, nr_pins, dom) < 0) {
+                ERROR("Failed to pin batch of %d page tables", nr_pins);
+                goto out;
+            }
+            nr_pins = 0;
+        }
+    }
+
+    /* Flush final partial batch. */
+    if ((nr_pins != 0) && (xc_mmuext_op(xc_handle, pin, nr_pins, dom) < 0)) {
+        ERROR("Failed to pin batch of %d page tables", nr_pins);
+        goto out;
+    }
+
+    DPRINTF("\b\b\b\b100%%\n");
+    DPRINTF("Memory reloaded (%ld pages)\n", nr_pfns);
+
+    /* Get the list of PFNs that are not in the psuedo-phys map */
+    {
+        unsigned int count;
+        unsigned long *pfntab;
+        int nr_frees, rc;
+
+        if (!read_exact(io_fd, &count, sizeof(count))) {
+            ERROR("Error when reading pfn count");
+            goto out;
+        }
+
+        if(!(pfntab = malloc(sizeof(unsigned long) * count))) {
+            ERROR("Out of memory");
+            goto out;
+        }
+
+        if (!read_exact(io_fd, pfntab, sizeof(unsigned long)*count)) {
+            ERROR("Error when reading pfntab");
+            goto out;
+        }
+
+        nr_frees = 0; 
+        for (i = 0; i < count; i++) {
+
+            unsigned long pfn = pfntab[i];
+
+            if(p2m[pfn] != INVALID_P2M_ENTRY) {
+                /* pfn is not in physmap now, but was at some point during 
+                   the save/migration process - need to free it */
+                pfntab[nr_frees++] = p2m[pfn];
+                p2m[pfn]  = INVALID_P2M_ENTRY; // not in pseudo-physical map
+            }
+        }
+
+        if (nr_frees > 0) {
+
+            struct xen_memory_reservation reservation = {
+                .nr_extents   = nr_frees,
+                .extent_order = 0,
+                .domid        = dom
+            };
+            set_xen_guest_handle(reservation.extent_start, pfntab);
+
+            if ((rc = xc_memory_op(xc_handle, XENMEM_decrease_reservation,
+                                   &reservation)) != nr_frees) {
+                ERROR("Could not decrease reservation : %d", rc);
+                goto out;
+            } else
+                DPRINTF("Decreased reservation by %d pages\n", count);
+        }
+    }
+
+    for (i = 0; i <= max_vcpu_id; i++) {
+        if (!(vcpumap & (1ULL << i)))
+            continue;
+
+        if (!read_exact(io_fd, &ctxt, sizeof(ctxt))) {
+            ERROR("Error when reading ctxt %d", i);
+            goto out;
+        }
+
+        if ( !new_ctxt_format )
+            ctxt.flags |= VGCF_online;
+
+        if (i == 0) {
+            /*
+             * Uncanonicalise the suspend-record frame number and poke
+             * resume record.
+             */
+            pfn = ctxt.user_regs.edx;
+            if ((pfn >= p2m_size) ||
+                (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB)) {
+                ERROR("Suspend record frame number is bad");
+                goto out;
+            }
+            ctxt.user_regs.edx = mfn = p2m[pfn];
+            start_info = xc_map_foreign_range(
+                xc_handle, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, mfn);
+            start_info->nr_pages = p2m_size;
+            start_info->shared_info = shared_info_frame << PAGE_SHIFT;
+            start_info->flags = 0;
+            *store_mfn = start_info->store_mfn = p2m[start_info->store_mfn];
+            start_info->store_evtchn = store_evtchn;
+            start_info->console.domU.mfn = p2m[start_info->console.domU.mfn];
+            start_info->console.domU.evtchn = console_evtchn;
+            *console_mfn = start_info->console.domU.mfn;
+            munmap(start_info, PAGE_SIZE);
+        }
+
+        /* Uncanonicalise each GDT frame number. */
+        if (ctxt.gdt_ents > 8192) {
+            ERROR("GDT entry count out of range");
+            goto out;
+        }
+
+        for (j = 0; (512*j) < ctxt.gdt_ents; j++) {
+            pfn = ctxt.gdt_frames[j];
+            if ((pfn >= p2m_size) ||
+                (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB)) {
+                ERROR("GDT frame number is bad");
+                goto out;
+            }
+            ctxt.gdt_frames[j] = p2m[pfn];
+        }
+
+        /* Uncanonicalise the page table base pointer. */
+        pfn = xen_cr3_to_pfn(ctxt.ctrlreg[3]);
+
+        if (pfn >= p2m_size) {
+            ERROR("PT base is bad: pfn=%lu p2m_size=%lu type=%08lx",
+                  pfn, p2m_size, pfn_type[pfn]);
+            goto out;
+        }
+
+        if ( (pfn_type[pfn] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK) !=
+             ((unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT) ) {
+            ERROR("PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx",
+                  pfn, p2m_size, pfn_type[pfn],
+                  (unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT);
+            goto out;
+        }
+
+        ctxt.ctrlreg[3] = xen_pfn_to_cr3(p2m[pfn]);
+
+        /* Guest pagetable (x86/64) stored in otherwise-unused CR1. */
+        if ( (pt_levels == 4) && ctxt.ctrlreg[1] )
+        {
+            pfn = xen_cr3_to_pfn(ctxt.ctrlreg[1]);
+
+            if (pfn >= p2m_size) {
+                ERROR("User PT base is bad: pfn=%lu p2m_size=%lu type=%08lx",
+                      pfn, p2m_size, pfn_type[pfn]);
+                goto out;
+            }
+
+            if ( (pfn_type[pfn] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK) !=
+                 ((unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT) ) {
+                ERROR("User PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx",
+                      pfn, p2m_size, pfn_type[pfn],
+                      (unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT);
+                goto out;
+            }
+
+            ctxt.ctrlreg[1] = xen_pfn_to_cr3(p2m[pfn]);
+        }
+
+        domctl.cmd = XEN_DOMCTL_setvcpucontext;
+        domctl.domain = (domid_t)dom;
+        domctl.u.vcpucontext.vcpu = i;
+        set_xen_guest_handle(domctl.u.vcpucontext.ctxt, &ctxt);
+        rc = xc_domctl(xc_handle, &domctl);
+        if (rc != 0) {
+            ERROR("Couldn't build vcpu%d", i);
+            goto out;
+        }
+        rc = 1;
+    }
+
+    if (!read_exact(io_fd, shared_info_page, PAGE_SIZE)) {
+        ERROR("Error when reading shared info page");
+        goto out;
+    }
+
+    /* clear any pending events and the selector */
+    memset(&(shared_info->evtchn_pending[0]), 0,
+           sizeof (shared_info->evtchn_pending));
+    for ( i = 0; i < MAX_VIRT_CPUS; i++ )
+        shared_info->vcpu_info[i].evtchn_pending_sel = 0;
+
+    /* Copy saved contents of shared-info page. No checking needed. */
+    page = xc_map_foreign_range(
+        xc_handle, dom, PAGE_SIZE, PROT_WRITE, shared_info_frame);
+    memcpy(page, shared_info, PAGE_SIZE);
+    munmap(page, PAGE_SIZE);
+
+    /* Uncanonicalise the pfn-to-mfn table frame-number list. */
+    for (i = 0; i < P2M_FL_ENTRIES; i++) {
+        pfn = p2m_frame_list[i];
+        if ((pfn >= p2m_size) || (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB)) {
+            ERROR("PFN-to-MFN frame number is bad");
+            goto out;
+        }
+
+        p2m_frame_list[i] = p2m[pfn];
+    }
+
+    /* Copy the P2M we've constructed to the 'live' P2M */
+    if (!(live_p2m = xc_map_foreign_batch(xc_handle, dom, PROT_WRITE,
+                                          p2m_frame_list, P2M_FL_ENTRIES))) {
+        ERROR("Couldn't map p2m table");
+        goto out;
+    }
+
+    memcpy(live_p2m, p2m, ROUNDUP(p2m_size * sizeof(xen_pfn_t), PAGE_SHIFT));
+    munmap(live_p2m, ROUNDUP(p2m_size * sizeof(xen_pfn_t), PAGE_SHIFT));
+
+    DPRINTF("Domain ready to be built.\n");
+    rc = 0;
+
+ out:
+    if ( (rc != 0) && (dom != 0) )
+        xc_domain_destroy(xc_handle, dom);
+    free(mmu);
+    free(p2m);
+    free(pfn_type);
+    free(hvm_buf);
+
+    /* discard cache for save file  */
+    discard_file_cache(io_fd, 1 /*flush*/);
+
+    DPRINTF("Restore exit with rc=%d\n", rc);
+    
+    return rc;
+}
diff -r 9ec7dadc98ba -r eb3e430242ac tools/libxc/xc_hvm_restore.c
--- a/tools/libxc/xc_hvm_restore.c      Fri Apr 06 10:06:30 2007 -0600
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,360 +0,0 @@
-/******************************************************************************
- * xc_hvm_restore.c
- *
- * Restore the state of a HVM guest.
- *
- * Copyright (c) 2003, K A Fraser.
- * Copyright (c) 2006 Intel Corperation
- * rewriten for hvm guest by Zhai Edwin <edwin.zhai@xxxxxxxxx>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- */
-
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "xg_private.h"
-#include "xg_save_restore.h"
-
-#include <xen/hvm/ioreq.h>
-#include <xen/hvm/params.h>
-#include <xen/hvm/e820.h>
-
-/* max mfn of the whole machine */
-static unsigned long max_mfn;
-
-/* virtual starting address of the hypervisor */
-static unsigned long hvirt_start;
-
-/* #levels of page tables used by the currrent guest */
-static unsigned int pt_levels;
-
-/* A list of PFNs that exist, used when allocating memory to the guest */
-static xen_pfn_t *pfns = NULL;
-
-static ssize_t
-read_exact(int fd, void *buf, size_t count)
-{
-    int r = 0, s;
-    unsigned char *b = buf;
-
-    while (r < count) {
-        s = read(fd, &b[r], count - r);
-        if ((s == -1) && (errno == EINTR))
-            continue;
-        if (s <= 0) {
-            break;
-        }
-        r += s;
-    }
-
-    return (r == count) ? 1 : 0;
-}
-
-int xc_hvm_restore(int xc_handle, int io_fd,
-                     uint32_t dom, unsigned long max_pfn,
-                     unsigned int store_evtchn, unsigned long *store_mfn,
-                     unsigned int pae, unsigned int apic)
-{
-    DECLARE_DOMCTL;
-
-    /* A copy of the CPU context of the guest. */
-    vcpu_guest_context_t ctxt;
-
-    char *region_base;
-
-    unsigned long buf[PAGE_SIZE/sizeof(unsigned long)];
-
-    xc_dominfo_t info;
-    unsigned int rc = 1, n, i;
-    uint32_t rec_len, nr_vcpus;
-    uint8_t *hvm_buf = NULL;
-    unsigned long long v_end;
-    unsigned long shared_page_nr;
-
-    unsigned long pfn;
-    unsigned int prev_pc, this_pc;
-    int verify = 0;
-
-    /* Types of the pfns in the current region */
-    unsigned long region_pfn_type[MAX_BATCH_SIZE];
-
-    /* The size of an array big enough to contain all guest pfns */
-    unsigned long pfn_array_size = max_pfn + 1;
-
-    /* Number of pages of memory the guest has.  *Not* the same as max_pfn. */
-    unsigned long nr_pages = max_pfn;
-    /* MMIO hole doesn't contain RAM */
-    if ( nr_pages >= HVM_BELOW_4G_MMIO_START >> PAGE_SHIFT ) 
-        nr_pages -= HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT; 
-    /* VGA hole doesn't contain RAM */
-    nr_pages -= 0x20;
-
-    /* XXX: Unlikely to be true, but matches previous behaviour. :( */
-    v_end = (nr_pages + 0x20) << PAGE_SHIFT;
-
-    DPRINTF("xc_hvm_restore:dom=%d, nr_pages=0x%lx, store_evtchn=%d, "
-            "*store_mfn=%ld, pae=%u, apic=%u.\n", 
-            dom, nr_pages, store_evtchn, *store_mfn, pae, apic);
-
-    if(!get_platform_info(xc_handle, dom,
-                          &max_mfn, &hvirt_start, &pt_levels)) {
-        ERROR("Unable to get platform info.");
-        return 1;
-    }
-
-    DPRINTF("xc_hvm_restore start: nr_pages = %lx, max_pfn = %lx, "
-            "max_mfn = %lx, hvirt_start=%lx, pt_levels=%d\n",
-            nr_pages, max_pfn, max_mfn, hvirt_start, pt_levels);
-
-    if (mlock(&ctxt, sizeof(ctxt))) {
-        /* needed for build dom0 op, but might as well do early */
-        ERROR("Unable to mlock ctxt");
-        return 1;
-    }
-
-
-    pfns = malloc(pfn_array_size * sizeof(xen_pfn_t));
-    if (pfns == NULL) {
-        ERROR("memory alloc failed");
-        errno = ENOMEM;
-        goto out;
-    }
-
-    if(xc_domain_setmaxmem(xc_handle, dom, PFN_TO_KB(nr_pages)) != 0) {
-        errno = ENOMEM;
-        goto out;
-    }
-
-    for ( i = 0; i < pfn_array_size; i++ )
-        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;
-
-    /* Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000. */
-    rc = xc_domain_memory_populate_physmap(
-        xc_handle, dom, (nr_pages > 0xa0) ? 0xa0 : nr_pages,
-        0, 0, &pfns[0x00]);
-    if ( (rc == 0) && (nr_pages > 0xc0) )
-        rc = xc_domain_memory_populate_physmap(
-            xc_handle, dom, nr_pages - 0xa0, 0, 0, &pfns[0xc0]);
-    if ( rc != 0 )
-    {
-        PERROR("Could not allocate memory for HVM guest.\n");
-        goto out;
-    }
-
-
-    /**********XXXXXXXXXXXXXXXX******************/
-    if (xc_domain_getinfo(xc_handle, dom, 1, &info) != 1) {
-        ERROR("Could not get domain info");
-        return 1;
-    }
-
-    domctl.cmd = XEN_DOMCTL_getdomaininfo;
-    domctl.domain = (domid_t)dom;
-    if (xc_domctl(xc_handle, &domctl) < 0) {
-        ERROR("Could not get information on new domain");
-        goto out;
-    }
-
-    prev_pc = 0;
-
-    n = 0;
-    while (1) {
-
-        int j;
-
-        this_pc = (n * 100) / nr_pages;
-        if ( (this_pc - prev_pc) >= 5 )
-        {
-            PPRINTF("\b\b\b\b%3d%%", this_pc);
-            prev_pc = this_pc;
-        }
-
-        if (!read_exact(io_fd, &j, sizeof(int))) {
-            ERROR("HVM restore Error when reading batch size");
-            goto out;
-        }
-
-        PPRINTF("batch %d\n",j);
-
-        if (j == -1) {
-            verify = 1;
-            DPRINTF("Entering page verify mode\n");
-            continue;
-        }
-
-        if (j == 0)
-            break;  /* our work here is done */
-
-        if (j > MAX_BATCH_SIZE) {
-            ERROR("Max batch size exceeded. Giving up.");
-            goto out;
-        }
-
-        if (!read_exact(io_fd, region_pfn_type, j*sizeof(unsigned long))) {
-            ERROR("Error when reading region pfn types");
-            goto out;
-        }
-
-        region_base = xc_map_foreign_batch(
-            xc_handle, dom, PROT_WRITE, region_pfn_type, j);
-
-        for ( i = 0; i < j; i++ )
-        {
-            void *page;
-
-            pfn = region_pfn_type[i];
-            if ( pfn & XEN_DOMCTL_PFINFO_LTAB_MASK )
-                continue;
-
-            if ( pfn > max_pfn )
-            {
-                ERROR("pfn out of range");
-                goto out;
-            }
-
-            if ( pfn >= 0xa0 && pfn < 0xc0) {
-                ERROR("hvm restore:pfn in vga hole");
-                goto out;
-            }
-
-
-            /* In verify mode, we use a copy; otherwise we work in place */
-            page = verify ? (void *)buf : (region_base + i*PAGE_SIZE);
-
-            if (!read_exact(io_fd, page, PAGE_SIZE)) {
-                ERROR("Error when reading page (%x)", i);
-                goto out;
-            }
-
-            if (verify) {
-
-                int res = memcmp(buf, (region_base + i*PAGE_SIZE), PAGE_SIZE);
-
-                if (res) {
-
-                    int v;
-
-                    DPRINTF("************** pfn=%lx gotcs=%08lx "
-                            "actualcs=%08lx\n", pfn, 
-                            csum_page(region_base + i*PAGE_SIZE),
-                            csum_page(buf));
-
-                    for (v = 0; v < 4; v++) {
-
-                        unsigned long *p = (unsigned long *)
-                            (region_base + i*PAGE_SIZE);
-                        if (buf[v] != p[v])
-                            DPRINTF("    %d: %08lx %08lx\n", v, buf[v], p[v]);
-                    }
-                }
-            }
-
-        } /* end of 'batch' for loop */
-        munmap(region_base, j*PAGE_SIZE);
-        n+= j; /* crude stats */
-
-    }/*while 1*/
-    
-    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_PAE_ENABLED, pae);
-    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_EVTCHN, store_evtchn);
-
-    if ( v_end > HVM_BELOW_4G_RAM_END )
-        shared_page_nr = (HVM_BELOW_4G_RAM_END >> PAGE_SHIFT) - 1;
-    else
-        shared_page_nr = (v_end >> PAGE_SHIFT) - 1;
-
-    /* Ensure we clear these pages */
-    if ( xc_clear_domain_page(xc_handle, dom, shared_page_nr) ||
-         xc_clear_domain_page(xc_handle, dom, shared_page_nr-1) ||
-         xc_clear_domain_page(xc_handle, dom, shared_page_nr-2) ) {
-        rc = -1;
-        goto out;
-    }
-
-    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, shared_page_nr-1);
-    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_BUFIOREQ_PFN, shared_page_nr-2);
-    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN, shared_page_nr);
-
-    /* caculate the store_mfn , wrong val cause hang when introduceDomain */
-    *store_mfn = (v_end >> PAGE_SHIFT) - 2;
-    DPRINTF("hvm restore: calculate new store_mfn=0x%lx, v_end=0x%llx.\n", 
-            *store_mfn, v_end);
-
-    if (!read_exact(io_fd, &nr_vcpus, sizeof(uint32_t))) {
-        ERROR("error read nr vcpu !\n");
-        goto out;
-    }
-    DPRINTF("hvm restore:get nr_vcpus=%d.\n", nr_vcpus);
-
-    for (i =0; i < nr_vcpus; i++) {
-        if (!read_exact(io_fd, &rec_len, sizeof(uint32_t))) {
-            ERROR("error read vcpu context size!\n");
-            goto out;
-        }
-        if (rec_len != sizeof(ctxt)) {
-            ERROR("vcpu context size dismatch!\n");
-            goto out;
-        }
-
-        if (!read_exact(io_fd, &(ctxt), sizeof(ctxt))) {
-            ERROR("error read vcpu context.\n");
-            goto out;
-        }
-
-        if ( (rc = xc_vcpu_setcontext(xc_handle, dom, i, &ctxt)) ) {
-            ERROR("Could not set vcpu context, rc=%d", rc);
-            goto out;
-        }
-    }
-
-    /* restore hvm context including pic/pit/shpage */
-    if (!read_exact(io_fd, &rec_len, sizeof(uint32_t))) {
-        ERROR("error read hvm context size!\n");
-        goto out;
-    }
-
-    hvm_buf = malloc(rec_len);
-    if (hvm_buf == NULL) {
-        ERROR("memory alloc for hvm context buffer failed");
-        errno = ENOMEM;
-        goto out;
-    }
-
-    if (!read_exact(io_fd, hvm_buf, rec_len)) {
-        ERROR("error read hvm buffer!\n");
-        goto out;
-    }
-
-    if (( rc = xc_domain_hvm_setcontext(xc_handle, dom, hvm_buf, rec_len))) {
-        ERROR("error set hvm buffer!\n");
-        goto out;
-    }
-
-    rc = 0;
-    goto out;
-
- out:
-    if ( (rc != 0) && (dom != 0) )
-        xc_domain_destroy(xc_handle, dom);
-    free(pfns);
-    free(hvm_buf);
-
-    DPRINTF("Restore exit with rc=%d\n", rc);
-
-    return rc;
-}
diff -r 9ec7dadc98ba -r eb3e430242ac tools/libxc/xc_hvm_save.c
--- a/tools/libxc/xc_hvm_save.c Fri Apr 06 10:06:30 2007 -0600
+++ b/tools/libxc/xc_hvm_save.c Fri Apr 06 10:08:30 2007 -0600
@@ -45,36 +45,10 @@
 #define DEF_MAX_ITERS   29   /* limit us to 30 times round loop   */
 #define DEF_MAX_FACTOR   3   /* never send more than 3x nr_pfns   */
 
-/* max mfn of the whole machine */
-static unsigned long max_mfn;
-
-/* virtual starting address of the hypervisor */
-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;
-    xen_hvm_drain_io_t arg;
-    int rc;
-
-    hypercall.op     = __HYPERVISOR_hvm_op;
-    hypercall.arg[0] = HVMOP_drain_io;
-    hypercall.arg[1] = (unsigned long)&arg;
-    arg.domid = dom;
-    if ( lock_pages(&arg, sizeof(arg)) != 0 )
-        return -1;
-    rc = do_xen_hypercall(handle, &hypercall);
-    unlock_pages(&arg, sizeof(arg));
-    return rc;
-}
 
 /*
 ** During (live) save/migrate, we maintain a number of bitmaps to track
@@ -291,9 +265,8 @@ int xc_hvm_save(int xc_handle, int io_fd
     xc_dominfo_t info;
 
     int rc = 1, i, j, last_iter, iter = 0;
-    int live  = (flags & XCFLAGS_LIVE);
-    int debug = (flags & XCFLAGS_DEBUG);
-    int stdvga = (flags & XCFLAGS_STDVGA);
+    int live  = !!(flags & XCFLAGS_LIVE);
+    int debug = !!(flags & XCFLAGS_DEBUG);
     int sent_last_iter, skip_this_iter;
 
     /* The highest guest-physical frame number used by the current guest */
@@ -302,8 +275,8 @@ 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;
 
-    /* Other magic frames: ioreqs and xenstore comms */
-    unsigned long ioreq_pfn, bufioreq_pfn, store_pfn;
+    /* Magic frames: ioreqs and xenstore comms. */
+    uint64_t magic_pfns[3]; /* ioreq_pfn, bufioreq_pfn, store_pfn */
 
     /* A copy of the CPU context of the guest. */
     vcpu_guest_context_t ctxt;
@@ -330,122 +303,97 @@ int xc_hvm_save(int xc_handle, int io_fd
 
     xc_shadow_op_stats_t stats;
 
-    unsigned long total_sent    = 0;
+    unsigned long total_sent = 0;
+
+    uint64_t vcpumap = 1ULL;
 
     DPRINTF("xc_hvm_save: dom=%d, max_iters=%d, max_factor=%d, flags=0x%x, "
             "live=%d, debug=%d.\n", dom, max_iters, max_factor, flags,
             live, debug);
     
     /* If no explicit control parameters given, use defaults */
-    if(!max_iters)
-        max_iters = DEF_MAX_ITERS;
-    if(!max_factor)
-        max_factor = DEF_MAX_FACTOR;
+    max_iters  = max_iters  ? : DEF_MAX_ITERS;
+    max_factor = max_factor ? : DEF_MAX_FACTOR;
 
     initialize_mbit_rate();
 
-    if(!get_platform_info(xc_handle, dom,
-                          &max_mfn, &hvirt_start, &pt_levels)) {
-        ERROR("HVM:Unable to get platform info.");
+    if ( xc_domain_getinfo(xc_handle, dom, 1, &info) != 1 )
+    {
+        ERROR("HVM: Could not get domain info");
         return 1;
     }
-
-    if (xc_domain_getinfo(xc_handle, dom, 1, &info) != 1) {
-        ERROR("HVM:Could not get domain info");
+    nr_vcpus = info.nr_online_vcpus;
+
+    if ( mlock(&ctxt, sizeof(ctxt)) )
+    {
+        ERROR("HVM: Unable to mlock ctxt");
         return 1;
     }
-    nr_vcpus = info.nr_online_vcpus;
-
-    if (mlock(&ctxt, sizeof(ctxt))) {
-        ERROR("HVM:Unable to mlock ctxt");
-        return 1;
-    }
 
     /* Only have to worry about vcpu 0 even for SMP */
-    if (xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt)) {
-        ERROR("HVM:Could not get vcpu context");
-        goto out;
-    }
-
-    /* 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;
-    }
-
-    if ( xc_get_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, &store_pfn)
-         || xc_get_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN, &ioreq_pfn)
-         || xc_get_hvm_param(xc_handle, dom, 
-                             HVM_PARAM_BUFIOREQ_PFN, &bufioreq_pfn) )
-    {
-        ERROR("HVM: Could not read magic PFN parameters");
-        goto out;
-    }
-    DPRINTF("saved hvm domain info:max_memkb=0x%lx, max_mfn=0x%lx, "
-            "nr_pages=0x%lx\n", info.max_memkb, max_mfn, info.nr_pages); 
-
-    if (live) {
-        
-        if (xc_shadow_control(xc_handle, dom,
-                              XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY,
-                              NULL, 0, NULL, 0, NULL) < 0) {
+    if ( xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt) )
+    {
+        ERROR("HVM: Could not get vcpu context");
+        goto out;
+    }
+
+    DPRINTF("saved hvm domain info: max_memkb=0x%lx, nr_pages=0x%lx\n",
+            info.max_memkb, info.nr_pages); 
+
+    if ( live )
+    {
+        /* Live suspend. Enable log-dirty mode. */
+        if ( xc_shadow_control(xc_handle, dom,
+                               XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY,
+                               NULL, 0, NULL, 0, NULL) < 0 )
+        {
             ERROR("Couldn't enable shadow mode");
             goto out;
         }
 
-        last_iter = 0;
-
         DPRINTF("hvm domain live migration debug start: logdirty enable.\n");
-    } else {
-        /* This is a non-live suspend. Issue the call back to get the
-           domain suspended */
-
-        last_iter = 1;
-
-        /* suspend hvm domain */
-        if (suspend_and_state(suspend, xc_handle, io_fd, dom, &info, &ctxt)) {
+    }
+    else
+    {
+        /* This is a non-live suspend. Suspend the domain .*/
+        if ( suspend_and_state(suspend, xc_handle, io_fd, dom, &info, &ctxt) )
+        {
             ERROR("HVM Domain appears not to have suspended");
             goto out;
         }
     }
 
-    DPRINTF("after 1st handle hvm domain nr_pages=0x%lx, "
+    last_iter = !live;
+
+    max_pfn = xc_memory_op(xc_handle, XENMEM_maximum_gpfn, &dom);
+
+    DPRINTF("after 1st handle hvm domain max_pfn=0x%lx, "
             "max_memkb=0x%lx, live=%d.\n",
-            info.nr_pages, info.max_memkb, live);
-
-    /* Calculate the highest PFN of "normal" memory:
-     * HVM memory is sequential except for the VGA and MMIO holes. */
-    max_pfn = info.nr_pages - 1;
-    /* If the domain has a Cirrus framebuffer and we haven't already 
-     * suspended qemu-dm, it will have 8MB of framebuffer memory 
-     * still allocated, which we don't want to copy: qemu will save it 
-     * for us later */
-    if ( live && !stdvga )
-        max_pfn -= 0x800;
-    /* Skip the VGA hole from 0xa0000 to 0xc0000 */
-    max_pfn += 0x20;
-    /* Skip the MMIO hole: 256MB just below 4GB */
-    if ( max_pfn >= (HVM_BELOW_4G_MMIO_START >> PAGE_SHIFT) )
-        max_pfn += (HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT); 
+            max_pfn, info.max_memkb, live);
 
     /* Size of any array that covers 0 ... max_pfn */
     pfn_array_size = max_pfn + 1;
+    if ( !write_exact(io_fd, &pfn_array_size, sizeof(unsigned long)) )
+    {
+        ERROR("Error when writing to state file (1)");
+        goto out;
+    }
+    
 
     /* pretend we sent all the pages last iteration */
     sent_last_iter = pfn_array_size;
 
     /* calculate the power of 2 order of pfn_array_size, e.g.
        15->4 16->4 17->5 */
-    for (i = pfn_array_size-1, order_nr = 0; i ; i >>= 1, order_nr++)
+    for ( i = pfn_array_size-1, order_nr = 0; i ; i >>= 1, order_nr++ )
         continue;
 
     /* Setup to_send / to_fix and to_skip bitmaps */
     to_send = malloc(BITMAP_SIZE);
     to_skip = malloc(BITMAP_SIZE);
 
-
-    if (live) {
+    if ( live )
+    {
         /* Get qemu-dm logging dirty pages too */
         void *seg = init_qemu_maps(dom, BITMAP_SIZE);
         qemu_bitmaps[0] = seg;
@@ -462,44 +410,40 @@ int xc_hvm_save(int xc_handle, int io_fd
     }
     hvm_buf = malloc(hvm_buf_size);
 
-    if (!to_send ||!to_skip ||!hvm_buf) {
+    if ( !to_send || !to_skip || !hvm_buf )
+    {
         ERROR("Couldn't allocate memory");
         goto out;
     }
 
     memset(to_send, 0xff, BITMAP_SIZE);
 
-    if (lock_pages(to_send, BITMAP_SIZE)) {
+    if ( lock_pages(to_send, BITMAP_SIZE) )
+    {
         ERROR("Unable to lock to_send");
         return 1;
     }
 
     /* (to fix is local only) */
-    if (lock_pages(to_skip, BITMAP_SIZE)) {
+    if ( lock_pages(to_skip, BITMAP_SIZE) )
+    {
         ERROR("Unable to lock to_skip");
         return 1;
     }
 
     analysis_phase(xc_handle, dom, pfn_array_size, to_skip, 0);
 
-
     /* We want zeroed memory so use calloc rather than malloc. */
     pfn_batch = calloc(MAX_BATCH_SIZE, sizeof(*pfn_batch));
-
-    if (pfn_batch == NULL) {
+    if ( pfn_batch == NULL )
+    {
         ERROR("failed to alloc memory for pfn_batch array");
         errno = ENOMEM;
         goto out;
     }
 
-    /* Start writing out the saved-domain record. */
-    if (!write_exact(io_fd, &max_pfn, sizeof(unsigned long))) {
-        ERROR("write: max_pfn");
-        goto out;
-    }
-
-    while(1) {
-
+    for ( ; ; )
+    {
         unsigned int prev_pc, sent_this_iter, N, batch;
 
         iter++;
@@ -510,51 +454,56 @@ int xc_hvm_save(int xc_handle, int io_fd
 
         DPRINTF("Saving HVM domain memory pages: iter %d   0%%", iter);
 
-        while( N < pfn_array_size ){
-
+        while ( N < pfn_array_size )
+        {
             unsigned int this_pc = (N * 100) / pfn_array_size;
             int rc;
 
-            if ((this_pc - prev_pc) >= 5) {
+            if ( (this_pc - prev_pc) >= 5 )
+            {
                 DPRINTF("\b\b\b\b%3d%%", this_pc);
                 prev_pc = this_pc;
             }
 
-            /* slightly wasteful to peek the whole array evey time,
-               but this is fast enough for the moment. */
-            if (!last_iter && (rc = xc_shadow_control(
+            if ( !last_iter )
+            {
+                /* Slightly wasteful to peek the whole array evey time,
+                   but this is fast enough for the moment. */
+                rc = xc_shadow_control(
                     xc_handle, dom, XEN_DOMCTL_SHADOW_OP_PEEK, to_skip, 
-                    pfn_array_size, NULL, 0, NULL)) != pfn_array_size) {
-                ERROR("Error peeking HVM shadow bitmap");
-                goto out;
-            }
-
+                    pfn_array_size, NULL, 0, NULL);
+                if ( rc != pfn_array_size )
+                {
+                    ERROR("Error peeking HVM shadow bitmap");
+                    goto out;
+                }
+            }
 
             /* load pfn_batch[] with the mfn of all the pages we're doing in
                this batch. */
-            for (batch = 0; batch < MAX_BATCH_SIZE && N < pfn_array_size; N++){
-
+            for ( batch = 0;
+                  (batch < MAX_BATCH_SIZE) && (N < pfn_array_size);
+                  N++ )
+            {
                 int n = permute(N, pfn_array_size, order_nr);
 
-                if (0&&debug) {
+                if ( 0 && debug )
                     DPRINTF("%d pfn= %08lx %d \n",
                             iter, (unsigned long)n, test_bit(n, to_send));
-                }
-
-                if (!last_iter && test_bit(n, to_send)&& test_bit(n, to_skip))
+
+                if ( !last_iter &&
+                     test_bit(n, to_send) &&
+                     test_bit(n, to_skip) )
                     skip_this_iter++; /* stats keeping */
 
-                if (!((test_bit(n, to_send) && !test_bit(n, to_skip)) ||
-                      (test_bit(n, to_send) && last_iter)))
+                if ( !((test_bit(n, to_send) && !test_bit(n, to_skip)) ||
+                       (test_bit(n, to_send) && last_iter)) )
                     continue;
 
                 /* Skip PFNs that aren't really there */
-                if ((n >= 0xa0 && n < 0xc0) /* VGA hole */
-                    || (n >= (HVM_BELOW_4G_MMIO_START >> PAGE_SHIFT)
-                        && n < (1ULL << 32) >> PAGE_SHIFT) /* 4G MMIO hole */
-                    || n == store_pfn
-                    || n == ioreq_pfn
-                    || n == bufioreq_pfn)
+                if ( (n >= 0xa0 && n < 0xc0) /* VGA hole */
+                     || (n >= (HVM_BELOW_4G_MMIO_START >> PAGE_SHIFT) &&
+                         n < (1ULL << 32) >> PAGE_SHIFT) /* 4G MMIO hole */ )
                     continue;
 
                 /*
@@ -568,24 +517,27 @@ int xc_hvm_save(int xc_handle, int io_fd
                 batch++;
             }
 
-            if (batch == 0)
+            if ( batch == 0 )
                 goto skip; /* vanishingly unlikely... */
 
-            /* map_foreign use pfns now !*/
-            if ((region_base = xc_map_foreign_batch(
-                     xc_handle, dom, PROT_READ, pfn_batch, batch)) == 0) {
+            region_base = xc_map_foreign_batch(
+                xc_handle, dom, PROT_READ, pfn_batch, batch);
+            if ( region_base == 0 )
+            {
                 ERROR("map batch failed");
                 goto out;
             }
 
             /* write num of pfns */
-            if(!write_exact(io_fd, &batch, sizeof(unsigned int))) {
+            if ( !write_exact(io_fd, &batch, sizeof(unsigned int)) )
+            {
                 ERROR("Error when writing to state file (2)");
                 goto out;
             }
 
             /* write all the pfns */
-            if(!write_exact(io_fd, pfn_batch, sizeof(unsigned long)*batch)) {
+            if ( !write_exact(io_fd, pfn_batch, sizeof(unsigned long)*batch) )
+            {
                 ERROR("Error when writing to state file (3)");
                 goto out;
             }
@@ -615,21 +567,23 @@ int xc_hvm_save(int xc_handle, int io_fd
         DPRINTF("\r %d: sent %d, skipped %d, ",
                 iter, sent_this_iter, skip_this_iter );
 
-        if (last_iter) {
+        if ( last_iter )
+        {
             print_stats( xc_handle, dom, sent_this_iter, &stats, 1);
-
             DPRINTF("Total pages sent= %ld (%.2fx)\n",
                     total_sent, ((float)total_sent)/pfn_array_size );
         }
 
-        if (last_iter && debug){
+        if ( last_iter && debug )
+        {
             int minusone = -1;
             memset(to_send, 0xff, BITMAP_SIZE);
             debug = 0;
             DPRINTF("Entering debug resend-all mode\n");
 
             /* send "-1" to put receiver into debug mode */
-            if(!write_exact(io_fd, &minusone, sizeof(int))) {
+            if ( !write_exact(io_fd, &minusone, sizeof(int)) )
+            {
                 ERROR("Error when writing to state file (6)");
                 goto out;
             }
@@ -637,22 +591,22 @@ int xc_hvm_save(int xc_handle, int io_fd
             continue;
         }
 
-        if (last_iter) break;
-
-        if (live) {
-
-
-            if(
-                ((sent_this_iter > sent_last_iter) && RATE_IS_MAX()) ||
-                (iter >= max_iters) ||
-                (sent_this_iter+skip_this_iter < 50) ||
-                (total_sent > pfn_array_size*max_factor) ) {
-
+        if ( last_iter )
+            break;
+
+        if ( live )
+        {
+            if ( ((sent_this_iter > sent_last_iter) && RATE_IS_MAX()) ||
+                 (iter >= max_iters) ||
+                 (sent_this_iter+skip_this_iter < 50) ||
+                 (total_sent > pfn_array_size*max_factor) )
+            {
                 DPRINTF("Start last iteration for HVM domain\n");
                 last_iter = 1;
 
-                if (suspend_and_state(suspend, xc_handle, io_fd, dom, &info,
-                                      &ctxt)) {
+                if ( suspend_and_state(suspend, xc_handle, io_fd, dom, &info,
+                                       &ctxt))
+                {
                     ERROR("Domain appears not to have suspended");
                     goto out;
                 }
@@ -662,25 +616,30 @@ int xc_hvm_save(int xc_handle, int io_fd
                         (unsigned long)ctxt.user_regs.edx);
             }
 
-            if (xc_shadow_control(xc_handle, dom, 
-                                  XEN_DOMCTL_SHADOW_OP_CLEAN, to_send, 
-                                  pfn_array_size, NULL, 
-                                  0, &stats) != pfn_array_size) {
+            if ( xc_shadow_control(xc_handle, dom, 
+                                   XEN_DOMCTL_SHADOW_OP_CLEAN, to_send, 
+                                   pfn_array_size, NULL, 
+                                   0, &stats) != pfn_array_size )
+            {
                 ERROR("Error flushing shadow PT");
                 goto out;
             }
 
             /* Pull in the dirty bits from qemu too */
-            if (!last_iter) {
+            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++) {
+                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++) 
+            }
+            else
+            {
+                for ( j = 0; j < BITMAP_SIZE / sizeof(unsigned long); j++ )
                     to_send[j] |= qemu_bitmaps[qemu_active][j];
             }
 
@@ -688,61 +647,96 @@ int xc_hvm_save(int xc_handle, int io_fd
 
             print_stats(xc_handle, dom, sent_this_iter, &stats, 1);
         }
-
-
     } /* end of while 1 */
 
 
     DPRINTF("All HVM memory is saved\n");
+
+    {
+        struct {
+            int minustwo;
+            int max_vcpu_id;
+            uint64_t vcpumap;
+        } chunk = { -2, info.max_vcpu_id };
+
+        if (info.max_vcpu_id >= 64) {
+            ERROR("Too many VCPUS in guest!");
+            goto out;
+        }
+
+        for (i = 1; i <= info.max_vcpu_id; i++) {
+            xc_vcpuinfo_t vinfo;
+            if ((xc_vcpu_getinfo(xc_handle, dom, i, &vinfo) == 0) &&
+                vinfo.online)
+                vcpumap |= 1ULL << i;
+        }
+
+        chunk.vcpumap = vcpumap;
+        if(!write_exact(io_fd, &chunk, sizeof(chunk))) {
+            ERROR("Error when writing to state file (errno %d)", errno);
+            goto out;
+        }
+    }
 
     /* Zero terminate */
     i = 0;
-    if (!write_exact(io_fd, &i, sizeof(int))) {
+    if ( !write_exact(io_fd, &i, sizeof(int)) )
+    {
         ERROR("Error when writing to state file (6)");
         goto out;
     }
 
-
-    /* save vcpu/vmcs context */
-    if (!write_exact(io_fd, &nr_vcpus, sizeof(uint32_t))) {
-        ERROR("error write nr vcpus");
-        goto out;
-    }
-
-    /*XXX: need a online map to exclude down cpu */
-    for (i = 0; i < nr_vcpus; i++) {
-
-        if (xc_vcpu_getcontext(xc_handle, dom, i, &ctxt)) {
+    /* Save magic-page locations. */
+    memset(magic_pfns, 0, sizeof(magic_pfns));
+    xc_get_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN,
+                     (unsigned long *)&magic_pfns[0]);
+    xc_get_hvm_param(xc_handle, dom, HVM_PARAM_BUFIOREQ_PFN,
+                     (unsigned long *)&magic_pfns[1]);
+    xc_get_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN,
+                     (unsigned long *)&magic_pfns[2]);
+    if ( !write_exact(io_fd, magic_pfns, sizeof(magic_pfns)) )
+    {
+        ERROR("Error when writing to state file (7)");
+        goto out;
+    }
+
+    /* save vcpu/vmcs contexts */
+    for ( i = 0; i < nr_vcpus; i++ )
+    {
+        if (!(vcpumap & (1ULL << i)))
+            continue;
+
+        if ( xc_vcpu_getcontext(xc_handle, dom, i, &ctxt) )
+        {
             ERROR("HVM:Could not get vcpu context");
             goto out;
         }
 
-        rec_size = sizeof(ctxt);
-        DPRINTF("write %d vcpucontext of total %d.\n", i, nr_vcpus); 
-        if (!write_exact(io_fd, &rec_size, sizeof(uint32_t))) {
-            ERROR("error write vcpu ctxt size");
+        DPRINTF("write vcpu %d context.\n", i); 
+        if ( !write_exact(io_fd, &(ctxt), sizeof(ctxt)) )
+        {
+            ERROR("write vcpu context failed!\n");
             goto out;
         }
-
-        if (!write_exact(io_fd, &(ctxt), sizeof(ctxt)) ) {
-            ERROR("write vmcs failed!\n");
-            goto out;
-        }
     }
 
     if ( (rec_size = xc_domain_hvm_getcontext(xc_handle, dom, hvm_buf, 
-                                              hvm_buf_size)) == -1) {
+                                              hvm_buf_size)) == -1 )
+    {
         ERROR("HVM:Could not get hvm buffer");
         goto out;
     }
 
-    if (!write_exact(io_fd, &rec_size, sizeof(uint32_t))) {
+    if ( !write_exact(io_fd, &rec_size, sizeof(uint32_t)) )
+    {
         ERROR("error write hvm buffer size");
         goto out;
     }
 
-    if ( !write_exact(io_fd, hvm_buf, rec_size) ) {
+    if ( !write_exact(io_fd, hvm_buf, rec_size) )
+    {
         ERROR("write HVM info failed!\n");
+        goto out;
     }
 
     /* Success! */
@@ -750,12 +744,11 @@ int xc_hvm_save(int xc_handle, int io_fd
 
  out:
 
-    if (live) {
-        if(xc_shadow_control(xc_handle, dom, 
-                             XEN_DOMCTL_SHADOW_OP_OFF,
-                             NULL, 0, NULL, 0, NULL) < 0) {
+    if ( live )
+    {
+        if ( xc_shadow_control(xc_handle, dom, XEN_DOMCTL_SHADOW_OP_OFF,
+                               NULL, 0, NULL, 0, NULL) < 0 )
             DPRINTF("Warning - couldn't disable shadow mode");
-        }
     }
 
     free(hvm_buf);
diff -r 9ec7dadc98ba -r eb3e430242ac tools/libxc/xc_linux_restore.c
--- a/tools/libxc/xc_linux_restore.c    Fri Apr 06 10:06:30 2007 -0600
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,962 +0,0 @@
-/******************************************************************************
- * xc_linux_restore.c
- *
- * Restore the state of a Linux session.
- *
- * Copyright (c) 2003, K A Fraser.
- */
-
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "xg_private.h"
-#include "xg_save_restore.h"
-#include "xc_dom.h"
-
-/* max mfn of the current host machine */
-static unsigned long max_mfn;
-
-/* virtual starting address of the hypervisor */
-static unsigned long hvirt_start;
-
-/* #levels of page tables used by the current guest */
-static unsigned int pt_levels;
-
-/* number of pfns this guest has (i.e. number of entries in the P2M) */
-static unsigned long p2m_size;
-
-/* number of 'in use' pfns in the guest (i.e. #P2M entries with a valid mfn) */
-static unsigned long nr_pfns;
-
-/* largest possible value of nr_pfns (i.e. domain's maximum memory size) */
-static unsigned long max_nr_pfns;
-
-/* Live mapping of the table mapping each PFN to its current MFN. */
-static xen_pfn_t *live_p2m = NULL;
-
-/* A table mapping each PFN to its new MFN. */
-static xen_pfn_t *p2m = NULL;
-
-/* A table of P2M mappings in the current region */
-static xen_pfn_t *p2m_batch = NULL;
-
-static ssize_t
-read_exact(int fd, void *buf, size_t count)
-{
-    int r = 0, s;
-    unsigned char *b = buf;
-
-    while (r < count) {
-        s = read(fd, &b[r], count - r);
-        if ((s == -1) && (errno == EINTR))
-            continue;
-        if (s <= 0) {
-            break;
-        }
-        r += s;
-    }
-
-    return (r == count) ? 1 : 0;
-}
-
-/*
-** In the state file (or during transfer), all page-table pages are
-** converted into a 'canonical' form where references to actual mfns
-** are replaced with references to the corresponding pfns.
-** This function inverts that operation, replacing the pfn values with
-** the (now known) appropriate mfn values.
-*/
-static int uncanonicalize_pagetable(int xc_handle, uint32_t dom, 
-                                    unsigned long type, void *page)
-{
-    int i, pte_last;
-    unsigned long pfn;
-    uint64_t pte;
-    int nr_mfns = 0; 
-
-    pte_last = PAGE_SIZE / ((pt_levels == 2)? 4 : 8);
-
-    /* First pass: work out how many (if any) MFNs we need to alloc */
-    for(i = 0; i < pte_last; i++) {
-        
-        if(pt_levels == 2)
-            pte = ((uint32_t *)page)[i];
-        else
-            pte = ((uint64_t *)page)[i];
-        
-        /* XXX SMH: below needs fixing for PROT_NONE etc */
-        if(!(pte & _PAGE_PRESENT))
-            continue; 
-        
-        pfn = (pte >> PAGE_SHIFT) & MFN_MASK_X86;
-        
-        if(pfn >= p2m_size) {
-            /* This "page table page" is probably not one; bail. */
-            ERROR("Frame number in type %lu page table is out of range: "
-                  "i=%d pfn=0x%lx p2m_size=%lu",
-                  type >> 28, i, pfn, p2m_size);
-            return 0;
-        }
-        
-        if(p2m[pfn] == INVALID_P2M_ENTRY) {
-            /* Have a 'valid' PFN without a matching MFN - need to alloc */
-            p2m_batch[nr_mfns++] = pfn; 
-        }
-    }
-    
-    
-    /* Alllocate the requistite number of mfns */
-    if (nr_mfns && xc_domain_memory_populate_physmap(
-            xc_handle, dom, nr_mfns, 0, 0, p2m_batch) != 0) { 
-        ERROR("Failed to allocate memory for batch.!\n"); 
-        errno = ENOMEM;
-        return 0; 
-    }
-    
-    /* Second pass: uncanonicalize each present PTE */
-    nr_mfns = 0;
-    for(i = 0; i < pte_last; i++) {
-
-        if(pt_levels == 2)
-            pte = ((uint32_t *)page)[i];
-        else
-            pte = ((uint64_t *)page)[i];
-        
-        /* XXX SMH: below needs fixing for PROT_NONE etc */
-        if(!(pte & _PAGE_PRESENT))
-            continue;
-        
-        pfn = (pte >> PAGE_SHIFT) & MFN_MASK_X86;
-        
-        if(p2m[pfn] == INVALID_P2M_ENTRY)
-            p2m[pfn] = p2m_batch[nr_mfns++];
-
-        pte &= ~MADDR_MASK_X86;
-        pte |= (uint64_t)p2m[pfn] << PAGE_SHIFT;
-
-        if(pt_levels == 2)
-            ((uint32_t *)page)[i] = (uint32_t)pte;
-        else
-            ((uint64_t *)page)[i] = (uint64_t)pte;
-    }
-
-    return 1;
-}
-
-
-int xc_linux_restore(int xc_handle, int io_fd, uint32_t dom,
-                     unsigned long p2msize, unsigned long maxnrpfns,
-                     unsigned int store_evtchn, unsigned long *store_mfn,
-                     unsigned int console_evtchn, unsigned long *console_mfn)
-{
-    DECLARE_DOMCTL;
-    int rc = 1, i, j, n, m, pae_extended_cr3 = 0;
-    unsigned long mfn, pfn;
-    unsigned int prev_pc, this_pc;
-    int verify = 0;
-    int nraces = 0;
-
-    /* The new domain's shared-info frame number. */
-    unsigned long shared_info_frame;
-    unsigned char shared_info_page[PAGE_SIZE]; /* saved contents from file */
-    shared_info_t *shared_info = (shared_info_t *)shared_info_page;
-
-    /* A copy of the CPU context of the guest. */
-    vcpu_guest_context_t ctxt;
-
-    /* A table containing the type of each PFN (/not/ MFN!). */
-    unsigned long *pfn_type = NULL;
-
-    /* A table of MFNs to map in the current region */
-    xen_pfn_t *region_mfn = NULL;
-
-    /* Types of the pfns in the current region */
-    unsigned long region_pfn_type[MAX_BATCH_SIZE];
-
-    /* A temporary mapping, and a copy, of one frame of guest memory. */
-    unsigned long *page = NULL;
-
-    /* A copy of the pfn-to-mfn table frame list. */
-    xen_pfn_t *p2m_frame_list = NULL;
-
-    /* A temporary mapping of the guest's start_info page. */
-    start_info_t *start_info;
-
-    /* Our mapping of the current region (batch) */
-    char *region_base;
-
-    xc_mmu_t *mmu = NULL;
-
-    /* used by debug verify code */
-    unsigned long buf[PAGE_SIZE/sizeof(unsigned long)];
-
-    struct mmuext_op pin[MAX_PIN_BATCH];
-    unsigned int nr_pins;
-
-    uint64_t vcpumap = 1ULL;
-    unsigned int max_vcpu_id = 0;
-    int new_ctxt_format = 0;
-
-    p2m_size    = p2msize;
-    max_nr_pfns = maxnrpfns;
-
-    /* For info only */
-    nr_pfns = 0;
-
-    DPRINTF("xc_linux_restore start: p2m_size = %lx\n", p2m_size);
-
-    /*
-     * XXX For now, 32bit dom0's can only save/restore 32bit domUs
-     * on 64bit hypervisors.
-     */
-    memset(&domctl, 0, sizeof(domctl));
-    domctl.domain = dom;
-    domctl.cmd    = XEN_DOMCTL_set_address_size;
-    domctl.u.address_size.size = sizeof(unsigned long) * 8;
-    rc = do_domctl(xc_handle, &domctl);
-    if ( rc != 0 ) {
-       ERROR("Unable to set guest address size.");
-       goto out;
-    }
-
-    if(!get_platform_info(xc_handle, dom,
-                          &max_mfn, &hvirt_start, &pt_levels)) {
-        ERROR("Unable to get platform info.");
-        return 1;
-    }
-
-    if (lock_pages(&ctxt, sizeof(ctxt))) {
-        /* needed for build domctl, but might as well do early */
-        ERROR("Unable to lock ctxt");
-        return 1;
-    }
-
-    if (!(p2m_frame_list = malloc(P2M_FL_SIZE))) {
-        ERROR("Couldn't allocate p2m_frame_list array");
-        goto out;
-    }
-
-    /* Read first entry of P2M list, or extended-info signature (~0UL). */
-    if (!read_exact(io_fd, p2m_frame_list, sizeof(long))) {
-        ERROR("read extended-info signature failed");
-        goto out;
-    }
-
-    if (p2m_frame_list[0] == ~0UL) {
-        uint32_t tot_bytes;
-
-        /* Next 4 bytes: total size of following extended info. */
-        if (!read_exact(io_fd, &tot_bytes, sizeof(tot_bytes))) {
-            ERROR("read extended-info size failed");
-            goto out;
-        }
-
-        while (tot_bytes) {
-            uint32_t chunk_bytes;
-            char     chunk_sig[4];
-
-            /* 4-character chunk signature + 4-byte remaining chunk size. */
-            if (!read_exact(io_fd, chunk_sig, sizeof(chunk_sig)) ||
-                !read_exact(io_fd, &chunk_bytes, sizeof(chunk_bytes))) {
-                ERROR("read extended-info chunk signature failed");
-                goto out;
-            }
-            tot_bytes -= 8;
-
-            /* VCPU context structure? */
-            if (!strncmp(chunk_sig, "vcpu", 4)) {
-                if (!read_exact(io_fd, &ctxt, sizeof(ctxt))) {
-                    ERROR("read extended-info vcpu context failed");
-                    goto out;
-                }
-                tot_bytes   -= sizeof(struct vcpu_guest_context);
-                chunk_bytes -= sizeof(struct vcpu_guest_context);
-
-                if (ctxt.vm_assist & (1UL << VMASST_TYPE_pae_extended_cr3))
-                    pae_extended_cr3 = 1;
-            }
-
-            /* Any remaining bytes of this chunk: read and discard. */
-            while (chunk_bytes) {
-                unsigned long sz = chunk_bytes;
-                if ( sz > P2M_FL_SIZE )
-                    sz = P2M_FL_SIZE;
-                if (!read_exact(io_fd, p2m_frame_list, sz)) {
-                    ERROR("read-and-discard extended-info chunk bytes failed");
-                    goto out;
-                }
-                chunk_bytes -= sz;
-                tot_bytes   -= sz;
-            }
-        }
-
-        /* Now read the real first entry of P2M list. */
-        if (!read_exact(io_fd, p2m_frame_list, sizeof(long))) {
-            ERROR("read first entry of p2m_frame_list failed");
-            goto out;
-        }
-    }
-
-    /* First entry is already read into the p2m array. */
-    if (!read_exact(io_fd, &p2m_frame_list[1], P2M_FL_SIZE - sizeof(long))) {
-        ERROR("read p2m_frame_list failed");
-        goto out;
-    }
-
-    /* We want zeroed memory so use calloc rather than malloc. */
-    p2m        = calloc(p2m_size, sizeof(xen_pfn_t));
-    pfn_type   = calloc(p2m_size, sizeof(unsigned long));
-    region_mfn = calloc(MAX_BATCH_SIZE, sizeof(xen_pfn_t));
-    p2m_batch  = calloc(MAX_BATCH_SIZE, sizeof(xen_pfn_t));
-
-    if ((p2m == NULL) || (pfn_type == NULL) ||
-        (region_mfn == NULL) || (p2m_batch == NULL)) {
-        ERROR("memory alloc failed");
-        errno = ENOMEM;
-        goto out;
-    }
-
-    if (lock_pages(region_mfn, sizeof(xen_pfn_t) * MAX_BATCH_SIZE)) {
-        ERROR("Could not lock region_mfn");
-        goto out;
-    }
-
-    if (lock_pages(p2m_batch, sizeof(xen_pfn_t) * MAX_BATCH_SIZE)) {
-        ERROR("Could not lock p2m_batch");
-        goto out;
-    }
-
-    /* Get the domain's shared-info frame. */
-    domctl.cmd = XEN_DOMCTL_getdomaininfo;
-    domctl.domain = (domid_t)dom;
-    if (xc_domctl(xc_handle, &domctl) < 0) {
-        ERROR("Could not get information on new domain");
-        goto out;
-    }
-    shared_info_frame = domctl.u.getdomaininfo.shared_info_frame;
-
-    if (xc_domain_setmaxmem(xc_handle, dom, PFN_TO_KB(max_nr_pfns)) != 0) {
-        errno = ENOMEM;
-        goto out;
-    }
-
-    /* Mark all PFNs as invalid; we allocate on demand */
-    for ( pfn = 0; pfn < p2m_size; pfn++ )
-        p2m[pfn] = INVALID_P2M_ENTRY;
-
-    if(!(mmu = xc_init_mmu_updates(xc_handle, dom))) {
-        ERROR("Could not initialise for MMU updates");
-        goto out;
-    }
-
-    DPRINTF("Reloading memory pages:   0%%\n");
-
-    /*
-     * Now simply read each saved frame into its new machine frame.
-     * We uncanonicalise page tables as we go.
-     */
-    prev_pc = 0;
-
-    n = m = 0;
-    while (1) {
-
-        int j, nr_mfns = 0; 
-
-        this_pc = (n * 100) / p2m_size;
-        if ( (this_pc - prev_pc) >= 5 )
-        {
-            PPRINTF("\b\b\b\b%3d%%", this_pc);
-            prev_pc = this_pc;
-        }
-
-        if (!read_exact(io_fd, &j, sizeof(int))) {
-            ERROR("Error when reading batch size");
-            goto out;
-        }
-
-        PPRINTF("batch %d\n",j);
-
-        if (j == -1) {
-            verify = 1;
-            DPRINTF("Entering page verify mode\n");
-            continue;
-        }
-
-        if (j == -2) {
-            new_ctxt_format = 1;
-            if (!read_exact(io_fd, &max_vcpu_id, sizeof(int)) ||
-                (max_vcpu_id >= 64) ||
-                !read_exact(io_fd, &vcpumap, sizeof(uint64_t))) {
-                ERROR("Error when reading max_vcpu_id");
-                goto out;
-            }
-            continue;
-        }
-
-        if (j == 0)
-            break;  /* our work here is done */
-
-        if (j > MAX_BATCH_SIZE) {
-            ERROR("Max batch size exceeded. Giving up.");
-            goto out;
-        }
-
-        if (!read_exact(io_fd, region_pfn_type, j*sizeof(unsigned long))) {
-            ERROR("Error when reading region pfn types");
-            goto out;
-        }
-
-        /* First pass for this batch: work out how much memory to alloc */
-        nr_mfns = 0; 
-        for ( i = 0; i < j; i++ )
-        {
-            unsigned long pfn, pagetype;
-            pfn      = region_pfn_type[i] & ~XEN_DOMCTL_PFINFO_LTAB_MASK;
-            pagetype = region_pfn_type[i] &  XEN_DOMCTL_PFINFO_LTAB_MASK;
-
-            if ( (pagetype != XEN_DOMCTL_PFINFO_XTAB) && 
-                 (p2m[pfn] == INVALID_P2M_ENTRY) )
-            {
-                /* Have a live PFN which hasn't had an MFN allocated */
-                p2m_batch[nr_mfns++] = pfn; 
-            }
-        } 
-
-
-        /* Now allocate a bunch of mfns for this batch */
-        if (nr_mfns && xc_domain_memory_populate_physmap(
-                xc_handle, dom, nr_mfns, 0, 0, p2m_batch) != 0) { 
-            ERROR("Failed to allocate memory for batch.!\n"); 
-            errno = ENOMEM;
-            goto out;
-        }
-
-        /* Second pass for this batch: update p2m[] and region_mfn[] */
-        nr_mfns = 0; 
-        for ( i = 0; i < j; i++ )
-        {
-            unsigned long pfn, pagetype;
-            pfn      = region_pfn_type[i] & ~XEN_DOMCTL_PFINFO_LTAB_MASK;
-            pagetype = region_pfn_type[i] &  XEN_DOMCTL_PFINFO_LTAB_MASK;
-
-            if ( pagetype == XEN_DOMCTL_PFINFO_XTAB)
-                region_mfn[i] = ~0UL; /* map will fail but we don't care */
-            else 
-            {
-                if (p2m[pfn] == INVALID_P2M_ENTRY) {
-                    /* We just allocated a new mfn above; update p2m */
-                    p2m[pfn] = p2m_batch[nr_mfns++]; 
-                    nr_pfns++; 
-                }
-
-                /* setup region_mfn[] for batch map */
-                region_mfn[i] = p2m[pfn]; 
-            }
-        } 
-
-        /* Map relevant mfns */
-        region_base = xc_map_foreign_batch(
-            xc_handle, dom, PROT_WRITE, region_mfn, j);
-
-        if ( region_base == NULL )
-        {
-            ERROR("map batch failed");
-            goto out;
-        }
-
-        for ( i = 0; i < j; i++ )
-        {
-            void *page;
-            unsigned long pagetype;
-
-            pfn      = region_pfn_type[i] & ~XEN_DOMCTL_PFINFO_LTAB_MASK;
-            pagetype = region_pfn_type[i] &  XEN_DOMCTL_PFINFO_LTAB_MASK;
-
-            if ( pagetype == XEN_DOMCTL_PFINFO_XTAB )
-                /* a bogus/unmapped page: skip it */
-                continue;
-
-            if ( pfn > p2m_size )
-            {
-                ERROR("pfn out of range");
-                goto out;
-            }
-
-            pfn_type[pfn] = pagetype;
-
-            mfn = p2m[pfn];
-
-            /* In verify mode, we use a copy; otherwise we work in place */
-            page = verify ? (void *)buf : (region_base + i*PAGE_SIZE);
-
-            if (!read_exact(io_fd, page, PAGE_SIZE)) {
-                ERROR("Error when reading page (type was %lx)", pagetype);
-                goto out;
-            }
-
-            pagetype &= XEN_DOMCTL_PFINFO_LTABTYPE_MASK;
-
-            if ( (pagetype >= XEN_DOMCTL_PFINFO_L1TAB) && 
-                 (pagetype <= XEN_DOMCTL_PFINFO_L4TAB) )
-            {
-                /*
-                ** A page table page - need to 'uncanonicalize' it, i.e.
-                ** replace all the references to pfns with the corresponding
-                ** mfns for the new domain.
-                **
-                ** On PAE we need to ensure that PGDs are in MFNs < 4G, and
-                ** so we may need to update the p2m after the main loop.
-                ** Hence we defer canonicalization of L1s until then.
-                */
-                if ((pt_levels != 3) ||
-                    pae_extended_cr3 ||
-                    (pagetype != XEN_DOMCTL_PFINFO_L1TAB)) {
-
-                    if (!uncanonicalize_pagetable(xc_handle, dom, 
-                                                  pagetype, page)) {
-                        /*
-                        ** Failing to uncanonicalize a page table can be ok
-                        ** under live migration since the pages type may have
-                        ** changed by now (and we'll get an update later).
-                        */
-                        DPRINTF("PT L%ld race on pfn=%08lx mfn=%08lx\n",
-                                pagetype >> 28, pfn, mfn);
-                        nraces++;
-                        continue;
-                    } 
-                }
-            }
-            else if ( pagetype != XEN_DOMCTL_PFINFO_NOTAB )
-            {
-                ERROR("Bogus page type %lx page table is out of range: "
-                    "i=%d p2m_size=%lu", pagetype, i, p2m_size);
-                goto out;
-
-            }
-
-
-            if (verify) {
-
-                int res = memcmp(buf, (region_base + i*PAGE_SIZE), PAGE_SIZE);
-
-                if (res) {
-
-                    int v;
-
-                    DPRINTF("************** pfn=%lx type=%lx gotcs=%08lx "
-                            "actualcs=%08lx\n", pfn, pfn_type[pfn],
-                            csum_page(region_base + i*PAGE_SIZE),
-                            csum_page(buf));
-
-                    for (v = 0; v < 4; v++) {
-
-                        unsigned long *p = (unsigned long *)
-                            (region_base + i*PAGE_SIZE);
-                        if (buf[v] != p[v])
-                            DPRINTF("    %d: %08lx %08lx\n", v, buf[v], p[v]);
-                    }
-                }
-            }
-
-            if (xc_add_mmu_update(xc_handle, mmu,
-                                  (((unsigned long long)mfn) << PAGE_SHIFT)
-                                  | MMU_MACHPHYS_UPDATE, pfn)) {
-                ERROR("failed machpys update mfn=%lx pfn=%lx", mfn, pfn);
-                goto out;
-            }
-        } /* end of 'batch' for loop */
-
-        munmap(region_base, j*PAGE_SIZE);
-        n+= j; /* crude stats */
-
-        /* 
-         * Discard cache for portion of file read so far up to last
-         *  page boundary every 16MB or so.
-         */
-        m += j;
-        if ( m > MAX_PAGECACHE_USAGE )
-        {
-            discard_file_cache(io_fd, 0 /* no flush */);
-            m = 0;
-        }
-    }
-
-    /*
-     * Ensure we flush all machphys updates before potential PAE-specific
-     * reallocations below.
-     */
-    if (xc_finish_mmu_updates(xc_handle, mmu)) {
-        ERROR("Error doing finish_mmu_updates()");
-        goto out;
-    }
-
-    DPRINTF("Received all pages (%d races)\n", nraces);
-
-    if ((pt_levels == 3) && !pae_extended_cr3) {
-
-        /*
-        ** XXX SMH on PAE we need to ensure PGDs are in MFNs < 4G. This
-        ** is a little awkward and involves (a) finding all such PGDs and
-        ** replacing them with 'lowmem' versions; (b) upating the p2m[]
-        ** with the new info; and (c) canonicalizing all the L1s using the
-        ** (potentially updated) p2m[].
-        **
-        ** This is relatively slow (and currently involves two passes through
-        ** the pfn_type[] array), but at least seems to be correct. May wish
-        ** to consider more complex approaches to optimize this later.
-        */
-
-        int j, k;
-        
-        /* First pass: find all L3TABs current in > 4G mfns and get new mfns */
-        for ( i = 0; i < p2m_size; i++ )
-        {
-            if ( ((pfn_type[i] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK) ==
-                  XEN_DOMCTL_PFINFO_L3TAB) &&
-                 (p2m[i] > 0xfffffUL) )
-            {
-                unsigned long new_mfn;
-                uint64_t l3ptes[4];
-                uint64_t *l3tab;
-
-                l3tab = (uint64_t *)
-                    xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
-                                         PROT_READ, p2m[i]);
-
-                for(j = 0; j < 4; j++)
-                    l3ptes[j] = l3tab[j];
-
-                munmap(l3tab, PAGE_SIZE);
-
-                if (!(new_mfn=xc_make_page_below_4G(xc_handle, dom, p2m[i]))) {
-                    ERROR("Couldn't get a page below 4GB :-(");
-                    goto out;
-                }
-
-                p2m[i] = new_mfn;
-                if (xc_add_mmu_update(xc_handle, mmu,
-                                      (((unsigned long long)new_mfn)
-                                       << PAGE_SHIFT) |
-                                      MMU_MACHPHYS_UPDATE, i)) {
-                    ERROR("Couldn't m2p on PAE root pgdir");
-                    goto out;
-                }
-
-                l3tab = (uint64_t *)
-                    xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
-                                         PROT_READ | PROT_WRITE, p2m[i]);
-
-                for(j = 0; j < 4; j++)
-                    l3tab[j] = l3ptes[j];
-
-                munmap(l3tab, PAGE_SIZE);
-
-            }
-        }
-
-        /* Second pass: find all L1TABs and uncanonicalize them */
-        j = 0;
-
-        for ( i = 0; i < p2m_size; i++ )
-        {
-            if ( ((pfn_type[i] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK) ==
-                  XEN_DOMCTL_PFINFO_L1TAB) )
-            {
-                region_mfn[j] = p2m[i];
-                j++;
-            }
-
-            if(i == (p2m_size-1) || j == MAX_BATCH_SIZE) {
-
-                if (!(region_base = xc_map_foreign_batch(
-                          xc_handle, dom, PROT_READ | PROT_WRITE,
-                          region_mfn, j))) {
-                    ERROR("map batch failed");
-                    goto out;
-                }
-
-                for(k = 0; k < j; k++) {
-                    if(!uncanonicalize_pagetable(xc_handle, dom, 
-                                                 XEN_DOMCTL_PFINFO_L1TAB,
-                                                 region_base + k*PAGE_SIZE)) {
-                        ERROR("failed uncanonicalize pt!");
-                        goto out;
-                    }
-                }
-
-                munmap(region_base, j*PAGE_SIZE);
-                j = 0;
-            }
-        }
-
-        if (xc_finish_mmu_updates(xc_handle, mmu)) {
-            ERROR("Error doing finish_mmu_updates()");
-            goto out;
-        }
-    }
-
-    /*
-     * Pin page tables. Do this after writing to them as otherwise Xen
-     * will barf when doing the type-checking.
-     */
-    nr_pins = 0;
-    for ( i = 0; i < p2m_size; i++ )
-    {
-        if ( (pfn_type[i] & XEN_DOMCTL_PFINFO_LPINTAB) == 0 )
-            continue;
-
-        switch ( pfn_type[i] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK )
-        {
-        case XEN_DOMCTL_PFINFO_L1TAB:
-            pin[nr_pins].cmd = MMUEXT_PIN_L1_TABLE;
-            break;
-
-        case XEN_DOMCTL_PFINFO_L2TAB:
-            pin[nr_pins].cmd = MMUEXT_PIN_L2_TABLE;
-            break;
-
-        case XEN_DOMCTL_PFINFO_L3TAB:
-            pin[nr_pins].cmd = MMUEXT_PIN_L3_TABLE;
-            break;
-
-        case XEN_DOMCTL_PFINFO_L4TAB:
-            pin[nr_pins].cmd = MMUEXT_PIN_L4_TABLE;
-            break;
-
-        default:
-            continue;
-        }
-
-        pin[nr_pins].arg1.mfn = p2m[i];
-        nr_pins++;
-
-        /* Batch full? Then flush. */
-        if (nr_pins == MAX_PIN_BATCH) {
-            if (xc_mmuext_op(xc_handle, pin, nr_pins, dom) < 0) {
-                ERROR("Failed to pin batch of %d page tables", nr_pins);
-                goto out;
-            }
-            nr_pins = 0;
-        }
-    }
-
-    /* Flush final partial batch. */
-    if ((nr_pins != 0) && (xc_mmuext_op(xc_handle, pin, nr_pins, dom) < 0)) {
-        ERROR("Failed to pin batch of %d page tables", nr_pins);
-        goto out;
-    }
-
-    DPRINTF("\b\b\b\b100%%\n");
-    DPRINTF("Memory reloaded (%ld pages of max %ld)\n", nr_pfns, max_nr_pfns);
-
-    /* Get the list of PFNs that are not in the psuedo-phys map */
-    {
-        unsigned int count;
-        unsigned long *pfntab;
-        int nr_frees, rc;
-
-        if (!read_exact(io_fd, &count, sizeof(count))) {
-            ERROR("Error when reading pfn count");
-            goto out;
-        }
-
-        if(!(pfntab = malloc(sizeof(unsigned long) * count))) {
-            ERROR("Out of memory");
-            goto out;
-        }
-
-        if (!read_exact(io_fd, pfntab, sizeof(unsigned long)*count)) {
-            ERROR("Error when reading pfntab");
-            goto out;
-        }
-
-        nr_frees = 0; 
-        for (i = 0; i < count; i++) {
-
-            unsigned long pfn = pfntab[i];
-
-            if(p2m[pfn] != INVALID_P2M_ENTRY) {
-                /* pfn is not in physmap now, but was at some point during 
-                   the save/migration process - need to free it */
-                pfntab[nr_frees++] = p2m[pfn];
-                p2m[pfn]  = INVALID_P2M_ENTRY; // not in pseudo-physical map
-            }
-        }
-
-        if (nr_frees > 0) {
-
-            struct xen_memory_reservation reservation = {
-                .nr_extents   = nr_frees,
-                .extent_order = 0,
-                .domid        = dom
-            };
-            set_xen_guest_handle(reservation.extent_start, pfntab);
-
-            if ((rc = xc_memory_op(xc_handle, XENMEM_decrease_reservation,
-                                   &reservation)) != nr_frees) {
-                ERROR("Could not decrease reservation : %d", rc);
-                goto out;
-            } else
-                DPRINTF("Decreased reservation by %d pages\n", count);
-        }
-    }
-
-    for (i = 0; i <= max_vcpu_id; i++) {
-        if (!(vcpumap & (1ULL << i)))
-            continue;
-
-        if (!read_exact(io_fd, &ctxt, sizeof(ctxt))) {
-            ERROR("Error when reading ctxt %d", i);
-            goto out;
-        }
-
-        if ( !new_ctxt_format )
-            ctxt.flags |= VGCF_online;
-
-        if (i == 0) {
-            /*
-             * Uncanonicalise the suspend-record frame number and poke
-             * resume record.
-             */
-            pfn = ctxt.user_regs.edx;
-            if ((pfn >= p2m_size) ||
-                (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB)) {
-                ERROR("Suspend record frame number is bad");
-                goto out;
-            }
-            ctxt.user_regs.edx = mfn = p2m[pfn];
-            start_info = xc_map_foreign_range(
-                xc_handle, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, mfn);
-            start_info->nr_pages = p2m_size;
-            start_info->shared_info = shared_info_frame << PAGE_SHIFT;
-            start_info->flags = 0;
-            *store_mfn = start_info->store_mfn = p2m[start_info->store_mfn];
-            start_info->store_evtchn = store_evtchn;
-            start_info->console.domU.mfn = p2m[start_info->console.domU.mfn];
-            start_info->console.domU.evtchn = console_evtchn;
-            *console_mfn = start_info->console.domU.mfn;
-            munmap(start_info, PAGE_SIZE);
-        }
-
-        /* Uncanonicalise each GDT frame number. */
-        if (ctxt.gdt_ents > 8192) {
-            ERROR("GDT entry count out of range");
-            goto out;
-        }
-
-        for (j = 0; (512*j) < ctxt.gdt_ents; j++) {
-            pfn = ctxt.gdt_frames[j];
-            if ((pfn >= p2m_size) ||
-                (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB)) {
-                ERROR("GDT frame number is bad");
-                goto out;
-            }
-            ctxt.gdt_frames[j] = p2m[pfn];
-        }
-
-        /* Uncanonicalise the page table base pointer. */
-        pfn = xen_cr3_to_pfn(ctxt.ctrlreg[3]);
-
-        if (pfn >= p2m_size) {
-            ERROR("PT base is bad: pfn=%lu p2m_size=%lu type=%08lx",
-                  pfn, p2m_size, pfn_type[pfn]);
-            goto out;
-        }
-
-        if ( (pfn_type[pfn] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK) !=
-             ((unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT) ) {
-            ERROR("PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx",
-                  pfn, p2m_size, pfn_type[pfn],
-                  (unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT);
-            goto out;
-        }
-
-        ctxt.ctrlreg[3] = xen_pfn_to_cr3(p2m[pfn]);
-
-        /* Guest pagetable (x86/64) stored in otherwise-unused CR1. */
-        if ( (pt_levels == 4) && ctxt.ctrlreg[1] )
-        {
-            pfn = xen_cr3_to_pfn(ctxt.ctrlreg[1]);
-
-            if (pfn >= p2m_size) {
-                ERROR("User PT base is bad: pfn=%lu p2m_size=%lu type=%08lx",
-                      pfn, p2m_size, pfn_type[pfn]);
-                goto out;
-            }
-
-            if ( (pfn_type[pfn] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK) !=
-                 ((unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT) ) {
-                ERROR("User PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx",
-                      pfn, p2m_size, pfn_type[pfn],
-                      (unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT);
-                goto out;
-            }
-
-            ctxt.ctrlreg[1] = xen_pfn_to_cr3(p2m[pfn]);
-        }
-
-        domctl.cmd = XEN_DOMCTL_setvcpucontext;
-        domctl.domain = (domid_t)dom;
-        domctl.u.vcpucontext.vcpu = i;
-        set_xen_guest_handle(domctl.u.vcpucontext.ctxt, &ctxt);
-        rc = xc_domctl(xc_handle, &domctl);
-        if (rc != 0) {
-            ERROR("Couldn't build vcpu%d", i);
-            goto out;
-        }
-    }
-
-    if (!read_exact(io_fd, shared_info_page, PAGE_SIZE)) {
-        ERROR("Error when reading shared info page");
-        goto out;
-    }
-
-    /* clear any pending events and the selector */
-    memset(&(shared_info->evtchn_pending[0]), 0,
-           sizeof (shared_info->evtchn_pending));
-    for ( i = 0; i < MAX_VIRT_CPUS; i++ )
-        shared_info->vcpu_info[i].evtchn_pending_sel = 0;
-
-    /* Copy saved contents of shared-info page. No checking needed. */
-    page = xc_map_foreign_range(
-        xc_handle, dom, PAGE_SIZE, PROT_WRITE, shared_info_frame);
-    memcpy(page, shared_info, PAGE_SIZE);
-    munmap(page, PAGE_SIZE);
-
-    /* Uncanonicalise the pfn-to-mfn table frame-number list. */
-    for (i = 0; i < P2M_FL_ENTRIES; i++) {
-        pfn = p2m_frame_list[i];
-        if ((pfn >= p2m_size) || (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB)) {
-            ERROR("PFN-to-MFN frame number is bad");
-            goto out;
-        }
-
-        p2m_frame_list[i] = p2m[pfn];
-    }
-
-    /* Copy the P2M we've constructed to the 'live' P2M */
-    if (!(live_p2m = xc_map_foreign_batch(xc_handle, dom, PROT_WRITE,
-                                          p2m_frame_list, P2M_FL_ENTRIES))) {
-        ERROR("Couldn't map p2m table");
-        goto out;
-    }
-
-    memcpy(live_p2m, p2m, ROUNDUP(p2m_size * sizeof(xen_pfn_t), PAGE_SHIFT));
-    munmap(live_p2m, ROUNDUP(p2m_size * sizeof(xen_pfn_t), PAGE_SHIFT));
-
-    DPRINTF("Domain ready to be built.\n");
-
- out:
-    if ( (rc != 0) && (dom != 0) )
-        xc_domain_destroy(xc_handle, dom);
-    free(mmu);
-    free(p2m);
-    free(pfn_type);
-
-    /* discard cache for save file  */
-    discard_file_cache(io_fd, 1 /*flush*/);
-
-    DPRINTF("Restore exit with rc=%d\n", rc);
-    
-    return rc;
-}
diff -r 9ec7dadc98ba -r eb3e430242ac tools/libxc/xenguest.h
--- a/tools/libxc/xenguest.h    Fri Apr 06 10:06:30 2007 -0600
+++ b/tools/libxc/xenguest.h    Fri Apr 06 10:08:30 2007 -0600
@@ -38,32 +38,21 @@ int xc_hvm_save(int xc_handle, int io_fd
                 void (*qemu_flip_buffer)(int, int));
 
 /**
- * This function will restore a saved domain running Linux.
+ * This function will restore a saved domain.
  *
  * @parm xc_handle a handle to an open hypervisor interface
  * @parm fd the file descriptor to restore a domain from
  * @parm dom the id of the domain
- * @parm p2m_size number of pages the guest has (i.e. number entries in P2M)
- * @parm max_nr_pfns domains maximum real memory allocation, in pages
  * @parm store_evtchn the store event channel for this domain to use
  * @parm store_mfn returned with the mfn of the store page
+ * @parm hvm non-zero if this is a HVM restore
+ * @parm pae non-zero if this HVM domain has PAE support enabled
  * @return 0 on success, -1 on failure
  */
-int xc_linux_restore(int xc_handle, int io_fd, uint32_t dom,
-                     unsigned long p2m_size, unsigned long max_nr_pfns,
-                     unsigned int store_evtchn, unsigned long *store_mfn,
-                     unsigned int console_evtchn, unsigned long *console_mfn);
-
-/**
- * This function will restore a saved hvm domain running unmodified guest.
- *
- * @parm store_mfn pass mem size & returned with the mfn of the store page
- * @return 0 on success, -1 on failure
- */
-int xc_hvm_restore(int xc_handle, int io_fd, uint32_t dom,
-                      unsigned long max_pfn, unsigned int store_evtchn,
-                      unsigned long *store_mfn, 
-                      unsigned int pae, unsigned int apic);
+int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom,
+                      unsigned int store_evtchn, unsigned long *store_mfn,
+                      unsigned int console_evtchn, unsigned long *console_mfn,
+                      unsigned int hvm, unsigned int pae);
 
 /**
  * This function will create a domain for a paravirtualized Linux
@@ -159,8 +148,6 @@ int xc_get_hvm_param(
 int xc_get_hvm_param(
     int handle, domid_t dom, int param, unsigned long *value);
 
-int xc_hvm_drain_io(int handle, domid_t dom);
-
 /* PowerPC specific. */
 int xc_prose_build(int xc_handle,
                    uint32_t domid,
diff -r 9ec7dadc98ba -r eb3e430242ac tools/libxc/xg_private.c
--- a/tools/libxc/xg_private.c  Fri Apr 06 10:06:30 2007 -0600
+++ b/tools/libxc/xg_private.c  Fri Apr 06 10:08:30 2007 -0600
@@ -209,16 +209,6 @@ __attribute__((weak))
     return -1;
 }
 
-__attribute__((weak)) 
-    int xc_hvm_restore(int xc_handle, int io_fd, uint32_t dom,
-                       unsigned long max_pfn, unsigned int store_evtchn,
-                       unsigned long *store_mfn,
-                       unsigned int pae, unsigned int apic)
-{
-    errno = ENOSYS;
-    return -1;
-}
-
 __attribute__((weak)) int xc_get_hvm_param(
     int handle, domid_t dom, int param, unsigned long *value)
 {
@@ -227,11 +217,6 @@ __attribute__((weak)) int xc_get_hvm_par
 
 __attribute__((weak)) int xc_set_hvm_param(
     int handle, domid_t dom, int param, unsigned long value)
-{
-    return -ENOSYS;
-}
-
-__attribute__((weak)) int xc_hvm_drain_io(int handle, domid_t dom)
 {
     return -ENOSYS;
 }
diff -r 9ec7dadc98ba -r eb3e430242ac tools/libxen/include/xen_host.h
--- a/tools/libxen/include/xen_host.h   Fri Apr 06 10:06:30 2007 -0600
+++ b/tools/libxen/include/xen_host.h   Fri Apr 06 10:08:30 2007 -0600
@@ -436,6 +436,13 @@ xen_host_dmesg(xen_session *session, cha
 
 
 /**
+ * List all supported methods.
+ */
+extern bool
+xen_host_list_methods(xen_session *session, struct xen_string_set **result);
+
+
+/**
  * Return a list of all the hosts known to the system.
  */
 extern bool
diff -r 9ec7dadc98ba -r eb3e430242ac tools/libxen/include/xen_sr.h
--- a/tools/libxen/include/xen_sr.h     Fri Apr 06 10:06:30 2007 -0600
+++ b/tools/libxen/include/xen_sr.h     Fri Apr 06 10:08:30 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_pbd_decl.h"
 #include "xen_sr_decl.h"
+#include "xen_string_set.h"
 #include "xen_vdi_decl.h"
 
 
@@ -72,7 +73,7 @@ typedef struct xen_sr_record
     int64_t physical_utilisation;
     int64_t physical_size;
     char *type;
-    char *location;
+    char *content_type;
 } xen_sr_record;
 
 /**
@@ -169,20 +170,6 @@ xen_sr_get_by_uuid(xen_session *session,
 
 
 /**
- * Create a new SR instance, and return its handle.
- */
-extern bool
-xen_sr_create(xen_session *session, xen_sr *result, xen_sr_record *record);
-
-
-/**
- * Destroy the specified SR instance.
- */
-extern bool
-xen_sr_destroy(xen_session *session, xen_sr sr);
-
-
-/**
  * Get all the SR instances with the given label.
  */
 extern bool
@@ -253,10 +240,10 @@ xen_sr_get_type(xen_session *session, ch
 
 
 /**
- * Get the location field of the given SR.
- */
-extern bool
-xen_sr_get_location(xen_session *session, char **result, xen_sr sr);
+ * Get the content_type field of the given SR.
+ */
+extern bool
+xen_sr_get_content_type(xen_session *session, char **result, xen_sr sr);
 
 
 /**
@@ -274,11 +261,10 @@ xen_sr_set_name_description(xen_session 
 
 
 /**
- * Take an exact copy of the Storage Repository; the cloned storage
- * repository has the same type as its parent
- */
-extern bool
-xen_sr_clone(xen_session *session, xen_sr *result, xen_sr sr, char *loc, char 
*name);
+ * Return a set of all the SR types supported by the system.
+ */
+extern bool
+xen_sr_get_supported_types(xen_session *session, struct xen_string_set 
**result);
 
 
 /**
diff -r 9ec7dadc98ba -r eb3e430242ac tools/libxen/include/xen_vdi.h
--- a/tools/libxen/include/xen_vdi.h    Fri Apr 06 10:06:30 2007 -0600
+++ b/tools/libxen/include/xen_vdi.h    Fri Apr 06 10:08:30 2007 -0600
@@ -338,21 +338,6 @@ xen_vdi_remove_from_other_config(xen_ses
 
 
 /**
- * Take an exact copy of the VDI; the snapshot lives in the same
- * Storage Repository as its parent.
- */
-extern bool
-xen_vdi_snapshot(xen_session *session, xen_vdi *result, xen_vdi vdi);
-
-
-/**
- * Resize the vdi to the size.
- */
-extern bool
-xen_vdi_resize(xen_session *session, xen_vdi vdi, int64_t size);
-
-
-/**
  * Return a list of all the VDIs known to the system.
  */
 extern bool
diff -r 9ec7dadc98ba -r eb3e430242ac tools/libxen/src/xen_common.c
--- a/tools/libxen/src/xen_common.c     Fri Apr 06 10:06:30 2007 -0600
+++ b/tools/libxen/src/xen_common.c     Fri Apr 06 10:08:30 2007 -0600
@@ -102,6 +102,9 @@ add_struct_value(const struct abstract_t
                           const char *),
                  const char *, xmlNode *);
 
+static xmlNode *
+add_container(xmlNode *parent, const char *name);
+
 static void
 call_raw(xen_session *, const char *, abstract_value [], int,
          const abstract_type *, void *);
@@ -1290,6 +1293,48 @@ make_body_add_type(enum abstract_typenam
     }
     break;
 
+    case MAP:
+    {
+        const struct struct_member *member = v->type->members;
+        arbitrary_map *map_val = v->u.struct_val;
+        xmlNode *param_node = add_param_struct(params_node);
+        for (size_t i = 0; i < map_val->size; i++) {
+            enum abstract_typename typename_key = member[0].type->typename;
+            enum abstract_typename typename_val = member[1].type->typename;
+            int offset_key = member[0].offset;
+            int offset_val = member[1].offset;
+            int struct_size = v->type->struct_size;
+
+            switch (typename_key) {
+            case STRING: {
+                char **addr = (void *)(map_val + 1) +
+                             (i * struct_size) +
+                             offset_key;
+                char *key = *addr;
+
+                switch (typename_val) {
+                case STRING: {
+                    char *val;
+                    addr = (void *)(map_val + 1) +
+                           (i * struct_size) +
+                           offset_val;
+                    val = *addr;
+                    add_struct_member(param_node, key, "string", val);
+                    break;
+                }
+                default:
+                    assert(false);
+                }
+                break;
+            }
+            default:
+                assert(false);
+            }
+        }
+    }
+    break;
+
+
     default:
         assert(false);
     }
diff -r 9ec7dadc98ba -r eb3e430242ac tools/libxen/src/xen_host.c
--- a/tools/libxen/src/xen_host.c       Fri Apr 06 10:06:30 2007 -0600
+++ b/tools/libxen/src/xen_host.c       Fri Apr 06 10:08:30 2007 -0600
@@ -740,6 +740,18 @@ xen_host_dmesg(xen_session *session, cha
 
 
 bool
+xen_host_list_methods(xen_session *session, struct xen_string_set **result)
+{
+
+    abstract_type result_type = abstract_type_string_set;
+
+    *result = NULL;
+    xen_call_(session, "host.list_methods", NULL, 0, &result_type, result);
+    return session->ok;
+}
+
+
+bool
 xen_host_get_all(xen_session *session, struct xen_host_set **result)
 {
 
diff -r 9ec7dadc98ba -r eb3e430242ac tools/libxen/src/xen_sr.c
--- a/tools/libxen/src/xen_sr.c Fri Apr 06 10:06:30 2007 -0600
+++ b/tools/libxen/src/xen_sr.c Fri Apr 06 10:08:30 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
@@ -65,9 +65,9 @@ static const struct_member xen_sr_record
         { .key = "type",
           .type = &abstract_type_string,
           .offset = offsetof(xen_sr_record, type) },
-        { .key = "location",
-          .type = &abstract_type_string,
-          .offset = offsetof(xen_sr_record, location) }
+        { .key = "content_type",
+          .type = &abstract_type_string,
+          .offset = offsetof(xen_sr_record, content_type) }
     };
 
 const abstract_type xen_sr_record_abstract_type_ =
@@ -94,7 +94,7 @@ xen_sr_record_free(xen_sr_record *record
     xen_vdi_record_opt_set_free(record->vdis);
     xen_pbd_record_opt_set_free(record->pbds);
     free(record->type);
-    free(record->location);
+    free(record->content_type);
     free(record);
 }
 
@@ -140,37 +140,6 @@ xen_sr_get_by_uuid(xen_session *session,
 
 
 bool
-xen_sr_create(xen_session *session, xen_sr *result, xen_sr_record *record)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &xen_sr_record_abstract_type_,
-              .u.struct_val = record }
-        };
-
-    abstract_type result_type = abstract_type_string;
-
-    *result = NULL;
-    XEN_CALL_("SR.create");
-    return session->ok;
-}
-
-
-bool
-xen_sr_destroy(xen_session *session, xen_sr sr)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &abstract_type_string,
-              .u.string_val = sr }
-        };
-
-    xen_call_(session, "SR.destroy", param_values, 1, NULL, NULL);
-    return session->ok;
-}
-
-
-bool
 xen_sr_get_by_name_label(xen_session *session, struct xen_sr_set **result, 
char *label)
 {
     abstract_value param_values[] =
@@ -239,6 +208,23 @@ xen_sr_get_vdis(xen_session *session, st
 
 
 bool
+xen_sr_get_pbds(xen_session *session, struct xen_pbd_set **result, xen_sr sr)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = sr }
+        };
+
+    abstract_type result_type = abstract_type_string_set;
+
+    *result = NULL;
+    XEN_CALL_("SR.get_PBDs");
+    return session->ok;
+}
+
+
+bool
 xen_sr_get_virtual_allocation(xen_session *session, int64_t *result, xen_sr sr)
 {
     abstract_value param_values[] =
@@ -304,18 +290,18 @@ xen_sr_get_type(xen_session *session, ch
 
 
 bool
-xen_sr_get_location(xen_session *session, char **result, xen_sr sr)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &abstract_type_string,
-              .u.string_val = sr }
-        };
-
-    abstract_type result_type = abstract_type_string;
-
-    *result = NULL;
-    XEN_CALL_("SR.get_location");
+xen_sr_get_content_type(xen_session *session, char **result, xen_sr sr)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = sr }
+        };
+
+    abstract_type result_type = abstract_type_string;
+
+    *result = NULL;
+    XEN_CALL_("SR.get_content_type");
     return session->ok;
 }
 
@@ -353,22 +339,13 @@ xen_sr_set_name_description(xen_session 
 
 
 bool
-xen_sr_clone(xen_session *session, xen_sr *result, xen_sr sr, char *loc, char 
*name)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &abstract_type_string,
-              .u.string_val = sr },
-            { .type = &abstract_type_string,
-              .u.string_val = loc },
-            { .type = &abstract_type_string,
-              .u.string_val = name }
-        };
-
-    abstract_type result_type = abstract_type_string;
-
-    *result = NULL;
-    XEN_CALL_("SR.clone");
+xen_sr_get_supported_types(xen_session *session, struct xen_string_set 
**result)
+{
+
+    abstract_type result_type = abstract_type_string_set;
+
+    *result = NULL;
+    xen_call_(session, "SR.get_supported_types", NULL, 0, &result_type, 
result);
     return session->ok;
 }
 
diff -r 9ec7dadc98ba -r eb3e430242ac tools/libxen/src/xen_vdi.c
--- a/tools/libxen/src/xen_vdi.c        Fri Apr 06 10:06:30 2007 -0600
+++ b/tools/libxen/src/xen_vdi.c        Fri Apr 06 10:08:30 2007 -0600
@@ -508,39 +508,6 @@ xen_vdi_remove_from_other_config(xen_ses
 
 
 bool
-xen_vdi_snapshot(xen_session *session, xen_vdi *result, xen_vdi vdi)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &abstract_type_string,
-              .u.string_val = vdi }
-        };
-
-    abstract_type result_type = abstract_type_string;
-
-    *result = NULL;
-    XEN_CALL_("VDI.snapshot");
-    return session->ok;
-}
-
-
-bool
-xen_vdi_resize(xen_session *session, xen_vdi vdi, int64_t size)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &abstract_type_string,
-              .u.string_val = vdi },
-            { .type = &abstract_type_int,
-              .u.int_val = size }
-        };
-
-    xen_call_(session, "VDI.resize", param_values, 2, NULL, NULL);
-    return session->ok;
-}
-
-
-bool
 xen_vdi_get_all(xen_session *session, struct xen_vdi_set **result)
 {
 
diff -r 9ec7dadc98ba -r eb3e430242ac tools/libxen/test/test_bindings.c
--- a/tools/libxen/test/test_bindings.c Fri Apr 06 10:06:30 2007 -0600
+++ b/tools/libxen/test/test_bindings.c Fri Apr 06 10:08:30 2007 -0600
@@ -64,6 +64,7 @@ typedef struct
 
 static xen_vm create_new_vm(xen_session *session, bool hvm);
 static void print_session_info(xen_session *session);
+static void print_methods(xen_session *session);
 static void print_vm_power_state(xen_session *session, xen_vm vm);
 static void print_vm_metrics(xen_session *session, xen_vm vm);
 
@@ -159,6 +160,14 @@ int main(int argc, char **argv)
         xen_session_login_with_password(call_func, NULL, username, password);
 
     print_session_info(session);
+    if (!session->ok)
+    {
+        /* Error has been logged, just clean up. */
+        CLEANUP;
+        return 1;
+    }
+
+    print_methods(session);
     if (!session->ok)
     {
         /* Error has been logged, just clean up. */
@@ -644,6 +653,40 @@ static void print_session_info(xen_sessi
 }
 
 
+static int pstrcmp(const void *p1, const void *p2)
+{
+    return strcmp(*(char **)p1, *(char **)p2);
+}
+
+
+/**
+ * Print the list of supported methods.
+ */
+static void print_methods(xen_session *session)
+{
+    xen_string_set *methods;
+
+    if (!xen_host_list_methods(session, &methods))
+    {
+        print_error(session);
+        goto done;
+    }
+
+    printf("%zd.\n", methods->size);
+    qsort(methods->contents, methods->size, sizeof(char *), pstrcmp);
+
+    printf("Supported methods:\n");
+    for (size_t i = 0; i < methods->size; i++)
+    {
+        printf("  %s\n", methods->contents[i]);
+    }
+    fflush(stdout);
+
+done:
+    xen_string_set_free(methods);
+}
+
+
 /**
  * Print the metrics for the given VM.
  */
diff -r 9ec7dadc98ba -r eb3e430242ac tools/python/xen/xend/XendAPI.py
--- a/tools/python/xen/xend/XendAPI.py  Fri Apr 06 10:06:30 2007 -0600
+++ b/tools/python/xen/xend/XendAPI.py  Fri Apr 06 10:08:30 2007 -0600
@@ -26,20 +26,22 @@ import time
 import time
 import xmlrpclib
 
-from xen.xend import XendDomain, XendDomainInfo, XendNode, XendDmesg
-from xen.xend import XendLogging, XendTaskManager
-
-from xen.xend.XendAPIVersion import *
-from xen.xend.XendAuthSessions import instance as auth_manager
-from xen.xend.XendError import *
-from xen.xend.XendClient import ERROR_INVALID_DOMAIN
-from xen.xend.XendLogging import log
-from xen.xend.XendNetwork import XendNetwork
-from xen.xend.XendTask import XendTask
-from xen.xend.XendPIFMetrics import XendPIFMetrics
-from xen.xend.XendVMMetrics import XendVMMetrics
-
-from xen.xend.XendAPIConstants import *
+import XendDomain, XendDomainInfo, XendNode, XendDmesg
+import XendLogging, XendTaskManager
+
+from XendAPIVersion import *
+from XendAuthSessions import instance as auth_manager
+from XendError import *
+from XendClient import ERROR_INVALID_DOMAIN
+from XendLogging import log
+from XendNetwork import XendNetwork
+from XendTask import XendTask
+from XendPIFMetrics import XendPIFMetrics
+from XendVMMetrics import XendVMMetrics
+
+import XendPBD
+
+from XendAPIConstants import *
 from xen.util.xmlrpclib2 import stringify
 
 from xen.util.blkif import blkdev_name_to_number
@@ -394,6 +396,17 @@ def valid_sr(func):
            _check_ref(lambda r: XendNode.instance().is_valid_sr,
                       'SR', func, *args, **kwargs)
 
+def valid_pbd(func):
+    """Decorator to verify if pbd_ref is valid before calling
+    method.
+
+    @param func: function with params: (self, session, pbd_ref)
+    @rtype: callable object
+    """
+    return lambda *args, **kwargs: \
+           _check_ref(lambda r: r in XendPBD.get_all_refs(),
+                      'PBD', func, *args, **kwargs)
+
 def valid_pif(func):
     """Decorator to verify if pif_ref is valid before calling
     method.
@@ -479,6 +492,7 @@ classes = {
     'VTPM'         : valid_vtpm,
     'console'      : valid_console,
     'SR'           : valid_sr,
+    'PBD'          : valid_pbd,
     'PIF'          : valid_pif,
     'PIF_metrics'  : valid_pif_metrics,
     'task'         : valid_task,
@@ -488,6 +502,7 @@ autoplug_classes = {
 autoplug_classes = {
     'network'     : XendNetwork,
     'VM_metrics'  : XendVMMetrics,
+    'PBD'         : XendPBD.XendPBD,
     'PIF_metrics' : XendPIFMetrics,
 }
 
@@ -774,7 +789,6 @@ class XendAPI(object):
                     'progress',
                     'type',
                     'result',
-                    'error_code',
                     'error_info',
                     'allowed_operations',
                     'session'
@@ -809,10 +823,6 @@ class XendAPI(object):
         task = XendTaskManager.get_task(task_ref)
         return xen_api_success(task.result)
 
-    def task_get_error_code(self, session, task_ref):
-        task = XendTaskManager.get_task(task_ref)
-        return xen_api_success(task.error_code)
-
     def task_get_error_info(self, session, task_ref):
         task = XendTaskManager.get_task(task_ref)
         return xen_api_success(task.error_info)
@@ -843,6 +853,7 @@ class XendAPI(object):
 
     host_attr_ro = ['software_version',
                     'resident_VMs',
+                    'PBDs',
                     'PIFs',
                     'host_CPUs',
                     'cpu_configuration',
@@ -870,7 +881,8 @@ class XendAPI(object):
                     ('get_log', 'String'),
                     ('send_debug_keys', None)]
     
-    host_funcs = [('get_by_name_label', 'Set(host)')]
+    host_funcs = [('get_by_name_label', None),
+                  ('list_methods', None)]
 
     # attributes
     def host_get_name_label(self, session, host_ref):
@@ -913,6 +925,8 @@ class XendAPI(object):
         return xen_api_success(XendNode.instance().xen_version())
     def host_get_resident_VMs(self, session, host_ref):
         return xen_api_success(XendDomain.instance().get_domain_refs())
+    def host_get_PBDs(self, _, ref):
+        return xen_api_success(XendPBD.get_all_refs())
     def host_get_PIFs(self, session, ref):
         return xen_api_success(XendNode.instance().get_PIF_refs())
     def host_get_host_CPUs(self, session, host_ref):
@@ -925,8 +939,6 @@ class XendAPI(object):
         return xen_api_success(['pygrub'])
     def host_get_sched_policy(self, _, host_ref):
         return xen_api_success(XendNode.instance().get_vcpus_policy())
-    def host_set_sched_policy(self, _, host_ref, policy):
-        return xen_api_todo()
     def host_get_cpu_configuration(self, _, host_ref):
         return xen_api_success(XendNode.instance().get_cpu_configuration())
     
@@ -992,6 +1004,12 @@ class XendAPI(object):
             return xen_api_success((XendNode.instance().uuid,))
         return xen_api_success([])
     
+    def host_list_methods(self, _):
+        def _funcs():
+            return [getattr(XendAPI, x) for x in XendAPI.__dict__]
+
+        return xen_api_success([x.api for x in _funcs()
+                                if hasattr(x, 'api')])
 
     # Xen API: Class host_CPU
     # ----------------------------------------------------------------
@@ -2061,8 +2079,8 @@ class XendAPI(object):
             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)
+        except XendError, exn:
+            return xen_api_error(['INTERNAL_ERROR', str(exn)])
           
     def VIF_destroy(self, session, vif_ref):
         xendom = XendDomain.instance()
@@ -2169,7 +2187,7 @@ class XendAPI(object):
                    'other_config']
     VDI_attr_inst = VDI_attr_ro + VDI_attr_rw
 
-    VDI_methods = [('snapshot', 'VDI'), ('destroy', None)]
+    VDI_methods = [('destroy', None)]
     VDI_funcs = [('create', 'VDI'),
                   ('get_by_name_label', 'Set(VDI)')]
 
@@ -2233,8 +2251,6 @@ class XendAPI(object):
         return xen_api_success_void()
 
     # Object Methods
-    def VDI_snapshot(self, session, vdi_ref):
-        return xen_api_todo()
     
     def VDI_destroy(self, session, vdi_ref):
         sr = XendNode.instance().get_sr_containing_vdi(vdi_ref)
@@ -2349,8 +2365,8 @@ class XendAPI(object):
                 vtpm_ref = dom.create_vtpm(vtpm_struct)
                 xendom.managed_config_save(dom)
                 return xen_api_success(vtpm_ref)
-            except XendError:
-                return xen_api_error(XEND_ERROR_TODO)
+            except XendError, exn:
+                return xen_api_error(['INTERNAL_ERROR', str(exn)])
         else:
             return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
 
@@ -2424,8 +2440,8 @@ class XendAPI(object):
             console_ref = dom.create_console(console_struct)
             xendom.managed_config_save(dom)
             return xen_api_success(console_ref)
-        except XendError, e:
-            return xen_api_error([XEND_ERROR_TODO, str(e)])
+        except XendError, exn:
+            return xen_api_error(['INTERNAL_ERROR', str(exn)])
 
     # Xen API: Class SR
     # ----------------------------------------------------------------
@@ -2434,18 +2450,17 @@ class XendAPI(object):
                   'physical_utilisation',
                   'physical_size',
                   'type',
-                  'location']
+                  'content_type']
     
     SR_attr_rw = ['name_label',
                   'name_description']
     
     SR_attr_inst = ['physical_size',
                     'type',
-                    'location',
                     'name_label',
                     'name_description']
     
-    SR_methods = [('clone', 'SR'), ('destroy', None)]
+    SR_methods = []
     SR_funcs = [('get_by_name_label', 'Set(SR)'),
                 ('get_by_uuid', 'SR')]
 
@@ -2456,15 +2471,10 @@ class XendAPI(object):
     def SR_get_by_name_label(self, session, label):
         return xen_api_success(XendNode.instance().get_sr_by_name(label))
     
-    def SR_create(self, session):
-        return xen_api_error(XEND_ERROR_UNSUPPORTED)
+    def SR_get_supported_types(self, _):
+        return xen_api_success(['local', 'qcow_file'])
 
     # Class Methods
-    def SR_clone(self, session, sr_ref):
-        return xen_api_error(XEND_ERROR_UNSUPPORTED)
-    
-    def SR_destroy(self, session, sr_ref):
-        return xen_api_error(XEND_ERROR_UNSUPPORTED)
     
     def SR_get_record(self, session, sr_ref):
         sr = XendNode.instance().get_sr(sr_ref)
@@ -2497,8 +2507,8 @@ class XendAPI(object):
     def SR_get_type(self, _, ref):
         return self._get_SR_attr(ref, 'type')
 
-    def SR_get_location(self, _, ref):
-        return self._get_SR_attr(ref, 'location')
+    def SR_get_content_type(self, _, ref):
+        return self._get_SR_attr(ref, 'content_type')
 
     def SR_get_name_label(self, _, ref):
         return self._get_SR_attr(ref, 'name_label')
@@ -2519,6 +2529,33 @@ class XendAPI(object):
             sr.name_description = value
             XendNode.instance().save()        
         return xen_api_success_void()
+
+
+    # Xen API: Class PBD
+    # ----------------------------------------------------------------
+
+    PBD_attr_ro = ['host',
+                   'SR',
+                   'device_config',
+                   'currently_attached']
+    PBD_attr_rw = []
+    PBD_methods = [('destroy', None)]
+    PBD_funcs   = [('create', None)]
+
+    def PBD_get_all(self, _):
+        return xen_api_success(XendPBD.get_all_refs())
+
+    def _PBD_get(self, _, ref):
+        return XendPBD.get(ref)
+
+    def PBD_create(self, _, record):
+        if 'uuid' in record:
+            return xen_api_error(['VALUE_NOT_SUPPORTED',
+                                  'uuid', record['uuid'],
+                                  'You may not specify a UUID on creation'])
+        new_uuid = XendPBD.XendPBD(record).get_uuid()
+        XendNode.instance().save()
+        return xen_api_success(new_uuid)
 
 
     # Xen API: Class event
@@ -2572,15 +2609,6 @@ class XendAPI(object):
 
     def debug_get_record(self, session, debug_ref):
         return xen_api_success({'uuid': debug_ref})
-
-
-    def list_all_methods(self, _):
-        def _funcs():
-            return [getattr(XendAPI, x) for x in XendAPI.__dict__]
-
-        return xen_api_success([x.api for x in _funcs()
-                                if hasattr(x, 'api')])
-    list_all_methods.api = '_UNSUPPORTED_list_all_methods'
 
 
 class XendAPIAsyncProxy:
diff -r 9ec7dadc98ba -r eb3e430242ac tools/python/xen/xend/XendCheckpoint.py
--- a/tools/python/xen/xend/XendCheckpoint.py   Fri Apr 06 10:06:30 2007 -0600
+++ b/tools/python/xen/xend/XendCheckpoint.py   Fri Apr 06 10:08:30 2007 -0600
@@ -91,7 +91,7 @@ def save(fd, dominfo, network, live, dst
         # more information.
         cmd = [xen.util.auxbin.pathTo(XC_SAVE), str(fd),
                str(dominfo.getDomid()), "0", "0", 
-               str(int(live) | (int(hvm) << 2) | (int(stdvga) << 3)) ]
+               str(int(live) | (int(hvm) << 2)) ]
         log.debug("[xc_save]: %s", string.join(cmd))
 
         def saveInputHandler(line, tochild):
@@ -187,7 +187,6 @@ def restore(xd, fd, dominfo = None, paus
     assert console_port
 
     nr_pfns = (dominfo.getMemoryTarget() + 3) / 4 
-    max_nr_pfns = (dominfo.getMemoryMaximum() + 3) / 4 
 
     # if hvm, pass mem size to calculate the store_mfn
     image_cfg = dominfo.info.get('image', {})
@@ -202,27 +201,21 @@ def restore(xd, fd, dominfo = None, paus
         pae  = 0
 
     try:
-        l = read_exact(fd, sizeof_unsigned_long,
-                       "not a valid guest state file: pfn count read")
-        p2m_size = unpack("L", l)[0]    # native sizeof long
-
-        if p2m_size > 16*1024*1024:     # XXX 
-            raise XendError(
-                "not a valid guest state file: pfn count out of range")
-
         shadow = dominfo.info['shadow_memory']
-        log.debug("restore:shadow=0x%x, _static_max=0x%x, _static_min=0x%x, "
-                  "p2m_size=0x%x.", dominfo.info['shadow_memory'],
+        log.debug("restore:shadow=0x%x, _static_max=0x%x, _static_min=0x%x, ",
+                  dominfo.info['shadow_memory'],
                   dominfo.info['memory_static_max'],
-                  dominfo.info['memory_static_min'], p2m_size)
+                  dominfo.info['memory_static_min'])
 
         balloon.free(xc.pages_to_kib(nr_pfns) + shadow * 1024)
 
         shadow_cur = xc.shadow_mem_control(dominfo.getDomid(), shadow)
         dominfo.info['shadow_memory'] = shadow_cur
 
+        xc.domain_setmaxmem(dominfo.getDomid(), dominfo.getMemoryMaximum())
+
         cmd = map(str, [xen.util.auxbin.pathTo(XC_RESTORE),
-                        fd, dominfo.getDomid(), p2m_size, max_nr_pfns, 
+                        fd, dominfo.getDomid(),
                         store_port, console_port, int(is_hvm), pae, apic])
         log.debug("[xc_restore]: %s", string.join(cmd))
 
diff -r 9ec7dadc98ba -r eb3e430242ac 
tools/python/xen/xend/XendLocalStorageRepo.py
--- a/tools/python/xen/xend/XendLocalStorageRepo.py     Fri Apr 06 10:06:30 
2007 -0600
+++ b/tools/python/xen/xend/XendLocalStorageRepo.py     Fri Apr 06 10:08:30 
2007 -0600
@@ -30,13 +30,13 @@ import struct
 import struct
 
 from xen.util import mkdir
-from xen.xend import uuid
-from xen.xend.XendError import XendError
-from xen.xend.XendVDI import *
-from xen.xend.XendTask import XendTask
-from xen.xend.XendStorageRepository import XendStorageRepository
-from xen.xend.XendStateStore import XendStateStore
-from xen.xend.XendOptions import instance as xendoptions
+import uuid
+from XendError import XendError
+from XendVDI import *
+from XendTask import XendTask
+from XendStorageRepository import XendStorageRepository
+from XendStateStore import XendStateStore
+from XendOptions import instance as xendoptions
 
 MB = 1024 * 1024
 
@@ -58,8 +58,7 @@ class XendLocalStorageRepo(XendStorageRe
         """
 
         XendStorageRepository.__init__(self, sr_uuid, sr_type,
-                                       name_label, name_description,
-                                       '/')
+                                       name_label, name_description)
         
         self.state = XendStateStore(xendoptions().get_xend_state_path()
                                     + '/local_sr')
diff -r 9ec7dadc98ba -r eb3e430242ac tools/python/xen/xend/XendNode.py
--- a/tools/python/xen/xend/XendNode.py Fri Apr 06 10:06:30 2007 -0600
+++ b/tools/python/xen/xend/XendNode.py Fri Apr 06 10:08:30 2007 -0600
@@ -22,17 +22,18 @@ import xen.lowlevel.xc
 
 from xen.util import Brctl
 
-from xen.xend import uuid, arch
-from xen.xend.XendError import *
-from xen.xend.XendOptions import instance as xendoptions
-from xen.xend.XendQCoWStorageRepo import XendQCoWStorageRepo
-from xen.xend.XendLocalStorageRepo import XendLocalStorageRepo
-from xen.xend.XendLogging import log
-from xen.xend.XendPIF import *
-from xen.xend.XendPIFMetrics import XendPIFMetrics
-from xen.xend.XendNetwork import *
-from xen.xend.XendStateStore import XendStateStore
-from xen.xend.XendMonitor import XendMonitor
+import uuid, arch
+import XendPBD
+from XendError import *
+from XendOptions import instance as xendoptions
+from XendQCoWStorageRepo import XendQCoWStorageRepo
+from XendLocalStorageRepo import XendLocalStorageRepo
+from XendLogging import log
+from XendPIF import *
+from XendPIFMetrics import XendPIFMetrics
+from XendNetwork import *
+from XendStateStore import XendStateStore
+from XendMonitor import XendMonitor
 
 class XendNode:
     """XendNode - Represents a Domain 0 Host."""
@@ -193,13 +194,14 @@ class XendNode:
         saved_srs = self.state_store.load_state('sr')
         if saved_srs:
             for sr_uuid, sr_cfg in saved_srs.items():
+                log.error("SAved SRS %s %s", sr_uuid, sr_cfg['type'])
                 if sr_cfg['type'] == 'qcow_file':
                     self.srs[sr_uuid] = XendQCoWStorageRepo(sr_uuid)
-                elif sr_cfg['type'] == 'local_image':
+                elif sr_cfg['type'] == 'local':
                     self.srs[sr_uuid] = XendLocalStorageRepo(sr_uuid)
 
         # Create missing SRs if they don't exist
-        if not self.get_sr_by_type('local_image'):
+        if not self.get_sr_by_type('local'):
             image_sr_uuid = uuid.createString()
             self.srs[image_sr_uuid] = XendLocalStorageRepo(image_sr_uuid)
             
@@ -207,6 +209,11 @@ class XendNode:
             qcow_sr_uuid = uuid.createString()
             self.srs[qcow_sr_uuid] = XendQCoWStorageRepo(qcow_sr_uuid)
 
+        saved_pbds = self.state_store.load_state('pbd')
+        if saved_pbds:
+            for pbd_uuid, pbd_cfg in saved_pbds.items():
+                pbd_cfg['uuid'] = pbd_uuid
+                XendPBD.XendPBD(pbd_cfg)
 
 
     def network_create(self, record, persist = True, net_uuid = None):
@@ -280,6 +287,7 @@ class XendNode:
         self.state_store.save_state('cpu', self.cpus)
         self.save_PIFs()
         self.save_networks()
+        self.save_PBDs()
         self.save_SRs()
 
     def save_PIFs(self):
@@ -291,6 +299,11 @@ class XendNode:
         net_records = dict([(k, v.get_record_internal(False))
                             for k, v in self.networks.items()])
         self.state_store.save_state('network', net_records)
+
+    def save_PBDs(self):
+        pbd_records = dict([(v.get_uuid(), v.get_record())
+                            for v in XendPBD.get_all()])
+        self.state_store.save_state('pbd', pbd_records)
 
     def save_SRs(self):
         sr_records = dict([(k, v.get_record(transient = False))
diff -r 9ec7dadc98ba -r eb3e430242ac tools/python/xen/xend/XendPBD.py
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/python/xen/xend/XendPBD.py  Fri Apr 06 10:08:30 2007 -0600
@@ -0,0 +1,79 @@
+#============================================================================
+# 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 Xensource Inc.
+#============================================================================
+
+
+import uuid
+from XendLogging import log
+
+
+attr_inst = ['uuid',
+             'host',
+             'SR',
+             'device_config']
+attr_ro = attr_inst + ['currently_attached']
+
+
+_all = {}
+
+
+def get(ref):
+    return _all[ref]
+
+
+def get_all():
+    return _all.values()
+
+
+def get_all_refs():
+    return _all.keys()
+
+
+def get_by_SR(sr_ref):
+    return [k for (k, v) in _all.items() if v.get_SR() == sr_ref]
+
+
+class XendPBD:
+    """Physical block devices."""
+    
+    def __init__(self, record):
+        if 'uuid' not in record:
+            record['uuid'] = uuid.createString()
+
+        import XendAPI
+        for v in attr_inst:
+            setattr(self, v, record[v])
+        self.currently_attached = True
+        _all[record['uuid']] = self
+
+
+    def destroy(self):
+        if self.uuid in _all:
+            del _all[self.uuid]
+
+
+    def get_record(self):
+        import XendAPI
+        result = {}
+        for v in attr_ro:
+            result[v] = getattr(self, v)
+        return result
+
+
+for v in attr_ro:
+    def f(v_):
+        setattr(XendPBD, 'get_' + v_, lambda s: getattr(s, v_))
+    f(v)
diff -r 9ec7dadc98ba -r eb3e430242ac 
tools/python/xen/xend/XendQCoWStorageRepo.py
--- a/tools/python/xen/xend/XendQCoWStorageRepo.py      Fri Apr 06 10:06:30 
2007 -0600
+++ b/tools/python/xen/xend/XendQCoWStorageRepo.py      Fri Apr 06 10:08:30 
2007 -0600
@@ -29,12 +29,13 @@ import struct
 import struct
 
 from xen.util import mkdir
-from xen.xend import uuid
-from xen.xend.XendError import XendError
-from xen.xend.XendVDI import *
-from xen.xend.XendTask import XendTask
-from xen.xend.XendStorageRepository import XendStorageRepository
-from xen.xend.XendOptions import instance as xendoptions
+import uuid
+import XendPBD
+from XendError import XendError
+from XendVDI import *
+from XendTask import XendTask
+from XendStorageRepository import XendStorageRepository
+from XendOptions import instance as xendoptions
 
 XEND_STORAGE_NO_MAXIMUM = sys.maxint
 XEND_STORAGE_QCOW_FILENAME = "%s.qcow"
@@ -72,7 +73,6 @@ class XendQCoWStorageRepo(XendStorageRep
                  sr_type = "qcow_file",
                  name_label = "QCoW",
                  name_description = "Xend QCoW Storage Repository",
-                 location = xendoptions().get_xend_storage_path(),
                  storage_max = XEND_STORAGE_NO_MAXIMUM):
         """
         @keyword storage_max: Maximum disk space to use in bytes.
@@ -85,9 +85,9 @@ class XendQCoWStorageRepo(XendStorageRep
         """
 
         XendStorageRepository.__init__(self, sr_uuid, sr_type, name_label,
-                                       name_description, location,
-                                       storage_max)
+                                       name_description, storage_max)
         self.storage_free = 0
+        self.location = xendoptions().get_xend_storage_path()
         self._refresh()
 
     def get_record(self, transient = True):
@@ -98,8 +98,9 @@ class XendQCoWStorageRepo(XendStorageRep
                   'physical_utilisation': self.physical_utilisation,
                   'physical_size': self.physical_size,
                   'type': self.type,
-                  'location': self.location,
-                  'VDIs': self.images.keys()}
+                  'content_type': self.content_type,
+                  'VDIs': self.images.keys(),
+                  'PBDs': XendPBD.get_by_SR(self.uuid)}
         
         if self.physical_size == XEND_STORAGE_NO_MAXIMUM:
             stfs = os.statvfs(self.location)
diff -r 9ec7dadc98ba -r eb3e430242ac tools/python/xen/xend/XendStateStore.py
--- a/tools/python/xen/xend/XendStateStore.py   Fri Apr 06 10:06:30 2007 -0600
+++ b/tools/python/xen/xend/XendStateStore.py   Fri Apr 06 10:08:30 2007 -0600
@@ -204,7 +204,7 @@ class XendStateStore:
                 if type(val) == dict:
                     for val_uuid in val.keys():
                         val_node = doc.createElement(key)
-                        if key == 'other_config':
+                        if key in ['other_config', 'device_config']:
                             val_node.setAttribute('key', str(val_uuid))
                             val_node.setAttribute('value', str(val[val_uuid]))
                         else:
diff -r 9ec7dadc98ba -r eb3e430242ac 
tools/python/xen/xend/XendStorageRepository.py
--- a/tools/python/xen/xend/XendStorageRepository.py    Fri Apr 06 10:06:30 
2007 -0600
+++ b/tools/python/xen/xend/XendStorageRepository.py    Fri Apr 06 10:08:30 
2007 -0600
@@ -22,8 +22,9 @@ import threading
 import threading
 import sys
 
-from xen.xend.XendError import XendError
-from xen.xend.XendVDI import *
+from XendError import XendError
+from XendVDI import *
+import XendPBD
 
 XEND_STORAGE_NO_MAXIMUM = sys.maxint
 
@@ -34,7 +35,6 @@ class XendStorageRepository:
                  sr_type = "unknown",
                  name_label = 'Unknown',
                  name_description = 'Not Implemented',
-                 location = '',
                  storage_max = XEND_STORAGE_NO_MAXIMUM):
         """
         @keyword storage_max: Maximum disk space to use in bytes.
@@ -49,7 +49,6 @@ class XendStorageRepository:
         # XenAPI Parameters
         self.uuid = uuid
         self.type = sr_type
-        self.location = location
         self.name_label = name_label
         self.name_description = name_description
         self.images = {}
@@ -57,6 +56,7 @@ class XendStorageRepository:
         self.physical_size = storage_max
         self.physical_utilisation = 0
         self.virtual_allocation = 0
+        self.content_type = ''
  
         self.lock = threading.RLock()
 
@@ -68,9 +68,10 @@ class XendStorageRepository:
                   'physical_utilisation': self.physical_utilisation,
                   'physical_size': self.physical_size,
                   'type': self.type,
-                  'location': self.location,
+                  'content_type': self.content_type,
                   'VDIs': self.images.keys()}
-
+        if not transient:
+            retval ['PBDs'] = XendPBD.get_by_SR(self.uuid)
         return retval
 
 
diff -r 9ec7dadc98ba -r eb3e430242ac tools/python/xen/xend/XendTask.py
--- a/tools/python/xen/xend/XendTask.py Fri Apr 06 10:06:30 2007 -0600
+++ b/tools/python/xen/xend/XendTask.py Fri Apr 06 10:08:30 2007 -0600
@@ -24,7 +24,7 @@ class XendTask(threading.Thread):
     """Represents a Asynchronous Task used by Xen API.
 
     Basically proxies the callable object in a thread and returns the
-    results via self.{type,result,error_code,error_info}.
+    results via self.{type,result,error_info}.
 
     @cvar task_progress: Thread local storage for progress tracking.
                          It is a dict indexed by thread_id. Note that the
@@ -71,7 +71,6 @@ class XendTask(threading.Thread):
         self.uuid = uuid
         
         self.result = None
-        self.error_code = ''
         self.error_info = []
         
         self.name_label = label or func.__name__
@@ -118,13 +117,11 @@ class XendTask(threading.Thread):
                 self.result = result['Value']
                 self.set_status(XEN_API_TASK_STATUS_TYPE[1])
             else:
-                self.error_code = result['ErrorDescription'][0]
-                self.error_info = result['ErrorDescription'][1:]
+                self.error_info = result['ErrorDescription']
                 self.set_status(XEN_API_TASK_STATUS_TYPE[2])                
         except Exception, e:
             log.exception('Error running Async Task')
-            self.error_code = 'INTERNAL ERROR'
-            self.error_info = [str(e)]
+            self.error_info = ['INTERNAL ERROR', str(e)]
             self.set_status(XEN_API_TASK_STATUS_TYPE[2])
 
         self.task_progress_lock.acquire()
@@ -144,7 +141,6 @@ class XendTask(threading.Thread):
             'progress': self.get_progress(),
             'type': self.type,
             'result': self.result,
-            'error_code': self.error_code,
             'error_info': self.error_info,
             'allowed_operations': {},
             'session': self.session,
diff -r 9ec7dadc98ba -r eb3e430242ac tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py    Fri Apr 06 10:06:30 2007 -0600
+++ b/tools/python/xen/xend/image.py    Fri Apr 06 10:08:30 2007 -0600
@@ -426,11 +426,14 @@ class HVMImageHandler(ImageHandler):
         # Execute device model.
         #todo: Error handling
         args = [self.device_model]
-        args = args + ([ "-d",  "%d" % self.vm.getDomid(),
-                  "-m", "%s" % (self.getRequiredInitialReservation() / 1024)])
+        args = args + ([ "-d",  "%d" % self.vm.getDomid() ])
+        if arch.type == "ia64":
+            args = args + ([ "-m", "%s" %
+                             (self.getRequiredInitialReservation() / 1024) ])
         args = args + self.dmargs
         if restore:
-            args = args + ([ "-loadvm", "/tmp/xen.qemu-dm.%d" % 
self.vm.getDomid() ])
+            args = args + ([ "-loadvm", "/tmp/xen.qemu-dm.%d" %
+                             self.vm.getDomid() ])
         env = dict(os.environ)
         if self.display:
             env['DISPLAY'] = self.display
diff -r 9ec7dadc98ba -r eb3e430242ac tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py       Fri Apr 06 10:06:30 2007 -0600
+++ b/tools/python/xen/xm/main.py       Fri Apr 06 10:08:30 2007 -0600
@@ -591,7 +591,7 @@ class Shell(cmd.Cmd):
         self.prompt = "xm> "
         if serverType == SERVER_XEN_API:
             try:
-                res = server.xenapi._UNSUPPORTED_list_all_methods()
+                res = server.xenapi.host.list_methods()
                 for f in res:
                     setattr(Shell, 'do_' + f + ' ', self.default)
             except:
diff -r 9ec7dadc98ba -r eb3e430242ac tools/xcutils/xc_restore.c
--- a/tools/xcutils/xc_restore.c        Fri Apr 06 10:06:30 2007 -0600
+++ b/tools/xcutils/xc_restore.c        Fri Apr 06 10:08:30 2007 -0600
@@ -21,37 +21,31 @@ main(int argc, char **argv)
     unsigned int xc_fd, io_fd, domid, store_evtchn, console_evtchn;
     unsigned int hvm, pae, apic;
     int ret;
-    unsigned long p2m_size, max_nr_pfns, store_mfn, console_mfn;
+    unsigned long store_mfn, console_mfn;
 
-    if (argc != 10)
-        errx(1, "usage: %s iofd domid p2m_size max_nr_pfns store_evtchn "
+    if ( argc != 8 )
+        errx(1, "usage: %s iofd domid store_evtchn "
              "console_evtchn hvm pae apic", argv[0]);
 
     xc_fd = xc_interface_open();
-    if (xc_fd < 0)
+    if ( xc_fd < 0 )
         errx(1, "failed to open control interface");
 
     io_fd = atoi(argv[1]);
     domid = atoi(argv[2]);
-    p2m_size = atoi(argv[3]);
-    max_nr_pfns = atoi(argv[4]);
-    store_evtchn = atoi(argv[5]);
-    console_evtchn = atoi(argv[6]);
-    hvm  = atoi(argv[7]);
-    pae  = atoi(argv[8]);
-    apic = atoi(argv[9]);
+    store_evtchn = atoi(argv[3]);
+    console_evtchn = atoi(argv[4]);
+    hvm  = atoi(argv[5]);
+    pae  = atoi(argv[6]);
+    apic = atoi(argv[7]);
 
-    if (hvm) {
-        ret = xc_hvm_restore(xc_fd, io_fd, domid, max_nr_pfns, store_evtchn,
-                &store_mfn, pae, apic);
-    } else
-        ret = xc_linux_restore(xc_fd, io_fd, domid, p2m_size,
-                               max_nr_pfns, store_evtchn, &store_mfn,
-                               console_evtchn, &console_mfn);
+    ret = xc_domain_restore(xc_fd, io_fd, domid, store_evtchn, &store_mfn,
+                            console_evtchn, &console_mfn, hvm, pae);
 
-    if (ret == 0) {
+    if ( ret == 0 )
+    {
        printf("store-mfn %li\n", store_mfn);
-        if (!hvm)
+        if ( !hvm )
             printf("console-mfn %li\n", console_mfn);
        fflush(stdout);
     }
diff -r 9ec7dadc98ba -r eb3e430242ac unmodified_drivers/linux-2.6/Makefile
--- a/unmodified_drivers/linux-2.6/Makefile     Fri Apr 06 10:06:30 2007 -0600
+++ b/unmodified_drivers/linux-2.6/Makefile     Fri Apr 06 10:08:30 2007 -0600
@@ -2,6 +2,7 @@ include $(M)/overrides.mk
 
 obj-m += platform-pci/
 obj-m += xenbus/
+obj-m += balloon/
 obj-m += blkfront/
 obj-m += netfront/
 obj-m += util/
diff -r 9ec7dadc98ba -r eb3e430242ac unmodified_drivers/linux-2.6/balloon/Kbuild
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/unmodified_drivers/linux-2.6/balloon/Kbuild       Fri Apr 06 10:08:30 
2007 -0600
@@ -0,0 +1,9 @@
+include $(M)/overrides.mk
+
+obj-m  = xen-balloon.o
+
+EXTRA_CFLAGS += -I$(M)/platform-pci
+
+xen-balloon-objs =
+xen-balloon-objs += balloon.o
+xen-balloon-objs += sysfs.o
diff -r 9ec7dadc98ba -r eb3e430242ac 
unmodified_drivers/linux-2.6/balloon/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/unmodified_drivers/linux-2.6/balloon/Makefile     Fri Apr 06 10:08:30 
2007 -0600
@@ -0,0 +1,3 @@
+ifneq ($(KERNELRELEASE),)
+include $(src)/Kbuild
+endif
diff -r 9ec7dadc98ba -r eb3e430242ac 
unmodified_drivers/linux-2.6/compat-include/xen/platform-compat.h
--- a/unmodified_drivers/linux-2.6/compat-include/xen/platform-compat.h Fri Apr 
06 10:06:30 2007 -0600
+++ b/unmodified_drivers/linux-2.6/compat-include/xen/platform-compat.h Fri Apr 
06 10:08:30 2007 -0600
@@ -25,6 +25,10 @@
 #define NET_IP_ALIGN 0
 #endif
 
+#if defined(_LINUX_SKBUFF_H) && !defined(CHECKSUM_HW)
+#define CHECKSUM_HW CHECKSUM_PARTIAL
+#endif
+
 #if defined(_LINUX_ERR_H) && !defined(IS_ERR_VALUE)
 #define IS_ERR_VALUE(x) unlikely((x) > (unsigned long)-1000L)
 #endif
@@ -36,7 +40,7 @@
 /* Some kernels have this typedef backported so we cannot reliably
  * detect based on version number, hence we forcibly #define it.
  */
-#if defined(__LINUX_TYPES_H) || defined(__LINUX_GFP_H)
+#if defined(__LINUX_TYPES_H) || defined(__LINUX_GFP_H) || 
defined(_LINUX_KERNEL_H)
 #define gfp_t unsigned
 #endif
 
@@ -45,6 +49,14 @@
 #define atomic_notifier_chain_register(chain,nb) 
notifier_chain_register(chain,nb)
 #define atomic_notifier_chain_unregister(chain,nb) 
notifier_chain_unregister(chain,nb)
 #define atomic_notifier_call_chain(chain,val,v) 
notifier_call_chain(chain,val,v)
+#endif
+
+#if defined(_LINUX_MM_H) && defined set_page_count
+#define init_page_count(page) set_page_count(page, 1)
+#endif
+
+#if defined(__LINUX_GFP_H) && !defined __GFP_NOMEMALLOC
+#define __GFP_NOMEMALLOC 0
 #endif
 
 #if defined(_LINUX_FS_H) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)
@@ -71,9 +83,17 @@ void *kzalloc(size_t size, int flags);
 #define end_that_request_last(req, uptodate) end_that_request_last(req)
 #endif
 
+#if defined(_LINUX_CAPABILITY_H) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
+#define capable(cap) (1)
+#endif
+
 #if defined(_LINUX_KERNEL_H) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
 extern char *kasprintf(gfp_t gfp, const char *fmt, ...)
        __attribute__ ((format (printf, 2, 3)));
+#endif
+
+#if defined(_LINUX_SYSRQ_H) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)
+#define handle_sysrq(x,y,z) handle_sysrq(x,y)
 #endif
 
 /*
diff -r 9ec7dadc98ba -r eb3e430242ac unmodified_drivers/linux-2.6/mkbuildtree
--- a/unmodified_drivers/linux-2.6/mkbuildtree  Fri Apr 06 10:06:30 2007 -0600
+++ b/unmodified_drivers/linux-2.6/mkbuildtree  Fri Apr 06 10:08:30 2007 -0600
@@ -15,6 +15,9 @@ XL=$C/../../linux-2.6-xen-sparse
 
 for d in $(find ${XL}/drivers/xen/ -maxdepth 1 -type d | sed -e 1d); do
     if ! echo $d | egrep -q back; then
+        lndir $d $(basename $d) > /dev/null 2>&1
+    fi
+    if ! echo $d | egrep -q ball; then
         lndir $d $(basename $d) > /dev/null 2>&1
     fi
 done
diff -r 9ec7dadc98ba -r eb3e430242ac unmodified_drivers/linux-2.6/overrides.mk
--- a/unmodified_drivers/linux-2.6/overrides.mk Fri Apr 06 10:06:30 2007 -0600
+++ b/unmodified_drivers/linux-2.6/overrides.mk Fri Apr 06 10:08:30 2007 -0600
@@ -4,7 +4,8 @@
 #
 # (i.e. we need the native config for things like -mregparm, but
 # a Xen kernel to find the right headers)
-EXTRA_CFLAGS += -D__XEN_INTERFACE_VERSION__=0x00030202
+EXTRA_CFLAGS += -D__XEN_INTERFACE_VERSION__=0x00030205
+EXTRA_CFLAGS += -DCONFIG_XEN_COMPAT=0xffffff
 EXTRA_CFLAGS += -I$(M)/include -I$(M)/compat-include 
-DHAVE_XEN_PLATFORM_COMPAT_H
 ifeq ($(ARCH),ia64)
   EXTRA_CFLAGS += -DCONFIG_VMX_GUEST
diff -r 9ec7dadc98ba -r eb3e430242ac 
unmodified_drivers/linux-2.6/platform-pci/platform-pci.c
--- a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c  Fri Apr 06 
10:06:30 2007 -0600
+++ b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c  Fri Apr 06 
10:08:30 2007 -0600
@@ -208,14 +208,6 @@ static uint64_t get_callback_via(struct 
                ((uint64_t)(pin - 1) & 3));
 }
 
-/* Invalidate foreign mappings (e.g., in qemu-based device model). */
-static uint16_t invlmap_port;
-void xen_invalidate_foreign_mappings(void)
-{
-       outb(0, invlmap_port);
-}
-EXPORT_SYMBOL(xen_invalidate_foreign_mappings);
-
 static int __devinit platform_pci_init(struct pci_dev *pdev,
                                       const struct pci_device_id *ent)
 {
@@ -239,8 +231,6 @@ static int __devinit platform_pci_init(s
                printk(KERN_WARNING DRV_NAME ":no resources found\n");
                return -ENOENT;
        }
-
-       invlmap_port = ioaddr;
 
        if (request_mem_region(mmio_addr, mmio_len, DRV_NAME) == NULL)
        {
diff -r 9ec7dadc98ba -r eb3e430242ac 
unmodified_drivers/linux-2.6/platform-pci/xen_support.c
--- a/unmodified_drivers/linux-2.6/platform-pci/xen_support.c   Fri Apr 06 
10:06:30 2007 -0600
+++ b/unmodified_drivers/linux-2.6/platform-pci/xen_support.c   Fri Apr 06 
10:08:30 2007 -0600
@@ -59,12 +59,3 @@ void xen_machphys_update(unsigned long m
 }
 EXPORT_SYMBOL(xen_machphys_update);
 
-void balloon_update_driver_allowance(long delta)
-{
-}
-EXPORT_SYMBOL(balloon_update_driver_allowance);
-
-void balloon_release_driver_page(struct page *page)
-{
-}
-EXPORT_SYMBOL(balloon_release_driver_page);
diff -r 9ec7dadc98ba -r eb3e430242ac xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Fri Apr 06 10:06:30 2007 -0600
+++ b/xen/arch/x86/hvm/hvm.c    Fri Apr 06 10:08:30 2007 -0600
@@ -131,7 +131,7 @@ void hvm_do_resume(struct vcpu *v)
         switch ( p->state )
         {
         case STATE_IORESP_READY: /* IORESP_READY -> NONE */
-            hvm_io_assist(v);
+            hvm_io_assist();
             break;
         case STATE_IOREQ_READY:  /* IOREQ_{READY,INPROCESS} -> IORESP_READY */
         case STATE_IOREQ_INPROCESS:
@@ -144,48 +144,6 @@ void hvm_do_resume(struct vcpu *v)
             domain_crash_synchronous();
         }
     }
-}
-
-/* Called from the tools when saving a domain to make sure the io
- * request-response ring is entirely empty. */
-static int hvmop_drain_io(
-    XEN_GUEST_HANDLE(xen_hvm_drain_io_t) uop)
-{
-    struct xen_hvm_drain_io op;
-    struct domain *d;
-    struct vcpu *v;
-    ioreq_t *p;
-    int rc;
-
-    if ( copy_from_guest(&op, uop, 1) )
-        return -EFAULT;
-
-    if ( !IS_PRIV(current->domain) )
-        return -EPERM;
-
-    d = rcu_lock_domain_by_id(op.domid);
-    if ( d == NULL )
-        return -ESRCH;
-
-    rc = -EINVAL;
-    /* Can't do this to yourself, or to a domain without an ioreq ring */
-    if ( d == current->domain || !is_hvm_domain(d) || get_sp(d) == NULL )
-        goto out;
-
-    rc = 0;
-
-    domain_pause(d);  /* It's not safe to do this to running vcpus */
-    for_each_vcpu(d, v)
-    {
-        p = &get_vio(v->domain, v->vcpu_id)->vp_ioreq;
-        if ( p->state == STATE_IORESP_READY )
-            hvm_io_assist(v);
-    }
-    domain_unpause(d);
-
- out:
-    rcu_unlock_domain(d);
-    return rc;
 }
 
 int hvm_domain_initialise(struct domain *d)
@@ -563,19 +521,13 @@ static hvm_hypercall_t *hvm_hypercall_ta
     HYPERCALL(hvm_op)
 };
 
-void hvm_do_hypercall(struct cpu_user_regs *pregs)
-{
-    if ( unlikely(ring_3(pregs)) )
-    {
-        pregs->eax = -EPERM;
-        return;
-    }
-
+static void __hvm_do_hypercall(struct cpu_user_regs *pregs)
+{
     if ( (pregs->eax >= NR_hypercalls) || !hvm_hypercall_table[pregs->eax] )
     {
-        gdprintk(XENLOG_WARNING, "HVM vcpu %d:%d did a bad hypercall %d.\n",
-                current->domain->domain_id, current->vcpu_id,
-                pregs->eax);
+        if ( pregs->eax != __HYPERVISOR_grant_table_op )
+            gdprintk(XENLOG_WARNING, "HVM vcpu %d:%d bad hypercall %d.\n",
+                     current->domain->domain_id, current->vcpu_id, pregs->eax);
         pregs->eax = -ENOSYS;
         return;
     }
@@ -641,20 +593,14 @@ static hvm_hypercall_t *hvm_hypercall32_
     HYPERCALL(event_channel_op)
 };
 
-void hvm_do_hypercall(struct cpu_user_regs *pregs)
-{
-    if ( unlikely(ring_3(pregs)) )
-    {
-        pregs->rax = -EPERM;
-        return;
-    }
-
+static void __hvm_do_hypercall(struct cpu_user_regs *pregs)
+{
     pregs->rax = (uint32_t)pregs->eax; /* mask in case compat32 caller */
     if ( (pregs->rax >= NR_hypercalls) || !hvm_hypercall64_table[pregs->rax] )
     {
-        gdprintk(XENLOG_WARNING, "HVM vcpu %d:%d did a bad hypercall %ld.\n",
-                current->domain->domain_id, current->vcpu_id,
-                pregs->rax);
+        if ( pregs->rax != __HYPERVISOR_grant_table_op )
+            gdprintk(XENLOG_WARNING, "HVM vcpu %d:%d bad hypercall %ld.\n",
+                     current->domain->domain_id, current->vcpu_id, pregs->rax);
         pregs->rax = -ENOSYS;
         return;
     }
@@ -678,6 +624,37 @@ void hvm_do_hypercall(struct cpu_user_re
 }
 
 #endif /* defined(__x86_64__) */
+
+int hvm_do_hypercall(struct cpu_user_regs *pregs)
+{
+    int flush, preempted;
+    unsigned long old_eip;
+
+    if ( unlikely(ring_3(pregs)) )
+    {
+        pregs->eax = -EPERM;
+        return 0;
+    }
+
+    /*
+     * NB. In future flush only on decrease_reservation.
+     * For now we also need to flush when pages are added, as qemu-dm is not
+     * yet capable of faulting pages into an existing valid mapcache bucket.
+     */
+    flush = ((uint32_t)pregs->eax == __HYPERVISOR_memory_op);
+
+    /* Check for preemption: RIP will be modified from this dummy value. */
+    old_eip = pregs->eip;
+    pregs->eip = 0xF0F0F0FF;
+
+    __hvm_do_hypercall(pregs);
+
+    preempted = (pregs->eip != 0xF0F0F0FF);
+    pregs->eip = old_eip;
+
+    return (preempted ? HVM_HCALL_preempted :
+            flush ? HVM_HCALL_invalidate : HVM_HCALL_completed);
+}
 
 void hvm_update_guest_cr3(struct vcpu *v, unsigned long guest_cr3)
 {
@@ -963,12 +940,6 @@ long do_hvm_op(unsigned long op, XEN_GUE
             guest_handle_cast(arg, xen_hvm_set_pci_link_route_t));
         break;
 
-    case HVMOP_drain_io:
-        rc = hvmop_drain_io(
-            guest_handle_cast(arg, xen_hvm_drain_io_t));
-        break;
-
-
     default:
     {
         gdprintk(XENLOG_WARNING, "Bad HVM op %ld.\n", op);
diff -r 9ec7dadc98ba -r eb3e430242ac xen/arch/x86/hvm/io.c
--- a/xen/arch/x86/hvm/io.c     Fri Apr 06 10:06:30 2007 -0600
+++ b/xen/arch/x86/hvm/io.c     Fri Apr 06 10:08:30 2007 -0600
@@ -289,8 +289,12 @@ static void set_reg_value (int size, int
 
 long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs);
 
-static inline void set_eflags_CF(int size, unsigned long v1,
-                                 unsigned long v2, struct cpu_user_regs *regs)
+static inline void set_eflags_CF(int size,
+                                 unsigned int instr,
+                                 unsigned long result,
+                                 unsigned long src,
+                                 unsigned long dst,
+                                 struct cpu_user_regs *regs)
 {
     unsigned long mask;
 
@@ -300,14 +304,28 @@ static inline void set_eflags_CF(int siz
 
     mask = ~0UL >> (8 * (sizeof(mask) - size));
 
-    if ((v1 & mask) > (v2 & mask))
-        regs->eflags |= X86_EFLAGS_CF;
+    if ( instr == INSTR_ADD )
+    {
+        /* CF=1 <==> result is less than the augend and addend) */
+        if ( (result & mask) < (dst & mask) )
+        {
+            ASSERT((result & mask) < (src & mask));
+            regs->eflags |= X86_EFLAGS_CF;
+        }
+    }
     else
-        regs->eflags &= ~X86_EFLAGS_CF;
-}
-
-static inline void set_eflags_OF(int size, unsigned long v1,
-                                 unsigned long v2, unsigned long v3,
+    {
+        ASSERT( instr == INSTR_CMP || instr == INSTR_SUB );
+        if ( (src & mask) > (dst & mask) )
+            regs->eflags |= X86_EFLAGS_CF;
+    }
+}
+
+static inline void set_eflags_OF(int size,
+                                 unsigned int instr,
+                                 unsigned long result,
+                                 unsigned long src,
+                                 unsigned long dst,
                                  struct cpu_user_regs *regs)
 {
     unsigned long mask;
@@ -316,21 +334,32 @@ static inline void set_eflags_OF(int siz
         size = BYTE;
     ASSERT((size <= sizeof(mask)) && (size > 0));
 
-    mask = ~0UL >> (8 * (sizeof(mask) - size));
-
-    if ((v3 ^ v2) & (v3 ^ v1) & mask)
-        regs->eflags |= X86_EFLAGS_OF;
-}
-
-static inline void set_eflags_AF(int size, unsigned long v1,
-                                 unsigned long v2, unsigned long v3,
+    mask =  1UL << ((8*size) - 1);
+
+    if ( instr == INSTR_ADD )
+    {
+        if ((src ^ result) & (dst ^ result) & mask);
+            regs->eflags |= X86_EFLAGS_OF;
+    }
+    else
+    {
+        ASSERT(instr == INSTR_CMP || instr == INSTR_SUB);
+        if ((dst ^ src) & (dst ^ result) & mask)
+            regs->eflags |= X86_EFLAGS_OF;
+    }
+}
+
+static inline void set_eflags_AF(int size,
+                                 unsigned long result,
+                                 unsigned long src,
+                                 unsigned long dst,
                                  struct cpu_user_regs *regs)
 {
-    if ((v1 ^ v2 ^ v3) & 0x10)
+    if ((result ^ src ^ dst) & 0x10)
         regs->eflags |= X86_EFLAGS_AF;
 }
 
-static inline void set_eflags_ZF(int size, unsigned long v1,
+static inline void set_eflags_ZF(int size, unsigned long result,
                                  struct cpu_user_regs *regs)
 {
     unsigned long mask;
@@ -341,11 +370,11 @@ static inline void set_eflags_ZF(int siz
 
     mask = ~0UL >> (8 * (sizeof(mask) - size));
 
-    if ((v1 & mask) == 0)
+    if ((result & mask) == 0)
         regs->eflags |= X86_EFLAGS_ZF;
 }
 
-static inline void set_eflags_SF(int size, unsigned long v1,
+static inline void set_eflags_SF(int size, unsigned long result,
                                  struct cpu_user_regs *regs)
 {
     unsigned long mask;
@@ -354,9 +383,9 @@ static inline void set_eflags_SF(int siz
         size = BYTE;
     ASSERT((size <= sizeof(mask)) && (size > 0));
 
-    mask = ~0UL >> (8 * (sizeof(mask) - size));
-
-    if (v1 & mask)
+    mask = 1UL << ((8*size) - 1);
+
+    if (result & mask)
         regs->eflags |= X86_EFLAGS_SF;
 }
 
@@ -379,10 +408,10 @@ static char parity_table[256] = {
     1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
 };
 
-static inline void set_eflags_PF(int size, unsigned long v1,
+static inline void set_eflags_PF(int size, unsigned long result,
                                  struct cpu_user_regs *regs)
 {
-    if (parity_table[v1 & 0xFF])
+    if (parity_table[result & 0xFF])
         regs->eflags |= X86_EFLAGS_PF;
 }
 
@@ -454,7 +483,7 @@ static void hvm_mmio_assist(struct cpu_u
 {
     int sign = p->df ? -1 : 1;
     int size = -1, index = -1;
-    unsigned long value = 0, diff = 0;
+    unsigned long value = 0, result = 0;
     unsigned long src, dst;
 
     src = mmio_opp->operand[0];
@@ -575,31 +604,15 @@ static void hvm_mmio_assist(struct cpu_u
         if (src & REGISTER) {
             index = operand_index(src);
             value = get_reg_value(size, index, 0, regs);
-            diff = (unsigned long) p->data & value;
+            result = (unsigned long) p->data & value;
         } else if (src & IMMEDIATE) {
             value = mmio_opp->immediate;
-            diff = (unsigned long) p->data & value;
+            result = (unsigned long) p->data & value;
         } else if (src & MEMORY) {
             index = operand_index(dst);
             value = get_reg_value(size, index, 0, regs);
-            diff = (unsigned long) p->data & value;
-            set_reg_value(size, index, 0, regs, diff);
-        }
-        break;
-
-    case INSTR_ADD:
-        if (src & REGISTER) {
-            index = operand_index(src);
-            value = get_reg_value(size, index, 0, regs);
-            diff = (unsigned long) p->data + value;
-        } else if (src & IMMEDIATE) {
-            value = mmio_opp->immediate;
-            diff = (unsigned long) p->data + value;
-        } else if (src & MEMORY) {
-            index = operand_index(dst);
-            value = get_reg_value(size, index, 0, regs);
-            diff = (unsigned long) p->data + value;
-            set_reg_value(size, index, 0, regs, diff);
+            result = (unsigned long) p->data & value;
+            set_reg_value(size, index, 0, regs, result);
         }
 
         /*
@@ -609,24 +622,55 @@ static void hvm_mmio_assist(struct cpu_u
          */
         regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
                           X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
-        set_eflags_ZF(size, diff, regs);
-        set_eflags_SF(size, diff, regs);
-        set_eflags_PF(size, diff, regs);
+        set_eflags_ZF(size, result, regs);
+        set_eflags_SF(size, result, regs);
+        set_eflags_PF(size, result, regs);
+        break;
+
+    case INSTR_ADD:
+        if (src & REGISTER) {
+            index = operand_index(src);
+            value = get_reg_value(size, index, 0, regs);
+            result = (unsigned long) p->data + value;
+        } else if (src & IMMEDIATE) {
+            value = mmio_opp->immediate;
+            result = (unsigned long) p->data + value;
+        } else if (src & MEMORY) {
+            index = operand_index(dst);
+            value = get_reg_value(size, index, 0, regs);
+            result = (unsigned long) p->data + value;
+            set_reg_value(size, index, 0, regs, result);
+        }
+
+        /*
+         * The CF, OF, SF, ZF, AF, and PF flags are set according
+         * to the result
+         */
+        regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|X86_EFLAGS_AF|
+                          X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
+        set_eflags_CF(size, mmio_opp->instr, result, value,
+                      (unsigned long) p->data, regs);
+        set_eflags_OF(size, mmio_opp->instr, result, value,
+                      (unsigned long) p->data, regs);
+        set_eflags_AF(size, result, value, (unsigned long) p->data, regs);
+        set_eflags_ZF(size, result, regs);
+        set_eflags_SF(size, result, regs);
+        set_eflags_PF(size, result, regs);
         break;
 
     case INSTR_OR:
         if (src & REGISTER) {
             index = operand_index(src);
             value = get_reg_value(size, index, 0, regs);
-            diff = (unsigned long) p->data | value;
+            result = (unsigned long) p->data | value;
         } else if (src & IMMEDIATE) {
             value = mmio_opp->immediate;
-            diff = (unsigned long) p->data | value;
+            result = (unsigned long) p->data | value;
         } else if (src & MEMORY) {
             index = operand_index(dst);
             value = get_reg_value(size, index, 0, regs);
-            diff = (unsigned long) p->data | value;
-            set_reg_value(size, index, 0, regs, diff);
+            result = (unsigned long) p->data | value;
+            set_reg_value(size, index, 0, regs, result);
         }
 
         /*
@@ -636,24 +680,24 @@ static void hvm_mmio_assist(struct cpu_u
          */
         regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
                           X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
-        set_eflags_ZF(size, diff, regs);
-        set_eflags_SF(size, diff, regs);
-        set_eflags_PF(size, diff, regs);
+        set_eflags_ZF(size, result, regs);
+        set_eflags_SF(size, result, regs);
+        set_eflags_PF(size, result, regs);
         break;
 
     case INSTR_XOR:
         if (src & REGISTER) {
             index = operand_index(src);
             value = get_reg_value(size, index, 0, regs);
-            diff = (unsigned long) p->data ^ value;
+            result = (unsigned long) p->data ^ value;
         } else if (src & IMMEDIATE) {
             value = mmio_opp->immediate;
-            diff = (unsigned long) p->data ^ value;
+            result = (unsigned long) p->data ^ value;
         } else if (src & MEMORY) {
             index = operand_index(dst);
             value = get_reg_value(size, index, 0, regs);
-            diff = (unsigned long) p->data ^ value;
-            set_reg_value(size, index, 0, regs, diff);
+            result = (unsigned long) p->data ^ value;
+            set_reg_value(size, index, 0, regs, result);
         }
 
         /*
@@ -663,9 +707,9 @@ static void hvm_mmio_assist(struct cpu_u
          */
         regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
                           X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
-        set_eflags_ZF(size, diff, regs);
-        set_eflags_SF(size, diff, regs);
-        set_eflags_PF(size, diff, regs);
+        set_eflags_ZF(size, result, regs);
+        set_eflags_SF(size, result, regs);
+        set_eflags_PF(size, result, regs);
         break;
 
     case INSTR_CMP:
@@ -673,16 +717,16 @@ static void hvm_mmio_assist(struct cpu_u
         if (src & REGISTER) {
             index = operand_index(src);
             value = get_reg_value(size, index, 0, regs);
-            diff = (unsigned long) p->data - value;
+            result = (unsigned long) p->data - value;
         } else if (src & IMMEDIATE) {
             value = mmio_opp->immediate;
-            diff = (unsigned long) p->data - value;
+            result = (unsigned long) p->data - value;
         } else if (src & MEMORY) {
             index = operand_index(dst);
             value = get_reg_value(size, index, 0, regs);
-            diff = value - (unsigned long) p->data;
+            result = value - (unsigned long) p->data;
             if ( mmio_opp->instr == INSTR_SUB )
-                set_reg_value(size, index, 0, regs, diff);
+                set_reg_value(size, index, 0, regs, result);
         }
 
         /*
@@ -691,12 +735,24 @@ static void hvm_mmio_assist(struct cpu_u
          */
         regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|X86_EFLAGS_AF|
                           X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
-        set_eflags_CF(size, value, (unsigned long) p->data, regs);
-        set_eflags_OF(size, diff, value, (unsigned long) p->data, regs);
-        set_eflags_AF(size, diff, value, (unsigned long) p->data, regs);
-        set_eflags_ZF(size, diff, regs);
-        set_eflags_SF(size, diff, regs);
-        set_eflags_PF(size, diff, regs);
+        if ( src & (REGISTER | IMMEDIATE) )
+        {
+            set_eflags_CF(size, mmio_opp->instr, result, value,
+                          (unsigned long) p->data, regs);
+            set_eflags_OF(size, mmio_opp->instr, result, value,
+                          (unsigned long) p->data, regs);
+        }
+        else
+        {
+            set_eflags_CF(size, mmio_opp->instr, result,
+                          (unsigned long) p->data, value, regs);
+            set_eflags_OF(size, mmio_opp->instr, result,
+                          (unsigned long) p->data, value, regs);
+        }
+        set_eflags_AF(size, result, value, (unsigned long) p->data, regs);
+        set_eflags_ZF(size, result, regs);
+        set_eflags_SF(size, result, regs);
+        set_eflags_PF(size, result, regs);
         break;
 
     case INSTR_TEST:
@@ -709,16 +765,16 @@ static void hvm_mmio_assist(struct cpu_u
             index = operand_index(dst);
             value = get_reg_value(size, index, 0, regs);
         }
-        diff = (unsigned long) p->data & value;
+        result = (unsigned long) p->data & value;
 
         /*
          * Sets the SF, ZF, and PF status flags. CF and OF are set to 0
          */
         regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
                           X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
-        set_eflags_ZF(size, diff, regs);
-        set_eflags_SF(size, diff, regs);
-        set_eflags_PF(size, diff, regs);
+        set_eflags_ZF(size, result, regs);
+        set_eflags_SF(size, result, regs);
+        set_eflags_PF(size, result, regs);
         break;
 
     case INSTR_BT:
@@ -764,13 +820,14 @@ static void hvm_mmio_assist(struct cpu_u
     }
 }
 
-void hvm_io_assist(struct vcpu *v)
+void hvm_io_assist(void)
 {
     vcpu_iodata_t *vio;
     ioreq_t *p;
     struct cpu_user_regs *regs;
     struct hvm_io_op *io_opp;
     unsigned long gmfn;
+    struct vcpu *v = current;
     struct domain *d = v->domain;
 
     io_opp = &v->arch.hvm_vcpu.io_op;
@@ -788,10 +845,17 @@ void hvm_io_assist(struct vcpu *v)
 
     p->state = STATE_IOREQ_NONE;
 
-    if ( p->type == IOREQ_TYPE_PIO )
+    switch ( p->type )
+    {
+    case IOREQ_TYPE_INVALIDATE:
+        goto out;
+    case IOREQ_TYPE_PIO:
         hvm_pio_assist(regs, p, io_opp);
-    else
+        break;
+    default:
         hvm_mmio_assist(regs, p, io_opp);
+        break;
+    }
 
     /* Copy register changes back into current guest state. */
     hvm_load_cpu_guest_regs(v, regs);
@@ -804,6 +868,7 @@ void hvm_io_assist(struct vcpu *v)
         mark_dirty(d, gmfn);
     }
 
+ out:
     vcpu_end_shutdown_deferral(v);
 }
 
diff -r 9ec7dadc98ba -r eb3e430242ac xen/arch/x86/hvm/irq.c
--- a/xen/arch/x86/hvm/irq.c    Fri Apr 06 10:06:30 2007 -0600
+++ b/xen/arch/x86/hvm/irq.c    Fri Apr 06 10:08:30 2007 -0600
@@ -335,6 +335,21 @@ int is_isa_irq_masked(struct vcpu *v, in
     return ((v->domain->arch.hvm_domain.vpic[isa_irq >> 3].imr &
              (1 << (isa_irq & 7))) &&
             domain_vioapic(v->domain)->redirtbl[gsi].fields.mask);
+}
+
+/*
+ * TODO: 1. Should not need special treatment of event-channel events.
+ *       2. Should take notice of interrupt shadows (or clear them).
+ */
+int hvm_local_events_need_delivery(struct vcpu *v)
+{
+    int pending;
+
+    pending = (vcpu_info(v, evtchn_upcall_pending) || cpu_has_pending_irq(v));
+    if ( unlikely(pending) )
+        pending = hvm_interrupts_enabled(v); 
+
+    return pending;
 }
 
 #if 0 /* Keep for debugging */
diff -r 9ec7dadc98ba -r eb3e430242ac xen/arch/x86/hvm/platform.c
--- a/xen/arch/x86/hvm/platform.c       Fri Apr 06 10:06:30 2007 -0600
+++ b/xen/arch/x86/hvm/platform.c       Fri Apr 06 10:08:30 2007 -0600
@@ -865,7 +865,7 @@ void send_pio_req(unsigned long port, un
     if ( hvm_portio_intercept(p) )
     {
         p->state = STATE_IORESP_READY;
-        hvm_io_assist(v);
+        hvm_io_assist();
         return;
     }
 
@@ -914,7 +914,7 @@ static void send_mmio_req(unsigned char 
     if ( hvm_mmio_intercept(p) || hvm_buffered_io_intercept(p) )
     {
         p->state = STATE_IORESP_READY;
-        hvm_io_assist(v);
+        hvm_io_assist();
         return;
     }
 
@@ -939,6 +939,34 @@ void send_timeoffset_req(unsigned long t
 
     if ( !hvm_buffered_io_send(p) )
         printk("Unsuccessful timeoffset update\n");
+}
+
+/* Ask ioemu mapcache to invalidate mappings. */
+void send_invalidate_req(void)
+{
+    struct vcpu *v = current;
+    vcpu_iodata_t *vio;
+    ioreq_t *p;
+
+    vio = get_vio(v->domain, v->vcpu_id);
+    if ( vio == NULL )
+    {
+        printk("bad shared page: %lx\n", (unsigned long) vio);
+        domain_crash_synchronous();
+    }
+
+    p = &vio->vp_ioreq;
+    if ( p->state != STATE_IOREQ_NONE )
+        printk("WARNING: send invalidate req with something "
+               "already pending (%d)?\n", p->state);
+
+    p->type = IOREQ_TYPE_INVALIDATE;
+    p->size = 4;
+    p->dir = IOREQ_WRITE;
+    p->data = ~0UL; /* flush all */
+    p->io_count++;
+
+    hvm_send_assist_req(v);
 }
 
 static void mmio_operands(int type, unsigned long gpa,
diff -r 9ec7dadc98ba -r eb3e430242ac xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Fri Apr 06 10:06:30 2007 -0600
+++ b/xen/arch/x86/hvm/svm/svm.c        Fri Apr 06 10:08:30 2007 -0600
@@ -131,66 +131,6 @@ static void svm_store_cpu_guest_regs(
     }
 }
 
-
-static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
-{
-    u64 msr_content = 0;
-    struct vcpu *v = current;
-    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
-
-    switch ((u32)regs->ecx)
-    {
-    case MSR_EFER:
-        msr_content = v->arch.hvm_svm.cpu_shadow_efer;
-        break;
-
-#ifdef __x86_64__
-    case MSR_FS_BASE:
-        msr_content = vmcb->fs.base;
-        goto check_long_mode;
-
-    case MSR_GS_BASE:
-        msr_content = vmcb->gs.base;
-        goto check_long_mode;
-
-    case MSR_SHADOW_GS_BASE:
-        msr_content = vmcb->kerngsbase;
-    check_long_mode:
-        if ( !svm_long_mode_enabled(v) )
-        {
-            svm_inject_exception(v, TRAP_gp_fault, 1, 0);
-            return 0;
-        }
-        break;
-#endif
-
-    case MSR_STAR:
-        msr_content = vmcb->star;
-        break;
- 
-    case MSR_LSTAR:
-        msr_content = vmcb->lstar;
-        break;
- 
-    case MSR_CSTAR:
-        msr_content = vmcb->cstar;
-        break;
- 
-    case MSR_SYSCALL_MASK:
-        msr_content = vmcb->sfmask;
-        break;
-    default:
-        return 0;
-    }
-
-    HVM_DBG_LOG(DBG_LEVEL_2, "msr_content: %"PRIx64"\n",
-                msr_content);
-
-    regs->eax = (u32)(msr_content >>  0);
-    regs->edx = (u32)(msr_content >> 32);
-    return 1;
-}
-
 static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
 {
     u64 msr_content = (u32)regs->eax | ((u64)regs->edx << 32);
@@ -242,52 +182,12 @@ static inline int long_mode_do_msr_write
 
         break;
 
-#ifdef __x86_64__
-    case MSR_FS_BASE:
-    case MSR_GS_BASE:
-    case MSR_SHADOW_GS_BASE:
-        if ( !svm_long_mode_enabled(v) )
-            goto gp_fault;
-
-        if ( !is_canonical_address(msr_content) )
-            goto uncanonical_address;
-
-        if ( ecx == MSR_FS_BASE )
-            vmcb->fs.base = msr_content;
-        else if ( ecx == MSR_GS_BASE )
-            vmcb->gs.base = msr_content;
-        else
-            vmcb->kerngsbase = msr_content;
-        break;
-#endif
- 
-    case MSR_STAR:
-        vmcb->star = msr_content;
-        break;
- 
-    case MSR_LSTAR:
-    case MSR_CSTAR:
-        if ( !is_canonical_address(msr_content) )
-            goto uncanonical_address;
-
-        if ( ecx == MSR_LSTAR )
-            vmcb->lstar = msr_content;
-        else
-            vmcb->cstar = msr_content;
-        break;
- 
-    case MSR_SYSCALL_MASK:
-        vmcb->sfmask = msr_content;
-        break;
-
     default:
         return 0;
     }
 
     return 1;
 
- uncanonical_address:
-    HVM_DBG_LOG(DBG_LEVEL_1, "Not cano address of msr write %x\n", ecx);
  gp_fault:
     svm_inject_exception(v, TRAP_gp_fault, 1, 0);
     return 0;
@@ -596,6 +496,12 @@ static int svm_realmode(struct vcpu *v)
     unsigned long eflags = v->arch.hvm_svm.vmcb->rflags;
 
     return (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE);
+}
+
+static int svm_interrupts_enabled(struct vcpu *v)
+{
+    unsigned long eflags = v->arch.hvm_svm.vmcb->rflags;
+    return !irq_masked(eflags); 
 }
 
 static int svm_guest_x86_mode(struct vcpu *v)
@@ -900,6 +806,7 @@ static struct hvm_function_table svm_fun
     .paging_enabled       = svm_paging_enabled,
     .long_mode_enabled    = svm_long_mode_enabled,
     .pae_enabled          = svm_pae_enabled,
+    .interrupts_enabled   = svm_interrupts_enabled,
     .guest_x86_mode       = svm_guest_x86_mode,
     .get_guest_ctrl_reg   = svm_get_ctrl_reg,
     .get_segment_base     = svm_get_segment_base,
@@ -2013,22 +1920,14 @@ static inline void svm_do_msr_access(
         case MSR_IA32_TIME_STAMP_COUNTER:
             msr_content = hvm_get_guest_time(v);
             break;
-        case MSR_IA32_SYSENTER_CS:
-            msr_content = vmcb->sysenter_cs;
-            break;
-        case MSR_IA32_SYSENTER_ESP: 
-            msr_content = vmcb->sysenter_esp;
-            break;
-        case MSR_IA32_SYSENTER_EIP:     
-            msr_content = vmcb->sysenter_eip;
-            break;
         case MSR_IA32_APICBASE:
             msr_content = vcpu_vlapic(v)->hw.apic_base_msr;
             break;
+        case MSR_EFER:
+            msr_content = v->arch.hvm_svm.cpu_shadow_efer;
+            break;
+
         default:
-            if (long_mode_do_msr_read(regs))
-                goto done;
-
             if ( rdmsr_hypervisor_regs(ecx, &eax, &edx) ||
                  rdmsr_safe(ecx, eax, edx) == 0 )
             {
@@ -2060,15 +1959,6 @@ static inline void svm_do_msr_access(
         case MSR_IA32_TIME_STAMP_COUNTER:
             hvm_set_guest_time(v, msr_content);
             pt_reset(v);
-            break;
-        case MSR_IA32_SYSENTER_CS:
-            vmcb->sysenter_cs = msr_content;
-            break;
-        case MSR_IA32_SYSENTER_ESP: 
-            vmcb->sysenter_esp = msr_content;
-            break;
-        case MSR_IA32_SYSENTER_EIP:     
-            vmcb->sysenter_eip = msr_content;
             break;
         case MSR_IA32_APICBASE:
             vlapic_msr_set(vcpu_vlapic(v), msr_content);
@@ -2276,7 +2166,7 @@ asmlinkage void svm_vmexit_handler(struc
     unsigned long eip;
     struct vcpu *v = current;
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
-    int inst_len;
+    int inst_len, rc;
 
     exit_reason = vmcb->exitcode;
     save_svm_cpu_user_regs(v, regs);
@@ -2385,8 +2275,13 @@ asmlinkage void svm_vmexit_handler(struc
         inst_len = __get_instruction_length(v, INSTR_VMCALL, NULL);
         ASSERT(inst_len > 0);
         HVMTRACE_1D(VMMCALL, v, regs->eax);
-        __update_guest_eip(vmcb, inst_len);
-        hvm_do_hypercall(regs);
+        rc = hvm_do_hypercall(regs);
+        if ( rc != HVM_HCALL_preempted )
+        {
+            __update_guest_eip(vmcb, inst_len);
+            if ( rc == HVM_HCALL_invalidate )
+                send_invalidate_req();
+        }
         break;
 
     case VMEXIT_CR0_READ:
diff -r 9ec7dadc98ba -r eb3e430242ac xen/arch/x86/hvm/svm/vmcb.c
--- a/xen/arch/x86/hvm/svm/vmcb.c       Fri Apr 06 10:06:30 2007 -0600
+++ b/xen/arch/x86/hvm/svm/vmcb.c       Fri Apr 06 10:08:30 2007 -0600
@@ -141,6 +141,14 @@ static int construct_vmcb(struct vcpu *v
 
     disable_intercept_for_msr((char *)arch_svm->msrpm, MSR_FS_BASE);
     disable_intercept_for_msr((char *)arch_svm->msrpm, MSR_GS_BASE);
+    disable_intercept_for_msr((char *)arch_svm->msrpm, MSR_SHADOW_GS_BASE);
+    disable_intercept_for_msr((char *)arch_svm->msrpm, MSR_CSTAR);
+    disable_intercept_for_msr((char *)arch_svm->msrpm, MSR_LSTAR);
+    disable_intercept_for_msr((char *)arch_svm->msrpm, MSR_STAR);
+    disable_intercept_for_msr((char *)arch_svm->msrpm, MSR_SYSCALL_MASK);
+    disable_intercept_for_msr((char *)arch_svm->msrpm, MSR_IA32_SYSENTER_CS);
+    disable_intercept_for_msr((char *)arch_svm->msrpm, MSR_IA32_SYSENTER_ESP);
+    disable_intercept_for_msr((char *)arch_svm->msrpm, MSR_IA32_SYSENTER_EIP);
 
     vmcb->msrpm_base_pa = (u64)virt_to_maddr(arch_svm->msrpm);
     vmcb->iopm_base_pa  = (u64)virt_to_maddr(hvm_io_bitmap);
diff -r 9ec7dadc98ba -r eb3e430242ac xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Fri Apr 06 10:06:30 2007 -0600
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Fri Apr 06 10:08:30 2007 -0600
@@ -957,6 +957,13 @@ static int vmx_pae_enabled(struct vcpu *
     return (vmx_paging_enabled(v) && (cr4 & X86_CR4_PAE));
 }
 
+static int vmx_interrupts_enabled(struct vcpu *v) 
+{
+    unsigned long eflags = __vmread(GUEST_RFLAGS); 
+    return !irq_masked(eflags); 
+}
+
+
 static void vmx_update_host_cr3(struct vcpu *v)
 {
     ASSERT( (v == current) || !vcpu_runnable(v) );
@@ -1030,6 +1037,7 @@ static struct hvm_function_table vmx_fun
     .paging_enabled       = vmx_paging_enabled,
     .long_mode_enabled    = vmx_long_mode_enabled,
     .pae_enabled          = vmx_pae_enabled,
+    .interrupts_enabled   = vmx_interrupts_enabled,
     .guest_x86_mode       = vmx_guest_x86_mode,
     .get_guest_ctrl_reg   = vmx_get_ctrl_reg,
     .get_segment_base     = vmx_get_segment_base,
@@ -2618,10 +2626,16 @@ asmlinkage void vmx_vmexit_handler(struc
     }
     case EXIT_REASON_VMCALL:
     {
+        int rc;
         HVMTRACE_1D(VMMCALL, v, regs->eax);
         inst_len = __get_instruction_length(); /* Safe: VMCALL */
-        __update_guest_eip(inst_len);
-        hvm_do_hypercall(regs);
+        rc = hvm_do_hypercall(regs);
+        if ( rc != HVM_HCALL_preempted )
+        {
+            __update_guest_eip(inst_len);
+            if ( rc == HVM_HCALL_invalidate )
+                send_invalidate_req();
+        }
         break;
     }
     case EXIT_REASON_CR_ACCESS:
diff -r 9ec7dadc98ba -r eb3e430242ac xen/common/domain.c
--- a/xen/common/domain.c       Fri Apr 06 10:06:30 2007 -0600
+++ b/xen/common/domain.c       Fri Apr 06 10:08:30 2007 -0600
@@ -307,7 +307,7 @@ void domain_kill(struct domain *d)
     domain_pause(d);
 
     /* Already dying? Then bail. */
-    if ( xchg(&d->is_dying, 1) )
+    if ( test_and_set_bool(d->is_dying) )
     {
         domain_unpause(d);
         return;
@@ -453,7 +453,7 @@ void domain_pause_for_debugger(void)
     struct vcpu *v;
 
     atomic_inc(&d->pause_count);
-    if ( xchg(&d->is_paused_by_controller, 1) )
+    if ( test_and_set_bool(d->is_paused_by_controller) )
         domain_unpause(d); /* race-free atomic_dec(&d->pause_count) */
 
     for_each_vcpu ( d, v )
@@ -553,13 +553,13 @@ void domain_pause_by_systemcontroller(st
 void domain_pause_by_systemcontroller(struct domain *d)
 {
     domain_pause(d);
-    if ( xchg(&d->is_paused_by_controller, 1) )
+    if ( test_and_set_bool(d->is_paused_by_controller) )
         domain_unpause(d);
 }
 
 void domain_unpause_by_systemcontroller(struct domain *d)
 {
-    if ( xchg(&d->is_paused_by_controller, 0) )
+    if ( test_and_clear_bool(d->is_paused_by_controller) )
         domain_unpause(d);
 }
 
diff -r 9ec7dadc98ba -r eb3e430242ac xen/common/memory.c
--- a/xen/common/memory.c       Fri Apr 06 10:06:30 2007 -0600
+++ b/xen/common/memory.c       Fri Apr 06 10:08:30 2007 -0600
@@ -173,17 +173,6 @@ int guest_remove_page(struct domain *d, 
     if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
         put_page(page);
 
-    if ( unlikely((page->count_info & PGC_count_mask) != 1) )
-    {
-        shadow_drop_references(d, page);
-        /* We'll make this a guest-visible error in future, so take heed! */
-        if ( (page->count_info & PGC_count_mask) != 1 )
-            gdprintk(XENLOG_INFO, "Dom%d freeing in-use page %lx "
-                     "(pseudophys %lx): count=%lx type=%lx\n",
-                     d->domain_id, mfn, get_gpfn_from_mfn(mfn),
-                     (unsigned long)page->count_info, page->u.inuse.type_info);
-    }
-
     guest_physmap_remove_page(d, gmfn, mfn);
 
     put_page(page);
diff -r 9ec7dadc98ba -r eb3e430242ac xen/common/schedule.c
--- a/xen/common/schedule.c     Fri Apr 06 10:06:30 2007 -0600
+++ b/xen/common/schedule.c     Fri Apr 06 10:08:30 2007 -0600
@@ -461,7 +461,11 @@ ret_t do_sched_op(int cmd, XEN_GUEST_HAN
         if ( d == NULL )
             break;
 
+        /* domain_pause() prevens any further execution in guest context. */
+        domain_pause(d);
         domain_shutdown(d, (u8)sched_remote_shutdown.reason);
+        domain_unpause(d);
+
         rcu_unlock_domain(d);
         ret = 0;
 
diff -r 9ec7dadc98ba -r eb3e430242ac xen/drivers/char/ns16550.c
--- a/xen/drivers/char/ns16550.c        Fri Apr 06 10:06:30 2007 -0600
+++ b/xen/drivers/char/ns16550.c        Fri Apr 06 10:08:30 2007 -0600
@@ -239,7 +239,7 @@ static void ns16550_init_postirq(struct 
         uart->irqaction.name    = "ns16550";
         uart->irqaction.dev_id  = port;
         if ( (rc = setup_irq(uart->irq, &uart->irqaction)) != 0 )
-            printk("ERROR: Failed to allocate na16550 IRQ %d\n", uart->irq);
+            printk("ERROR: Failed to allocate ns16550 IRQ %d\n", uart->irq);
 
         /* Master interrupt enable; also keep DTR/RTS asserted. */
         ns_write_reg(uart, MCR, MCR_OUT2 | MCR_DTR | MCR_RTS);
diff -r 9ec7dadc98ba -r eb3e430242ac xen/include/asm-ia64/xentypes.h
--- a/xen/include/asm-ia64/xentypes.h   Fri Apr 06 10:06:30 2007 -0600
+++ b/xen/include/asm-ia64/xentypes.h   Fri Apr 06 10:08:30 2007 -0600
@@ -5,6 +5,11 @@ typedef unsigned long ssize_t;
 typedef unsigned long ssize_t;
 typedef unsigned long size_t;
 typedef long long loff_t;
+
+typedef char bool_t;
+#define test_and_set_bool(b)   xchg(&(b), 1)
+#define test_and_clear_bool(b) xchg(&(b), 0)
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* _ASM_IA64_XENTYPES_H */
diff -r 9ec7dadc98ba -r eb3e430242ac xen/include/asm-powerpc/types.h
--- a/xen/include/asm-powerpc/types.h   Fri Apr 06 10:06:30 2007 -0600
+++ b/xen/include/asm-powerpc/types.h   Fri Apr 06 10:08:30 2007 -0600
@@ -70,5 +70,9 @@ typedef u64 dma64_addr_t;
 
 typedef unsigned short xmem_bufctl_t;
 
+typedef int bool_t;
+#define test_and_set_bool(b)   xchg(&(b), 1)
+#define test_and_clear_bool(b) xchg(&(b), 0)
+
 #endif  /* __ASSEMBLY__ */
 #endif
diff -r 9ec7dadc98ba -r eb3e430242ac xen/include/asm-x86/event.h
--- a/xen/include/asm-x86/event.h       Fri Apr 06 10:06:30 2007 -0600
+++ b/xen/include/asm-x86/event.h       Fri Apr 06 10:08:30 2007 -0600
@@ -35,12 +35,13 @@ static inline void vcpu_mark_events_pend
         vcpu_kick(v);
 }
 
+int hvm_local_events_need_delivery(struct vcpu *v);
 static inline int local_events_need_delivery(void)
 {
     struct vcpu *v = current;
-    return ((vcpu_info(v, evtchn_upcall_pending) &&
-             !vcpu_info(v, evtchn_upcall_mask)) ||
-            (is_hvm_vcpu(v) && cpu_has_pending_irq(v)));
+    return (is_hvm_vcpu(v) ? hvm_local_events_need_delivery(v) :
+            (vcpu_info(v, evtchn_upcall_pending) &&
+             !vcpu_info(v, evtchn_upcall_mask)));
 }
 
 static inline int local_event_delivery_is_enabled(void)
diff -r 9ec7dadc98ba -r eb3e430242ac xen/include/asm-x86/hvm/hvm.h
--- a/xen/include/asm-x86/hvm/hvm.h     Fri Apr 06 10:06:30 2007 -0600
+++ b/xen/include/asm-x86/hvm/hvm.h     Fri Apr 06 10:08:30 2007 -0600
@@ -93,13 +93,15 @@ struct hvm_function_table {
      * 1) determine whether paging is enabled,
      * 2) determine whether long mode is enabled,
      * 3) determine whether PAE paging is enabled,
-     * 4) determine the mode the guest is running in,
-     * 5) return the current guest control-register value
-     * 6) return the current guest segment descriptor base
+     * 4) determine whether interrupts are enabled or not,
+     * 5) determine the mode the guest is running in,
+     * 6) return the current guest control-register value
+     * 7) return the current guest segment descriptor base
      */
     int (*paging_enabled)(struct vcpu *v);
     int (*long_mode_enabled)(struct vcpu *v);
     int (*pae_enabled)(struct vcpu *v);
+    int (*interrupts_enabled)(struct vcpu *v);
     int (*guest_x86_mode)(struct vcpu *v);
     unsigned long (*get_guest_ctrl_reg)(struct vcpu *v, unsigned int num);
     unsigned long (*get_segment_base)(struct vcpu *v, enum x86_segment seg);
@@ -190,6 +192,12 @@ hvm_pae_enabled(struct vcpu *v)
 }
 
 static inline int
+hvm_interrupts_enabled(struct vcpu *v)
+{
+    return hvm_funcs.interrupts_enabled(v);
+}
+
+static inline int
 hvm_guest_x86_mode(struct vcpu *v)
 {
     return hvm_funcs.guest_x86_mode(v);
diff -r 9ec7dadc98ba -r eb3e430242ac xen/include/asm-x86/hvm/io.h
--- a/xen/include/asm-x86/hvm/io.h      Fri Apr 06 10:06:30 2007 -0600
+++ b/xen/include/asm-x86/hvm/io.h      Fri Apr 06 10:08:30 2007 -0600
@@ -147,9 +147,10 @@ extern void send_pio_req(unsigned long p
 extern void send_pio_req(unsigned long port, unsigned long count, int size,
                          paddr_t value, int dir, int df, int value_is_ptr);
 void send_timeoffset_req(unsigned long timeoff);
+void send_invalidate_req(void);
 extern void handle_mmio(unsigned long gpa);
 extern void hvm_interrupt_post(struct vcpu *v, int vector, int type);
-extern void hvm_io_assist(struct vcpu *v);
+extern void hvm_io_assist(void);
 
 #endif /* __ASM_X86_HVM_IO_H__ */
 
diff -r 9ec7dadc98ba -r eb3e430242ac xen/include/asm-x86/hvm/support.h
--- a/xen/include/asm-x86/hvm/support.h Fri Apr 06 10:06:30 2007 -0600
+++ b/xen/include/asm-x86/hvm/support.h Fri Apr 06 10:08:30 2007 -0600
@@ -228,7 +228,10 @@ void hvm_print_line(struct vcpu *v, cons
 void hvm_print_line(struct vcpu *v, const char c);
 void hlt_timer_fn(void *data);
 
-void hvm_do_hypercall(struct cpu_user_regs *pregs);
+#define HVM_HCALL_completed  0 /* hypercall completed - no further action */
+#define HVM_HCALL_preempted  1 /* hypercall preempted - re-execute VMCALL */
+#define HVM_HCALL_invalidate 2 /* invalidate ioemu-dm memory cache        */
+int hvm_do_hypercall(struct cpu_user_regs *pregs);
 
 void hvm_hlt(unsigned long rflags);
 void hvm_triple_fault(void);
diff -r 9ec7dadc98ba -r eb3e430242ac xen/include/asm-x86/types.h
--- a/xen/include/asm-x86/types.h       Fri Apr 06 10:06:30 2007 -0600
+++ b/xen/include/asm-x86/types.h       Fri Apr 06 10:08:30 2007 -0600
@@ -52,6 +52,10 @@ typedef unsigned long paddr_t;
 
 typedef unsigned long size_t;
 
+typedef char bool_t;
+#define test_and_set_bool(b)   xchg(&(b), 1)
+#define test_and_clear_bool(b) xchg(&(b), 0)
+
 #endif /* __ASSEMBLY__ */
 
 #if defined(__i386__)
diff -r 9ec7dadc98ba -r eb3e430242ac xen/include/public/acm.h
--- a/xen/include/public/acm.h  Fri Apr 06 10:06:30 2007 -0600
+++ b/xen/include/public/acm.h  Fri Apr 06 10:08:30 2007 -0600
@@ -124,7 +124,7 @@ struct acm_policy_version
 {
     uint32_t major;
     uint32_t minor;
-} __attribute__((packed));
+};
 
 
 /* each buffer consists of all policy information for
@@ -145,12 +145,12 @@ struct acm_policy_buffer {
     uint32_t secondary_policy_code;
     uint32_t secondary_buffer_offset;
     struct acm_policy_version xml_pol_version; /* add in V3 */
-} __attribute__((packed));
+};
 
 
 struct acm_policy_reference_buffer {
     uint32_t len;
-} __attribute__((packed));
+};
 
 struct acm_chwall_policy_buffer {
     uint32_t policy_version; /* ACM_CHWALL_VERSION */
@@ -162,7 +162,7 @@ struct acm_chwall_policy_buffer {
     uint32_t chwall_conflict_sets_offset;
     uint32_t chwall_running_types_offset;
     uint32_t chwall_conflict_aggregate_offset;
-} __attribute__((packed));
+};
 
 struct acm_ste_policy_buffer {
     uint32_t policy_version; /* ACM_STE_VERSION */
@@ -170,7 +170,7 @@ struct acm_ste_policy_buffer {
     uint32_t ste_max_types;
     uint32_t ste_max_ssidrefs;
     uint32_t ste_ssid_offset;
-} __attribute__((packed));
+};
 
 struct acm_stats_buffer {
     uint32_t magic;
@@ -179,7 +179,7 @@ struct acm_stats_buffer {
     uint32_t primary_stats_offset;
     uint32_t secondary_policy_code;
     uint32_t secondary_stats_offset;
-} __attribute__((packed));
+};
 
 struct acm_ste_stats_buffer {
     uint32_t ec_eval_count;
@@ -188,7 +188,7 @@ struct acm_ste_stats_buffer {
     uint32_t gt_denied_count;
     uint32_t ec_cachehit_count;
     uint32_t gt_cachehit_count;
-} __attribute__((packed));
+};
 
 struct acm_ssid_buffer {
     uint32_t len;
@@ -200,7 +200,7 @@ struct acm_ssid_buffer {
     uint32_t secondary_policy_code;
     uint32_t secondary_max_types;
     uint32_t secondary_types_offset;
-} __attribute__((packed));
+};
 
 #endif
 
diff -r 9ec7dadc98ba -r eb3e430242ac xen/include/public/foreign/Makefile
--- a/xen/include/public/foreign/Makefile       Fri Apr 06 10:06:30 2007 -0600
+++ b/xen/include/public/foreign/Makefile       Fri Apr 06 10:08:30 2007 -0600
@@ -13,7 +13,7 @@ clean:
        rm -f checker checker.c $(XEN_TARGET_ARCH).size
        rm -f *.pyc *.o *~
 
-ifeq ($(CROSS_COMPILE),)
+ifeq ($(CROSS_COMPILE)$(XEN_TARGET_ARCH),$(XEN_COMPILE_ARCH))
 check-headers: checker
        ./checker > $(XEN_TARGET_ARCH).size
        diff -u reference.size $(XEN_TARGET_ARCH).size
diff -r 9ec7dadc98ba -r eb3e430242ac xen/include/public/hvm/hvm_op.h
--- a/xen/include/public/hvm/hvm_op.h   Fri Apr 06 10:06:30 2007 -0600
+++ b/xen/include/public/hvm/hvm_op.h   Fri Apr 06 10:08:30 2007 -0600
@@ -70,12 +70,4 @@ typedef struct xen_hvm_set_pci_link_rout
 typedef struct xen_hvm_set_pci_link_route xen_hvm_set_pci_link_route_t;
 DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_pci_link_route_t);
 
-/* Drain all outstanding qemu-dm IO responses from a domain's ioreq ring. */
-#define HVMOP_drain_io            5
-struct xen_hvm_drain_io {
-    domid_t  domid;
-};
-typedef struct xen_hvm_drain_io xen_hvm_drain_io_t;
-DEFINE_XEN_GUEST_HANDLE(xen_hvm_drain_io_t);
-
 #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
diff -r 9ec7dadc98ba -r eb3e430242ac xen/include/public/hvm/ioreq.h
--- a/xen/include/public/hvm/ioreq.h    Fri Apr 06 10:06:30 2007 -0600
+++ b/xen/include/public/hvm/ioreq.h    Fri Apr 06 10:08:30 2007 -0600
@@ -40,6 +40,7 @@
 #define IOREQ_TYPE_XCHG         5
 #define IOREQ_TYPE_ADD          6
 #define IOREQ_TYPE_TIMEOFFSET   7
+#define IOREQ_TYPE_INVALIDATE   8 /* mapcache */
 
 /*
  * VMExit dispatcher should cooperate with instruction decoder to
diff -r 9ec7dadc98ba -r eb3e430242ac xen/include/xen/types.h
--- a/xen/include/xen/types.h   Fri Apr 06 10:06:30 2007 -0600
+++ b/xen/include/xen/types.h   Fri Apr 06 10:08:30 2007 -0600
@@ -19,8 +19,6 @@
 #define LONG_MAX        ((long)(~0UL>>1))
 #define LONG_MIN        (-LONG_MAX - 1)
 #define ULONG_MAX       (~0UL)
-
-typedef char bool_t;
 
 /* bsd */
 typedef unsigned char           u_char;

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