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

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



# HG changeset patch
# User awilliam@xxxxxxxxxxxx
# Date 1173715628 21600
# Node ID cb2575cec95c9960c30133725943a0da81daa2f5
# Parent  d1853a39e063ea82f8900fa91208258492845f6a
# Parent  8a01644306ee024eb49a195a50662d04021aefa1
merge with xen-unstable.hg
---
 xen/arch/x86/mm/shadow/page-guest32.h                            |  100 -
 buildconfigs/linux-defconfig_xen0_ia64                           |    2 
 buildconfigs/linux-defconfig_xen0_x86_32                         |    2 
 buildconfigs/linux-defconfig_xen0_x86_64                         |    2 
 buildconfigs/linux-defconfig_xenU_ia64                           |    2 
 buildconfigs/linux-defconfig_xenU_x86_32                         |    2 
 buildconfigs/linux-defconfig_xenU_x86_64                         |    2 
 buildconfigs/linux-defconfig_xen_ia64                            |    2 
 buildconfigs/linux-defconfig_xen_x86_32                          |    2 
 buildconfigs/linux-defconfig_xen_x86_64                          |    2 
 docs/man/xm.pod.1                                                |    2 
 docs/misc/dump-core-format.txt                                   |    8 
 docs/xen-api/coversheet.tex                                      |    2 
 docs/xen-api/presentation.tex                                    |   16 
 docs/xen-api/vm-lifecycle.tex                                    |   16 
 docs/xen-api/wire-protocol.tex                                   |   50 
 docs/xen-api/xenapi-datamodel.tex                                |  744 
++++------
 docs/xen-api/xenapi.tex                                          |    3 
 linux-2.6-xen-sparse/arch/i386/kernel/cpu/mtrr/main-xen.c        |   24 
 linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c              |    4 
 linux-2.6-xen-sparse/arch/i386/kernel/ioport-xen.c               |    2 
 linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c            |    6 
 linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c              |    6 
 linux-2.6-xen-sparse/arch/i386/kernel/quirks-xen.c               |    6 
 linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c                 |   39 
 linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c                   |    4 
 linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c                  |    2 
 linux-2.6-xen-sparse/arch/ia64/xen/xcom_hcall.c                  |    2 
 linux-2.6-xen-sparse/arch/ia64/xen/xcom_mini.c                   |    2 
 linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c                |   24 
 linux-2.6-xen-sparse/arch/x86_64/kernel/ioport-xen.c             |    2 
 linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c            |    8 
 linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c                 |    2 
 linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.h                 |   13 
 linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c                  |   28 
 linux-2.6-xen-sparse/drivers/xen/Kconfig                         |    9 
 linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c           |    1 
 linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c            |   13 
 linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.c     |    6 
 linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.h     |    2 
 linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c              |   12 
 linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c               |    1 
 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h   |   10 
 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h  |    2 
 linux-2.6-xen-sparse/include/asm-ia64/hypercall.h                |    6 
 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 |   10 
 patches/linux-2.6.18/softlockup-no-idle-hz.patch                 |    1 
 tools/ioemu/hw/ide.c                                             |  176 ++
 tools/ioemu/target-i386-dm/helper2.c                             |   21 
 tools/ioemu/vl.h                                                 |    1 
 tools/libxc/xc_core_ia64.c                                       |   24 
 tools/libxc/xc_dom_x86.c                                         |   30 
 tools/libxc/xc_hvm_restore.c                                     |   73 
 tools/libxc/xc_hvm_save.c                                        |  149 +-
 tools/libxc/xc_misc.c                                            |   19 
 tools/libxc/xc_private.c                                         |    2 
 tools/libxc/xc_ptrace_core.c                                     |    1 
 tools/libxc/xenctrl.h                                            |    8 
 tools/libxc/xenguest.h                                           |    3 
 tools/libxc/xg_private.c                                         |    5 
 tools/libxen/include/xen_crashdump.h                             |   23 
 tools/libxen/include/xen_vbd.h                                   |   16 
 tools/libxen/include/xen_vdi.h                                   |    7 
 tools/libxen/include/xen_vif.h                                   |   16 
 tools/libxen/include/xen_vm.h                                    |  133 -
 tools/libxen/src/xen_common.c                                    |   21 
 tools/libxen/src/xen_crashdump.c                                 |   47 
 tools/libxen/src/xen_vbd.c                                       |   28 
 tools/libxen/src/xen_vdi.c                                       |   16 
 tools/libxen/src/xen_vif.c                                       |   28 
 tools/libxen/src/xen_vm.c                                        |  244 +--
 tools/libxen/test/test_bindings.c                                |    2 
 tools/python/xen/lowlevel/xc/xc.c                                |   26 
 tools/python/xen/xend/XendAPI.py                                 |  163 --
 tools/python/xen/xend/XendCheckpoint.py                          |    7 
 tools/python/xen/xend/XendConfig.py                              |  276 +--
 tools/python/xen/xend/XendDomain.py                              |    2 
 tools/python/xen/xend/XendDomainInfo.py                          |   78 -
 tools/python/xen/xend/XendError.py                               |    7 
 tools/python/xen/xend/XendNode.py                                |    9 
 tools/python/xen/xend/image.py                                   |   59 
 tools/python/xen/xend/server/XMLRPCServer.py                     |    2 
 tools/python/xen/xm/XenAPI.py                                    |    2 
 tools/python/xen/xm/main.py                                      |   21 
 tools/python/xen/xm/messages/en/xen-xm.po                        |    5 
 tools/xm-test/tests/vtpm/09_vtpm-xapi.py                         |    9 
 xen/arch/ia64/xen/xensetup.c                                     |    2 
 xen/arch/powerpc/domain.c                                        |    2 
 xen/arch/powerpc/setup.c                                         |    3 
 xen/arch/x86/apic.c                                              |   14 
 xen/arch/x86/domain.c                                            |    9 
 xen/arch/x86/domctl.c                                            |   10 
 xen/arch/x86/hvm/hvm.c                                           |   64 
 xen/arch/x86/hvm/rtc.c                                           |   17 
 xen/arch/x86/hvm/svm/svm.c                                       |  220 ++
 xen/arch/x86/hvm/svm/vmcb.c                                      |   15 
 xen/arch/x86/mm/Makefile                                         |    1 
 xen/arch/x86/mm/hap/Makefile                                     |    2 
 xen/arch/x86/mm/hap/hap.c                                        |  708 
+++++++++
 xen/arch/x86/mm/hap/private.h                                    |  112 +
 xen/arch/x86/mm/hap/support.c                                    |  334 ++++
 xen/arch/x86/mm/page-guest32.h                                   |  100 +
 xen/arch/x86/mm/paging.c                                         |   34 
 xen/arch/x86/mm/shadow/common.c                                  |   17 
 xen/arch/x86/mm/shadow/types.h                                   |    2 
 xen/arch/x86/setup.c                                             |    8 
 xen/common/compat/domain.c                                       |    4 
 xen/common/domain.c                                              |   74 
 xen/common/event_channel.c                                       |    3 
 xen/common/keyhandler.c                                          |   34 
 xen/common/page_alloc.c                                          |  138 -
 xen/common/sched_credit.c                                        |   40 
 xen/common/schedule.c                                            |  139 +
 xen/common/sysctl.c                                              |   15 
 xen/common/xmalloc.c                                             |    6 
 xen/drivers/char/console.c                                       |    2 
 xen/include/asm-x86/domain.h                                     |   16 
 xen/include/asm-x86/hap.h                                        |  122 +
 xen/include/asm-x86/hvm/svm/vmcb.h                               |    1 
 xen/include/asm-x86/hvm/vpt.h                                    |    1 
 xen/include/asm-x86/paging.h                                     |    2 
 xen/include/public/hvm/hvm_op.h                                  |    8 
 xen/include/public/sysctl.h                                      |   13 
 xen/include/public/vcpu.h                                        |   42 
 xen/include/public/xen.h                                         |    1 
 xen/include/xen/mm.h                                             |    5 
 xen/include/xen/sched-if.h                                       |    2 
 xen/include/xen/sched.h                                          |    8 
 xen/include/xen/timer.h                                          |    4 
 130 files changed, 3527 insertions(+), 1794 deletions(-)

diff -r d1853a39e063 -r cb2575cec95c buildconfigs/linux-defconfig_xen0_ia64
--- a/buildconfigs/linux-defconfig_xen0_ia64    Mon Mar 12 09:43:48 2007 -0600
+++ b/buildconfigs/linux-defconfig_xen0_ia64    Mon Mar 12 10:07:08 2007 -0600
@@ -1619,7 +1619,7 @@ CONFIG_XEN_BALLOON=y
 CONFIG_XEN_BALLOON=y
 CONFIG_XEN_REBOOT=y
 # CONFIG_XEN_SMPBOOT is not set
-CONFIG_XEN_INTERFACE_VERSION=0x00030203
+CONFIG_XEN_INTERFACE_VERSION=0x00030205
 
 #
 # XEN
diff -r d1853a39e063 -r cb2575cec95c buildconfigs/linux-defconfig_xen0_x86_32
--- a/buildconfigs/linux-defconfig_xen0_x86_32  Mon Mar 12 09:43:48 2007 -0600
+++ b/buildconfigs/linux-defconfig_xen0_x86_32  Mon Mar 12 10:07:08 2007 -0600
@@ -1384,7 +1384,7 @@ CONFIG_CRYPTO_CRC32C=m
 #
 # CONFIG_CRYPTO_DEV_PADLOCK is not set
 CONFIG_XEN=y
-CONFIG_XEN_INTERFACE_VERSION=0x00030203
+CONFIG_XEN_INTERFACE_VERSION=0x00030205
 
 #
 # XEN
diff -r d1853a39e063 -r cb2575cec95c buildconfigs/linux-defconfig_xen0_x86_64
--- a/buildconfigs/linux-defconfig_xen0_x86_64  Mon Mar 12 09:43:48 2007 -0600
+++ b/buildconfigs/linux-defconfig_xen0_x86_64  Mon Mar 12 10:07:08 2007 -0600
@@ -1334,7 +1334,7 @@ CONFIG_CRYPTO_CRC32C=m
 # Hardware crypto devices
 #
 CONFIG_XEN=y
-CONFIG_XEN_INTERFACE_VERSION=0x00030203
+CONFIG_XEN_INTERFACE_VERSION=0x00030205
 
 #
 # XEN
diff -r d1853a39e063 -r cb2575cec95c buildconfigs/linux-defconfig_xenU_ia64
--- a/buildconfigs/linux-defconfig_xenU_ia64    Mon Mar 12 09:43:48 2007 -0600
+++ b/buildconfigs/linux-defconfig_xenU_ia64    Mon Mar 12 10:07:08 2007 -0600
@@ -1471,7 +1471,7 @@ CONFIG_XEN_BALLOON=y
 CONFIG_XEN_BALLOON=y
 CONFIG_XEN_REBOOT=y
 # CONFIG_XEN_SMPBOOT is not set
-CONFIG_XEN_INTERFACE_VERSION=0x00030203
+CONFIG_XEN_INTERFACE_VERSION=0x00030205
 
 #
 # XEN
diff -r d1853a39e063 -r cb2575cec95c buildconfigs/linux-defconfig_xenU_x86_32
--- a/buildconfigs/linux-defconfig_xenU_x86_32  Mon Mar 12 09:43:48 2007 -0600
+++ b/buildconfigs/linux-defconfig_xenU_x86_32  Mon Mar 12 10:07:08 2007 -0600
@@ -904,7 +904,7 @@ CONFIG_CRYPTO_CRC32C=m
 #
 # CONFIG_CRYPTO_DEV_PADLOCK is not set
 CONFIG_XEN=y
-CONFIG_XEN_INTERFACE_VERSION=0x00030203
+CONFIG_XEN_INTERFACE_VERSION=0x00030205
 
 #
 # XEN
diff -r d1853a39e063 -r cb2575cec95c buildconfigs/linux-defconfig_xenU_x86_64
--- a/buildconfigs/linux-defconfig_xenU_x86_64  Mon Mar 12 09:43:48 2007 -0600
+++ b/buildconfigs/linux-defconfig_xenU_x86_64  Mon Mar 12 10:07:08 2007 -0600
@@ -1200,7 +1200,7 @@ CONFIG_CRYPTO_CRC32C=m
 # Hardware crypto devices
 #
 CONFIG_XEN=y
-CONFIG_XEN_INTERFACE_VERSION=0x00030203
+CONFIG_XEN_INTERFACE_VERSION=0x00030205
 
 #
 # XEN
diff -r d1853a39e063 -r cb2575cec95c buildconfigs/linux-defconfig_xen_ia64
--- a/buildconfigs/linux-defconfig_xen_ia64     Mon Mar 12 09:43:48 2007 -0600
+++ b/buildconfigs/linux-defconfig_xen_ia64     Mon Mar 12 10:07:08 2007 -0600
@@ -1619,7 +1619,7 @@ CONFIG_XEN_BALLOON=y
 CONFIG_XEN_BALLOON=y
 CONFIG_XEN_REBOOT=y
 # CONFIG_XEN_SMPBOOT is not set
-CONFIG_XEN_INTERFACE_VERSION=0x00030203
+CONFIG_XEN_INTERFACE_VERSION=0x00030205
 
 #
 # XEN
diff -r d1853a39e063 -r cb2575cec95c buildconfigs/linux-defconfig_xen_x86_32
--- a/buildconfigs/linux-defconfig_xen_x86_32   Mon Mar 12 09:43:48 2007 -0600
+++ b/buildconfigs/linux-defconfig_xen_x86_32   Mon Mar 12 10:07:08 2007 -0600
@@ -3242,7 +3242,7 @@ CONFIG_CRYPTO_TEST=m
 #
 # CONFIG_CRYPTO_DEV_PADLOCK is not set
 CONFIG_XEN=y
-CONFIG_XEN_INTERFACE_VERSION=0x00030203
+CONFIG_XEN_INTERFACE_VERSION=0x00030205
 
 #
 # XEN
diff -r d1853a39e063 -r cb2575cec95c buildconfigs/linux-defconfig_xen_x86_64
--- a/buildconfigs/linux-defconfig_xen_x86_64   Mon Mar 12 09:43:48 2007 -0600
+++ b/buildconfigs/linux-defconfig_xen_x86_64   Mon Mar 12 10:07:08 2007 -0600
@@ -3072,7 +3072,7 @@ CONFIG_CRYPTO_TEST=m
 # Hardware crypto devices
 #
 CONFIG_XEN=y
-CONFIG_XEN_INTERFACE_VERSION=0x00030203
+CONFIG_XEN_INTERFACE_VERSION=0x00030205
 
 #
 # XEN
diff -r d1853a39e063 -r cb2575cec95c docs/man/xm.pod.1
--- a/docs/man/xm.pod.1 Mon Mar 12 09:43:48 2007 -0600
+++ b/docs/man/xm.pod.1 Mon Mar 12 10:07:08 2007 -0600
@@ -619,7 +619,7 @@ devices, or by device id, such as 0x1400
 =item I<mode>
 
 The access mode for the device from the guest domain.  Supported modes
-are I<rw> (read/write) or I<ro> (read-only).
+are I<w> (read/write) or I<r> (read-only).
 
 =item I<bedomain-id>
 
diff -r d1853a39e063 -r cb2575cec95c docs/misc/dump-core-format.txt
--- a/docs/misc/dump-core-format.txt    Mon Mar 12 09:43:48 2007 -0600
+++ b/docs/misc/dump-core-format.txt    Mon Mar 12 10:07:08 2007 -0600
@@ -80,8 +80,7 @@ Currently the following sections are def
                         gmfn:   machine physical frame number
                 The size of arrays is stored in xch_nr_pages member of header
                 note descriptor in .note.Xen note section.
-                There is no rule about the order. Analysis tools must no rely
-                on its order.
+                The entryies are stored in pfn-ascending order.
                 This section must exist when the domain is non auto
                 translated physmap mode. Currently x86 paravirtualized domain.
 
@@ -94,8 +93,7 @@ Currently the following sections are def
                 in .xen_pages section.
                 The size of arrays is stored in xch_nr_pages member of header
                 note descriptor in .note.Xen note section.
-                There is no rule about the order. Analysis tools must no rely
-                on its order.
+                The entries are stored in ascending order.
                 This section must exist when the domain is auto translated
                 physmap mode. Currently x86 full virtualized domain and
                 ia64 domain.
@@ -226,6 +224,8 @@ Currently only (major, minor) = (0, 1) i
 [When the format is changed, it would be described here.]
 
 (0, 1) update
+- .xen_p2m, .xen_pfn section
+  Arrays must be in pfn ascending order for efficient looking up.
 - EI_CLASS member of elf header was changed to ELFCLASS64 independent of
   architecture. This is mainly for x86_32pae.
   The format version isn't bumped because analysis tools can distinguish it.
diff -r d1853a39e063 -r cb2575cec95c docs/xen-api/coversheet.tex
--- a/docs/xen-api/coversheet.tex       Mon Mar 12 09:43:48 2007 -0600
+++ b/docs/xen-api/coversheet.tex       Mon Mar 12 10:07:08 2007 -0600
@@ -47,4 +47,4 @@ Date: \datestring{}
 \legalnotice{}
 
 \newpage
-\pagestyle{plain}
\ No newline at end of file
+\pagestyle{fancy}
\ No newline at end of file
diff -r d1853a39e063 -r cb2575cec95c docs/xen-api/presentation.tex
--- a/docs/xen-api/presentation.tex     Mon Mar 12 09:43:48 2007 -0600
+++ b/docs/xen-api/presentation.tex     Mon Mar 12 10:07:08 2007 -0600
@@ -57,14 +57,14 @@ type $t_1$ to values of type $t_2$.
 \end{itemize}
 
 Note that there are a number of cases where {\em Ref}s are {\em doubly
-linked\/}---e.g.\ a VM has a field called {\tt groups} of type
-$(\mathit{VMGroup}~\mathit{Ref})~\mathit{Set}$; this field lists
-the VMGroups that a particular VM is part of. Similarly, the VMGroups
-class has a field called {\tt VMs} of type $(\mathit{VM}~{\mathit
-Ref})~\mathit{Set}$ that contains the VMs that are part of a particular
-VMGroup. These two fields are {\em bound together\/}, in the sense that
-adding a new VMGroup to a VM causes the VMs field of the corresponding
-VMGroup object to be updated automatically.
+linked\/}---e.g.\ a VM has a field called {\tt VIFs} of type
+$(\mathit{VIF}~\mathit{Ref})~\mathit{Set}$; this field lists
+the network interfaces attached to a particular VM. Similarly, the VIF
+class has a field called {\tt VM} of type $(\mathit{VM}~{\mathit
+Ref})$ which references the VM to which the interface is connected.
+These two fields are {\em bound together\/}, in the sense that
+creating a new VIF causes the {\tt VIFs} field of the corresponding
+VM object to be updated automatically.
 
 The API reference explicitly lists the fields that are
 bound together in this way. It also contains a diagram that shows
diff -r d1853a39e063 -r cb2575cec95c docs/xen-api/vm-lifecycle.tex
--- a/docs/xen-api/vm-lifecycle.tex     Mon Mar 12 09:43:48 2007 -0600
+++ b/docs/xen-api/vm-lifecycle.tex     Mon Mar 12 10:07:08 2007 -0600
@@ -22,3 +22,19 @@
 
 Figure~\ref{fig-vm-lifecycle} shows the states that a VM can be in
 and the API calls that can be used to move the VM between these states.
+
+\section{VM boot parameters}
+
+The VM class contains a number of fields that control the way in which the VM 
is booted.
+With reference to the fields defined in the VM class (see later in this 
document),
+this section outlines the boot options available and the mechanisms provided 
for controlling them.
+
+VM booting is controlled by setting one of the two mutually exclusive groups: 
``PV'', and ``HVM''.  If HVM.boot\_policy is the empty string, then paravirtual 
domain building and booting will be used; otherwise the VM will be loaded as an 
HVM domain, and booted using an emulated BIOS.
+
+When paravirtual booting is in use, the PV/bootloader field indicates the 
bootloader to use.  It may be ``pygrub'', in which case the platform's default 
installation of pygrub will be used, or a full path within the control domain 
to some other bootloader.  The other fields, PV/kernel, PV/ramdisk, PV/args and 
PV/bootloader\_args will be passed to the bootloader unmodified, and 
interpretation of those fields is then specific to the bootloader itself, 
including the possibility that the bootloader will ignore some or all of those 
given values. Finally the paths of all bootable disks are added to the 
bootloader commandline (a disk is bootable if its VBD has the bootable flag 
set). There may be zero, one or many bootable disks; the bootloader decides 
which disk (if any) to boot from.
+
+If the bootloader is pygrub, then the menu.lst is parsed if present in the 
guest's filesystem, otherwise the specified kernel and ramdisk are used, or an 
autodetected kernel is used if nothing is specified and autodetection is 
possible.  PV/args is appended to the kernel command line, no matter which 
mechanism is used for finding the kernel.
+
+If PV/bootloader is empty but PV/kernel is specified, then the kernel and 
ramdisk values will be treated as paths within the control domain.  If both 
PV/bootloader and PV/kernel are empty, then the behaviour is as if 
PV/bootloader was specified as ``pygrub''.
+
+When using HVM booting, HVM/boot\_policy and HVM/boot\_params specify the boot 
handling.  Only one policy is currently defined: ``BIOS order''.  In this case, 
HVM/boot\_params should contain one key-value pair ``order'' = ``N'' where N is 
the string that will be passed to QEMU.
\ No newline at end of file
diff -r d1853a39e063 -r cb2575cec95c docs/xen-api/wire-protocol.tex
--- a/docs/xen-api/wire-protocol.tex    Mon Mar 12 09:43:48 2007 -0600
+++ b/docs/xen-api/wire-protocol.tex    Mon Mar 12 10:07:08 2007 -0600
@@ -30,8 +30,13 @@ These types are mapped onto XML-RPC type
   \item Floats, Bools, DateTimes and Strings map directly to the XML-RPC {\tt
   double}, {\tt boolean}, {\tt dateTime.iso8601}, and {\tt string} elements.
 
-  \item all our ``{\tt ref\_}'' types (e.g.\ {\tt ref\_vm} in the above
-  example) map to XML-RPC's {\tt String} type.  The string itself is the OSF
+  \item all ``{\tt ref\_}'' types are opaque references, encoded as the
+  XML-RPC's {\tt String} type. Users of the API should not make assumptions
+  about the concrete form of these strings and should not expect them to
+  remain valid after the client's session with the server has terminated.
+
+  \item fields named ``{\tt uuid}'' of type ``{\tt String}'' are mapped to
+  the XML-RPC {\tt String} type. The string itself is the OSF
   DCE UUID presentation format (as output by {\tt uuidgen}, etc).
 
   \item ints are all assumed to be 64-bit in our API and are encoded as a
@@ -82,6 +87,32 @@ These types are mapped onto XML-RPC type
 
   \item our {\tt Void} type is transmitted as an empty string.
 
+\end{itemize}
+
+\subsection{Note on References vs UUIDs}
+
+References are opaque types --- encoded as XML-RPC strings on the wire --- 
understood
+only by the particular server which generated them. Servers are free to choose
+any concrete representation they find convenient; clients should not make any 
+assumptions or attempt to parse the string contents. References are not 
guaranteed
+to be permanent identifiers for objects; clients should not assume that 
references 
+generated during one session are valid for any future session. References do 
not
+allow objects to be compared for equality. Two references to the same object 
are
+not guaranteed to be textually identical.
+
+UUIDs are intended to be permanent names for objects. They are
+guaranteed to be in the OSF DCE UUID presentation format (as output by {\tt 
uuidgen}.
+Clients may store UUIDs on disk and use them to lookup objects in subsequent 
sessions
+with the server. Clients may also test equality on objects by comparing UUID 
strings.
+
+The API provides mechanisms
+for translating between UUIDs and opaque references. Each class that contains 
a UUID
+field provides:
+\begin{itemize}
+\item  A ``{\tt get\_by\_uuid}'' method that takes a UUID, $u$, and returns an 
opaque reference
+to the server-side object that has UUID=$u$; 
+\item A {\tt get\_uuid} function (a regular ``field getter'' RPC) that takes 
an opaque reference,
+$r$, and returns the UUID of the server-side object that is referenced by $r$.
 \end{itemize}
 
 \subsection{Return Values/Status Codes}
@@ -138,7 +169,7 @@ may look like this:
 
 \subsection{Transport Layer}
 
-We ought to support at least
+The following transport layers are currently supported:
 \begin{itemize}
 \item HTTP/S for remote administration
 \item HTTP over Unix domain sockets for local administration
@@ -247,13 +278,12 @@ call takes the session token as the only
 \begin{verbatim}
 >>> all_vms = host.get_resident_VMs(session)['Value']
 >>> all_vms
-['b7b92d9e-d442-4710-92a5-ab039fd7d89b', 
'23e1e837-abbf-4675-b077-d4007989b0cc',
-  '2045dbc0-0734-4eea-9cb2-b8218c6b5bf2', 
'3202ae18-a046-4c32-9fda-e32e9631866e']
-\end{verbatim}
-
-The VM references here are UUIDs, though they may not be that simple in the
-future, and you should treat them as opaque strings.  Once a reference to a VM
-has been acquired a lifecycle operation may be invoked:
+['OpaqueRef:1', 'OpaqueRef:2', 'OpaqueRef:3', 'OpaqueRef:4' ]
+\end{verbatim}
+
+The VM references here have the form {\tt OpaqueRef:X}, though they may not be 
+that simple in the future, and you should treat them as opaque strings.  
+Once a reference to a VM has been acquired a lifecycle operation may be 
invoked:
 
 \begin{verbatim}
 >>> xen.VM.start(session, all_vms[3], False)
diff -r d1853a39e063 -r cb2575cec95c docs/xen-api/xenapi-datamodel.tex
--- a/docs/xen-api/xenapi-datamodel.tex Mon Mar 12 09:43:48 2007 -0600
+++ b/docs/xen-api/xenapi-datamodel.tex Mon Mar 12 10:07:08 2007 -0600
@@ -231,7 +231,7 @@ Quals & Field & Type & Description \\
 $\mathit{RO}_\mathit{run}$ &  {\tt last\_active} & int & Timestamp for last 
time session was active \\
 \hline
 \end{longtable}
-\subsection{Additional RPCs associated with class: session}
+\subsection{RPCs associated with class: session}
 \subsubsection{RPC name:~login\_with\_password}
 
 {\bf Overview:} 
@@ -505,7 +505,7 @@ Quals & Field & Type & Description \\
 $\mathit{RO}_\mathit{run}$ &  {\tt allowed\_operations} & 
(task\_allowed\_operations) Set & Operations allowed on this task \\
 \hline
 \end{longtable}
-\subsection{Additional RPCs associated with class: task}
+\subsection{RPCs associated with class: task}
 \subsubsection{RPC name:~cancel}
 
 {\bf Overview:} 
@@ -1022,40 +1022,7 @@ references to objects with match names
 \hline
 \multicolumn{1}{|l}{Name} & \multicolumn{3}{l|}{\bf VM} \\
 \multicolumn{1}{|l}{Description} & \multicolumn{3}{l|}{\parbox{11cm}{\em A
-virtual machine (or 'guest').
-
-VM booting is controlled by setting one of the two mutually exclusive
-groups: "PV", and "HVM".  If HVM.boot\_policy is the empty string, then
-paravirtual domain building and booting will be used; otherwise the VM will
-be loaded as an HVM domain, and booted using an emulated BIOS.
-
-When paravirtual booting is in use, the PV/bootloader field indicates the
-bootloader to use.  It may be "pygrub", in which case the platform's
-default installation of pygrub will be used, or a full path within the
-control domain to some other bootloader.  The other fields, PV/kernel,
-PV/ramdisk, PV/args and PV/bootloader\_args will be passed to the
-bootloader unmodified, and interpretation of those fields is then specific
-to the bootloader itself, including the possibility that the bootloader
-will ignore some or all of those given values. Finally the paths of all
-bootable disks are added to the bootloader commandline (a disk is bootable
-if its VBD has the bootable flag set). There may be zero, one or many
-bootable disks; the bootloader decides which disk (if any) to boot from.
-
-If the bootloader is pygrub, then the menu.lst is parsed if present in the
-guest's filesystem, otherwise the specified kernel and ramdisk are used, or
-an autodetected kernel is used if nothing is specified and autodetection is
-possible.  PV/args is appended to the kernel command line, no matter which
-mechanism is used for finding the kernel.
-
-If PV/bootloader is empty but PV/kernel is specified, then the kernel and
-ramdisk values will be treated as paths within the control domain.  If both
-PV/bootloader and PV/kernel are empty, then the behaviour is as if
-PV/bootloader was specified as "pygrub".
-
-When using HVM booting, HVM/boot\_policy and HVM/boot\_params specify the
-boot handling.  Only one policy is currently defined: "BIOS order".  In
-this case, HVM/boot\_params should contain one key-value pair "order" = "N"
-where N is the string that will be passed to QEMU.}} \\
+virtual machine (or 'guest').}} \\
 \hline
 Quals & Field & Type & Description \\
 \hline
@@ -1091,12 +1058,8 @@ Quals & Field & Type & Description \\
 $\mathit{RW}$ &  {\tt PV/bootloader\_args} & string & miscellaneous arguments 
for the bootloader \\
 $\mathit{RW}$ &  {\tt HVM/boot\_policy} & string & HVM boot policy \\
 $\mathit{RW}$ &  {\tt HVM/boot\_params} & (string $\rightarrow$ string) Map & 
HVM boot params \\
-$\mathit{RW}$ &  {\tt platform/std\_VGA} & bool & emulate standard VGA instead 
of cirrus logic \\
-$\mathit{RW}$ &  {\tt platform/serial} & string & redirect serial port to pty 
\\
-$\mathit{RW}$ &  {\tt platform/localtime} & bool & set RTC to local time \\
-$\mathit{RW}$ &  {\tt platform/clock\_offset} & bool & timeshift applied to 
guest's clock \\
-$\mathit{RW}$ &  {\tt platform/enable\_audio} & bool & emulate audio \\
-$\mathit{RO}_\mathit{ins}$ &  {\tt PCI\_bus} & string & PCI bus path for 
pass-through devices \\
+$\mathit{RW}$ &  {\tt platform} & (string $\rightarrow$ string) Map & 
platform-specific configuration \\
+$\mathit{RW}$ &  {\tt PCI\_bus} & string & PCI bus path for pass-through 
devices \\
 $\mathit{RW}$ &  {\tt other\_config} & (string $\rightarrow$ string) Map & 
additional configuration \\
 $\mathit{RO}_\mathit{run}$ &  {\tt domid} & int & domain ID (if available, -1 
otherwise) \\
 $\mathit{RO}_\mathit{run}$ &  {\tt is\_control\_domain} & bool & true if this 
is a control domain (domain 0 or a driver domain) \\
@@ -1104,7 +1067,7 @@ Quals & Field & Type & Description \\
 $\mathit{RO}_\mathit{run}$ &  {\tt guest\_metrics} & VM\_guest\_metrics ref & 
metrics associated with the running guest \\
 \hline
 \end{longtable}
-\subsection{Additional RPCs associated with class: VM}
+\subsection{RPCs associated with class: VM}
 \subsubsection{RPC name:~clone}
 
 {\bf Overview:} 
@@ -1178,7 +1141,8 @@ void
 
 \vspace{0.3cm}
 
-\noindent{\bf Possible Error Codes:} {\tt VM\_BAD\_POWER\_STATE}
+\noindent{\bf Possible Error Codes:} {\tt VM\_BAD\_POWER\_STATE}, {\tt
+VM\_HVM\_REQUIRED}
 
 \vspace{0.6cm}
 \subsubsection{RPC name:~pause}
@@ -1362,8 +1326,10 @@ void
 
 
 \vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
+
+\noindent{\bf Possible Error Codes:} {\tt VM\_BAD\_POWER\_STATE}
+
+\vspace{0.6cm}
 \subsubsection{RPC name:~hard\_reboot}
 
 {\bf Overview:} 
@@ -3438,13 +3404,13 @@ void
 \vspace{0.3cm}
 \vspace{0.3cm}
 \vspace{0.3cm}
-\subsubsection{RPC name:~get\_platform\_std\_VGA}
-
-{\bf Overview:} 
-Get the platform/std\_VGA field of the given VM.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} bool get_platform_std_VGA (session_id s, VM ref 
self)\end{verbatim}
+\subsubsection{RPC name:~get\_platform}
+
+{\bf Overview:} 
+Get the platform field of the given VM.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} ((string -> string) Map) get_platform (session_id s, VM ref 
self)\end{verbatim}
 
 
 \noindent{\bf Arguments:}
@@ -3462,21 +3428,21 @@ Get the platform/std\_VGA field of the g
 
  \noindent {\bf Return Type:} 
 {\tt 
-bool
-}
-
-
-value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~set\_platform\_std\_VGA}
-
-{\bf Overview:} 
-Set the platform/std\_VGA field of the given VM.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} void set_platform_std_VGA (session_id s, VM ref self, bool 
value)\end{verbatim}
+(string $\rightarrow$ string) Map
+}
+
+
+value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~set\_platform}
+
+{\bf Overview:} 
+Set the platform field of the given VM.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void set_platform (session_id s, VM ref self, (string -> 
string) Map value)\end{verbatim}
 
 
 \noindent{\bf Arguments:}
@@ -3488,7 +3454,7 @@ Set the platform/std\_VGA field of the g
 {\bf type} & {\bf name} & {\bf description} \\ \hline
 {\tt VM ref } & self & reference to the object \\ \hline 
 
-{\tt bool } & value & New value to set \\ \hline 
+{\tt (string $\rightarrow$ string) Map } & value & New value to set \\ \hline 
 
 \end{tabular}
 
@@ -3504,13 +3470,13 @@ void
 \vspace{0.3cm}
 \vspace{0.3cm}
 \vspace{0.3cm}
-\subsubsection{RPC name:~get\_platform\_serial}
-
-{\bf Overview:} 
-Get the platform/serial field of the given VM.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} string get_platform_serial (session_id s, VM ref 
self)\end{verbatim}
+\subsubsection{RPC name:~add\_to\_platform}
+
+{\bf Overview:} 
+Add the given key-value pair to the platform field of the given VM.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void add_to_platform (session_id s, VM ref self, string key, 
string value)\end{verbatim}
 
 
 \noindent{\bf Arguments:}
@@ -3522,6 +3488,77 @@ Get the platform/serial field of the giv
 {\bf type} & {\bf name} & {\bf description} \\ \hline
 {\tt VM ref } & self & reference to the object \\ \hline 
 
+{\tt string } & key & Key to add \\ \hline 
+
+{\tt string } & value & Value to add \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~remove\_from\_platform}
+
+{\bf Overview:} 
+Remove the given key and its corresponding value from the platform field of
+the given VM.  If the key is not in that Map, then do nothing.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void remove_from_platform (session_id s, VM ref self, string 
key)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+ 
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VM ref } & self & reference to the object \\ \hline 
+
+{\tt string } & key & Key to remove \\ \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\_PCI\_bus}
+
+{\bf Overview:} 
+Get the PCI\_bus field of the given VM.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} string get_PCI_bus (session_id s, VM 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 VM ref } & self & reference to the object \\ \hline 
+
 \end{tabular}
 
 \vspace{0.3cm}
@@ -3536,13 +3573,13 @@ value of the field
 \vspace{0.3cm}
 \vspace{0.3cm}
 \vspace{0.3cm}
-\subsubsection{RPC name:~set\_platform\_serial}
-
-{\bf Overview:} 
-Set the platform/serial field of the given VM.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} void set_platform_serial (session_id s, VM ref self, string 
value)\end{verbatim}
+\subsubsection{RPC name:~set\_PCI\_bus}
+
+{\bf Overview:} 
+Set the PCI\_bus field of the given VM.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void set_PCI_bus (session_id s, VM ref self, string 
value)\end{verbatim}
 
 
 \noindent{\bf Arguments:}
@@ -3567,236 +3604,6 @@ void
 
 
 
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~get\_platform\_localtime}
-
-{\bf Overview:} 
-Get the platform/localtime field of the given VM.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} bool get_platform_localtime (session_id s, VM 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 VM ref } & self & reference to the object \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-bool
-}
-
-
-value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~set\_platform\_localtime}
-
-{\bf Overview:} 
-Set the platform/localtime field of the given VM.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} void set_platform_localtime (session_id s, VM ref self, bool 
value)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VM ref } & self & reference to the object \\ \hline 
-
-{\tt bool } & value & New value to set \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-void
-}
-
-
-
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~get\_platform\_clock\_offset}
-
-{\bf Overview:} 
-Get the platform/clock\_offset field of the given VM.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} bool get_platform_clock_offset (session_id s, VM 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 VM ref } & self & reference to the object \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-bool
-}
-
-
-value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~set\_platform\_clock\_offset}
-
-{\bf Overview:} 
-Set the platform/clock\_offset field of the given VM.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} void set_platform_clock_offset (session_id s, VM ref self, 
bool value)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VM ref } & self & reference to the object \\ \hline 
-
-{\tt bool } & value & New value to set \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-void
-}
-
-
-
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~get\_platform\_enable\_audio}
-
-{\bf Overview:} 
-Get the platform/enable\_audio field of the given VM.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} bool get_platform_enable_audio (session_id s, VM 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 VM ref } & self & reference to the object \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-bool
-}
-
-
-value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~set\_platform\_enable\_audio}
-
-{\bf Overview:} 
-Set the platform/enable\_audio field of the given VM.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} void set_platform_enable_audio (session_id s, VM ref self, 
bool value)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VM ref } & self & reference to the object \\ \hline 
-
-{\tt bool } & value & New value to set \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-void
-}
-
-
-
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~get\_PCI\_bus}
-
-{\bf Overview:} 
-Get the PCI\_bus field of the given VM.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} string get_PCI_bus (session_id s, VM 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 VM ref } & self & reference to the object \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-string
-}
-
-
-value of the field
 \vspace{0.3cm}
 \vspace{0.3cm}
 \vspace{0.3cm}
@@ -4245,7 +4052,7 @@ Quals & Field & Type & Description \\
 $\mathit{RO}_\mathit{run}$ &  {\tt VCPUs/utilisation} & (int $\rightarrow$ 
float) Map & Utilisation for all of guest's current VCPUs \\
 \hline
 \end{longtable}
-\subsection{Additional RPCs associated with class: VM\_metrics}
+\subsection{RPCs associated with class: VM\_metrics}
 \subsubsection{RPC name:~get\_all}
 
 {\bf Overview:} 
@@ -4481,7 +4288,7 @@ Quals & Field & Type & Description \\
 $\mathit{RO}_\mathit{run}$ &  {\tt other} & (string $\rightarrow$ string) Map 
& anything else \\
 \hline
 \end{longtable}
-\subsection{Additional RPCs associated with class: VM\_guest\_metrics}
+\subsection{RPCs associated with class: VM\_guest\_metrics}
 \subsubsection{RPC name:~get\_all}
 
 {\bf Overview:} 
@@ -4825,7 +4632,7 @@ Quals & Field & Type & Description \\
 $\mathit{RO}_\mathit{ins}$ &  {\tt metrics} & host\_metrics ref & metrics 
associated with this host. \\
 \hline
 \end{longtable}
-\subsection{Additional RPCs associated with class: host}
+\subsection{RPCs associated with class: host}
 \subsubsection{RPC name:~disable}
 
 {\bf Overview:} 
@@ -6078,7 +5885,7 @@ Quals & Field & Type & Description \\
 $\mathit{RO}_\mathit{run}$ &  {\tt memory/free} & int & Host's free memory 
(bytes) \\
 \hline
 \end{longtable}
-\subsection{Additional RPCs associated with class: host\_metrics}
+\subsection{RPCs associated with class: host\_metrics}
 \subsubsection{RPC name:~get\_all}
 
 {\bf Overview:} 
@@ -6283,7 +6090,7 @@ Quals & Field & Type & Description \\
 $\mathit{RO}_\mathit{run}$ &  {\tt utilisation} & float & the current CPU 
utilisation \\
 \hline
 \end{longtable}
-\subsection{Additional RPCs associated with class: host\_cpu}
+\subsection{RPCs associated with class: host\_cpu}
 \subsubsection{RPC name:~get\_all}
 
 {\bf Overview:} 
@@ -6677,7 +6484,7 @@ Quals & Field & Type & Description \\
 $\mathit{RO}_\mathit{run}$ &  {\tt PIFs} & (PIF ref) Set & list of connected 
pifs \\
 \hline
 \end{longtable}
-\subsection{Additional RPCs associated with class: network}
+\subsection{RPCs associated with class: network}
 \subsubsection{RPC name:~get\_all}
 
 {\bf Overview:} 
@@ -7115,7 +6922,72 @@ Quals & Field & Type & Description \\
 $\mathit{RO}_\mathit{run}$ &  {\tt metrics} & VIF\_metrics ref & metrics 
associated with this VIF. \\
 \hline
 \end{longtable}
-\subsection{Additional RPCs associated with class: VIF}
+\subsection{RPCs associated with class: VIF}
+\subsubsection{RPC name:~plug}
+
+{\bf Overview:} 
+Hotplug the specified VIF, dynamically attaching it to the running VM.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void plug (session_id s, VIF 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 VIF ref } & self & The VIF to hotplug \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~unplug}
+
+{\bf Overview:} 
+Hot-unplug the specified VIF, dynamically unattaching it from the running
+VM.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void unplug (session_id s, VIF 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 VIF ref } & self & The VIF to hot-unplug \\ \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:} 
@@ -7942,7 +7814,7 @@ Quals & Field & Type & Description \\
 $\mathit{RO}_\mathit{run}$ &  {\tt io/write\_kbs} & float & Write bandwidth 
(KiB/s) \\
 \hline
 \end{longtable}
-\subsection{Additional RPCs associated with class: VIF\_metrics}
+\subsection{RPCs associated with class: VIF\_metrics}
 \subsubsection{RPC name:~get\_all}
 
 {\bf Overview:} 
@@ -8148,7 +8020,7 @@ Quals & Field & Type & Description \\
 $\mathit{RO}_\mathit{ins}$ &  {\tt metrics} & PIF\_metrics ref & metrics 
associated with this PIF. \\
 \hline
 \end{longtable}
-\subsection{Additional RPCs associated with class: PIF}
+\subsection{RPCs associated with class: PIF}
 \subsubsection{RPC name:~create\_VLAN}
 
 {\bf Overview:} 
@@ -8719,7 +8591,7 @@ Quals & Field & Type & Description \\
 $\mathit{RO}_\mathit{run}$ &  {\tt io/write\_kbs} & float & Write bandwidth 
(KiB/s) \\
 \hline
 \end{longtable}
-\subsection{Additional RPCs associated with class: PIF\_metrics}
+\subsection{RPCs associated with class: PIF\_metrics}
 \subsubsection{RPC name:~get\_all}
 
 {\bf Overview:} 
@@ -8926,7 +8798,7 @@ Quals & Field & Type & Description \\
 $\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 \\
 \hline
 \end{longtable}
-\subsection{Additional RPCs associated with class: SR}
+\subsection{RPCs associated with class: SR}
 \subsubsection{RPC name:~clone}
 
 {\bf Overview:} 
@@ -9549,7 +9421,7 @@ Quals & Field & Type & Description \\
 $\mathit{RO}_\mathit{run}$ &  {\tt uuid} & string & unique identifier/object 
reference \\
 $\mathit{RW}$ &  {\tt name/label} & string & a human-readable name \\
 $\mathit{RW}$ &  {\tt name/description} & string & a notes field containg 
human-readable description \\
-$\mathit{RW}$ &  {\tt SR} & SR ref & storage repository in which the VDI 
resides \\
+$\mathit{RO}_\mathit{ins}$ &  {\tt SR} & SR ref & storage repository in which 
the VDI resides \\
 $\mathit{RO}_\mathit{run}$ &  {\tt VBDs} & (VBD ref) Set & list of vbds that 
refer to this disk \\
 $\mathit{RO}_\mathit{run}$ &  {\tt crash\_dumps} & (crashdump ref) Set & list 
of crash dumps that refer to this disk \\
 $\mathit{RW}$ &  {\tt virtual\_size} & int & size of disk as presented to the 
guest (in bytes). Note that, depending on storage backend type, requested size 
may not be respected exactly \\
@@ -9560,7 +9432,7 @@ Quals & Field & Type & Description \\
 $\mathit{RW}$ &  {\tt read\_only} & bool & true if this disk may ONLY be 
mounted read-only \\
 \hline
 \end{longtable}
-\subsection{Additional RPCs associated with class: VDI}
+\subsection{RPCs associated with class: VDI}
 \subsubsection{RPC name:~snapshot}
 
 {\bf Overview:} 
@@ -9842,40 +9714,6 @@ SR ref
 
 
 value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~set\_SR}
-
-{\bf Overview:} 
-Set the SR field of the given VDI.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} void set_SR (session_id s, VDI ref self, SR ref 
value)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
- 
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VDI ref } & self & reference to the object \\ \hline 
-
-{\tt SR ref } & value & New value to set \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-void
-}
-
-
-
 \vspace{0.3cm}
 \vspace{0.3cm}
 \vspace{0.3cm}
@@ -10426,7 +10264,7 @@ Quals & Field & Type & Description \\
 $\mathit{RO}_\mathit{run}$ &  {\tt metrics} & VBD\_metrics ref & metrics 
associated with this VBD \\
 \hline
 \end{longtable}
-\subsection{Additional RPCs associated with class: VBD}
+\subsection{RPCs associated with class: VBD}
 \subsubsection{RPC name:~media\_change}
 
 {\bf Overview:} 
@@ -10447,6 +10285,71 @@ devices, detach the VBD and attach a new
 {\tt VBD ref } & vbd & The vbd representing the CDROM-like device \\ \hline 
 
 {\tt VDI ref } & vdi & The new VDI to 'insert' \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~plug}
+
+{\bf Overview:} 
+Hotplug the specified VBD, dynamically attaching it to the running VM.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void plug (session_id s, VBD 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 VBD ref } & self & The VBD to hotplug \\ \hline 
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:} 
+{\tt 
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~unplug}
+
+{\bf Overview:} 
+Hot-unplug the specified VBD, dynamically unattaching it from the running
+VM.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void unplug (session_id s, VBD 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 VBD ref } & self & The VBD to hot-unplug \\ \hline 
 
 \end{tabular}
 
@@ -11354,7 +11257,7 @@ Quals & Field & Type & Description \\
 $\mathit{RO}_\mathit{run}$ &  {\tt io/write\_kbs} & float & Write bandwidth 
(KiB/s) \\
 \hline
 \end{longtable}
-\subsection{Additional RPCs associated with class: VBD\_metrics}
+\subsection{RPCs associated with class: VBD\_metrics}
 \subsubsection{RPC name:~get\_all}
 
 {\bf Overview:} 
@@ -11556,7 +11459,7 @@ Quals & Field & Type & Description \\
 $\mathit{RO}_\mathit{run}$ &  {\tt currently\_attached} & bool & is the SR 
currently attached on this host? \\
 \hline
 \end{longtable}
-\subsection{Additional RPCs associated with class: PBD}
+\subsection{RPCs associated with class: PBD}
 \subsubsection{RPC name:~get\_all}
 
 {\bf Overview:} 
@@ -11884,7 +11787,39 @@ Quals & Field & Type & Description \\
 $\mathit{RO}_\mathit{ins}$ &  {\tt VDI} & VDI ref & the virtual disk \\
 \hline
 \end{longtable}
-\subsection{Additional RPCs associated with class: crashdump}
+\subsection{RPCs associated with class: crashdump}
+\subsubsection{RPC name:~destroy}
+
+{\bf Overview:} 
+Destroy the specified crashdump.
+
+ \noindent {\bf Signature:} 
+\begin{verbatim} void destroy (session_id s, crashdump 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 crashdump ref } & self & The crashdump to destroy \\ \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:} 
@@ -11999,70 +11934,6 @@ VDI ref
 
 
 value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~create}
-
-{\bf Overview:} 
-Create a new crashdump instance, and return its handle.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} (crashdump ref) create (session_id s, crashdump 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 crashdump record } & args & All constructor arguments \\ \hline 
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:} 
-{\tt 
-crashdump 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 crashdump instance.
-
- \noindent {\bf Signature:} 
-\begin{verbatim} void destroy (session_id s, crashdump 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 crashdump 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}
@@ -12148,7 +12019,7 @@ Quals & Field & Type & Description \\
 $\mathit{RO}_\mathit{ins}$ &  {\tt backend} & VM ref & the domain where the 
backend is located \\
 \hline
 \end{longtable}
-\subsection{Additional RPCs associated with class: VTPM}
+\subsection{RPCs associated with class: VTPM}
 \subsubsection{RPC name:~get\_uuid}
 
 {\bf Overview:} 
@@ -12393,7 +12264,7 @@ Quals & Field & Type & Description \\
 $\mathit{RW}$ &  {\tt other\_config} & (string $\rightarrow$ string) Map & 
additional configuration \\
 \hline
 \end{longtable}
-\subsection{Additional RPCs associated with class: console}
+\subsection{RPCs associated with class: console}
 \subsubsection{RPC name:~get\_all}
 
 {\bf Overview:} 
@@ -12828,7 +12699,7 @@ Quals & Field & Type & Description \\
 $\mathit{RW}$ &  {\tt fullname} & string & full name \\
 \hline
 \end{longtable}
-\subsection{Additional RPCs associated with class: user}
+\subsection{RPCs associated with class: user}
 \subsubsection{RPC name:~get\_uuid}
 
 {\bf Overview:} 
@@ -13093,7 +12964,7 @@ all fields from the object
 \section{Class: debug}
 \subsection{Fields for class: debug}
 {\bf Class debug has no fields.}
-\subsection{Additional RPCs associated with class: debug}
+\subsection{RPCs associated with class: debug}
 \subsubsection{RPC name:~get\_all}
 
 {\bf Overview:} 
@@ -13467,6 +13338,15 @@ expected and actual VM state at the time
 \begin{verbatim}VM_BAD_POWER_STATE(vm, expected, actual)\end{verbatim}
 \begin{center}\rule{10em}{0.1pt}\end{center}
 
+\subsubsection{VM\_HVM\_REQUIRED}
+
+HVM is required for this operation
+
+\vspace{0.3cm}
+{\bf Signature:}
+\begin{verbatim}VM_HVM_REQUIRED(vm)\end{verbatim}
+\begin{center}\rule{10em}{0.1pt}\end{center}
+
 
 
 \newpage
diff -r d1853a39e063 -r cb2575cec95c docs/xen-api/xenapi.tex
--- a/docs/xen-api/xenapi.tex   Mon Mar 12 09:43:48 2007 -0600
+++ b/docs/xen-api/xenapi.tex   Mon Mar 12 10:07:08 2007 -0600
@@ -16,6 +16,7 @@
 \usepackage{a4wide}
 \usepackage{graphics}
 \usepackage{longtable}
+\usepackage{fancyhdr}
 
 \setlength\topskip{0cm}
 \setlength\topmargin{0cm}
@@ -35,7 +36,7 @@
 
 \chapter{Introduction}
 
-This document contains a proposal for a Xen Management API---an interface for
+This document contains a description of the Xen Management API---an interface 
for
 remotely configuring and controlling virtualised guests running on a
 Xen-enabled host. 
 
diff -r d1853a39e063 -r cb2575cec95c 
linux-2.6-xen-sparse/arch/i386/kernel/cpu/mtrr/main-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/cpu/mtrr/main-xen.c Mon Mar 12 
09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/cpu/mtrr/main-xen.c Mon Mar 12 
10:07:08 2007 -0600
@@ -14,11 +14,11 @@ void generic_get_mtrr(unsigned int reg, 
 void generic_get_mtrr(unsigned int reg, unsigned long *base,
                      unsigned int *size, mtrr_type * type)
 {
-       dom0_op_t op;
+       struct xen_platform_op op;
 
-       op.cmd = DOM0_READ_MEMTYPE;
+       op.cmd = XENPF_read_memtype;
        op.u.read_memtype.reg = reg;
-       (void)HYPERVISOR_dom0_op(&op);
+       (void)HYPERVISOR_platform_op(&op);
 
        *size = op.u.read_memtype.nr_mfns;
        *base = op.u.read_memtype.mfn;
@@ -36,12 +36,12 @@ unsigned int *usage_table;
 
 static void __init set_num_var_ranges(void)
 {
-       dom0_op_t op;
+       struct xen_platform_op op;
 
        for (num_var_ranges = 0; ; num_var_ranges++) {
-               op.cmd = DOM0_READ_MEMTYPE;
+               op.cmd = XENPF_read_memtype;
                op.u.read_memtype.reg = num_var_ranges;
-               if (HYPERVISOR_dom0_op(&op) != 0)
+               if (HYPERVISOR_platform_op(&op) != 0)
                        break;
        }
 }
@@ -64,15 +64,15 @@ int mtrr_add_page(unsigned long base, un
                  unsigned int type, char increment)
 {
        int error;
-       dom0_op_t op;
+       struct xen_platform_op op;
 
        mutex_lock(&mtrr_mutex);
 
-       op.cmd = DOM0_ADD_MEMTYPE;
+       op.cmd = XENPF_add_memtype;
        op.u.add_memtype.mfn     = base;
        op.u.add_memtype.nr_mfns = size;
        op.u.add_memtype.type    = type;
-       error = HYPERVISOR_dom0_op(&op);
+       error = HYPERVISOR_platform_op(&op);
        if (error) {
                mutex_unlock(&mtrr_mutex);
                BUG_ON(error > 0);
@@ -117,7 +117,7 @@ int mtrr_del_page(int reg, unsigned long
        unsigned long lbase;
        unsigned int lsize;
        int error = -EINVAL;
-       dom0_op_t op;
+       struct xen_platform_op op;
 
        mutex_lock(&mtrr_mutex);
 
@@ -141,10 +141,10 @@ int mtrr_del_page(int reg, unsigned long
                goto out;
        }
        if (--usage_table[reg] < 1) {
-               op.cmd = DOM0_DEL_MEMTYPE;
+               op.cmd = XENPF_del_memtype;
                op.u.del_memtype.handle = 0;
                op.u.del_memtype.reg    = reg;
-               error = HYPERVISOR_dom0_op(&op);
+               error = HYPERVISOR_platform_op(&op);
                if (error) {
                        BUG_ON(error > 0);
                        goto out;
diff -r d1853a39e063 -r cb2575cec95c 
linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c       Mon Mar 12 
09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c       Mon Mar 12 
10:07:08 2007 -0600
@@ -2510,10 +2510,10 @@ static int __init io_apic_bug_finalize(v
        if(sis_apic_bug == -1)
                sis_apic_bug = 0;
        if (is_initial_xendomain()) {
-               dom0_op_t op = { .cmd = DOM0_PLATFORM_QUIRK };
+               struct xen_platform_op op = { .cmd = XENPF_platform_quirk };
                op.u.platform_quirk.quirk_id = sis_apic_bug ?
                        QUIRK_IOAPIC_BAD_REGSEL : QUIRK_IOAPIC_GOOD_REGSEL;
-               HYPERVISOR_dom0_op(&op);
+               HYPERVISOR_platform_op(&op);
        }
        return 0;
 }
diff -r d1853a39e063 -r cb2575cec95c 
linux-2.6-xen-sparse/arch/i386/kernel/ioport-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/ioport-xen.c        Mon Mar 12 
09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/ioport-xen.c        Mon Mar 12 
10:07:08 2007 -0600
@@ -81,7 +81,7 @@ asmlinkage long sys_ioperm(unsigned long
                t->io_bitmap_ptr = bitmap;
                set_thread_flag(TIF_IO_BITMAP);
 
-               set_iobitmap.bitmap   = (char *)bitmap;
+               set_xen_guest_handle(set_iobitmap.bitmap, (char *)bitmap);
                set_iobitmap.nr_ports = IO_BITMAP_BITS;
                HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap, &set_iobitmap);
        }
diff -r d1853a39e063 -r cb2575cec95c 
linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c     Mon Mar 12 
09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c     Mon Mar 12 
10:07:08 2007 -0600
@@ -71,12 +71,12 @@ static int do_microcode_update (const vo
                return -ENOMEM;
 
        if (copy_from_user(kbuf, ubuf, len) == 0) {
-               dom0_op_t op;
+               struct xen_platform_op op;
 
-               op.cmd = DOM0_MICROCODE;
+               op.cmd = XENPF_microcode_update;
                set_xen_guest_handle(op.u.microcode.data, kbuf);
                op.u.microcode.length = len;
-               err = HYPERVISOR_dom0_op(&op);
+               err = HYPERVISOR_platform_op(&op);
        } else
                err = -EFAULT;
 
diff -r d1853a39e063 -r cb2575cec95c 
linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c       Mon Mar 12 
09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c       Mon Mar 12 
10:07:08 2007 -0600
@@ -307,7 +307,8 @@ void exit_thread(void)
        if (unlikely(test_thread_flag(TIF_IO_BITMAP))) {
                struct task_struct *tsk = current;
                struct thread_struct *t = &tsk->thread;
-               struct physdev_set_iobitmap set_iobitmap = { 0 };
+               struct physdev_set_iobitmap set_iobitmap;
+               memset(&set_iobitmap, 0, sizeof(set_iobitmap));
                HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap, &set_iobitmap);
                kfree(t->io_bitmap_ptr);
                t->io_bitmap_ptr = NULL;
@@ -606,7 +607,8 @@ struct task_struct fastcall * __switch_t
        }
 
        if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) {
-               iobmp_op.bitmap   = (char *)next->io_bitmap_ptr;
+               set_xen_guest_handle(iobmp_op.bitmap,
+                                    (char *)next->io_bitmap_ptr);
                iobmp_op.nr_ports = next->io_bitmap_ptr ? IO_BITMAP_BITS : 0;
                mcl->op      = __HYPERVISOR_physdev_op;
                mcl->args[0] = PHYSDEVOP_set_iobitmap;
diff -r d1853a39e063 -r cb2575cec95c 
linux-2.6-xen-sparse/arch/i386/kernel/quirks-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/quirks-xen.c        Mon Mar 12 
09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/quirks-xen.c        Mon Mar 12 
10:07:08 2007 -0600
@@ -30,11 +30,11 @@ static void __devinit quirk_intel_irqbal
        raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word);
 
        if (!(word & (1 << 13))) {
-               dom0_op_t op;
+               struct xen_platform_op op;
                printk(KERN_INFO "Disabling irq balancing and affinity\n");
-               op.cmd = DOM0_PLATFORM_QUIRK;
+               op.cmd = XENPF_platform_quirk;
                op.u.platform_quirk.quirk_id = QUIRK_NOIRQBALANCING;
-               (void)HYPERVISOR_dom0_op(&op);
+               (void)HYPERVISOR_platform_op(&op);
        }
 
        /* put back the original value for config space*/
diff -r d1853a39e063 -r cb2575cec95c 
linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c  Mon Mar 12 09:43:48 
2007 -0600
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c  Mon Mar 12 10:07:08 
2007 -0600
@@ -435,7 +435,7 @@ int do_settimeofday(struct timespec *tv)
        s64 nsec;
        unsigned int cpu;
        struct shadow_time_info *shadow;
-       dom0_op_t op;
+       struct xen_platform_op op;
 
        if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
                return -EINVAL;
@@ -460,11 +460,11 @@ int do_settimeofday(struct timespec *tv)
        __normalize_time(&sec, &nsec);
 
        if (is_initial_xendomain() && !independent_wallclock) {
-               op.cmd = DOM0_SETTIME;
+               op.cmd = XENPF_settime;
                op.u.settime.secs        = sec;
                op.u.settime.nsecs       = nsec;
                op.u.settime.system_time = shadow->system_timestamp;
-               HYPERVISOR_dom0_op(&op);
+               HYPERVISOR_platform_op(&op);
                update_wallclock();
        } else if (independent_wallclock) {
                nsec -= shadow->system_timestamp;
@@ -488,7 +488,7 @@ static void sync_xen_wallclock(unsigned 
 {
        time_t sec;
        s64 nsec;
-       dom0_op_t op;
+       struct xen_platform_op op;
 
        if (!ntp_synced() || independent_wallclock || !is_initial_xendomain())
                return;
@@ -499,11 +499,11 @@ static void sync_xen_wallclock(unsigned 
        nsec = xtime.tv_nsec + ((jiffies - wall_jiffies) * (u64)NS_PER_TICK);
        __normalize_time(&sec, &nsec);
 
-       op.cmd = DOM0_SETTIME;
+       op.cmd = XENPF_settime;
        op.u.settime.secs        = sec;
        op.u.settime.nsecs       = nsec;
        op.u.settime.system_time = processed_system_time;
-       HYPERVISOR_dom0_op(&op);
+       HYPERVISOR_platform_op(&op);
 
        update_wallclock();
 
@@ -907,6 +907,10 @@ static void setup_cpu0_timer_irq(void)
        BUG_ON(per_cpu(timer_irq, 0) < 0);
 }
 
+static struct vcpu_set_periodic_timer xen_set_periodic_tick = {
+       .period_ns = NS_PER_TICK
+};
+
 void __init time_init(void)
 {
 #ifdef CONFIG_HPET_TIMER
@@ -919,6 +923,10 @@ void __init time_init(void)
                return;
        }
 #endif
+
+       HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, 0,
+                          &xen_set_periodic_tick);
+
        get_time_values_from_xen(0);
 
        processed_system_time = per_cpu(shadow_time, 0).system_timestamp;
@@ -976,8 +984,10 @@ EXPORT_SYMBOL(jiffies_to_st);
  */
 static void stop_hz_timer(void)
 {
+       struct vcpu_set_singleshot_timer singleshot;
        unsigned int cpu = smp_processor_id();
        unsigned long j;
+       int rc;
 
        cpu_set(cpu, nohz_cpu_mask);
 
@@ -997,8 +1007,16 @@ static void stop_hz_timer(void)
                j = jiffies + 1;
        }
 
-       if (HYPERVISOR_set_timer_op(jiffies_to_st(j)) != 0)
-               BUG();
+       singleshot.timeout_abs_ns = jiffies_to_st(j);
+       singleshot.flags = 0;
+       rc = HYPERVISOR_vcpu_op(VCPUOP_set_singleshot_timer, cpu, &singleshot);
+#ifdef XEN_COMPAT_030004
+       if (rc) {
+               BUG_ON(rc != -ENOSYS);
+               rc = HYPERVISOR_set_timer_op(singleshot.timeout_abs_ns);
+       }
+#endif
+       BUG_ON(rc);
 }
 
 static void start_hz_timer(void)
@@ -1030,6 +1048,8 @@ void time_resume(void)
        init_cpu_khz();
 
        for_each_online_cpu(cpu) {
+               HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, cpu,
+                                  &xen_set_periodic_tick);
                get_time_values_from_xen(cpu);
                per_cpu(processed_system_time, cpu) =
                        per_cpu(shadow_time, 0).system_timestamp;
@@ -1049,6 +1069,9 @@ int local_setup_timer(unsigned int cpu)
        int seq, irq;
 
        BUG_ON(cpu == 0);
+
+       HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, cpu,
+                          &xen_set_periodic_tick);
 
        do {
                seq = read_seqbegin(&xtime_lock);
diff -r d1853a39e063 -r cb2575cec95c 
linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c
--- a/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c    Mon Mar 12 09:43:48 
2007 -0600
+++ b/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c    Mon Mar 12 10:07:08 
2007 -0600
@@ -146,7 +146,7 @@ void xen_tlb_flush_mask(cpumask_t *mask)
        if ( cpus_empty(*mask) )
                return;
        op.cmd = MMUEXT_TLB_FLUSH_MULTI;
-       op.arg2.vcpumask = mask->bits;
+       set_xen_guest_handle(op.arg2.vcpumask, mask->bits);
        BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
 }
 
@@ -165,7 +165,7 @@ void xen_invlpg_mask(cpumask_t *mask, un
                return;
        op.cmd = MMUEXT_INVLPG_MULTI;
        op.arg1.linear_addr = ptr & PAGE_MASK;
-       op.arg2.vcpumask    = mask->bits;
+       set_xen_guest_handle(op.arg2.vcpumask, mask->bits);
        BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
 }
 
diff -r d1853a39e063 -r cb2575cec95c 
linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c   Mon Mar 12 09:43:48 
2007 -0600
+++ b/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c   Mon Mar 12 10:07:08 
2007 -0600
@@ -600,7 +600,7 @@ static void pgd_walk(pgd_t *pgd_base, pg
        int    g, u, m, rc;
 
        if (xen_feature(XENFEAT_auto_translated_physmap))
-               return 0;
+               return;
 
        for (g = 0; g < USER_PTRS_PER_PGD; g++, pgd++) {
                if (pgd_none(*pgd))
diff -r d1853a39e063 -r cb2575cec95c 
linux-2.6-xen-sparse/arch/ia64/xen/xcom_hcall.c
--- a/linux-2.6-xen-sparse/arch/ia64/xen/xcom_hcall.c   Mon Mar 12 09:43:48 
2007 -0600
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/xcom_hcall.c   Mon Mar 12 10:07:08 
2007 -0600
@@ -21,7 +21,7 @@
 #include <linux/gfp.h>
 #include <linux/module.h>
 #include <xen/interface/xen.h>
-#include <xen/interface/dom0_ops.h>
+#include <xen/interface/platform.h>
 #include <xen/interface/memory.h>
 #include <xen/interface/xencomm.h>
 #include <xen/interface/version.h>
diff -r d1853a39e063 -r cb2575cec95c 
linux-2.6-xen-sparse/arch/ia64/xen/xcom_mini.c
--- a/linux-2.6-xen-sparse/arch/ia64/xen/xcom_mini.c    Mon Mar 12 09:43:48 
2007 -0600
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/xcom_mini.c    Mon Mar 12 10:07:08 
2007 -0600
@@ -20,7 +20,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <xen/interface/xen.h>
-#include <xen/interface/dom0_ops.h>
+#include <xen/interface/platform.h>
 #include <xen/interface/memory.h>
 #include <xen/interface/xencomm.h>
 #include <xen/interface/version.h>
diff -r d1853a39e063 -r cb2575cec95c 
linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c
--- a/linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c Mon Mar 12 09:43:48 
2007 -0600
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c Mon Mar 12 10:07:08 
2007 -0600
@@ -22,7 +22,7 @@
 #include <linux/gfp.h>
 #include <linux/module.h>
 #include <xen/interface/xen.h>
-#include <xen/interface/dom0_ops.h>
+#include <xen/interface/platform.h>
 #define __XEN__
 #include <xen/interface/domctl.h>
 #include <xen/interface/sysctl.h>
@@ -40,25 +40,25 @@
 #define ROUND_DIV(v,s) (((v) + (s) - 1) / (s))
 
 static int
-xencomm_privcmd_dom0_op(privcmd_hypercall_t *hypercall)
-{
-       dom0_op_t kern_op;
-       dom0_op_t __user *user_op = (dom0_op_t __user *)hypercall->arg[0];
+xencomm_privcmd_platform_op(privcmd_hypercall_t *hypercall)
+{
+       struct xen_platform_op kern_op;
+       struct xen_platform_op __user *user_op = (struct xen_platform_op __user 
*)hypercall->arg[0];
        struct xencomm_handle *op_desc;
        struct xencomm_handle *desc = NULL;
        int ret = 0;
 
-       if (copy_from_user(&kern_op, user_op, sizeof(dom0_op_t)))
+       if (copy_from_user(&kern_op, user_op, sizeof(struct xen_platform_op)))
                return -EFAULT;
 
-       if (kern_op.interface_version != DOM0_INTERFACE_VERSION)
+       if (kern_op.interface_version != XENPF_INTERFACE_VERSION)
                return -EACCES;
 
        op_desc = xencomm_create_inline(&kern_op);
 
        switch (kern_op.cmd) {
        default:
-               printk("%s: unknown dom0 cmd %d\n", __func__, kern_op.cmd);
+               printk("%s: unknown platform cmd %d\n", __func__, kern_op.cmd);
                return -ENOSYS;
        }
 
@@ -67,10 +67,10 @@ xencomm_privcmd_dom0_op(privcmd_hypercal
                return ret;
        }
 
-       ret = xencomm_arch_hypercall_dom0_op(op_desc);
+       ret = xencomm_arch_hypercall_platform_op(op_desc);
 
        /* FIXME: should we restore the handle?  */
-       if (copy_to_user(user_op, &kern_op, sizeof(dom0_op_t)))
+       if (copy_to_user(user_op, &kern_op, sizeof(struct xen_platform_op)))
                ret = -EFAULT;
 
        if (desc)
@@ -638,8 +638,8 @@ privcmd_hypercall(privcmd_hypercall_t *h
 privcmd_hypercall(privcmd_hypercall_t *hypercall)
 {
        switch (hypercall->op) {
-       case __HYPERVISOR_dom0_op:
-               return xencomm_privcmd_dom0_op(hypercall);
+       case __HYPERVISOR_platform_op:
+               return xencomm_privcmd_platform_op(hypercall);
        case __HYPERVISOR_domctl:
                return xencomm_privcmd_domctl(hypercall);
        case __HYPERVISOR_sysctl:
diff -r d1853a39e063 -r cb2575cec95c 
linux-2.6-xen-sparse/arch/x86_64/kernel/ioport-xen.c
--- a/linux-2.6-xen-sparse/arch/x86_64/kernel/ioport-xen.c      Mon Mar 12 
09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/ioport-xen.c      Mon Mar 12 
10:07:08 2007 -0600
@@ -59,7 +59,7 @@ asmlinkage long sys_ioperm(unsigned long
                memset(bitmap, 0xff, IO_BITMAP_BYTES);
                t->io_bitmap_ptr = bitmap;
 
-               set_iobitmap.bitmap   = (char *)bitmap;
+               set_xen_guest_handle(set_iobitmap.bitmap, (char *)bitmap);
                set_iobitmap.nr_ports = IO_BITMAP_BITS;
                HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap, &set_iobitmap);
        }
diff -r d1853a39e063 -r cb2575cec95c 
linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c
--- a/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c     Mon Mar 12 
09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c     Mon Mar 12 
10:07:08 2007 -0600
@@ -50,7 +50,7 @@
 #include <asm/pda.h>
 #include <asm/prctl.h>
 #include <asm/kdebug.h>
-#include <xen/interface/dom0_ops.h>
+#include <xen/interface/platform.h>
 #include <xen/interface/physdev.h>
 #include <xen/interface/vcpu.h>
 #include <asm/desc.h>
@@ -304,7 +304,8 @@ void exit_thread(void)
                struct tss_struct *tss = &per_cpu(init_tss, get_cpu());
 #endif
 #ifdef CONFIG_XEN
-               struct physdev_set_iobitmap iobmp_op = { 0 };
+               struct physdev_set_iobitmap iobmp_op;
+               memset(&iobmp_op, 0, sizeof(iobmp_op));
 #endif
 
                kfree(t->io_bitmap_ptr);
@@ -540,7 +541,8 @@ __switch_to(struct task_struct *prev_p, 
        }
 
        if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) {
-               iobmp_op.bitmap   = (char *)next->io_bitmap_ptr;
+               set_xen_guest_handle(iobmp_op.bitmap,
+                                    (char *)next->io_bitmap_ptr);
                iobmp_op.nr_ports = next->io_bitmap_ptr ? IO_BITMAP_BITS : 0;
                mcl->op      = __HYPERVISOR_physdev_op;
                mcl->args[0] = PHYSDEVOP_set_iobitmap;
diff -r d1853a39e063 -r cb2575cec95c 
linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c
--- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c  Mon Mar 12 09:43:48 
2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c  Mon Mar 12 10:07:08 
2007 -0600
@@ -504,7 +504,6 @@ static struct tpm_vendor_specific tpm_vt
 };
 
 struct tpm_chip *init_vtpm(struct device *dev,
-                           struct tpm_virtual_device *tvd,
                            struct tpm_private *tp)
 {
        long rc;
@@ -516,7 +515,6 @@ struct tpm_chip *init_vtpm(struct device
                return ERR_PTR(-ENOMEM);
 
        vtpm_state_init(vtpms);
-       vtpms->tpmvd = tvd;
        vtpms->tpm_private = tp;
 
        chip = tpm_register_hardware(dev, &tpm_vtpm);
diff -r d1853a39e063 -r cb2575cec95c 
linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.h
--- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.h  Mon Mar 12 09:43:48 
2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.h  Mon Mar 12 10:07:08 
2007 -0600
@@ -3,16 +3,6 @@
 
 struct tpm_chip;
 struct tpm_private;
-
-struct tpm_virtual_device {
-       /*
-        * This field indicates the maximum size the driver can
-        * transfer in one chunk. It is filled in by the front-end
-        * driver and should be propagated to the generic tpm driver
-        * for allocation of buffers.
-        */
-       unsigned int max_tx_size;
-};
 
 struct vtpm_state {
        struct transmission *current_request;
@@ -30,8 +20,6 @@ struct vtpm_state {
 
        unsigned long        disconnect_time;
 
-       struct tpm_virtual_device *tpmvd;
-
        /*
         * The following is a private structure of the underlying
         * driver. It is passed as parameter in the send function.
@@ -51,7 +39,6 @@ int vtpm_vd_send(struct tpm_private * tp
 
 /* these functions are offered by tpm_vtpm.c */
 struct tpm_chip *init_vtpm(struct device *,
-                           struct tpm_virtual_device *,
                            struct tpm_private *);
 void cleanup_vtpm(struct device *);
 int vtpm_vd_recv(const struct tpm_chip* chip,
diff -r d1853a39e063 -r cb2575cec95c 
linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c
--- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c   Mon Mar 12 09:43:48 
2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c   Mon Mar 12 10:07:08 
2007 -0600
@@ -369,10 +369,6 @@ static void backend_changed(struct xenbu
        }
 }
 
-struct tpm_virtual_device tvd = {
-       .max_tx_size = PAGE_SIZE * TPMIF_TX_RING_SIZE,
-};
-
 static int tpmfront_probe(struct xenbus_device *dev,
                           const struct xenbus_device_id *id)
 {
@@ -383,7 +379,7 @@ static int tpmfront_probe(struct xenbus_
        if (!tp)
                return -ENOMEM;
 
-       tp->chip = init_vtpm(&dev->dev, &tvd, tp);
+       tp->chip = init_vtpm(&dev->dev, tp);
        if (IS_ERR(tp->chip))
                return PTR_ERR(tp->chip);
 
@@ -500,11 +496,6 @@ static void __init init_tpm_xenbus(void)
        xenbus_register_frontend(&tpmfront);
 }
 
-static void __exit exit_tpm_xenbus(void)
-{
-       xenbus_unregister_driver(&tpmfront);
-}
-
 static int tpmif_allocate_tx_buffers(struct tpm_private *tp)
 {
        unsigned int i;
@@ -530,13 +521,11 @@ static void tpmif_rx_action(unsigned lon
 static void tpmif_rx_action(unsigned long priv)
 {
        struct tpm_private *tp = (struct tpm_private *)priv;
-
        int i = 0;
        unsigned int received;
        unsigned int offset = 0;
        u8 *buffer;
-       tpmif_tx_request_t *tx;
-       tx = &tp->tx->ring[i].req;
+       tpmif_tx_request_t *tx = &tp->tx->ring[i].req;
 
        atomic_set(&tp->tx_busy, 0);
        wake_up_interruptible(&tp->wait_q);
@@ -545,7 +534,7 @@ static void tpmif_rx_action(unsigned lon
 
        buffer = kmalloc(received, GFP_ATOMIC);
        if (!buffer)
-               goto exit;
+               return;
 
        for (i = 0; i < TPMIF_TX_RING_SIZE && offset < received; i++) {
                struct tx_buffer *txb = tp->tx_buffers[i];
@@ -566,10 +555,6 @@ static void tpmif_rx_action(unsigned lon
 
        vtpm_vd_recv(tp->chip, buffer, received, tp->tx_remember);
        kfree(buffer);
-
-exit:
-
-       return;
 }
 
 
@@ -730,13 +715,6 @@ static int __init tpmif_init(void)
 }
 
 
-void __exit tpmif_exit(void)
-{
-       exit_tpm_xenbus();
-       tpm_private_put();
-       gnttab_free_grant_references(gref_head);
-}
-
 module_init(tpmif_init);
 
 MODULE_LICENSE("Dual BSD/GPL");
diff -r d1853a39e063 -r cb2575cec95c linux-2.6-xen-sparse/drivers/xen/Kconfig
--- a/linux-2.6-xen-sparse/drivers/xen/Kconfig  Mon Mar 12 09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/Kconfig  Mon Mar 12 10:07:08 2007 -0600
@@ -13,7 +13,7 @@ if XEN
 if XEN
 config XEN_INTERFACE_VERSION
        hex
-       default 0x00030203
+       default 0x00030205
 
 menu "XEN"
 
@@ -227,6 +227,9 @@ choice
        config XEN_COMPAT_030002_AND_LATER
                bool "3.0.2 and later"
 
+       config XEN_COMPAT_030004_AND_LATER
+               bool "3.0.4 and later"
+
        config XEN_COMPAT_LATEST_ONLY
                bool "no compatibility code"
 
@@ -236,6 +239,10 @@ 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
+
 endmenu
 
 config HAVE_IRQ_IGNORE_UNHANDLED
diff -r d1853a39e063 -r cb2575cec95c 
linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c
--- a/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c    Mon Mar 12 
09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c    Mon Mar 12 
10:07:08 2007 -0600
@@ -11,7 +11,6 @@
 #include <asm/mmu_context.h>
 #include <xen/evtchn.h>
 #include <asm/hypervisor.h>
-#include <xen/interface/dom0_ops.h>
 #include <xen/xenbus.h>
 #include <linux/cpu.h>
 #include <linux/kthread.h>
diff -r d1853a39e063 -r cb2575cec95c 
linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c
--- a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c     Mon Mar 12 
09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c     Mon Mar 12 
10:07:08 2007 -0600
@@ -349,16 +349,12 @@ void pciback_config_free_dev(struct pci_
 
 int pciback_config_add_field_offset(struct pci_dev *dev,
                                    struct config_field *field,
-                                   unsigned int offset)
+                                   unsigned int base_offset)
 {
        int err = 0;
        struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
        struct config_field_entry *cfg_entry;
        void *tmp;
-
-       /* silently ignore duplicate fields */
-       if (pciback_field_is_dup(dev, field->offset))
-               goto out;
 
        cfg_entry = kmalloc(sizeof(*cfg_entry), GFP_KERNEL);
        if (!cfg_entry) {
@@ -368,7 +364,12 @@ int pciback_config_add_field_offset(stru
 
        cfg_entry->data = NULL;
        cfg_entry->field = field;
-       cfg_entry->base_offset = offset;
+       cfg_entry->base_offset = base_offset;
+
+       /* silently ignore duplicate fields */
+       err = pciback_field_is_dup(dev,OFFSET(cfg_entry));
+       if (err)
+               goto out;
 
        if (field->init) {
                tmp = field->init(dev, OFFSET(cfg_entry));
diff -r d1853a39e063 -r cb2575cec95c 
linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.c
--- a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.c      Mon Mar 
12 09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.c      Mon Mar 
12 10:07:08 2007 -0600
@@ -32,16 +32,14 @@ static inline void register_quirk(struct
        list_add_tail(&quirk->quirks_list, &pciback_quirks);
 }
 
-int pciback_field_is_dup(struct pci_dev *dev, int reg)
+int pciback_field_is_dup(struct pci_dev *dev, unsigned int reg)
 {
        int ret = 0;
        struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
-       struct config_field *field;
        struct config_field_entry *cfg_entry;
 
        list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
-               field = cfg_entry->field;
-               if (field->offset == reg) {
+               if ( OFFSET(cfg_entry) == reg) {
                        ret = 1;
                        break;
                }
diff -r d1853a39e063 -r cb2575cec95c 
linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.h
--- a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.h      Mon Mar 
12 09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.h      Mon Mar 
12 10:07:08 2007 -0600
@@ -30,6 +30,6 @@ void pciback_config_field_free(struct co
 
 int pciback_config_quirk_release(struct pci_dev *dev);
 
-int pciback_field_is_dup(struct pci_dev *dev, int reg);
+int pciback_field_is_dup(struct pci_dev *dev, unsigned int reg);
 
 #endif
diff -r d1853a39e063 -r cb2575cec95c 
linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c
--- a/linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c       Mon Mar 12 
09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c       Mon Mar 12 
10:07:08 2007 -0600
@@ -589,10 +589,6 @@ static int pcistub_reg_add(int domain, i
        }
        dev = psdev->dev;
 
-       /* check for duplicate field */
-       if (pciback_field_is_dup(dev, reg))
-               goto out;
-
        field = kzalloc(sizeof(*field), GFP_ATOMIC);
        if (!field) {
                err = -ENOMEM;
@@ -728,10 +724,10 @@ static ssize_t pcistub_quirk_show(struct
                        if (count >= PAGE_SIZE)
                                goto out;
 
-                       count += scnprintf(buf + count, PAGE_SIZE -
-                                          count, "\t\t%08x:%01x:%08x\n",
-                                          field->offset, field->size,
-                                          field->mask);
+                       count += scnprintf(buf + count, PAGE_SIZE - count,
+                                          "\t\t%08x:%01x:%08x\n",
+                                          cfg_entry->base_offset + 
field->offset, 
+                                          field->size, field->mask);
                }
        }
 
diff -r d1853a39e063 -r cb2575cec95c 
linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c
--- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c        Mon Mar 12 
09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c        Mon Mar 12 
10:07:08 2007 -0600
@@ -28,7 +28,6 @@
 #include <asm/hypervisor.h>
 #include <xen/public/privcmd.h>
 #include <xen/interface/xen.h>
-#include <xen/interface/dom0_ops.h>
 #include <xen/xen_proc.h>
 
 static struct proc_dir_entry *privcmd_intf;
diff -r d1853a39e063 -r cb2575cec95c 
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    Mon Mar 
12 09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h    Mon Mar 
12 10:07:08 2007 -0600
@@ -201,11 +201,11 @@ HYPERVISOR_set_timer_op(
 }
 
 static inline int
-HYPERVISOR_dom0_op(
-       dom0_op_t *dom0_op)
-{
-       dom0_op->interface_version = DOM0_INTERFACE_VERSION;
-       return _hypercall1(int, dom0_op, dom0_op);
+HYPERVISOR_platform_op(
+       struct xen_platform_op *platform_op)
+{
+       platform_op->interface_version = XENPF_INTERFACE_VERSION;
+       return _hypercall1(int, platform_op, platform_op);
 }
 
 static inline int
diff -r d1853a39e063 -r cb2575cec95c 
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   Mon Mar 
12 09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h   Mon Mar 
12 10:07:08 2007 -0600
@@ -38,7 +38,7 @@
 #include <linux/version.h>
 #include <linux/errno.h>
 #include <xen/interface/xen.h>
-#include <xen/interface/dom0_ops.h>
+#include <xen/interface/platform.h>
 #include <xen/interface/event_channel.h>
 #include <xen/interface/physdev.h>
 #include <xen/interface/sched.h>
diff -r d1853a39e063 -r cb2575cec95c 
linux-2.6-xen-sparse/include/asm-ia64/hypercall.h
--- a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Mon Mar 12 09:43:48 
2007 -0600
+++ b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Mon Mar 12 10:07:08 
2007 -0600
@@ -120,9 +120,9 @@ HYPERVISOR_set_timer_op(u64 timeout)
 }
 
 static inline int
-xencomm_arch_hypercall_dom0_op(struct xencomm_handle *op)
-{
-       return _hypercall1(int, dom0_op, op);
+xencomm_arch_hypercall_platform_op(struct xencomm_handle *op)
+{
+       return _hypercall1(int, platform_op, op);
 }
 
 static inline int
diff -r d1853a39e063 -r cb2575cec95c 
linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h
--- a/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h        Mon Mar 12 
09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h        Mon Mar 12 
10:07:08 2007 -0600
@@ -51,7 +51,7 @@ extern int running_on_xen;
 #include <linux/version.h>
 #include <linux/errno.h>
 #include <xen/interface/xen.h>
-#include <xen/interface/dom0_ops.h>
+#include <xen/interface/platform.h>
 #include <xen/interface/event_channel.h>
 #include <xen/interface/physdev.h>
 #include <xen/interface/sched.h>
diff -r d1853a39e063 -r cb2575cec95c 
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  Mon Mar 
12 09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h  Mon Mar 
12 10:07:08 2007 -0600
@@ -204,11 +204,11 @@ HYPERVISOR_set_timer_op(
 }
 
 static inline int
-HYPERVISOR_dom0_op(
-       dom0_op_t *dom0_op)
-{
-       dom0_op->interface_version = DOM0_INTERFACE_VERSION;
-       return _hypercall1(int, dom0_op, dom0_op);
+HYPERVISOR_platform_op(
+       struct xen_platform_op *platform_op)
+{
+       platform_op->interface_version = XENPF_INTERFACE_VERSION;
+       return _hypercall1(int, platform_op, platform_op);
 }
 
 static inline int
diff -r d1853a39e063 -r cb2575cec95c 
patches/linux-2.6.18/softlockup-no-idle-hz.patch
--- a/patches/linux-2.6.18/softlockup-no-idle-hz.patch  Mon Mar 12 09:43:48 
2007 -0600
+++ b/patches/linux-2.6.18/softlockup-no-idle-hz.patch  Mon Mar 12 10:07:08 
2007 -0600
@@ -34,7 +34,7 @@ diff -pruN ../orig-linux-2.6.18/kernel/s
 +                      !per_cpu(watchdog_task, this_cpu))
 +              return MAX_JIFFY_OFFSET;
 +
-+      return min_t(long, 0, touch_timestamp + HZ - jiffies);
++      return max_t(long, 0, touch_timestamp + HZ - jiffies);
 +}
 +
  /*
diff -r d1853a39e063 -r cb2575cec95c tools/ioemu/hw/ide.c
--- a/tools/ioemu/hw/ide.c      Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/ioemu/hw/ide.c      Mon Mar 12 10:07:08 2007 -0600
@@ -396,17 +396,41 @@ typedef struct PCIIDEState {
 
 #ifdef DMA_MULTI_THREAD
 
+static pthread_t ide_dma_thread;
 static int file_pipes[2];
 
 static void ide_dma_loop(BMDMAState *bm);
 static void dma_thread_loop(BMDMAState *bm);
 
+extern int suspend_requested;
 static void *dma_thread_func(void* opaque)
 {
     BMDMAState* req;
-
-    while (read(file_pipes[0], &req, sizeof(req))) {
-        dma_thread_loop(req);
+    fd_set fds;
+    int rv, nfds = file_pipes[0] + 1;
+    struct timeval tm;
+
+    while (1) {
+
+        /* Wait at most a second for the pipe to become readable */
+        FD_ZERO(&fds);
+        FD_SET(file_pipes[0], &fds);
+        tm.tv_sec = 1;
+        tm.tv_usec = 0;
+        rv = select(nfds, &fds, NULL, NULL, &tm);
+        
+        if (rv != 0) {
+            if (read(file_pipes[0], &req, sizeof(req)) == 0)
+                return NULL;
+            dma_thread_loop(req);
+        } else {
+            if (suspend_requested)  {
+                /* Need to tidy up the DMA thread so that we don't end up 
+                 * finishing operations after the domain's ioreqs are 
+                 * drained and its state saved */
+                return NULL;
+            }
+        }
     }
 
     return NULL;
@@ -414,23 +438,40 @@ static void *dma_thread_func(void* opaqu
 
 static void dma_create_thread(void)
 {
-    pthread_t tid;
     int rt;
+    pthread_attr_t a;
 
     if (pipe(file_pipes) != 0) {
         fprintf(stderr, "create pipe failed\n");
         exit(1);
     }
 
-    if ((rt = pthread_create(&tid, NULL, dma_thread_func, NULL))) {
+    if ((rt = pthread_attr_init(&a))
+        || (rt = pthread_attr_setdetachstate(&a, PTHREAD_CREATE_JOINABLE))) {
+        fprintf(stderr, "Oops, dma thread attr setup failed, errno=%d\n", rt);
+        exit(1);
+    }    
+    
+    if ((rt = pthread_create(&ide_dma_thread, &a, dma_thread_func, NULL))) {
         fprintf(stderr, "Oops, dma thread creation failed, errno=%d\n", rt);
         exit(1);
     }
-
-    if ((rt = pthread_detach(tid))) {
-        fprintf(stderr, "Oops, dma thread detachment failed, errno=%d\n", rt);
-        exit(1);
-    }
+}
+
+void ide_stop_dma_thread(void)
+{
+    int rc;
+    /* Make sure the IDE DMA thread is stopped */
+    if ( (rc = pthread_join(ide_dma_thread, NULL)) != 0 )
+    {
+        fprintf(stderr, "Oops, error collecting IDE DMA thread (%s)\n", 
+                strerror(rc));
+    }
+}
+
+#else
+void ide_stop_dma_thread(void)
+{
 }
 #endif /* DMA_MULTI_THREAD */
 
@@ -2602,6 +2643,120 @@ void pci_cmd646_ide_init(PCIBus *bus, Bl
 #endif /* DMA_MULTI_THREAD */
 }
 
+static void pci_ide_save(QEMUFile* f, void *opaque)
+{
+    PCIIDEState *d = opaque;
+    int i;
+
+    for(i = 0; i < 2; i++) {
+        BMDMAState *bm = &d->bmdma[i];
+        qemu_put_8s(f, &bm->cmd);
+        qemu_put_8s(f, &bm->status);
+        qemu_put_be32s(f, &bm->addr);
+        /* XXX: if a transfer is pending, we do not save it yet */
+    }
+
+    /* per IDE interface data */
+    for(i = 0; i < 2; i++) {
+        IDEState *s = &d->ide_if[i * 2];
+        uint8_t drive1_selected;
+        qemu_put_8s(f, &s->cmd);
+        drive1_selected = (s->cur_drive != s);
+        qemu_put_8s(f, &drive1_selected);
+    }
+
+    /* per IDE drive data */
+    for(i = 0; i < 4; i++) {
+        IDEState *s = &d->ide_if[i];
+        qemu_put_be32s(f, &s->mult_sectors);
+        qemu_put_be32s(f, &s->identify_set);
+        if (s->identify_set) {
+            qemu_put_buffer(f, (const uint8_t *)s->identify_data, 512);
+        }
+        qemu_put_8s(f, &s->write_cache);
+        qemu_put_8s(f, &s->feature);
+        qemu_put_8s(f, &s->error);
+        qemu_put_be32s(f, &s->nsector);
+        qemu_put_8s(f, &s->sector);
+        qemu_put_8s(f, &s->lcyl);
+        qemu_put_8s(f, &s->hcyl);
+        qemu_put_8s(f, &s->hob_feature);
+        qemu_put_8s(f, &s->hob_nsector);
+        qemu_put_8s(f, &s->hob_sector);
+        qemu_put_8s(f, &s->hob_lcyl);
+        qemu_put_8s(f, &s->hob_hcyl);
+        qemu_put_8s(f, &s->select);
+        qemu_put_8s(f, &s->status);
+        qemu_put_8s(f, &s->lba48);
+
+        qemu_put_8s(f, &s->sense_key);
+        qemu_put_8s(f, &s->asc);
+        /* XXX: if a transfer is pending, we do not save it yet */
+    }
+}
+
+static int pci_ide_load(QEMUFile* f, void *opaque, int version_id)
+{
+    PCIIDEState *d = opaque;
+    int ret, i;
+
+    if (version_id != 1)
+        return -EINVAL;
+
+    for(i = 0; i < 2; i++) {
+        BMDMAState *bm = &d->bmdma[i];
+        qemu_get_8s(f, &bm->cmd);
+        qemu_get_8s(f, &bm->status);
+        qemu_get_be32s(f, &bm->addr);
+        /* XXX: if a transfer is pending, we do not save it yet */
+    }
+
+    /* per IDE interface data */
+    for(i = 0; i < 2; i++) {
+        IDEState *s = &d->ide_if[i * 2];
+        uint8_t drive1_selected;
+        qemu_get_8s(f, &s->cmd);
+        qemu_get_8s(f, &drive1_selected);
+        s->cur_drive = &d->ide_if[i * 2 + (drive1_selected != 0)];
+    }
+
+    /* per IDE drive data */
+    for(i = 0; i < 4; i++) {
+        IDEState *s = &d->ide_if[i];
+        qemu_get_be32s(f, &s->mult_sectors);
+        qemu_get_be32s(f, &s->identify_set);
+        if (s->identify_set) {
+            qemu_get_buffer(f, (uint8_t *)s->identify_data, 512);
+        }
+        qemu_get_8s(f, &s->write_cache);
+        qemu_get_8s(f, &s->feature);
+        qemu_get_8s(f, &s->error);
+        qemu_get_be32s(f, &s->nsector);
+        qemu_get_8s(f, &s->sector);
+        qemu_get_8s(f, &s->lcyl);
+        qemu_get_8s(f, &s->hcyl);
+        qemu_get_8s(f, &s->hob_feature);
+        qemu_get_8s(f, &s->hob_nsector);
+        qemu_get_8s(f, &s->hob_sector);
+        qemu_get_8s(f, &s->hob_lcyl);
+        qemu_get_8s(f, &s->hob_hcyl);
+        qemu_get_8s(f, &s->select);
+        qemu_get_8s(f, &s->status);
+        qemu_get_8s(f, &s->lba48);
+
+        qemu_get_8s(f, &s->sense_key);
+        qemu_get_8s(f, &s->asc);
+        /* XXX: if a transfer is pending, we do not save it yet */
+        if (s->status & (DRQ_STAT|BUSY_STAT)) {
+            /* Tell the guest that its transfer has gone away */
+            ide_abort_command(s);
+            ide_set_irq(s);
+        }
+    }
+    return 0;
+}
+
+
 /* hd_table must contain 4 block drivers */
 /* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */
 void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn)
@@ -2643,6 +2798,7 @@ void pci_piix3_ide_init(PCIBus *bus, Blo
     buffered_pio_init();
 
     register_savevm("ide_pci", 0, 1, generic_pci_save, generic_pci_load, d);
+    register_savevm("ide", 0, 1, pci_ide_save, pci_ide_load, d);
 
 #ifdef DMA_MULTI_THREAD    
     dma_create_thread();
diff -r d1853a39e063 -r cb2575cec95c tools/ioemu/target-i386-dm/helper2.c
--- a/tools/ioemu/target-i386-dm/helper2.c      Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/ioemu/target-i386-dm/helper2.c      Mon Mar 12 10:07:08 2007 -0600
@@ -577,7 +577,28 @@ int main_loop(void)
         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");
     }
diff -r d1853a39e063 -r cb2575cec95c tools/ioemu/vl.h
--- a/tools/ioemu/vl.h  Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/ioemu/vl.h  Mon Mar 12 10:07:08 2007 -0600
@@ -843,6 +843,7 @@ void pci_piix3_ide_init(PCIBus *bus, Blo
 void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn);
 int pmac_ide_init (BlockDriverState **hd_table,
                    SetIRQFunc *set_irq, void *irq_opaque, int irq);
+void ide_stop_dma_thread(void);
 
 /* cdrom.c */
 int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track);
diff -r d1853a39e063 -r cb2575cec95c tools/libxc/xc_core_ia64.c
--- a/tools/libxc/xc_core_ia64.c        Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxc/xc_core_ia64.c        Mon Mar 12 10:07:08 2007 -0600
@@ -22,6 +22,28 @@
 #include "xc_core.h"
 #include "xc_efi.h"
 #include "xc_dom.h"
+#include <inttypes.h>
+
+static int
+xc_memory_map_cmp(const void *lhs__, const void *rhs__)
+{
+    const struct xc_core_memory_map *lhs =
+        (const struct xc_core_memory_map *)lhs__;
+    const struct xc_core_memory_map *rhs =
+        (const struct xc_core_memory_map *)rhs__;
+
+    if (lhs->addr < rhs->addr)
+        return -1;
+    if (lhs->addr > rhs->addr)
+        return 1;
+
+    /* memory map overlap isn't allowed. complain */
+    DPRINTF("duplicated addresses are detected "
+            "(0x%" PRIx64 ", 0x%" PRIx64 "), "
+            "(0x%" PRIx64 ", 0x%" PRIx64 ")\n",
+            lhs->addr, lhs->size, rhs->addr, rhs->size);
+    return 0;
+}
 
 int
 xc_core_arch_auto_translated_physmap(const xc_dominfo_t *info)
@@ -111,6 +133,7 @@ memory_map_get_old_hvm(int xc_handle, xc
     }
     *mapp = map;
     *nr_entries = i;
+    qsort(map, *nr_entries, sizeof(map[0]), &xc_memory_map_cmp);
     return 0;
 
 out:
@@ -196,6 +219,7 @@ xc_core_arch_memory_map_get(int xc_handl
     ret = 0;
 out:
     munmap(memmap_info, PAGE_SIZE);
+    qsort(map, *nr_entries, sizeof(map[0]), &xc_memory_map_cmp);
     return ret;
     
 old:
diff -r d1853a39e063 -r cb2575cec95c tools/libxc/xc_dom_x86.c
--- a/tools/libxc/xc_dom_x86.c  Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxc/xc_dom_x86.c  Mon Mar 12 10:07:08 2007 -0600
@@ -433,23 +433,11 @@ static int vcpu_x86_32(struct xc_dom_ima
 {
     vcpu_guest_context_x86_32_t *ctxt = ptr;
     xen_pfn_t cr3_pfn;
-    int i;
 
     xc_dom_printf("%s: called\n", __FUNCTION__);
 
     /* clear everything */
     memset(ctxt, 0, sizeof(*ctxt));
-
-    /* Virtual IDT is empty at start-of-day. */
-    for ( i = 0; i < 256; i++ )
-    {
-        ctxt->trap_ctxt[i].vector = i;
-        ctxt->trap_ctxt[i].cs = FLAT_KERNEL_CS_X86_32;
-    }
-
-    /* No callback handlers. */
-    ctxt->event_callback_cs = FLAT_KERNEL_CS_X86_32;
-    ctxt->failsafe_callback_cs = FLAT_KERNEL_CS_X86_32;
 
     ctxt->user_regs.ds = FLAT_KERNEL_DS_X86_32;
     ctxt->user_regs.es = FLAT_KERNEL_DS_X86_32;
@@ -464,9 +452,8 @@ static int vcpu_x86_32(struct xc_dom_ima
         dom->parms.virt_base + (dom->start_info_pfn) * PAGE_SIZE_X86;
     ctxt->user_regs.eflags = 1 << 9; /* Interrupt Enable */
 
-    ctxt->kernel_ss = FLAT_KERNEL_SS_X86_32;
-    ctxt->kernel_sp =
-        dom->parms.virt_base + (dom->bootstack_pfn + 1) * PAGE_SIZE_X86;
+    ctxt->kernel_ss = ctxt->user_regs.ss;
+    ctxt->kernel_sp = ctxt->user_regs.esp;
 
     ctxt->flags = VGCF_in_kernel_X86_32;
     if ( dom->parms.pae == 2 /* extended_cr3 */ ||
@@ -485,19 +472,11 @@ static int vcpu_x86_64(struct xc_dom_ima
 {
     vcpu_guest_context_x86_64_t *ctxt = ptr;
     xen_pfn_t cr3_pfn;
-    int i;
 
     xc_dom_printf("%s: called\n", __FUNCTION__);
 
     /* clear everything */
     memset(ctxt, 0, sizeof(*ctxt));
-
-    /* Virtual IDT is empty at start-of-day. */
-    for ( i = 0; i < 256; i++ )
-    {
-        ctxt->trap_ctxt[i].vector = i;
-        ctxt->trap_ctxt[i].cs = FLAT_KERNEL_CS_X86_64;
-    }
 
     ctxt->user_regs.ds = FLAT_KERNEL_DS_X86_64;
     ctxt->user_regs.es = FLAT_KERNEL_DS_X86_64;
@@ -512,9 +491,8 @@ static int vcpu_x86_64(struct xc_dom_ima
         dom->parms.virt_base + (dom->start_info_pfn) * PAGE_SIZE_X86;
     ctxt->user_regs.rflags = 1 << 9; /* Interrupt Enable */
 
-    ctxt->kernel_ss = FLAT_KERNEL_SS_X86_64;
-    ctxt->kernel_sp =
-        dom->parms.virt_base + (dom->bootstack_pfn + 1) * PAGE_SIZE_X86;
+    ctxt->kernel_ss = ctxt->user_regs.ss;
+    ctxt->kernel_sp = ctxt->user_regs.esp;
 
     ctxt->flags = VGCF_in_kernel_X86_64;
     cr3_pfn = xc_dom_p2m_guest(dom, dom->pgtables_seg.pfn);
diff -r d1853a39e063 -r cb2575cec95c tools/libxc/xc_hvm_restore.c
--- a/tools/libxc/xc_hvm_restore.c      Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxc/xc_hvm_restore.c      Mon Mar 12 10:07:08 2007 -0600
@@ -101,6 +101,9 @@ int xc_hvm_restore(int xc_handle, int io
     /* Number of pages of memory the guest has.  *Not* the same as max_pfn. */
     unsigned long nr_pages;
 
+    /* The size of an array big enough to contain all guest pfns */
+    unsigned long pfn_array_size = max_pfn + 1;
+
     /* hvm guest mem size (Mb) */
     memsize = (unsigned long long)*store_mfn;
     v_end = memsize << 20;
@@ -127,7 +130,7 @@ int xc_hvm_restore(int xc_handle, int io
     }
 
 
-    pfns = malloc(max_pfn * sizeof(xen_pfn_t));
+    pfns = malloc(pfn_array_size * sizeof(xen_pfn_t));
     if (pfns == NULL) {
         ERROR("memory alloc failed");
         errno = ENOMEM;
@@ -139,11 +142,11 @@ int xc_hvm_restore(int xc_handle, int io
         goto out;
     }
 
-    for ( i = 0; i < max_pfn; i++ )
+    for ( i = 0; i < pfn_array_size; i++ )
         pfns[i] = i;
-    for ( i = HVM_BELOW_4G_RAM_END >> PAGE_SHIFT; i < max_pfn; i++ )
+    for ( i = HVM_BELOW_4G_RAM_END >> PAGE_SHIFT; i < pfn_array_size; i++ )
         pfns[i] += HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT;
-    arch_max_pfn = pfns[max_pfn - 1];/* used later */
+    arch_max_pfn = pfns[max_pfn];/* used later */
 
     /* Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000. */
     rc = xc_domain_memory_populate_physmap(
@@ -281,6 +284,14 @@ int xc_hvm_restore(int xc_handle, int io
     else
         shared_page_nr = (v_end >> PAGE_SHIFT) - 1;
 
+    /* Paranoia: clean 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) ) {
+        ERROR("error clearing comms frames!\n");
+        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);
@@ -288,6 +299,33 @@ int xc_hvm_restore(int xc_handle, int io
     /* 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))) {
@@ -310,33 +348,6 @@ int xc_hvm_restore(int xc_handle, int io
     if (( rc = xc_domain_hvm_setcontext(xc_handle, dom, hvm_buf, rec_len))) {
         ERROR("error set hvm buffer!\n");
         goto out;
-    }
-
-    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;
-        }
     }
 
     /* Shared-info pfn */
diff -r d1853a39e063 -r cb2575cec95c tools/libxc/xc_hvm_save.c
--- a/tools/libxc/xc_hvm_save.c Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxc/xc_hvm_save.c Mon Mar 12 10:07:08 2007 -0600
@@ -27,11 +27,13 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <sys/time.h>
-#include <xen/hvm/e820.h>
 
 #include "xc_private.h"
 #include "xg_private.h"
 #include "xg_save_restore.h"
+
+#include <xen/hvm/e820.h>
+#include <xen/hvm/params.h>
 
 /*
 ** Default values for important tuning parameters. Can override by passing
@@ -49,11 +51,25 @@ 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 */
+/* #levels of page tables used by the current guest */
 static unsigned int pt_levels;
 
-/* total number of pages used by the current guest */
-static unsigned long max_pfn;
+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
@@ -61,7 +77,7 @@ static unsigned long max_pfn;
 */
 
 #define BITS_PER_LONG (sizeof(unsigned long) * 8)
-#define BITMAP_SIZE   ((max_pfn + BITS_PER_LONG - 1) / 8)
+#define BITMAP_SIZE   ((pfn_array_size + BITS_PER_LONG - 1) / 8)
 
 #define BITMAP_ENTRY(_nr,_bmap) \
    ((unsigned long *)(_bmap))[(_nr)/BITS_PER_LONG]
@@ -183,7 +199,7 @@ static int print_stats(int xc_handle, ui
     return 0;
 }
 
-static int analysis_phase(int xc_handle, uint32_t domid, int max_pfn,
+static int analysis_phase(int xc_handle, uint32_t domid, int pfn_array_size,
                           unsigned long *arr, int runs)
 {
     long long start, now;
@@ -196,7 +212,7 @@ static int analysis_phase(int xc_handle,
         int i;
 
         xc_shadow_control(xc_handle, domid, XEN_DOMCTL_SHADOW_OP_CLEAN,
-                          arr, max_pfn, NULL, 0, NULL);
+                          arr, pfn_array_size, NULL, 0, NULL);
         DPRINTF("#Flush\n");
         for ( i = 0; i < 40; i++ ) {
             usleep(50000);
@@ -236,7 +252,7 @@ static int suspend_and_state(int (*suspe
 
 
     if (info->shutdown && info->shutdown_reason == SHUTDOWN_suspend)
-        return 0; // success
+        return 0; // success        
 
     if (info->paused) {
         // try unpausing domain, wait, and retest
@@ -268,10 +284,20 @@ int xc_hvm_save(int xc_handle, int io_fd
     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 sent_last_iter, skip_this_iter;
+
+    /* The highest guest-physical frame number used by the current guest */
+    unsigned long max_pfn;
+
+    /* The size of an array big enough to contain all guest pfns */
+    unsigned long pfn_array_size;
 
     /* The new domain's shared-info frame number. */
     unsigned long shared_info_frame;
+
+    /* Other magic frames: ioreqs and xenstore comms */
+    unsigned long ioreq_pfn, bufioreq_pfn, store_pfn;
 
     /* A copy of the CPU context of the guest. */
     vcpu_guest_context_t ctxt;
@@ -291,7 +317,7 @@ int xc_hvm_save(int xc_handle, int io_fd
 
     uint32_t rec_size, nr_vcpus;
 
-    /* power of 2 order of max_pfn */
+    /* power of 2 order of pfn_array_size */
     int order_nr;
 
     /* bitmap of pages:
@@ -350,6 +376,15 @@ int xc_hvm_save(int xc_handle, int io_fd
     if(!(live_shinfo = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
                                             PROT_READ, shared_info_frame))) {
         ERROR("HVM:Couldn't map live_shinfo");
+        goto out;
+    }
+
+    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;
     }
 
@@ -368,6 +403,7 @@ int xc_hvm_save(int xc_handle, int io_fd
         }
 
         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
@@ -388,20 +424,28 @@ int xc_hvm_save(int xc_handle, int io_fd
 
     /* Calculate the highest PFN of "normal" memory:
      * HVM memory is sequential except for the VGA and MMIO holes. */
-    max_pfn = info.nr_pages;
+    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;   
+    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); 
 
-    skip_this_iter = 0;/*XXX*/
+    /* Size of any array that covers 0 ... max_pfn */
+    pfn_array_size = max_pfn + 1;
+
     /* pretend we sent all the pages last iteration */
-    sent_last_iter = max_pfn;
-
-    /* calculate the power of 2 order of max_pfn, e.g.
+    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 = max_pfn-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 */
@@ -435,7 +479,7 @@ int xc_hvm_save(int xc_handle, int io_fd
         return 1;
     }
 
-    analysis_phase(xc_handle, dom, max_pfn, to_skip, 0);
+    analysis_phase(xc_handle, dom, pfn_array_size, to_skip, 0);
 
 
     /* We want zeroed memory so use calloc rather than malloc. */
@@ -465,9 +509,17 @@ int xc_hvm_save(int xc_handle, int io_fd
 
         DPRINTF("Saving HVM domain memory pages: iter %d   0%%", iter);
 
-        while( N < max_pfn ){
-
-            unsigned int this_pc = (N * 100) / max_pfn;
+        if (last_iter && (max_pfn != live_shinfo->arch.max_pfn)) {
+            DPRINTF("calculated max_pfn as %#lx, shinfo says %#lx\n",
+                    max_pfn, live_shinfo->arch.max_pfn);
+            ERROR("Max pfn doesn't match shared info");
+            goto out;
+        }
+
+        while( N < pfn_array_size ){
+
+            unsigned int this_pc = (N * 100) / pfn_array_size;
+            int rc;
 
             if ((this_pc - prev_pc) >= 5) {
                 DPRINTF("\b\b\b\b%3d%%", this_pc);
@@ -476,9 +528,9 @@ int xc_hvm_save(int xc_handle, int io_fd
 
             /* slightly wasteful to peek the whole array evey time,
                but this is fast enough for the moment. */
-            if (!last_iter && xc_shadow_control(
-                    xc_handle, dom, XEN_DOMCTL_SHADOW_OP_PEEK,
-                    to_skip, max_pfn, NULL, 0, NULL) != max_pfn) {
+            if (!last_iter && (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;
             }
@@ -486,11 +538,11 @@ int xc_hvm_save(int xc_handle, int io_fd
 
             /* load pfn_batch[] with the mfn of all the pages we're doing in
                this batch. */
-            for (batch = 0; batch < MAX_BATCH_SIZE && N < max_pfn ; N++) {
-
-                int n = permute(N, max_pfn, order_nr);
-
-                if (debug) {
+            for (batch = 0; batch < MAX_BATCH_SIZE && N < pfn_array_size; N++){
+
+                int n = permute(N, pfn_array_size, order_nr);
+
+                if (0&&debug) {
                     DPRINTF("%d pfn= %08lx %d \n",
                             iter, (unsigned long)n, test_bit(n, to_send));
                 }
@@ -505,7 +557,10 @@ int xc_hvm_save(int xc_handle, int io_fd
                 /* 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 < (1ULL << 32) >> PAGE_SHIFT) /* 4G MMIO hole */
+                    || n == store_pfn
+                    || n == ioreq_pfn
+                    || n == bufioreq_pfn)
                     continue;
 
                 /*
@@ -570,7 +625,7 @@ int xc_hvm_save(int xc_handle, int io_fd
             print_stats( xc_handle, dom, sent_this_iter, &stats, 1);
 
             DPRINTF("Total pages sent= %ld (%.2fx)\n",
-                    total_sent, ((float)total_sent)/max_pfn );
+                    total_sent, ((float)total_sent)/pfn_array_size );
         }
 
         if (last_iter && debug){
@@ -597,7 +652,7 @@ int xc_hvm_save(int xc_handle, int io_fd
                 ((sent_this_iter > sent_last_iter) && RATE_IS_MAX()) ||
                 (iter >= max_iters) ||
                 (sent_this_iter+skip_this_iter < 50) ||
-                (total_sent > max_pfn*max_factor) ) {
+                (total_sent > pfn_array_size*max_factor) ) {
 
                 DPRINTF("Start last iteration for HVM domain\n");
                 last_iter = 1;
@@ -616,7 +671,8 @@ int xc_hvm_save(int xc_handle, int io_fd
 
             if (xc_shadow_control(xc_handle, dom, 
                                   XEN_DOMCTL_SHADOW_OP_CLEAN, to_send, 
-                                  max_pfn, NULL, 0, &stats) != max_pfn) {
+                                  pfn_array_size, NULL, 
+                                  0, &stats) != pfn_array_size) {
                 ERROR("Error flushing shadow PT");
                 goto out;
             }
@@ -640,20 +696,6 @@ int xc_hvm_save(int xc_handle, int io_fd
         goto out;
     }
 
-    if ( (rec_size = xc_domain_hvm_getcontext(xc_handle, dom, hvm_buf, 
-                                              hvm_buf_size)) == -1) {
-        ERROR("HVM:Could not get hvm buffer");
-        goto out;
-    }
-
-    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) ) {
-        ERROR("write HVM info failed!\n");
-    }
 
     /* save vcpu/vmcs context */
     if (!write_exact(io_fd, &nr_vcpus, sizeof(uint32_t))) {
@@ -682,6 +724,21 @@ int xc_hvm_save(int xc_handle, int io_fd
         }
     }
 
+    if ( (rec_size = xc_domain_hvm_getcontext(xc_handle, dom, hvm_buf, 
+                                              hvm_buf_size)) == -1) {
+        ERROR("HVM:Could not get hvm buffer");
+        goto out;
+    }
+
+    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) ) {
+        ERROR("write HVM info failed!\n");
+    }
+
     /* Shared-info pfn */
     if (!write_exact(io_fd, &(shared_info_frame), sizeof(uint32_t)) ) {
         ERROR("write shared-info pfn failed!\n");
diff -r d1853a39e063 -r cb2575cec95c tools/libxc/xc_misc.c
--- a/tools/libxc/xc_misc.c     Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxc/xc_misc.c     Mon Mar 12 10:07:08 2007 -0600
@@ -29,6 +29,25 @@ int xc_readconsolering(int xc_handle,
         *pnr_chars = sysctl.u.readconsole.count;
 
     unlock_pages(buffer, nr_chars);
+
+    return ret;
+}
+
+int xc_send_debug_keys(int xc_handle, char *keys)
+{
+    int ret, len = strlen(keys);
+    DECLARE_SYSCTL;
+
+    sysctl.cmd = XEN_SYSCTL_debug_keys;
+    set_xen_guest_handle(sysctl.u.debug_keys.keys, keys);
+    sysctl.u.debug_keys.nr_keys = len;
+
+    if ( (ret = lock_pages(keys, len)) != 0 )
+        return ret;
+
+    ret = do_sysctl(xc_handle, &sysctl);
+
+    unlock_pages(keys, len);
 
     return ret;
 }
diff -r d1853a39e063 -r cb2575cec95c tools/libxc/xc_private.c
--- a/tools/libxc/xc_private.c  Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxc/xc_private.c  Mon Mar 12 10:07:08 2007 -0600
@@ -23,7 +23,7 @@ void xc_default_error_handler(const xc_e
     fprintf(stderr, "ERROR %s: %s\n", desc, err->message);
 }
 
-const xc_error const *xc_get_last_error(void)
+const xc_error *xc_get_last_error(void)
 {
     return &last_error;
 }
diff -r d1853a39e063 -r cb2575cec95c tools/libxc/xc_ptrace_core.c
--- a/tools/libxc/xc_ptrace_core.c      Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxc/xc_ptrace_core.c      Mon Mar 12 10:07:08 2007 -0600
@@ -390,7 +390,6 @@ map_gmfn_to_offset_elf(unsigned long gmf
 {
     /* 
      * linear search
-     * There is no gurantee that those tables are sorted.
      */
     unsigned long i;
     if (current_is_auto_translated_physmap) {
diff -r d1853a39e063 -r cb2575cec95c tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h     Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxc/xenctrl.h     Mon Mar 12 10:07:08 2007 -0600
@@ -467,6 +467,8 @@ int xc_readconsolering(int xc_handle,
                        unsigned int *pnr_chars,
                        int clear);
 
+int xc_send_debug_keys(int xc_handle, char *keys);
+
 typedef xen_sysctl_physinfo_t xc_physinfo_t;
 int xc_physinfo(int xc_handle,
                 xc_physinfo_t *info);
@@ -770,19 +772,19 @@ typedef struct {
  * data pointed to are only valid until the next call to
  * libxc.
  */
-const xc_error const *xc_get_last_error(void);
+const xc_error *xc_get_last_error(void);
 
 /*
  * Clear the last error
  */
 void xc_clear_last_error(void);
 
-typedef void (*xc_error_handler)(const xc_error const* err);
+typedef void (*xc_error_handler)(const xc_error * const err);
 
 /*
  * The default error handler which prints to stderr
  */
-void xc_default_error_handler(const xc_error const* err);
+void xc_default_error_handler(const xc_error * const err);
 
 /*
  * Convert an error code into a text description
diff -r d1853a39e063 -r cb2575cec95c tools/libxc/xenguest.h
--- a/tools/libxc/xenguest.h    Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxc/xenguest.h    Mon Mar 12 10:07:08 2007 -0600
@@ -12,6 +12,7 @@
 #define XCFLAGS_LIVE      1
 #define XCFLAGS_DEBUG     2
 #define XCFLAGS_HVM       4
+#define XCFLAGS_STDVGA    8
 
 
 /**
@@ -155,6 +156,8 @@ 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 d1853a39e063 -r cb2575cec95c tools/libxc/xg_private.c
--- a/tools/libxc/xg_private.c  Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxc/xg_private.c  Mon Mar 12 10:07:08 2007 -0600
@@ -225,6 +225,11 @@ __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 d1853a39e063 -r cb2575cec95c tools/libxen/include/xen_crashdump.h
--- a/tools/libxen/include/xen_crashdump.h      Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxen/include/xen_crashdump.h      Mon Mar 12 10:07:08 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
@@ -162,20 +162,6 @@ xen_crashdump_get_by_uuid(xen_session *s
 
 
 /**
- * Create a new crashdump instance, and return its handle.
- */
-extern bool
-xen_crashdump_create(xen_session *session, xen_crashdump *result, 
xen_crashdump_record *record);
-
-
-/**
- * Destroy the specified crashdump instance.
- */
-extern bool
-xen_crashdump_destroy(xen_session *session, xen_crashdump crashdump);
-
-
-/**
  * Get the uuid field of the given crashdump.
  */
 extern bool
@@ -197,6 +183,13 @@ xen_crashdump_get_vdi(xen_session *sessi
 
 
 /**
+ * Destroy the specified crashdump
+ */
+extern bool
+xen_crashdump_destroy(xen_session *session, xen_crashdump self);
+
+
+/**
  * Return a list of all the crashdumps known to the system.
  */
 extern bool
diff -r d1853a39e063 -r cb2575cec95c tools/libxen/include/xen_vbd.h
--- a/tools/libxen/include/xen_vbd.h    Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxen/include/xen_vbd.h    Mon Mar 12 10:07:08 2007 -0600
@@ -358,6 +358,22 @@ xen_vbd_media_change(xen_session *sessio
 
 
 /**
+ * Hotplug the specified VBD, dynamically attaching it to the running
+ * VM
+ */
+extern bool
+xen_vbd_plug(xen_session *session, xen_vbd self);
+
+
+/**
+ * Hot-unplug the specified VBD, dynamically unattaching it from the
+ * running VM
+ */
+extern bool
+xen_vbd_unplug(xen_session *session, xen_vbd self);
+
+
+/**
  * Return a list of all the VBDs known to the system.
  */
 extern bool
diff -r d1853a39e063 -r cb2575cec95c tools/libxen/include/xen_vdi.h
--- a/tools/libxen/include/xen_vdi.h    Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxen/include/xen_vdi.h    Mon Mar 12 10:07:08 2007 -0600
@@ -293,13 +293,6 @@ xen_vdi_set_name_description(xen_session
 
 
 /**
- * Set the SR field of the given VDI.
- */
-extern bool
-xen_vdi_set_sr(xen_session *session, xen_vdi vdi, xen_sr sr);
-
-
-/**
  * Set the virtual_size field of the given VDI.
  */
 extern bool
diff -r d1853a39e063 -r cb2575cec95c tools/libxen/include/xen_vif.h
--- a/tools/libxen/include/xen_vif.h    Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxen/include/xen_vif.h    Mon Mar 12 10:07:08 2007 -0600
@@ -332,6 +332,22 @@ xen_vif_remove_from_qos_algorithm_params
 
 
 /**
+ * Hotplug the specified VIF, dynamically attaching it to the running
+ * VM
+ */
+extern bool
+xen_vif_plug(xen_session *session, xen_vif self);
+
+
+/**
+ * Hot-unplug the specified VIF, dynamically unattaching it from the
+ * running VM
+ */
+extern bool
+xen_vif_unplug(xen_session *session, xen_vif self);
+
+
+/**
  * Return a list of all the VIFs known to the system.
  */
 extern bool
diff -r d1853a39e063 -r cb2575cec95c tools/libxen/include/xen_vm.h
--- a/tools/libxen/include/xen_vm.h     Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxen/include/xen_vm.h     Mon Mar 12 10:07:08 2007 -0600
@@ -40,39 +40,6 @@
  * The VM class.
  * 
  * A virtual machine (or 'guest').
- * 
- * VM booting is controlled by setting one of the two mutually exclusive
- * groups: "PV", and "HVM".  If HVM.boot_policy is the empty string, then
- * paravirtual domain building and booting will be used; otherwise the VM will
- * be loaded as an HVM domain, and booted using an emulated BIOS.
- * 
- * When paravirtual booting is in use, the PV/bootloader field indicates the
- * bootloader to use.  It may be "pygrub", in which case the platform's
- * default installation of pygrub will be used, or a full path within the
- * control domain to some other bootloader.  The other fields, PV/kernel,
- * PV/ramdisk, PV/args and PV/bootloader_args will be passed to the bootloader
- * unmodified, and interpretation of those fields is then specific to the
- * bootloader itself, including the possibility that the bootloader will
- * ignore some or all of those given values. Finally the paths of all bootable
- * disks are added to the bootloader commandline (a disk is bootable if its
- * VBD has the bootable flag set). There may be zero, one or many bootable
- * disks; the bootloader decides which disk (if any) to boot from.
- * 
- * If the bootloader is pygrub, then the menu.lst is parsed if present in the
- * guest's filesystem, otherwise the specified kernel and ramdisk are used, or
- * an autodetected kernel is used if nothing is specified and autodetection is
- * possible.  PV/args is appended to the kernel command line, no matter which
- * mechanism is used for finding the kernel.
- * 
- * If PV/bootloader is empty but PV/kernel is specified, then the kernel and
- * ramdisk values will be treated as paths within the control domain.  If both
- * PV/bootloader and PV/kernel are empty, then the behaviour is as if
- * PV/bootloader was specified as "pygrub".
- * 
- * When using HVM booting, HVM/boot_policy and HVM/boot_params specify the
- * boot handling.  Only one policy is currently defined: "BIOS order".  In
- * this case, HVM/boot_params should contain one key-value pair "order" = "N"
- * where N is the string that will be passed to QEMU..
  */
 
 
@@ -139,11 +106,7 @@ typedef struct xen_vm_record
     char *pv_bootloader_args;
     char *hvm_boot_policy;
     xen_string_string_map *hvm_boot_params;
-    bool platform_std_vga;
-    char *platform_serial;
-    bool platform_localtime;
-    bool platform_clock_offset;
-    bool platform_enable_audio;
+    xen_string_string_map *platform;
     char *pci_bus;
     xen_string_string_map *other_config;
     int64_t domid;
@@ -493,38 +456,10 @@ xen_vm_get_hvm_boot_params(xen_session *
 
 
 /**
- * Get the platform/std_VGA field of the given VM.
- */
-extern bool
-xen_vm_get_platform_std_vga(xen_session *session, bool *result, xen_vm vm);
-
-
-/**
- * Get the platform/serial field of the given VM.
- */
-extern bool
-xen_vm_get_platform_serial(xen_session *session, char **result, xen_vm vm);
-
-
-/**
- * Get the platform/localtime field of the given VM.
- */
-extern bool
-xen_vm_get_platform_localtime(xen_session *session, bool *result, xen_vm vm);
-
-
-/**
- * Get the platform/clock_offset field of the given VM.
- */
-extern bool
-xen_vm_get_platform_clock_offset(xen_session *session, bool *result, xen_vm 
vm);
-
-
-/**
- * Get the platform/enable_audio field of the given VM.
- */
-extern bool
-xen_vm_get_platform_enable_audio(xen_session *session, bool *result, xen_vm 
vm);
+ * Get the platform field of the given VM.
+ */
+extern bool
+xen_vm_get_platform(xen_session *session, xen_string_string_map **result, 
xen_vm vm);
 
 
 /**
@@ -765,38 +700,32 @@ xen_vm_remove_from_hvm_boot_params(xen_s
 
 
 /**
- * Set the platform/std_VGA field of the given VM.
- */
-extern bool
-xen_vm_set_platform_std_vga(xen_session *session, xen_vm vm, bool std_vga);
-
-
-/**
- * Set the platform/serial field of the given VM.
- */
-extern bool
-xen_vm_set_platform_serial(xen_session *session, xen_vm vm, char *serial);
-
-
-/**
- * Set the platform/localtime field of the given VM.
- */
-extern bool
-xen_vm_set_platform_localtime(xen_session *session, xen_vm vm, bool localtime);
-
-
-/**
- * Set the platform/clock_offset field of the given VM.
- */
-extern bool
-xen_vm_set_platform_clock_offset(xen_session *session, xen_vm vm, bool 
clock_offset);
-
-
-/**
- * Set the platform/enable_audio field of the given VM.
- */
-extern bool
-xen_vm_set_platform_enable_audio(xen_session *session, xen_vm vm, bool 
enable_audio);
+ * Set the platform field of the given VM.
+ */
+extern bool
+xen_vm_set_platform(xen_session *session, xen_vm vm, xen_string_string_map 
*platform);
+
+
+/**
+ * Add the given key-value pair to the platform field of the given VM.
+ */
+extern bool
+xen_vm_add_to_platform(xen_session *session, xen_vm vm, char *key, char 
*value);
+
+
+/**
+ * Remove the given key and its corresponding value from the platform
+ * field of the given VM.  If the key is not in that Map, then do nothing.
+ */
+extern bool
+xen_vm_remove_from_platform(xen_session *session, xen_vm vm, char *key);
+
+
+/**
+ * Set the PCI_bus field of the given VM.
+ */
+extern bool
+xen_vm_set_pci_bus(xen_session *session, xen_vm vm, char *pci_bus);
 
 
 /**
diff -r d1853a39e063 -r cb2575cec95c tools/libxen/src/xen_common.c
--- a/tools/libxen/src/xen_common.c     Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxen/src/xen_common.c     Mon Mar 12 10:07:08 2007 -0600
@@ -110,7 +110,7 @@ static size_t size_of_member(const abstr
 static size_t size_of_member(const abstract_type *);
 
 static const char *
-get_val_as_string(const struct abstract_type *, void *, char *);
+get_val_as_string(const struct abstract_type *, void *, char *, size_t);
 
 
 void
@@ -666,8 +666,7 @@ static void parse_into(xen_session *s, x
     {
         if (!is_container_node(value_node, "value") ||
             value_node->children->type != XML_ELEMENT_NODE ||
-            0 != strcmp((char *)value_node->children->name, "struct") ||
-            value_node->children->children == NULL)
+            0 != strcmp((char *)value_node->children->name, "struct"))
         {
             server_error(s,
                          "Expected Map from the server, but didn't get it");
@@ -890,6 +889,9 @@ static size_t size_of_member(const abstr
     case REF:
         return sizeof(arbitrary_record_opt *);
 
+    case STRUCT:
+        return type->struct_size;
+
     default:
         assert(false);
     }
@@ -1183,7 +1185,8 @@ add_struct_value(const struct abstract_t
     case INT:
     case ENUM:
     {
-        const char *val_as_string = get_val_as_string(type, value, buf);
+        const char *val_as_string =
+            get_val_as_string(type, value, buf, sizeof(buf));
         adder(node, key, "string", val_as_string);
     }
     break;
@@ -1215,7 +1218,8 @@ add_struct_value(const struct abstract_t
 
             for (size_t i = 0; i < set_val->size; i++)
             {
-                void *member_value = set_val->contents + (i * member_size);
+                void *member_value = (char *)set_val->contents +
+                                     (i * member_size);
                 add_struct_value(member_type, member_value,
                                  add_unnamed_value, NULL, data_node);
             }
@@ -1254,7 +1258,7 @@ add_struct_value(const struct abstract_t
                 void *r_value = contents + (i * member_size) + r_offset;
 
                 const char *l_value_as_string =
-                    get_val_as_string(l_type, l_value, buf);
+                    get_val_as_string(l_type, l_value, buf, sizeof(buf));
 
                 add_struct_value(r_type, r_value, add_struct_member,
                                  l_value_as_string, struct_node);
@@ -1270,7 +1274,8 @@ add_struct_value(const struct abstract_t
 
 
 static const char *
-get_val_as_string(const struct abstract_type *type, void *value, char *buf)
+get_val_as_string(const struct abstract_type *type, void *value, char *buf,
+                  size_t bufsize)
 {
     switch (type->typename)
     {
@@ -1304,7 +1309,7 @@ get_val_as_string(const struct abstract_
     case INT:
     {
         int64_t val = *(int64_t *)value;
-        snprintf(buf, sizeof(buf), "%"PRId64, val);
+        snprintf(buf, bufsize, "%"PRId64, val);
         return buf;
     }
     break;
diff -r d1853a39e063 -r cb2575cec95c tools/libxen/src/xen_crashdump.c
--- a/tools/libxen/src/xen_crashdump.c  Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxen/src/xen_crashdump.c  Mon Mar 12 10:07:08 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
@@ -115,37 +115,6 @@ xen_crashdump_get_by_uuid(xen_session *s
 
 
 bool
-xen_crashdump_create(xen_session *session, xen_crashdump *result, 
xen_crashdump_record *record)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &xen_crashdump_record_abstract_type_,
-              .u.struct_val = record }
-        };
-
-    abstract_type result_type = abstract_type_string;
-
-    *result = NULL;
-    XEN_CALL_("crashdump.create");
-    return session->ok;
-}
-
-
-bool
-xen_crashdump_destroy(xen_session *session, xen_crashdump crashdump)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &abstract_type_string,
-              .u.string_val = crashdump }
-        };
-
-    xen_call_(session, "crashdump.destroy", param_values, 1, NULL, NULL);
-    return session->ok;
-}
-
-
-bool
 xen_crashdump_get_vm(xen_session *session, xen_vm *result, xen_crashdump 
crashdump)
 {
     abstract_value param_values[] =
@@ -180,6 +149,20 @@ xen_crashdump_get_vdi(xen_session *sessi
 
 
 bool
+xen_crashdump_destroy(xen_session *session, xen_crashdump self)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = self }
+        };
+
+    xen_call_(session, "crashdump.destroy", param_values, 1, NULL, NULL);
+    return session->ok;
+}
+
+
+bool
 xen_crashdump_get_all(xen_session *session, struct xen_crashdump_set **result)
 {
 
diff -r d1853a39e063 -r cb2575cec95c tools/libxen/src/xen_vbd.c
--- a/tools/libxen/src/xen_vbd.c        Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxen/src/xen_vbd.c        Mon Mar 12 10:07:08 2007 -0600
@@ -552,6 +552,34 @@ xen_vbd_media_change(xen_session *sessio
 
 
 bool
+xen_vbd_plug(xen_session *session, xen_vbd self)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = self }
+        };
+
+    xen_call_(session, "VBD.plug", param_values, 1, NULL, NULL);
+    return session->ok;
+}
+
+
+bool
+xen_vbd_unplug(xen_session *session, xen_vbd self)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = self }
+        };
+
+    xen_call_(session, "VBD.unplug", param_values, 1, NULL, NULL);
+    return session->ok;
+}
+
+
+bool
 xen_vbd_get_all(xen_session *session, struct xen_vbd_set **result)
 {
 
diff -r d1853a39e063 -r cb2575cec95c tools/libxen/src/xen_vdi.c
--- a/tools/libxen/src/xen_vdi.c        Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxen/src/xen_vdi.c        Mon Mar 12 10:07:08 2007 -0600
@@ -410,22 +410,6 @@ xen_vdi_set_name_description(xen_session
 
 
 bool
-xen_vdi_set_sr(xen_session *session, xen_vdi vdi, xen_sr sr)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &abstract_type_string,
-              .u.string_val = vdi },
-            { .type = &abstract_type_string,
-              .u.string_val = sr }
-        };
-
-    xen_call_(session, "VDI.set_SR", param_values, 2, NULL, NULL);
-    return session->ok;
-}
-
-
-bool
 xen_vdi_set_virtual_size(xen_session *session, xen_vdi vdi, int64_t 
virtual_size)
 {
     abstract_value param_values[] =
diff -r d1853a39e063 -r cb2575cec95c tools/libxen/src/xen_vif.c
--- a/tools/libxen/src/xen_vif.c        Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxen/src/xen_vif.c        Mon Mar 12 10:07:08 2007 -0600
@@ -500,6 +500,34 @@ xen_vif_remove_from_qos_algorithm_params
 
 
 bool
+xen_vif_plug(xen_session *session, xen_vif self)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = self }
+        };
+
+    xen_call_(session, "VIF.plug", param_values, 1, NULL, NULL);
+    return session->ok;
+}
+
+
+bool
+xen_vif_unplug(xen_session *session, xen_vif self)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = self }
+        };
+
+    xen_call_(session, "VIF.unplug", param_values, 1, NULL, NULL);
+    return session->ok;
+}
+
+
+bool
 xen_vif_get_all(xen_session *session, struct xen_vif_set **result)
 {
 
diff -r d1853a39e063 -r cb2575cec95c tools/libxen/src/xen_vm.c
--- a/tools/libxen/src/xen_vm.c Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxen/src/xen_vm.c Mon Mar 12 10:07:08 2007 -0600
@@ -145,21 +145,9 @@ static const struct_member xen_vm_record
         { .key = "HVM_boot_params",
           .type = &abstract_type_string_string_map,
           .offset = offsetof(xen_vm_record, hvm_boot_params) },
-        { .key = "platform_std_VGA",
-          .type = &abstract_type_bool,
-          .offset = offsetof(xen_vm_record, platform_std_vga) },
-        { .key = "platform_serial",
-          .type = &abstract_type_string,
-          .offset = offsetof(xen_vm_record, platform_serial) },
-        { .key = "platform_localtime",
-          .type = &abstract_type_bool,
-          .offset = offsetof(xen_vm_record, platform_localtime) },
-        { .key = "platform_clock_offset",
-          .type = &abstract_type_bool,
-          .offset = offsetof(xen_vm_record, platform_clock_offset) },
-        { .key = "platform_enable_audio",
-          .type = &abstract_type_bool,
-          .offset = offsetof(xen_vm_record, platform_enable_audio) },
+        { .key = "platform",
+          .type = &abstract_type_string_string_map,
+          .offset = offsetof(xen_vm_record, platform) },
         { .key = "PCI_bus",
           .type = &abstract_type_string,
           .offset = offsetof(xen_vm_record, pci_bus) },
@@ -217,7 +205,7 @@ xen_vm_record_free(xen_vm_record *record
     free(record->pv_bootloader_args);
     free(record->hvm_boot_policy);
     xen_string_string_map_free(record->hvm_boot_params);
-    free(record->platform_serial);
+    xen_string_string_map_free(record->platform);
     free(record->pci_bus);
     xen_string_string_map_free(record->other_config);
     xen_vm_metrics_record_opt_free(record->metrics);
@@ -825,82 +813,18 @@ xen_vm_get_hvm_boot_params(xen_session *
 
 
 bool
-xen_vm_get_platform_std_vga(xen_session *session, bool *result, xen_vm vm)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &abstract_type_string,
-              .u.string_val = vm }
-        };
-
-    abstract_type result_type = abstract_type_bool;
-
-    XEN_CALL_("VM.get_platform_std_VGA");
-    return session->ok;
-}
-
-
-bool
-xen_vm_get_platform_serial(xen_session *session, char **result, xen_vm vm)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &abstract_type_string,
-              .u.string_val = vm }
-        };
-
-    abstract_type result_type = abstract_type_string;
-
-    *result = NULL;
-    XEN_CALL_("VM.get_platform_serial");
-    return session->ok;
-}
-
-
-bool
-xen_vm_get_platform_localtime(xen_session *session, bool *result, xen_vm vm)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &abstract_type_string,
-              .u.string_val = vm }
-        };
-
-    abstract_type result_type = abstract_type_bool;
-
-    XEN_CALL_("VM.get_platform_localtime");
-    return session->ok;
-}
-
-
-bool
-xen_vm_get_platform_clock_offset(xen_session *session, bool *result, xen_vm vm)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &abstract_type_string,
-              .u.string_val = vm }
-        };
-
-    abstract_type result_type = abstract_type_bool;
-
-    XEN_CALL_("VM.get_platform_clock_offset");
-    return session->ok;
-}
-
-
-bool
-xen_vm_get_platform_enable_audio(xen_session *session, bool *result, xen_vm vm)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &abstract_type_string,
-              .u.string_val = vm }
-        };
-
-    abstract_type result_type = abstract_type_bool;
-
-    XEN_CALL_("VM.get_platform_enable_audio");
+xen_vm_get_platform(xen_session *session, xen_string_string_map **result, 
xen_vm vm)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vm }
+        };
+
+    abstract_type result_type = abstract_type_string_string_map;
+
+    *result = NULL;
+    XEN_CALL_("VM.get_platform");
     return session->ok;
 }
 
@@ -1442,81 +1366,67 @@ xen_vm_remove_from_hvm_boot_params(xen_s
 
 
 bool
-xen_vm_set_platform_std_vga(xen_session *session, xen_vm vm, bool std_vga)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &abstract_type_string,
-              .u.string_val = vm },
-            { .type = &abstract_type_bool,
-              .u.bool_val = std_vga }
-        };
-
-    xen_call_(session, "VM.set_platform_std_VGA", param_values, 2, NULL, NULL);
-    return session->ok;
-}
-
-
-bool
-xen_vm_set_platform_serial(xen_session *session, xen_vm vm, char *serial)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &abstract_type_string,
-              .u.string_val = vm },
-            { .type = &abstract_type_string,
-              .u.string_val = serial }
-        };
-
-    xen_call_(session, "VM.set_platform_serial", param_values, 2, NULL, NULL);
-    return session->ok;
-}
-
-
-bool
-xen_vm_set_platform_localtime(xen_session *session, xen_vm vm, bool localtime)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &abstract_type_string,
-              .u.string_val = vm },
-            { .type = &abstract_type_bool,
-              .u.bool_val = localtime }
-        };
-
-    xen_call_(session, "VM.set_platform_localtime", param_values, 2, NULL, 
NULL);
-    return session->ok;
-}
-
-
-bool
-xen_vm_set_platform_clock_offset(xen_session *session, xen_vm vm, bool 
clock_offset)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &abstract_type_string,
-              .u.string_val = vm },
-            { .type = &abstract_type_bool,
-              .u.bool_val = clock_offset }
-        };
-
-    xen_call_(session, "VM.set_platform_clock_offset", param_values, 2, NULL, 
NULL);
-    return session->ok;
-}
-
-
-bool
-xen_vm_set_platform_enable_audio(xen_session *session, xen_vm vm, bool 
enable_audio)
-{
-    abstract_value param_values[] =
-        {
-            { .type = &abstract_type_string,
-              .u.string_val = vm },
-            { .type = &abstract_type_bool,
-              .u.bool_val = enable_audio }
-        };
-
-    xen_call_(session, "VM.set_platform_enable_audio", param_values, 2, NULL, 
NULL);
+xen_vm_set_platform(xen_session *session, xen_vm vm, xen_string_string_map 
*platform)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vm },
+            { .type = &abstract_type_string_string_map,
+              .u.set_val = (arbitrary_set *)platform }
+        };
+
+    xen_call_(session, "VM.set_platform", param_values, 2, NULL, NULL);
+    return session->ok;
+}
+
+
+bool
+xen_vm_add_to_platform(xen_session *session, xen_vm vm, char *key, char *value)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vm },
+            { .type = &abstract_type_string,
+              .u.string_val = key },
+            { .type = &abstract_type_string,
+              .u.string_val = value }
+        };
+
+    xen_call_(session, "VM.add_to_platform", param_values, 3, NULL, NULL);
+    return session->ok;
+}
+
+
+bool
+xen_vm_remove_from_platform(xen_session *session, xen_vm vm, char *key)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vm },
+            { .type = &abstract_type_string,
+              .u.string_val = key }
+        };
+
+    xen_call_(session, "VM.remove_from_platform", param_values, 2, NULL, NULL);
+    return session->ok;
+}
+
+
+bool
+xen_vm_set_pci_bus(xen_session *session, xen_vm vm, char *pci_bus)
+{
+    abstract_value param_values[] =
+        {
+            { .type = &abstract_type_string,
+              .u.string_val = vm },
+            { .type = &abstract_type_string,
+              .u.string_val = pci_bus }
+        };
+
+    xen_call_(session, "VM.set_PCI_bus", param_values, 2, NULL, NULL);
     return session->ok;
 }
 
diff -r d1853a39e063 -r cb2575cec95c tools/libxen/test/test_bindings.c
--- a/tools/libxen/test/test_bindings.c Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxen/test/test_bindings.c Mon Mar 12 10:07:08 2007 -0600
@@ -375,6 +375,8 @@ static xen_vm create_new_vm(xen_session 
             .memory_static_min = 128,
             .vcpus_policy = "credit",
             .vcpus_params = vcpus_params,
+            .vcpus_max = 4,
+            .vcpus_at_startup = 2,
             .actions_after_shutdown = XEN_ON_NORMAL_EXIT_DESTROY,
             .actions_after_reboot = XEN_ON_NORMAL_EXIT_RESTART,
             .actions_after_crash = XEN_ON_CRASH_BEHAVIOUR_PRESERVE,
diff -r d1853a39e063 -r cb2575cec95c tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/python/xen/lowlevel/xc/xc.c Mon Mar 12 10:07:08 2007 -0600
@@ -47,7 +47,7 @@ static PyObject *pyxc_error_to_exception
 static PyObject *pyxc_error_to_exception(void)
 {
     PyObject *pyerr;
-    const xc_error const *err = xc_get_last_error();
+    const xc_error *err = xc_get_last_error();
     const char *desc = xc_error_code_to_desc(err->code);
 
     if (err->code == XC_ERROR_NONE)
@@ -1007,6 +1007,24 @@ static PyObject *pyxc_domain_send_trigge
     return zero;
 }
 
+static PyObject *pyxc_send_debug_keys(XcObject *self,
+                                      PyObject *args,
+                                      PyObject *kwds)
+{
+    char *keys;
+
+    static char *kwd_list[] = { "keys", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "s", kwd_list, &keys) )
+        return NULL;
+
+    if ( xc_send_debug_keys(self->xc_handle, keys) != 0 )
+        return pyxc_error_to_exception();
+
+    Py_INCREF(zero);
+    return zero;
+}
+
 static PyObject *dom_op(XcObject *self, PyObject *args,
                         int (*fn)(int, uint32_t))
 {
@@ -1419,6 +1437,12 @@ static PyMethodDef pyxc_methods[] = {
       " trigger [int]: Trigger type number.\n"
       " vcpu    [int]: VCPU to be sent trigger.\n"
       "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "send_debug_keys",
+      (PyCFunction)pyxc_send_debug_keys,
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Inject debug keys into Xen.\n"
+      " keys    [str]: String of keys to inject.\n" },
 
 #ifdef __powerpc__
     { "arch_alloc_real_mode_area", 
diff -r d1853a39e063 -r cb2575cec95c tools/python/xen/xend/XendAPI.py
--- a/tools/python/xen/xend/XendAPI.py  Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/python/xen/xend/XendAPI.py  Mon Mar 12 10:07:08 2007 -0600
@@ -676,8 +676,9 @@ class XendAPI(object):
         return xen_api_success_void()
     def host_remove_from_other_config(self, session, host_ref, key):
         node = XendNode.instance()
-        del node.other_config[key]
-        node.save()
+        if key in node.other_config:
+            del node.other_config[key]
+            node.save()
         return xen_api_success_void()
     def host_get_API_version_major(self, _, ref):
         return xen_api_success(XEN_API_VERSION_MAJOR)
@@ -998,7 +999,6 @@ class XendAPI(object):
                   'VIFs',
                   'VBDs',
                   'VTPMs',
-                  'PCI_bus',
                   'tools_version',
                   'domid',
                   'is_control_domain',
@@ -1024,12 +1024,8 @@ class XendAPI(object):
                   'PV_bootloader_args',
                   'HVM_boot_policy',
                   'HVM_boot_params',
-                  'platform_std_VGA',
-                  'platform_serial',
-                  'platform_localtime',
-                  'platform_clock_offset',
-                  'platform_enable_audio',
-                  'platform_keymap',
+                  'platform',
+                  'PCI_bus',
                   'other_config']
 
     VM_methods = [('clone', 'VM'),
@@ -1042,6 +1038,10 @@ class XendAPI(object):
                   ('hard_reboot', None),
                   ('suspend', None),
                   ('resume', None),
+                  ('add_to_HVM_boot_params', None),
+                  ('remove_from_HVM_boot_params', None),
+                  ('add_to_platform', None),
+                  ('remove_from_platform', None),
                   ('add_to_other_config', None),
                   ('remove_from_other_config', None)]
     
@@ -1071,13 +1071,7 @@ class XendAPI(object):
         'PV_bootloader_args',
         'HVM_boot_policy',
         'HVM_boot_params',
-        'platform_std_VGA',
-        'platform_serial',
-        'platform_localtime',
-        'platform_clock_offset',
-        'platform_enable_audio',
-        'platform_keymap',
-        'grub_cmdline',
+        'platform',
         'PCI_bus',
         'other_config']
         
@@ -1089,7 +1083,10 @@ class XendAPI(object):
         xd = XendDomain.instance()
         dominfo = xd.get_vm_by_uuid(vm_ref)
         dominfo.info[name] = value
-        xd.managed_config_save(dominfo)
+        return self._VM_save(dominfo)
+
+    def _VM_save(self, dominfo):
+        XendDomain.instance().managed_config_save(dominfo)
         return xen_api_success_void()
 
     # attributes (ro)
@@ -1136,10 +1133,6 @@ class XendAPI(object):
         dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
         return xen_api_success(dom.get_consoles())
     
-    def VM_get_PCI_bus(self, session, vm_ref):
-        dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
-        return dom.get_pci_bus()
-    
     def VM_get_tools_version(self, session, vm_ref):
         dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
         return dom.get_tools_version()
@@ -1214,29 +1207,16 @@ class XendAPI(object):
     def VM_get_HVM_boot_params(self, session, vm_ref):
         return self.VM_get('HVM_boot_params', session, vm_ref)
     
-    def VM_get_platform_std_VGA(self, session, vm_ref):
-        dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
-        return xen_api_success(dom.get_platform_std_vga())
-    
-    def VM_get_platform_serial(self, session, vm_ref):
-        dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
-        return xen_api_success(dom.get_platform_serial())        
-    
-    def VM_get_platform_localtime(self, session, vm_ref):
-        dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
-        return xen_api_success(dom.get_platform_localtime())
-    
-    def VM_get_platform_clock_offset(self, session, vm_ref):
-        dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
-        return xen_api_success(dom.get_platform_clock_offset())        
-    
-    def VM_get_platform_enable_audio(self, session, vm_ref):
-        dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
-        return xen_api_success(dom.get_platform_enable_audio())        
-    
-    def VM_get_platform_keymap(self, session, vm_ref):
-        dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
-        return xen_api_success(dom.get_platform_keymap())
+    def VM_get_platform(self, session, vm_ref):
+        dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
+        return xen_api_success(dom.get_platform())
+    
+    def VM_get_PCI_bus(self, session, vm_ref):
+        dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
+        return dom.get_pci_bus()
+    
+    def VM_set_PCI_bus(self, session, vm_ref, val):
+        return self.VM_set('PCI_bus', session, vm_ref, val)
     
     def VM_get_other_config(self, session, vm_ref):
         return self.VM_get('other_config', session, vm_ref)        
@@ -1253,7 +1233,7 @@ class XendAPI(object):
     def VM_set_name_label(self, session, vm_ref, label):
         dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
         dom.setName(label)
-        return xen_api_success_void()
+        return self._VM_save(dom)
     
     def VM_set_name_description(self, session, vm_ref, desc):
         dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
@@ -1284,12 +1264,12 @@ class XendAPI(object):
         return xen_api_todo()
     
     def VM_set_actions_after_shutdown(self, session, vm_ref, action):
-        if action not in XEN_API_ON_NORMAL_EXIST:
+        if action not in XEN_API_ON_NORMAL_EXIT:
             return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
         return self.VM_set('actions_after_shutdown', session, vm_ref, action)
     
     def VM_set_actions_after_reboot(self, session, vm_ref, action):
-        if action not in XEN_API_ON_NORMAL_EXIST:
+        if action not in XEN_API_ON_NORMAL_EXIT:
             return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
         return self.VM_set('actions_after_reboot', session, vm_ref, action)
     
@@ -1319,14 +1299,16 @@ class XendAPI(object):
         if 'HVM_boot_params' not in dom.info:
             dom.info['HVM_boot_params'] = {}
         dom.info['HVM_boot_params'][key] = value
-        return xen_api_success_void()
+        return self._VM_save(dom)
 
     def VM_remove_from_HVM_boot_params(self, session, vm_ref, key):
         dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
         if 'HVM_boot_params' in dom.info \
                and key in dom.info['HVM_boot_params']:
             del dom.info['HVM_boot_params'][key]
-        return xen_api_success_void()
+            return self._VM_save(dom)
+        else:
+            return xen_api_success_void()
 
     def VM_set_PV_bootloader(self, session, vm_ref, value):
         return self.VM_set('PV_bootloader', session, vm_ref, value)
@@ -1343,40 +1325,42 @@ class XendAPI(object):
     def VM_set_PV_bootloader_args(self, session, vm_ref, value):
         return self.VM_set('PV_bootloader_args', session, vm_ref, value)
 
-    def VM_set_platform_std_VGA(self, session, vm_ref, value):
-        return self.VM_set('platform_std_vga', session, vm_ref, value)
-    
-    def VM_set_platform_serial(self, session, vm_ref, value):
-        return self.VM_set('platform_serial', session, vm_ref, value)
-
-    def VM_set_platform_keymap(self, session, vm_ref, value):
-        return self.VM_set('platform_keymap', session, vm_ref, value)
-    
-    def VM_set_platform_localtime(self, session, vm_ref, value):
-        return self.VM_set('platform_localtime', session, vm_ref, value)
-    
-    def VM_set_platform_clock_offset(self, session, vm_ref, value):
-        return self.VM_set('platform_clock_offset', session, vm_ref, value)
-    
-    def VM_set_platform_enable_audio(self, session, vm_ref, value):
-        return self.VM_set('platform_enable_audio', session, vm_ref, value)
-    
+    def VM_set_platform(self, session, vm_ref, value):
+        return self.VM_set('platform', session, vm_ref, value)
+    
+    def VM_add_to_platform(self, session, vm_ref, key, value):
+        dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
+        plat = dom.get_platform()
+        plat[key] = value
+        return self.VM_set_platform(session, vm_ref, plat)
+
+    def VM_remove_from_platform(self, session, vm_ref, key):
+        dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
+        plat = dom.get_platform()
+        if key in plat:
+            del plat[key]
+            return self.VM_set_platform(session, vm_ref, plat)
+        else:
+            return xen_api_success_void()
+
     def VM_set_other_config(self, session, vm_ref, value):
-        return self.VM_set('otherconfig', session, vm_ref, value)
+        return self.VM_set('other_config', session, vm_ref, value)
 
     def VM_add_to_other_config(self, session, vm_ref, key, value):
         dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
-        if dom and 'otherconfig' in dom.info:
-            dom.info['otherconfig'][key] = value
-        return xen_api_success_void()
+        if dom and 'other_config' in dom.info:
+            dom.info['other_config'][key] = value
+        return self._VM_save(dom)
 
     def VM_remove_from_other_config(self, session, vm_ref, key):
         dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
-        if dom and 'otherconfig' in dom.info \
-               and key in dom.info['otherconfig']:
-            del dom.info['otherconfig'][key]
-        return xen_api_success_void()        
-    
+        if dom and 'other_config' in dom.info \
+               and key in dom.info['other_config']:
+            del dom.info['other_config'][key]
+            return self._VM_save(dom)
+        else:
+            return xen_api_success_void()
+
     # class methods
     def VM_get_all(self, session):
         refs = [d.get_uuid() for d in XendDomain.instance().list('all')]
@@ -1437,12 +1421,7 @@ class XendAPI(object):
             'PV_bootloader_args': xeninfo.info.get('PV_bootloader_args'),
             'HVM_boot_policy': xeninfo.info.get('HVM_boot_policy'),
             'HVM_boot_params': xeninfo.info.get('HVM_boot_params'),
-            'platform_std_VGA': xeninfo.get_platform_std_vga(),
-            'platform_serial': xeninfo.get_platform_serial(),
-            'platform_localtime': xeninfo.get_platform_localtime(),
-            'platform_clock_offset': xeninfo.get_platform_clock_offset(),
-            'platform_enable_audio': xeninfo.get_platform_enable_audio(),
-            'platform_keymap': xeninfo.get_platform_keymap(),
+            'platform': xeninfo.get_platform(),
             'PCI_bus': xeninfo.get_pci_bus(),
             'tools_version': xeninfo.get_tools_version(),
             'other_config': xeninfo.info.get('other_config', {}),
@@ -1486,10 +1465,13 @@ class XendAPI(object):
                                      start_paused = start_paused)
     
     def VM_start(self, session, vm_ref, start_paused):
-        return XendTask.log_progress(0, 100, do_vm_func,
-                                     "domain_start", vm_ref,
-                                     start_paused = start_paused)
-    
+        try:
+            return XendTask.log_progress(0, 100, do_vm_func,
+                                         "domain_start", vm_ref,
+                                         start_paused = start_paused)
+        except HVMRequired, exn:
+            return xen_api_error(['VM_HVM_REQUIRED', vm_ref])
+
     def VM_suspend(self, session, vm_ref):
         return XendTask.log_progress(0, 100, do_vm_func,
                                      "domain_suspend", vm_ref)
@@ -1754,13 +1736,13 @@ class XendAPI(object):
 
     # Xen API: Class VDI
     # ----------------------------------------------------------------
-    VDI_attr_ro = ['VBDs',
+    VDI_attr_ro = ['SR',
+                   'VBDs',
                    'physical_utilisation',
                    'sector_size',
                    'type']
     VDI_attr_rw = ['name_label',
                    'name_description',
-                   'SR',
                    'virtual_size',
                    'sharable',
                    'read_only']
@@ -1811,9 +1793,6 @@ class XendAPI(object):
     def VDI_set_name_description(self, session, vdi_ref, value):
         self._get_VDI(vdi_ref).name_description = value
         return xen_api_success_void()
-
-    def VDI_set_SR(self, session, vdi_ref, value):
-        return xen_api_error(XEND_ERROR_UNSUPPORTED)
 
     def VDI_set_virtual_size(self, session, vdi_ref, value):
         return xen_api_error(XEND_ERROR_UNSUPPORTED)
@@ -1929,7 +1908,7 @@ class XendAPI(object):
                  XendDomain.POWER_STATE_NAMES[dom.state]])
             from xen.xend.server import tpmif
             tpmif.destroy_vtpmstate(dom.getName())
-            return xen_api_success(True)
+            return xen_api_success_void()
         else:
             return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
 
diff -r d1853a39e063 -r cb2575cec95c tools/python/xen/xend/XendCheckpoint.py
--- a/tools/python/xen/xend/XendCheckpoint.py   Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/python/xen/xend/XendCheckpoint.py   Mon Mar 12 10:07:08 2007 -0600
@@ -74,9 +74,13 @@ def save(fd, dominfo, network, live, dst
 
         image_cfg = dominfo.info.get('image', {})
         hvm = image_cfg.has_key('hvm')
+        stdvga = 0
 
         if hvm:
             log.info("save hvm domain")
+            if image_cfg['hvm']['devices']['stdvga'] == 1:
+                stdvga = 1
+
         # xc_save takes three customization parameters: maxit, max_f, and
         # flags the last controls whether or not save is 'live', while the
         # first two further customize behaviour when 'live' save is
@@ -84,7 +88,8 @@ def save(fd, dominfo, network, live, dst
         # libxenguest; see the comments and/or code in xc_linux_save() for
         # more information.
         cmd = [xen.util.auxbin.pathTo(XC_SAVE), str(fd),
-               str(dominfo.getDomid()), "0", "0", str(int(live) | (int(hvm) << 
2)) ]
+               str(dominfo.getDomid()), "0", "0", 
+               str(int(live) | (int(hvm) << 2) | (int(stdvga) << 3)) ]
         log.debug("[xc_save]: %s", string.join(cmd))
 
         def saveInputHandler(line, tochild):
diff -r d1853a39e063 -r cb2575cec95c tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py       Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/python/xen/xend/XendConfig.py       Mon Mar 12 10:07:08 2007 -0600
@@ -12,7 +12,7 @@
 # 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) 2006 XenSource Ltd
+# Copyright (C) 2006-2007 XenSource Ltd
 #============================================================================
 
 import logging
@@ -111,22 +111,18 @@ XENAPI_CFG_TO_LEGACY_CFG = {
     'actions_after_shutdown': 'on_poweroff',
     'actions_after_reboot': 'on_reboot',
     'actions_after_crash': 'on_crash', 
-    'platform_localtime': 'localtime',
     'PV_bootloader': 'bootloader',
     'PV_bootloader_args': 'bootloader_args',
 }
 
 LEGACY_CFG_TO_XENAPI_CFG = reverse_dict(XENAPI_CFG_TO_LEGACY_CFG)
 
-# Mapping from XendConfig configuration keys to the old
-# legacy configuration keys that are found in the 'image'
-# SXP object.
-XENAPI_HVM_CFG = {
-    'platform_std_vga': 'stdvga',
-    'platform_serial' : 'serial',
-    'platform_localtime': 'localtime',
-    'platform_keymap' : 'keymap'
-}    
+# Platform configuration keys.
+XENAPI_PLATFORM_CFG = [ 'acpi', 'apic', 'device_model', 'display', 'fda',
+                        'fdb', 'keymap', 'isa', 'localtime', 'nographic',
+                        'pae', 'serial', 'sdl', 'soundhw','stdvga', 'usb',
+                        'usbdevice', 'vnc', 'vncconsole', 'vncdisplay',
+                        'vnclisten', 'vncpasswd', 'vncunused', 'xauthority']
 
 # List of XendConfig configuration keys that have no direct equivalent
 # in the old world.
@@ -151,7 +147,6 @@ XENAPI_CFG_TYPES = {
     'actions_after_shutdown': str,
     'actions_after_reboot': str,
     'actions_after_crash': str,
-    'tpm_backend': int,    
     'PV_bootloader': str,
     'PV_kernel': str,
     'PV_ramdisk': str,
@@ -159,15 +154,10 @@ XENAPI_CFG_TYPES = {
     'PV_bootloader_args': str,
     'HVM_boot_policy': str,
     'HVM_boot_params': dict,
-    'platform_std_vga': bool0,
-    'platform_serial': str,
-    'platform_localtime': bool0,
-    'platform_clock_offset': bool0,
-    'platform_enable_audio': bool0,
-    'platform_keymap': str,
-    'pci_bus': str,
+    'PCI_bus': str,
+    'platform': dict,
     'tools_version': dict,
-    'otherconfig': dict,
+    'other_config': dict,
 }
 
 # List of legacy configuration keys that have no equivalent in the
@@ -237,44 +227,7 @@ LEGACY_XENSTORE_VM_PARAMS = [
     'on_xend_stop',
 ]
 
-LEGACY_IMAGE_CFG = [
-    ('root', str),
-    ('ip', str),
-    ('nographic', int),
-    ('vnc', int),
-    ('sdl', int),
-    ('vncdisplay', int),
-    ('vncunused', int),
-    ('vncpasswd', str),
-    ('vnclisten', str),
-]
-
-LEGACY_IMAGE_HVM_CFG = [
-    ('device_model', str),
-    ('display', str),
-    ('xauthority', str),
-    ('vncconsole', int),
-    ('pae', int),
-    ('apic', int),
-]
-
-LEGACY_IMAGE_HVM_DEVICES_CFG = [
-    ('acpi', int),    
-    ('boot', str),
-    ('fda', str),
-    ('fdb', str),
-    ('isa', int),
-    ('keymap', str),    
-    ('localtime', int),    
-    ('serial', str),
-    ('stdvga', int),
-    ('soundhw', str),
-    ('usb', int),
-    ('usbdevice', str),    
-    ('vcpus', int),
-]
-
-LEGACY_DM = '/usr/lib/xen/bin/qemu-dm'
+DEFAULT_DM = '/usr/lib/xen/bin/qemu-dm'
 
 ##
 ## Config Choices
@@ -316,7 +269,6 @@ class XendConfig(dict):
             self._sxp_to_xapi_unsupported(sxp_obj)
         elif xapi:
             self.update_with_xenapi_config(xapi)
-            self._add_xapi_unsupported(xapi)
         elif dominfo:
             # output from xc.domain_getinfo
             self._dominfo_to_xapi(dominfo)
@@ -363,7 +315,6 @@ class XendConfig(dict):
             'memory_dynamic_max': 0,
             'memory_actual': 0,
             'devices': {},
-            'image': {},
             'security': None,
             'on_xend_start': 'ignore',
             'on_xend_stop': 'ignore',
@@ -377,6 +328,7 @@ class XendConfig(dict):
             'vbd_refs': [],
             'vtpm_refs': [],
             'other_config': {},
+            'platform': {}
         }
         
         return defaults
@@ -417,12 +369,23 @@ class XendConfig(dict):
         if 'name_label' not in self:
             self['name_label'] = 'Domain-' + self['uuid']
 
+    def _platform_sanity_check(self):
+        if self.is_hvm():
+            if 'device_model' not in self['platform']:
+                self['platform']['device_model'] = DEFAULT_DM
+
+            # Compatibility hack, can go away soon.
+            if 'soundhw' not in self['platform'] and \
+               self['platform'].get('enable_audio'):
+                self['platform']['soundhw'] = 'sb16'
+
     def validate(self):
         self._uuid_sanity_check()
         self._name_sanity_check()
         self._memory_sanity_check()
         self._actions_sanity_check()
         self._vcpus_sanity_check()
+        self._platform_sanity_check()
 
     def _dominfo_to_xapi(self, dominfo):
         self['domid'] = dominfo['domid']
@@ -497,6 +460,18 @@ class XendConfig(dict):
                 except (TypeError, ValueError), e:
                     log.warn("Unable to parse key %s: %s: %s" %
                              (key, str(val), e))
+
+        if 'platform' not in cfg:
+            cfg['platform'] = {}
+        localtime = sxp.child_value(sxp_cfg, 'localtime')
+        if localtime is not None:
+            cfg['platform']['localtime'] = localtime
+
+        # Compatibility hack -- can go soon.
+        for key in XENAPI_PLATFORM_CFG:
+            val = sxp.child_value(sxp_cfg, "platform_" + key, None)
+            if val is not None:
+                self['platform'][key] = val
 
         # Compatibility hack -- can go soon.
         boot_order = sxp.child_value(sxp_cfg, 'HVM_boot')
@@ -652,10 +627,9 @@ class XendConfig(dict):
             self.update_with_image_sxp(image_sxp)
 
         # Convert Legacy HVM parameters to Xen API configuration
-        self['platform_std_vga'] = bool0(cfg.get('stdvga', 0))
-        self['platform_serial'] = str(cfg.get('serial', ''))
-        self['platform_localtime'] = bool0(cfg.get('localtime', 0))
-        self['platform_enable_audio'] = bool0(cfg.get('soundhw', 0))
+        for key in XENAPI_PLATFORM_CFG:
+            if key in cfg:
+                self['platform'][key] = cfg[key]
 
         # make sure a sane maximum is set
         if self['memory_static_max'] <= 0:
@@ -672,7 +646,7 @@ class XendConfig(dict):
         self['vtpm_refs'] = cfg.get('vtpm_refs', [])
 
         # coalesce hvm vnc frame buffer with vfb config
-        if self['image']['type'] == 'hvm' and self['image'].get('vnc', 0):
+        if self.is_hvm() and self['platform'].get('vnc', 0):
             # add vfb device if it isn't there already
             has_rfb = False
             for console_uuid in self['console_refs']:
@@ -685,11 +659,11 @@ class XendConfig(dict):
 
             if not has_rfb:
                 dev_config = ['vfb']
-                # copy VNC related params from image config to vfb dev conf
+                # copy VNC related params from platform config to vfb dev conf
                 for key in ['vncpasswd', 'vncunused', 'vncdisplay',
                             'vnclisten']:
-                    if key in self['image']:
-                        dev_config.append([key, self['image'][key]])
+                    if key in self['platform']:
+                        dev_config.append([key, self['platform'][key]])
 
                 self.device_add('vfb', cfg_sxp = dev_config)
 
@@ -706,39 +680,19 @@ class XendConfig(dict):
         # the image (as well as HVM images)
         image_sxp = sxp.child_value(sxp_cfg, 'image', [])
         if image_sxp:
-            image = {}
-            image['type'] = sxp.name(image_sxp)
-            for arg, conv in LEGACY_IMAGE_CFG:
-                val = sxp.child_value(image_sxp, arg, None)
-                if val != None:
-                    image[arg] = conv(val)
-
-            image_hvm = {}
-            for arg, conv in LEGACY_IMAGE_HVM_CFG:
-                val = sxp.child_value(image_sxp, arg, None)
-                if val != None:
-                    image_hvm[arg] = conv(val)
-                    
-            image_hvm_devices = {}
-            for arg, conv in LEGACY_IMAGE_HVM_DEVICES_CFG:
-                val = sxp.child_value(image_sxp, arg, None)
-                if val != None:
-                    image_hvm_devices[arg] = conv(val)
-
-            if image_hvm or image_hvm_devices:
-                image['hvm'] = image_hvm
-                image['hvm']['devices'] = image_hvm_devices
-
+            image_type = sxp.name(image_sxp)
+            if image_type != 'hvm' and image_type != 'linux':
+                self['platform']['image_type'] = image_type
+            
+            for key in XENAPI_PLATFORM_CFG:
+                val = sxp.child_value(image_sxp, key, None)
+                if val is not None:
+                    self['platform'][key] = val
+            
             notes = sxp.children(image_sxp, 'notes')
             if notes:
-                image['notes'] = self.notes_from_sxp(notes[0])
-
-            self['image'] = image
-
-            for apikey, imgkey in XENAPI_HVM_CFG.items():
-                val = sxp.child_value(image_sxp, imgkey, None)
-                if val != None:
-                    self[apikey] = val
+                self['notes'] = self.notes_from_sxp(notes[0])
+
             self._hvm_boot_params_from_sxp(image_sxp)
 
         # extract backend value
@@ -774,33 +728,6 @@ class XendConfig(dict):
         _set_cfg_if_exists('up_time')
         _set_cfg_if_exists('status') # TODO, deprecated  
 
-    def _add_xapi_unsupported(self, xapi_dict):
-        """Updates the configuration object with entries that are not
-        officially supported by the Xen API but is required for
-        the rest of Xend to function.
-        """
-
-        # populate image
-        if 'image' in xapi_dict:
-            self['image'].update(xapi_dict['image'])
-        else:
-            hvm = self['HVM_boot_policy'] != ''
-            self['image']['type'] = hvm and 'hvm' or 'linux'
-            if hvm:
-                self['image']['hvm'] = {'devices': {}}
-                for xapi, cfgapi in XENAPI_HVM_CFG.items():
-                    if xapi in self:
-                        self['image']['hvm']['devices'][cfgapi] = self[xapi]
-
-                # currently unsupported options
-                self['image']['hvm']['device_model'] = LEGACY_DM
-                self['image']['vnc'] = 0
-                self['image']['hvm']['pae'] = 1
-
-                if self['platform_enable_audio']:
-                    self['image']['hvm']['devices']['soundhw'] = 'sb16'
-
-
     def _get_old_state_string(self):
         """Returns the old xm state string.
         @rtype: string
@@ -890,9 +817,7 @@ class XendConfig(dict):
             if self.has_key(legacy) and self[legacy] not in (None, []):
                 sxpr.append([legacy, self[legacy]])
 
-        if 'image' in self and self['image']:
-            sxpr.append(['image', self.image_sxpr()])
-
+        sxpr.append(['image', self.image_sxpr()])
         sxpr.append(['status', domain.state])
         sxpr.append(['memory_dynamic_min',  self.get('memory_dynamic_min')])
         sxpr.append(['memory_dynamic_max',  self.get('memory_dynamic_max')])
@@ -1339,7 +1264,7 @@ class XendConfig(dict):
     def image_sxpr(self):
         """Returns a backwards compatible image SXP expression that is
         used in xenstore's /vm/<uuid>/image value and xm list."""
-        image = [self['image'].get('type', 'linux')]
+        image = [self.image_type()]
         if self.has_key('PV_kernel'):
             image.append(['kernel', self['PV_kernel']])
         if self.has_key('PV_ramdisk') and self['PV_ramdisk']:
@@ -1347,28 +1272,12 @@ class XendConfig(dict):
         if self.has_key('PV_args') and self['PV_args']:
             image.append(['args', self['PV_args']])
 
-        for arg, conv in LEGACY_IMAGE_CFG:
-            if self['image'].has_key(arg):
-                image.append([arg, self['image'][arg]])
-
-        if 'hvm' in self['image']:
-            for arg, conv in LEGACY_IMAGE_HVM_CFG:
-                if self['image']['hvm'].get(arg):
-                    image.append([arg, conv(self['image']['hvm'][arg])])
-
-        if 'hvm' in self['image'] and 'devices' in self['image']['hvm']:
-            for arg, conv in LEGACY_IMAGE_HVM_DEVICES_CFG:
-                val = self['image']['hvm']['devices'].get(arg)
-                if val != None:
-                    try:
-                        if conv: val = conv(val)
-                    except (ValueError, TypeError):
-                        if type(val) == bool: val = int(val)
-                            
-                    image.append([arg, val])
-
-        if 'notes' in self['image']:
-            image.append(self.notes_sxp(self['image']['notes']))
+        for key in XENAPI_PLATFORM_CFG:
+            if key in self['platform']:
+                image.append([key, self['platform'][key]])
+
+        if 'notes' in self:
+            image.append(self.notes_sxp(self['notes']))
 
         return image
 
@@ -1399,57 +1308,24 @@ class XendConfig(dict):
             self['PV_ramdisk'] = sxp.child_value(image_sxp, 'ramdisk','')
             self['PV_args'] = kernel_args
 
-        # Store image SXP in python dictionary format
-        image = {}
-        image['type'] = sxp.name(image_sxp)
-        for arg, conv in LEGACY_IMAGE_CFG:
-            val = sxp.child_value(image_sxp, arg, None)
-            if val != None:
-                image[arg] = conv(val)
-
-        image_hvm = {}
-        for arg, conv in LEGACY_IMAGE_HVM_CFG:
-            val = sxp.child_value(image_sxp, arg, None)
-            if val != None:
-                image_hvm[arg] = conv(val)
-                    
-        image_hvm_devices = {}
-        for arg, conv in LEGACY_IMAGE_HVM_DEVICES_CFG:
-            val = sxp.child_value(image_sxp, arg, None)
-            if val != None:
-                try:
-                    image_hvm_devices[arg] = conv(val)
-                except (ValueError, TypeError):
-                    image_hvm_devices[arg] = val
-                        
-
-        if image_hvm or image_hvm_devices:
-            image['hvm'] = image_hvm
-            image['hvm']['devices'] = image_hvm_devices
+        for key in XENAPI_PLATFORM_CFG:
+            val = sxp.child_value(image_sxp, key, None)
+            if val is not None:
+                self['platform'][key] = val
 
         notes = sxp.children(image_sxp, 'notes')
         if notes:
-            image['notes'] = self.notes_from_sxp(notes[0])
-
-        self['image'] = image
-
-        for apikey, imgkey in XENAPI_HVM_CFG.items():
-            val = sxp.child_value(image_sxp, imgkey, None)
-            if val != None:
-                type_conv = XENAPI_CFG_TYPES[apikey]
-                if callable(type_conv):
-                    self[apikey] = type_conv(val)
-                else:
-                    self[apikey] = val
+            self['notes'] = self.notes_from_sxp(notes[0])
+
         self._hvm_boot_params_from_sxp(image_sxp)
 
     def set_notes(self, notes):
         'Add parsed elfnotes to image'
-        self['image']['notes'] = notes
+        self['notes'] = notes
 
     def get_notes(self):
         try:
-            return self['image']['notes'] or {}
+            return self['notes'] or {}
         except KeyError:
             return {}
 
@@ -1471,11 +1347,9 @@ class XendConfig(dict):
             self['HVM_boot_policy'] = 'BIOS order'
             self['HVM_boot_params'] = { 'order' : boot }
 
-
-#
-# debugging 
-#
-
-if __name__ == "__main__":
-    pass
-    
+    def is_hvm(self):
+        return self['HVM_boot_policy'] != ''
+
+    def image_type(self):
+        stored_type = self['platform'].get('image_type')
+        return stored_type or (self.is_hvm() and 'hvm' or 'linux')
diff -r d1853a39e063 -r cb2575cec95c tools/python/xen/xend/XendDomain.py
--- a/tools/python/xen/xend/XendDomain.py       Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/python/xen/xend/XendDomain.py       Mon Mar 12 10:07:08 2007 -0600
@@ -495,7 +495,7 @@ class XendDomain:
             self._refresh(refresh_shutdown = False)
             dom = self.domain_lookup_nr(domid)
             if not dom:
-                raise XendInvalidDomain("No domain named '%s'." % str(domid))
+                raise XendInvalidDomain(str(domid))
             return dom
         finally:
             self.domains_lock.release()
diff -r d1853a39e063 -r cb2575cec95c tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/python/xen/xend/XendDomainInfo.py   Mon Mar 12 10:07:08 2007 -0600
@@ -13,7 +13,7 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #============================================================================
 # Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx>
-# Copyright (C) 2005, 2006 XenSource Ltd
+# Copyright (C) 2005-2007 XenSource Ltd
 #============================================================================
 
 """Representation of a single domain.
@@ -176,14 +176,8 @@ def recreate(info, priv):
         vm._storeVmDetails()
         vm._storeDomDetails()
         
-    if vm.info['image']: # Only dom0 should be without an image entry when
-                         # recreating, but we cope with missing ones
-                         # elsewhere just in case.
-        vm.image = image.create(vm,
-                                vm.info,
-                                vm.info['image'],
-                                vm.info['devices'])
-        vm.image.recreate()
+    vm.image = image.create(vm, vm.info)
+    vm.image.recreate()
 
     vm._registerWatches()
     vm.refreshShutdown(xeninfo)
@@ -448,9 +442,7 @@ class XendDomainInfo:
         self.storeDom("control/shutdown", reason)
 
         ## shutdown hypercall for hvm domain desides xenstore write
-        image_cfg = self.info.get('image', {})
-        hvm = image_cfg.has_key('hvm')
-        if hvm:
+        if self.info.is_hvm():
             for code in DOMAIN_SHUTDOWN_REASONS.keys():
                 if DOMAIN_SHUTDOWN_REASONS[code] == reason:
                     break
@@ -781,7 +773,6 @@ class XendDomainInfo:
             'name':               self.info['name_label'],
             'console/limit':      str(xoptions.get_console_limit() * 1024),
             'memory/target':      str(self.info['memory_static_min'] * 1024),
-            'control/platform-feature-multiprocessor-suspend': str(1)
             }
 
         def f(n, v):
@@ -795,6 +786,9 @@ class XendDomainInfo:
         f('console/ring-ref', self.console_mfn)
         f('store/port',       self.store_port)
         f('store/ring-ref',   self.store_mfn)
+
+        if arch.type == "x86":
+            f('control/platform-feature-multiprocessor-suspend', True)
 
         # elfnotes
         for n, v in self.info.get_notes().iteritems():
@@ -1387,9 +1381,7 @@ class XendDomainInfo:
 
         self.shutdownStartTime = None
 
-        image_cfg = self.info.get('image', {})
-        hvm = image_cfg.has_key('hvm')
-
+        hvm = self.info.is_hvm()
         if hvm:
             info = xc.xeninfo()
             if 'hvm' not in info['xen_caps']:
@@ -1436,14 +1428,8 @@ class XendDomainInfo:
 
         self._configureBootloader()
 
-        if not self._infoIsSet('image'):
-            raise VmError('Missing image in configuration')
-
         try:
-            self.image = image.create(self,
-                                      self.info,
-                                      self.info['image'],
-                                      self.info['devices'])
+            self.image = image.create(self, self.info)
 
             localtime = self.info.get('platform_localtime', False)
             if localtime:
@@ -1503,9 +1489,15 @@ class XendDomainInfo:
             self.info['start_time'] = time.time()
 
             self._stateSet(DOM_STATE_RUNNING)
-        except (RuntimeError, VmError), exn:
+        except VmError, exn:
             log.exception("XendDomainInfo.initDomain: exception occurred")
-            self.image.cleanupBootloading()
+            if self.image:
+                self.image.cleanupBootloading()
+            raise exn
+        except RuntimeError, exn:
+            log.exception("XendDomainInfo.initDomain: exception occurred")
+            if self.image:
+                self.image.cleanupBootloading()
             raise VmError(str(exn))
 
 
@@ -1572,13 +1564,8 @@ class XendDomainInfo:
         self.console_mfn = console_mfn
 
         self._introduceDomain()
-        image_cfg = self.info.get('image', {})
-        hvm = image_cfg.has_key('hvm')
-        if hvm:
-            self.image = image.create(self,
-                    self.info,
-                    self.info['image'],
-                    self.info['devices'])
+        if self.info.is_hvm():
+            self.image = image.create(self, self.info)
             if self.image:
                 self.image.createDeviceModel(True)
                 self.image.register_shutdown_watch()
@@ -1740,11 +1727,7 @@ class XendDomainInfo:
 
         if boot:
             # HVM booting.
-            self.info['image']['type'] = 'hvm'
-            if not 'devices' in self.info['image']:
-                self.info['image']['devices'] = {}
-            self.info['image']['devices']['boot'] = \
-                self.info['HVM_boot_params'].get('order', 'dc')
+            pass
         elif not blexec and kernel:
             # Boot from dom0.  Nothing left to do -- the kernel and ramdisk
             # will be picked up by image.py.
@@ -1908,10 +1891,9 @@ class XendDomainInfo:
             if self._infoIsSet(info_key):
                 to_store[key] = str(self.info[info_key])
 
-        if self.info.get('image'):
-            image_sxpr = self.info.image_sxpr()
-            if image_sxpr:
-                to_store['image'] = sxp.to_string(image_sxpr)
+        image_sxpr = self.info.image_sxpr()
+        if image_sxpr:
+            to_store['image'] = sxp.to_string(image_sxpr)
 
         if self._infoIsSet('security'):
             secinfo = self.info['security']
@@ -2072,18 +2054,8 @@ class XendDomainInfo:
         return retval
     def get_power_state(self):
         return XEN_API_VM_POWER_STATE[self.state]
-    def get_platform_std_vga(self):
-        return self.info.get('platform_std_vga', False)    
-    def get_platform_serial(self):
-        return self.info.get('platform_serial', '')
-    def get_platform_localtime(self):
-        return self.info.get('platform_localtime', False)
-    def get_platform_clock_offset(self):
-        return self.info.get('platform_clock_offset', False)
-    def get_platform_enable_audio(self):
-        return self.info.get('platform_enable_audio', False)
-    def get_platform_keymap(self):
-        return self.info.get('platform_keymap', '')
+    def get_platform(self):
+        return self.info.get('platform', {})    
     def get_pci_bus(self):
         return self.info.get('pci_bus', '')
     def get_tools_version(self):
diff -r d1853a39e063 -r cb2575cec95c tools/python/xen/xend/XendError.py
--- a/tools/python/xen/xend/XendError.py        Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/python/xen/xend/XendError.py        Mon Mar 12 10:07:08 2007 -0600
@@ -13,6 +13,7 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #============================================================================
 # Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx>
+# Copyright (c) 2006, 2007 XenSource Inc.
 #============================================================================
 
 from xmlrpclib import Fault
@@ -55,6 +56,12 @@ class VmError(XendError):
     """Vm construction error."""
     pass
 
+class HVMRequired(VmError):
+    def __init__(self):
+        XendError.__init__(self,
+                           'HVM guest support is unavailable: is VT/AMD-V '
+                           'supported by your CPU and enabled in your BIOS?')
+
 
 XEND_ERROR_AUTHENTICATION_FAILED = ('ELUSER', 'Authentication Failed')
 XEND_ERROR_SESSION_INVALID       = ('EPERMDENIED', 'Session Invalid')
diff -r d1853a39e063 -r cb2575cec95c tools/python/xen/xend/XendNode.py
--- a/tools/python/xen/xend/XendNode.py Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/python/xen/xend/XendNode.py Mon Mar 12 10:07:08 2007 -0600
@@ -95,15 +95,12 @@ class XendNode:
                 self.cpus[u] = {'uuid': u, 'number': i }
 
         for u in self.cpus.keys():
-            log.error(self.cpus[u])
             number = self.cpus[u]['number']
             # We can run off the end of the cpuinfo list if domain0 does not
             # have #vcpus == #pcpus. In that case we just replicate one that's
             # in the hash table.
             if not cpuinfo.has_key(number):
                 number = cpuinfo.keys()[0]
-            log.error(number)
-            log.error(cpuinfo)
             if arch.type == "x86":
                 self.cpus[u].update(
                     { 'host'     : self.uuid,
@@ -453,6 +450,12 @@ class XendNode:
                 return pif.network
         raise Exception('Bridge %s is not connected to a network' % bridge)
 
+    #
+    # Debug keys.
+    #
+
+    def send_debug_keys(self, keys):
+        return self.xc.send_debug_keys(keys)
 
     #
     # Getting host information.
diff -r d1853a39e063 -r cb2575cec95c tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py    Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/python/xen/xend/image.py    Mon Mar 12 10:07:08 2007 -0600
@@ -13,7 +13,7 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #============================================================================
 # Copyright (C) 2005 Mike Wray <mike.wray@xxxxxx>
-# Copyright (C) 2005 XenSource Ltd
+# Copyright (C) 2005-2007 XenSource Ltd
 #============================================================================
 
 
@@ -24,7 +24,7 @@ import signal
 
 import xen.lowlevel.xc
 from xen.xend.XendConstants import REVERSE_DOMAIN_SHUTDOWN_REASONS
-from xen.xend.XendError import VmError, XendError
+from xen.xend.XendError import VmError, XendError, HVMRequired
 from xen.xend.XendLogging import log
 from xen.xend.XendOptions import instance as xenopts
 from xen.xend.server.netif import randomMAC
@@ -36,13 +36,12 @@ MAX_GUEST_CMDLINE = 1024
 MAX_GUEST_CMDLINE = 1024
 
 
-def create(vm, vmConfig, imageConfig, deviceConfig):
+def create(vm, vmConfig):
     """Create an image handler for a vm.
 
     @return ImageHandler instance
     """
-    return findImageHandlerClass(imageConfig)(vm, vmConfig, imageConfig,
-                                              deviceConfig)
+    return findImageHandlerClass(vmConfig)(vm, vmConfig)
 
 
 class ImageHandler:
@@ -65,7 +64,7 @@ class ImageHandler:
     ostype = None
 
 
-    def __init__(self, vm, vmConfig, imageConfig, deviceConfig):
+    def __init__(self, vm, vmConfig):
         self.vm = vm
 
         self.bootloader = False
@@ -73,9 +72,9 @@ class ImageHandler:
         self.ramdisk = None
         self.cmdline = None
 
-        self.configure(vmConfig, imageConfig, deviceConfig)
-
-    def configure(self, vmConfig, imageConfig, _):
+        self.configure(vmConfig)
+
+    def configure(self, vmConfig):
         """Config actions common to all unix-like domains."""
         if '_temp_using_bootloader' in vmConfig:
             self.bootloader = True
@@ -262,30 +261,29 @@ class HVMImageHandler(ImageHandler):
 
     ostype = "hvm"
 
-    def __init__(self, vm, vmConfig, imageConfig, deviceConfig):
-        ImageHandler.__init__(self, vm, vmConfig, imageConfig, deviceConfig)
+    def __init__(self, vm, vmConfig):
+        ImageHandler.__init__(self, vm, vmConfig)
         self.shutdownWatch = None
         self.rebootFeatureWatch = None
 
-    def configure(self, vmConfig, imageConfig, deviceConfig):
-        ImageHandler.configure(self, vmConfig, imageConfig, deviceConfig)
+    def configure(self, vmConfig):
+        ImageHandler.configure(self, vmConfig)
 
         if not self.kernel:
             self.kernel = '/usr/lib/xen/boot/hvmloader'
 
         info = xc.xeninfo()
         if 'hvm' not in info['xen_caps']:
-            raise VmError("HVM guest support is unavailable: is VT/AMD-V "
-                          "supported by your CPU and enabled in your BIOS?")
+            raise HVMRequired()
 
         self.dmargs = self.parseDeviceModelArgs(vmConfig)
-        self.device_model = imageConfig['hvm'].get('device_model')
+        self.device_model = vmConfig['platform'].get('device_model')
         if not self.device_model:
             raise VmError("hvm: missing device model")
         
-        self.display = imageConfig['hvm'].get('display')
-        self.xauthority = imageConfig['hvm'].get('xauthority')
-        self.vncconsole = imageConfig['hvm'].get('vncconsole')
+        self.display = vmConfig['platform'].get('display')
+        self.xauthority = vmConfig['platform'].get('xauthority')
+        self.vncconsole = vmConfig['platform'].get('vncconsole')
 
         self.vm.storeVm(("image/dmargs", " ".join(self.dmargs)),
                         ("image/device-model", self.device_model),
@@ -293,9 +291,9 @@ class HVMImageHandler(ImageHandler):
 
         self.pid = None
 
-        self.pae  = imageConfig['hvm'].get('pae', 0)
-        self.apic  = imageConfig['hvm'].get('apic', 0)
-        self.acpi  = imageConfig['hvm']['devices'].get('acpi', 0)
+        self.pae  = int(vmConfig['platform'].get('pae',  0))
+        self.apic = int(vmConfig['platform'].get('apic', 0))
+        self.acpi = int(vmConfig['platform'].get('acpi', 0))
         
 
     def buildDomain(self):
@@ -331,11 +329,10 @@ class HVMImageHandler(ImageHandler):
                    'localtime', 'serial', 'stdvga', 'isa',
                    'acpi', 'usb', 'usbdevice', 'keymap' ]
         
-        hvmDeviceConfig = vmConfig['image']['hvm']['devices']
         ret = ['-vcpus', str(self.vm.getVCpuCount())]
 
         for a in dmargs:
-            v = hvmDeviceConfig.get(a)
+            v = vmConfig['platform'].get(a)
 
             # python doesn't allow '-' in variable names
             if a == 'stdvga': a = 'std-vga'
@@ -395,14 +392,14 @@ class HVMImageHandler(ImageHandler):
         # Find RFB console device, and if it exists, make QEMU enable
         # the VNC console.
         #
-        if vmConfig['image'].get('nographic'):
+        if vmConfig['platform'].get('nographic'):
             # skip vnc init if nographic is set
             ret.append('-nographic')
             return ret
 
         vnc_config = {}
-        has_vnc = int(vmConfig['image'].get('vnc', 0)) != 0
-        has_sdl = int(vmConfig['image'].get('sdl', 0)) != 0
+        has_vnc = int(vmConfig['platform'].get('vnc', 0)) != 0
+        has_sdl = int(vmConfig['platform'].get('sdl', 0)) != 0
         for dev_uuid in vmConfig['console_refs']:
             dev_type, dev_info = vmConfig['devices'][dev_uuid]
             if dev_type == 'vfb':
@@ -414,8 +411,8 @@ class HVMImageHandler(ImageHandler):
             if not vnc_config:
                 for key in ('vncunused', 'vnclisten', 'vncdisplay',
                             'vncpasswd'):
-                    if key in vmConfig['image']:
-                        vnc_config[key] = vmConfig['image'][key]
+                    if key in vmConfig['platform']:
+                        vnc_config[key] = vmConfig['platform'][key]
 
             if not vnc_config.get('vncunused', 0) and \
                    vnc_config.get('vncdisplay', 0):
@@ -634,9 +631,7 @@ def findImageHandlerClass(image):
     @param image config
     @return ImageHandler subclass or None
     """
-    image_type = image['type']
-    if image_type is None:
-        raise VmError('missing image type')
+    image_type = image.image_type()
     try:
         return _handlers[arch.type][image_type]
     except KeyError:
diff -r d1853a39e063 -r cb2575cec95c 
tools/python/xen/xend/server/XMLRPCServer.py
--- a/tools/python/xen/xend/server/XMLRPCServer.py      Mon Mar 12 09:43:48 
2007 -0600
+++ b/tools/python/xen/xend/server/XMLRPCServer.py      Mon Mar 12 10:07:08 
2007 -0600
@@ -157,7 +157,7 @@ class XMLRPCServer:
                     self.server.register_function(fn, "xend.domain.%s" % 
name[7:])
 
         # Functions in XendNode and XendDmesg
-        for type, lst, n in [(XendNode, ['info'], 'node'),
+        for type, lst, n in [(XendNode, ['info', 'send_debug_keys'], 'node'),
                              (XendDmesg, ['info', 'clear'], 'node.dmesg')]:
             inst = type.instance()
             for name in lst:
diff -r d1853a39e063 -r cb2575cec95c tools/python/xen/xm/XenAPI.py
--- a/tools/python/xen/xm/XenAPI.py     Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/python/xen/xm/XenAPI.py     Mon Mar 12 10:07:08 2007 -0600
@@ -155,7 +155,7 @@ class Session(xen.util.xmlrpclib2.Server
 
 def _parse_result(result):
     if type(result) != dict or 'Status' not in result:
-        raise xmlrpclib.Fault(500, 'Missing Status in response from server')
+        raise xmlrpclib.Fault(500, 'Missing Status in response from server' + 
result)
     if result['Status'] == 'Success':
         if 'Value' in result:
             return result['Value']
diff -r d1853a39e063 -r cb2575cec95c tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py       Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/python/xen/xm/main.py       Mon Mar 12 10:07:08 2007 -0600
@@ -25,6 +25,7 @@ import cmd
 import cmd
 import os
 import pprint
+import readline
 import shlex
 import sys
 import re
@@ -133,6 +134,7 @@ SUBCOMMAND_HELP = {
     'sched-credit': ('[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]]',
                      'Get/set credit scheduler parameters.'),
     'sysrq'       : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
+    'debug-keys'  : ('<Keys>', 'Send debug keys to Xen.'),
     'trigger'     : ('<Domain> <nmi|reset|init> [<VCPU>]',
                      'Send a trigger to a domain.'),
     'vcpu-list'   : ('[<Domain>]',
@@ -260,7 +262,6 @@ common_commands = [
     "shutdown",
     "start",
     "suspend",
-    "trigger",
     "top",
     "unpause",
     "uptime",
@@ -300,6 +301,7 @@ domain_commands = [
     ]
 
 host_commands = [
+    "debug-keys",
     "dmesg",
     "info",
     "log",
@@ -557,6 +559,10 @@ class Shell(cmd.Cmd):
             for f in res:
                 setattr(Shell, 'do_' + f, self.default)
 
+    def preloop(self):
+        cmd.Cmd.preloop(self)
+        readline.set_completer_delims(' ')
+
     def default(self, line):
         words = shlex.split(line)
         if len(words) > 0 and words[0] == 'xm':
@@ -576,9 +582,9 @@ class Shell(cmd.Cmd):
         return False
 
     def completedefault(self, text, line, begidx, endidx):
-        cmd = line.split(' ')[0]
-        clas, func = cmd.split('.')
-        if begidx != len(cmd) + 1 or \
+        words = shlex.split(line[:begidx])
+        clas, func = words[0].split('.')
+        if len(words) > 1 or \
            func.startswith('get_by_') or \
            func == 'get_all':
             return []
@@ -1394,6 +1400,10 @@ def xm_trigger(args):
         vcpu = int(args[2])
     
     server.xend.domain.send_trigger(dom, trigger, vcpu)
+
+def xm_debug_keys(args):
+    arg_check(args, "debug-keys", 1)
+    server.xend.node.send_debug_keys(str(args[0]))
 
 def xm_top(args):
     arg_check(args, "top", 0)
@@ -1738,6 +1748,7 @@ commands = {
     "pause": xm_pause,
     "unpause": xm_unpause,
     # host commands
+    "debug-keys": xm_debug_keys,
     "dmesg": xm_dmesg,
     "info": xm_info,
     "log": xm_log,
@@ -1881,7 +1892,7 @@ def _run_cmd(cmd, cmd_name, args):
             err("Domain '%s' does not exist." % ex.faultString)
         else:
             err(ex.faultString)
-        _usage(cmd_name)
+            _usage(cmd_name)
     except xmlrpclib.ProtocolError, ex:
         if ex.errcode == -1:
             print  >>sys.stderr, (
diff -r d1853a39e063 -r cb2575cec95c tools/python/xen/xm/messages/en/xen-xm.po
--- a/tools/python/xen/xm/messages/en/xen-xm.po Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/python/xen/xm/messages/en/xen-xm.po Mon Mar 12 10:07:08 2007 -0600
@@ -19,7 +19,7 @@ msgid ""
 msgid ""
 msgstr ""
 "Project-Id-Version: Xen-xm 3.0\n"
-"PO-Revision-Date: 2007-02-20 15:22+0000\n"
+"PO-Revision-Date: 2007-03-10 23:17+0000\n"
 "Last-Translator: Ewan Mellor <ewan@xxxxxxxxxxxxx>\n"
 "Language-Team: xen-devel <xen-devel@xxxxxxxxxxxxxxxxxxx>\n"
 "MIME-Version: 1.0\n"
@@ -61,3 +61,6 @@ msgstr "The VLAN tag you gave (%(1)s) is
 
 msgid "VM_BAD_POWER_STATE"
 msgstr "The VM must be %(2)s to perform the requested operation (it is 
currently %(3)s)."
+
+msgid "VM_HVM_REQUIRED"
+msgstr "HVM guest support is unavailable: is VT/AMD-V supported by your CPU 
and enabled in your BIOS?"
diff -r d1853a39e063 -r cb2575cec95c tools/xm-test/tests/vtpm/09_vtpm-xapi.py
--- a/tools/xm-test/tests/vtpm/09_vtpm-xapi.py  Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/xm-test/tests/vtpm/09_vtpm-xapi.py  Mon Mar 12 10:07:08 2007 -0600
@@ -113,7 +113,7 @@ if not re.search("PCR-00:",run["output"]
     FAIL("1. Virtual TPM is not working correctly on /dev/vtpm on backend 
side: \n%s" % run["output"])
 
 try:
-    rc = session.xenapi.VTPM.destroy(vtpm_uuid)
+    session.xenapi.VTPM.destroy(vtpm_uuid)
     #Should never get here
     FAIL("Could destroy vTPM while VM is running")
 except:
@@ -124,7 +124,7 @@ if rc:
     FAIL("Could not suspend VM")
 
 try:
-    rc = session.xenapi.VTPM.destroy(vtpm_uuid)
+    session.xenapi.VTPM.destroy(vtpm_uuid)
     #May not throw an exception in 'suspend' state
 except:
     pass
@@ -150,8 +150,9 @@ if not re.search("PCR-00:",run["output"]
 
 domain.stop()
 
-rc = session.xenapi.VTPM.destroy(vtpm_uuid)
-if not rc:
+try:
+    session.xenapi.VTPM.destroy(vtpm_uuid)
+except:
     FAIL("Could NOT destroy vTPM while domain is halted.")
 
 domain.destroy()
diff -r d1853a39e063 -r cb2575cec95c xen/arch/ia64/xen/xensetup.c
--- a/xen/arch/ia64/xen/xensetup.c      Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/ia64/xen/xensetup.c      Mon Mar 12 10:07:08 2007 -0600
@@ -543,8 +543,6 @@ printk("num_online_cpus=%d, max_cpus=%d\
 
     domain0_ready = 1;
 
-    schedulers_start();
-
     domain_unpause_by_systemcontroller(dom0);
 
     startup_cpu_idle_loop();
diff -r d1853a39e063 -r cb2575cec95c xen/arch/powerpc/domain.c
--- a/xen/arch/powerpc/domain.c Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/powerpc/domain.c Mon Mar 12 10:07:08 2007 -0600
@@ -142,6 +142,8 @@ void free_vcpu_struct(struct vcpu *v)
 
 int vcpu_initialise(struct vcpu *v)
 {
+    /* Guests by default have a 100Hz ticker. */
+    v->periodic_period = MILLISECS(10);
     return 0;
 }
 
diff -r d1853a39e063 -r cb2575cec95c xen/arch/powerpc/setup.c
--- a/xen/arch/powerpc/setup.c  Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/powerpc/setup.c  Mon Mar 12 10:07:08 2007 -0600
@@ -365,9 +365,6 @@ static void __init __start_xen(multiboot
         kick_secondary_cpus(max_cpus);
     }
 
-    /* Secondary processors must be online before we call this.  */
-    schedulers_start();
-
     /* This cannot be called before secondary cpus are marked online.  */
     percpu_free_unused_areas();
 
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/apic.c
--- a/xen/arch/x86/apic.c       Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/x86/apic.c       Mon Mar 12 10:07:08 2007 -0600
@@ -1023,6 +1023,13 @@ int reprogram_timer(s_time_t timeout)
     u64         apic_tmict;
 
     /*
+     * If we don't have local APIC then we just poll the timer list off the
+     * PIT interrupt.
+     */
+    if ( !cpu_has_apic )
+        return 1;
+
+    /*
      * We use this value because we don't trust zero (we think it may just
      * cause an immediate interrupt). At least this is guaranteed to hold it
      * off for ages (esp. since the clock ticks on bus clock, not cpu clock!).
@@ -1043,13 +1050,6 @@ int reprogram_timer(s_time_t timeout)
                 (u32)now, (u32)(timeout>>32),(u32)timeout);
         return 0;
     }
-
-    /*
-     * If we don't have local APIC then we just poll the timer list off the
-     * PIT interrupt. Cheesy but good enough to work on eg. VMware :-)
-     */
-    if ( !cpu_has_apic )
-        return 1;
 
     /* conversion to bus units */
     apic_tmict = (((u64)bus_scale) * expire)>>18;
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/x86/domain.c     Mon Mar 12 10:07:08 2007 -0600
@@ -350,6 +350,9 @@ int vcpu_initialise(struct vcpu *v)
     }
     else
     {
+        /* PV guests by default have a 100Hz ticker. */
+        v->periodic_period = MILLISECS(10);
+
         /* PV guests get an emulated PIT too for video BIOSes to use. */
         if ( !is_idle_domain(d) && (v->vcpu_id == 0) )
             pit_init(v, cpu_khz);
@@ -457,8 +460,10 @@ int arch_domain_create(struct domain *d)
  fail:
     free_xenheap_page(d->shared_info);
 #ifdef __x86_64__
-    free_domheap_page(virt_to_page(d->arch.mm_perdomain_l2));
-    free_domheap_page(virt_to_page(d->arch.mm_perdomain_l3));
+    if ( d->arch.mm_perdomain_l2 )
+        free_domheap_page(virt_to_page(d->arch.mm_perdomain_l2));
+    if ( d->arch.mm_perdomain_l3 )
+        free_domheap_page(virt_to_page(d->arch.mm_perdomain_l3));
 #endif
     free_xenheap_pages(d->arch.mm_perdomain_pt, pdpt_order);
     return rc;
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/domctl.c
--- a/xen/arch/x86/domctl.c     Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/x86/domctl.c     Mon Mar 12 10:07:08 2007 -0600
@@ -145,6 +145,12 @@ long arch_do_domctl(
         }
 
         arr32 = alloc_xenheap_page();
+        if ( !arr32 )
+        {
+            ret = -ENOMEM;
+            put_domain(d);
+            break;
+        }
  
         ret = 0;
         for ( n = 0; n < num; )
@@ -157,7 +163,7 @@ long arch_do_domctl(
                                         domctl->u.getpageframeinfo2.array,
                                         n, k) )
             {
-                ret = -EINVAL;
+                ret = -EFAULT;
                 break;
             }
      
@@ -201,7 +207,7 @@ long arch_do_domctl(
             if ( copy_to_guest_offset(domctl->u.getpageframeinfo2.array,
                                       n, arr32, k) )
             {
-                ret = -EINVAL;
+                ret = -EFAULT;
                 break;
             }
 
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/x86/hvm/hvm.c    Mon Mar 12 10:07:08 2007 -0600
@@ -146,6 +146,48 @@ void hvm_do_resume(struct vcpu *v)
     }
 }
 
+/* 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)
 {
     int rc;
@@ -161,7 +203,8 @@ int hvm_domain_initialise(struct domain 
     spin_lock_init(&d->arch.hvm_domain.buffered_io_lock);
     spin_lock_init(&d->arch.hvm_domain.irq_lock);
 
-    rc = paging_enable(d, PG_SH_enable|PG_refcounts|PG_translate|PG_external);
+    /* paging support will be determined inside paging.c */
+    rc = paging_enable(d, PG_refcounts|PG_translate|PG_external);
     if ( rc != 0 )
         return rc;
 
@@ -379,7 +422,7 @@ void hvm_triple_fault(void)
  */
 static int __hvm_copy(void *buf, paddr_t addr, int size, int dir, int virt)
 {
-    unsigned long mfn;
+    unsigned long gfn, mfn;
     char *p;
     int count, todo;
 
@@ -389,9 +432,11 @@ static int __hvm_copy(void *buf, paddr_t
         count = min_t(int, PAGE_SIZE - (addr & ~PAGE_MASK), todo);
 
         if ( virt )
-            mfn = get_mfn_from_gpfn(paging_gva_to_gfn(current, addr));
+            gfn = paging_gva_to_gfn(current, addr);
         else
-            mfn = get_mfn_from_gpfn(addr >> PAGE_SHIFT);
+            gfn = addr >> PAGE_SHIFT;
+        
+        mfn = get_mfn_from_gpfn(gfn);
 
         if ( mfn == INVALID_MFN )
             return todo;
@@ -399,14 +444,15 @@ static int __hvm_copy(void *buf, paddr_t
         p = (char *)map_domain_page(mfn) + (addr & ~PAGE_MASK);
 
         if ( dir )
+        {
             memcpy(p, buf, count); /* dir == TRUE:  *to* guest */
+            mark_dirty(current->domain, mfn);
+        }
         else
             memcpy(buf, p, count); /* dir == FALSE: *from guest */
 
         unmap_domain_page(p);
         
-        mark_dirty(current->domain, mfn);
-
         addr += count;
         buf  += count;
         todo -= count;
@@ -912,6 +958,12 @@ 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 d1853a39e063 -r cb2575cec95c xen/arch/x86/hvm/rtc.c
--- a/xen/arch/x86/hvm/rtc.c    Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/x86/hvm/rtc.c    Mon Mar 12 10:07:08 2007 -0600
@@ -174,6 +174,11 @@ static void rtc_copy_date(RTCState *s)
 {
     const struct tm *tm = &s->current_tm;
 
+    if (s->time_offset_seconds != s->pt.vcpu->domain->time_offset_seconds) {
+        s->current_tm = gmtime(get_localtime(s->pt.vcpu->domain));
+        s->time_offset_seconds = s->pt.vcpu->domain->time_offset_seconds;
+    }
+
     s->hw.cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec);
     s->hw.cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min);
     if ( s->hw.cmos_data[RTC_REG_B] & RTC_24H )
@@ -211,9 +216,15 @@ static int get_days_in_month(int month, 
 }
 
 /* update 'tm' to the next second */
-static void rtc_next_second(struct tm *tm)
-{
+static void rtc_next_second(RTCState *s)
+{
+    struct tm *tm = &s->current_tm;
     int days_in_month;
+
+    if (s->time_offset_seconds != s->pt.vcpu->domain->time_offset_seconds) {
+        s->current_tm = gmtime(get_localtime(s->pt.vcpu->domain));
+        s->time_offset_seconds = s->pt.vcpu->domain->time_offset_seconds;
+    }
 
     tm->tm_sec++;
     if ((unsigned)tm->tm_sec >= 60) {
@@ -258,7 +269,7 @@ static void rtc_update_second(void *opaq
     }
     else
     {
-        rtc_next_second(&s->current_tm);
+        rtc_next_second(s);
         
         if ( !(s->hw.cmos_data[RTC_REG_B] & RTC_SET) )
             s->hw.cmos_data[RTC_REG_A] |= RTC_UIP;
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/x86/hvm/svm/svm.c        Mon Mar 12 10:07:08 2007 -0600
@@ -49,6 +49,7 @@
 #include <public/sched.h>
 #include <asm/hvm/vpt.h>
 #include <asm/hvm/trace.h>
+#include <asm/hap.h>
 
 #define SVM_EXTRA_DEBUG
 
@@ -76,6 +77,10 @@ static void *root_vmcb[NR_CPUS] __read_m
 /* physical address of above for host VMSAVE/VMLOAD */
 u64 root_vmcb_pa[NR_CPUS] __read_mostly;
 
+/* hardware assisted paging bits */
+extern int opt_hap_enabled;
+extern int hap_capable_system;
+
 static inline void svm_inject_exception(struct vcpu *v, int trap, 
                                         int ev, int error_code)
 {
@@ -102,22 +107,10 @@ static void stop_svm(void)
 static void stop_svm(void)
 {
     u32 eax, edx;    
-    int cpu = smp_processor_id();
-
     /* We turn off the EFER_SVME bit. */
     rdmsr(MSR_EFER, eax, edx);
     eax &= ~EFER_SVME;
     wrmsr(MSR_EFER, eax, edx);
- 
-    /* release the HSA */
-    free_host_save_area(hsa[cpu]);
-    hsa[cpu] = NULL;
-    wrmsr(MSR_K8_VM_HSAVE_PA, 0, 0 );
-
-    /* free up the root vmcb */
-    free_vmcb(root_vmcb[cpu]);
-    root_vmcb[cpu] = NULL;
-    root_vmcb_pa[cpu] = 0;
 }
 
 static void svm_store_cpu_guest_regs(
@@ -240,7 +233,9 @@ static inline int long_mode_do_msr_write
         /*
          * Check for EFER.LME transitions from 0->1 or 1->0.  Do the
          * sanity checks and then make sure that both EFER.LME and
-         * EFER.LMA are cleared.
+         * EFER.LMA are cleared. (EFER.LME can't be set in the vmcb
+         * until the guest also sets CR0.PG, since even if the guest has
+         * paging "disabled", the vmcb's CR0 always has PG set.)
          */
         if ( (msr_content & EFER_LME) && !svm_lme_is_set(v) )
         {
@@ -269,10 +264,12 @@ static inline int long_mode_do_msr_write
 
             vmcb->efer &= ~(EFER_LME | EFER_LMA);
         }
+
 #endif /* __x86_64__ */
 
         /* update the guest EFER's shadow with the intended value */
         v->arch.hvm_svm.cpu_shadow_efer = msr_content;
+
         break;
 
 #ifdef __x86_64__
@@ -902,6 +899,10 @@ static void arch_svm_do_launch(struct vc
 {
     svm_do_launch(v);
 
+    if ( paging_mode_hap(v->domain) ) {
+        v->arch.hvm_svm.vmcb->h_cr3 = 
pagetable_get_paddr(v->domain->arch.phys_table);
+    }
+
     if ( v->vcpu_id != 0 )
     {
         cpu_user_regs_t *regs = &current->arch.guest_context.user_regs;
@@ -1008,6 +1009,21 @@ static struct hvm_function_table svm_fun
     .event_injection_faulted = svm_event_injection_faulted
 };
 
+void svm_npt_detect(void)
+{
+    u32 eax, ebx, ecx, edx;
+
+    /* check CPUID for nested paging support */
+    cpuid(0x8000000A, &eax, &ebx, &ecx, &edx);
+    if ( edx & 0x01 ) { /* nested paging */
+        hap_capable_system = 1;
+    }
+    else if ( opt_hap_enabled ) {
+        printk(" nested paging is not supported by this CPU.\n");
+        hap_capable_system = 0; /* no nested paging, we disable flag. */
+    }
+}
+
 int start_svm(void)
 {
     u32 eax, ecx, edx;
@@ -1030,13 +1046,16 @@ int start_svm(void)
         return 0;
     }
 
-    if (!(hsa[cpu] = alloc_host_save_area()))
-        return 0;
+    if (!hsa[cpu])
+        if (!(hsa[cpu] = alloc_host_save_area()))
+            return 0;
     
     rdmsr(MSR_EFER, eax, edx);
     eax |= EFER_SVME;
     wrmsr(MSR_EFER, eax, edx);
     printk("AMD SVM Extension is enabled for cpu %d.\n", cpu );
+
+    svm_npt_detect();
 
     /* Initialize the HSA for this core */
     phys_hsa = (u64) virt_to_maddr(hsa[cpu]);
@@ -1044,8 +1063,9 @@ int start_svm(void)
     phys_hsa_hi = (u32) (phys_hsa >> 32);    
     wrmsr(MSR_K8_VM_HSAVE_PA, phys_hsa_lo, phys_hsa_hi);
   
-    if (!(root_vmcb[cpu] = alloc_vmcb())) 
-        return 0;
+    if (!root_vmcb[cpu])
+        if (!(root_vmcb[cpu] = alloc_vmcb())) 
+            return 0;
     root_vmcb_pa[cpu] = virt_to_maddr(root_vmcb[cpu]);
 
     if (cpu == 0)
@@ -1073,6 +1093,18 @@ void arch_svm_do_resume(struct vcpu *v)
         reset_stack_and_jump( svm_asm_do_resume );
     }
 }
+
+static int svm_do_nested_pgfault(paddr_t gpa, struct cpu_user_regs *regs)
+{
+    if (mmio_space(gpa)) {
+        handle_mmio(gpa);
+        return 1;
+    }
+
+    /* We should not reach here. Otherwise, P2M table is not correct.*/
+    return 0;
+}
+
 
 static int svm_do_page_fault(unsigned long va, struct cpu_user_regs *regs) 
 {
@@ -1700,6 +1732,52 @@ static void svm_io_instruction(struct vc
     }
 }
 
+static int npt_set_cr0(unsigned long value) 
+{
+    struct vcpu *v = current;
+    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+  
+    ASSERT(vmcb);
+
+    /* ET is reserved and should be always be 1*/
+    value |= X86_CR0_ET;
+
+    /* Check whether the guest is about to turn on long mode. 
+     * If it is, set EFER.LME and EFER.LMA.  Update the shadow EFER.LMA
+     * bit too, so svm_long_mode_enabled() will work.
+     */
+    if ( (value & X86_CR0_PG) && svm_lme_is_set(v) &&
+         (vmcb->cr4 & X86_CR4_PAE) && (vmcb->cr0 & X86_CR0_PE) )
+    {
+        v->arch.hvm_svm.cpu_shadow_efer |= EFER_LMA;
+        vmcb->efer |= EFER_LMA | EFER_LME;
+    }
+
+    /* Whenever CR0.PG is cleared under long mode, LMA will be cleared 
+     * immediatly. We emulate this process for svm_long_mode_enabled().
+     */
+    if ( (value & (X86_CR0_PE | X86_CR0_PG)) == X86_CR0_PE )
+    {
+        if ( svm_long_mode_enabled(v) )
+        {
+            v->arch.hvm_svm.cpu_shadow_efer &= ~EFER_LMA;
+        }
+    }
+    
+    vmcb->cr0 = value | X86_CR0_WP;
+    v->arch.hvm_svm.cpu_shadow_cr0 = value;
+
+    /* TS cleared? Then initialise FPU now. */
+    if ( !(value & X86_CR0_TS) ) {
+        setup_fpu(v);
+        vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM;
+    }
+    
+    paging_update_paging_modes(v);
+    
+    return 1;
+}
+
 static int svm_set_cr0(unsigned long value)
 {
     struct vcpu *v = current;
@@ -1795,6 +1873,85 @@ static int svm_set_cr0(unsigned long val
     }
 
     return 1;
+}
+
+//
+// nested paging functions
+//
+
+static int npt_mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
+{  
+    unsigned long value;
+    struct vcpu *v = current;
+    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+    struct vlapic *vlapic = vcpu_vlapic(v);
+
+    ASSERT(vmcb);
+
+    value = get_reg(gpreg, regs, vmcb);
+
+    switch (cr) {
+    case 0:
+        return npt_set_cr0(value);
+
+    case 3:
+        vmcb->cr3 = value;
+        v->arch.hvm_svm.cpu_cr3 = value;
+        break;
+
+    case 4: /* CR4 */
+        vmcb->cr4 = value;
+        v->arch.hvm_svm.cpu_shadow_cr4 = value;
+        paging_update_paging_modes(v);
+        break;
+
+    case 8:
+        vlapic_set_reg(vlapic, APIC_TASKPRI, ((value & 0x0F) << 4));
+        vmcb->vintr.fields.tpr = value & 0x0F;
+        break;
+
+    default:
+        gdprintk(XENLOG_ERR, "invalid cr: %d\n", cr);
+        domain_crash(v->domain);
+        return 0;
+    }
+    
+    return 1;
+}
+
+static void npt_mov_from_cr(int cr, int gp, struct cpu_user_regs *regs)
+{
+    unsigned long value = 0;
+    struct vcpu *v = current;
+    struct vmcb_struct *vmcb;
+    struct vlapic *vlapic = vcpu_vlapic(v);
+
+    vmcb = v->arch.hvm_svm.vmcb;
+    ASSERT(vmcb);
+
+    switch(cr) {
+    case 0:
+        value = (unsigned long) v->arch.hvm_svm.cpu_shadow_cr0;
+        break;
+    case 2:
+        value = vmcb->cr2;
+        break;
+    case 3:
+        value = (unsigned long) v->arch.hvm_svm.cpu_cr3;
+        break;
+    case 4:
+        value = (unsigned long) v->arch.hvm_svm.cpu_shadow_cr4;
+       break;
+    case 8:
+        value = (unsigned long)vlapic_get_reg(vlapic, APIC_TASKPRI);
+        value = (value & 0xF0) >> 4;
+        break;
+    default:
+        domain_crash(v->domain);
+        return;
+    }
+    
+    set_reg(gp, value, regs, vmcb);
 }
 
 /*
@@ -2043,12 +2200,18 @@ static int svm_cr_access(struct vcpu *v,
     {
     case INSTR_MOV2CR:
         gpreg = decode_src_reg(prefix, buffer[index+2]);
-        result = mov_to_cr(gpreg, cr, regs);
+        if ( paging_mode_hap(v->domain) )
+            result = npt_mov_to_cr(gpreg, cr, regs);
+        else
+            result = mov_to_cr(gpreg, cr, regs);
         break;
 
     case INSTR_MOVCR2:
         gpreg = decode_src_reg(prefix, buffer[index+2]);
-        mov_from_cr(cr, gpreg, regs);
+        if ( paging_mode_hap(v->domain) )
+            npt_mov_from_cr(cr, gpreg, regs);
+        else
+            mov_from_cr(cr, gpreg, regs);
         break;
 
     case INSTR_CLTS:
@@ -2075,7 +2238,10 @@ static int svm_cr_access(struct vcpu *v,
         if (svm_dbg_on)
             printk("CR0-LMSW CR0 - New value=%lx\n", value);
 
-        result = svm_set_cr0(value);
+        if ( paging_mode_hap(v->domain) )
+            result = npt_set_cr0(value);
+        else
+            result = svm_set_cr0(value);
         break;
 
     case INSTR_SMSW:
@@ -2358,6 +2524,11 @@ static int svm_do_vmmcall_reset_to_realm
 
     vmcb->cr4 = SVM_CR4_HOST_MASK;
     v->arch.hvm_svm.cpu_shadow_cr4 = 0;
+
+    if ( paging_mode_hap(v->domain) ) {
+        vmcb->cr0 = v->arch.hvm_svm.cpu_shadow_cr0;
+        vmcb->cr4 = v->arch.hvm_svm.cpu_shadow_cr4;
+    }
 
     /* This will jump to ROMBIOS */
     vmcb->rip = 0xFFF0;
@@ -3042,6 +3213,15 @@ asmlinkage void svm_vmexit_handler(struc
         hvm_triple_fault();
         break;
 
+    case VMEXIT_NPF:
+    {
+        regs->error_code = vmcb->exitinfo1;
+        if ( !svm_do_nested_pgfault(vmcb->exitinfo2, regs) ) {
+            domain_crash(v->domain);
+        }
+        break;
+    }
+
     default:
     exit_and_crash:
         gdprintk(XENLOG_ERR, "unexpected VMEXIT: exit reason = 0x%x, "
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/hvm/svm/vmcb.c
--- a/xen/arch/x86/hvm/svm/vmcb.c       Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/x86/hvm/svm/vmcb.c       Mon Mar 12 10:07:08 2007 -0600
@@ -79,11 +79,6 @@ struct host_save_area *alloc_host_save_a
     return hsa;
 }
 
-void free_host_save_area(struct host_save_area *hsa)
-{
-    free_xenheap_page(hsa);
-}
-
 static int construct_vmcb(struct vcpu *v)
 {
     struct arch_svm_struct *arch_svm = &v->arch.hvm_svm;
@@ -200,6 +195,13 @@ static int construct_vmcb(struct vcpu *v
     vmcb->cr3 = v->arch.hvm_vcpu.hw_cr3; 
 
     arch_svm->vmcb->exception_intercepts = MONITOR_DEFAULT_EXCEPTION_BITMAP;
+
+    if ( paging_mode_hap(v->domain) ) {
+        vmcb->cr0 = arch_svm->cpu_shadow_cr0;
+        vmcb->np_enable = 1; /* enable nested paging */
+        vmcb->g_pat = 0x0007040600070406ULL; /* guest PAT */
+        vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_PG;
+    }
 
     return 0;
 }
@@ -310,7 +312,8 @@ void svm_dump_vmcb(const char *from, str
     printk("KernGSBase = 0x%016llx PAT = 0x%016llx \n", 
            (unsigned long long) vmcb->kerngsbase,
            (unsigned long long) vmcb->g_pat);
-    
+    printk("H_CR3 = 0x%016llx\n", (unsigned long long)vmcb->h_cr3);
+
     /* print out all the selectors */
     svm_dump_sel("CS", &vmcb->cs);
     svm_dump_sel("DS", &vmcb->ds);
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/mm/Makefile
--- a/xen/arch/x86/mm/Makefile  Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/x86/mm/Makefile  Mon Mar 12 10:07:08 2007 -0600
@@ -1,4 +1,5 @@ subdir-y += shadow
 subdir-y += shadow
+subdir-y += hap
 
 obj-y += paging.o
 obj-y += p2m.o
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/mm/hap/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/mm/hap/Makefile      Mon Mar 12 10:07:08 2007 -0600
@@ -0,0 +1,2 @@
+obj-y += hap.o
+obj-y += support.o
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/mm/hap/hap.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/mm/hap/hap.c Mon Mar 12 10:07:08 2007 -0600
@@ -0,0 +1,708 @@
+/******************************************************************************
+ * arch/x86/mm/hap/hap.c
+ *
+ * hardware assisted paging
+ * Copyright (c) 2007 Advanced Micro Devices (Wei Huang)
+ * Parts of this code are Copyright (c) 2007 by XenSource Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 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 <xen/config.h>
+#include <xen/types.h>
+#include <xen/mm.h>
+#include <xen/trace.h>
+#include <xen/sched.h>
+#include <xen/perfc.h>
+#include <xen/irq.h>
+#include <xen/domain_page.h>
+#include <xen/guest_access.h>
+#include <xen/keyhandler.h>
+#include <asm/event.h>
+#include <asm/page.h>
+#include <asm/current.h>
+#include <asm/flushtlb.h>
+#include <asm/shared.h>
+#include <asm/hap.h>
+#include <asm/paging.h>
+#include <asm/domain.h>
+
+#include "private.h"
+
+/* Override macros from asm/page.h to make them work with mfn_t */
+#undef mfn_to_page
+#define mfn_to_page(_m) (frame_table + mfn_x(_m))
+#undef mfn_valid
+#define mfn_valid(_mfn) (mfn_x(_mfn) < max_page)
+#undef page_to_mfn
+#define page_to_mfn(_pg) (_mfn((_pg) - frame_table))
+
+/************************************************/
+/*             HAP SUPPORT FUNCTIONS            */
+/************************************************/
+mfn_t hap_alloc(struct domain *d, unsigned long backpointer)
+{
+    struct page_info *sp = NULL;
+    void *p;
+
+    ASSERT(hap_locked_by_me(d));
+
+    sp = list_entry(d->arch.paging.hap.freelists.next, struct page_info, list);
+    list_del(&sp->list);
+    d->arch.paging.hap.free_pages -= 1;
+
+    /* Now safe to clear the page for reuse */
+    p = hap_map_domain_page(page_to_mfn(sp));
+    ASSERT(p != NULL);
+    clear_page(p);
+    hap_unmap_domain_page(p);
+
+    return page_to_mfn(sp);
+}
+
+void hap_free(struct domain *d, mfn_t smfn)
+{
+    struct page_info *sp = mfn_to_page(smfn); 
+
+    ASSERT(hap_locked_by_me(d));
+
+    d->arch.paging.hap.free_pages += 1;
+    list_add_tail(&sp->list, &d->arch.paging.hap.freelists);
+}
+
+static int hap_alloc_p2m_pages(struct domain *d)
+{
+    struct page_info *pg;
+
+    ASSERT(hap_locked_by_me(d));
+
+    pg = mfn_to_page(hap_alloc(d, 0));
+    d->arch.paging.hap.p2m_pages += 1;
+    d->arch.paging.hap.total_pages -= 1;
+    
+    page_set_owner(pg, d);
+    pg->count_info = 1;
+    list_add_tail(&pg->list, &d->arch.paging.hap.p2m_freelist);
+
+    return 1;
+}
+
+struct page_info * hap_alloc_p2m_page(struct domain *d)
+{
+    struct list_head *entry;
+    struct page_info *pg;
+    mfn_t mfn;
+    void *p;
+
+    hap_lock(d);
+    
+    if ( list_empty(&d->arch.paging.hap.p2m_freelist) && 
+         !hap_alloc_p2m_pages(d) ) {
+        hap_unlock(d);
+        return NULL;
+    }
+    entry = d->arch.paging.hap.p2m_freelist.next;
+    list_del(entry);
+    
+    hap_unlock(d);
+
+    pg = list_entry(entry, struct page_info, list);
+    mfn = page_to_mfn(pg);
+    p = hap_map_domain_page(mfn);
+    clear_page(p);
+    hap_unmap_domain_page(p);
+
+    return pg;
+}
+
+void hap_free_p2m_page(struct domain *d, struct page_info *pg)
+{
+    ASSERT(page_get_owner(pg) == d);
+    /* Should have just the one ref we gave it in alloc_p2m_page() */
+    if ( (pg->count_info & PGC_count_mask) != 1 ) {
+        HAP_ERROR("Odd p2m page count c=%#x t=%"PRtype_info"\n",
+                  pg->count_info, pg->u.inuse.type_info);
+    }
+    /* Free should not decrement domain's total allocation, since 
+     * these pages were allocated without an owner. */
+    page_set_owner(pg, NULL); 
+    free_domheap_pages(pg, 0);
+    d->arch.paging.hap.p2m_pages--;
+}
+
+/* Return the size of the pool, rounded up to the nearest MB */
+static unsigned int
+hap_get_allocation(struct domain *d)
+{
+    unsigned int pg = d->arch.paging.hap.total_pages;
+
+    HERE_I_AM;
+    return ((pg >> (20 - PAGE_SHIFT))
+            + ((pg & ((1 << (20 - PAGE_SHIFT)) - 1)) ? 1 : 0));
+}
+
+/* Set the pool of pages to the required number of pages.
+ * Returns 0 for success, non-zero for failure. */
+static unsigned int
+hap_set_allocation(struct domain *d, unsigned int pages, int *preempted)
+{
+    struct page_info *sp;
+
+    ASSERT(hap_locked_by_me(d));
+
+    while ( d->arch.paging.hap.total_pages != pages ) {
+        if ( d->arch.paging.hap.total_pages < pages ) {
+            /* Need to allocate more memory from domheap */
+            sp = alloc_domheap_pages(NULL, 0, 0);
+            if ( sp == NULL ) {
+                HAP_PRINTK("failed to allocate hap pages.\n");
+                return -ENOMEM;
+            }
+            d->arch.paging.hap.free_pages += 1;
+            d->arch.paging.hap.total_pages += 1;
+            list_add_tail(&sp->list, &d->arch.paging.hap.freelists);
+        }
+        else if ( d->arch.paging.hap.total_pages > pages ) {
+            /* Need to return memory to domheap */
+            ASSERT(!list_empty(&d->arch.paging.hap.freelists));
+            sp = list_entry(d->arch.paging.hap.freelists.next,
+                            struct page_info, list);
+            list_del(&sp->list);
+            d->arch.paging.hap.free_pages -= 1;
+            d->arch.paging.hap.total_pages -= 1;
+            free_domheap_pages(sp, 0);
+        }
+        
+        /* Check to see if we need to yield and try again */
+        if ( preempted && hypercall_preempt_check() ) {
+            *preempted = 1;
+            return 0;
+        }
+    }
+
+    return 0;
+}
+
+#if CONFIG_PAGING_LEVELS == 4
+void hap_install_xen_entries_in_l4(struct vcpu *v, mfn_t gl4mfn, mfn_t sl4mfn)
+{
+    struct domain *d = v->domain;
+    l4_pgentry_t *sl4e;
+
+    sl4e = hap_map_domain_page(sl4mfn);
+    ASSERT(sl4e != NULL);
+
+    /* Copy the common Xen mappings from the idle domain */
+    memcpy(&sl4e[ROOT_PAGETABLE_FIRST_XEN_SLOT],
+           &idle_pg_table[ROOT_PAGETABLE_FIRST_XEN_SLOT],
+           ROOT_PAGETABLE_XEN_SLOTS * sizeof(l4_pgentry_t));
+
+    /* Install the per-domain mappings for this domain */
+    sl4e[l4_table_offset(PERDOMAIN_VIRT_START)] =
+        l4e_from_pfn(mfn_x(page_to_mfn(virt_to_page(d->arch.mm_perdomain_l3))),
+                     __PAGE_HYPERVISOR);
+
+    sl4e[l4_table_offset(LINEAR_PT_VIRT_START)] =
+        l4e_from_pfn(mfn_x(gl4mfn), __PAGE_HYPERVISOR);
+
+    /* install domain-specific P2M table */
+    sl4e[l4_table_offset(RO_MPT_VIRT_START)] =
+        l4e_from_pfn(mfn_x(pagetable_get_mfn(d->arch.phys_table)),
+                     __PAGE_HYPERVISOR);
+
+    hap_unmap_domain_page(sl4e);
+}
+#endif /* CONFIG_PAGING_LEVELS == 4 */
+
+#if CONFIG_PAGING_LEVELS == 3
+void hap_install_xen_entries_in_l2h(struct vcpu *v, mfn_t sl2hmfn)
+{
+    struct domain *d = v->domain;
+    l2_pgentry_t *sl2e;
+
+    int i;
+
+    sl2e = hap_map_domain_page(sl2hmfn);
+    ASSERT(sl2e != NULL);
+    
+    /* Copy the common Xen mappings from the idle domain */
+    memcpy(&sl2e[L2_PAGETABLE_FIRST_XEN_SLOT & (L2_PAGETABLE_ENTRIES-1)],
+           &idle_pg_table_l2[L2_PAGETABLE_FIRST_XEN_SLOT],
+           L2_PAGETABLE_XEN_SLOTS * sizeof(l2_pgentry_t));
+
+    /* Install the per-domain mappings for this domain */
+    for ( i = 0; i < PDPT_L2_ENTRIES; i++ )
+        sl2e[l2_table_offset(PERDOMAIN_VIRT_START) + i] =
+            l2e_from_pfn(
+                         
mfn_x(page_to_mfn(virt_to_page(d->arch.mm_perdomain_pt) + i)),
+                         __PAGE_HYPERVISOR);
+    
+    for ( i = 0; i < HAP_L3_PAGETABLE_ENTRIES; i++ )
+        sl2e[l2_table_offset(LINEAR_PT_VIRT_START) + i] =
+            l2e_empty();
+
+    if ( paging_mode_translate(d) )
+    {
+        /* Install the domain-specific p2m table */
+        l3_pgentry_t *p2m;
+        ASSERT(pagetable_get_pfn(d->arch.phys_table) != 0);
+        p2m = hap_map_domain_page(pagetable_get_mfn(d->arch.phys_table));
+        for ( i = 0; i < MACHPHYS_MBYTES>>1; i++ )
+        {
+            sl2e[l2_table_offset(RO_MPT_VIRT_START) + i] =
+                (l3e_get_flags(p2m[i]) & _PAGE_PRESENT)
+                ? l2e_from_pfn(mfn_x(_mfn(l3e_get_pfn(p2m[i]))),
+                                      __PAGE_HYPERVISOR)
+                : l2e_empty();
+        }
+        hap_unmap_domain_page(p2m);
+    }
+
+    hap_unmap_domain_page(sl2e);
+}
+#endif
+
+#if CONFIG_PAGING_LEVELS == 2
+void hap_install_xen_entries_in_l2(struct vcpu *v, mfn_t gl2mfn, mfn_t sl2mfn)
+{
+    struct domain *d = v->domain;
+    l2_pgentry_t *sl2e;
+    int i;
+
+    sl2e = hap_map_domain_page(sl2mfn);
+    ASSERT(sl2e != NULL);
+    
+    /* Copy the common Xen mappings from the idle domain */
+    memcpy(&sl2e[L2_PAGETABLE_FIRST_XEN_SLOT],
+           &idle_pg_table[L2_PAGETABLE_FIRST_XEN_SLOT],
+           L2_PAGETABLE_XEN_SLOTS * sizeof(l2_pgentry_t));
+
+    /* Install the per-domain mappings for this domain */
+    for ( i = 0; i < PDPT_L2_ENTRIES; i++ )
+        sl2e[l2_table_offset(PERDOMAIN_VIRT_START) + i] =
+            l2e_from_pfn(
+                mfn_x(page_to_mfn(virt_to_page(d->arch.mm_perdomain_pt) + i)),
+                __PAGE_HYPERVISOR);
+
+
+    sl2e[l2_table_offset(LINEAR_PT_VIRT_START)] =
+        l2e_from_pfn(mfn_x(gl2mfn), __PAGE_HYPERVISOR);
+
+    /* install domain-specific P2M table */
+    sl2e[l2_table_offset(RO_MPT_VIRT_START)] =
+        l2e_from_pfn(mfn_x(pagetable_get_mfn(d->arch.phys_table)),
+                            __PAGE_HYPERVISOR);
+
+    hap_unmap_domain_page(sl2e);
+}
+#endif
+
+mfn_t hap_make_monitor_table(struct vcpu *v)
+{
+    struct domain *d = v->domain;
+
+    ASSERT(pagetable_get_pfn(v->arch.monitor_table) == 0);
+
+#if CONFIG_PAGING_LEVELS == 4
+    {
+        mfn_t m4mfn;
+        m4mfn = hap_alloc(d, 0);
+        hap_install_xen_entries_in_l4(v, m4mfn, m4mfn);
+        return m4mfn;
+    }
+#elif CONFIG_PAGING_LEVELS == 3
+    {
+        mfn_t m3mfn, m2mfn; 
+        l3_pgentry_t *l3e;
+        l2_pgentry_t *l2e;
+        int i;
+
+        m3mfn = hap_alloc(d, 0);
+
+        /* Install a monitor l2 table in slot 3 of the l3 table.
+         * This is used for all Xen entries, including linear maps
+         */
+        m2mfn = hap_alloc(d, 0);
+        l3e = hap_map_domain_page(m3mfn);
+        l3e[3] = l3e_from_pfn(mfn_x(m2mfn), _PAGE_PRESENT);
+        hap_install_xen_entries_in_l2h(v, m2mfn);
+        /* Install the monitor's own linear map */
+        l2e = hap_map_domain_page(m2mfn);
+        for ( i = 0; i < L3_PAGETABLE_ENTRIES; i++ )
+            l2e[l2_table_offset(LINEAR_PT_VIRT_START) + i] =
+                (l3e_get_flags(l3e[i]) & _PAGE_PRESENT) 
+                ? l2e_from_pfn(l3e_get_pfn(l3e[i]), __PAGE_HYPERVISOR) 
+                : l2e_empty();
+        hap_unmap_domain_page(l2e);
+        hap_unmap_domain_page(l3e);
+
+        HAP_PRINTK("new monitor table: %#lx\n", mfn_x(m3mfn));
+        return m3mfn;
+    }
+#else
+    {
+        mfn_t m2mfn;
+        
+        m2mfn = hap_alloc(d, 0);
+        hap_install_xen_entries_in_l2(v, m2mfn, m2mfn);
+    
+        return m2mfn;
+    }
+#endif
+}
+
+void hap_destroy_monitor_table(struct vcpu* v, mfn_t mmfn)
+{
+    struct domain *d = v->domain;
+
+#if CONFIG_PAGING_LEVELS == 4
+    /* Need to destroy the l3 monitor page in slot 0 too */
+    {
+        mfn_t m3mfn;
+        l4_pgentry_t *l4e = hap_map_domain_page(mmfn);
+        ASSERT(l4e_get_flags(l4e[0]) & _PAGE_PRESENT);
+        m3mfn = _mfn(l4e_get_pfn(l4e[0]));
+        hap_free(d, m3mfn);
+        hap_unmap_domain_page(l4e);
+    }
+#elif CONFIG_PAGING_LEVELS == 3
+    /* Need to destroy the l2 monitor page in slot 4 too */
+    {
+        l3_pgentry_t *l3e = hap_map_domain_page(mmfn);
+        ASSERT(l3e_get_flags(l3e[3]) & _PAGE_PRESENT);
+        hap_free(d, _mfn(l3e_get_pfn(l3e[3])));
+        hap_unmap_domain_page(l3e);
+    }
+#endif
+
+    /* Put the memory back in the pool */
+    hap_free(d, mmfn);
+}
+
+/************************************************/
+/*          HAP DOMAIN LEVEL FUNCTIONS          */
+/************************************************/
+void hap_domain_init(struct domain *d)
+{
+    hap_lock_init(d);
+    INIT_LIST_HEAD(&d->arch.paging.hap.freelists);
+    INIT_LIST_HEAD(&d->arch.paging.hap.p2m_freelist);
+}
+
+/* return 0 for success, -errno for failure */
+int hap_enable(struct domain *d, u32 mode)
+{
+    unsigned int old_pages;
+    int rv = 0;
+
+    HERE_I_AM;
+
+    domain_pause(d);
+    /* error check */
+    if ( (d == current->domain) ) {
+        rv = -EINVAL;
+        goto out;
+    }
+
+    old_pages = d->arch.paging.hap.total_pages;
+    if ( old_pages == 0 ) {
+        unsigned int r;
+        hap_lock(d);
+        r = hap_set_allocation(d, 256, NULL);
+        hap_unlock(d);
+        if ( r != 0 ) {
+            hap_set_allocation(d, 0, NULL);
+            rv = -ENOMEM;
+            goto out;
+        }
+    }
+
+    /* allocate P2m table */
+    if ( mode & PG_translate ) {
+        rv = p2m_alloc_table(d, hap_alloc_p2m_page, hap_free_p2m_page);
+        if ( rv != 0 )
+            goto out;
+    }
+
+    d->arch.paging.mode = mode | PG_SH_enable;
+
+ out:
+    domain_unpause(d);
+    return rv;
+}
+
+void hap_final_teardown(struct domain *d)
+{
+    HERE_I_AM;
+
+    if ( d->arch.paging.hap.total_pages != 0 )
+        hap_teardown(d);
+
+    p2m_teardown(d);
+}
+
+void hap_teardown(struct domain *d)
+{
+    struct vcpu *v;
+    mfn_t mfn;
+    HERE_I_AM;
+
+    ASSERT(test_bit(_DOMF_dying, &d->domain_flags));
+    ASSERT(d != current->domain);
+
+    if ( !hap_locked_by_me(d) )
+        hap_lock(d); /* Keep various asserts happy */
+
+    if ( paging_mode_enabled(d) ) {
+        /* release the monitor table held by each vcpu */
+        for_each_vcpu(d, v) {
+            if ( v->arch.paging.mode && paging_mode_external(d) ) {
+                mfn = pagetable_get_mfn(v->arch.monitor_table);
+                if ( mfn_valid(mfn) && (mfn_x(mfn) != 0) )
+                    hap_destroy_monitor_table(v, mfn);
+                v->arch.monitor_table = pagetable_null();
+            }
+        }
+    }
+
+    if ( d->arch.paging.hap.total_pages != 0 ) {
+        HAP_PRINTK("teardown of domain %u starts."
+                      "  pages total = %u, free = %u, p2m=%u\n",
+                      d->domain_id,
+                      d->arch.paging.hap.total_pages,
+                      d->arch.paging.hap.free_pages,
+                      d->arch.paging.hap.p2m_pages);
+        hap_set_allocation(d, 0, NULL);
+        HAP_PRINTK("teardown done."
+                      "  pages total = %u, free = %u, p2m=%u\n",
+                      d->arch.paging.hap.total_pages,
+                      d->arch.paging.hap.free_pages,
+                      d->arch.paging.hap.p2m_pages);
+        ASSERT(d->arch.paging.hap.total_pages == 0);
+    }
+    
+    d->arch.paging.mode &= ~PG_log_dirty;
+
+    hap_unlock(d);
+}
+
+int hap_domctl(struct domain *d, xen_domctl_shadow_op_t *sc,
+               XEN_GUEST_HANDLE(void) u_domctl)
+{
+    int rc, preempted = 0;
+
+    HERE_I_AM;
+
+    if ( unlikely(d == current->domain) ) {
+        gdprintk(XENLOG_INFO, "Don't try to do a hap op on yourself!\n");
+        return -EINVAL;
+    }
+    
+    switch ( sc->op ) {
+    case XEN_DOMCTL_SHADOW_OP_OFF:
+    case XEN_DOMCTL_SHADOW_OP_ENABLE_TEST:
+    case XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY:
+    case XEN_DOMCTL_SHADOW_OP_ENABLE_TRANSLATE:
+    case XEN_DOMCTL_SHADOW_OP_CLEAN:
+    case XEN_DOMCTL_SHADOW_OP_PEEK:
+    case XEN_DOMCTL_SHADOW_OP_ENABLE:
+        HAP_ERROR("Bad hap domctl op %u\n", sc->op);
+        domain_crash(d);
+        return -EINVAL;
+    case XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION:
+        hap_lock(d);
+        rc = hap_set_allocation(d, sc->mb << (20 - PAGE_SHIFT), &preempted);
+        hap_unlock(d);
+        if ( preempted )
+            /* Not finished.  Set up to re-run the call. */
+            rc = hypercall_create_continuation(__HYPERVISOR_domctl, "h", 
+                                               u_domctl);
+        else
+            /* Finished.  Return the new allocation */
+            sc->mb = hap_get_allocation(d);
+        return rc;
+    case XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION:
+        sc->mb = hap_get_allocation(d);
+        return 0;
+    default:
+        HAP_ERROR("Bad hap domctl op %u\n", sc->op);
+        return -EINVAL;
+    }
+}
+
+void hap_vcpu_init(struct vcpu *v)
+{
+    v->arch.paging.mode = &hap_paging_real_mode;
+}
+/************************************************/
+/*          HAP PAGING MODE FUNCTIONS           */
+/************************************************/
+/* In theory, hap should not intercept guest page fault. This function can 
+ * be recycled to handle host/nested page fault, if needed.
+ */
+int hap_page_fault(struct vcpu *v, unsigned long va, 
+                   struct cpu_user_regs *regs)
+{
+    HERE_I_AM;
+    domain_crash(v->domain);
+    return 0;
+}
+
+/* called when guest issues a invlpg request. 
+ * Return 1 if need to issue page invalidation on CPU; Return 0 if does not
+ * need to do so.
+ */
+int hap_invlpg(struct vcpu *v, unsigned long va)
+{
+    HERE_I_AM;
+    return 0;
+}
+
+void hap_update_cr3(struct vcpu *v, int do_locking)
+{
+    struct domain *d = v->domain;
+    mfn_t gmfn;
+
+    HERE_I_AM;
+    /* Don't do anything on an uninitialised vcpu */
+    if ( !is_hvm_domain(d) && !test_bit(_VCPUF_initialised, &v->vcpu_flags) ) {
+        ASSERT(v->arch.cr3 == 0);
+        return;
+    }
+
+    if ( do_locking )
+        hap_lock(v->domain);
+    
+    ASSERT(hap_locked_by_me(v->domain));
+    ASSERT(v->arch.paging.mode);
+    
+    gmfn = pagetable_get_mfn(v->arch.guest_table);
+
+    make_cr3(v, pagetable_get_pfn(v->arch.monitor_table));
+    
+    hvm_update_guest_cr3(v, pagetable_get_paddr(v->arch.monitor_table));
+
+    HAP_PRINTK("d=%u v=%u guest_table=%05lx, monitor_table = %05lx\n", 
+               d->domain_id, v->vcpu_id, 
+               (unsigned long)pagetable_get_pfn(v->arch.guest_table),
+               (unsigned long)pagetable_get_pfn(v->arch.monitor_table));
+
+    flush_tlb_mask(d->domain_dirty_cpumask);
+
+    if ( do_locking )
+        hap_unlock(v->domain);
+}
+
+void hap_update_paging_modes(struct vcpu *v)
+{
+    struct domain *d;
+
+    HERE_I_AM;
+
+    d = v->domain;
+    hap_lock(d);
+
+    /* update guest paging mode. Note that we rely on hvm functions to detect
+     * guest's paging mode. So, make sure the shadow registers (CR0, CR4, EFER)
+     * reflect guest's status correctly.
+     */
+    if ( hvm_paging_enabled(v) ) {
+        if ( hvm_long_mode_enabled(v) )
+            v->arch.paging.mode = &hap_paging_long_mode;
+        else if ( hvm_pae_enabled(v) )
+            v->arch.paging.mode = &hap_paging_pae_mode;
+        else
+            v->arch.paging.mode = &hap_paging_protected_mode;
+    }
+    else {
+        v->arch.paging.mode = &hap_paging_real_mode;
+    }
+
+    v->arch.paging.translate_enabled = !!hvm_paging_enabled(v);    
+
+    /* use p2m map */
+    v->arch.guest_table =
+        pagetable_from_pfn(pagetable_get_pfn(d->arch.phys_table));
+
+    if ( pagetable_is_null(v->arch.monitor_table) ) {
+        mfn_t mmfn = hap_make_monitor_table(v);
+        v->arch.monitor_table = pagetable_from_mfn(mmfn);
+        make_cr3(v, mfn_x(mmfn));
+    }
+
+    flush_tlb_mask(d->domain_dirty_cpumask);
+    hap_unlock(d);
+}
+
+void 
+hap_write_p2m_entry(struct vcpu *v, unsigned long gfn, l1_pgentry_t *p,
+                    l1_pgentry_t new, unsigned int level)
+{
+    hap_lock(v->domain);
+    safe_write_pte(p, new);
+    hap_unlock(v->domain);
+}
+
+/* Entry points into this mode of the hap code. */
+struct paging_mode hap_paging_real_mode = {
+    .page_fault             = hap_page_fault, 
+    .invlpg                 = hap_invlpg,
+    .gva_to_gfn             = hap_gva_to_gfn_real_mode,
+    .update_cr3             = hap_update_cr3,
+    .update_paging_modes    = hap_update_paging_modes,
+    .write_p2m_entry        = hap_write_p2m_entry,
+    .guest_levels           = 1
+};
+
+struct paging_mode hap_paging_protected_mode = {
+    .page_fault             = hap_page_fault, 
+    .invlpg                 = hap_invlpg,
+    .gva_to_gfn             = hap_gva_to_gfn_protected_mode,
+    .update_cr3             = hap_update_cr3,
+    .update_paging_modes    = hap_update_paging_modes,
+    .write_p2m_entry        = hap_write_p2m_entry,
+    .guest_levels           = 2
+};
+
+struct paging_mode hap_paging_pae_mode = {
+    .page_fault             = hap_page_fault, 
+    .invlpg                 = hap_invlpg,
+    .gva_to_gfn             = hap_gva_to_gfn_pae_mode,
+    .update_cr3             = hap_update_cr3,
+    .update_paging_modes    = hap_update_paging_modes,
+    .write_p2m_entry        = hap_write_p2m_entry,
+    .guest_levels           = 3
+};
+
+struct paging_mode hap_paging_long_mode = {
+    .page_fault             = hap_page_fault, 
+    .invlpg                 = hap_invlpg,
+    .gva_to_gfn             = hap_gva_to_gfn_long_mode,
+    .update_cr3             = hap_update_cr3,
+    .update_paging_modes    = hap_update_paging_modes,
+    .write_p2m_entry        = hap_write_p2m_entry,
+    .guest_levels           = 4
+};
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
+
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/mm/hap/private.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/mm/hap/private.h     Mon Mar 12 10:07:08 2007 -0600
@@ -0,0 +1,112 @@
+/*
+ * arch/x86/mm/hap/private.h
+ *
+ * Copyright (c) 2007, AMD Corporation (Wei Huang)
+ *
+ * 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.
+ *
+ */
+#ifndef __HAP_PRIVATE_H__
+#define __HAP_PRIVATE_H__
+
+#include <asm/flushtlb.h>
+#include <asm/hvm/support.h>
+
+/********************************************/
+/*          GUEST TRANSLATION FUNCS         */
+/********************************************/
+unsigned long hap_gva_to_gfn_real_mode(struct vcpu *v, unsigned long gva);
+unsigned long hap_gva_to_gfn_protected_mode(struct vcpu *v, unsigned long gva);
+unsigned long hap_gva_to_gfn_pae_mode(struct vcpu *v, unsigned long gva);
+unsigned long hap_gva_to_gfn_long_mode(struct vcpu *v, unsigned long gva);
+/********************************************/
+/*            MISC DEFINITIONS              */
+/********************************************/
+
+/* PT_SHIFT describes the amount by which a virtual address is shifted right 
+ * to right justify the portion to be used for indexing into a page 
+ * table, given the guest memory model (i.e. number of levels) and the level 
+ * of the page table being accessed. The idea is from Virtual Iron's code.
+ */
+static const int PT_SHIFT[][5] =
+  {   /*     ------  level ------           nr_levels  */
+    /*         1     2     3     4                   */
+    {    0,    0,    0,    0,    0},   /* 0 not used */
+    {    0,    0,    0,    0,    0},   /* 1 not used */
+    {    0,   12,   22,    0,    0},   /* 2  */
+    {    0,   12,   21,   30,    0},   /* 3  */
+    {    0,   12,   21,   30,   39}    /* 4  */
+  };
+
+/* PT_ENTRIES describes the number of entries in a page table, given the 
+ * memory model (i.e. number of levels) and the level of the page table 
+ * being considered. This idea from Virtual Iron's shadow code*/
+static const int PT_ENTRIES[][5] =
+  {   /*     ------  level ------           nr_levels  */
+    /*         1     2     3     4                   */
+    {    0,    0,    0,    0,    0},   /* 0 not used */
+    {    0,    0,    0,    0,    0},   /* 1 not used */
+    {    0, 1024, 1024,    0,    0},   /* 2  */
+    {    0,  512,  512,    4,    0},   /* 3  */
+    {    0,  512,  512,  512,  512}    /* 4  */
+  };
+
+/********************************************/
+/*       PAGING DEFINITION FOR GUEST        */
+/********************************************/
+#define PHYSICAL_PAGE_4K_SIZE (1UL << 12)
+#define PHYSICAL_PAGE_2M_SIZE (1UL << 21)
+#define PHYSICAL_PAGE_4M_SIZE (1UL << 22)
+#define PHYSICAL_PAGE_4K_MASK ( ~(PHYSICAL_PAGE_4K_SIZE - 1) )
+#define PHYSICAL_PAGE_2M_MASK ( ~(PHYSICAL_PAGE_2M_SIZE - 1) )
+#define PHYSICAL_PAGE_4M_MASK ( ~(PHYSICAL_PAGE_4M_SIZE - 1) )
+
+/* long mode physical address mask */
+#define PHYSICAL_ADDR_BITS_LM    52
+#define PHYSICAL_ADDR_MASK_LM    ((1UL << PHYSICAL_ADDR_BITS_LM)-1)
+#define PHYSICAL_ADDR_2M_MASK_LM (PHYSICAL_PAGE_2M_MASK & 
PHYSICAL_ADDR_MASK_LM)
+#define PHYSICAL_ADDR_4K_MASK_LM (PHYSICAL_PAGE_4K_MASK & 
PHYSICAL_ADDR_MASK_LM)
+
+#define PAGE_NX_BIT      (1ULL << 63)
+/************************************************/
+/*        PAGETABLE RELATED VARIABLES           */
+/************************************************/
+#if CONFIG_PAGING_LEVELS == 2
+#define HAP_L1_PAGETABLE_ENTRIES    1024
+#define HAP_L2_PAGETABLE_ENTRIES    1024
+#define HAP_L1_PAGETABLE_SHIFT        12
+#define HAP_L2_PAGETABLE_SHIFT        22
+#endif
+
+#if CONFIG_PAGING_LEVELS == 3
+#define HAP_L1_PAGETABLE_ENTRIES     512
+#define HAP_L2_PAGETABLE_ENTRIES     512
+#define HAP_L3_PAGETABLE_ENTRIES       4
+#define HAP_L1_PAGETABLE_SHIFT        12
+#define HAP_L2_PAGETABLE_SHIFT        21
+#define HAP_L3_PAGETABLE_SHIFT        30
+#endif
+
+#if CONFIG_PAGING_LEVELS == 4
+#define HAP_L1_PAGETABLE_ENTRIES     512
+#define HAP_L2_PAGETABLE_ENTRIES     512
+#define HAP_L3_PAGETABLE_ENTRIES     512
+#define HAP_L4_PAGETABLE_ENTRIES     512
+#define HAP_L1_PAGETABLE_SHIFT        12
+#define HAP_L2_PAGETABLE_SHIFT        21
+#define HAP_L3_PAGETABLE_SHIFT        30
+#define HAP_L4_PAGETABLE_SHIFT        39
+#endif
+
+#endif /* __SVM_NPT_H__ */
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/mm/hap/support.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/mm/hap/support.c     Mon Mar 12 10:07:08 2007 -0600
@@ -0,0 +1,334 @@
+/*
+ * arch/x86/mm/hap/support.c
+ * 
+ * guest page table walker
+ * Copyright (c) 2007, AMD Corporation (Wei Huang)
+ *
+ * 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 <xen/config.h>
+#include <xen/types.h>
+#include <xen/mm.h>
+#include <xen/domain_page.h>
+#include <asm/page.h>
+#include <xen/event.h>
+#include <xen/sched.h>
+#include <asm/hvm/svm/vmcb.h>
+#include <asm/domain.h>
+#include <asm/shadow.h>
+#include <asm/hap.h>
+
+#include "private.h"
+#include "../page-guest32.h"
+
+/*******************************************/
+/*      Platform Specific Functions        */
+/*******************************************/
+
+/* Translate guest virtual address to guest physical address. Specifically
+ * for real mode guest. 
+ */
+unsigned long hap_gva_to_gfn_real_mode(struct vcpu *v, unsigned long gva)
+{
+    HERE_I_AM;
+    return ((paddr_t)gva >> PAGE_SHIFT);
+}
+
+/* Translate guest virtual address to guest physical address. Specifically
+ * for protected guest. 
+ */
+unsigned long hap_gva_to_gfn_protected_mode(struct vcpu *v, unsigned long gva)
+{
+    unsigned long gcr3 = hvm_get_guest_ctrl_reg(v, 3);
+    int mode = 2; /* two-level guest */
+    int lev, index;
+    paddr_t gpa = 0;
+    unsigned long gpfn, mfn;
+    int success = 1;
+    l2_pgentry_32_t *l2e; /* guest page entry size is 32-bit */
+    l1_pgentry_32_t *l1e;
+
+    HERE_I_AM;
+
+    gpfn = (gcr3 >> PAGE_SHIFT);
+    for ( lev = mode; lev >= 1; lev-- ) {
+        mfn = get_mfn_from_gpfn( gpfn );
+        if ( mfn == INVALID_MFN ) {
+            HAP_PRINTK("bad pfn=0x%lx from gva=0x%lx at lev%d\n", gpfn, gva, 
+                       lev);
+            success = 0;
+            break;
+        }
+        index = (gva >> PT_SHIFT[mode][lev]) & (PT_ENTRIES[mode][lev]-1);
+
+        if ( lev == 2 ) {
+            l2e = map_domain_page( mfn );
+            HAP_PRINTK("l2 page table entry is %ulx at index = %d\n", 
+                       l2e[index].l2, index);
+            if ( !(l2e_get_flags_32(l2e[index]) & _PAGE_PRESENT) ) {
+                HAP_PRINTK("Level 2 entry not present at index = %d\n", index);
+                success = 0;
+            }
+
+            if ( l2e_get_flags_32(l2e[index]) & _PAGE_PSE ) { /* handle PSE */
+                HAP_PRINTK("guest page table is PSE\n");
+                if ( l2e_get_intpte(l2e[index]) & 0x001FE000UL ) { /*[13:20] */
+                    printk("guest physical memory size is too large!\n");
+                    domain_crash(v->domain);
+                }
+                gpa = (l2e_get_intpte(l2e[index]) & PHYSICAL_PAGE_4M_MASK) + 
+                    (gva & ~PHYSICAL_PAGE_4M_MASK);
+                unmap_domain_page(l2e);
+                break; /* last level page table, return from here */
+            }
+            else {
+                gpfn = l2e_get_pfn( l2e[index] );
+            }
+            unmap_domain_page(l2e);
+        }
+
+        if ( lev == 1 ) {
+            l1e = map_domain_page( mfn );
+            HAP_PRINTK("l1 page table entry is %ulx at index = %d\n", 
+                       l1e[index].l1, index);
+            if ( !(l1e_get_flags_32(l1e[index]) & _PAGE_PRESENT) ) {
+                HAP_PRINTK("Level 1 entry not present at index = %d\n", index);
+                success = 0;
+            }
+            gpfn = l1e_get_pfn( l1e[index] );
+            gpa = (l1e_get_intpte(l1e[index]) & PHYSICAL_PAGE_4K_MASK) + 
+                (gva & ~PHYSICAL_PAGE_4K_MASK);            
+            unmap_domain_page(l1e);
+        }
+
+        if ( !success ) /* error happened, jump out */
+            break;
+    }
+
+    HAP_PRINTK("success = %d, gva = %lx, gpa = %lx\n", success, gva, gpa);
+
+    if ( !success ) /* error happened */
+        return INVALID_GFN;
+    else
+        return ((paddr_t)gpa >> PAGE_SHIFT);
+}
+
+
+
+/* Translate guest virtual address to guest physical address. Specifically
+ * for PAE mode guest. 
+ */
+unsigned long hap_gva_to_gfn_pae_mode(struct vcpu *v, unsigned long gva)
+{
+#if CONFIG_PAGING_LEVELS >= 3
+    unsigned long gcr3 = hvm_get_guest_ctrl_reg(v, 3);
+    int mode = 3; /* three-level guest */
+    int lev, index;
+    paddr_t gpa = 0;
+    unsigned long gpfn, mfn;
+    int success = 1;
+    l1_pgentry_t *l1e;
+    l2_pgentry_t *l2e;
+    l3_pgentry_t *l3e;
+    
+    HERE_I_AM;
+
+    gpfn = (gcr3 >> PAGE_SHIFT);
+    for ( lev = mode; lev >= 1; lev-- ) {
+        mfn = get_mfn_from_gpfn( gpfn );
+        if ( mfn == INVALID_MFN ) {
+            HAP_PRINTK("bad pfn=0x%lx from gva=0x%lx at lev%d\n", gpfn, gva, 
+                       lev);
+            success = 0;
+            break;
+        }
+        index = (gva >> PT_SHIFT[mode][lev]) & (PT_ENTRIES[mode][lev]-1);
+
+        if ( lev == 3 ) {
+            l3e = map_domain_page( mfn );
+            index += ( ((gcr3 >> 5 ) & 127 ) * 4 );
+            if ( !(l3e_get_flags(l3e[index]) & _PAGE_PRESENT) ) {
+                HAP_PRINTK("Level 3 entry not present at index = %d\n", index);
+                success = 0;
+            }
+            gpfn = l3e_get_pfn( l3e[index] );
+            unmap_domain_page(l3e);
+        }
+
+        if ( lev == 2 ) {
+            l2e = map_domain_page( mfn );
+            if ( !(l2e_get_flags(l2e[index]) & _PAGE_PRESENT) ) {
+                HAP_PRINTK("Level 2 entry not present at index = %d\n", index);
+                success = 0;
+            }
+
+            if ( l2e_get_flags(l2e[index]) & _PAGE_PSE ) { /* handle PSE */
+                HAP_PRINTK("guest page table is PSE\n");
+                gpa = (l2e_get_intpte(l2e[index]) & PHYSICAL_PAGE_2M_MASK) + 
+                    (gva & ~PHYSICAL_PAGE_2M_MASK);
+                unmap_domain_page(l2e);
+                break; /* last level page table, jump out from here */
+            }
+            else { 
+                gpfn = l2e_get_pfn(l2e[index]);
+            }
+            unmap_domain_page(l2e);
+        }
+
+        if ( lev == 1 ) {
+            l1e = map_domain_page( mfn );
+            if ( !(l1e_get_flags(l1e[index]) & _PAGE_PRESENT) ) {
+                HAP_PRINTK("Level 1 entry not present at index = %d\n", index);
+                success = 0;
+            }
+            gpfn = l1e_get_pfn( l1e[index] );
+            gpa = (l1e_get_intpte(l1e[index]) & PHYSICAL_PAGE_4K_MASK) + 
+                (gva & ~PHYSICAL_PAGE_4K_MASK);
+            unmap_domain_page(l1e);
+        }
+
+        if ( success != 1 ) /* error happened, jump out */
+            break;
+    }
+
+    gpa &= ~PAGE_NX_BIT; /* clear NX bit of guest physical address */
+    HAP_PRINTK("success = %d, gva = %lx, gpa = %lx\n", success, gva, gpa);
+
+    if ( !success )
+        return INVALID_GFN;
+    else
+        return ((paddr_t)gpa >> PAGE_SHIFT);
+#else
+    HERE_I_AM;
+    printk("guest paging level (3) is greater than host paging level!\n");
+    domain_crash(v->domain);
+    return INVALID_GFN;
+#endif
+}
+
+
+
+/* Translate guest virtual address to guest physical address. Specifically
+ * for long mode guest. 
+ */
+unsigned long hap_gva_to_gfn_long_mode(struct vcpu *v, unsigned long gva)
+{
+#if CONFIG_PAGING_LEVELS == 4
+    unsigned long gcr3 = hvm_get_guest_ctrl_reg(v, 3);
+    int mode = 4; /* four-level guest */
+    int lev, index;
+    paddr_t gpa = 0;
+    unsigned long gpfn, mfn;
+    int success = 1;
+    l4_pgentry_t *l4e;
+    l3_pgentry_t *l3e;
+    l2_pgentry_t *l2e;
+    l1_pgentry_t *l1e;
+
+    HERE_I_AM;
+
+    gpfn = (gcr3 >> PAGE_SHIFT);
+    for ( lev = mode; lev >= 1; lev-- ) {
+        mfn = get_mfn_from_gpfn( gpfn );
+        if ( mfn == INVALID_MFN ) {
+            HAP_PRINTK("bad pfn=0x%lx from gva=0x%lx at lev%d\n", gpfn, gva, 
+                       lev);
+            success = 0;
+            break;
+        }
+        index = (gva >> PT_SHIFT[mode][lev]) & (PT_ENTRIES[mode][lev]-1);
+
+        if ( lev == 4 ) {
+            l4e = map_domain_page( mfn );
+            if ( !(l4e_get_flags(l4e[index]) & _PAGE_PRESENT) ) {
+                HAP_PRINTK("Level 4 entry not present at index = %d\n", index);
+                success = 0;
+            }
+            gpfn = l4e_get_pfn( l4e[index] );
+            unmap_domain_page(l4e);
+        }
+
+        if ( lev == 3 ) {
+            l3e = map_domain_page( mfn );
+            if ( !(l3e_get_flags(l3e[index]) & _PAGE_PRESENT) ) {
+                HAP_PRINTK("Level 3 entry not present at index = %d\n", index);
+                success = 0;
+            }
+            gpfn = l3e_get_pfn( l3e[index] );
+            unmap_domain_page(l3e);
+        }
+
+        if ( lev == 2 ) {
+            l2e = map_domain_page( mfn );
+            if ( !(l2e_get_flags(l2e[index]) & _PAGE_PRESENT) ) {
+                HAP_PRINTK("Level 2 entry not present at index = %d\n", index);
+                success = 0;
+            }
+
+            if ( l2e_get_flags(l2e[index]) & _PAGE_PSE ) { /* handle PSE */
+                HAP_PRINTK("guest page table is PSE\n");
+                gpa = (l2e_get_intpte(l2e[index]) & PHYSICAL_ADDR_2M_MASK_LM) 
+                    + (gva & ~PHYSICAL_PAGE_2M_MASK);
+                unmap_domain_page(l2e);
+                break; /* last level page table, jump out from here */
+            }
+            else { 
+                gpfn = l2e_get_pfn(l2e[index]);
+            }
+            unmap_domain_page(l2e);
+        }
+
+        if ( lev == 1 ) {
+            l1e = map_domain_page( mfn );
+            if ( !(l1e_get_flags(l1e[index]) & _PAGE_PRESENT) ) {
+                HAP_PRINTK("Level 1 entry not present at index = %d\n", index);
+                success = 0;
+            }
+            gpfn = l1e_get_pfn( l1e[index] );
+            gpa = (l1e_get_intpte(l1e[index]) & PHYSICAL_ADDR_4K_MASK_LM) + 
+                (gva & ~PHYSICAL_PAGE_4K_MASK);
+            unmap_domain_page(l1e);
+        }
+
+        if ( success != 1 ) /* error happened, jump out */
+            break;
+    }
+
+    gpa &= ~PAGE_NX_BIT; /* clear NX bit of guest physical address */
+    HAP_PRINTK("success = %d, gva = %lx, gpa = %lx\n", success, gva, gpa);
+
+    if ( !success )
+        return INVALID_GFN;
+    else
+        return ((paddr_t)gpa >> PAGE_SHIFT);
+#else
+    HERE_I_AM;
+    printk("guest paging level (4) is greater than host paging level!\n");
+    domain_crash(v->domain);
+    return INVALID_GFN;
+#endif
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/mm/page-guest32.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/mm/page-guest32.h    Mon Mar 12 10:07:08 2007 -0600
@@ -0,0 +1,100 @@
+
+#ifndef __X86_PAGE_GUEST_H__
+#define __X86_PAGE_GUEST_H__
+
+#ifndef __ASSEMBLY__
+# include <asm/types.h>
+#endif
+
+#define PAGETABLE_ORDER_32         10
+#define L1_PAGETABLE_ENTRIES_32    (1<<PAGETABLE_ORDER_32)
+#define L2_PAGETABLE_ENTRIES_32    (1<<PAGETABLE_ORDER_32)
+#define ROOT_PAGETABLE_ENTRIES_32  L2_PAGETABLE_ENTRIES_32
+
+
+#define L1_PAGETABLE_SHIFT_32 12
+#define L2_PAGETABLE_SHIFT_32 22
+
+/* Extract flags into 12-bit integer, or turn 12-bit flags into a pte mask. */
+
+#ifndef __ASSEMBLY__
+
+typedef u32 intpte_32_t;
+
+typedef struct { intpte_32_t l1; } l1_pgentry_32_t;
+typedef struct { intpte_32_t l2; } l2_pgentry_32_t;
+typedef l2_pgentry_t root_pgentry_32_t;
+#endif
+
+#define get_pte_flags_32(x) ((u32)(x) & 0xFFF)
+#define put_pte_flags_32(x) ((intpte_32_t)(x))
+
+/* Get pte access flags (unsigned int). */
+#define l1e_get_flags_32(x)           (get_pte_flags_32((x).l1))
+#define l2e_get_flags_32(x)           (get_pte_flags_32((x).l2))
+
+#define l1e_get_paddr_32(x)           \
+    ((paddr_t)(((x).l1 & (PADDR_MASK&PAGE_MASK))))
+#define l2e_get_paddr_32(x)           \
+    ((paddr_t)(((x).l2 & (PADDR_MASK&PAGE_MASK))))
+
+/* Construct an empty pte. */
+#define l1e_empty_32()                ((l1_pgentry_32_t) { 0 })
+#define l2e_empty_32()                ((l2_pgentry_32_t) { 0 })
+
+/* Construct a pte from a pfn and access flags. */
+#define l1e_from_pfn_32(pfn, flags)   \
+    ((l1_pgentry_32_t) { ((intpte_32_t)(pfn) << PAGE_SHIFT) | 
put_pte_flags_32(flags) })
+#define l2e_from_pfn_32(pfn, flags)   \
+    ((l2_pgentry_32_t) { ((intpte_32_t)(pfn) << PAGE_SHIFT) | 
put_pte_flags_32(flags) })
+
+/* Construct a pte from a physical address and access flags. */
+#ifndef __ASSEMBLY__
+static inline l1_pgentry_32_t l1e_from_paddr_32(paddr_t pa, unsigned int flags)
+{
+    ASSERT((pa & ~(PADDR_MASK & PAGE_MASK)) == 0);
+    return (l1_pgentry_32_t) { pa | put_pte_flags_32(flags) };
+}
+static inline l2_pgentry_32_t l2e_from_paddr_32(paddr_t pa, unsigned int flags)
+{
+    ASSERT((pa & ~(PADDR_MASK & PAGE_MASK)) == 0);
+    return (l2_pgentry_32_t) { pa | put_pte_flags_32(flags) };
+}
+#endif /* !__ASSEMBLY__ */
+
+
+/* Construct a pte from a page pointer and access flags. */
+#define l1e_from_page_32(page, flags) 
(l1e_from_pfn_32(page_to_mfn(page),(flags)))
+#define l2e_from_page_32(page, flags) 
(l2e_from_pfn_32(page_to_mfn(page),(flags)))
+
+/* Add extra flags to an existing pte. */
+#define l1e_add_flags_32(x, flags)    ((x).l1 |= put_pte_flags_32(flags))
+#define l2e_add_flags_32(x, flags)    ((x).l2 |= put_pte_flags_32(flags))
+
+/* Remove flags from an existing pte. */
+#define l1e_remove_flags_32(x, flags) ((x).l1 &= ~put_pte_flags_32(flags))
+#define l2e_remove_flags_32(x, flags) ((x).l2 &= ~put_pte_flags_32(flags))
+
+/* Check if a pte's page mapping or significant access flags have changed. */
+#define l1e_has_changed_32(x,y,flags) \
+    ( !!(((x).l1 ^ (y).l1) & ((PADDR_MASK&PAGE_MASK)|put_pte_flags_32(flags))) 
)
+#define l2e_has_changed_32(x,y,flags) \
+    ( !!(((x).l2 ^ (y).l2) & ((PADDR_MASK&PAGE_MASK)|put_pte_flags_32(flags))) 
)
+
+/* Given a virtual address, get an entry offset into a page table. */
+#define l1_table_offset_32(a)         \
+    (((a) >> L1_PAGETABLE_SHIFT_32) & (L1_PAGETABLE_ENTRIES_32 - 1))
+#define l2_table_offset_32(a)         \
+    (((a) >> L2_PAGETABLE_SHIFT_32) & (L2_PAGETABLE_ENTRIES_32 - 1))
+
+#endif /* __X86_PAGE_GUEST_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/mm/paging.c
--- a/xen/arch/x86/mm/paging.c  Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/x86/mm/paging.c  Mon Mar 12 10:07:08 2007 -0600
@@ -24,10 +24,12 @@
 #include <asm/paging.h>
 #include <asm/shadow.h>
 #include <asm/p2m.h>
+#include <asm/hap.h>
 
 /* Xen command-line option to enable hardware-assisted paging */
 int opt_hap_enabled = 0; 
 boolean_param("hap", opt_hap_enabled);
+int hap_capable_system = 0;
 
 /* Printouts */
 #define PAGING_PRINTK(_f, _a...)                                     \
@@ -46,12 +48,18 @@ void paging_domain_init(struct domain *d
 {
     p2m_init(d);
     shadow_domain_init(d);
+
+    if ( opt_hap_enabled && hap_capable_system && is_hvm_domain(d) )
+        hap_domain_init(d);
 }
 
 /* vcpu paging struct initialization goes here */
 void paging_vcpu_init(struct vcpu *v)
 {
-    shadow_vcpu_init(v);
+    if ( opt_hap_enabled && hap_capable_system && is_hvm_vcpu(v) )
+        hap_vcpu_init(v);
+    else
+        shadow_vcpu_init(v);
 }
 
 
@@ -59,32 +67,38 @@ int paging_domctl(struct domain *d, xen_
                   XEN_GUEST_HANDLE(void) u_domctl)
 {
     /* Here, dispatch domctl to the appropriate paging code */
-    return shadow_domctl(d, sc, u_domctl);
+    if ( opt_hap_enabled && hap_capable_system && is_hvm_domain(d) )
+        return hap_domctl(d, sc, u_domctl);
+    else
+        return shadow_domctl(d, sc, u_domctl);
 }
 
 /* Call when destroying a domain */
 void paging_teardown(struct domain *d)
 {
-    shadow_teardown(d);
-    /* Call other modes' teardown code here */    
+    if ( opt_hap_enabled && hap_capable_system && is_hvm_domain(d) )
+        hap_teardown(d);
+    else
+        shadow_teardown(d);
 }
 
 /* Call once all of the references to the domain have gone away */
 void paging_final_teardown(struct domain *d)
 {
-    shadow_teardown(d);
-    /* Call other modes' final teardown code here */
+    if ( opt_hap_enabled && hap_capable_system && is_hvm_domain(d) )
+        hap_final_teardown(d);
+    else
+        shadow_final_teardown(d);
 }
 
 /* Enable an arbitrary paging-assistance mode.  Call once at domain
  * creation. */
 int paging_enable(struct domain *d, u32 mode)
 {
-    if ( mode & PG_SH_enable ) 
-        return shadow_enable(d, mode);
+    if ( opt_hap_enabled && hap_capable_system && is_hvm_domain(d) )
+        return hap_enable(d, mode | PG_HAP_enable);
     else
-        /* No other modes supported yet */
-        return -EINVAL; 
+        return shadow_enable(d, mode | PG_SH_enable);
 }
 
 /* Print paging-assistance info to the console */
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/mm/shadow/common.c
--- a/xen/arch/x86/mm/shadow/common.c   Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/x86/mm/shadow/common.c   Mon Mar 12 10:07:08 2007 -0600
@@ -802,7 +802,7 @@ void shadow_prealloc(struct domain *d, u
     v = current;
     if ( v->domain != d )
         v = d->vcpu[0];
-    ASSERT(v != NULL);
+    ASSERT(v != NULL); /* Shouldn't have enabled shadows if we've no vcpus  */
 
     /* Stage one: walk the list of pinned pages, unpinning them */
     perfc_incrc(shadow_prealloc_1);
@@ -861,7 +861,9 @@ static void shadow_blow_tables(struct do
     struct vcpu *v = d->vcpu[0];
     mfn_t smfn;
     int i;
-    
+
+    ASSERT(v != NULL);
+
     /* Pass one: unpin all pinned pages */
     list_for_each_backwards_safe(l,t, &d->arch.paging.shadow.pinned_shadows)
     {
@@ -1129,6 +1131,7 @@ shadow_free_p2m_page(struct domain *d, s
         SHADOW_ERROR("Odd p2m page count c=%#x t=%"PRtype_info"\n",
                      pg->count_info, pg->u.inuse.type_info);
     }
+    pg->count_info = 0;
     /* Free should not decrement domain's total allocation, since 
      * these pages were allocated without an owner. */
     page_set_owner(pg, NULL); 
@@ -1243,6 +1246,9 @@ static unsigned int sh_set_allocation(st
             list_del(&sp->list);
             d->arch.paging.shadow.free_pages -= 1<<SHADOW_MAX_ORDER;
             d->arch.paging.shadow.total_pages -= 1<<SHADOW_MAX_ORDER;
+            for ( j = 0; j < 1<<SHADOW_MAX_ORDER; j++ ) 
+                /* Keep the page allocator happy */
+                ((struct page_info *)sp)[j].count_info = 0;
             free_domheap_pages((struct page_info *)sp, SHADOW_MAX_ORDER);
         }
 
@@ -2989,6 +2995,13 @@ int shadow_domctl(struct domain *d,
         return 0;
     }
 
+    if ( unlikely(d->vcpu[0] == NULL) )
+    {
+        SHADOW_ERROR("Shadow op on a domain (%u) with no vcpus\n",
+                     d->domain_id);
+        return -EINVAL;
+    }
+
     switch ( sc->op )
     {
     case XEN_DOMCTL_SHADOW_OP_OFF:
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/mm/shadow/page-guest32.h
--- a/xen/arch/x86/mm/shadow/page-guest32.h     Mon Mar 12 09:43:48 2007 -0600
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-
-#ifndef __X86_PAGE_GUEST_H__
-#define __X86_PAGE_GUEST_H__
-
-#ifndef __ASSEMBLY__
-# include <asm/types.h>
-#endif
-
-#define PAGETABLE_ORDER_32         10
-#define L1_PAGETABLE_ENTRIES_32    (1<<PAGETABLE_ORDER_32)
-#define L2_PAGETABLE_ENTRIES_32    (1<<PAGETABLE_ORDER_32)
-#define ROOT_PAGETABLE_ENTRIES_32  L2_PAGETABLE_ENTRIES_32
-
-
-#define L1_PAGETABLE_SHIFT_32 12
-#define L2_PAGETABLE_SHIFT_32 22
-
-/* Extract flags into 12-bit integer, or turn 12-bit flags into a pte mask. */
-
-#ifndef __ASSEMBLY__
-
-typedef u32 intpte_32_t;
-
-typedef struct { intpte_32_t l1; } l1_pgentry_32_t;
-typedef struct { intpte_32_t l2; } l2_pgentry_32_t;
-typedef l2_pgentry_t root_pgentry_32_t;
-#endif
-
-#define get_pte_flags_32(x) ((u32)(x) & 0xFFF)
-#define put_pte_flags_32(x) ((intpte_32_t)(x))
-
-/* Get pte access flags (unsigned int). */
-#define l1e_get_flags_32(x)           (get_pte_flags_32((x).l1))
-#define l2e_get_flags_32(x)           (get_pte_flags_32((x).l2))
-
-#define l1e_get_paddr_32(x)           \
-    ((paddr_t)(((x).l1 & (PADDR_MASK&PAGE_MASK))))
-#define l2e_get_paddr_32(x)           \
-    ((paddr_t)(((x).l2 & (PADDR_MASK&PAGE_MASK))))
-
-/* Construct an empty pte. */
-#define l1e_empty_32()                ((l1_pgentry_32_t) { 0 })
-#define l2e_empty_32()                ((l2_pgentry_32_t) { 0 })
-
-/* Construct a pte from a pfn and access flags. */
-#define l1e_from_pfn_32(pfn, flags)   \
-    ((l1_pgentry_32_t) { ((intpte_32_t)(pfn) << PAGE_SHIFT) | 
put_pte_flags_32(flags) })
-#define l2e_from_pfn_32(pfn, flags)   \
-    ((l2_pgentry_32_t) { ((intpte_32_t)(pfn) << PAGE_SHIFT) | 
put_pte_flags_32(flags) })
-
-/* Construct a pte from a physical address and access flags. */
-#ifndef __ASSEMBLY__
-static inline l1_pgentry_32_t l1e_from_paddr_32(paddr_t pa, unsigned int flags)
-{
-    ASSERT((pa & ~(PADDR_MASK & PAGE_MASK)) == 0);
-    return (l1_pgentry_32_t) { pa | put_pte_flags_32(flags) };
-}
-static inline l2_pgentry_32_t l2e_from_paddr_32(paddr_t pa, unsigned int flags)
-{
-    ASSERT((pa & ~(PADDR_MASK & PAGE_MASK)) == 0);
-    return (l2_pgentry_32_t) { pa | put_pte_flags_32(flags) };
-}
-#endif /* !__ASSEMBLY__ */
-
-
-/* Construct a pte from a page pointer and access flags. */
-#define l1e_from_page_32(page, flags) 
(l1e_from_pfn_32(page_to_mfn(page),(flags)))
-#define l2e_from_page_32(page, flags) 
(l2e_from_pfn_32(page_to_mfn(page),(flags)))
-
-/* Add extra flags to an existing pte. */
-#define l1e_add_flags_32(x, flags)    ((x).l1 |= put_pte_flags_32(flags))
-#define l2e_add_flags_32(x, flags)    ((x).l2 |= put_pte_flags_32(flags))
-
-/* Remove flags from an existing pte. */
-#define l1e_remove_flags_32(x, flags) ((x).l1 &= ~put_pte_flags_32(flags))
-#define l2e_remove_flags_32(x, flags) ((x).l2 &= ~put_pte_flags_32(flags))
-
-/* Check if a pte's page mapping or significant access flags have changed. */
-#define l1e_has_changed_32(x,y,flags) \
-    ( !!(((x).l1 ^ (y).l1) & ((PADDR_MASK&PAGE_MASK)|put_pte_flags_32(flags))) 
)
-#define l2e_has_changed_32(x,y,flags) \
-    ( !!(((x).l2 ^ (y).l2) & ((PADDR_MASK&PAGE_MASK)|put_pte_flags_32(flags))) 
)
-
-/* Given a virtual address, get an entry offset into a page table. */
-#define l1_table_offset_32(a)         \
-    (((a) >> L1_PAGETABLE_SHIFT_32) & (L1_PAGETABLE_ENTRIES_32 - 1))
-#define l2_table_offset_32(a)         \
-    (((a) >> L2_PAGETABLE_SHIFT_32) & (L2_PAGETABLE_ENTRIES_32 - 1))
-
-#endif /* __X86_PAGE_GUEST_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/mm/shadow/types.h
--- a/xen/arch/x86/mm/shadow/types.h    Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/x86/mm/shadow/types.h    Mon Mar 12 10:07:08 2007 -0600
@@ -235,7 +235,7 @@ static inline shadow_l4e_t shadow_l4e_fr
 
 #if GUEST_PAGING_LEVELS == 2
 
-#include "page-guest32.h"
+#include "../page-guest32.h"
 
 #define GUEST_L1_PAGETABLE_ENTRIES     1024
 #define GUEST_L2_PAGETABLE_ENTRIES     1024
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/x86/setup.c      Mon Mar 12 10:07:08 2007 -0600
@@ -195,13 +195,13 @@ static void __init percpu_free_unused_ar
 
     /* Find first unused CPU number. */
     for ( i = 0; i < NR_CPUS; i++ )
-        if ( !cpu_online(i) )
+        if ( !cpu_possible(i) )
             break;
     first_unused = i;
 
-    /* Check that there are no holes in cpu_online_map. */
+    /* Check that there are no holes in cpu_possible_map. */
     for ( ; i < NR_CPUS; i++ )
-        BUG_ON(cpu_online(i));
+        BUG_ON(cpu_possible(i));
 
 #ifndef MEMORY_GUARD
     init_xenheap_pages(__pa(__per_cpu_start) + (first_unused << PERCPU_SHIFT),
@@ -717,8 +717,6 @@ void __init __start_xen(multiboot_info_t
 
     do_initcalls();
 
-    schedulers_start();
-
     if ( opt_watchdog ) 
         watchdog_enable();
 
diff -r d1853a39e063 -r cb2575cec95c xen/common/compat/domain.c
--- a/xen/common/compat/domain.c        Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/common/compat/domain.c        Mon Mar 12 10:07:08 2007 -0600
@@ -55,6 +55,10 @@ int compat_vcpu_op(int cmd, int vcpuid, 
     case VCPUOP_up:
     case VCPUOP_down:
     case VCPUOP_is_up:
+    case VCPUOP_set_periodic_timer:
+    case VCPUOP_stop_periodic_timer:
+    case VCPUOP_set_singleshot_timer:
+    case VCPUOP_stop_singleshot_timer:
         rc = do_vcpu_op(cmd, vcpuid, arg);
         break;
 
diff -r d1853a39e063 -r cb2575cec95c xen/common/domain.c
--- a/xen/common/domain.c       Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/common/domain.c       Mon Mar 12 10:07:08 2007 -0600
@@ -267,6 +267,9 @@ void domain_kill(struct domain *d)
     domain_relinquish_resources(d);
     put_domain(d);
 
+    /* Kick page scrubbing after domain_relinquish_resources(). */
+    page_scrub_kick();
+
     send_guest_global_virq(dom0, VIRQ_DOM_EXC);
 }
 
@@ -543,16 +546,12 @@ long do_vcpu_op(int cmd, int vcpuid, XEN
     {
     case VCPUOP_initialise:
         if ( (ctxt = xmalloc(struct vcpu_guest_context)) == NULL )
-        {
-            rc = -ENOMEM;
-            break;
-        }
+            return -ENOMEM;
 
         if ( copy_from_guest(ctxt, arg, 1) )
         {
             xfree(ctxt);
-            rc = -EFAULT;
-            break;
+            return -EFAULT;
         }
 
         LOCK_BIGLOCK(d);
@@ -566,9 +565,11 @@ long do_vcpu_op(int cmd, int vcpuid, XEN
 
     case VCPUOP_up:
         if ( !test_bit(_VCPUF_initialised, &v->vcpu_flags) )
-            rc = -EINVAL;
-        else if ( test_and_clear_bit(_VCPUF_down, &v->vcpu_flags) )
+            return -EINVAL;
+
+        if ( test_and_clear_bit(_VCPUF_down, &v->vcpu_flags) )
             vcpu_wake(v);
+
         break;
 
     case VCPUOP_down:
@@ -586,6 +587,63 @@ long do_vcpu_op(int cmd, int vcpuid, XEN
         vcpu_runstate_get(v, &runstate);
         if ( copy_to_guest(arg, &runstate, 1) )
             rc = -EFAULT;
+        break;
+    }
+
+    case VCPUOP_set_periodic_timer:
+    {
+        struct vcpu_set_periodic_timer set;
+
+        if ( copy_from_guest(&set, arg, 1) )
+            return -EFAULT;
+
+        if ( set.period_ns < MILLISECS(1) )
+            return -EINVAL;
+
+        v->periodic_period = set.period_ns;
+        vcpu_force_reschedule(v);
+
+        break;
+    }
+
+    case VCPUOP_stop_periodic_timer:
+    {
+        v->periodic_period = 0;
+        vcpu_force_reschedule(v);
+        break;
+    }
+
+    case VCPUOP_set_singleshot_timer:
+    {
+        struct vcpu_set_singleshot_timer set;
+
+        if ( v != current )
+            return -EINVAL;
+
+        if ( copy_from_guest(&set, arg, 1) )
+            return -EFAULT;
+
+        if ( (set.flags & VCPU_SSHOTTMR_future) &&
+             (set.timeout_abs_ns < NOW()) )
+            return -ETIME;
+
+        if ( v->singleshot_timer.cpu != smp_processor_id() )
+        {
+            stop_timer(&v->singleshot_timer);
+            v->singleshot_timer.cpu = smp_processor_id();
+        }
+
+        set_timer(&v->singleshot_timer, set.timeout_abs_ns);
+
+        break;
+    }
+
+    case VCPUOP_stop_singleshot_timer:
+    {
+        if ( v != current )
+            return -EINVAL;
+
+        stop_timer(&v->singleshot_timer);
         break;
     }
 
diff -r d1853a39e063 -r cb2575cec95c xen/common/event_channel.c
--- a/xen/common/event_channel.c        Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/common/event_channel.c        Mon Mar 12 10:07:08 2007 -0600
@@ -560,6 +560,9 @@ void send_guest_global_virq(struct domai
 
     ASSERT(virq_is_global(virq));
 
+    if ( unlikely(d == NULL) )
+        return;
+
     v = d->vcpu[0];
     if ( unlikely(v == NULL) )
         return;
diff -r d1853a39e063 -r cb2575cec95c xen/common/keyhandler.c
--- a/xen/common/keyhandler.c   Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/common/keyhandler.c   Mon Mar 12 10:07:08 2007 -0600
@@ -47,7 +47,7 @@ void handle_keypress(unsigned char key, 
 {
     irq_keyhandler_t *h;
 
-    if ( key_table[key].flags & KEYHANDLER_IRQ_CALLBACK )
+    if ( !in_irq() || (key_table[key].flags & KEYHANDLER_IRQ_CALLBACK) )
     {
         console_start_log_everything();
         if ( (h = key_table[key].u.irq_handler) != NULL )
@@ -135,12 +135,25 @@ static void cpuset_print(char *set, int 
     *set++ = '\0';
 }
 
+static void periodic_timer_print(char *str, int size, uint64_t period)
+{
+    if ( period == 0 )
+    {
+        strlcpy(str, "No periodic timer", size);
+        return;
+    }
+
+    snprintf(str, size,
+             "%u Hz periodic timer (period %u ms)",
+             1000000000/(int)period, (int)period/1000000);
+}
+
 static void dump_domains(unsigned char key)
 {
     struct domain *d;
     struct vcpu   *v;
     s_time_t       now = NOW();
-    char           cpuset[100];
+    char           tmpstr[100];
 
     printk("'%c' pressed -> dumping domain info (now=0x%X:%08X)\n", key,
            (u32)(now>>32), (u32)now);
@@ -150,11 +163,11 @@ static void dump_domains(unsigned char k
     for_each_domain ( d )
     {
         printk("General information for domain %u:\n", d->domain_id);
-        cpuset_print(cpuset, sizeof(cpuset), d->domain_dirty_cpumask);
+        cpuset_print(tmpstr, sizeof(tmpstr), d->domain_dirty_cpumask);
         printk("    flags=%lx refcnt=%d nr_pages=%d xenheap_pages=%d "
                "dirty_cpus=%s\n",
                d->domain_flags, atomic_read(&d->refcnt),
-               d->tot_pages, d->xenheap_pages, cpuset);
+               d->tot_pages, d->xenheap_pages, tmpstr);
         printk("    handle=%02x%02x%02x%02x-%02x%02x-%02x%02x-"
                "%02x%02x-%02x%02x%02x%02x%02x%02x vm_assist=%08lx\n",
                d->handle[ 0], d->handle[ 1], d->handle[ 2], d->handle[ 3],
@@ -179,18 +192,21 @@ static void dump_domains(unsigned char k
                    v->vcpu_flags,
                    vcpu_info(v, evtchn_upcall_pending),
                    vcpu_info(v, evtchn_upcall_mask));
-            cpuset_print(cpuset, sizeof(cpuset), v->vcpu_dirty_cpumask);
-            printk("dirty_cpus=%s ", cpuset);
-            cpuset_print(cpuset, sizeof(cpuset), v->cpu_affinity);
-            printk("cpu_affinity=%s\n", cpuset);
+            cpuset_print(tmpstr, sizeof(tmpstr), v->vcpu_dirty_cpumask);
+            printk("dirty_cpus=%s ", tmpstr);
+            cpuset_print(tmpstr, sizeof(tmpstr), v->cpu_affinity);
+            printk("cpu_affinity=%s\n", tmpstr);
             arch_dump_vcpu_info(v);
+            periodic_timer_print(tmpstr, sizeof(tmpstr), v->periodic_period);
+            printk("    %s\n", tmpstr);
             printk("    Notifying guest (virq %d, port %d, stat %d/%d/%d)\n",
                    VIRQ_DEBUG, v->virq_to_evtchn[VIRQ_DEBUG],
                    test_bit(v->virq_to_evtchn[VIRQ_DEBUG], 
                             shared_info_addr(d, evtchn_pending)),
                    test_bit(v->virq_to_evtchn[VIRQ_DEBUG], 
                             shared_info_addr(d, evtchn_mask)),
-                   
test_bit(v->virq_to_evtchn[VIRQ_DEBUG]/BITS_PER_GUEST_LONG(d),
+                   test_bit(v->virq_to_evtchn[VIRQ_DEBUG] /
+                            BITS_PER_GUEST_LONG(d),
                             vcpu_info_addr(v, evtchn_pending_sel)));
             send_guest_vcpu_virq(v, VIRQ_DEBUG);
         }
diff -r d1853a39e063 -r cb2575cec95c xen/common/page_alloc.c
--- a/xen/common/page_alloc.c   Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/common/page_alloc.c   Mon Mar 12 10:07:08 2007 -0600
@@ -49,7 +49,7 @@ string_param("badpage", opt_badpage);
  * Bit width of the DMA heap.
  */
 static unsigned int  dma_bitsize = CONFIG_DMA_BITSIZE;
-static unsigned long max_dma_mfn = (1UL << (CONFIG_DMA_BITSIZE - PAGE_SHIFT)) 
- 1;
+static unsigned long max_dma_mfn = (1UL<<(CONFIG_DMA_BITSIZE-PAGE_SHIFT))-1;
 static void parse_dma_bits(char *s)
 {
     unsigned int v = simple_strtol(s, NULL, 0);
@@ -345,6 +345,7 @@ static struct page_info *alloc_heap_page
     unsigned int i, j, zone;
     unsigned int node = cpu_to_node(cpu), num_nodes = num_online_nodes();
     unsigned long request = 1UL << order;
+    cpumask_t extra_cpus_mask, mask;
     struct page_info *pg;
 
     ASSERT(node >= 0);
@@ -403,6 +404,29 @@ static struct page_info *alloc_heap_page
 
     spin_unlock(&heap_lock);
 
+    cpus_clear(mask);
+
+    for ( i = 0; i < (1 << order); i++ )
+    {
+        /* Reference count must continuously be zero for free pages. */
+        BUG_ON(pg[i].count_info != 0);
+
+        /* Add in any extra CPUs that need flushing because of this page. */
+        cpus_andnot(extra_cpus_mask, pg[i].u.free.cpumask, mask);
+        tlbflush_filter(extra_cpus_mask, pg[i].tlbflush_timestamp);
+        cpus_or(mask, mask, extra_cpus_mask);
+
+        /* Initialise fields which have other uses for free pages. */
+        pg[i].u.inuse.type_info = 0;
+        page_set_owner(&pg[i], NULL);
+    }
+
+    if ( unlikely(!cpus_empty(mask)) )
+    {
+        perfc_incrc(need_flush_tlb_flush);
+        flush_tlb_mask(mask);
+    }
+
     return pg;
 }
 
@@ -411,12 +435,27 @@ static void free_heap_pages(
     unsigned int zone, struct page_info *pg, unsigned int order)
 {
     unsigned long mask;
-    unsigned int node = phys_to_nid(page_to_maddr(pg));
+    unsigned int i, node = phys_to_nid(page_to_maddr(pg));
+    struct domain *d;
 
     ASSERT(zone < NR_ZONES);
     ASSERT(order <= MAX_ORDER);
     ASSERT(node >= 0);
     ASSERT(node < num_online_nodes());
+
+    for ( i = 0; i < (1 << order); i++ )
+    {
+        BUG_ON(pg[i].count_info != 0);
+        if ( (d = page_get_owner(&pg[i])) != NULL )
+        {
+            pg[i].tlbflush_timestamp = tlbflush_current_time();
+            pg[i].u.free.cpumask     = d->domain_dirty_cpumask;
+        }
+        else
+        {
+            cpus_clear(pg[i].u.free.cpumask);
+        }
+    }
 
     spin_lock(&heap_lock);
 
@@ -554,7 +593,7 @@ void end_boot_allocator(void)
 /*
  * Scrub all unallocated pages in all heap zones. This function is more
  * convoluted than appears necessary because we do not want to continuously
- * hold the lock or disable interrupts while scrubbing very large memory areas.
+ * hold the lock while scrubbing very large memory areas.
  */
 void scrub_heap_pages(void)
 {
@@ -575,7 +614,7 @@ void scrub_heap_pages(void)
         if ( (mfn % ((100*1024*1024)/PAGE_SIZE)) == 0 )
             printk(".");
 
-        spin_lock_irq(&heap_lock);
+        spin_lock(&heap_lock);
 
         /* Re-check page status with lock held. */
         if ( !allocated_in_map(mfn) )
@@ -595,7 +634,7 @@ void scrub_heap_pages(void)
             }
         }
 
-        spin_unlock_irq(&heap_lock);
+        spin_unlock(&heap_lock);
     }
 
     printk("done.\n");
@@ -609,8 +648,6 @@ void scrub_heap_pages(void)
 
 void init_xenheap_pages(paddr_t ps, paddr_t pe)
 {
-    unsigned long flags;
-
     ps = round_pgup(ps);
     pe = round_pgdown(pe);
     if ( pe <= ps )
@@ -625,33 +662,21 @@ void init_xenheap_pages(paddr_t ps, padd
     if ( !IS_XEN_HEAP_FRAME(maddr_to_page(pe)) )
         pe -= PAGE_SIZE;
 
-    local_irq_save(flags);
     init_heap_pages(MEMZONE_XEN, maddr_to_page(ps), (pe - ps) >> PAGE_SHIFT);
-    local_irq_restore(flags);
 }
 
 
 void *alloc_xenheap_pages(unsigned int order)
 {
-    unsigned long flags;
     struct page_info *pg;
-    int i;
-
-    local_irq_save(flags);
+
+    ASSERT(!in_irq());
+
     pg = alloc_heap_pages(MEMZONE_XEN, MEMZONE_XEN, smp_processor_id(), order);
-    local_irq_restore(flags);
-
     if ( unlikely(pg == NULL) )
         goto no_memory;
 
     memguard_unguard_range(page_to_virt(pg), 1 << (order + PAGE_SHIFT));
-
-    for ( i = 0; i < (1 << order); i++ )
-    {
-        pg[i].count_info        = 0;
-        pg[i].u.inuse._domain   = 0;
-        pg[i].u.inuse.type_info = 0;
-    }
 
     return page_to_virt(pg);
 
@@ -663,16 +688,14 @@ void *alloc_xenheap_pages(unsigned int o
 
 void free_xenheap_pages(void *v, unsigned int order)
 {
-    unsigned long flags;
+    ASSERT(!in_irq());
 
     if ( v == NULL )
         return;
 
-    memguard_guard_range(v, 1 << (order + PAGE_SHIFT));    
-
-    local_irq_save(flags);
+    memguard_guard_range(v, 1 << (order + PAGE_SHIFT));
+
     free_heap_pages(MEMZONE_XEN, virt_to_page(v), order);
-    local_irq_restore(flags);
 }
 
 
@@ -762,8 +785,6 @@ struct page_info *__alloc_domheap_pages(
     unsigned int memflags)
 {
     struct page_info *pg = NULL;
-    cpumask_t mask;
-    unsigned long i;
     unsigned int bits = memflags >> _MEMF_bits, zone_hi = NR_ZONES - 1;
 
     ASSERT(!in_irq());
@@ -792,38 +813,10 @@ struct page_info *__alloc_domheap_pages(
             return NULL;
     }
 
-    if ( pg == NULL )
-        if ( (pg = alloc_heap_pages(MEMZONE_XEN + 1,
-                                    zone_hi,
-                                    cpu, order)) == NULL )
-            return NULL;
-
-    mask = pg->u.free.cpumask;
-    tlbflush_filter(mask, pg->tlbflush_timestamp);
-
-    pg->count_info        = 0;
-    pg->u.inuse._domain   = 0;
-    pg->u.inuse.type_info = 0;
-
-    for ( i = 1; i < (1 << order); i++ )
-    {
-        /* Add in any extra CPUs that need flushing because of this page. */
-        cpumask_t extra_cpus_mask;
-        cpus_andnot(extra_cpus_mask, pg[i].u.free.cpumask, mask);
-        tlbflush_filter(extra_cpus_mask, pg[i].tlbflush_timestamp);
-        cpus_or(mask, mask, extra_cpus_mask);
-
-        pg[i].count_info        = 0;
-        pg[i].u.inuse._domain   = 0;
-        pg[i].u.inuse.type_info = 0;
-        page_set_owner(&pg[i], NULL);
-    }
-
-    if ( unlikely(!cpus_empty(mask)) )
-    {
-        perfc_incrc(need_flush_tlb_flush);
-        flush_tlb_mask(mask);
-    }
+    if ( (pg == NULL) &&
+         ((pg = alloc_heap_pages(MEMZONE_XEN + 1, zone_hi,
+                                 cpu, order)) == NULL) )
+         return NULL;
 
     if ( (d != NULL) && assign_pages(d, pg, order, memflags) )
     {
@@ -867,10 +860,7 @@ void free_domheap_pages(struct page_info
 
         for ( i = 0; i < (1 << order); i++ )
         {
-            shadow_drop_references(d, &pg[i]);
-            ASSERT((pg[i].u.inuse.type_info & PGT_count_mask) == 0);
-            pg[i].tlbflush_timestamp  = tlbflush_current_time();
-            pg[i].u.free.cpumask      = d->domain_dirty_cpumask;
+            BUG_ON((pg[i].u.inuse.type_info & PGT_count_mask) != 0);
             list_del(&pg[i].list);
         }
 
@@ -892,6 +882,7 @@ void free_domheap_pages(struct page_info
              */
             for ( i = 0; i < (1 << order); i++ )
             {
+                page_set_owner(&pg[i], NULL);
                 spin_lock(&page_scrub_lock);
                 list_add(&pg[i].list, &page_scrub_list);
                 scrub_pages++;
@@ -902,8 +893,6 @@ void free_domheap_pages(struct page_info
     else
     {
         /* Freeing anonymous domain-heap pages. */
-        for ( i = 0; i < (1 << order); i++ )
-            cpus_clear(pg[i].u.free.cpumask);
         free_heap_pages(pfn_dom_zone_type(page_to_mfn(pg)), pg, order);
         drop_dom_ref = 0;
     }
@@ -981,6 +970,8 @@ __initcall(pagealloc_keyhandler_init);
  * PAGE SCRUBBING
  */
 
+static DEFINE_PER_CPU(struct timer, page_scrub_timer);
+
 static void page_scrub_softirq(void)
 {
     struct list_head *ent;
@@ -989,7 +980,7 @@ static void page_scrub_softirq(void)
     int               i;
     s_time_t          start = NOW();
 
-    /* Aim to do 1ms of work (ten percent of a 10ms jiffy). */
+    /* Aim to do 1ms of work every 10ms. */
     do {
         spin_lock(&page_scrub_lock);
 
@@ -1025,6 +1016,13 @@ static void page_scrub_softirq(void)
             free_heap_pages(pfn_dom_zone_type(page_to_mfn(pg)), pg, 0);
         }
     } while ( (NOW() - start) < MILLISECS(1) );
+
+    set_timer(&this_cpu(page_scrub_timer), NOW() + MILLISECS(10));
+}
+
+static void page_scrub_timer_fn(void *unused)
+{
+    page_scrub_schedule_work();
 }
 
 unsigned long avail_scrub_pages(void)
@@ -1060,6 +1058,10 @@ __initcall(register_heap_trigger);
 
 static __init int page_scrub_init(void)
 {
+    int cpu;
+    for_each_cpu ( cpu )
+        init_timer(&per_cpu(page_scrub_timer, cpu),
+                   page_scrub_timer_fn, NULL, cpu);
     open_softirq(PAGE_SCRUB_SOFTIRQ, page_scrub_softirq);
     return 0;
 }
diff -r d1853a39e063 -r cb2575cec95c xen/common/sched_credit.c
--- a/xen/common/sched_credit.c Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/common/sched_credit.c Mon Mar 12 10:07:08 2007 -0600
@@ -186,6 +186,8 @@ struct csched_pcpu {
 struct csched_pcpu {
     struct list_head runq;
     uint32_t runq_sort_last;
+    struct timer ticker;
+    unsigned int tick;
 };
 
 /*
@@ -245,7 +247,7 @@ struct csched_private {
  */
 static struct csched_private csched_priv;
 
-
+static void csched_tick(void *_cpu);
 
 static inline int
 __cycle_cpu(int cpu, const cpumask_t *mask)
@@ -362,12 +364,13 @@ csched_pcpu_init(int cpu)
     if ( csched_priv.master >= csched_priv.ncpus )
         csched_priv.master = cpu;
 
+    init_timer(&spc->ticker, csched_tick, (void *)(unsigned long)cpu, cpu);
     INIT_LIST_HEAD(&spc->runq);
     spc->runq_sort_last = csched_priv.runq_sort;
     per_cpu(schedule_data, cpu).sched_priv = spc;
 
     /* Start off idling... */
-    BUG_ON( !is_idle_vcpu(per_cpu(schedule_data, cpu).curr) );
+    BUG_ON(!is_idle_vcpu(per_cpu(schedule_data, cpu).curr));
     cpu_set(cpu, csched_priv.idlers);
 
     spin_unlock_irqrestore(&csched_priv.lock, flags);
@@ -1013,8 +1016,13 @@ csched_acct(void)
 }
 
 static void
-csched_tick(unsigned int cpu)
-{
+csched_tick(void *_cpu)
+{
+    unsigned int cpu = (unsigned long)_cpu;
+    struct csched_pcpu *spc = CSCHED_PCPU(cpu);
+
+    spc->tick++;
+
     /*
      * Accounting for running VCPU
      */
@@ -1028,7 +1036,7 @@ csched_tick(unsigned int cpu)
      * we could distribute or at the very least cycle the duty.
      */
     if ( (csched_priv.master == cpu) &&
-         (per_cpu(schedule_data, cpu).tick % CSCHED_TICKS_PER_ACCT) == 0 )
+         (spc->tick % CSCHED_TICKS_PER_ACCT) == 0 )
     {
         csched_acct();
     }
@@ -1041,6 +1049,8 @@ csched_tick(unsigned int cpu)
      * once per accounting period (currently 30 milliseconds).
      */
     csched_runq_sort(cpu);
+
+    set_timer(&spc->ticker, NOW() + MILLISECS(CSCHED_MSECS_PER_TICK));
 }
 
 static struct csched_vcpu *
@@ -1248,8 +1258,7 @@ csched_dump_pcpu(int cpu)
     spc = CSCHED_PCPU(cpu);
     runq = &spc->runq;
 
-    printk(" tick=%lu, sort=%d, sibling=0x%lx, core=0x%lx\n",
-            per_cpu(schedule_data, cpu).tick,
+    printk(" sort=%d, sibling=0x%lx, core=0x%lx\n",
             spc->runq_sort_last,
             cpu_sibling_map[cpu].bits[0],
             cpu_core_map[cpu].bits[0]);
@@ -1341,6 +1350,22 @@ csched_init(void)
     CSCHED_STATS_RESET();
 }
 
+/* Tickers cannot be kicked until SMP subsystem is alive. */
+static __init int csched_start_tickers(void)
+{
+    struct csched_pcpu *spc;
+    unsigned int cpu;
+
+    for_each_online_cpu ( cpu )
+    {
+        spc = CSCHED_PCPU(cpu);
+        set_timer(&spc->ticker, NOW() + MILLISECS(CSCHED_MSECS_PER_TICK));
+    }
+
+    return 0;
+}
+__initcall(csched_start_tickers);
+
 
 struct scheduler sched_credit_def = {
     .name           = "SMP Credit Scheduler",
@@ -1359,7 +1384,6 @@ struct scheduler sched_credit_def = {
     .adjust         = csched_dom_cntl,
 
     .pick_cpu       = csched_cpu_pick,
-    .tick           = csched_tick,
     .do_schedule    = csched_schedule,
 
     .dump_cpu_state = csched_dump_pcpu,
diff -r d1853a39e063 -r cb2575cec95c xen/common/schedule.c
--- a/xen/common/schedule.c     Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/common/schedule.c     Mon Mar 12 10:07:08 2007 -0600
@@ -45,8 +45,8 @@ boolean_param("dom0_vcpus_pin", opt_dom0
 
 /* Various timer handlers. */
 static void s_timer_fn(void *unused);
-static void t_timer_fn(void *unused);
-static void vcpu_timer_fn(void *data);
+static void vcpu_periodic_timer_fn(void *data);
+static void vcpu_singleshot_timer_fn(void *data);
 static void poll_timer_fn(void *data);
 
 /* This is global for now so that private implementations can reach it */
@@ -65,9 +65,6 @@ static struct scheduler ops;
 #define SCHED_OP(fn, ...)                                 \
          (( ops.fn != NULL ) ? ops.fn( __VA_ARGS__ )      \
           : (typeof(ops.fn(__VA_ARGS__)))0 )
-
-/* Per-CPU periodic timer sends an event to the currently-executing domain. */
-static DEFINE_PER_CPU(struct timer, t_timer);
 
 static inline void vcpu_runstate_change(
     struct vcpu *v, int new_state, s_time_t new_entry_time)
@@ -113,9 +110,13 @@ int sched_init_vcpu(struct vcpu *v, unsi
     else
         cpus_setall(v->cpu_affinity);
 
-    /* Initialise the per-domain timers. */
-    init_timer(&v->timer, vcpu_timer_fn, v, v->processor);
-    init_timer(&v->poll_timer, poll_timer_fn, v, v->processor);
+    /* Initialise the per-vcpu timers. */
+    init_timer(&v->periodic_timer, vcpu_periodic_timer_fn,
+               v, v->processor);
+    init_timer(&v->singleshot_timer, vcpu_singleshot_timer_fn,
+               v, v->processor);
+    init_timer(&v->poll_timer, poll_timer_fn,
+               v, v->processor);
 
     /* Idle VCPUs are scheduled immediately. */
     if ( is_idle_domain(d) )
@@ -132,7 +133,8 @@ int sched_init_vcpu(struct vcpu *v, unsi
 
 void sched_destroy_vcpu(struct vcpu *v)
 {
-    kill_timer(&v->timer);
+    kill_timer(&v->periodic_timer);
+    kill_timer(&v->singleshot_timer);
     kill_timer(&v->poll_timer);
     SCHED_OP(destroy_vcpu, v);
 }
@@ -223,10 +225,29 @@ static void vcpu_migrate(struct vcpu *v)
     vcpu_wake(v);
 }
 
+/*
+ * Force a VCPU through a deschedule/reschedule path.
+ * For example, using this when setting the periodic timer period means that
+ * most periodic-timer state need only be touched from within the scheduler
+ * which can thus be done without need for synchronisation.
+ */
+void vcpu_force_reschedule(struct vcpu *v)
+{
+    vcpu_schedule_lock_irq(v);
+    if ( test_bit(_VCPUF_running, &v->vcpu_flags) )
+        set_bit(_VCPUF_migrating, &v->vcpu_flags);
+    vcpu_schedule_unlock_irq(v);
+
+    if ( test_bit(_VCPUF_migrating, &v->vcpu_flags) )
+    {
+        vcpu_sleep_nosync(v);
+        vcpu_migrate(v);
+    }
+}
+
 int vcpu_set_affinity(struct vcpu *v, cpumask_t *affinity)
 {
     cpumask_t online_affinity;
-    unsigned long flags;
 
     if ( (v->domain->domain_id == 0) && opt_dom0_vcpus_pin )
         return -EINVAL;
@@ -235,13 +256,13 @@ int vcpu_set_affinity(struct vcpu *v, cp
     if ( cpus_empty(online_affinity) )
         return -EINVAL;
 
-    vcpu_schedule_lock_irqsave(v, flags);
+    vcpu_schedule_lock_irq(v);
 
     v->cpu_affinity = *affinity;
     if ( !cpu_isset(v->processor, v->cpu_affinity) )
         set_bit(_VCPUF_migrating, &v->vcpu_flags);
 
-    vcpu_schedule_unlock_irqrestore(v, flags);
+    vcpu_schedule_unlock_irq(v);
 
     if ( test_bit(_VCPUF_migrating, &v->vcpu_flags) )
     {
@@ -450,7 +471,7 @@ ret_t do_sched_op(int cmd, XEN_GUEST_HAN
 
 #ifndef COMPAT
 
-/* Per-domain one-shot-timer hypercall. */
+/* Per-vcpu oneshot-timer hypercall. */
 long do_set_timer_op(s_time_t timeout)
 {
     struct vcpu *v = current;
@@ -458,7 +479,7 @@ long do_set_timer_op(s_time_t timeout)
 
     if ( timeout == 0 )
     {
-        stop_timer(&v->timer);
+        stop_timer(&v->singleshot_timer);
     }
     else if ( unlikely(timeout < 0) || /* overflow into 64th bit? */
               unlikely((offset > 0) && ((uint32_t)(offset >> 50) != 0)) )
@@ -474,14 +495,20 @@ long do_set_timer_op(s_time_t timeout)
          * timeout in this case can burn a lot of CPU. We therefore go for a
          * reasonable middleground of triggering a timer event in 100ms.
          */
-        gdprintk(XENLOG_INFO, "Warning: huge timeout set by domain %d (vcpu 
%d):"
-                " %"PRIx64"\n",
+        gdprintk(XENLOG_INFO, "Warning: huge timeout set by domain %d "
+                "(vcpu %d): %"PRIx64"\n",
                 v->domain->domain_id, v->vcpu_id, (uint64_t)timeout);
-        set_timer(&v->timer, NOW() + MILLISECS(100));
+        set_timer(&v->singleshot_timer, NOW() + MILLISECS(100));
     }
     else
     {
-        set_timer(&v->timer, timeout);
+        if ( v->singleshot_timer.cpu != smp_processor_id() )
+        {
+            stop_timer(&v->singleshot_timer);
+            v->singleshot_timer.cpu = smp_processor_id();
+        }
+
+        set_timer(&v->singleshot_timer, timeout);
     }
 
     return 0;
@@ -540,6 +567,28 @@ long sched_adjust(struct domain *d, stru
     return 0;
 }
 
+static void vcpu_periodic_timer_work(struct vcpu *v)
+{
+    s_time_t now = NOW();
+    uint64_t periodic_next_event;
+
+    ASSERT(!active_timer(&v->periodic_timer));
+
+    if ( v->periodic_period == 0 )
+        return;
+
+    periodic_next_event = v->periodic_last_event + v->periodic_period;
+    if ( now > periodic_next_event )
+    {
+        send_timer_event(v);
+        v->periodic_last_event = now;
+        periodic_next_event = now + v->periodic_period;
+    }
+
+    v->periodic_timer.cpu = smp_processor_id();
+    set_timer(&v->periodic_timer, periodic_next_event);
+}
+
 /* 
  * The main function
  * - deschedule the current domain (scheduler independent).
@@ -606,14 +655,13 @@ static void schedule(void)
 
     perfc_incrc(sched_ctx);
 
-    prev->sleep_tick = sd->tick;
+    stop_timer(&prev->periodic_timer);
 
     /* Ensure that the domain has an up-to-date time base. */
     if ( !is_idle_vcpu(next) )
     {
         update_vcpu_system_time(next);
-        if ( next->sleep_tick != sd->tick )
-            send_timer_event(next);
+        vcpu_periodic_timer_work(next);
     }
 
     TRACE_4D(TRC_SCHED_SWITCH,
@@ -631,13 +679,6 @@ void context_saved(struct vcpu *prev)
         vcpu_migrate(prev);
 }
 
-/****************************************************************************
- * Timers: the scheduler utilises a number of timers
- * - s_timer: per CPU timer for preemption and scheduling decisions
- * - t_timer: per CPU periodic timer to send timer interrupt to current dom
- * - dom_timer: per domain timer to specifiy timeout values
- ****************************************************************************/
-
 /* The scheduler timer: force a run through the scheduler */
 static void s_timer_fn(void *unused)
 {
@@ -645,28 +686,15 @@ static void s_timer_fn(void *unused)
     perfc_incrc(sched_irq);
 }
 
-/* Periodic tick timer: send timer event to current domain */
-static void t_timer_fn(void *unused)
-{
-    struct vcpu *v   = current;
-
-    this_cpu(schedule_data).tick++;
-
-    if ( !is_idle_vcpu(v) )
-    {
-        update_vcpu_system_time(v);
-        send_timer_event(v);
-    }
-
-    page_scrub_schedule_work();
-
-    SCHED_OP(tick, smp_processor_id());
-
-    set_timer(&this_cpu(t_timer), NOW() + MILLISECS(10));
-}
-
-/* Per-VCPU timer function: sends a virtual timer interrupt. */
-static void vcpu_timer_fn(void *data)
+/* Per-VCPU periodic timer function: sends a virtual timer interrupt. */
+static void vcpu_periodic_timer_fn(void *data)
+{
+    struct vcpu *v = data;
+    vcpu_periodic_timer_work(v);
+}
+
+/* Per-VCPU single-shot timer function: sends a virtual timer interrupt. */
+static void vcpu_singleshot_timer_fn(void *data)
 {
     struct vcpu *v = data;
     send_timer_event(v);
@@ -691,7 +719,6 @@ void __init scheduler_init(void)
     {
         spin_lock_init(&per_cpu(schedule_data, i).schedule_lock);
         init_timer(&per_cpu(schedule_data, i).s_timer, s_timer_fn, NULL, i);
-        init_timer(&per_cpu(t_timer, i), t_timer_fn, NULL, i);
     }
 
     for ( i = 0; schedulers[i] != NULL; i++ )
@@ -706,16 +733,6 @@ void __init scheduler_init(void)
 
     printk("Using scheduler: %s (%s)\n", ops.name, ops.opt_name);
     SCHED_OP(init);
-}
-
-/*
- * Start a scheduler for each CPU
- * This has to be done *after* the timers, e.g., APICs, have been initialised
- */
-void schedulers_start(void) 
-{   
-    t_timer_fn(0);
-    smp_call_function((void *)t_timer_fn, NULL, 1, 1);
 }
 
 void dump_runq(unsigned char key)
diff -r d1853a39e063 -r cb2575cec95c xen/common/sysctl.c
--- a/xen/common/sysctl.c       Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/common/sysctl.c       Mon Mar 12 10:07:08 2007 -0600
@@ -18,6 +18,7 @@
 #include <xen/console.h>
 #include <xen/iocap.h>
 #include <xen/guest_access.h>
+#include <xen/keyhandler.h>
 #include <asm/current.h>
 #include <public/sysctl.h>
 
@@ -121,6 +122,20 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysc
     break;
 #endif
 
+    case XEN_SYSCTL_debug_keys:
+    {
+        char c;
+        uint32_t i;
+
+        for ( i = 0; i < op->u.debug_keys.nr_keys; i++ )
+        {
+            if ( copy_from_guest_offset(&c, op->u.debug_keys.keys, i, 1) )
+                return -EFAULT;
+            handle_keypress(c, guest_cpu_user_regs());
+        }
+    }
+    break;
+
     default:
         ret = arch_do_sysctl(op, u_sysctl);
         break;
diff -r d1853a39e063 -r cb2575cec95c xen/common/xmalloc.c
--- a/xen/common/xmalloc.c      Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/common/xmalloc.c      Mon Mar 12 10:07:08 2007 -0600
@@ -33,6 +33,8 @@
 #include <xen/timer.h>
 #include <xen/cache.h>
 #include <xen/prefetch.h>
+#include <xen/irq.h>
+#include <xen/smp.h>
 
 /*
  * XMALLOC_DEBUG:
@@ -175,6 +177,8 @@ void *_xmalloc(size_t size, size_t align
     struct xmalloc_hdr *i;
     unsigned long flags;
 
+    ASSERT(!in_irq());
+
     /* We currently always return cacheline aligned. */
     BUG_ON(align > SMP_CACHE_BYTES);
 
@@ -212,6 +216,8 @@ void xfree(void *p)
 {
     unsigned long flags;
     struct xmalloc_hdr *i, *tmp, *hdr;
+
+    ASSERT(!in_irq());
 
     if ( p == NULL )
         return;
diff -r d1853a39e063 -r cb2575cec95c xen/drivers/char/console.c
--- a/xen/drivers/char/console.c        Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/drivers/char/console.c        Mon Mar 12 10:07:08 2007 -0600
@@ -399,6 +399,8 @@ static void __putstr(const char *str)
         vga_putchar(c);
         putchar_console_ring(c);
     }
+
+    send_guest_global_virq(dom0, VIRQ_CON_RING);
 }
 
 static int printk_prefix_check(char *p, char **pp)
diff -r d1853a39e063 -r cb2575cec95c xen/include/asm-x86/domain.h
--- a/xen/include/asm-x86/domain.h      Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/include/asm-x86/domain.h      Mon Mar 12 10:07:08 2007 -0600
@@ -104,6 +104,21 @@ struct shadow_vcpu {
 };
 
 /************************************************/
+/*            hardware assisted paging          */
+/************************************************/
+struct hap_domain {
+    spinlock_t        lock;
+    int               locker;
+    const char       *locker_function;
+    
+    struct list_head  freelists;
+    struct list_head  p2m_freelist;
+    unsigned int      total_pages;  /* number of pages allocated */
+    unsigned int      free_pages;   /* number of pages on freelists */
+    unsigned int      p2m_pages;    /* number of pages allocates to p2m */
+};
+
+/************************************************/
 /*       p2m handling                           */
 /************************************************/
 
@@ -135,6 +150,7 @@ struct paging_domain {
     struct shadow_domain shadow;
 
     /* Other paging assistance code will have structs here */
+    struct hap_domain    hap;
 };
 
 struct paging_vcpu {
diff -r d1853a39e063 -r cb2575cec95c xen/include/asm-x86/hap.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/asm-x86/hap.h Mon Mar 12 10:07:08 2007 -0600
@@ -0,0 +1,122 @@
+/******************************************************************************
+ * include/asm-x86/hap.h
+ *
+ * hardware-assisted paging
+ * Copyright (c) 2007 Advanced Micro Devices (Wei Huang)
+ * 
+ * Parts of this code are Copyright (c) 2006 by XenSource Inc.
+ * Parts of this code are Copyright (c) 2006 by Michael A Fetterman
+ * Parts based on earlier work by Michael A Fetterman, Ian Pratt et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 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
+ */
+
+#ifndef _XEN_HAP_H
+#define _XEN_HAP_H
+
+#define HERE_I_AM                                                     \
+    debugtrace_printk("HERE I AM: %s %s %d\n", __func__, __FILE__, __LINE__)
+#define HAP_PRINTK(_f, _a...)                                         \
+    debugtrace_printk("hap: %s(): " _f, __func__, ##_a)
+#define HAP_ERROR(_f, _a...)                                          \
+    printk("hap error: %s(): " _f, __func__, ##_a)
+
+/************************************************/
+/*          hap domain page mapping             */
+/************************************************/
+static inline void *
+hap_map_domain_page(mfn_t mfn)
+{
+    return map_domain_page(mfn_x(mfn));
+}
+
+static inline void
+hap_unmap_domain_page(void *p)
+{
+    unmap_domain_page(p);
+}
+
+static inline void *
+hap_map_domain_page_global(mfn_t mfn)
+{
+    return map_domain_page_global(mfn_x(mfn));
+}
+
+static inline void 
+hap_unmap_domain_page_global(void *p) 
+{
+    unmap_domain_page_global(p);
+}
+
+/************************************************/
+/*           locking for hap code               */
+/************************************************/
+#define hap_lock_init(_d)                                   \
+    do {                                                    \
+        spin_lock_init(&(_d)->arch.paging.hap.lock);        \
+        (_d)->arch.paging.hap.locker = -1;                  \
+        (_d)->arch.paging.hap.locker_function = "nobody";   \
+    } while (0)
+
+#define hap_locked_by_me(_d)                     \
+    (current->processor == (_d)->arch.paging.hap.locker)
+
+#define hap_lock(_d)                                                       \
+    do {                                                                   \
+        if ( unlikely((_d)->arch.paging.hap.locker == current->processor) )\
+        {                                                                  \
+            printk("Error: hap lock held by %s\n",                         \
+                   (_d)->arch.paging.hap.locker_function);                 \
+            BUG();                                                         \
+        }                                                                  \
+        spin_lock(&(_d)->arch.paging.hap.lock);                            \
+        ASSERT((_d)->arch.paging.hap.locker == -1);                        \
+        (_d)->arch.paging.hap.locker = current->processor;                 \
+        (_d)->arch.paging.hap.locker_function = __func__;                  \
+    } while (0)
+
+#define hap_unlock(_d)                                              \
+    do {                                                            \
+        ASSERT((_d)->arch.paging.hap.locker == current->processor); \
+        (_d)->arch.paging.hap.locker = -1;                          \
+        (_d)->arch.paging.hap.locker_function = "nobody";           \
+        spin_unlock(&(_d)->arch.paging.hap.lock);                   \
+    } while (0)
+
+/************************************************/
+/*        hap domain level functions            */
+/************************************************/
+void  hap_domain_init(struct domain *d);
+int   hap_domctl(struct domain *d, xen_domctl_shadow_op_t *sc,
+                 XEN_GUEST_HANDLE(void) u_domctl);
+int   hap_enable(struct domain *d, u32 mode);
+void  hap_final_teardown(struct domain *d);
+void  hap_teardown(struct domain *d);
+void  hap_vcpu_init(struct vcpu *v);
+
+extern struct paging_mode hap_paging_real_mode;
+extern struct paging_mode hap_paging_protected_mode;
+extern struct paging_mode hap_paging_pae_mode;
+extern struct paging_mode hap_paging_long_mode;
+#endif /* XEN_HAP_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r d1853a39e063 -r cb2575cec95c xen/include/asm-x86/hvm/svm/vmcb.h
--- a/xen/include/asm-x86/hvm/svm/vmcb.h        Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/include/asm-x86/hvm/svm/vmcb.h        Mon Mar 12 10:07:08 2007 -0600
@@ -460,7 +460,6 @@ struct vmcb_struct *alloc_vmcb(void);
 struct vmcb_struct *alloc_vmcb(void);
 struct host_save_area *alloc_host_save_area(void);
 void free_vmcb(struct vmcb_struct *vmcb);
-void free_host_save_area(struct host_save_area *hsa);
 
 int  svm_create_vmcb(struct vcpu *v);
 void svm_destroy_vmcb(struct vcpu *v);
diff -r d1853a39e063 -r cb2575cec95c xen/include/asm-x86/hvm/vpt.h
--- a/xen/include/asm-x86/hvm/vpt.h     Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/include/asm-x86/hvm/vpt.h     Mon Mar 12 10:07:08 2007 -0600
@@ -92,6 +92,7 @@ typedef struct RTCState {
     struct timer second_timer;
     struct timer second_timer2;
     struct periodic_time pt;
+    int32_t time_offset_seconds;
 } RTCState;
 
 #define FREQUENCE_PMTIMER  3579545  /* Timer should run at 3.579545 MHz */
diff -r d1853a39e063 -r cb2575cec95c xen/include/asm-x86/paging.h
--- a/xen/include/asm-x86/paging.h      Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/include/asm-x86/paging.h      Mon Mar 12 10:07:08 2007 -0600
@@ -273,7 +273,7 @@ static inline void paging_write_p2m_entr
     struct vcpu *v = current;
     if ( v->domain != d )
         v = d->vcpu[0];
-    if ( likely(paging_mode_enabled(d) && v->arch.paging.mode != NULL) )
+    if ( likely(v && paging_mode_enabled(d) && v->arch.paging.mode != NULL) )
     {
         return v->arch.paging.mode->write_p2m_entry(v, gfn, p, new, level);
     }
diff -r d1853a39e063 -r cb2575cec95c xen/include/public/hvm/hvm_op.h
--- a/xen/include/public/hvm/hvm_op.h   Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/include/public/hvm/hvm_op.h   Mon Mar 12 10:07:08 2007 -0600
@@ -70,4 +70,12 @@ 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 d1853a39e063 -r cb2575cec95c xen/include/public/sysctl.h
--- a/xen/include/public/sysctl.h       Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/include/public/sysctl.h       Mon Mar 12 10:07:08 2007 -0600
@@ -140,6 +140,18 @@ typedef struct xen_sysctl_getdomaininfol
 typedef struct xen_sysctl_getdomaininfolist xen_sysctl_getdomaininfolist_t;
 DEFINE_XEN_GUEST_HANDLE(xen_sysctl_getdomaininfolist_t);
 
+/*
+ * Inject debug keys into Xen.
+ */
+#define XEN_SYSCTL_debug_keys        7
+struct xen_sysctl_debug_keys {
+    /* IN variables. */
+    XEN_GUEST_HANDLE_64(char) keys;
+    uint32_t nr_keys;
+};
+typedef struct xen_sysctl_debug_keys xen_sysctl_debug_keys_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_debug_keys_t);
+
 struct xen_sysctl {
     uint32_t cmd;
     uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */
@@ -150,6 +162,7 @@ struct xen_sysctl {
         struct xen_sysctl_sched_id          sched_id;
         struct xen_sysctl_perfc_op          perfc_op;
         struct xen_sysctl_getdomaininfolist getdomaininfolist;
+        struct xen_sysctl_debug_keys        debug_keys;
         uint8_t                             pad[128];
     } u;
 };
diff -r d1853a39e063 -r cb2575cec95c xen/include/public/vcpu.h
--- a/xen/include/public/vcpu.h Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/include/public/vcpu.h Mon Mar 12 10:07:08 2007 -0600
@@ -42,13 +42,13 @@
  * @extra_arg == pointer to vcpu_guest_context structure containing initial
  *               state for the VCPU.
  */
-#define VCPUOP_initialise           0
+#define VCPUOP_initialise            0
 
 /*
  * Bring up a VCPU. This makes the VCPU runnable. This operation will fail
  * if the VCPU has not been initialised (VCPUOP_initialise).
  */
-#define VCPUOP_up                   1
+#define VCPUOP_up                    1
 
 /*
  * Bring down a VCPU (i.e., make it non-runnable).
@@ -64,16 +64,16 @@
  *     practise to move a VCPU onto an 'idle' or default page table, LDT and
  *     GDT before bringing it down.
  */
-#define VCPUOP_down                 2
+#define VCPUOP_down                  2
 
 /* Returns 1 if the given VCPU is up. */
-#define VCPUOP_is_up                3
+#define VCPUOP_is_up                 3
 
 /*
  * Return information about the state and running time of a VCPU.
  * @extra_arg == pointer to vcpu_runstate_info structure.
  */
-#define VCPUOP_get_runstate_info    4
+#define VCPUOP_get_runstate_info     4
 struct vcpu_runstate_info {
     /* VCPU's current state (RUNSTATE_*). */
     int      state;
@@ -128,6 +128,38 @@ struct vcpu_register_runstate_memory_are
     } addr;
 };
 typedef struct vcpu_register_runstate_memory_area 
vcpu_register_runstate_memory_area_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_register_runstate_memory_area_t);
+
+/*
+ * Set or stop a VCPU's periodic timer. Every VCPU has one periodic timer
+ * which can be set via these commands. Periods smaller than one millisecond
+ * may not be supported.
+ */
+#define VCPUOP_set_periodic_timer    6 /* arg == vcpu_set_periodic_timer_t */
+#define VCPUOP_stop_periodic_timer   7 /* arg == NULL */
+struct vcpu_set_periodic_timer {
+    uint64_t period_ns;
+};
+typedef struct vcpu_set_periodic_timer vcpu_set_periodic_timer_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_set_periodic_timer_t);
+
+/*
+ * Set or stop a VCPU's single-shot timer. Every VCPU has one single-shot
+ * timer which can be set via these commands.
+ */
+#define VCPUOP_set_singleshot_timer  8 /* arg == vcpu_set_singleshot_timer_t */
+#define VCPUOP_stop_singleshot_timer 9 /* arg == NULL */
+struct vcpu_set_singleshot_timer {
+    uint64_t timeout_abs_ns;   /* Absolute system time value in nanoseconds. */
+    uint32_t flags;            /* VCPU_SSHOTTMR_??? */
+};
+typedef struct vcpu_set_singleshot_timer vcpu_set_singleshot_timer_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_set_singleshot_timer_t);
+
+/* Flags to VCPUOP_set_singleshot_timer. */
+ /* Require the timeout to be in the future (return -ETIME if it's passed). */
+#define _VCPU_SSHOTTMR_future (0)
+#define VCPU_SSHOTTMR_future  (1U << _VCPU_SSHOTTMR_future)
 
 #endif /* __XEN_PUBLIC_VCPU_H__ */
 
diff -r d1853a39e063 -r cb2575cec95c xen/include/public/xen.h
--- a/xen/include/public/xen.h  Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/include/public/xen.h  Mon Mar 12 10:07:08 2007 -0600
@@ -131,6 +131,7 @@
 #define VIRQ_TBUF       4  /* G. (DOM0) Trace buffer has records available.  */
 #define VIRQ_DEBUGGER   6  /* G. (DOM0) A domain has paused for debugging.   */
 #define VIRQ_XENOPROF   7  /* V. XenOprofile interrupt: new sample available */
+#define VIRQ_CON_RING   8  /* G. (DOM0) Bytes received on console            */
 
 /* Architecture-specific VIRQ definitions. */
 #define VIRQ_ARCH_0    16
diff -r d1853a39e063 -r cb2575cec95c xen/include/xen/mm.h
--- a/xen/include/xen/mm.h      Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/include/xen/mm.h      Mon Mar 12 10:07:08 2007 -0600
@@ -92,6 +92,11 @@ extern struct list_head page_scrub_list;
         if ( !list_empty(&page_scrub_list) )    \
             raise_softirq(PAGE_SCRUB_SOFTIRQ);  \
     } while ( 0 )
+#define page_scrub_kick()                                               \
+    do {                                                                \
+        if ( !list_empty(&page_scrub_list) )                            \
+            cpumask_raise_softirq(cpu_online_map, PAGE_SCRUB_SOFTIRQ);  \
+    } while ( 0 )
 unsigned long avail_scrub_pages(void);
 
 #include <asm/mm.h>
diff -r d1853a39e063 -r cb2575cec95c xen/include/xen/sched-if.h
--- a/xen/include/xen/sched-if.h        Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/include/xen/sched-if.h        Mon Mar 12 10:07:08 2007 -0600
@@ -16,7 +16,6 @@ struct schedule_data {
     struct vcpu        *idle;           /* idle task for this cpu          */
     void               *sched_priv;
     struct timer        s_timer;        /* scheduling timer                */
-    unsigned long       tick;           /* current periodic 'tick'         */
 } __cacheline_aligned;
 
 DECLARE_PER_CPU(struct schedule_data, schedule_data);
@@ -61,7 +60,6 @@ struct scheduler {
     unsigned int sched_id;  /* ID for this scheduler             */
 
     void         (*init)           (void);
-    void         (*tick)           (unsigned int cpu);
 
     int          (*init_domain)    (struct domain *);
     void         (*destroy_domain) (struct domain *);
diff -r d1853a39e063 -r cb2575cec95c xen/include/xen/sched.h
--- a/xen/include/xen/sched.h   Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/include/xen/sched.h   Mon Mar 12 10:07:08 2007 -0600
@@ -79,8 +79,10 @@ struct vcpu
 
     struct vcpu     *next_in_list;
 
-    struct timer     timer;         /* one-shot timer for timeout values */
-    unsigned long    sleep_tick;    /* tick at which this vcpu started sleep */
+    uint64_t         periodic_period;
+    uint64_t         periodic_last_event;
+    struct timer     periodic_timer;
+    struct timer     singleshot_timer;
 
     struct timer     poll_timer;    /* timeout for SCHEDOP_poll */
 
@@ -332,7 +334,6 @@ void __domain_crash_synchronous(void) __
 
 #define set_current_state(_s) do { current->state = (_s); } while (0)
 void scheduler_init(void);
-void schedulers_start(void);
 int  sched_init_vcpu(struct vcpu *v, unsigned int processor);
 void sched_destroy_vcpu(struct vcpu *v);
 int  sched_init_domain(struct domain *d);
@@ -497,6 +498,7 @@ void domain_unpause_by_systemcontroller(
 void domain_unpause_by_systemcontroller(struct domain *d);
 void cpu_init(void);
 
+void vcpu_force_reschedule(struct vcpu *v);
 int vcpu_set_affinity(struct vcpu *v, cpumask_t *affinity);
 
 void vcpu_runstate_get(struct vcpu *v, struct vcpu_runstate_info *runstate);
diff -r d1853a39e063 -r cb2575cec95c xen/include/xen/timer.h
--- a/xen/include/xen/timer.h   Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/include/xen/timer.h   Mon Mar 12 10:07:08 2007 -0600
@@ -35,7 +35,7 @@ struct timer {
  * The timer must *previously* have been initialised by init_timer(), or its
  * structure initialised to all-zeroes.
  */
-static __inline__ int active_timer(struct timer *timer)
+static inline int active_timer(struct timer *timer)
 {
     return (timer->heap_offset != 0);
 }
@@ -46,7 +46,7 @@ static __inline__ int active_timer(struc
  * time (and multiple times) on an inactive timer. It must *never* execute
  * concurrently with any other operation on the same timer.
  */
-static __inline__ void init_timer(
+static inline void init_timer(
     struct timer *timer,
     void           (*function)(void *),
     void            *data,

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


 


Rackspace

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