direct-io.hg

changeset 14510:cb2575cec95c

merge with xen-unstable.hg
author awilliam@xenbuild2.aw
date Mon Mar 12 10:07:08 2007 -0600 (2007-03-12)
parents d1853a39e063 8a01644306ee
children c0cdb349a11a
files linux-2.6-xen-sparse/arch/ia64/xen/xcom_hcall.c linux-2.6-xen-sparse/include/asm-ia64/hypercall.h xen/arch/x86/mm/shadow/page-guest32.h
line diff
     1.1 --- a/buildconfigs/linux-defconfig_xen0_ia64	Mon Mar 12 09:43:48 2007 -0600
     1.2 +++ b/buildconfigs/linux-defconfig_xen0_ia64	Mon Mar 12 10:07:08 2007 -0600
     1.3 @@ -1619,7 +1619,7 @@ CONFIG_CRYPTO_DES=y
     1.4  CONFIG_XEN_BALLOON=y
     1.5  CONFIG_XEN_REBOOT=y
     1.6  # CONFIG_XEN_SMPBOOT is not set
     1.7 -CONFIG_XEN_INTERFACE_VERSION=0x00030203
     1.8 +CONFIG_XEN_INTERFACE_VERSION=0x00030205
     1.9  
    1.10  #
    1.11  # XEN
     2.1 --- a/buildconfigs/linux-defconfig_xen0_x86_32	Mon Mar 12 09:43:48 2007 -0600
     2.2 +++ b/buildconfigs/linux-defconfig_xen0_x86_32	Mon Mar 12 10:07:08 2007 -0600
     2.3 @@ -1384,7 +1384,7 @@ CONFIG_CRYPTO_CRC32C=m
     2.4  #
     2.5  # CONFIG_CRYPTO_DEV_PADLOCK is not set
     2.6  CONFIG_XEN=y
     2.7 -CONFIG_XEN_INTERFACE_VERSION=0x00030203
     2.8 +CONFIG_XEN_INTERFACE_VERSION=0x00030205
     2.9  
    2.10  #
    2.11  # XEN
     3.1 --- a/buildconfigs/linux-defconfig_xen0_x86_64	Mon Mar 12 09:43:48 2007 -0600
     3.2 +++ b/buildconfigs/linux-defconfig_xen0_x86_64	Mon Mar 12 10:07:08 2007 -0600
     3.3 @@ -1334,7 +1334,7 @@ CONFIG_CRYPTO_CRC32C=m
     3.4  # Hardware crypto devices
     3.5  #
     3.6  CONFIG_XEN=y
     3.7 -CONFIG_XEN_INTERFACE_VERSION=0x00030203
     3.8 +CONFIG_XEN_INTERFACE_VERSION=0x00030205
     3.9  
    3.10  #
    3.11  # XEN
     4.1 --- a/buildconfigs/linux-defconfig_xenU_ia64	Mon Mar 12 09:43:48 2007 -0600
     4.2 +++ b/buildconfigs/linux-defconfig_xenU_ia64	Mon Mar 12 10:07:08 2007 -0600
     4.3 @@ -1471,7 +1471,7 @@ CONFIG_CRYPTO_DES=y
     4.4  CONFIG_XEN_BALLOON=y
     4.5  CONFIG_XEN_REBOOT=y
     4.6  # CONFIG_XEN_SMPBOOT is not set
     4.7 -CONFIG_XEN_INTERFACE_VERSION=0x00030203
     4.8 +CONFIG_XEN_INTERFACE_VERSION=0x00030205
     4.9  
    4.10  #
    4.11  # XEN
     5.1 --- a/buildconfigs/linux-defconfig_xenU_x86_32	Mon Mar 12 09:43:48 2007 -0600
     5.2 +++ b/buildconfigs/linux-defconfig_xenU_x86_32	Mon Mar 12 10:07:08 2007 -0600
     5.3 @@ -904,7 +904,7 @@ CONFIG_CRYPTO_CRC32C=m
     5.4  #
     5.5  # CONFIG_CRYPTO_DEV_PADLOCK is not set
     5.6  CONFIG_XEN=y
     5.7 -CONFIG_XEN_INTERFACE_VERSION=0x00030203
     5.8 +CONFIG_XEN_INTERFACE_VERSION=0x00030205
     5.9  
    5.10  #
    5.11  # XEN
     6.1 --- a/buildconfigs/linux-defconfig_xenU_x86_64	Mon Mar 12 09:43:48 2007 -0600
     6.2 +++ b/buildconfigs/linux-defconfig_xenU_x86_64	Mon Mar 12 10:07:08 2007 -0600
     6.3 @@ -1200,7 +1200,7 @@ CONFIG_CRYPTO_CRC32C=m
     6.4  # Hardware crypto devices
     6.5  #
     6.6  CONFIG_XEN=y
     6.7 -CONFIG_XEN_INTERFACE_VERSION=0x00030203
     6.8 +CONFIG_XEN_INTERFACE_VERSION=0x00030205
     6.9  
    6.10  #
    6.11  # XEN
     7.1 --- a/buildconfigs/linux-defconfig_xen_ia64	Mon Mar 12 09:43:48 2007 -0600
     7.2 +++ b/buildconfigs/linux-defconfig_xen_ia64	Mon Mar 12 10:07:08 2007 -0600
     7.3 @@ -1619,7 +1619,7 @@ CONFIG_CRYPTO_DES=y
     7.4  CONFIG_XEN_BALLOON=y
     7.5  CONFIG_XEN_REBOOT=y
     7.6  # CONFIG_XEN_SMPBOOT is not set
     7.7 -CONFIG_XEN_INTERFACE_VERSION=0x00030203
     7.8 +CONFIG_XEN_INTERFACE_VERSION=0x00030205
     7.9  
    7.10  #
    7.11  # XEN
     8.1 --- a/buildconfigs/linux-defconfig_xen_x86_32	Mon Mar 12 09:43:48 2007 -0600
     8.2 +++ b/buildconfigs/linux-defconfig_xen_x86_32	Mon Mar 12 10:07:08 2007 -0600
     8.3 @@ -3242,7 +3242,7 @@ CONFIG_CRYPTO_TEST=m
     8.4  #
     8.5  # CONFIG_CRYPTO_DEV_PADLOCK is not set
     8.6  CONFIG_XEN=y
     8.7 -CONFIG_XEN_INTERFACE_VERSION=0x00030203
     8.8 +CONFIG_XEN_INTERFACE_VERSION=0x00030205
     8.9  
    8.10  #
    8.11  # XEN
     9.1 --- a/buildconfigs/linux-defconfig_xen_x86_64	Mon Mar 12 09:43:48 2007 -0600
     9.2 +++ b/buildconfigs/linux-defconfig_xen_x86_64	Mon Mar 12 10:07:08 2007 -0600
     9.3 @@ -3072,7 +3072,7 @@ CONFIG_CRYPTO_TEST=m
     9.4  # Hardware crypto devices
     9.5  #
     9.6  CONFIG_XEN=y
     9.7 -CONFIG_XEN_INTERFACE_VERSION=0x00030203
     9.8 +CONFIG_XEN_INTERFACE_VERSION=0x00030205
     9.9  
    9.10  #
    9.11  # XEN
    10.1 --- a/docs/man/xm.pod.1	Mon Mar 12 09:43:48 2007 -0600
    10.2 +++ b/docs/man/xm.pod.1	Mon Mar 12 10:07:08 2007 -0600
    10.3 @@ -619,7 +619,7 @@ devices, or by device id, such as 0x1400
    10.4  =item I<mode>
    10.5  
    10.6  The access mode for the device from the guest domain.  Supported modes
    10.7 -are I<rw> (read/write) or I<ro> (read-only).
    10.8 +are I<w> (read/write) or I<r> (read-only).
    10.9  
   10.10  =item I<bedomain-id>
   10.11  
    11.1 --- a/docs/misc/dump-core-format.txt	Mon Mar 12 09:43:48 2007 -0600
    11.2 +++ b/docs/misc/dump-core-format.txt	Mon Mar 12 10:07:08 2007 -0600
    11.3 @@ -80,8 +80,7 @@ Currently the following sections are def
    11.4                          gmfn:   machine physical frame number
    11.5                  The size of arrays is stored in xch_nr_pages member of header
    11.6                  note descriptor in .note.Xen note section.
    11.7 -                There is no rule about the order. Analysis tools must no rely
    11.8 -                on its order.
    11.9 +                The entryies are stored in pfn-ascending order.
   11.10                  This section must exist when the domain is non auto
   11.11                  translated physmap mode. Currently x86 paravirtualized domain.
   11.12  
   11.13 @@ -94,8 +93,7 @@ Currently the following sections are def
   11.14                  in .xen_pages section.
   11.15                  The size of arrays is stored in xch_nr_pages member of header
   11.16                  note descriptor in .note.Xen note section.
   11.17 -                There is no rule about the order. Analysis tools must no rely
   11.18 -                on its order.
   11.19 +                The entries are stored in ascending order.
   11.20                  This section must exist when the domain is auto translated
   11.21                  physmap mode. Currently x86 full virtualized domain and
   11.22                  ia64 domain.
   11.23 @@ -226,6 +224,8 @@ Currently only (major, minor) = (0, 1) i
   11.24  [When the format is changed, it would be described here.]
   11.25  
   11.26  (0, 1) update
   11.27 +- .xen_p2m, .xen_pfn section
   11.28 +  Arrays must be in pfn ascending order for efficient looking up.
   11.29  - EI_CLASS member of elf header was changed to ELFCLASS64 independent of
   11.30    architecture. This is mainly for x86_32pae.
   11.31    The format version isn't bumped because analysis tools can distinguish it.
    12.1 --- a/docs/xen-api/coversheet.tex	Mon Mar 12 09:43:48 2007 -0600
    12.2 +++ b/docs/xen-api/coversheet.tex	Mon Mar 12 10:07:08 2007 -0600
    12.3 @@ -47,4 +47,4 @@ Date: \datestring{}
    12.4  \legalnotice{}
    12.5  
    12.6  \newpage
    12.7 -\pagestyle{plain}
    12.8 \ No newline at end of file
    12.9 +\pagestyle{fancy}
   12.10 \ No newline at end of file
    13.1 --- a/docs/xen-api/presentation.tex	Mon Mar 12 09:43:48 2007 -0600
    13.2 +++ b/docs/xen-api/presentation.tex	Mon Mar 12 10:07:08 2007 -0600
    13.3 @@ -57,14 +57,14 @@ type $t_1$ to values of type $t_2$.
    13.4  \end{itemize}
    13.5  
    13.6  Note that there are a number of cases where {\em Ref}s are {\em doubly
    13.7 -linked\/}---e.g.\ a VM has a field called {\tt groups} of type
    13.8 -$(\mathit{VMGroup}~\mathit{Ref})~\mathit{Set}$; this field lists
    13.9 -the VMGroups that a particular VM is part of. Similarly, the VMGroups
   13.10 -class has a field called {\tt VMs} of type $(\mathit{VM}~{\mathit
   13.11 -Ref})~\mathit{Set}$ that contains the VMs that are part of a particular
   13.12 -VMGroup. These two fields are {\em bound together\/}, in the sense that
   13.13 -adding a new VMGroup to a VM causes the VMs field of the corresponding
   13.14 -VMGroup object to be updated automatically.
   13.15 +linked\/}---e.g.\ a VM has a field called {\tt VIFs} of type
   13.16 +$(\mathit{VIF}~\mathit{Ref})~\mathit{Set}$; this field lists
   13.17 +the network interfaces attached to a particular VM. Similarly, the VIF
   13.18 +class has a field called {\tt VM} of type $(\mathit{VM}~{\mathit
   13.19 +Ref})$ which references the VM to which the interface is connected.
   13.20 +These two fields are {\em bound together\/}, in the sense that
   13.21 +creating a new VIF causes the {\tt VIFs} field of the corresponding
   13.22 +VM object to be updated automatically.
   13.23  
   13.24  The API reference explicitly lists the fields that are
   13.25  bound together in this way. It also contains a diagram that shows
    14.1 --- a/docs/xen-api/vm-lifecycle.tex	Mon Mar 12 09:43:48 2007 -0600
    14.2 +++ b/docs/xen-api/vm-lifecycle.tex	Mon Mar 12 10:07:08 2007 -0600
    14.3 @@ -22,3 +22,19 @@
    14.4  
    14.5  Figure~\ref{fig-vm-lifecycle} shows the states that a VM can be in
    14.6  and the API calls that can be used to move the VM between these states.
    14.7 +
    14.8 +\section{VM boot parameters}
    14.9 +
   14.10 +The VM class contains a number of fields that control the way in which the VM is booted.
   14.11 +With reference to the fields defined in the VM class (see later in this document),
   14.12 +this section outlines the boot options available and the mechanisms provided for controlling them.
   14.13 +
   14.14 +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.
   14.15 +
   14.16 +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.
   14.17 +
   14.18 +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.
   14.19 +
   14.20 +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''.
   14.21 +
   14.22 +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.
   14.23 \ No newline at end of file
    15.1 --- a/docs/xen-api/wire-protocol.tex	Mon Mar 12 09:43:48 2007 -0600
    15.2 +++ b/docs/xen-api/wire-protocol.tex	Mon Mar 12 10:07:08 2007 -0600
    15.3 @@ -30,8 +30,13 @@ These types are mapped onto XML-RPC type
    15.4    \item Floats, Bools, DateTimes and Strings map directly to the XML-RPC {\tt
    15.5    double}, {\tt boolean}, {\tt dateTime.iso8601}, and {\tt string} elements.
    15.6  
    15.7 -  \item all our ``{\tt ref\_}'' types (e.g.\ {\tt ref\_vm} in the above
    15.8 -  example) map to XML-RPC's {\tt String} type.  The string itself is the OSF
    15.9 +  \item all ``{\tt ref\_}'' types are opaque references, encoded as the
   15.10 +  XML-RPC's {\tt String} type. Users of the API should not make assumptions
   15.11 +  about the concrete form of these strings and should not expect them to
   15.12 +  remain valid after the client's session with the server has terminated.
   15.13 +
   15.14 +  \item fields named ``{\tt uuid}'' of type ``{\tt String}'' are mapped to
   15.15 +  the XML-RPC {\tt String} type. The string itself is the OSF
   15.16    DCE UUID presentation format (as output by {\tt uuidgen}, etc).
   15.17  
   15.18    \item ints are all assumed to be 64-bit in our API and are encoded as a
   15.19 @@ -84,6 +89,32 @@ These types are mapped onto XML-RPC type
   15.20  
   15.21  \end{itemize}
   15.22  
   15.23 +\subsection{Note on References vs UUIDs}
   15.24 +
   15.25 +References are opaque types --- encoded as XML-RPC strings on the wire --- understood
   15.26 +only by the particular server which generated them. Servers are free to choose
   15.27 +any concrete representation they find convenient; clients should not make any 
   15.28 +assumptions or attempt to parse the string contents. References are not guaranteed
   15.29 +to be permanent identifiers for objects; clients should not assume that references 
   15.30 +generated during one session are valid for any future session. References do not
   15.31 +allow objects to be compared for equality. Two references to the same object are
   15.32 +not guaranteed to be textually identical.
   15.33 +
   15.34 +UUIDs are intended to be permanent names for objects. They are
   15.35 +guaranteed to be in the OSF DCE UUID presentation format (as output by {\tt uuidgen}.
   15.36 +Clients may store UUIDs on disk and use them to lookup objects in subsequent sessions
   15.37 +with the server. Clients may also test equality on objects by comparing UUID strings.
   15.38 +
   15.39 +The API provides mechanisms
   15.40 +for translating between UUIDs and opaque references. Each class that contains a UUID
   15.41 +field provides:
   15.42 +\begin{itemize}
   15.43 +\item  A ``{\tt get\_by\_uuid}'' method that takes a UUID, $u$, and returns an opaque reference
   15.44 +to the server-side object that has UUID=$u$; 
   15.45 +\item A {\tt get\_uuid} function (a regular ``field getter'' RPC) that takes an opaque reference,
   15.46 +$r$, and returns the UUID of the server-side object that is referenced by $r$.
   15.47 +\end{itemize}
   15.48 +
   15.49  \subsection{Return Values/Status Codes}
   15.50  \label{synchronous-result}
   15.51  
   15.52 @@ -138,7 +169,7 @@ may look like this:
   15.53  
   15.54  \subsection{Transport Layer}
   15.55  
   15.56 -We ought to support at least
   15.57 +The following transport layers are currently supported:
   15.58  \begin{itemize}
   15.59  \item HTTP/S for remote administration
   15.60  \item HTTP over Unix domain sockets for local administration
   15.61 @@ -247,13 +278,12 @@ call takes the session token as the only
   15.62  \begin{verbatim}
   15.63  >>> all_vms = host.get_resident_VMs(session)['Value']
   15.64  >>> all_vms
   15.65 -['b7b92d9e-d442-4710-92a5-ab039fd7d89b', '23e1e837-abbf-4675-b077-d4007989b0cc',
   15.66 -  '2045dbc0-0734-4eea-9cb2-b8218c6b5bf2', '3202ae18-a046-4c32-9fda-e32e9631866e']
   15.67 +['OpaqueRef:1', 'OpaqueRef:2', 'OpaqueRef:3', 'OpaqueRef:4' ]
   15.68  \end{verbatim}
   15.69  
   15.70 -The VM references here are UUIDs, though they may not be that simple in the
   15.71 -future, and you should treat them as opaque strings.  Once a reference to a VM
   15.72 -has been acquired a lifecycle operation may be invoked:
   15.73 +The VM references here have the form {\tt OpaqueRef:X}, though they may not be 
   15.74 +that simple in the future, and you should treat them as opaque strings.  
   15.75 +Once a reference to a VM has been acquired a lifecycle operation may be invoked:
   15.76  
   15.77  \begin{verbatim}
   15.78  >>> xen.VM.start(session, all_vms[3], False)
    16.1 --- a/docs/xen-api/xenapi-datamodel.tex	Mon Mar 12 09:43:48 2007 -0600
    16.2 +++ b/docs/xen-api/xenapi-datamodel.tex	Mon Mar 12 10:07:08 2007 -0600
    16.3 @@ -231,7 +231,7 @@ Quals & Field & Type & Description \\
    16.4  $\mathit{RO}_\mathit{run}$ &  {\tt last\_active} & int & Timestamp for last time session was active \\
    16.5  \hline
    16.6  \end{longtable}
    16.7 -\subsection{Additional RPCs associated with class: session}
    16.8 +\subsection{RPCs associated with class: session}
    16.9  \subsubsection{RPC name:~login\_with\_password}
   16.10  
   16.11  {\bf Overview:} 
   16.12 @@ -505,7 +505,7 @@ Quals & Field & Type & Description \\
   16.13  $\mathit{RO}_\mathit{run}$ &  {\tt allowed\_operations} & (task\_allowed\_operations) Set & Operations allowed on this task \\
   16.14  \hline
   16.15  \end{longtable}
   16.16 -\subsection{Additional RPCs associated with class: task}
   16.17 +\subsection{RPCs associated with class: task}
   16.18  \subsubsection{RPC name:~cancel}
   16.19  
   16.20  {\bf Overview:} 
   16.21 @@ -1022,40 +1022,7 @@ references to objects with match names
   16.22  \hline
   16.23  \multicolumn{1}{|l}{Name} & \multicolumn{3}{l|}{\bf VM} \\
   16.24  \multicolumn{1}{|l}{Description} & \multicolumn{3}{l|}{\parbox{11cm}{\em A
   16.25 -virtual machine (or 'guest').
   16.26 -
   16.27 -VM booting is controlled by setting one of the two mutually exclusive
   16.28 -groups: "PV", and "HVM".  If HVM.boot\_policy is the empty string, then
   16.29 -paravirtual domain building and booting will be used; otherwise the VM will
   16.30 -be loaded as an HVM domain, and booted using an emulated BIOS.
   16.31 -
   16.32 -When paravirtual booting is in use, the PV/bootloader field indicates the
   16.33 -bootloader to use.  It may be "pygrub", in which case the platform's
   16.34 -default installation of pygrub will be used, or a full path within the
   16.35 -control domain to some other bootloader.  The other fields, PV/kernel,
   16.36 -PV/ramdisk, PV/args and PV/bootloader\_args will be passed to the
   16.37 -bootloader unmodified, and interpretation of those fields is then specific
   16.38 -to the bootloader itself, including the possibility that the bootloader
   16.39 -will ignore some or all of those given values. Finally the paths of all
   16.40 -bootable disks are added to the bootloader commandline (a disk is bootable
   16.41 -if its VBD has the bootable flag set). There may be zero, one or many
   16.42 -bootable disks; the bootloader decides which disk (if any) to boot from.
   16.43 -
   16.44 -If the bootloader is pygrub, then the menu.lst is parsed if present in the
   16.45 -guest's filesystem, otherwise the specified kernel and ramdisk are used, or
   16.46 -an autodetected kernel is used if nothing is specified and autodetection is
   16.47 -possible.  PV/args is appended to the kernel command line, no matter which
   16.48 -mechanism is used for finding the kernel.
   16.49 -
   16.50 -If PV/bootloader is empty but PV/kernel is specified, then the kernel and
   16.51 -ramdisk values will be treated as paths within the control domain.  If both
   16.52 -PV/bootloader and PV/kernel are empty, then the behaviour is as if
   16.53 -PV/bootloader was specified as "pygrub".
   16.54 -
   16.55 -When using HVM booting, HVM/boot\_policy and HVM/boot\_params specify the
   16.56 -boot handling.  Only one policy is currently defined: "BIOS order".  In
   16.57 -this case, HVM/boot\_params should contain one key-value pair "order" = "N"
   16.58 -where N is the string that will be passed to QEMU.}} \\
   16.59 +virtual machine (or 'guest').}} \\
   16.60  \hline
   16.61  Quals & Field & Type & Description \\
   16.62  \hline
   16.63 @@ -1091,12 +1058,8 @@ Quals & Field & Type & Description \\
   16.64  $\mathit{RW}$ &  {\tt PV/bootloader\_args} & string & miscellaneous arguments for the bootloader \\
   16.65  $\mathit{RW}$ &  {\tt HVM/boot\_policy} & string & HVM boot policy \\
   16.66  $\mathit{RW}$ &  {\tt HVM/boot\_params} & (string $\rightarrow$ string) Map & HVM boot params \\
   16.67 -$\mathit{RW}$ &  {\tt platform/std\_VGA} & bool & emulate standard VGA instead of cirrus logic \\
   16.68 -$\mathit{RW}$ &  {\tt platform/serial} & string & redirect serial port to pty \\
   16.69 -$\mathit{RW}$ &  {\tt platform/localtime} & bool & set RTC to local time \\
   16.70 -$\mathit{RW}$ &  {\tt platform/clock\_offset} & bool & timeshift applied to guest's clock \\
   16.71 -$\mathit{RW}$ &  {\tt platform/enable\_audio} & bool & emulate audio \\
   16.72 -$\mathit{RO}_\mathit{ins}$ &  {\tt PCI\_bus} & string & PCI bus path for pass-through devices \\
   16.73 +$\mathit{RW}$ &  {\tt platform} & (string $\rightarrow$ string) Map & platform-specific configuration \\
   16.74 +$\mathit{RW}$ &  {\tt PCI\_bus} & string & PCI bus path for pass-through devices \\
   16.75  $\mathit{RW}$ &  {\tt other\_config} & (string $\rightarrow$ string) Map & additional configuration \\
   16.76  $\mathit{RO}_\mathit{run}$ &  {\tt domid} & int & domain ID (if available, -1 otherwise) \\
   16.77  $\mathit{RO}_\mathit{run}$ &  {\tt is\_control\_domain} & bool & true if this is a control domain (domain 0 or a driver domain) \\
   16.78 @@ -1104,7 +1067,7 @@ Quals & Field & Type & Description \\
   16.79  $\mathit{RO}_\mathit{run}$ &  {\tt guest\_metrics} & VM\_guest\_metrics ref & metrics associated with the running guest \\
   16.80  \hline
   16.81  \end{longtable}
   16.82 -\subsection{Additional RPCs associated with class: VM}
   16.83 +\subsection{RPCs associated with class: VM}
   16.84  \subsubsection{RPC name:~clone}
   16.85  
   16.86  {\bf Overview:} 
   16.87 @@ -1178,7 +1141,8 @@ void
   16.88  
   16.89  \vspace{0.3cm}
   16.90  
   16.91 -\noindent{\bf Possible Error Codes:} {\tt VM\_BAD\_POWER\_STATE}
   16.92 +\noindent{\bf Possible Error Codes:} {\tt VM\_BAD\_POWER\_STATE}, {\tt
   16.93 +VM\_HVM\_REQUIRED}
   16.94  
   16.95  \vspace{0.6cm}
   16.96  \subsubsection{RPC name:~pause}
   16.97 @@ -1362,8 +1326,10 @@ void
   16.98  
   16.99  
  16.100  \vspace{0.3cm}
  16.101 -\vspace{0.3cm}
  16.102 -\vspace{0.3cm}
  16.103 +
  16.104 +\noindent{\bf Possible Error Codes:} {\tt VM\_BAD\_POWER\_STATE}
  16.105 +
  16.106 +\vspace{0.6cm}
  16.107  \subsubsection{RPC name:~hard\_reboot}
  16.108  
  16.109  {\bf Overview:} 
  16.110 @@ -3438,321 +3404,128 @@ void
  16.111  \vspace{0.3cm}
  16.112  \vspace{0.3cm}
  16.113  \vspace{0.3cm}
  16.114 -\subsubsection{RPC name:~get\_platform\_std\_VGA}
  16.115 -
  16.116 -{\bf Overview:} 
  16.117 -Get the platform/std\_VGA field of the given VM.
  16.118 -
  16.119 - \noindent {\bf Signature:} 
  16.120 -\begin{verbatim} bool get_platform_std_VGA (session_id s, VM ref self)\end{verbatim}
  16.121 -
  16.122 -
  16.123 -\noindent{\bf Arguments:}
  16.124 -
  16.125 - 
  16.126 -\vspace{0.3cm}
  16.127 -\begin{tabular}{|c|c|p{7cm}|}
  16.128 - \hline
  16.129 -{\bf type} & {\bf name} & {\bf description} \\ \hline
  16.130 -{\tt VM ref } & self & reference to the object \\ \hline 
  16.131 -
  16.132 -\end{tabular}
  16.133 -
  16.134 -\vspace{0.3cm}
  16.135 -
  16.136 - \noindent {\bf Return Type:} 
  16.137 -{\tt 
  16.138 -bool
  16.139 -}
  16.140 -
  16.141 -
  16.142 -value of the field
  16.143 -\vspace{0.3cm}
  16.144 -\vspace{0.3cm}
  16.145 -\vspace{0.3cm}
  16.146 -\subsubsection{RPC name:~set\_platform\_std\_VGA}
  16.147 -
  16.148 -{\bf Overview:} 
  16.149 -Set the platform/std\_VGA field of the given VM.
  16.150 -
  16.151 - \noindent {\bf Signature:} 
  16.152 -\begin{verbatim} void set_platform_std_VGA (session_id s, VM ref self, bool value)\end{verbatim}
  16.153 -
  16.154 -
  16.155 -\noindent{\bf Arguments:}
  16.156 -
  16.157 - 
  16.158 -\vspace{0.3cm}
  16.159 -\begin{tabular}{|c|c|p{7cm}|}
  16.160 - \hline
  16.161 -{\bf type} & {\bf name} & {\bf description} \\ \hline
  16.162 -{\tt VM ref } & self & reference to the object \\ \hline 
  16.163 -
  16.164 -{\tt bool } & value & New value to set \\ \hline 
  16.165 -
  16.166 -\end{tabular}
  16.167 -
  16.168 -\vspace{0.3cm}
  16.169 -
  16.170 - \noindent {\bf Return Type:} 
  16.171 -{\tt 
  16.172 -void
  16.173 -}
  16.174 -
  16.175 -
  16.176 -
  16.177 -\vspace{0.3cm}
  16.178 -\vspace{0.3cm}
  16.179 -\vspace{0.3cm}
  16.180 -\subsubsection{RPC name:~get\_platform\_serial}
  16.181 -
  16.182 -{\bf Overview:} 
  16.183 -Get the platform/serial field of the given VM.
  16.184 -
  16.185 - \noindent {\bf Signature:} 
  16.186 -\begin{verbatim} string get_platform_serial (session_id s, VM ref self)\end{verbatim}
  16.187 -
  16.188 -
  16.189 -\noindent{\bf Arguments:}
  16.190 -
  16.191 - 
  16.192 -\vspace{0.3cm}
  16.193 -\begin{tabular}{|c|c|p{7cm}|}
  16.194 - \hline
  16.195 -{\bf type} & {\bf name} & {\bf description} \\ \hline
  16.196 -{\tt VM ref } & self & reference to the object \\ \hline 
  16.197 -
  16.198 -\end{tabular}
  16.199 -
  16.200 -\vspace{0.3cm}
  16.201 -
  16.202 - \noindent {\bf Return Type:} 
  16.203 -{\tt 
  16.204 -string
  16.205 -}
  16.206 -
  16.207 -
  16.208 -value of the field
  16.209 -\vspace{0.3cm}
  16.210 -\vspace{0.3cm}
  16.211 -\vspace{0.3cm}
  16.212 -\subsubsection{RPC name:~set\_platform\_serial}
  16.213 -
  16.214 -{\bf Overview:} 
  16.215 -Set the platform/serial field of the given VM.
  16.216 -
  16.217 - \noindent {\bf Signature:} 
  16.218 -\begin{verbatim} void set_platform_serial (session_id s, VM ref self, string value)\end{verbatim}
  16.219 -
  16.220 -
  16.221 -\noindent{\bf Arguments:}
  16.222 -
  16.223 - 
  16.224 -\vspace{0.3cm}
  16.225 -\begin{tabular}{|c|c|p{7cm}|}
  16.226 - \hline
  16.227 -{\bf type} & {\bf name} & {\bf description} \\ \hline
  16.228 -{\tt VM ref } & self & reference to the object \\ \hline 
  16.229 -
  16.230 -{\tt string } & value & New value to set \\ \hline 
  16.231 -
  16.232 -\end{tabular}
  16.233 -
  16.234 -\vspace{0.3cm}
  16.235 -
  16.236 - \noindent {\bf Return Type:} 
  16.237 -{\tt 
  16.238 -void
  16.239 -}
  16.240 -
  16.241 -
  16.242 -
  16.243 -\vspace{0.3cm}
  16.244 -\vspace{0.3cm}
  16.245 -\vspace{0.3cm}
  16.246 -\subsubsection{RPC name:~get\_platform\_localtime}
  16.247 -
  16.248 -{\bf Overview:} 
  16.249 -Get the platform/localtime field of the given VM.
  16.250 -
  16.251 - \noindent {\bf Signature:} 
  16.252 -\begin{verbatim} bool get_platform_localtime (session_id s, VM ref self)\end{verbatim}
  16.253 -
  16.254 -
  16.255 -\noindent{\bf Arguments:}
  16.256 -
  16.257 - 
  16.258 -\vspace{0.3cm}
  16.259 -\begin{tabular}{|c|c|p{7cm}|}
  16.260 - \hline
  16.261 -{\bf type} & {\bf name} & {\bf description} \\ \hline
  16.262 -{\tt VM ref } & self & reference to the object \\ \hline 
  16.263 -
  16.264 -\end{tabular}
  16.265 -
  16.266 -\vspace{0.3cm}
  16.267 -
  16.268 - \noindent {\bf Return Type:} 
  16.269 -{\tt 
  16.270 -bool
  16.271 -}
  16.272 -
  16.273 -
  16.274 -value of the field
  16.275 -\vspace{0.3cm}
  16.276 -\vspace{0.3cm}
  16.277 -\vspace{0.3cm}
  16.278 -\subsubsection{RPC name:~set\_platform\_localtime}
  16.279 -
  16.280 -{\bf Overview:} 
  16.281 -Set the platform/localtime field of the given VM.
  16.282 -
  16.283 - \noindent {\bf Signature:} 
  16.284 -\begin{verbatim} void set_platform_localtime (session_id s, VM ref self, bool value)\end{verbatim}
  16.285 -
  16.286 -
  16.287 -\noindent{\bf Arguments:}
  16.288 -
  16.289 - 
  16.290 -\vspace{0.3cm}
  16.291 -\begin{tabular}{|c|c|p{7cm}|}
  16.292 - \hline
  16.293 -{\bf type} & {\bf name} & {\bf description} \\ \hline
  16.294 -{\tt VM ref } & self & reference to the object \\ \hline 
  16.295 -
  16.296 -{\tt bool } & value & New value to set \\ \hline 
  16.297 -
  16.298 -\end{tabular}
  16.299 -
  16.300 -\vspace{0.3cm}
  16.301 -
  16.302 - \noindent {\bf Return Type:} 
  16.303 -{\tt 
  16.304 -void
  16.305 -}
  16.306 -
  16.307 -
  16.308 -
  16.309 -\vspace{0.3cm}
  16.310 -\vspace{0.3cm}
  16.311 -\vspace{0.3cm}
  16.312 -\subsubsection{RPC name:~get\_platform\_clock\_offset}
  16.313 -
  16.314 -{\bf Overview:} 
  16.315 -Get the platform/clock\_offset field of the given VM.
  16.316 -
  16.317 - \noindent {\bf Signature:} 
  16.318 -\begin{verbatim} bool get_platform_clock_offset (session_id s, VM ref self)\end{verbatim}
  16.319 -
  16.320 -
  16.321 -\noindent{\bf Arguments:}
  16.322 -
  16.323 - 
  16.324 -\vspace{0.3cm}
  16.325 -\begin{tabular}{|c|c|p{7cm}|}
  16.326 - \hline
  16.327 -{\bf type} & {\bf name} & {\bf description} \\ \hline
  16.328 -{\tt VM ref } & self & reference to the object \\ \hline 
  16.329 -
  16.330 -\end{tabular}
  16.331 -
  16.332 -\vspace{0.3cm}
  16.333 -
  16.334 - \noindent {\bf Return Type:} 
  16.335 -{\tt 
  16.336 -bool
  16.337 -}
  16.338 -
  16.339 -
  16.340 -value of the field
  16.341 -\vspace{0.3cm}
  16.342 -\vspace{0.3cm}
  16.343 -\vspace{0.3cm}
  16.344 -\subsubsection{RPC name:~set\_platform\_clock\_offset}
  16.345 -
  16.346 -{\bf Overview:} 
  16.347 -Set the platform/clock\_offset field of the given VM.
  16.348 -
  16.349 - \noindent {\bf Signature:} 
  16.350 -\begin{verbatim} void set_platform_clock_offset (session_id s, VM ref self, bool value)\end{verbatim}
  16.351 -
  16.352 -
  16.353 -\noindent{\bf Arguments:}
  16.354 -
  16.355 - 
  16.356 -\vspace{0.3cm}
  16.357 -\begin{tabular}{|c|c|p{7cm}|}
  16.358 - \hline
  16.359 -{\bf type} & {\bf name} & {\bf description} \\ \hline
  16.360 -{\tt VM ref } & self & reference to the object \\ \hline 
  16.361 -
  16.362 -{\tt bool } & value & New value to set \\ \hline 
  16.363 -
  16.364 -\end{tabular}
  16.365 -
  16.366 -\vspace{0.3cm}
  16.367 -
  16.368 - \noindent {\bf Return Type:} 
  16.369 -{\tt 
  16.370 -void
  16.371 -}
  16.372 -
  16.373 -
  16.374 -
  16.375 -\vspace{0.3cm}
  16.376 -\vspace{0.3cm}
  16.377 -\vspace{0.3cm}
  16.378 -\subsubsection{RPC name:~get\_platform\_enable\_audio}
  16.379 -
  16.380 -{\bf Overview:} 
  16.381 -Get the platform/enable\_audio field of the given VM.
  16.382 -
  16.383 - \noindent {\bf Signature:} 
  16.384 -\begin{verbatim} bool get_platform_enable_audio (session_id s, VM ref self)\end{verbatim}
  16.385 -
  16.386 -
  16.387 -\noindent{\bf Arguments:}
  16.388 -
  16.389 - 
  16.390 -\vspace{0.3cm}
  16.391 -\begin{tabular}{|c|c|p{7cm}|}
  16.392 - \hline
  16.393 -{\bf type} & {\bf name} & {\bf description} \\ \hline
  16.394 -{\tt VM ref } & self & reference to the object \\ \hline 
  16.395 -
  16.396 -\end{tabular}
  16.397 -
  16.398 -\vspace{0.3cm}
  16.399 -
  16.400 - \noindent {\bf Return Type:} 
  16.401 -{\tt 
  16.402 -bool
  16.403 -}
  16.404 -
  16.405 -
  16.406 -value of the field
  16.407 -\vspace{0.3cm}
  16.408 -\vspace{0.3cm}
  16.409 -\vspace{0.3cm}
  16.410 -\subsubsection{RPC name:~set\_platform\_enable\_audio}
  16.411 -
  16.412 -{\bf Overview:} 
  16.413 -Set the platform/enable\_audio field of the given VM.
  16.414 -
  16.415 - \noindent {\bf Signature:} 
  16.416 -\begin{verbatim} void set_platform_enable_audio (session_id s, VM ref self, bool value)\end{verbatim}
  16.417 -
  16.418 -
  16.419 -\noindent{\bf Arguments:}
  16.420 -
  16.421 - 
  16.422 -\vspace{0.3cm}
  16.423 -\begin{tabular}{|c|c|p{7cm}|}
  16.424 - \hline
  16.425 -{\bf type} & {\bf name} & {\bf description} \\ \hline
  16.426 -{\tt VM ref } & self & reference to the object \\ \hline 
  16.427 -
  16.428 -{\tt bool } & value & New value to set \\ \hline 
  16.429 +\subsubsection{RPC name:~get\_platform}
  16.430 +
  16.431 +{\bf Overview:} 
  16.432 +Get the platform field of the given VM.
  16.433 +
  16.434 + \noindent {\bf Signature:} 
  16.435 +\begin{verbatim} ((string -> string) Map) get_platform (session_id s, VM ref self)\end{verbatim}
  16.436 +
  16.437 +
  16.438 +\noindent{\bf Arguments:}
  16.439 +
  16.440 + 
  16.441 +\vspace{0.3cm}
  16.442 +\begin{tabular}{|c|c|p{7cm}|}
  16.443 + \hline
  16.444 +{\bf type} & {\bf name} & {\bf description} \\ \hline
  16.445 +{\tt VM ref } & self & reference to the object \\ \hline 
  16.446 +
  16.447 +\end{tabular}
  16.448 +
  16.449 +\vspace{0.3cm}
  16.450 +
  16.451 + \noindent {\bf Return Type:} 
  16.452 +{\tt 
  16.453 +(string $\rightarrow$ string) Map
  16.454 +}
  16.455 +
  16.456 +
  16.457 +value of the field
  16.458 +\vspace{0.3cm}
  16.459 +\vspace{0.3cm}
  16.460 +\vspace{0.3cm}
  16.461 +\subsubsection{RPC name:~set\_platform}
  16.462 +
  16.463 +{\bf Overview:} 
  16.464 +Set the platform field of the given VM.
  16.465 +
  16.466 + \noindent {\bf Signature:} 
  16.467 +\begin{verbatim} void set_platform (session_id s, VM ref self, (string -> string) Map value)\end{verbatim}
  16.468 +
  16.469 +
  16.470 +\noindent{\bf Arguments:}
  16.471 +
  16.472 + 
  16.473 +\vspace{0.3cm}
  16.474 +\begin{tabular}{|c|c|p{7cm}|}
  16.475 + \hline
  16.476 +{\bf type} & {\bf name} & {\bf description} \\ \hline
  16.477 +{\tt VM ref } & self & reference to the object \\ \hline 
  16.478 +
  16.479 +{\tt (string $\rightarrow$ string) Map } & value & New value to set \\ \hline 
  16.480 +
  16.481 +\end{tabular}
  16.482 +
  16.483 +\vspace{0.3cm}
  16.484 +
  16.485 + \noindent {\bf Return Type:} 
  16.486 +{\tt 
  16.487 +void
  16.488 +}
  16.489 +
  16.490 +
  16.491 +
  16.492 +\vspace{0.3cm}
  16.493 +\vspace{0.3cm}
  16.494 +\vspace{0.3cm}
  16.495 +\subsubsection{RPC name:~add\_to\_platform}
  16.496 +
  16.497 +{\bf Overview:} 
  16.498 +Add the given key-value pair to the platform field of the given VM.
  16.499 +
  16.500 + \noindent {\bf Signature:} 
  16.501 +\begin{verbatim} void add_to_platform (session_id s, VM ref self, string key, string value)\end{verbatim}
  16.502 +
  16.503 +
  16.504 +\noindent{\bf Arguments:}
  16.505 +
  16.506 + 
  16.507 +\vspace{0.3cm}
  16.508 +\begin{tabular}{|c|c|p{7cm}|}
  16.509 + \hline
  16.510 +{\bf type} & {\bf name} & {\bf description} \\ \hline
  16.511 +{\tt VM ref } & self & reference to the object \\ \hline 
  16.512 +
  16.513 +{\tt string } & key & Key to add \\ \hline 
  16.514 +
  16.515 +{\tt string } & value & Value to add \\ \hline 
  16.516 +
  16.517 +\end{tabular}
  16.518 +
  16.519 +\vspace{0.3cm}
  16.520 +
  16.521 + \noindent {\bf Return Type:} 
  16.522 +{\tt 
  16.523 +void
  16.524 +}
  16.525 +
  16.526 +
  16.527 +
  16.528 +\vspace{0.3cm}
  16.529 +\vspace{0.3cm}
  16.530 +\vspace{0.3cm}
  16.531 +\subsubsection{RPC name:~remove\_from\_platform}
  16.532 +
  16.533 +{\bf Overview:} 
  16.534 +Remove the given key and its corresponding value from the platform field of
  16.535 +the given VM.  If the key is not in that Map, then do nothing.
  16.536 +
  16.537 + \noindent {\bf Signature:} 
  16.538 +\begin{verbatim} void remove_from_platform (session_id s, VM ref self, string key)\end{verbatim}
  16.539 +
  16.540 +
  16.541 +\noindent{\bf Arguments:}
  16.542 +
  16.543 + 
  16.544 +\vspace{0.3cm}
  16.545 +\begin{tabular}{|c|c|p{7cm}|}
  16.546 + \hline
  16.547 +{\bf type} & {\bf name} & {\bf description} \\ \hline
  16.548 +{\tt VM ref } & self & reference to the object \\ \hline 
  16.549 +
  16.550 +{\tt string } & key & Key to remove \\ \hline 
  16.551  
  16.552  \end{tabular}
  16.553  
  16.554 @@ -3800,6 +3573,40 @@ value of the field
  16.555  \vspace{0.3cm}
  16.556  \vspace{0.3cm}
  16.557  \vspace{0.3cm}
  16.558 +\subsubsection{RPC name:~set\_PCI\_bus}
  16.559 +
  16.560 +{\bf Overview:} 
  16.561 +Set the PCI\_bus field of the given VM.
  16.562 +
  16.563 + \noindent {\bf Signature:} 
  16.564 +\begin{verbatim} void set_PCI_bus (session_id s, VM ref self, string value)\end{verbatim}
  16.565 +
  16.566 +
  16.567 +\noindent{\bf Arguments:}
  16.568 +
  16.569 + 
  16.570 +\vspace{0.3cm}
  16.571 +\begin{tabular}{|c|c|p{7cm}|}
  16.572 + \hline
  16.573 +{\bf type} & {\bf name} & {\bf description} \\ \hline
  16.574 +{\tt VM ref } & self & reference to the object \\ \hline 
  16.575 +
  16.576 +{\tt string } & value & New value to set \\ \hline 
  16.577 +
  16.578 +\end{tabular}
  16.579 +
  16.580 +\vspace{0.3cm}
  16.581 +
  16.582 + \noindent {\bf Return Type:} 
  16.583 +{\tt 
  16.584 +void
  16.585 +}
  16.586 +
  16.587 +
  16.588 +
  16.589 +\vspace{0.3cm}
  16.590 +\vspace{0.3cm}
  16.591 +\vspace{0.3cm}
  16.592  \subsubsection{RPC name:~get\_other\_config}
  16.593  
  16.594  {\bf Overview:} 
  16.595 @@ -4245,7 +4052,7 @@ Quals & Field & Type & Description \\
  16.596  $\mathit{RO}_\mathit{run}$ &  {\tt VCPUs/utilisation} & (int $\rightarrow$ float) Map & Utilisation for all of guest's current VCPUs \\
  16.597  \hline
  16.598  \end{longtable}
  16.599 -\subsection{Additional RPCs associated with class: VM\_metrics}
  16.600 +\subsection{RPCs associated with class: VM\_metrics}
  16.601  \subsubsection{RPC name:~get\_all}
  16.602  
  16.603  {\bf Overview:} 
  16.604 @@ -4481,7 +4288,7 @@ Quals & Field & Type & Description \\
  16.605  $\mathit{RO}_\mathit{run}$ &  {\tt other} & (string $\rightarrow$ string) Map & anything else \\
  16.606  \hline
  16.607  \end{longtable}
  16.608 -\subsection{Additional RPCs associated with class: VM\_guest\_metrics}
  16.609 +\subsection{RPCs associated with class: VM\_guest\_metrics}
  16.610  \subsubsection{RPC name:~get\_all}
  16.611  
  16.612  {\bf Overview:} 
  16.613 @@ -4825,7 +4632,7 @@ Quals & Field & Type & Description \\
  16.614  $\mathit{RO}_\mathit{ins}$ &  {\tt metrics} & host\_metrics ref & metrics associated with this host. \\
  16.615  \hline
  16.616  \end{longtable}
  16.617 -\subsection{Additional RPCs associated with class: host}
  16.618 +\subsection{RPCs associated with class: host}
  16.619  \subsubsection{RPC name:~disable}
  16.620  
  16.621  {\bf Overview:} 
  16.622 @@ -6078,7 +5885,7 @@ Quals & Field & Type & Description \\
  16.623  $\mathit{RO}_\mathit{run}$ &  {\tt memory/free} & int & Host's free memory (bytes) \\
  16.624  \hline
  16.625  \end{longtable}
  16.626 -\subsection{Additional RPCs associated with class: host\_metrics}
  16.627 +\subsection{RPCs associated with class: host\_metrics}
  16.628  \subsubsection{RPC name:~get\_all}
  16.629  
  16.630  {\bf Overview:} 
  16.631 @@ -6283,7 +6090,7 @@ Quals & Field & Type & Description \\
  16.632  $\mathit{RO}_\mathit{run}$ &  {\tt utilisation} & float & the current CPU utilisation \\
  16.633  \hline
  16.634  \end{longtable}
  16.635 -\subsection{Additional RPCs associated with class: host\_cpu}
  16.636 +\subsection{RPCs associated with class: host\_cpu}
  16.637  \subsubsection{RPC name:~get\_all}
  16.638  
  16.639  {\bf Overview:} 
  16.640 @@ -6677,7 +6484,7 @@ Quals & Field & Type & Description \\
  16.641  $\mathit{RO}_\mathit{run}$ &  {\tt PIFs} & (PIF ref) Set & list of connected pifs \\
  16.642  \hline
  16.643  \end{longtable}
  16.644 -\subsection{Additional RPCs associated with class: network}
  16.645 +\subsection{RPCs associated with class: network}
  16.646  \subsubsection{RPC name:~get\_all}
  16.647  
  16.648  {\bf Overview:} 
  16.649 @@ -7115,7 +6922,72 @@ Quals & Field & Type & Description \\
  16.650  $\mathit{RO}_\mathit{run}$ &  {\tt metrics} & VIF\_metrics ref & metrics associated with this VIF. \\
  16.651  \hline
  16.652  \end{longtable}
  16.653 -\subsection{Additional RPCs associated with class: VIF}
  16.654 +\subsection{RPCs associated with class: VIF}
  16.655 +\subsubsection{RPC name:~plug}
  16.656 +
  16.657 +{\bf Overview:} 
  16.658 +Hotplug the specified VIF, dynamically attaching it to the running VM.
  16.659 +
  16.660 + \noindent {\bf Signature:} 
  16.661 +\begin{verbatim} void plug (session_id s, VIF ref self)\end{verbatim}
  16.662 +
  16.663 +
  16.664 +\noindent{\bf Arguments:}
  16.665 +
  16.666 + 
  16.667 +\vspace{0.3cm}
  16.668 +\begin{tabular}{|c|c|p{7cm}|}
  16.669 + \hline
  16.670 +{\bf type} & {\bf name} & {\bf description} \\ \hline
  16.671 +{\tt VIF ref } & self & The VIF to hotplug \\ \hline 
  16.672 +
  16.673 +\end{tabular}
  16.674 +
  16.675 +\vspace{0.3cm}
  16.676 +
  16.677 + \noindent {\bf Return Type:} 
  16.678 +{\tt 
  16.679 +void
  16.680 +}
  16.681 +
  16.682 +
  16.683 +
  16.684 +\vspace{0.3cm}
  16.685 +\vspace{0.3cm}
  16.686 +\vspace{0.3cm}
  16.687 +\subsubsection{RPC name:~unplug}
  16.688 +
  16.689 +{\bf Overview:} 
  16.690 +Hot-unplug the specified VIF, dynamically unattaching it from the running
  16.691 +VM.
  16.692 +
  16.693 + \noindent {\bf Signature:} 
  16.694 +\begin{verbatim} void unplug (session_id s, VIF ref self)\end{verbatim}
  16.695 +
  16.696 +
  16.697 +\noindent{\bf Arguments:}
  16.698 +
  16.699 + 
  16.700 +\vspace{0.3cm}
  16.701 +\begin{tabular}{|c|c|p{7cm}|}
  16.702 + \hline
  16.703 +{\bf type} & {\bf name} & {\bf description} \\ \hline
  16.704 +{\tt VIF ref } & self & The VIF to hot-unplug \\ \hline 
  16.705 +
  16.706 +\end{tabular}
  16.707 +
  16.708 +\vspace{0.3cm}
  16.709 +
  16.710 + \noindent {\bf Return Type:} 
  16.711 +{\tt 
  16.712 +void
  16.713 +}
  16.714 +
  16.715 +
  16.716 +
  16.717 +\vspace{0.3cm}
  16.718 +\vspace{0.3cm}
  16.719 +\vspace{0.3cm}
  16.720  \subsubsection{RPC name:~get\_all}
  16.721  
  16.722  {\bf Overview:} 
  16.723 @@ -7942,7 +7814,7 @@ Quals & Field & Type & Description \\
  16.724  $\mathit{RO}_\mathit{run}$ &  {\tt io/write\_kbs} & float & Write bandwidth (KiB/s) \\
  16.725  \hline
  16.726  \end{longtable}
  16.727 -\subsection{Additional RPCs associated with class: VIF\_metrics}
  16.728 +\subsection{RPCs associated with class: VIF\_metrics}
  16.729  \subsubsection{RPC name:~get\_all}
  16.730  
  16.731  {\bf Overview:} 
  16.732 @@ -8148,7 +8020,7 @@ Quals & Field & Type & Description \\
  16.733  $\mathit{RO}_\mathit{ins}$ &  {\tt metrics} & PIF\_metrics ref & metrics associated with this PIF. \\
  16.734  \hline
  16.735  \end{longtable}
  16.736 -\subsection{Additional RPCs associated with class: PIF}
  16.737 +\subsection{RPCs associated with class: PIF}
  16.738  \subsubsection{RPC name:~create\_VLAN}
  16.739  
  16.740  {\bf Overview:} 
  16.741 @@ -8719,7 +8591,7 @@ Quals & Field & Type & Description \\
  16.742  $\mathit{RO}_\mathit{run}$ &  {\tt io/write\_kbs} & float & Write bandwidth (KiB/s) \\
  16.743  \hline
  16.744  \end{longtable}
  16.745 -\subsection{Additional RPCs associated with class: PIF\_metrics}
  16.746 +\subsection{RPCs associated with class: PIF\_metrics}
  16.747  \subsubsection{RPC name:~get\_all}
  16.748  
  16.749  {\bf Overview:} 
  16.750 @@ -8926,7 +8798,7 @@ Quals & Field & Type & Description \\
  16.751  $\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 \\
  16.752  \hline
  16.753  \end{longtable}
  16.754 -\subsection{Additional RPCs associated with class: SR}
  16.755 +\subsection{RPCs associated with class: SR}
  16.756  \subsubsection{RPC name:~clone}
  16.757  
  16.758  {\bf Overview:} 
  16.759 @@ -9549,7 +9421,7 @@ Quals & Field & Type & Description \\
  16.760  $\mathit{RO}_\mathit{run}$ &  {\tt uuid} & string & unique identifier/object reference \\
  16.761  $\mathit{RW}$ &  {\tt name/label} & string & a human-readable name \\
  16.762  $\mathit{RW}$ &  {\tt name/description} & string & a notes field containg human-readable description \\
  16.763 -$\mathit{RW}$ &  {\tt SR} & SR ref & storage repository in which the VDI resides \\
  16.764 +$\mathit{RO}_\mathit{ins}$ &  {\tt SR} & SR ref & storage repository in which the VDI resides \\
  16.765  $\mathit{RO}_\mathit{run}$ &  {\tt VBDs} & (VBD ref) Set & list of vbds that refer to this disk \\
  16.766  $\mathit{RO}_\mathit{run}$ &  {\tt crash\_dumps} & (crashdump ref) Set & list of crash dumps that refer to this disk \\
  16.767  $\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 \\
  16.768 @@ -9560,7 +9432,7 @@ Quals & Field & Type & Description \\
  16.769  $\mathit{RW}$ &  {\tt read\_only} & bool & true if this disk may ONLY be mounted read-only \\
  16.770  \hline
  16.771  \end{longtable}
  16.772 -\subsection{Additional RPCs associated with class: VDI}
  16.773 +\subsection{RPCs associated with class: VDI}
  16.774  \subsubsection{RPC name:~snapshot}
  16.775  
  16.776  {\bf Overview:} 
  16.777 @@ -9845,40 +9717,6 @@ value of the field
  16.778  \vspace{0.3cm}
  16.779  \vspace{0.3cm}
  16.780  \vspace{0.3cm}
  16.781 -\subsubsection{RPC name:~set\_SR}
  16.782 -
  16.783 -{\bf Overview:} 
  16.784 -Set the SR field of the given VDI.
  16.785 -
  16.786 - \noindent {\bf Signature:} 
  16.787 -\begin{verbatim} void set_SR (session_id s, VDI ref self, SR ref value)\end{verbatim}
  16.788 -
  16.789 -
  16.790 -\noindent{\bf Arguments:}
  16.791 -
  16.792 - 
  16.793 -\vspace{0.3cm}
  16.794 -\begin{tabular}{|c|c|p{7cm}|}
  16.795 - \hline
  16.796 -{\bf type} & {\bf name} & {\bf description} \\ \hline
  16.797 -{\tt VDI ref } & self & reference to the object \\ \hline 
  16.798 -
  16.799 -{\tt SR ref } & value & New value to set \\ \hline 
  16.800 -
  16.801 -\end{tabular}
  16.802 -
  16.803 -\vspace{0.3cm}
  16.804 -
  16.805 - \noindent {\bf Return Type:} 
  16.806 -{\tt 
  16.807 -void
  16.808 -}
  16.809 -
  16.810 -
  16.811 -
  16.812 -\vspace{0.3cm}
  16.813 -\vspace{0.3cm}
  16.814 -\vspace{0.3cm}
  16.815  \subsubsection{RPC name:~get\_VBDs}
  16.816  
  16.817  {\bf Overview:} 
  16.818 @@ -10426,7 +10264,7 @@ Quals & Field & Type & Description \\
  16.819  $\mathit{RO}_\mathit{run}$ &  {\tt metrics} & VBD\_metrics ref & metrics associated with this VBD \\
  16.820  \hline
  16.821  \end{longtable}
  16.822 -\subsection{Additional RPCs associated with class: VBD}
  16.823 +\subsection{RPCs associated with class: VBD}
  16.824  \subsubsection{RPC name:~media\_change}
  16.825  
  16.826  {\bf Overview:} 
  16.827 @@ -10462,6 +10300,71 @@ void
  16.828  \vspace{0.3cm}
  16.829  \vspace{0.3cm}
  16.830  \vspace{0.3cm}
  16.831 +\subsubsection{RPC name:~plug}
  16.832 +
  16.833 +{\bf Overview:} 
  16.834 +Hotplug the specified VBD, dynamically attaching it to the running VM.
  16.835 +
  16.836 + \noindent {\bf Signature:} 
  16.837 +\begin{verbatim} void plug (session_id s, VBD ref self)\end{verbatim}
  16.838 +
  16.839 +
  16.840 +\noindent{\bf Arguments:}
  16.841 +
  16.842 + 
  16.843 +\vspace{0.3cm}
  16.844 +\begin{tabular}{|c|c|p{7cm}|}
  16.845 + \hline
  16.846 +{\bf type} & {\bf name} & {\bf description} \\ \hline
  16.847 +{\tt VBD ref } & self & The VBD to hotplug \\ \hline 
  16.848 +
  16.849 +\end{tabular}
  16.850 +
  16.851 +\vspace{0.3cm}
  16.852 +
  16.853 + \noindent {\bf Return Type:} 
  16.854 +{\tt 
  16.855 +void
  16.856 +}
  16.857 +
  16.858 +
  16.859 +
  16.860 +\vspace{0.3cm}
  16.861 +\vspace{0.3cm}
  16.862 +\vspace{0.3cm}
  16.863 +\subsubsection{RPC name:~unplug}
  16.864 +
  16.865 +{\bf Overview:} 
  16.866 +Hot-unplug the specified VBD, dynamically unattaching it from the running
  16.867 +VM.
  16.868 +
  16.869 + \noindent {\bf Signature:} 
  16.870 +\begin{verbatim} void unplug (session_id s, VBD ref self)\end{verbatim}
  16.871 +
  16.872 +
  16.873 +\noindent{\bf Arguments:}
  16.874 +
  16.875 + 
  16.876 +\vspace{0.3cm}
  16.877 +\begin{tabular}{|c|c|p{7cm}|}
  16.878 + \hline
  16.879 +{\bf type} & {\bf name} & {\bf description} \\ \hline
  16.880 +{\tt VBD ref } & self & The VBD to hot-unplug \\ \hline 
  16.881 +
  16.882 +\end{tabular}
  16.883 +
  16.884 +\vspace{0.3cm}
  16.885 +
  16.886 + \noindent {\bf Return Type:} 
  16.887 +{\tt 
  16.888 +void
  16.889 +}
  16.890 +
  16.891 +
  16.892 +
  16.893 +\vspace{0.3cm}
  16.894 +\vspace{0.3cm}
  16.895 +\vspace{0.3cm}
  16.896  \subsubsection{RPC name:~get\_all}
  16.897  
  16.898  {\bf Overview:} 
  16.899 @@ -11354,7 +11257,7 @@ Quals & Field & Type & Description \\
  16.900  $\mathit{RO}_\mathit{run}$ &  {\tt io/write\_kbs} & float & Write bandwidth (KiB/s) \\
  16.901  \hline
  16.902  \end{longtable}
  16.903 -\subsection{Additional RPCs associated with class: VBD\_metrics}
  16.904 +\subsection{RPCs associated with class: VBD\_metrics}
  16.905  \subsubsection{RPC name:~get\_all}
  16.906  
  16.907  {\bf Overview:} 
  16.908 @@ -11556,7 +11459,7 @@ Quals & Field & Type & Description \\
  16.909  $\mathit{RO}_\mathit{run}$ &  {\tt currently\_attached} & bool & is the SR currently attached on this host? \\
  16.910  \hline
  16.911  \end{longtable}
  16.912 -\subsection{Additional RPCs associated with class: PBD}
  16.913 +\subsection{RPCs associated with class: PBD}
  16.914  \subsubsection{RPC name:~get\_all}
  16.915  
  16.916  {\bf Overview:} 
  16.917 @@ -11884,7 +11787,39 @@ Quals & Field & Type & Description \\
  16.918  $\mathit{RO}_\mathit{ins}$ &  {\tt VDI} & VDI ref & the virtual disk \\
  16.919  \hline
  16.920  \end{longtable}
  16.921 -\subsection{Additional RPCs associated with class: crashdump}
  16.922 +\subsection{RPCs associated with class: crashdump}
  16.923 +\subsubsection{RPC name:~destroy}
  16.924 +
  16.925 +{\bf Overview:} 
  16.926 +Destroy the specified crashdump.
  16.927 +
  16.928 + \noindent {\bf Signature:} 
  16.929 +\begin{verbatim} void destroy (session_id s, crashdump ref self)\end{verbatim}
  16.930 +
  16.931 +
  16.932 +\noindent{\bf Arguments:}
  16.933 +
  16.934 + 
  16.935 +\vspace{0.3cm}
  16.936 +\begin{tabular}{|c|c|p{7cm}|}
  16.937 + \hline
  16.938 +{\bf type} & {\bf name} & {\bf description} \\ \hline
  16.939 +{\tt crashdump ref } & self & The crashdump to destroy \\ \hline 
  16.940 +
  16.941 +\end{tabular}
  16.942 +
  16.943 +\vspace{0.3cm}
  16.944 +
  16.945 + \noindent {\bf Return Type:} 
  16.946 +{\tt 
  16.947 +void
  16.948 +}
  16.949 +
  16.950 +
  16.951 +
  16.952 +\vspace{0.3cm}
  16.953 +\vspace{0.3cm}
  16.954 +\vspace{0.3cm}
  16.955  \subsubsection{RPC name:~get\_all}
  16.956  
  16.957  {\bf Overview:} 
  16.958 @@ -12002,70 +11937,6 @@ value of the field
  16.959  \vspace{0.3cm}
  16.960  \vspace{0.3cm}
  16.961  \vspace{0.3cm}
  16.962 -\subsubsection{RPC name:~create}
  16.963 -
  16.964 -{\bf Overview:} 
  16.965 -Create a new crashdump instance, and return its handle.
  16.966 -
  16.967 - \noindent {\bf Signature:} 
  16.968 -\begin{verbatim} (crashdump ref) create (session_id s, crashdump record args)\end{verbatim}
  16.969 -
  16.970 -
  16.971 -\noindent{\bf Arguments:}
  16.972 -
  16.973 - 
  16.974 -\vspace{0.3cm}
  16.975 -\begin{tabular}{|c|c|p{7cm}|}
  16.976 - \hline
  16.977 -{\bf type} & {\bf name} & {\bf description} \\ \hline
  16.978 -{\tt crashdump record } & args & All constructor arguments \\ \hline 
  16.979 -
  16.980 -\end{tabular}
  16.981 -
  16.982 -\vspace{0.3cm}
  16.983 -
  16.984 - \noindent {\bf Return Type:} 
  16.985 -{\tt 
  16.986 -crashdump ref
  16.987 -}
  16.988 -
  16.989 -
  16.990 -reference to the newly created object
  16.991 -\vspace{0.3cm}
  16.992 -\vspace{0.3cm}
  16.993 -\vspace{0.3cm}
  16.994 -\subsubsection{RPC name:~destroy}
  16.995 -
  16.996 -{\bf Overview:} 
  16.997 -Destroy the specified crashdump instance.
  16.998 -
  16.999 - \noindent {\bf Signature:} 
 16.1000 -\begin{verbatim} void destroy (session_id s, crashdump ref self)\end{verbatim}
 16.1001 -
 16.1002 -
 16.1003 -\noindent{\bf Arguments:}
 16.1004 -
 16.1005 - 
 16.1006 -\vspace{0.3cm}
 16.1007 -\begin{tabular}{|c|c|p{7cm}|}
 16.1008 - \hline
 16.1009 -{\bf type} & {\bf name} & {\bf description} \\ \hline
 16.1010 -{\tt crashdump ref } & self & reference to the object \\ \hline 
 16.1011 -
 16.1012 -\end{tabular}
 16.1013 -
 16.1014 -\vspace{0.3cm}
 16.1015 -
 16.1016 - \noindent {\bf Return Type:} 
 16.1017 -{\tt 
 16.1018 -void
 16.1019 -}
 16.1020 -
 16.1021 -
 16.1022 -
 16.1023 -\vspace{0.3cm}
 16.1024 -\vspace{0.3cm}
 16.1025 -\vspace{0.3cm}
 16.1026  \subsubsection{RPC name:~get\_by\_uuid}
 16.1027  
 16.1028  {\bf Overview:} 
 16.1029 @@ -12148,7 +12019,7 @@ Quals & Field & Type & Description \\
 16.1030  $\mathit{RO}_\mathit{ins}$ &  {\tt backend} & VM ref & the domain where the backend is located \\
 16.1031  \hline
 16.1032  \end{longtable}
 16.1033 -\subsection{Additional RPCs associated with class: VTPM}
 16.1034 +\subsection{RPCs associated with class: VTPM}
 16.1035  \subsubsection{RPC name:~get\_uuid}
 16.1036  
 16.1037  {\bf Overview:} 
 16.1038 @@ -12393,7 +12264,7 @@ Quals & Field & Type & Description \\
 16.1039  $\mathit{RW}$ &  {\tt other\_config} & (string $\rightarrow$ string) Map & additional configuration \\
 16.1040  \hline
 16.1041  \end{longtable}
 16.1042 -\subsection{Additional RPCs associated with class: console}
 16.1043 +\subsection{RPCs associated with class: console}
 16.1044  \subsubsection{RPC name:~get\_all}
 16.1045  
 16.1046  {\bf Overview:} 
 16.1047 @@ -12828,7 +12699,7 @@ Quals & Field & Type & Description \\
 16.1048  $\mathit{RW}$ &  {\tt fullname} & string & full name \\
 16.1049  \hline
 16.1050  \end{longtable}
 16.1051 -\subsection{Additional RPCs associated with class: user}
 16.1052 +\subsection{RPCs associated with class: user}
 16.1053  \subsubsection{RPC name:~get\_uuid}
 16.1054  
 16.1055  {\bf Overview:} 
 16.1056 @@ -13093,7 +12964,7 @@ all fields from the object
 16.1057  \section{Class: debug}
 16.1058  \subsection{Fields for class: debug}
 16.1059  {\bf Class debug has no fields.}
 16.1060 -\subsection{Additional RPCs associated with class: debug}
 16.1061 +\subsection{RPCs associated with class: debug}
 16.1062  \subsubsection{RPC name:~get\_all}
 16.1063  
 16.1064  {\bf Overview:} 
 16.1065 @@ -13467,6 +13338,15 @@ expected and actual VM state at the time
 16.1066  \begin{verbatim}VM_BAD_POWER_STATE(vm, expected, actual)\end{verbatim}
 16.1067  \begin{center}\rule{10em}{0.1pt}\end{center}
 16.1068  
 16.1069 +\subsubsection{VM\_HVM\_REQUIRED}
 16.1070 +
 16.1071 +HVM is required for this operation
 16.1072 +
 16.1073 +\vspace{0.3cm}
 16.1074 +{\bf Signature:}
 16.1075 +\begin{verbatim}VM_HVM_REQUIRED(vm)\end{verbatim}
 16.1076 +\begin{center}\rule{10em}{0.1pt}\end{center}
 16.1077 +
 16.1078  
 16.1079  
 16.1080  \newpage
    17.1 --- a/docs/xen-api/xenapi.tex	Mon Mar 12 09:43:48 2007 -0600
    17.2 +++ b/docs/xen-api/xenapi.tex	Mon Mar 12 10:07:08 2007 -0600
    17.3 @@ -16,6 +16,7 @@
    17.4  \usepackage{a4wide}
    17.5  \usepackage{graphics}
    17.6  \usepackage{longtable}
    17.7 +\usepackage{fancyhdr}
    17.8  
    17.9  \setlength\topskip{0cm}
   17.10  \setlength\topmargin{0cm}
   17.11 @@ -35,7 +36,7 @@
   17.12  
   17.13  \chapter{Introduction}
   17.14  
   17.15 -This document contains a proposal for a Xen Management API---an interface for
   17.16 +This document contains a description of the Xen Management API---an interface for
   17.17  remotely configuring and controlling virtualised guests running on a
   17.18  Xen-enabled host. 
   17.19  
    18.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/cpu/mtrr/main-xen.c	Mon Mar 12 09:43:48 2007 -0600
    18.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/cpu/mtrr/main-xen.c	Mon Mar 12 10:07:08 2007 -0600
    18.3 @@ -14,11 +14,11 @@ static DEFINE_MUTEX(mtrr_mutex);
    18.4  void generic_get_mtrr(unsigned int reg, unsigned long *base,
    18.5  		      unsigned int *size, mtrr_type * type)
    18.6  {
    18.7 -	dom0_op_t op;
    18.8 +	struct xen_platform_op op;
    18.9  
   18.10 -	op.cmd = DOM0_READ_MEMTYPE;
   18.11 +	op.cmd = XENPF_read_memtype;
   18.12  	op.u.read_memtype.reg = reg;
   18.13 -	(void)HYPERVISOR_dom0_op(&op);
   18.14 +	(void)HYPERVISOR_platform_op(&op);
   18.15  
   18.16  	*size = op.u.read_memtype.nr_mfns;
   18.17  	*base = op.u.read_memtype.mfn;
   18.18 @@ -36,12 +36,12 @@ unsigned int *usage_table;
   18.19  
   18.20  static void __init set_num_var_ranges(void)
   18.21  {
   18.22 -	dom0_op_t op;
   18.23 +	struct xen_platform_op op;
   18.24  
   18.25  	for (num_var_ranges = 0; ; num_var_ranges++) {
   18.26 -		op.cmd = DOM0_READ_MEMTYPE;
   18.27 +		op.cmd = XENPF_read_memtype;
   18.28  		op.u.read_memtype.reg = num_var_ranges;
   18.29 -		if (HYPERVISOR_dom0_op(&op) != 0)
   18.30 +		if (HYPERVISOR_platform_op(&op) != 0)
   18.31  			break;
   18.32  	}
   18.33  }
   18.34 @@ -64,15 +64,15 @@ int mtrr_add_page(unsigned long base, un
   18.35  		  unsigned int type, char increment)
   18.36  {
   18.37  	int error;
   18.38 -	dom0_op_t op;
   18.39 +	struct xen_platform_op op;
   18.40  
   18.41  	mutex_lock(&mtrr_mutex);
   18.42  
   18.43 -	op.cmd = DOM0_ADD_MEMTYPE;
   18.44 +	op.cmd = XENPF_add_memtype;
   18.45  	op.u.add_memtype.mfn     = base;
   18.46  	op.u.add_memtype.nr_mfns = size;
   18.47  	op.u.add_memtype.type    = type;
   18.48 -	error = HYPERVISOR_dom0_op(&op);
   18.49 +	error = HYPERVISOR_platform_op(&op);
   18.50  	if (error) {
   18.51  		mutex_unlock(&mtrr_mutex);
   18.52  		BUG_ON(error > 0);
   18.53 @@ -117,7 +117,7 @@ int mtrr_del_page(int reg, unsigned long
   18.54  	unsigned long lbase;
   18.55  	unsigned int lsize;
   18.56  	int error = -EINVAL;
   18.57 -	dom0_op_t op;
   18.58 +	struct xen_platform_op op;
   18.59  
   18.60  	mutex_lock(&mtrr_mutex);
   18.61  
   18.62 @@ -141,10 +141,10 @@ int mtrr_del_page(int reg, unsigned long
   18.63  		goto out;
   18.64  	}
   18.65  	if (--usage_table[reg] < 1) {
   18.66 -		op.cmd = DOM0_DEL_MEMTYPE;
   18.67 +		op.cmd = XENPF_del_memtype;
   18.68  		op.u.del_memtype.handle = 0;
   18.69  		op.u.del_memtype.reg    = reg;
   18.70 -		error = HYPERVISOR_dom0_op(&op);
   18.71 +		error = HYPERVISOR_platform_op(&op);
   18.72  		if (error) {
   18.73  			BUG_ON(error > 0);
   18.74  			goto out;
    19.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c	Mon Mar 12 09:43:48 2007 -0600
    19.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c	Mon Mar 12 10:07:08 2007 -0600
    19.3 @@ -2510,10 +2510,10 @@ static int __init io_apic_bug_finalize(v
    19.4  	if(sis_apic_bug == -1)
    19.5  		sis_apic_bug = 0;
    19.6  	if (is_initial_xendomain()) {
    19.7 -		dom0_op_t op = { .cmd = DOM0_PLATFORM_QUIRK };
    19.8 +		struct xen_platform_op op = { .cmd = XENPF_platform_quirk };
    19.9  		op.u.platform_quirk.quirk_id = sis_apic_bug ?
   19.10  			QUIRK_IOAPIC_BAD_REGSEL : QUIRK_IOAPIC_GOOD_REGSEL;
   19.11 -		HYPERVISOR_dom0_op(&op);
   19.12 +		HYPERVISOR_platform_op(&op);
   19.13  	}
   19.14  	return 0;
   19.15  }
    20.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/ioport-xen.c	Mon Mar 12 09:43:48 2007 -0600
    20.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/ioport-xen.c	Mon Mar 12 10:07:08 2007 -0600
    20.3 @@ -81,7 +81,7 @@ asmlinkage long sys_ioperm(unsigned long
    20.4  		t->io_bitmap_ptr = bitmap;
    20.5  		set_thread_flag(TIF_IO_BITMAP);
    20.6  
    20.7 -		set_iobitmap.bitmap   = (char *)bitmap;
    20.8 +		set_xen_guest_handle(set_iobitmap.bitmap, (char *)bitmap);
    20.9  		set_iobitmap.nr_ports = IO_BITMAP_BITS;
   20.10  		HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap, &set_iobitmap);
   20.11  	}
    21.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c	Mon Mar 12 09:43:48 2007 -0600
    21.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c	Mon Mar 12 10:07:08 2007 -0600
    21.3 @@ -71,12 +71,12 @@ static int do_microcode_update (const vo
    21.4  		return -ENOMEM;
    21.5  
    21.6  	if (copy_from_user(kbuf, ubuf, len) == 0) {
    21.7 -		dom0_op_t op;
    21.8 +		struct xen_platform_op op;
    21.9  
   21.10 -		op.cmd = DOM0_MICROCODE;
   21.11 +		op.cmd = XENPF_microcode_update;
   21.12  		set_xen_guest_handle(op.u.microcode.data, kbuf);
   21.13  		op.u.microcode.length = len;
   21.14 -		err = HYPERVISOR_dom0_op(&op);
   21.15 +		err = HYPERVISOR_platform_op(&op);
   21.16  	} else
   21.17  		err = -EFAULT;
   21.18  
    22.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c	Mon Mar 12 09:43:48 2007 -0600
    22.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c	Mon Mar 12 10:07:08 2007 -0600
    22.3 @@ -307,7 +307,8 @@ void exit_thread(void)
    22.4  	if (unlikely(test_thread_flag(TIF_IO_BITMAP))) {
    22.5  		struct task_struct *tsk = current;
    22.6  		struct thread_struct *t = &tsk->thread;
    22.7 -		struct physdev_set_iobitmap set_iobitmap = { 0 };
    22.8 +		struct physdev_set_iobitmap set_iobitmap;
    22.9 +		memset(&set_iobitmap, 0, sizeof(set_iobitmap));
   22.10  		HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap, &set_iobitmap);
   22.11  		kfree(t->io_bitmap_ptr);
   22.12  		t->io_bitmap_ptr = NULL;
   22.13 @@ -606,7 +607,8 @@ struct task_struct fastcall * __switch_t
   22.14  	}
   22.15  
   22.16  	if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) {
   22.17 -		iobmp_op.bitmap   = (char *)next->io_bitmap_ptr;
   22.18 +		set_xen_guest_handle(iobmp_op.bitmap,
   22.19 +				     (char *)next->io_bitmap_ptr);
   22.20  		iobmp_op.nr_ports = next->io_bitmap_ptr ? IO_BITMAP_BITS : 0;
   22.21  		mcl->op      = __HYPERVISOR_physdev_op;
   22.22  		mcl->args[0] = PHYSDEVOP_set_iobitmap;
    23.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/quirks-xen.c	Mon Mar 12 09:43:48 2007 -0600
    23.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/quirks-xen.c	Mon Mar 12 10:07:08 2007 -0600
    23.3 @@ -30,11 +30,11 @@ static void __devinit quirk_intel_irqbal
    23.4  	raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word);
    23.5  
    23.6  	if (!(word & (1 << 13))) {
    23.7 -		dom0_op_t op;
    23.8 +		struct xen_platform_op op;
    23.9  		printk(KERN_INFO "Disabling irq balancing and affinity\n");
   23.10 -		op.cmd = DOM0_PLATFORM_QUIRK;
   23.11 +		op.cmd = XENPF_platform_quirk;
   23.12  		op.u.platform_quirk.quirk_id = QUIRK_NOIRQBALANCING;
   23.13 -		(void)HYPERVISOR_dom0_op(&op);
   23.14 +		(void)HYPERVISOR_platform_op(&op);
   23.15  	}
   23.16  
   23.17  	/* put back the original value for config space*/
    24.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c	Mon Mar 12 09:43:48 2007 -0600
    24.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c	Mon Mar 12 10:07:08 2007 -0600
    24.3 @@ -435,7 +435,7 @@ int do_settimeofday(struct timespec *tv)
    24.4  	s64 nsec;
    24.5  	unsigned int cpu;
    24.6  	struct shadow_time_info *shadow;
    24.7 -	dom0_op_t op;
    24.8 +	struct xen_platform_op op;
    24.9  
   24.10  	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
   24.11  		return -EINVAL;
   24.12 @@ -460,11 +460,11 @@ int do_settimeofday(struct timespec *tv)
   24.13  	__normalize_time(&sec, &nsec);
   24.14  
   24.15  	if (is_initial_xendomain() && !independent_wallclock) {
   24.16 -		op.cmd = DOM0_SETTIME;
   24.17 +		op.cmd = XENPF_settime;
   24.18  		op.u.settime.secs        = sec;
   24.19  		op.u.settime.nsecs       = nsec;
   24.20  		op.u.settime.system_time = shadow->system_timestamp;
   24.21 -		HYPERVISOR_dom0_op(&op);
   24.22 +		HYPERVISOR_platform_op(&op);
   24.23  		update_wallclock();
   24.24  	} else if (independent_wallclock) {
   24.25  		nsec -= shadow->system_timestamp;
   24.26 @@ -488,7 +488,7 @@ static void sync_xen_wallclock(unsigned 
   24.27  {
   24.28  	time_t sec;
   24.29  	s64 nsec;
   24.30 -	dom0_op_t op;
   24.31 +	struct xen_platform_op op;
   24.32  
   24.33  	if (!ntp_synced() || independent_wallclock || !is_initial_xendomain())
   24.34  		return;
   24.35 @@ -499,11 +499,11 @@ static void sync_xen_wallclock(unsigned 
   24.36  	nsec = xtime.tv_nsec + ((jiffies - wall_jiffies) * (u64)NS_PER_TICK);
   24.37  	__normalize_time(&sec, &nsec);
   24.38  
   24.39 -	op.cmd = DOM0_SETTIME;
   24.40 +	op.cmd = XENPF_settime;
   24.41  	op.u.settime.secs        = sec;
   24.42  	op.u.settime.nsecs       = nsec;
   24.43  	op.u.settime.system_time = processed_system_time;
   24.44 -	HYPERVISOR_dom0_op(&op);
   24.45 +	HYPERVISOR_platform_op(&op);
   24.46  
   24.47  	update_wallclock();
   24.48  
   24.49 @@ -907,6 +907,10 @@ static void setup_cpu0_timer_irq(void)
   24.50  	BUG_ON(per_cpu(timer_irq, 0) < 0);
   24.51  }
   24.52  
   24.53 +static struct vcpu_set_periodic_timer xen_set_periodic_tick = {
   24.54 +	.period_ns = NS_PER_TICK
   24.55 +};
   24.56 +
   24.57  void __init time_init(void)
   24.58  {
   24.59  #ifdef CONFIG_HPET_TIMER
   24.60 @@ -919,6 +923,10 @@ void __init time_init(void)
   24.61  		return;
   24.62  	}
   24.63  #endif
   24.64 +
   24.65 +	HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, 0,
   24.66 +			   &xen_set_periodic_tick);
   24.67 +
   24.68  	get_time_values_from_xen(0);
   24.69  
   24.70  	processed_system_time = per_cpu(shadow_time, 0).system_timestamp;
   24.71 @@ -976,8 +984,10 @@ EXPORT_SYMBOL(jiffies_to_st);
   24.72   */
   24.73  static void stop_hz_timer(void)
   24.74  {
   24.75 +	struct vcpu_set_singleshot_timer singleshot;
   24.76  	unsigned int cpu = smp_processor_id();
   24.77  	unsigned long j;
   24.78 +	int rc;
   24.79  
   24.80  	cpu_set(cpu, nohz_cpu_mask);
   24.81  
   24.82 @@ -997,8 +1007,16 @@ static void stop_hz_timer(void)
   24.83  		j = jiffies + 1;
   24.84  	}
   24.85  
   24.86 -	if (HYPERVISOR_set_timer_op(jiffies_to_st(j)) != 0)
   24.87 -		BUG();
   24.88 +	singleshot.timeout_abs_ns = jiffies_to_st(j);
   24.89 +	singleshot.flags = 0;
   24.90 +	rc = HYPERVISOR_vcpu_op(VCPUOP_set_singleshot_timer, cpu, &singleshot);
   24.91 +#ifdef XEN_COMPAT_030004
   24.92 +	if (rc) {
   24.93 +		BUG_ON(rc != -ENOSYS);
   24.94 +		rc = HYPERVISOR_set_timer_op(singleshot.timeout_abs_ns);
   24.95 +	}
   24.96 +#endif
   24.97 +	BUG_ON(rc);
   24.98  }
   24.99  
  24.100  static void start_hz_timer(void)
  24.101 @@ -1030,6 +1048,8 @@ void time_resume(void)
  24.102  	init_cpu_khz();
  24.103  
  24.104  	for_each_online_cpu(cpu) {
  24.105 +		HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, cpu,
  24.106 +				   &xen_set_periodic_tick);
  24.107  		get_time_values_from_xen(cpu);
  24.108  		per_cpu(processed_system_time, cpu) =
  24.109  			per_cpu(shadow_time, 0).system_timestamp;
  24.110 @@ -1050,6 +1070,9 @@ int local_setup_timer(unsigned int cpu)
  24.111  
  24.112  	BUG_ON(cpu == 0);
  24.113  
  24.114 +	HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, cpu,
  24.115 +			   &xen_set_periodic_tick);
  24.116 +
  24.117  	do {
  24.118  		seq = read_seqbegin(&xtime_lock);
  24.119  		/* Use cpu0 timestamp: cpu's shadow is not initialised yet. */
    25.1 --- a/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c	Mon Mar 12 09:43:48 2007 -0600
    25.2 +++ b/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c	Mon Mar 12 10:07:08 2007 -0600
    25.3 @@ -146,7 +146,7 @@ void xen_tlb_flush_mask(cpumask_t *mask)
    25.4  	if ( cpus_empty(*mask) )
    25.5  		return;
    25.6  	op.cmd = MMUEXT_TLB_FLUSH_MULTI;
    25.7 -	op.arg2.vcpumask = mask->bits;
    25.8 +	set_xen_guest_handle(op.arg2.vcpumask, mask->bits);
    25.9  	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
   25.10  }
   25.11  
   25.12 @@ -165,7 +165,7 @@ void xen_invlpg_mask(cpumask_t *mask, un
   25.13  		return;
   25.14  	op.cmd = MMUEXT_INVLPG_MULTI;
   25.15  	op.arg1.linear_addr = ptr & PAGE_MASK;
   25.16 -	op.arg2.vcpumask    = mask->bits;
   25.17 +	set_xen_guest_handle(op.arg2.vcpumask, mask->bits);
   25.18  	BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
   25.19  }
   25.20  
    26.1 --- a/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c	Mon Mar 12 09:43:48 2007 -0600
    26.2 +++ b/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c	Mon Mar 12 10:07:08 2007 -0600
    26.3 @@ -600,7 +600,7 @@ static void pgd_walk(pgd_t *pgd_base, pg
    26.4  	int    g, u, m, rc;
    26.5  
    26.6  	if (xen_feature(XENFEAT_auto_translated_physmap))
    26.7 -		return 0;
    26.8 +		return;
    26.9  
   26.10  	for (g = 0; g < USER_PTRS_PER_PGD; g++, pgd++) {
   26.11  		if (pgd_none(*pgd))
    27.1 --- a/linux-2.6-xen-sparse/arch/ia64/xen/xcom_hcall.c	Mon Mar 12 09:43:48 2007 -0600
    27.2 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/xcom_hcall.c	Mon Mar 12 10:07:08 2007 -0600
    27.3 @@ -21,7 +21,7 @@
    27.4  #include <linux/gfp.h>
    27.5  #include <linux/module.h>
    27.6  #include <xen/interface/xen.h>
    27.7 -#include <xen/interface/dom0_ops.h>
    27.8 +#include <xen/interface/platform.h>
    27.9  #include <xen/interface/memory.h>
   27.10  #include <xen/interface/xencomm.h>
   27.11  #include <xen/interface/version.h>
    28.1 --- a/linux-2.6-xen-sparse/arch/ia64/xen/xcom_mini.c	Mon Mar 12 09:43:48 2007 -0600
    28.2 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/xcom_mini.c	Mon Mar 12 10:07:08 2007 -0600
    28.3 @@ -20,7 +20,7 @@
    28.4  #include <linux/kernel.h>
    28.5  #include <linux/module.h>
    28.6  #include <xen/interface/xen.h>
    28.7 -#include <xen/interface/dom0_ops.h>
    28.8 +#include <xen/interface/platform.h>
    28.9  #include <xen/interface/memory.h>
   28.10  #include <xen/interface/xencomm.h>
   28.11  #include <xen/interface/version.h>
    29.1 --- a/linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c	Mon Mar 12 09:43:48 2007 -0600
    29.2 +++ b/linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c	Mon Mar 12 10:07:08 2007 -0600
    29.3 @@ -22,7 +22,7 @@
    29.4  #include <linux/gfp.h>
    29.5  #include <linux/module.h>
    29.6  #include <xen/interface/xen.h>
    29.7 -#include <xen/interface/dom0_ops.h>
    29.8 +#include <xen/interface/platform.h>
    29.9  #define __XEN__
   29.10  #include <xen/interface/domctl.h>
   29.11  #include <xen/interface/sysctl.h>
   29.12 @@ -40,25 +40,25 @@
   29.13  #define ROUND_DIV(v,s) (((v) + (s) - 1) / (s))
   29.14  
   29.15  static int
   29.16 -xencomm_privcmd_dom0_op(privcmd_hypercall_t *hypercall)
   29.17 +xencomm_privcmd_platform_op(privcmd_hypercall_t *hypercall)
   29.18  {
   29.19 -	dom0_op_t kern_op;
   29.20 -	dom0_op_t __user *user_op = (dom0_op_t __user *)hypercall->arg[0];
   29.21 +	struct xen_platform_op kern_op;
   29.22 +	struct xen_platform_op __user *user_op = (struct xen_platform_op __user *)hypercall->arg[0];
   29.23  	struct xencomm_handle *op_desc;
   29.24  	struct xencomm_handle *desc = NULL;
   29.25  	int ret = 0;
   29.26  
   29.27 -	if (copy_from_user(&kern_op, user_op, sizeof(dom0_op_t)))
   29.28 +	if (copy_from_user(&kern_op, user_op, sizeof(struct xen_platform_op)))
   29.29  		return -EFAULT;
   29.30  
   29.31 -	if (kern_op.interface_version != DOM0_INTERFACE_VERSION)
   29.32 +	if (kern_op.interface_version != XENPF_INTERFACE_VERSION)
   29.33  		return -EACCES;
   29.34  
   29.35  	op_desc = xencomm_create_inline(&kern_op);
   29.36  
   29.37  	switch (kern_op.cmd) {
   29.38  	default:
   29.39 -		printk("%s: unknown dom0 cmd %d\n", __func__, kern_op.cmd);
   29.40 +		printk("%s: unknown platform cmd %d\n", __func__, kern_op.cmd);
   29.41  		return -ENOSYS;
   29.42  	}
   29.43  
   29.44 @@ -67,10 +67,10 @@ xencomm_privcmd_dom0_op(privcmd_hypercal
   29.45  		return ret;
   29.46  	}
   29.47  
   29.48 -	ret = xencomm_arch_hypercall_dom0_op(op_desc);
   29.49 +	ret = xencomm_arch_hypercall_platform_op(op_desc);
   29.50  
   29.51  	/* FIXME: should we restore the handle?  */
   29.52 -	if (copy_to_user(user_op, &kern_op, sizeof(dom0_op_t)))
   29.53 +	if (copy_to_user(user_op, &kern_op, sizeof(struct xen_platform_op)))
   29.54  		ret = -EFAULT;
   29.55  
   29.56  	if (desc)
   29.57 @@ -638,8 +638,8 @@ int
   29.58  privcmd_hypercall(privcmd_hypercall_t *hypercall)
   29.59  {
   29.60  	switch (hypercall->op) {
   29.61 -	case __HYPERVISOR_dom0_op:
   29.62 -		return xencomm_privcmd_dom0_op(hypercall);
   29.63 +	case __HYPERVISOR_platform_op:
   29.64 +		return xencomm_privcmd_platform_op(hypercall);
   29.65  	case __HYPERVISOR_domctl:
   29.66  		return xencomm_privcmd_domctl(hypercall);
   29.67  	case __HYPERVISOR_sysctl:
    30.1 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/ioport-xen.c	Mon Mar 12 09:43:48 2007 -0600
    30.2 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/ioport-xen.c	Mon Mar 12 10:07:08 2007 -0600
    30.3 @@ -59,7 +59,7 @@ asmlinkage long sys_ioperm(unsigned long
    30.4  		memset(bitmap, 0xff, IO_BITMAP_BYTES);
    30.5  		t->io_bitmap_ptr = bitmap;
    30.6  
    30.7 -		set_iobitmap.bitmap   = (char *)bitmap;
    30.8 +		set_xen_guest_handle(set_iobitmap.bitmap, (char *)bitmap);
    30.9  		set_iobitmap.nr_ports = IO_BITMAP_BITS;
   30.10  		HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap, &set_iobitmap);
   30.11  	}
    31.1 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c	Mon Mar 12 09:43:48 2007 -0600
    31.2 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c	Mon Mar 12 10:07:08 2007 -0600
    31.3 @@ -50,7 +50,7 @@
    31.4  #include <asm/pda.h>
    31.5  #include <asm/prctl.h>
    31.6  #include <asm/kdebug.h>
    31.7 -#include <xen/interface/dom0_ops.h>
    31.8 +#include <xen/interface/platform.h>
    31.9  #include <xen/interface/physdev.h>
   31.10  #include <xen/interface/vcpu.h>
   31.11  #include <asm/desc.h>
   31.12 @@ -304,7 +304,8 @@ void exit_thread(void)
   31.13  		struct tss_struct *tss = &per_cpu(init_tss, get_cpu());
   31.14  #endif
   31.15  #ifdef CONFIG_XEN
   31.16 -		struct physdev_set_iobitmap iobmp_op = { 0 };
   31.17 +		struct physdev_set_iobitmap iobmp_op;
   31.18 +		memset(&iobmp_op, 0, sizeof(iobmp_op));
   31.19  #endif
   31.20  
   31.21  		kfree(t->io_bitmap_ptr);
   31.22 @@ -540,7 +541,8 @@ static inline void __save_init_fpu( stru
   31.23  	}
   31.24  
   31.25  	if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) {
   31.26 -		iobmp_op.bitmap   = (char *)next->io_bitmap_ptr;
   31.27 +		set_xen_guest_handle(iobmp_op.bitmap,
   31.28 +				     (char *)next->io_bitmap_ptr);
   31.29  		iobmp_op.nr_ports = next->io_bitmap_ptr ? IO_BITMAP_BITS : 0;
   31.30  		mcl->op      = __HYPERVISOR_physdev_op;
   31.31  		mcl->args[0] = PHYSDEVOP_set_iobitmap;
    32.1 --- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c	Mon Mar 12 09:43:48 2007 -0600
    32.2 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c	Mon Mar 12 10:07:08 2007 -0600
    32.3 @@ -504,7 +504,6 @@ static struct tpm_vendor_specific tpm_vt
    32.4  };
    32.5  
    32.6  struct tpm_chip *init_vtpm(struct device *dev,
    32.7 -                           struct tpm_virtual_device *tvd,
    32.8                             struct tpm_private *tp)
    32.9  {
   32.10  	long rc;
   32.11 @@ -516,7 +515,6 @@ struct tpm_chip *init_vtpm(struct device
   32.12  		return ERR_PTR(-ENOMEM);
   32.13  
   32.14  	vtpm_state_init(vtpms);
   32.15 -	vtpms->tpmvd = tvd;
   32.16  	vtpms->tpm_private = tp;
   32.17  
   32.18  	chip = tpm_register_hardware(dev, &tpm_vtpm);
    33.1 --- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.h	Mon Mar 12 09:43:48 2007 -0600
    33.2 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.h	Mon Mar 12 10:07:08 2007 -0600
    33.3 @@ -4,16 +4,6 @@
    33.4  struct tpm_chip;
    33.5  struct tpm_private;
    33.6  
    33.7 -struct tpm_virtual_device {
    33.8 -	/*
    33.9 -	 * This field indicates the maximum size the driver can
   33.10 -	 * transfer in one chunk. It is filled in by the front-end
   33.11 -	 * driver and should be propagated to the generic tpm driver
   33.12 -	 * for allocation of buffers.
   33.13 -	 */
   33.14 -	unsigned int max_tx_size;
   33.15 -};
   33.16 -
   33.17  struct vtpm_state {
   33.18  	struct transmission *current_request;
   33.19  	spinlock_t           req_list_lock;
   33.20 @@ -30,8 +20,6 @@ struct vtpm_state {
   33.21  
   33.22  	unsigned long        disconnect_time;
   33.23  
   33.24 -	struct tpm_virtual_device *tpmvd;
   33.25 -
   33.26  	/*
   33.27  	 * The following is a private structure of the underlying
   33.28  	 * driver. It is passed as parameter in the send function.
   33.29 @@ -51,7 +39,6 @@ int vtpm_vd_send(struct tpm_private * tp
   33.30  
   33.31  /* these functions are offered by tpm_vtpm.c */
   33.32  struct tpm_chip *init_vtpm(struct device *,
   33.33 -                           struct tpm_virtual_device *,
   33.34                             struct tpm_private *);
   33.35  void cleanup_vtpm(struct device *);
   33.36  int vtpm_vd_recv(const struct tpm_chip* chip,
    34.1 --- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c	Mon Mar 12 09:43:48 2007 -0600
    34.2 +++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c	Mon Mar 12 10:07:08 2007 -0600
    34.3 @@ -369,10 +369,6 @@ static void backend_changed(struct xenbu
    34.4  	}
    34.5  }
    34.6  
    34.7 -struct tpm_virtual_device tvd = {
    34.8 -	.max_tx_size = PAGE_SIZE * TPMIF_TX_RING_SIZE,
    34.9 -};
   34.10 -
   34.11  static int tpmfront_probe(struct xenbus_device *dev,
   34.12                            const struct xenbus_device_id *id)
   34.13  {
   34.14 @@ -383,7 +379,7 @@ static int tpmfront_probe(struct xenbus_
   34.15  	if (!tp)
   34.16  		return -ENOMEM;
   34.17  
   34.18 -	tp->chip = init_vtpm(&dev->dev, &tvd, tp);
   34.19 +	tp->chip = init_vtpm(&dev->dev, tp);
   34.20  	if (IS_ERR(tp->chip))
   34.21  		return PTR_ERR(tp->chip);
   34.22  
   34.23 @@ -500,11 +496,6 @@ static void __init init_tpm_xenbus(void)
   34.24  	xenbus_register_frontend(&tpmfront);
   34.25  }
   34.26  
   34.27 -static void __exit exit_tpm_xenbus(void)
   34.28 -{
   34.29 -	xenbus_unregister_driver(&tpmfront);
   34.30 -}
   34.31 -
   34.32  static int tpmif_allocate_tx_buffers(struct tpm_private *tp)
   34.33  {
   34.34  	unsigned int i;
   34.35 @@ -530,13 +521,11 @@ static void tpmif_free_tx_buffers(struct
   34.36  static void tpmif_rx_action(unsigned long priv)
   34.37  {
   34.38  	struct tpm_private *tp = (struct tpm_private *)priv;
   34.39 -
   34.40  	int i = 0;
   34.41  	unsigned int received;
   34.42  	unsigned int offset = 0;
   34.43  	u8 *buffer;
   34.44 -	tpmif_tx_request_t *tx;
   34.45 -	tx = &tp->tx->ring[i].req;
   34.46 +	tpmif_tx_request_t *tx = &tp->tx->ring[i].req;
   34.47  
   34.48  	atomic_set(&tp->tx_busy, 0);
   34.49  	wake_up_interruptible(&tp->wait_q);
   34.50 @@ -545,7 +534,7 @@ static void tpmif_rx_action(unsigned lon
   34.51  
   34.52  	buffer = kmalloc(received, GFP_ATOMIC);
   34.53  	if (!buffer)
   34.54 -		goto exit;
   34.55 +		return;
   34.56  
   34.57  	for (i = 0; i < TPMIF_TX_RING_SIZE && offset < received; i++) {
   34.58  		struct tx_buffer *txb = tp->tx_buffers[i];
   34.59 @@ -566,10 +555,6 @@ static void tpmif_rx_action(unsigned lon
   34.60  
   34.61  	vtpm_vd_recv(tp->chip, buffer, received, tp->tx_remember);
   34.62  	kfree(buffer);
   34.63 -
   34.64 -exit:
   34.65 -
   34.66 -	return;
   34.67  }
   34.68  
   34.69  
   34.70 @@ -730,13 +715,6 @@ static int __init tpmif_init(void)
   34.71  }
   34.72  
   34.73  
   34.74 -void __exit tpmif_exit(void)
   34.75 -{
   34.76 -	exit_tpm_xenbus();
   34.77 -	tpm_private_put();
   34.78 -	gnttab_free_grant_references(gref_head);
   34.79 -}
   34.80 -
   34.81  module_init(tpmif_init);
   34.82  
   34.83  MODULE_LICENSE("Dual BSD/GPL");
    35.1 --- a/linux-2.6-xen-sparse/drivers/xen/Kconfig	Mon Mar 12 09:43:48 2007 -0600
    35.2 +++ b/linux-2.6-xen-sparse/drivers/xen/Kconfig	Mon Mar 12 10:07:08 2007 -0600
    35.3 @@ -13,7 +13,7 @@ config XEN
    35.4  if XEN
    35.5  config XEN_INTERFACE_VERSION
    35.6  	hex
    35.7 -	default 0x00030203
    35.8 +	default 0x00030205
    35.9  
   35.10  menu "XEN"
   35.11  
   35.12 @@ -227,6 +227,9 @@ choice
   35.13  	config XEN_COMPAT_030002_AND_LATER
   35.14  		bool "3.0.2 and later"
   35.15  
   35.16 +	config XEN_COMPAT_030004_AND_LATER
   35.17 +		bool "3.0.4 and later"
   35.18 +
   35.19  	config XEN_COMPAT_LATEST_ONLY
   35.20  		bool "no compatibility code"
   35.21  
   35.22 @@ -236,6 +239,10 @@ config XEN_COMPAT_030002
   35.23  	bool
   35.24  	default XEN_COMPAT_030002_AND_LATER
   35.25  
   35.26 +config XEN_COMPAT_030004
   35.27 +	bool
   35.28 +	default XEN_COMPAT_030002_AND_LATER || XEN_COMPAT_030004_AND_LATER
   35.29 +
   35.30  endmenu
   35.31  
   35.32  config HAVE_IRQ_IGNORE_UNHANDLED
    36.1 --- a/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c	Mon Mar 12 09:43:48 2007 -0600
    36.2 +++ b/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c	Mon Mar 12 10:07:08 2007 -0600
    36.3 @@ -11,7 +11,6 @@
    36.4  #include <asm/mmu_context.h>
    36.5  #include <xen/evtchn.h>
    36.6  #include <asm/hypervisor.h>
    36.7 -#include <xen/interface/dom0_ops.h>
    36.8  #include <xen/xenbus.h>
    36.9  #include <linux/cpu.h>
   36.10  #include <linux/kthread.h>
    37.1 --- a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c	Mon Mar 12 09:43:48 2007 -0600
    37.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c	Mon Mar 12 10:07:08 2007 -0600
    37.3 @@ -349,17 +349,13 @@ void pciback_config_free_dev(struct pci_
    37.4  
    37.5  int pciback_config_add_field_offset(struct pci_dev *dev,
    37.6  				    struct config_field *field,
    37.7 -				    unsigned int offset)
    37.8 +				    unsigned int base_offset)
    37.9  {
   37.10  	int err = 0;
   37.11  	struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
   37.12  	struct config_field_entry *cfg_entry;
   37.13  	void *tmp;
   37.14  
   37.15 -	/* silently ignore duplicate fields */
   37.16 -	if (pciback_field_is_dup(dev, field->offset))
   37.17 -		goto out;
   37.18 -
   37.19  	cfg_entry = kmalloc(sizeof(*cfg_entry), GFP_KERNEL);
   37.20  	if (!cfg_entry) {
   37.21  		err = -ENOMEM;
   37.22 @@ -368,7 +364,12 @@ int pciback_config_add_field_offset(stru
   37.23  
   37.24  	cfg_entry->data = NULL;
   37.25  	cfg_entry->field = field;
   37.26 -	cfg_entry->base_offset = offset;
   37.27 +	cfg_entry->base_offset = base_offset;
   37.28 +
   37.29 +	/* silently ignore duplicate fields */
   37.30 +	err = pciback_field_is_dup(dev,OFFSET(cfg_entry));
   37.31 +	if (err)
   37.32 +		goto out;
   37.33  
   37.34  	if (field->init) {
   37.35  		tmp = field->init(dev, OFFSET(cfg_entry));
    38.1 --- a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.c	Mon Mar 12 09:43:48 2007 -0600
    38.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.c	Mon Mar 12 10:07:08 2007 -0600
    38.3 @@ -32,16 +32,14 @@ static inline void register_quirk(struct
    38.4  	list_add_tail(&quirk->quirks_list, &pciback_quirks);
    38.5  }
    38.6  
    38.7 -int pciback_field_is_dup(struct pci_dev *dev, int reg)
    38.8 +int pciback_field_is_dup(struct pci_dev *dev, unsigned int reg)
    38.9  {
   38.10  	int ret = 0;
   38.11  	struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
   38.12 -	struct config_field *field;
   38.13  	struct config_field_entry *cfg_entry;
   38.14  
   38.15  	list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
   38.16 -		field = cfg_entry->field;
   38.17 -		if (field->offset == reg) {
   38.18 +		if ( OFFSET(cfg_entry) == reg) {
   38.19  			ret = 1;
   38.20  			break;
   38.21  		}
    39.1 --- a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.h	Mon Mar 12 09:43:48 2007 -0600
    39.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.h	Mon Mar 12 10:07:08 2007 -0600
    39.3 @@ -30,6 +30,6 @@ void pciback_config_field_free(struct co
    39.4  
    39.5  int pciback_config_quirk_release(struct pci_dev *dev);
    39.6  
    39.7 -int pciback_field_is_dup(struct pci_dev *dev, int reg);
    39.8 +int pciback_field_is_dup(struct pci_dev *dev, unsigned int reg);
    39.9  
   39.10  #endif
    40.1 --- a/linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c	Mon Mar 12 09:43:48 2007 -0600
    40.2 +++ b/linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c	Mon Mar 12 10:07:08 2007 -0600
    40.3 @@ -589,10 +589,6 @@ static int pcistub_reg_add(int domain, i
    40.4  	}
    40.5  	dev = psdev->dev;
    40.6  
    40.7 -	/* check for duplicate field */
    40.8 -	if (pciback_field_is_dup(dev, reg))
    40.9 -		goto out;
   40.10 -
   40.11  	field = kzalloc(sizeof(*field), GFP_ATOMIC);
   40.12  	if (!field) {
   40.13  		err = -ENOMEM;
   40.14 @@ -728,10 +724,10 @@ static ssize_t pcistub_quirk_show(struct
   40.15  			if (count >= PAGE_SIZE)
   40.16  				goto out;
   40.17  
   40.18 -			count += scnprintf(buf + count, PAGE_SIZE -
   40.19 -					   count, "\t\t%08x:%01x:%08x\n",
   40.20 -					   field->offset, field->size,
   40.21 -					   field->mask);
   40.22 +			count += scnprintf(buf + count, PAGE_SIZE - count,
   40.23 +					   "\t\t%08x:%01x:%08x\n",
   40.24 +					   cfg_entry->base_offset + field->offset, 
   40.25 +					   field->size, field->mask);
   40.26  		}
   40.27  	}
   40.28  
    41.1 --- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c	Mon Mar 12 09:43:48 2007 -0600
    41.2 +++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c	Mon Mar 12 10:07:08 2007 -0600
    41.3 @@ -28,7 +28,6 @@
    41.4  #include <asm/hypervisor.h>
    41.5  #include <xen/public/privcmd.h>
    41.6  #include <xen/interface/xen.h>
    41.7 -#include <xen/interface/dom0_ops.h>
    41.8  #include <xen/xen_proc.h>
    41.9  
   41.10  static struct proc_dir_entry *privcmd_intf;
    42.1 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h	Mon Mar 12 09:43:48 2007 -0600
    42.2 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h	Mon Mar 12 10:07:08 2007 -0600
    42.3 @@ -201,11 +201,11 @@ HYPERVISOR_set_timer_op(
    42.4  }
    42.5  
    42.6  static inline int
    42.7 -HYPERVISOR_dom0_op(
    42.8 -	dom0_op_t *dom0_op)
    42.9 +HYPERVISOR_platform_op(
   42.10 +	struct xen_platform_op *platform_op)
   42.11  {
   42.12 -	dom0_op->interface_version = DOM0_INTERFACE_VERSION;
   42.13 -	return _hypercall1(int, dom0_op, dom0_op);
   42.14 +	platform_op->interface_version = XENPF_INTERFACE_VERSION;
   42.15 +	return _hypercall1(int, platform_op, platform_op);
   42.16  }
   42.17  
   42.18  static inline int
    43.1 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h	Mon Mar 12 09:43:48 2007 -0600
    43.2 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h	Mon Mar 12 10:07:08 2007 -0600
    43.3 @@ -38,7 +38,7 @@
    43.4  #include <linux/version.h>
    43.5  #include <linux/errno.h>
    43.6  #include <xen/interface/xen.h>
    43.7 -#include <xen/interface/dom0_ops.h>
    43.8 +#include <xen/interface/platform.h>
    43.9  #include <xen/interface/event_channel.h>
   43.10  #include <xen/interface/physdev.h>
   43.11  #include <xen/interface/sched.h>
    44.1 --- a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h	Mon Mar 12 09:43:48 2007 -0600
    44.2 +++ b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h	Mon Mar 12 10:07:08 2007 -0600
    44.3 @@ -120,9 +120,9 @@ HYPERVISOR_set_timer_op(u64 timeout)
    44.4  }
    44.5  
    44.6  static inline int
    44.7 -xencomm_arch_hypercall_dom0_op(struct xencomm_handle *op)
    44.8 +xencomm_arch_hypercall_platform_op(struct xencomm_handle *op)
    44.9  {
   44.10 -	return _hypercall1(int, dom0_op, op);
   44.11 +	return _hypercall1(int, platform_op, op);
   44.12  }
   44.13  
   44.14  static inline int
    45.1 --- a/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h	Mon Mar 12 09:43:48 2007 -0600
    45.2 +++ b/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h	Mon Mar 12 10:07:08 2007 -0600
    45.3 @@ -51,7 +51,7 @@ extern int running_on_xen;
    45.4  #include <linux/version.h>
    45.5  #include <linux/errno.h>
    45.6  #include <xen/interface/xen.h>
    45.7 -#include <xen/interface/dom0_ops.h>
    45.8 +#include <xen/interface/platform.h>
    45.9  #include <xen/interface/event_channel.h>
   45.10  #include <xen/interface/physdev.h>
   45.11  #include <xen/interface/sched.h>
    46.1 --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h	Mon Mar 12 09:43:48 2007 -0600
    46.2 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h	Mon Mar 12 10:07:08 2007 -0600
    46.3 @@ -204,11 +204,11 @@ HYPERVISOR_set_timer_op(
    46.4  }
    46.5  
    46.6  static inline int
    46.7 -HYPERVISOR_dom0_op(
    46.8 -	dom0_op_t *dom0_op)
    46.9 +HYPERVISOR_platform_op(
   46.10 +	struct xen_platform_op *platform_op)
   46.11  {
   46.12 -	dom0_op->interface_version = DOM0_INTERFACE_VERSION;
   46.13 -	return _hypercall1(int, dom0_op, dom0_op);
   46.14 +	platform_op->interface_version = XENPF_INTERFACE_VERSION;
   46.15 +	return _hypercall1(int, platform_op, platform_op);
   46.16  }
   46.17  
   46.18  static inline int
    47.1 --- a/patches/linux-2.6.18/softlockup-no-idle-hz.patch	Mon Mar 12 09:43:48 2007 -0600
    47.2 +++ b/patches/linux-2.6.18/softlockup-no-idle-hz.patch	Mon Mar 12 10:07:08 2007 -0600
    47.3 @@ -34,7 +34,7 @@ diff -pruN ../orig-linux-2.6.18/kernel/s
    47.4  +			!per_cpu(watchdog_task, this_cpu))
    47.5  +		return MAX_JIFFY_OFFSET;
    47.6  +
    47.7 -+	return min_t(long, 0, touch_timestamp + HZ - jiffies);
    47.8 ++	return max_t(long, 0, touch_timestamp + HZ - jiffies);
    47.9  +}
   47.10  +
   47.11   /*
    48.1 --- a/tools/ioemu/hw/ide.c	Mon Mar 12 09:43:48 2007 -0600
    48.2 +++ b/tools/ioemu/hw/ide.c	Mon Mar 12 10:07:08 2007 -0600
    48.3 @@ -396,17 +396,41 @@ typedef struct PCIIDEState {
    48.4  
    48.5  #ifdef DMA_MULTI_THREAD
    48.6  
    48.7 +static pthread_t ide_dma_thread;
    48.8  static int file_pipes[2];
    48.9  
   48.10  static void ide_dma_loop(BMDMAState *bm);
   48.11  static void dma_thread_loop(BMDMAState *bm);
   48.12  
   48.13 +extern int suspend_requested;
   48.14  static void *dma_thread_func(void* opaque)
   48.15  {
   48.16      BMDMAState* req;
   48.17 +    fd_set fds;
   48.18 +    int rv, nfds = file_pipes[0] + 1;
   48.19 +    struct timeval tm;
   48.20  
   48.21 -    while (read(file_pipes[0], &req, sizeof(req))) {
   48.22 -        dma_thread_loop(req);
   48.23 +    while (1) {
   48.24 +
   48.25 +        /* Wait at most a second for the pipe to become readable */
   48.26 +        FD_ZERO(&fds);
   48.27 +        FD_SET(file_pipes[0], &fds);
   48.28 +        tm.tv_sec = 1;
   48.29 +        tm.tv_usec = 0;
   48.30 +        rv = select(nfds, &fds, NULL, NULL, &tm);
   48.31 +        
   48.32 +        if (rv != 0) {
   48.33 +            if (read(file_pipes[0], &req, sizeof(req)) == 0)
   48.34 +                return NULL;
   48.35 +            dma_thread_loop(req);
   48.36 +        } else {
   48.37 +            if (suspend_requested)  {
   48.38 +                /* Need to tidy up the DMA thread so that we don't end up 
   48.39 +                 * finishing operations after the domain's ioreqs are 
   48.40 +                 * drained and its state saved */
   48.41 +                return NULL;
   48.42 +            }
   48.43 +        }
   48.44      }
   48.45  
   48.46      return NULL;
   48.47 @@ -414,24 +438,41 @@ static void *dma_thread_func(void* opaqu
   48.48  
   48.49  static void dma_create_thread(void)
   48.50  {
   48.51 -    pthread_t tid;
   48.52      int rt;
   48.53 +    pthread_attr_t a;
   48.54  
   48.55      if (pipe(file_pipes) != 0) {
   48.56          fprintf(stderr, "create pipe failed\n");
   48.57          exit(1);
   48.58      }
   48.59  
   48.60 -    if ((rt = pthread_create(&tid, NULL, dma_thread_func, NULL))) {
   48.61 +    if ((rt = pthread_attr_init(&a))
   48.62 +        || (rt = pthread_attr_setdetachstate(&a, PTHREAD_CREATE_JOINABLE))) {
   48.63 +        fprintf(stderr, "Oops, dma thread attr setup failed, errno=%d\n", rt);
   48.64 +        exit(1);
   48.65 +    }    
   48.66 +    
   48.67 +    if ((rt = pthread_create(&ide_dma_thread, &a, dma_thread_func, NULL))) {
   48.68          fprintf(stderr, "Oops, dma thread creation failed, errno=%d\n", rt);
   48.69          exit(1);
   48.70      }
   48.71 +}
   48.72  
   48.73 -    if ((rt = pthread_detach(tid))) {
   48.74 -        fprintf(stderr, "Oops, dma thread detachment failed, errno=%d\n", rt);
   48.75 -        exit(1);
   48.76 +void ide_stop_dma_thread(void)
   48.77 +{
   48.78 +    int rc;
   48.79 +    /* Make sure the IDE DMA thread is stopped */
   48.80 +    if ( (rc = pthread_join(ide_dma_thread, NULL)) != 0 )
   48.81 +    {
   48.82 +        fprintf(stderr, "Oops, error collecting IDE DMA thread (%s)\n", 
   48.83 +                strerror(rc));
   48.84      }
   48.85  }
   48.86 +
   48.87 +#else
   48.88 +void ide_stop_dma_thread(void)
   48.89 +{
   48.90 +}
   48.91  #endif /* DMA_MULTI_THREAD */
   48.92  
   48.93  #if defined(__ia64__)
   48.94 @@ -2602,6 +2643,120 @@ void pci_cmd646_ide_init(PCIBus *bus, Bl
   48.95  #endif /* DMA_MULTI_THREAD */
   48.96  }
   48.97  
   48.98 +static void pci_ide_save(QEMUFile* f, void *opaque)
   48.99 +{
  48.100 +    PCIIDEState *d = opaque;
  48.101 +    int i;
  48.102 +
  48.103 +    for(i = 0; i < 2; i++) {
  48.104 +        BMDMAState *bm = &d->bmdma[i];
  48.105 +        qemu_put_8s(f, &bm->cmd);
  48.106 +        qemu_put_8s(f, &bm->status);
  48.107 +        qemu_put_be32s(f, &bm->addr);
  48.108 +        /* XXX: if a transfer is pending, we do not save it yet */
  48.109 +    }
  48.110 +
  48.111 +    /* per IDE interface data */
  48.112 +    for(i = 0; i < 2; i++) {
  48.113 +        IDEState *s = &d->ide_if[i * 2];
  48.114 +        uint8_t drive1_selected;
  48.115 +        qemu_put_8s(f, &s->cmd);
  48.116 +        drive1_selected = (s->cur_drive != s);
  48.117 +        qemu_put_8s(f, &drive1_selected);
  48.118 +    }
  48.119 +
  48.120 +    /* per IDE drive data */
  48.121 +    for(i = 0; i < 4; i++) {
  48.122 +        IDEState *s = &d->ide_if[i];
  48.123 +        qemu_put_be32s(f, &s->mult_sectors);
  48.124 +        qemu_put_be32s(f, &s->identify_set);
  48.125 +        if (s->identify_set) {
  48.126 +            qemu_put_buffer(f, (const uint8_t *)s->identify_data, 512);
  48.127 +        }
  48.128 +        qemu_put_8s(f, &s->write_cache);
  48.129 +        qemu_put_8s(f, &s->feature);
  48.130 +        qemu_put_8s(f, &s->error);
  48.131 +        qemu_put_be32s(f, &s->nsector);
  48.132 +        qemu_put_8s(f, &s->sector);
  48.133 +        qemu_put_8s(f, &s->lcyl);
  48.134 +        qemu_put_8s(f, &s->hcyl);
  48.135 +        qemu_put_8s(f, &s->hob_feature);
  48.136 +        qemu_put_8s(f, &s->hob_nsector);
  48.137 +        qemu_put_8s(f, &s->hob_sector);
  48.138 +        qemu_put_8s(f, &s->hob_lcyl);
  48.139 +        qemu_put_8s(f, &s->hob_hcyl);
  48.140 +        qemu_put_8s(f, &s->select);
  48.141 +        qemu_put_8s(f, &s->status);
  48.142 +        qemu_put_8s(f, &s->lba48);
  48.143 +
  48.144 +        qemu_put_8s(f, &s->sense_key);
  48.145 +        qemu_put_8s(f, &s->asc);
  48.146 +        /* XXX: if a transfer is pending, we do not save it yet */
  48.147 +    }
  48.148 +}
  48.149 +
  48.150 +static int pci_ide_load(QEMUFile* f, void *opaque, int version_id)
  48.151 +{
  48.152 +    PCIIDEState *d = opaque;
  48.153 +    int ret, i;
  48.154 +
  48.155 +    if (version_id != 1)
  48.156 +        return -EINVAL;
  48.157 +
  48.158 +    for(i = 0; i < 2; i++) {
  48.159 +        BMDMAState *bm = &d->bmdma[i];
  48.160 +        qemu_get_8s(f, &bm->cmd);
  48.161 +        qemu_get_8s(f, &bm->status);
  48.162 +        qemu_get_be32s(f, &bm->addr);
  48.163 +        /* XXX: if a transfer is pending, we do not save it yet */
  48.164 +    }
  48.165 +
  48.166 +    /* per IDE interface data */
  48.167 +    for(i = 0; i < 2; i++) {
  48.168 +        IDEState *s = &d->ide_if[i * 2];
  48.169 +        uint8_t drive1_selected;
  48.170 +        qemu_get_8s(f, &s->cmd);
  48.171 +        qemu_get_8s(f, &drive1_selected);
  48.172 +        s->cur_drive = &d->ide_if[i * 2 + (drive1_selected != 0)];
  48.173 +    }
  48.174 +
  48.175 +    /* per IDE drive data */
  48.176 +    for(i = 0; i < 4; i++) {
  48.177 +        IDEState *s = &d->ide_if[i];
  48.178 +        qemu_get_be32s(f, &s->mult_sectors);
  48.179 +        qemu_get_be32s(f, &s->identify_set);
  48.180 +        if (s->identify_set) {
  48.181 +            qemu_get_buffer(f, (uint8_t *)s->identify_data, 512);
  48.182 +        }
  48.183 +        qemu_get_8s(f, &s->write_cache);
  48.184 +        qemu_get_8s(f, &s->feature);
  48.185 +        qemu_get_8s(f, &s->error);
  48.186 +        qemu_get_be32s(f, &s->nsector);
  48.187 +        qemu_get_8s(f, &s->sector);
  48.188 +        qemu_get_8s(f, &s->lcyl);
  48.189 +        qemu_get_8s(f, &s->hcyl);
  48.190 +        qemu_get_8s(f, &s->hob_feature);
  48.191 +        qemu_get_8s(f, &s->hob_nsector);
  48.192 +        qemu_get_8s(f, &s->hob_sector);
  48.193 +        qemu_get_8s(f, &s->hob_lcyl);
  48.194 +        qemu_get_8s(f, &s->hob_hcyl);
  48.195 +        qemu_get_8s(f, &s->select);
  48.196 +        qemu_get_8s(f, &s->status);
  48.197 +        qemu_get_8s(f, &s->lba48);
  48.198 +
  48.199 +        qemu_get_8s(f, &s->sense_key);
  48.200 +        qemu_get_8s(f, &s->asc);
  48.201 +        /* XXX: if a transfer is pending, we do not save it yet */
  48.202 +        if (s->status & (DRQ_STAT|BUSY_STAT)) {
  48.203 +            /* Tell the guest that its transfer has gone away */
  48.204 +            ide_abort_command(s);
  48.205 +            ide_set_irq(s);
  48.206 +        }
  48.207 +    }
  48.208 +    return 0;
  48.209 +}
  48.210 +
  48.211 +
  48.212  /* hd_table must contain 4 block drivers */
  48.213  /* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */
  48.214  void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn)
  48.215 @@ -2643,6 +2798,7 @@ void pci_piix3_ide_init(PCIBus *bus, Blo
  48.216      buffered_pio_init();
  48.217  
  48.218      register_savevm("ide_pci", 0, 1, generic_pci_save, generic_pci_load, d);
  48.219 +    register_savevm("ide", 0, 1, pci_ide_save, pci_ide_load, d);
  48.220  
  48.221  #ifdef DMA_MULTI_THREAD    
  48.222      dma_create_thread();
    49.1 --- a/tools/ioemu/target-i386-dm/helper2.c	Mon Mar 12 09:43:48 2007 -0600
    49.2 +++ b/tools/ioemu/target-i386-dm/helper2.c	Mon Mar 12 10:07:08 2007 -0600
    49.3 @@ -577,7 +577,28 @@ int main_loop(void)
    49.4          destroy_hvm_domain();
    49.5      else {
    49.6          char qemu_file[20];
    49.7 +        ioreq_t *req;
    49.8 +        int rc;
    49.9 +
   49.10          sprintf(qemu_file, "/tmp/xen.qemu-dm.%d", domid);
   49.11 +        xc_domain_pause(xc_handle, domid);
   49.12 +
   49.13 +        /* Pull all outstanding ioreqs through the system */
   49.14 +        handle_buffered_io(env);
   49.15 +        main_loop_wait(1); /* For the select() on events */
   49.16 +        
   49.17 +        /* Stop the IDE thread */
   49.18 +        ide_stop_dma_thread();
   49.19 +
   49.20 +        /* Make sure that all outstanding IO responses are handled too */ 
   49.21 +        if ( xc_hvm_drain_io(xc_handle, domid) != 0 )
   49.22 +        {
   49.23 +            fprintf(stderr, "error clearing ioreq rings (%s)\n", 
   49.24 +                    strerror(errno));
   49.25 +            return -1;
   49.26 +        }
   49.27 +
   49.28 +        /* Save the device state */
   49.29          if (qemu_savevm(qemu_file) < 0)
   49.30              fprintf(stderr, "qemu save fail.\n");
   49.31      }
    50.1 --- a/tools/ioemu/vl.h	Mon Mar 12 09:43:48 2007 -0600
    50.2 +++ b/tools/ioemu/vl.h	Mon Mar 12 10:07:08 2007 -0600
    50.3 @@ -843,6 +843,7 @@ void pci_cmd646_ide_init(PCIBus *bus, Bl
    50.4  void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn);
    50.5  int pmac_ide_init (BlockDriverState **hd_table,
    50.6                     SetIRQFunc *set_irq, void *irq_opaque, int irq);
    50.7 +void ide_stop_dma_thread(void);
    50.8  
    50.9  /* cdrom.c */
   50.10  int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track);
    51.1 --- a/tools/libxc/xc_core_ia64.c	Mon Mar 12 09:43:48 2007 -0600
    51.2 +++ b/tools/libxc/xc_core_ia64.c	Mon Mar 12 10:07:08 2007 -0600
    51.3 @@ -22,6 +22,28 @@
    51.4  #include "xc_core.h"
    51.5  #include "xc_efi.h"
    51.6  #include "xc_dom.h"
    51.7 +#include <inttypes.h>
    51.8 +
    51.9 +static int
   51.10 +xc_memory_map_cmp(const void *lhs__, const void *rhs__)
   51.11 +{
   51.12 +    const struct xc_core_memory_map *lhs =
   51.13 +        (const struct xc_core_memory_map *)lhs__;
   51.14 +    const struct xc_core_memory_map *rhs =
   51.15 +        (const struct xc_core_memory_map *)rhs__;
   51.16 +
   51.17 +    if (lhs->addr < rhs->addr)
   51.18 +        return -1;
   51.19 +    if (lhs->addr > rhs->addr)
   51.20 +        return 1;
   51.21 +
   51.22 +    /* memory map overlap isn't allowed. complain */
   51.23 +    DPRINTF("duplicated addresses are detected "
   51.24 +            "(0x%" PRIx64 ", 0x%" PRIx64 "), "
   51.25 +            "(0x%" PRIx64 ", 0x%" PRIx64 ")\n",
   51.26 +            lhs->addr, lhs->size, rhs->addr, rhs->size);
   51.27 +    return 0;
   51.28 +}
   51.29  
   51.30  int
   51.31  xc_core_arch_auto_translated_physmap(const xc_dominfo_t *info)
   51.32 @@ -111,6 +133,7 @@ memory_map_get_old_hvm(int xc_handle, xc
   51.33      }
   51.34      *mapp = map;
   51.35      *nr_entries = i;
   51.36 +    qsort(map, *nr_entries, sizeof(map[0]), &xc_memory_map_cmp);
   51.37      return 0;
   51.38  
   51.39  out:
   51.40 @@ -196,6 +219,7 @@ xc_core_arch_memory_map_get(int xc_handl
   51.41      ret = 0;
   51.42  out:
   51.43      munmap(memmap_info, PAGE_SIZE);
   51.44 +    qsort(map, *nr_entries, sizeof(map[0]), &xc_memory_map_cmp);
   51.45      return ret;
   51.46      
   51.47  old:
    52.1 --- a/tools/libxc/xc_dom_x86.c	Mon Mar 12 09:43:48 2007 -0600
    52.2 +++ b/tools/libxc/xc_dom_x86.c	Mon Mar 12 10:07:08 2007 -0600
    52.3 @@ -433,24 +433,12 @@ static int vcpu_x86_32(struct xc_dom_ima
    52.4  {
    52.5      vcpu_guest_context_x86_32_t *ctxt = ptr;
    52.6      xen_pfn_t cr3_pfn;
    52.7 -    int i;
    52.8  
    52.9      xc_dom_printf("%s: called\n", __FUNCTION__);
   52.10  
   52.11      /* clear everything */
   52.12      memset(ctxt, 0, sizeof(*ctxt));
   52.13  
   52.14 -    /* Virtual IDT is empty at start-of-day. */
   52.15 -    for ( i = 0; i < 256; i++ )
   52.16 -    {
   52.17 -        ctxt->trap_ctxt[i].vector = i;
   52.18 -        ctxt->trap_ctxt[i].cs = FLAT_KERNEL_CS_X86_32;
   52.19 -    }
   52.20 -
   52.21 -    /* No callback handlers. */
   52.22 -    ctxt->event_callback_cs = FLAT_KERNEL_CS_X86_32;
   52.23 -    ctxt->failsafe_callback_cs = FLAT_KERNEL_CS_X86_32;
   52.24 -
   52.25      ctxt->user_regs.ds = FLAT_KERNEL_DS_X86_32;
   52.26      ctxt->user_regs.es = FLAT_KERNEL_DS_X86_32;
   52.27      ctxt->user_regs.fs = FLAT_KERNEL_DS_X86_32;
   52.28 @@ -464,9 +452,8 @@ static int vcpu_x86_32(struct xc_dom_ima
   52.29          dom->parms.virt_base + (dom->start_info_pfn) * PAGE_SIZE_X86;
   52.30      ctxt->user_regs.eflags = 1 << 9; /* Interrupt Enable */
   52.31  
   52.32 -    ctxt->kernel_ss = FLAT_KERNEL_SS_X86_32;
   52.33 -    ctxt->kernel_sp =
   52.34 -        dom->parms.virt_base + (dom->bootstack_pfn + 1) * PAGE_SIZE_X86;
   52.35 +    ctxt->kernel_ss = ctxt->user_regs.ss;
   52.36 +    ctxt->kernel_sp = ctxt->user_regs.esp;
   52.37  
   52.38      ctxt->flags = VGCF_in_kernel_X86_32;
   52.39      if ( dom->parms.pae == 2 /* extended_cr3 */ ||
   52.40 @@ -485,20 +472,12 @@ static int vcpu_x86_64(struct xc_dom_ima
   52.41  {
   52.42      vcpu_guest_context_x86_64_t *ctxt = ptr;
   52.43      xen_pfn_t cr3_pfn;
   52.44 -    int i;
   52.45  
   52.46      xc_dom_printf("%s: called\n", __FUNCTION__);
   52.47  
   52.48      /* clear everything */
   52.49      memset(ctxt, 0, sizeof(*ctxt));
   52.50  
   52.51 -    /* Virtual IDT is empty at start-of-day. */
   52.52 -    for ( i = 0; i < 256; i++ )
   52.53 -    {
   52.54 -        ctxt->trap_ctxt[i].vector = i;
   52.55 -        ctxt->trap_ctxt[i].cs = FLAT_KERNEL_CS_X86_64;
   52.56 -    }
   52.57 -
   52.58      ctxt->user_regs.ds = FLAT_KERNEL_DS_X86_64;
   52.59      ctxt->user_regs.es = FLAT_KERNEL_DS_X86_64;
   52.60      ctxt->user_regs.fs = FLAT_KERNEL_DS_X86_64;
   52.61 @@ -512,9 +491,8 @@ static int vcpu_x86_64(struct xc_dom_ima
   52.62          dom->parms.virt_base + (dom->start_info_pfn) * PAGE_SIZE_X86;
   52.63      ctxt->user_regs.rflags = 1 << 9; /* Interrupt Enable */
   52.64  
   52.65 -    ctxt->kernel_ss = FLAT_KERNEL_SS_X86_64;
   52.66 -    ctxt->kernel_sp =
   52.67 -        dom->parms.virt_base + (dom->bootstack_pfn + 1) * PAGE_SIZE_X86;
   52.68 +    ctxt->kernel_ss = ctxt->user_regs.ss;
   52.69 +    ctxt->kernel_sp = ctxt->user_regs.esp;
   52.70  
   52.71      ctxt->flags = VGCF_in_kernel_X86_64;
   52.72      cr3_pfn = xc_dom_p2m_guest(dom, dom->pgtables_seg.pfn);
    53.1 --- a/tools/libxc/xc_hvm_restore.c	Mon Mar 12 09:43:48 2007 -0600
    53.2 +++ b/tools/libxc/xc_hvm_restore.c	Mon Mar 12 10:07:08 2007 -0600
    53.3 @@ -101,6 +101,9 @@ int xc_hvm_restore(int xc_handle, int io
    53.4      /* Number of pages of memory the guest has.  *Not* the same as max_pfn. */
    53.5      unsigned long nr_pages;
    53.6  
    53.7 +    /* The size of an array big enough to contain all guest pfns */
    53.8 +    unsigned long pfn_array_size = max_pfn + 1;
    53.9 +
   53.10      /* hvm guest mem size (Mb) */
   53.11      memsize = (unsigned long long)*store_mfn;
   53.12      v_end = memsize << 20;
   53.13 @@ -127,7 +130,7 @@ int xc_hvm_restore(int xc_handle, int io
   53.14      }
   53.15  
   53.16  
   53.17 -    pfns = malloc(max_pfn * sizeof(xen_pfn_t));
   53.18 +    pfns = malloc(pfn_array_size * sizeof(xen_pfn_t));
   53.19      if (pfns == NULL) {
   53.20          ERROR("memory alloc failed");
   53.21          errno = ENOMEM;
   53.22 @@ -139,11 +142,11 @@ int xc_hvm_restore(int xc_handle, int io
   53.23          goto out;
   53.24      }
   53.25  
   53.26 -    for ( i = 0; i < max_pfn; i++ )
   53.27 +    for ( i = 0; i < pfn_array_size; i++ )
   53.28          pfns[i] = i;
   53.29 -    for ( i = HVM_BELOW_4G_RAM_END >> PAGE_SHIFT; i < max_pfn; i++ )
   53.30 +    for ( i = HVM_BELOW_4G_RAM_END >> PAGE_SHIFT; i < pfn_array_size; i++ )
   53.31          pfns[i] += HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT;
   53.32 -    arch_max_pfn = pfns[max_pfn - 1];/* used later */
   53.33 +    arch_max_pfn = pfns[max_pfn];/* used later */
   53.34  
   53.35      /* Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000. */
   53.36      rc = xc_domain_memory_populate_physmap(
   53.37 @@ -281,6 +284,14 @@ int xc_hvm_restore(int xc_handle, int io
   53.38      else
   53.39          shared_page_nr = (v_end >> PAGE_SHIFT) - 1;
   53.40  
   53.41 +    /* Paranoia: clean pages. */
   53.42 +    if ( xc_clear_domain_page(xc_handle, dom, shared_page_nr) ||
   53.43 +         xc_clear_domain_page(xc_handle, dom, shared_page_nr-1) ||
   53.44 +         xc_clear_domain_page(xc_handle, dom, shared_page_nr-2) ) {
   53.45 +        ERROR("error clearing comms frames!\n");
   53.46 +        goto out;
   53.47 +    }
   53.48 +
   53.49      xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, shared_page_nr-1);
   53.50      xc_set_hvm_param(xc_handle, dom, HVM_PARAM_BUFIOREQ_PFN, shared_page_nr-2);
   53.51      xc_set_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN, shared_page_nr);
   53.52 @@ -289,29 +300,6 @@ int xc_hvm_restore(int xc_handle, int io
   53.53      *store_mfn = (v_end >> PAGE_SHIFT) - 2;
   53.54      DPRINTF("hvm restore:calculate new store_mfn=0x%lx,v_end=0x%llx..\n", *store_mfn, v_end);
   53.55  
   53.56 -    /* restore hvm context including pic/pit/shpage */
   53.57 -    if (!read_exact(io_fd, &rec_len, sizeof(uint32_t))) {
   53.58 -        ERROR("error read hvm context size!\n");
   53.59 -        goto out;
   53.60 -    }
   53.61 -
   53.62 -    hvm_buf = malloc(rec_len);
   53.63 -    if (hvm_buf == NULL) {
   53.64 -        ERROR("memory alloc for hvm context buffer failed");
   53.65 -        errno = ENOMEM;
   53.66 -        goto out;
   53.67 -    }
   53.68 -
   53.69 -    if (!read_exact(io_fd, hvm_buf, rec_len)) {
   53.70 -        ERROR("error read hvm buffer!\n");
   53.71 -        goto out;
   53.72 -    }
   53.73 -
   53.74 -    if (( rc = xc_domain_hvm_setcontext(xc_handle, dom, hvm_buf, rec_len))) {
   53.75 -        ERROR("error set hvm buffer!\n");
   53.76 -        goto out;
   53.77 -    }
   53.78 -
   53.79      if (!read_exact(io_fd, &nr_vcpus, sizeof(uint32_t))) {
   53.80          ERROR("error read nr vcpu !\n");
   53.81          goto out;
   53.82 @@ -339,6 +327,29 @@ int xc_hvm_restore(int xc_handle, int io
   53.83          }
   53.84      }
   53.85  
   53.86 +    /* restore hvm context including pic/pit/shpage */
   53.87 +    if (!read_exact(io_fd, &rec_len, sizeof(uint32_t))) {
   53.88 +        ERROR("error read hvm context size!\n");
   53.89 +        goto out;
   53.90 +    }
   53.91 +
   53.92 +    hvm_buf = malloc(rec_len);
   53.93 +    if (hvm_buf == NULL) {
   53.94 +        ERROR("memory alloc for hvm context buffer failed");
   53.95 +        errno = ENOMEM;
   53.96 +        goto out;
   53.97 +    }
   53.98 +
   53.99 +    if (!read_exact(io_fd, hvm_buf, rec_len)) {
  53.100 +        ERROR("error read hvm buffer!\n");
  53.101 +        goto out;
  53.102 +    }
  53.103 +
  53.104 +    if (( rc = xc_domain_hvm_setcontext(xc_handle, dom, hvm_buf, rec_len))) {
  53.105 +        ERROR("error set hvm buffer!\n");
  53.106 +        goto out;
  53.107 +    }
  53.108 +
  53.109      /* Shared-info pfn */
  53.110      if (!read_exact(io_fd, &(shared_info_frame), sizeof(uint32_t)) ) {
  53.111          ERROR("reading the shared-info pfn failed!\n");
    54.1 --- a/tools/libxc/xc_hvm_save.c	Mon Mar 12 09:43:48 2007 -0600
    54.2 +++ b/tools/libxc/xc_hvm_save.c	Mon Mar 12 10:07:08 2007 -0600
    54.3 @@ -27,12 +27,14 @@
    54.4  #include <stdlib.h>
    54.5  #include <unistd.h>
    54.6  #include <sys/time.h>
    54.7 -#include <xen/hvm/e820.h>
    54.8  
    54.9  #include "xc_private.h"
   54.10  #include "xg_private.h"
   54.11  #include "xg_save_restore.h"
   54.12  
   54.13 +#include <xen/hvm/e820.h>
   54.14 +#include <xen/hvm/params.h>
   54.15 +
   54.16  /*
   54.17  ** Default values for important tuning parameters. Can override by passing
   54.18  ** non-zero replacement values to xc_hvm_save().
   54.19 @@ -49,11 +51,25 @@ static unsigned long max_mfn;
   54.20  /* virtual starting address of the hypervisor */
   54.21  static unsigned long hvirt_start;
   54.22  
   54.23 -/* #levels of page tables used by the currrent guest */
   54.24 +/* #levels of page tables used by the current guest */
   54.25  static unsigned int pt_levels;
   54.26  
   54.27 -/* total number of pages used by the current guest */
   54.28 -static unsigned long max_pfn;
   54.29 +int xc_hvm_drain_io(int handle, domid_t dom)
   54.30 +{
   54.31 +    DECLARE_HYPERCALL;
   54.32 +    xen_hvm_drain_io_t arg;
   54.33 +    int rc;
   54.34 +
   54.35 +    hypercall.op     = __HYPERVISOR_hvm_op;
   54.36 +    hypercall.arg[0] = HVMOP_drain_io;
   54.37 +    hypercall.arg[1] = (unsigned long)&arg;
   54.38 +    arg.domid = dom;
   54.39 +    if ( lock_pages(&arg, sizeof(arg)) != 0 )
   54.40 +        return -1;
   54.41 +    rc = do_xen_hypercall(handle, &hypercall);
   54.42 +    unlock_pages(&arg, sizeof(arg));
   54.43 +    return rc;
   54.44 +}
   54.45  
   54.46  /*
   54.47  ** During (live) save/migrate, we maintain a number of bitmaps to track
   54.48 @@ -61,7 +77,7 @@ static unsigned long max_pfn;
   54.49  */
   54.50  
   54.51  #define BITS_PER_LONG (sizeof(unsigned long) * 8)
   54.52 -#define BITMAP_SIZE   ((max_pfn + BITS_PER_LONG - 1) / 8)
   54.53 +#define BITMAP_SIZE   ((pfn_array_size + BITS_PER_LONG - 1) / 8)
   54.54  
   54.55  #define BITMAP_ENTRY(_nr,_bmap) \
   54.56     ((unsigned long *)(_bmap))[(_nr)/BITS_PER_LONG]
   54.57 @@ -183,7 +199,7 @@ static int print_stats(int xc_handle, ui
   54.58      return 0;
   54.59  }
   54.60  
   54.61 -static int analysis_phase(int xc_handle, uint32_t domid, int max_pfn,
   54.62 +static int analysis_phase(int xc_handle, uint32_t domid, int pfn_array_size,
   54.63                            unsigned long *arr, int runs)
   54.64  {
   54.65      long long start, now;
   54.66 @@ -196,7 +212,7 @@ static int analysis_phase(int xc_handle,
   54.67          int i;
   54.68  
   54.69          xc_shadow_control(xc_handle, domid, XEN_DOMCTL_SHADOW_OP_CLEAN,
   54.70 -                          arr, max_pfn, NULL, 0, NULL);
   54.71 +                          arr, pfn_array_size, NULL, 0, NULL);
   54.72          DPRINTF("#Flush\n");
   54.73          for ( i = 0; i < 40; i++ ) {
   54.74              usleep(50000);
   54.75 @@ -236,7 +252,7 @@ static int suspend_and_state(int (*suspe
   54.76  
   54.77  
   54.78      if (info->shutdown && info->shutdown_reason == SHUTDOWN_suspend)
   54.79 -        return 0; // success
   54.80 +        return 0; // success        
   54.81  
   54.82      if (info->paused) {
   54.83          // try unpausing domain, wait, and retest
   54.84 @@ -268,11 +284,21 @@ int xc_hvm_save(int xc_handle, int io_fd
   54.85      int rc = 1, i, j, last_iter, iter = 0;
   54.86      int live  = (flags & XCFLAGS_LIVE);
   54.87      int debug = (flags & XCFLAGS_DEBUG);
   54.88 +    int stdvga = (flags & XCFLAGS_STDVGA);
   54.89      int sent_last_iter, skip_this_iter;
   54.90  
   54.91 +    /* The highest guest-physical frame number used by the current guest */
   54.92 +    unsigned long max_pfn;
   54.93 +
   54.94 +    /* The size of an array big enough to contain all guest pfns */
   54.95 +    unsigned long pfn_array_size;
   54.96 +
   54.97      /* The new domain's shared-info frame number. */
   54.98      unsigned long shared_info_frame;
   54.99  
  54.100 +    /* Other magic frames: ioreqs and xenstore comms */
  54.101 +    unsigned long ioreq_pfn, bufioreq_pfn, store_pfn;
  54.102 +
  54.103      /* A copy of the CPU context of the guest. */
  54.104      vcpu_guest_context_t ctxt;
  54.105  
  54.106 @@ -291,7 +317,7 @@ int xc_hvm_save(int xc_handle, int io_fd
  54.107  
  54.108      uint32_t rec_size, nr_vcpus;
  54.109  
  54.110 -    /* power of 2 order of max_pfn */
  54.111 +    /* power of 2 order of pfn_array_size */
  54.112      int order_nr;
  54.113  
  54.114      /* bitmap of pages:
  54.115 @@ -353,6 +379,15 @@ int xc_hvm_save(int xc_handle, int io_fd
  54.116          goto out;
  54.117      }
  54.118  
  54.119 +    if ( xc_get_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, &store_pfn)
  54.120 +         || xc_get_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN, &ioreq_pfn)
  54.121 +         || xc_get_hvm_param(xc_handle, dom, 
  54.122 +                             HVM_PARAM_BUFIOREQ_PFN, &bufioreq_pfn) )
  54.123 +    {
  54.124 +        ERROR("HVM: Could not read magic PFN parameters");
  54.125 +        goto out;
  54.126 +    }
  54.127 +
  54.128      DPRINTF("saved hvm domain info:max_memkb=0x%lx, max_mfn=0x%lx, "
  54.129              "nr_pages=0x%lx\n", info.max_memkb, max_mfn, info.nr_pages); 
  54.130  
  54.131 @@ -368,6 +403,7 @@ int xc_hvm_save(int xc_handle, int io_fd
  54.132          }
  54.133  
  54.134          last_iter = 0;
  54.135 +
  54.136          DPRINTF("hvm domain live migration debug start: logdirty enable.\n");
  54.137      } else {
  54.138          /* This is a non-live suspend. Issue the call back to get the
  54.139 @@ -388,20 +424,28 @@ int xc_hvm_save(int xc_handle, int io_fd
  54.140  
  54.141      /* Calculate the highest PFN of "normal" memory:
  54.142       * HVM memory is sequential except for the VGA and MMIO holes. */
  54.143 -    max_pfn = info.nr_pages;
  54.144 +    max_pfn = info.nr_pages - 1;
  54.145 +    /* If the domain has a Cirrus framebuffer and we haven't already 
  54.146 +     * suspended qemu-dm, it will have 8MB of framebuffer memory 
  54.147 +     * still allocated, which we don't want to copy: qemu will save it 
  54.148 +     * for us later */
  54.149 +    if ( live && !stdvga )
  54.150 +        max_pfn -= 0x800;
  54.151      /* Skip the VGA hole from 0xa0000 to 0xc0000 */
  54.152 -    max_pfn += 0x20;   
  54.153 +    max_pfn += 0x20;
  54.154      /* Skip the MMIO hole: 256MB just below 4GB */
  54.155      if ( max_pfn >= (HVM_BELOW_4G_MMIO_START >> PAGE_SHIFT) )
  54.156          max_pfn += (HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT); 
  54.157  
  54.158 -    skip_this_iter = 0;/*XXX*/
  54.159 -    /* pretend we sent all the pages last iteration */
  54.160 -    sent_last_iter = max_pfn;
  54.161 +    /* Size of any array that covers 0 ... max_pfn */
  54.162 +    pfn_array_size = max_pfn + 1;
  54.163  
  54.164 -    /* calculate the power of 2 order of max_pfn, e.g.
  54.165 +    /* pretend we sent all the pages last iteration */
  54.166 +    sent_last_iter = pfn_array_size;
  54.167 +
  54.168 +    /* calculate the power of 2 order of pfn_array_size, e.g.
  54.169         15->4 16->4 17->5 */
  54.170 -    for (i = max_pfn-1, order_nr = 0; i ; i >>= 1, order_nr++)
  54.171 +    for (i = pfn_array_size-1, order_nr = 0; i ; i >>= 1, order_nr++)
  54.172          continue;
  54.173  
  54.174      /* Setup to_send / to_fix and to_skip bitmaps */
  54.175 @@ -435,7 +479,7 @@ int xc_hvm_save(int xc_handle, int io_fd
  54.176          return 1;
  54.177      }
  54.178  
  54.179 -    analysis_phase(xc_handle, dom, max_pfn, to_skip, 0);
  54.180 +    analysis_phase(xc_handle, dom, pfn_array_size, to_skip, 0);
  54.181  
  54.182  
  54.183      /* We want zeroed memory so use calloc rather than malloc. */
  54.184 @@ -465,9 +509,17 @@ int xc_hvm_save(int xc_handle, int io_fd
  54.185  
  54.186          DPRINTF("Saving HVM domain memory pages: iter %d   0%%", iter);
  54.187  
  54.188 -        while( N < max_pfn ){
  54.189 +        if (last_iter && (max_pfn != live_shinfo->arch.max_pfn)) {
  54.190 +            DPRINTF("calculated max_pfn as %#lx, shinfo says %#lx\n",
  54.191 +                    max_pfn, live_shinfo->arch.max_pfn);
  54.192 +            ERROR("Max pfn doesn't match shared info");
  54.193 +            goto out;
  54.194 +        }
  54.195  
  54.196 -            unsigned int this_pc = (N * 100) / max_pfn;
  54.197 +        while( N < pfn_array_size ){
  54.198 +
  54.199 +            unsigned int this_pc = (N * 100) / pfn_array_size;
  54.200 +            int rc;
  54.201  
  54.202              if ((this_pc - prev_pc) >= 5) {
  54.203                  DPRINTF("\b\b\b\b%3d%%", this_pc);
  54.204 @@ -476,9 +528,9 @@ int xc_hvm_save(int xc_handle, int io_fd
  54.205  
  54.206              /* slightly wasteful to peek the whole array evey time,
  54.207                 but this is fast enough for the moment. */
  54.208 -            if (!last_iter && xc_shadow_control(
  54.209 -                    xc_handle, dom, XEN_DOMCTL_SHADOW_OP_PEEK,
  54.210 -                    to_skip, max_pfn, NULL, 0, NULL) != max_pfn) {
  54.211 +            if (!last_iter && (rc = xc_shadow_control(
  54.212 +                    xc_handle, dom, XEN_DOMCTL_SHADOW_OP_PEEK, to_skip, 
  54.213 +                    pfn_array_size, NULL, 0, NULL)) != pfn_array_size) {
  54.214                  ERROR("Error peeking HVM shadow bitmap");
  54.215                  goto out;
  54.216              }
  54.217 @@ -486,11 +538,11 @@ int xc_hvm_save(int xc_handle, int io_fd
  54.218  
  54.219              /* load pfn_batch[] with the mfn of all the pages we're doing in
  54.220                 this batch. */
  54.221 -            for (batch = 0; batch < MAX_BATCH_SIZE && N < max_pfn ; N++) {
  54.222 +            for (batch = 0; batch < MAX_BATCH_SIZE && N < pfn_array_size; N++){
  54.223  
  54.224 -                int n = permute(N, max_pfn, order_nr);
  54.225 +                int n = permute(N, pfn_array_size, order_nr);
  54.226  
  54.227 -                if (debug) {
  54.228 +                if (0&&debug) {
  54.229                      DPRINTF("%d pfn= %08lx %d \n",
  54.230                              iter, (unsigned long)n, test_bit(n, to_send));
  54.231                  }
  54.232 @@ -505,7 +557,10 @@ int xc_hvm_save(int xc_handle, int io_fd
  54.233                  /* Skip PFNs that aren't really there */
  54.234                  if ((n >= 0xa0 && n < 0xc0) /* VGA hole */
  54.235                      || (n >= (HVM_BELOW_4G_MMIO_START >> PAGE_SHIFT)
  54.236 -                        && n < (1ULL << 32) >> PAGE_SHIFT)) /* 4G MMIO hole */
  54.237 +                        && n < (1ULL << 32) >> PAGE_SHIFT) /* 4G MMIO hole */
  54.238 +                    || n == store_pfn
  54.239 +                    || n == ioreq_pfn
  54.240 +                    || n == bufioreq_pfn)
  54.241                      continue;
  54.242  
  54.243                  /*
  54.244 @@ -570,7 +625,7 @@ int xc_hvm_save(int xc_handle, int io_fd
  54.245              print_stats( xc_handle, dom, sent_this_iter, &stats, 1);
  54.246  
  54.247              DPRINTF("Total pages sent= %ld (%.2fx)\n",
  54.248 -                    total_sent, ((float)total_sent)/max_pfn );
  54.249 +                    total_sent, ((float)total_sent)/pfn_array_size );
  54.250          }
  54.251  
  54.252          if (last_iter && debug){
  54.253 @@ -597,7 +652,7 @@ int xc_hvm_save(int xc_handle, int io_fd
  54.254                  ((sent_this_iter > sent_last_iter) && RATE_IS_MAX()) ||
  54.255                  (iter >= max_iters) ||
  54.256                  (sent_this_iter+skip_this_iter < 50) ||
  54.257 -                (total_sent > max_pfn*max_factor) ) {
  54.258 +                (total_sent > pfn_array_size*max_factor) ) {
  54.259  
  54.260                  DPRINTF("Start last iteration for HVM domain\n");
  54.261                  last_iter = 1;
  54.262 @@ -616,7 +671,8 @@ int xc_hvm_save(int xc_handle, int io_fd
  54.263  
  54.264              if (xc_shadow_control(xc_handle, dom, 
  54.265                                    XEN_DOMCTL_SHADOW_OP_CLEAN, to_send, 
  54.266 -                                  max_pfn, NULL, 0, &stats) != max_pfn) {
  54.267 +                                  pfn_array_size, NULL, 
  54.268 +                                  0, &stats) != pfn_array_size) {
  54.269                  ERROR("Error flushing shadow PT");
  54.270                  goto out;
  54.271              }
  54.272 @@ -640,20 +696,6 @@ int xc_hvm_save(int xc_handle, int io_fd
  54.273          goto out;
  54.274      }
  54.275  
  54.276 -    if ( (rec_size = xc_domain_hvm_getcontext(xc_handle, dom, hvm_buf, 
  54.277 -                                              hvm_buf_size)) == -1) {
  54.278 -        ERROR("HVM:Could not get hvm buffer");
  54.279 -        goto out;
  54.280 -    }
  54.281 -
  54.282 -    if (!write_exact(io_fd, &rec_size, sizeof(uint32_t))) {
  54.283 -        ERROR("error write hvm buffer size");
  54.284 -        goto out;
  54.285 -    }
  54.286 -
  54.287 -    if ( !write_exact(io_fd, hvm_buf, rec_size) ) {
  54.288 -        ERROR("write HVM info failed!\n");
  54.289 -    }
  54.290  
  54.291      /* save vcpu/vmcs context */
  54.292      if (!write_exact(io_fd, &nr_vcpus, sizeof(uint32_t))) {
  54.293 @@ -682,6 +724,21 @@ int xc_hvm_save(int xc_handle, int io_fd
  54.294          }
  54.295      }
  54.296  
  54.297 +    if ( (rec_size = xc_domain_hvm_getcontext(xc_handle, dom, hvm_buf, 
  54.298 +                                              hvm_buf_size)) == -1) {
  54.299 +        ERROR("HVM:Could not get hvm buffer");
  54.300 +        goto out;
  54.301 +    }
  54.302 +
  54.303 +    if (!write_exact(io_fd, &rec_size, sizeof(uint32_t))) {
  54.304 +        ERROR("error write hvm buffer size");
  54.305 +        goto out;
  54.306 +    }
  54.307 +
  54.308 +    if ( !write_exact(io_fd, hvm_buf, rec_size) ) {
  54.309 +        ERROR("write HVM info failed!\n");
  54.310 +    }
  54.311 +
  54.312      /* Shared-info pfn */
  54.313      if (!write_exact(io_fd, &(shared_info_frame), sizeof(uint32_t)) ) {
  54.314          ERROR("write shared-info pfn failed!\n");
    55.1 --- a/tools/libxc/xc_misc.c	Mon Mar 12 09:43:48 2007 -0600
    55.2 +++ b/tools/libxc/xc_misc.c	Mon Mar 12 10:07:08 2007 -0600
    55.3 @@ -33,6 +33,25 @@ int xc_readconsolering(int xc_handle,
    55.4      return ret;
    55.5  }
    55.6  
    55.7 +int xc_send_debug_keys(int xc_handle, char *keys)
    55.8 +{
    55.9 +    int ret, len = strlen(keys);
   55.10 +    DECLARE_SYSCTL;
   55.11 +
   55.12 +    sysctl.cmd = XEN_SYSCTL_debug_keys;
   55.13 +    set_xen_guest_handle(sysctl.u.debug_keys.keys, keys);
   55.14 +    sysctl.u.debug_keys.nr_keys = len;
   55.15 +
   55.16 +    if ( (ret = lock_pages(keys, len)) != 0 )
   55.17 +        return ret;
   55.18 +
   55.19 +    ret = do_sysctl(xc_handle, &sysctl);
   55.20 +
   55.21 +    unlock_pages(keys, len);
   55.22 +
   55.23 +    return ret;
   55.24 +}
   55.25 +
   55.26  int xc_physinfo(int xc_handle,
   55.27                  xc_physinfo_t *put_info)
   55.28  {
    56.1 --- a/tools/libxc/xc_private.c	Mon Mar 12 09:43:48 2007 -0600
    56.2 +++ b/tools/libxc/xc_private.c	Mon Mar 12 10:07:08 2007 -0600
    56.3 @@ -23,7 +23,7 @@ void xc_default_error_handler(const xc_e
    56.4      fprintf(stderr, "ERROR %s: %s\n", desc, err->message);
    56.5  }
    56.6  
    56.7 -const xc_error const *xc_get_last_error(void)
    56.8 +const xc_error *xc_get_last_error(void)
    56.9  {
   56.10      return &last_error;
   56.11  }
    57.1 --- a/tools/libxc/xc_ptrace_core.c	Mon Mar 12 09:43:48 2007 -0600
    57.2 +++ b/tools/libxc/xc_ptrace_core.c	Mon Mar 12 10:07:08 2007 -0600
    57.3 @@ -390,7 +390,6 @@ map_gmfn_to_offset_elf(unsigned long gmf
    57.4  {
    57.5      /* 
    57.6       * linear search
    57.7 -     * There is no gurantee that those tables are sorted.
    57.8       */
    57.9      unsigned long i;
   57.10      if (current_is_auto_translated_physmap) {
    58.1 --- a/tools/libxc/xenctrl.h	Mon Mar 12 09:43:48 2007 -0600
    58.2 +++ b/tools/libxc/xenctrl.h	Mon Mar 12 10:07:08 2007 -0600
    58.3 @@ -467,6 +467,8 @@ int xc_readconsolering(int xc_handle,
    58.4                         unsigned int *pnr_chars,
    58.5                         int clear);
    58.6  
    58.7 +int xc_send_debug_keys(int xc_handle, char *keys);
    58.8 +
    58.9  typedef xen_sysctl_physinfo_t xc_physinfo_t;
   58.10  int xc_physinfo(int xc_handle,
   58.11                  xc_physinfo_t *info);
   58.12 @@ -770,19 +772,19 @@ typedef struct {
   58.13   * data pointed to are only valid until the next call to
   58.14   * libxc.
   58.15   */
   58.16 -const xc_error const *xc_get_last_error(void);
   58.17 +const xc_error *xc_get_last_error(void);
   58.18  
   58.19  /*
   58.20   * Clear the last error
   58.21   */
   58.22  void xc_clear_last_error(void);
   58.23  
   58.24 -typedef void (*xc_error_handler)(const xc_error const* err);
   58.25 +typedef void (*xc_error_handler)(const xc_error * const err);
   58.26  
   58.27  /*
   58.28   * The default error handler which prints to stderr
   58.29   */
   58.30 -void xc_default_error_handler(const xc_error const* err);
   58.31 +void xc_default_error_handler(const xc_error * const err);
   58.32  
   58.33  /*
   58.34   * Convert an error code into a text description
    59.1 --- a/tools/libxc/xenguest.h	Mon Mar 12 09:43:48 2007 -0600
    59.2 +++ b/tools/libxc/xenguest.h	Mon Mar 12 10:07:08 2007 -0600
    59.3 @@ -12,6 +12,7 @@
    59.4  #define XCFLAGS_LIVE      1
    59.5  #define XCFLAGS_DEBUG     2
    59.6  #define XCFLAGS_HVM       4
    59.7 +#define XCFLAGS_STDVGA    8
    59.8  
    59.9  
   59.10  /**
   59.11 @@ -155,6 +156,8 @@ int xc_set_hvm_param(
   59.12  int xc_get_hvm_param(
   59.13      int handle, domid_t dom, int param, unsigned long *value);
   59.14  
   59.15 +int xc_hvm_drain_io(int handle, domid_t dom);
   59.16 +
   59.17  /* PowerPC specific. */
   59.18  int xc_prose_build(int xc_handle,
   59.19                     uint32_t domid,
    60.1 --- a/tools/libxc/xg_private.c	Mon Mar 12 09:43:48 2007 -0600
    60.2 +++ b/tools/libxc/xg_private.c	Mon Mar 12 10:07:08 2007 -0600
    60.3 @@ -229,6 +229,11 @@ unsigned long csum_page(void *page)
    60.4      return -ENOSYS;
    60.5  }
    60.6  
    60.7 +__attribute__((weak)) int xc_hvm_drain_io(int handle, domid_t dom)
    60.8 +{
    60.9 +    return -ENOSYS;
   60.10 +}
   60.11 +
   60.12  /*
   60.13   * Local variables:
   60.14   * mode: C
    61.1 --- a/tools/libxen/include/xen_crashdump.h	Mon Mar 12 09:43:48 2007 -0600
    61.2 +++ b/tools/libxen/include/xen_crashdump.h	Mon Mar 12 10:07:08 2007 -0600
    61.3 @@ -1,5 +1,5 @@
    61.4  /*
    61.5 - * Copyright (c) 2006, XenSource Inc.
    61.6 + * Copyright (c) 2006-2007, XenSource Inc.
    61.7   *
    61.8   * This library is free software; you can redistribute it and/or
    61.9   * modify it under the terms of the GNU Lesser General Public
   61.10 @@ -162,20 +162,6 @@ xen_crashdump_get_by_uuid(xen_session *s
   61.11  
   61.12  
   61.13  /**
   61.14 - * Create a new crashdump instance, and return its handle.
   61.15 - */
   61.16 -extern bool
   61.17 -xen_crashdump_create(xen_session *session, xen_crashdump *result, xen_crashdump_record *record);
   61.18 -
   61.19 -
   61.20 -/**
   61.21 - * Destroy the specified crashdump instance.
   61.22 - */
   61.23 -extern bool
   61.24 -xen_crashdump_destroy(xen_session *session, xen_crashdump crashdump);
   61.25 -
   61.26 -
   61.27 -/**
   61.28   * Get the uuid field of the given crashdump.
   61.29   */
   61.30  extern bool
   61.31 @@ -197,6 +183,13 @@ xen_crashdump_get_vdi(xen_session *sessi
   61.32  
   61.33  
   61.34  /**
   61.35 + * Destroy the specified crashdump
   61.36 + */
   61.37 +extern bool
   61.38 +xen_crashdump_destroy(xen_session *session, xen_crashdump self);
   61.39 +
   61.40 +
   61.41 +/**
   61.42   * Return a list of all the crashdumps known to the system.
   61.43   */
   61.44  extern bool
    62.1 --- a/tools/libxen/include/xen_vbd.h	Mon Mar 12 09:43:48 2007 -0600
    62.2 +++ b/tools/libxen/include/xen_vbd.h	Mon Mar 12 10:07:08 2007 -0600
    62.3 @@ -358,6 +358,22 @@ xen_vbd_media_change(xen_session *sessio
    62.4  
    62.5  
    62.6  /**
    62.7 + * Hotplug the specified VBD, dynamically attaching it to the running
    62.8 + * VM
    62.9 + */
   62.10 +extern bool
   62.11 +xen_vbd_plug(xen_session *session, xen_vbd self);
   62.12 +
   62.13 +
   62.14 +/**
   62.15 + * Hot-unplug the specified VBD, dynamically unattaching it from the
   62.16 + * running VM
   62.17 + */
   62.18 +extern bool
   62.19 +xen_vbd_unplug(xen_session *session, xen_vbd self);
   62.20 +
   62.21 +
   62.22 +/**
   62.23   * Return a list of all the VBDs known to the system.
   62.24   */
   62.25  extern bool
    63.1 --- a/tools/libxen/include/xen_vdi.h	Mon Mar 12 09:43:48 2007 -0600
    63.2 +++ b/tools/libxen/include/xen_vdi.h	Mon Mar 12 10:07:08 2007 -0600
    63.3 @@ -293,13 +293,6 @@ xen_vdi_set_name_description(xen_session
    63.4  
    63.5  
    63.6  /**
    63.7 - * Set the SR field of the given VDI.
    63.8 - */
    63.9 -extern bool
   63.10 -xen_vdi_set_sr(xen_session *session, xen_vdi vdi, xen_sr sr);
   63.11 -
   63.12 -
   63.13 -/**
   63.14   * Set the virtual_size field of the given VDI.
   63.15   */
   63.16  extern bool
    64.1 --- a/tools/libxen/include/xen_vif.h	Mon Mar 12 09:43:48 2007 -0600
    64.2 +++ b/tools/libxen/include/xen_vif.h	Mon Mar 12 10:07:08 2007 -0600
    64.3 @@ -332,6 +332,22 @@ xen_vif_remove_from_qos_algorithm_params
    64.4  
    64.5  
    64.6  /**
    64.7 + * Hotplug the specified VIF, dynamically attaching it to the running
    64.8 + * VM
    64.9 + */
   64.10 +extern bool
   64.11 +xen_vif_plug(xen_session *session, xen_vif self);
   64.12 +
   64.13 +
   64.14 +/**
   64.15 + * Hot-unplug the specified VIF, dynamically unattaching it from the
   64.16 + * running VM
   64.17 + */
   64.18 +extern bool
   64.19 +xen_vif_unplug(xen_session *session, xen_vif self);
   64.20 +
   64.21 +
   64.22 +/**
   64.23   * Return a list of all the VIFs known to the system.
   64.24   */
   64.25  extern bool
    65.1 --- a/tools/libxen/include/xen_vm.h	Mon Mar 12 09:43:48 2007 -0600
    65.2 +++ b/tools/libxen/include/xen_vm.h	Mon Mar 12 10:07:08 2007 -0600
    65.3 @@ -40,39 +40,6 @@
    65.4   * The VM class.
    65.5   * 
    65.6   * A virtual machine (or 'guest').
    65.7 - * 
    65.8 - * VM booting is controlled by setting one of the two mutually exclusive
    65.9 - * groups: "PV", and "HVM".  If HVM.boot_policy is the empty string, then
   65.10 - * paravirtual domain building and booting will be used; otherwise the VM will
   65.11 - * be loaded as an HVM domain, and booted using an emulated BIOS.
   65.12 - * 
   65.13 - * When paravirtual booting is in use, the PV/bootloader field indicates the
   65.14 - * bootloader to use.  It may be "pygrub", in which case the platform's
   65.15 - * default installation of pygrub will be used, or a full path within the
   65.16 - * control domain to some other bootloader.  The other fields, PV/kernel,
   65.17 - * PV/ramdisk, PV/args and PV/bootloader_args will be passed to the bootloader
   65.18 - * unmodified, and interpretation of those fields is then specific to the
   65.19 - * bootloader itself, including the possibility that the bootloader will
   65.20 - * ignore some or all of those given values. Finally the paths of all bootable
   65.21 - * disks are added to the bootloader commandline (a disk is bootable if its
   65.22 - * VBD has the bootable flag set). There may be zero, one or many bootable
   65.23 - * disks; the bootloader decides which disk (if any) to boot from.
   65.24 - * 
   65.25 - * If the bootloader is pygrub, then the menu.lst is parsed if present in the
   65.26 - * guest's filesystem, otherwise the specified kernel and ramdisk are used, or
   65.27 - * an autodetected kernel is used if nothing is specified and autodetection is
   65.28 - * possible.  PV/args is appended to the kernel command line, no matter which
   65.29 - * mechanism is used for finding the kernel.
   65.30 - * 
   65.31 - * If PV/bootloader is empty but PV/kernel is specified, then the kernel and
   65.32 - * ramdisk values will be treated as paths within the control domain.  If both
   65.33 - * PV/bootloader and PV/kernel are empty, then the behaviour is as if
   65.34 - * PV/bootloader was specified as "pygrub".
   65.35 - * 
   65.36 - * When using HVM booting, HVM/boot_policy and HVM/boot_params specify the
   65.37 - * boot handling.  Only one policy is currently defined: "BIOS order".  In
   65.38 - * this case, HVM/boot_params should contain one key-value pair "order" = "N"
   65.39 - * where N is the string that will be passed to QEMU..
   65.40   */
   65.41  
   65.42  
   65.43 @@ -139,11 +106,7 @@ typedef struct xen_vm_record
   65.44      char *pv_bootloader_args;
   65.45      char *hvm_boot_policy;
   65.46      xen_string_string_map *hvm_boot_params;
   65.47 -    bool platform_std_vga;
   65.48 -    char *platform_serial;
   65.49 -    bool platform_localtime;
   65.50 -    bool platform_clock_offset;
   65.51 -    bool platform_enable_audio;
   65.52 +    xen_string_string_map *platform;
   65.53      char *pci_bus;
   65.54      xen_string_string_map *other_config;
   65.55      int64_t domid;
   65.56 @@ -493,38 +456,10 @@ xen_vm_get_hvm_boot_params(xen_session *
   65.57  
   65.58  
   65.59  /**
   65.60 - * Get the platform/std_VGA field of the given VM.
   65.61 - */
   65.62 -extern bool
   65.63 -xen_vm_get_platform_std_vga(xen_session *session, bool *result, xen_vm vm);
   65.64 -
   65.65 -
   65.66 -/**
   65.67 - * Get the platform/serial field of the given VM.
   65.68 + * Get the platform field of the given VM.
   65.69   */
   65.70  extern bool
   65.71 -xen_vm_get_platform_serial(xen_session *session, char **result, xen_vm vm);
   65.72 -
   65.73 -
   65.74 -/**
   65.75 - * Get the platform/localtime field of the given VM.
   65.76 - */
   65.77 -extern bool
   65.78 -xen_vm_get_platform_localtime(xen_session *session, bool *result, xen_vm vm);
   65.79 -
   65.80 -
   65.81 -/**
   65.82 - * Get the platform/clock_offset field of the given VM.
   65.83 - */
   65.84 -extern bool
   65.85 -xen_vm_get_platform_clock_offset(xen_session *session, bool *result, xen_vm vm);
   65.86 -
   65.87 -
   65.88 -/**
   65.89 - * Get the platform/enable_audio field of the given VM.
   65.90 - */
   65.91 -extern bool
   65.92 -xen_vm_get_platform_enable_audio(xen_session *session, bool *result, xen_vm vm);
   65.93 +xen_vm_get_platform(xen_session *session, xen_string_string_map **result, xen_vm vm);
   65.94  
   65.95  
   65.96  /**
   65.97 @@ -765,38 +700,32 @@ xen_vm_remove_from_hvm_boot_params(xen_s
   65.98  
   65.99  
  65.100  /**
  65.101 - * Set the platform/std_VGA field of the given VM.
  65.102 + * Set the platform field of the given VM.
  65.103   */
  65.104  extern bool
  65.105 -xen_vm_set_platform_std_vga(xen_session *session, xen_vm vm, bool std_vga);
  65.106 -
  65.107 -
  65.108 -/**
  65.109 - * Set the platform/serial field of the given VM.
  65.110 - */
  65.111 -extern bool
  65.112 -xen_vm_set_platform_serial(xen_session *session, xen_vm vm, char *serial);
  65.113 +xen_vm_set_platform(xen_session *session, xen_vm vm, xen_string_string_map *platform);
  65.114  
  65.115  
  65.116  /**
  65.117 - * Set the platform/localtime field of the given VM.
  65.118 + * Add the given key-value pair to the platform field of the given VM.
  65.119   */
  65.120  extern bool
  65.121 -xen_vm_set_platform_localtime(xen_session *session, xen_vm vm, bool localtime);
  65.122 +xen_vm_add_to_platform(xen_session *session, xen_vm vm, char *key, char *value);
  65.123  
  65.124  
  65.125  /**
  65.126 - * Set the platform/clock_offset field of the given VM.
  65.127 + * Remove the given key and its corresponding value from the platform
  65.128 + * field of the given VM.  If the key is not in that Map, then do nothing.
  65.129   */
  65.130  extern bool
  65.131 -xen_vm_set_platform_clock_offset(xen_session *session, xen_vm vm, bool clock_offset);
  65.132 +xen_vm_remove_from_platform(xen_session *session, xen_vm vm, char *key);
  65.133  
  65.134  
  65.135  /**
  65.136 - * Set the platform/enable_audio field of the given VM.
  65.137 + * Set the PCI_bus field of the given VM.
  65.138   */
  65.139  extern bool
  65.140 -xen_vm_set_platform_enable_audio(xen_session *session, xen_vm vm, bool enable_audio);
  65.141 +xen_vm_set_pci_bus(xen_session *session, xen_vm vm, char *pci_bus);
  65.142  
  65.143  
  65.144  /**
    66.1 --- a/tools/libxen/src/xen_common.c	Mon Mar 12 09:43:48 2007 -0600
    66.2 +++ b/tools/libxen/src/xen_common.c	Mon Mar 12 10:07:08 2007 -0600
    66.3 @@ -110,7 +110,7 @@ parse_structmap_value(xen_session *, xml
    66.4  static size_t size_of_member(const abstract_type *);
    66.5  
    66.6  static const char *
    66.7 -get_val_as_string(const struct abstract_type *, void *, char *);
    66.8 +get_val_as_string(const struct abstract_type *, void *, char *, size_t);
    66.9  
   66.10  
   66.11  void
   66.12 @@ -666,8 +666,7 @@ static void parse_into(xen_session *s, x
   66.13      {
   66.14          if (!is_container_node(value_node, "value") ||
   66.15              value_node->children->type != XML_ELEMENT_NODE ||
   66.16 -            0 != strcmp((char *)value_node->children->name, "struct") ||
   66.17 -            value_node->children->children == NULL)
   66.18 +            0 != strcmp((char *)value_node->children->name, "struct"))
   66.19          {
   66.20              server_error(s,
   66.21                           "Expected Map from the server, but didn't get it");
   66.22 @@ -890,6 +889,9 @@ static size_t size_of_member(const abstr
   66.23      case REF:
   66.24          return sizeof(arbitrary_record_opt *);
   66.25  
   66.26 +    case STRUCT:
   66.27 +        return type->struct_size;
   66.28 +
   66.29      default:
   66.30          assert(false);
   66.31      }
   66.32 @@ -1183,7 +1185,8 @@ add_struct_value(const struct abstract_t
   66.33      case INT:
   66.34      case ENUM:
   66.35      {
   66.36 -        const char *val_as_string = get_val_as_string(type, value, buf);
   66.37 +        const char *val_as_string =
   66.38 +            get_val_as_string(type, value, buf, sizeof(buf));
   66.39          adder(node, key, "string", val_as_string);
   66.40      }
   66.41      break;
   66.42 @@ -1215,7 +1218,8 @@ add_struct_value(const struct abstract_t
   66.43  
   66.44              for (size_t i = 0; i < set_val->size; i++)
   66.45              {
   66.46 -                void *member_value = set_val->contents + (i * member_size);
   66.47 +                void *member_value = (char *)set_val->contents +
   66.48 +                                     (i * member_size);
   66.49                  add_struct_value(member_type, member_value,
   66.50                                   add_unnamed_value, NULL, data_node);
   66.51              }
   66.52 @@ -1254,7 +1258,7 @@ add_struct_value(const struct abstract_t
   66.53                  void *r_value = contents + (i * member_size) + r_offset;
   66.54  
   66.55                  const char *l_value_as_string =
   66.56 -                    get_val_as_string(l_type, l_value, buf);
   66.57 +                    get_val_as_string(l_type, l_value, buf, sizeof(buf));
   66.58  
   66.59                  add_struct_value(r_type, r_value, add_struct_member,
   66.60                                   l_value_as_string, struct_node);
   66.61 @@ -1270,7 +1274,8 @@ add_struct_value(const struct abstract_t
   66.62  
   66.63  
   66.64  static const char *
   66.65 -get_val_as_string(const struct abstract_type *type, void *value, char *buf)
   66.66 +get_val_as_string(const struct abstract_type *type, void *value, char *buf,
   66.67 +                  size_t bufsize)
   66.68  {
   66.69      switch (type->typename)
   66.70      {
   66.71 @@ -1304,7 +1309,7 @@ get_val_as_string(const struct abstract_
   66.72      case INT:
   66.73      {
   66.74          int64_t val = *(int64_t *)value;
   66.75 -        snprintf(buf, sizeof(buf), "%"PRId64, val);
   66.76 +        snprintf(buf, bufsize, "%"PRId64, val);
   66.77          return buf;
   66.78      }
   66.79      break;
    67.1 --- a/tools/libxen/src/xen_crashdump.c	Mon Mar 12 09:43:48 2007 -0600
    67.2 +++ b/tools/libxen/src/xen_crashdump.c	Mon Mar 12 10:07:08 2007 -0600
    67.3 @@ -1,5 +1,5 @@
    67.4  /*
    67.5 - * Copyright (c) 2006, XenSource Inc.
    67.6 + * Copyright (c) 2006-2007, XenSource Inc.
    67.7   *
    67.8   * This library is free software; you can redistribute it and/or
    67.9   * modify it under the terms of the GNU Lesser General Public
   67.10 @@ -115,37 +115,6 @@ xen_crashdump_get_by_uuid(xen_session *s
   67.11  
   67.12  
   67.13  bool
   67.14 -xen_crashdump_create(xen_session *session, xen_crashdump *result, xen_crashdump_record *record)
   67.15 -{
   67.16 -    abstract_value param_values[] =
   67.17 -        {
   67.18 -            { .type = &xen_crashdump_record_abstract_type_,
   67.19 -              .u.struct_val = record }
   67.20 -        };
   67.21 -
   67.22 -    abstract_type result_type = abstract_type_string;
   67.23 -
   67.24 -    *result = NULL;
   67.25 -    XEN_CALL_("crashdump.create");
   67.26 -    return session->ok;
   67.27 -}
   67.28 -
   67.29 -
   67.30 -bool
   67.31 -xen_crashdump_destroy(xen_session *session, xen_crashdump crashdump)
   67.32 -{
   67.33 -    abstract_value param_values[] =
   67.34 -        {
   67.35 -            { .type = &abstract_type_string,
   67.36 -              .u.string_val = crashdump }
   67.37 -        };
   67.38 -
   67.39 -    xen_call_(session, "crashdump.destroy", param_values, 1, NULL, NULL);
   67.40 -    return session->ok;
   67.41 -}
   67.42 -
   67.43 -
   67.44 -bool
   67.45  xen_crashdump_get_vm(xen_session *session, xen_vm *result, xen_crashdump crashdump)
   67.46  {
   67.47      abstract_value param_values[] =
   67.48 @@ -180,6 +149,20 @@ xen_crashdump_get_vdi(xen_session *sessi
   67.49  
   67.50  
   67.51  bool
   67.52 +xen_crashdump_destroy(xen_session *session, xen_crashdump self)
   67.53 +{
   67.54 +    abstract_value param_values[] =
   67.55 +        {
   67.56 +            { .type = &abstract_type_string,
   67.57 +              .u.string_val = self }
   67.58 +        };
   67.59 +
   67.60 +    xen_call_(session, "crashdump.destroy", param_values, 1, NULL, NULL);
   67.61 +    return session->ok;
   67.62 +}
   67.63 +
   67.64 +
   67.65 +bool
   67.66  xen_crashdump_get_all(xen_session *session, struct xen_crashdump_set **result)
   67.67  {
   67.68  
    68.1 --- a/tools/libxen/src/xen_vbd.c	Mon Mar 12 09:43:48 2007 -0600
    68.2 +++ b/tools/libxen/src/xen_vbd.c	Mon Mar 12 10:07:08 2007 -0600
    68.3 @@ -552,6 +552,34 @@ xen_vbd_media_change(xen_session *sessio
    68.4  
    68.5  
    68.6  bool
    68.7 +xen_vbd_plug(xen_session *session, xen_vbd self)
    68.8 +{
    68.9 +    abstract_value param_values[] =
   68.10 +        {
   68.11 +            { .type = &abstract_type_string,
   68.12 +              .u.string_val = self }
   68.13 +        };
   68.14 +
   68.15 +    xen_call_(session, "VBD.plug", param_values, 1, NULL, NULL);
   68.16 +    return session->ok;
   68.17 +}
   68.18 +
   68.19 +
   68.20 +bool
   68.21 +xen_vbd_unplug(xen_session *session, xen_vbd self)
   68.22 +{
   68.23 +    abstract_value param_values[] =
   68.24 +        {
   68.25 +            { .type = &abstract_type_string,
   68.26 +              .u.string_val = self }
   68.27 +        };
   68.28 +
   68.29 +    xen_call_(session, "VBD.unplug", param_values, 1, NULL, NULL);
   68.30 +    return session->ok;
   68.31 +}
   68.32 +
   68.33 +
   68.34 +bool
   68.35  xen_vbd_get_all(xen_session *session, struct xen_vbd_set **result)
   68.36  {
   68.37  
    69.1 --- a/tools/libxen/src/xen_vdi.c	Mon Mar 12 09:43:48 2007 -0600
    69.2 +++ b/tools/libxen/src/xen_vdi.c	Mon Mar 12 10:07:08 2007 -0600
    69.3 @@ -410,22 +410,6 @@ xen_vdi_set_name_description(xen_session
    69.4  
    69.5  
    69.6  bool
    69.7 -xen_vdi_set_sr(xen_session *session, xen_vdi vdi, xen_sr sr)
    69.8 -{
    69.9 -    abstract_value param_values[] =
   69.10 -        {
   69.11 -            { .type = &abstract_type_string,
   69.12 -              .u.string_val = vdi },
   69.13 -            { .type = &abstract_type_string,
   69.14 -              .u.string_val = sr }
   69.15 -        };
   69.16 -
   69.17 -    xen_call_(session, "VDI.set_SR", param_values, 2, NULL, NULL);
   69.18 -    return session->ok;
   69.19 -}
   69.20 -
   69.21 -
   69.22 -bool
   69.23  xen_vdi_set_virtual_size(xen_session *session, xen_vdi vdi, int64_t virtual_size)
   69.24  {
   69.25      abstract_value param_values[] =
    70.1 --- a/tools/libxen/src/xen_vif.c	Mon Mar 12 09:43:48 2007 -0600
    70.2 +++ b/tools/libxen/src/xen_vif.c	Mon Mar 12 10:07:08 2007 -0600
    70.3 @@ -500,6 +500,34 @@ xen_vif_remove_from_qos_algorithm_params
    70.4  
    70.5  
    70.6  bool
    70.7 +xen_vif_plug(xen_session *session, xen_vif self)
    70.8 +{
    70.9 +    abstract_value param_values[] =
   70.10 +        {
   70.11 +            { .type = &abstract_type_string,
   70.12 +              .u.string_val = self }
   70.13 +        };
   70.14 +
   70.15 +    xen_call_(session, "VIF.plug", param_values, 1, NULL, NULL);
   70.16 +    return session->ok;
   70.17 +}
   70.18 +
   70.19 +
   70.20 +bool
   70.21 +xen_vif_unplug(xen_session *session, xen_vif self)
   70.22 +{
   70.23 +    abstract_value param_values[] =
   70.24 +        {
   70.25 +            { .type = &abstract_type_string,
   70.26 +              .u.string_val = self }
   70.27 +        };
   70.28 +
   70.29 +    xen_call_(session, "VIF.unplug", param_values, 1, NULL, NULL);
   70.30 +    return session->ok;
   70.31 +}
   70.32 +
   70.33 +
   70.34 +bool
   70.35  xen_vif_get_all(xen_session *session, struct xen_vif_set **result)
   70.36  {
   70.37  
    71.1 --- a/tools/libxen/src/xen_vm.c	Mon Mar 12 09:43:48 2007 -0600
    71.2 +++ b/tools/libxen/src/xen_vm.c	Mon Mar 12 10:07:08 2007 -0600
    71.3 @@ -145,21 +145,9 @@ static const struct_member xen_vm_record
    71.4          { .key = "HVM_boot_params",
    71.5            .type = &abstract_type_string_string_map,
    71.6            .offset = offsetof(xen_vm_record, hvm_boot_params) },
    71.7 -        { .key = "platform_std_VGA",
    71.8 -          .type = &abstract_type_bool,
    71.9 -          .offset = offsetof(xen_vm_record, platform_std_vga) },
   71.10 -        { .key = "platform_serial",
   71.11 -          .type = &abstract_type_string,
   71.12 -          .offset = offsetof(xen_vm_record, platform_serial) },
   71.13 -        { .key = "platform_localtime",
   71.14 -          .type = &abstract_type_bool,
   71.15 -          .offset = offsetof(xen_vm_record, platform_localtime) },
   71.16 -        { .key = "platform_clock_offset",
   71.17 -          .type = &abstract_type_bool,
   71.18 -          .offset = offsetof(xen_vm_record, platform_clock_offset) },
   71.19 -        { .key = "platform_enable_audio",
   71.20 -          .type = &abstract_type_bool,
   71.21 -          .offset = offsetof(xen_vm_record, platform_enable_audio) },
   71.22 +        { .key = "platform",
   71.23 +          .type = &abstract_type_string_string_map,
   71.24 +          .offset = offsetof(xen_vm_record, platform) },
   71.25          { .key = "PCI_bus",
   71.26            .type = &abstract_type_string,
   71.27            .offset = offsetof(xen_vm_record, pci_bus) },
   71.28 @@ -217,7 +205,7 @@ xen_vm_record_free(xen_vm_record *record
   71.29      free(record->pv_bootloader_args);
   71.30      free(record->hvm_boot_policy);
   71.31      xen_string_string_map_free(record->hvm_boot_params);
   71.32 -    free(record->platform_serial);
   71.33 +    xen_string_string_map_free(record->platform);
   71.34      free(record->pci_bus);
   71.35      xen_string_string_map_free(record->other_config);
   71.36      xen_vm_metrics_record_opt_free(record->metrics);
   71.37 @@ -825,23 +813,7 @@ xen_vm_get_hvm_boot_params(xen_session *
   71.38  
   71.39  
   71.40  bool
   71.41 -xen_vm_get_platform_std_vga(xen_session *session, bool *result, xen_vm vm)
   71.42 -{
   71.43 -    abstract_value param_values[] =
   71.44 -        {
   71.45 -            { .type = &abstract_type_string,
   71.46 -              .u.string_val = vm }
   71.47 -        };
   71.48 -
   71.49 -    abstract_type result_type = abstract_type_bool;
   71.50 -
   71.51 -    XEN_CALL_("VM.get_platform_std_VGA");
   71.52 -    return session->ok;
   71.53 -}
   71.54 -
   71.55 -
   71.56 -bool
   71.57 -xen_vm_get_platform_serial(xen_session *session, char **result, xen_vm vm)
   71.58 +xen_vm_get_platform(xen_session *session, xen_string_string_map **result, xen_vm vm)
   71.59  {
   71.60      abstract_value param_values[] =
   71.61          {
   71.62 @@ -849,58 +821,10 @@ xen_vm_get_platform_serial(xen_session *
   71.63                .u.string_val = vm }
   71.64          };
   71.65  
   71.66 -    abstract_type result_type = abstract_type_string;
   71.67 +    abstract_type result_type = abstract_type_string_string_map;
   71.68  
   71.69      *result = NULL;
   71.70 -    XEN_CALL_("VM.get_platform_serial");
   71.71 -    return session->ok;
   71.72 -}
   71.73 -
   71.74 -
   71.75 -bool
   71.76 -xen_vm_get_platform_localtime(xen_session *session, bool *result, xen_vm vm)
   71.77 -{
   71.78 -    abstract_value param_values[] =
   71.79 -        {
   71.80 -            { .type = &abstract_type_string,
   71.81 -              .u.string_val = vm }
   71.82 -        };
   71.83 -
   71.84 -    abstract_type result_type = abstract_type_bool;
   71.85 -
   71.86 -    XEN_CALL_("VM.get_platform_localtime");
   71.87 -    return session->ok;
   71.88 -}
   71.89 -
   71.90 -
   71.91 -bool
   71.92 -xen_vm_get_platform_clock_offset(xen_session *session, bool *result, xen_vm vm)
   71.93 -{
   71.94 -    abstract_value param_values[] =
   71.95 -        {
   71.96 -            { .type = &abstract_type_string,
   71.97 -              .u.string_val = vm }
   71.98 -        };
   71.99 -
  71.100 -    abstract_type result_type = abstract_type_bool;
  71.101 -
  71.102 -    XEN_CALL_("VM.get_platform_clock_offset");
  71.103 -    return session->ok;
  71.104 -}
  71.105 -
  71.106 -
  71.107 -bool
  71.108 -xen_vm_get_platform_enable_audio(xen_session *session, bool *result, xen_vm vm)
  71.109 -{
  71.110 -    abstract_value param_values[] =
  71.111 -        {
  71.112 -            { .type = &abstract_type_string,
  71.113 -              .u.string_val = vm }
  71.114 -        };
  71.115 -
  71.116 -    abstract_type result_type = abstract_type_bool;
  71.117 -
  71.118 -    XEN_CALL_("VM.get_platform_enable_audio");
  71.119 +    XEN_CALL_("VM.get_platform");
  71.120      return session->ok;
  71.121  }
  71.122  
  71.123 @@ -1442,81 +1366,67 @@ xen_vm_remove_from_hvm_boot_params(xen_s
  71.124  
  71.125  
  71.126  bool
  71.127 -xen_vm_set_platform_std_vga(xen_session *session, xen_vm vm, bool std_vga)
  71.128 +xen_vm_set_platform(xen_session *session, xen_vm vm, xen_string_string_map *platform)
  71.129  {
  71.130      abstract_value param_values[] =
  71.131          {
  71.132              { .type = &abstract_type_string,
  71.133                .u.string_val = vm },
  71.134 -            { .type = &abstract_type_bool,
  71.135 -              .u.bool_val = std_vga }
  71.136 +            { .type = &abstract_type_string_string_map,
  71.137 +              .u.set_val = (arbitrary_set *)platform }
  71.138          };
  71.139  
  71.140 -    xen_call_(session, "VM.set_platform_std_VGA", param_values, 2, NULL, NULL);
  71.141 +    xen_call_(session, "VM.set_platform", param_values, 2, NULL, NULL);
  71.142      return session->ok;
  71.143  }
  71.144  
  71.145  
  71.146  bool
  71.147 -xen_vm_set_platform_serial(xen_session *session, xen_vm vm, char *serial)
  71.148 +xen_vm_add_to_platform(xen_session *session, xen_vm vm, char *key, char *value)
  71.149  {
  71.150      abstract_value param_values[] =
  71.151          {
  71.152              { .type = &abstract_type_string,
  71.153                .u.string_val = vm },
  71.154              { .type = &abstract_type_string,
  71.155 -              .u.string_val = serial }
  71.156 +              .u.string_val = key },
  71.157 +            { .type = &abstract_type_string,
  71.158 +              .u.string_val = value }
  71.159          };
  71.160  
  71.161 -    xen_call_(session, "VM.set_platform_serial", param_values, 2, NULL, NULL);
  71.162 -    return session->ok;
  71.163 -}
  71.164 -
  71.165 -
  71.166 -bool
  71.167 -xen_vm_set_platform_localtime(xen_session *session, xen_vm vm, bool localtime)
  71.168 -{
  71.169 -    abstract_value param_values[] =
  71.170 -        {
  71.171 -            { .type = &abstract_type_string,
  71.172 -              .u.string_val = vm },
  71.173 -            { .type = &abstract_type_bool,
  71.174 -              .u.bool_val = localtime }
  71.175 -        };
  71.176 -
  71.177 -    xen_call_(session, "VM.set_platform_localtime", param_values, 2, NULL, NULL);
  71.178 +    xen_call_(session, "VM.add_to_platform", param_values, 3, NULL, NULL);
  71.179      return session->ok;
  71.180  }
  71.181  
  71.182  
  71.183  bool
  71.184 -xen_vm_set_platform_clock_offset(xen_session *session, xen_vm vm, bool clock_offset)
  71.185 +xen_vm_remove_from_platform(xen_session *session, xen_vm vm, char *key)
  71.186  {
  71.187      abstract_value param_values[] =
  71.188          {
  71.189              { .type = &abstract_type_string,
  71.190                .u.string_val = vm },
  71.191 -            { .type = &abstract_type_bool,
  71.192 -              .u.bool_val = clock_offset }
  71.193 +            { .type = &abstract_type_string,
  71.194 +              .u.string_val = key }
  71.195          };
  71.196  
  71.197 -    xen_call_(session, "VM.set_platform_clock_offset", param_values, 2, NULL, NULL);
  71.198 +    xen_call_(session, "VM.remove_from_platform", param_values, 2, NULL, NULL);
  71.199      return session->ok;
  71.200  }
  71.201  
  71.202  
  71.203  bool
  71.204 -xen_vm_set_platform_enable_audio(xen_session *session, xen_vm vm, bool enable_audio)
  71.205 +xen_vm_set_pci_bus(xen_session *session, xen_vm vm, char *pci_bus)
  71.206  {
  71.207      abstract_value param_values[] =
  71.208          {
  71.209              { .type = &abstract_type_string,
  71.210                .u.string_val = vm },
  71.211 -            { .type = &abstract_type_bool,
  71.212 -              .u.bool_val = enable_audio }
  71.213 +            { .type = &abstract_type_string,
  71.214 +              .u.string_val = pci_bus }
  71.215          };
  71.216  
  71.217 -    xen_call_(session, "VM.set_platform_enable_audio", param_values, 2, NULL, NULL);
  71.218 +    xen_call_(session, "VM.set_PCI_bus", param_values, 2, NULL, NULL);
  71.219      return session->ok;
  71.220  }
  71.221  
    72.1 --- a/tools/libxen/test/test_bindings.c	Mon Mar 12 09:43:48 2007 -0600
    72.2 +++ b/tools/libxen/test/test_bindings.c	Mon Mar 12 10:07:08 2007 -0600
    72.3 @@ -375,6 +375,8 @@ static xen_vm create_new_vm(xen_session 
    72.4              .memory_static_min = 128,
    72.5              .vcpus_policy = "credit",
    72.6              .vcpus_params = vcpus_params,
    72.7 +            .vcpus_max = 4,
    72.8 +            .vcpus_at_startup = 2,
    72.9              .actions_after_shutdown = XEN_ON_NORMAL_EXIT_DESTROY,
   72.10              .actions_after_reboot = XEN_ON_NORMAL_EXIT_RESTART,
   72.11              .actions_after_crash = XEN_ON_CRASH_BEHAVIOUR_PRESERVE,
    73.1 --- a/tools/python/xen/lowlevel/xc/xc.c	Mon Mar 12 09:43:48 2007 -0600
    73.2 +++ b/tools/python/xen/lowlevel/xc/xc.c	Mon Mar 12 10:07:08 2007 -0600
    73.3 @@ -47,7 +47,7 @@ static PyObject *dom_op(XcObject *self, 
    73.4  static PyObject *pyxc_error_to_exception(void)
    73.5  {
    73.6      PyObject *pyerr;
    73.7 -    const xc_error const *err = xc_get_last_error();
    73.8 +    const xc_error *err = xc_get_last_error();
    73.9      const char *desc = xc_error_code_to_desc(err->code);
   73.10  
   73.11      if (err->code == XC_ERROR_NONE)
   73.12 @@ -1007,6 +1007,24 @@ static PyObject *pyxc_domain_send_trigge
   73.13      return zero;
   73.14  }
   73.15  
   73.16 +static PyObject *pyxc_send_debug_keys(XcObject *self,
   73.17 +                                      PyObject *args,
   73.18 +                                      PyObject *kwds)
   73.19 +{
   73.20 +    char *keys;
   73.21 +
   73.22 +    static char *kwd_list[] = { "keys", NULL };
   73.23 +
   73.24 +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "s", kwd_list, &keys) )
   73.25 +        return NULL;
   73.26 +
   73.27 +    if ( xc_send_debug_keys(self->xc_handle, keys) != 0 )
   73.28 +        return pyxc_error_to_exception();
   73.29 +
   73.30 +    Py_INCREF(zero);
   73.31 +    return zero;
   73.32 +}
   73.33 +
   73.34  static PyObject *dom_op(XcObject *self, PyObject *args,
   73.35                          int (*fn)(int, uint32_t))
   73.36  {
   73.37 @@ -1420,6 +1438,12 @@ static PyMethodDef pyxc_methods[] = {
   73.38        " vcpu    [int]: VCPU to be sent trigger.\n"
   73.39        "Returns: [int] 0 on success; -1 on error.\n" },
   73.40  
   73.41 +    { "send_debug_keys",
   73.42 +      (PyCFunction)pyxc_send_debug_keys,
   73.43 +      METH_VARARGS | METH_KEYWORDS, "\n"
   73.44 +      "Inject debug keys into Xen.\n"
   73.45 +      " keys    [str]: String of keys to inject.\n" },
   73.46 +
   73.47  #ifdef __powerpc__
   73.48      { "arch_alloc_real_mode_area", 
   73.49        (PyCFunction)pyxc_alloc_real_mode_area, 
    74.1 --- a/tools/python/xen/xend/XendAPI.py	Mon Mar 12 09:43:48 2007 -0600
    74.2 +++ b/tools/python/xen/xend/XendAPI.py	Mon Mar 12 10:07:08 2007 -0600
    74.3 @@ -676,8 +676,9 @@ class XendAPI(object):
    74.4          return xen_api_success_void()
    74.5      def host_remove_from_other_config(self, session, host_ref, key):
    74.6          node = XendNode.instance()
    74.7 -        del node.other_config[key]
    74.8 -        node.save()
    74.9 +        if key in node.other_config:
   74.10 +            del node.other_config[key]
   74.11 +            node.save()
   74.12          return xen_api_success_void()
   74.13      def host_get_API_version_major(self, _, ref):
   74.14          return xen_api_success(XEN_API_VERSION_MAJOR)
   74.15 @@ -998,7 +999,6 @@ class XendAPI(object):
   74.16                    'VIFs',
   74.17                    'VBDs',
   74.18                    'VTPMs',
   74.19 -                  'PCI_bus',
   74.20                    'tools_version',
   74.21                    'domid',
   74.22                    'is_control_domain',
   74.23 @@ -1024,12 +1024,8 @@ class XendAPI(object):
   74.24                    'PV_bootloader_args',
   74.25                    'HVM_boot_policy',
   74.26                    'HVM_boot_params',
   74.27 -                  'platform_std_VGA',
   74.28 -                  'platform_serial',
   74.29 -                  'platform_localtime',
   74.30 -                  'platform_clock_offset',
   74.31 -                  'platform_enable_audio',
   74.32 -                  'platform_keymap',
   74.33 +                  'platform',
   74.34 +                  'PCI_bus',
   74.35                    'other_config']
   74.36  
   74.37      VM_methods = [('clone', 'VM'),
   74.38 @@ -1042,6 +1038,10 @@ class XendAPI(object):
   74.39                    ('hard_reboot', None),
   74.40                    ('suspend', None),
   74.41                    ('resume', None),
   74.42 +                  ('add_to_HVM_boot_params', None),
   74.43 +                  ('remove_from_HVM_boot_params', None),
   74.44 +                  ('add_to_platform', None),
   74.45 +                  ('remove_from_platform', None),
   74.46                    ('add_to_other_config', None),
   74.47                    ('remove_from_other_config', None)]
   74.48      
   74.49 @@ -1071,13 +1071,7 @@ class XendAPI(object):
   74.50          'PV_bootloader_args',
   74.51          'HVM_boot_policy',
   74.52          'HVM_boot_params',
   74.53 -        'platform_std_VGA',
   74.54 -        'platform_serial',
   74.55 -        'platform_localtime',
   74.56 -        'platform_clock_offset',
   74.57 -        'platform_enable_audio',
   74.58 -        'platform_keymap',
   74.59 -        'grub_cmdline',
   74.60 +        'platform',
   74.61          'PCI_bus',
   74.62          'other_config']
   74.63          
   74.64 @@ -1089,7 +1083,10 @@ class XendAPI(object):
   74.65          xd = XendDomain.instance()
   74.66          dominfo = xd.get_vm_by_uuid(vm_ref)
   74.67          dominfo.info[name] = value
   74.68 -        xd.managed_config_save(dominfo)
   74.69 +        return self._VM_save(dominfo)
   74.70 +
   74.71 +    def _VM_save(self, dominfo):
   74.72 +        XendDomain.instance().managed_config_save(dominfo)
   74.73          return xen_api_success_void()
   74.74  
   74.75      # attributes (ro)
   74.76 @@ -1136,10 +1133,6 @@ class XendAPI(object):
   74.77          dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
   74.78          return xen_api_success(dom.get_consoles())
   74.79      
   74.80 -    def VM_get_PCI_bus(self, session, vm_ref):
   74.81 -        dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
   74.82 -        return dom.get_pci_bus()
   74.83 -    
   74.84      def VM_get_tools_version(self, session, vm_ref):
   74.85          dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
   74.86          return dom.get_tools_version()
   74.87 @@ -1214,29 +1207,16 @@ class XendAPI(object):
   74.88      def VM_get_HVM_boot_params(self, session, vm_ref):
   74.89          return self.VM_get('HVM_boot_params', session, vm_ref)
   74.90      
   74.91 -    def VM_get_platform_std_VGA(self, session, vm_ref):
   74.92 -        dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
   74.93 -        return xen_api_success(dom.get_platform_std_vga())
   74.94 -    
   74.95 -    def VM_get_platform_serial(self, session, vm_ref):
   74.96 +    def VM_get_platform(self, session, vm_ref):
   74.97          dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
   74.98 -        return xen_api_success(dom.get_platform_serial())        
   74.99 -    
  74.100 -    def VM_get_platform_localtime(self, session, vm_ref):
  74.101 -        dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
  74.102 -        return xen_api_success(dom.get_platform_localtime())
  74.103 +        return xen_api_success(dom.get_platform())
  74.104      
  74.105 -    def VM_get_platform_clock_offset(self, session, vm_ref):
  74.106 -        dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
  74.107 -        return xen_api_success(dom.get_platform_clock_offset())        
  74.108 -    
  74.109 -    def VM_get_platform_enable_audio(self, session, vm_ref):
  74.110 +    def VM_get_PCI_bus(self, session, vm_ref):
  74.111          dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
  74.112 -        return xen_api_success(dom.get_platform_enable_audio())        
  74.113 +        return dom.get_pci_bus()
  74.114      
  74.115 -    def VM_get_platform_keymap(self, session, vm_ref):
  74.116 -        dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
  74.117 -        return xen_api_success(dom.get_platform_keymap())
  74.118 +    def VM_set_PCI_bus(self, session, vm_ref, val):
  74.119 +        return self.VM_set('PCI_bus', session, vm_ref, val)
  74.120      
  74.121      def VM_get_other_config(self, session, vm_ref):
  74.122          return self.VM_get('other_config', session, vm_ref)        
  74.123 @@ -1253,7 +1233,7 @@ class XendAPI(object):
  74.124      def VM_set_name_label(self, session, vm_ref, label):
  74.125          dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
  74.126          dom.setName(label)
  74.127 -        return xen_api_success_void()
  74.128 +        return self._VM_save(dom)
  74.129      
  74.130      def VM_set_name_description(self, session, vm_ref, desc):
  74.131          dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
  74.132 @@ -1284,12 +1264,12 @@ class XendAPI(object):
  74.133          return xen_api_todo()
  74.134      
  74.135      def VM_set_actions_after_shutdown(self, session, vm_ref, action):
  74.136 -        if action not in XEN_API_ON_NORMAL_EXIST:
  74.137 +        if action not in XEN_API_ON_NORMAL_EXIT:
  74.138              return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
  74.139          return self.VM_set('actions_after_shutdown', session, vm_ref, action)
  74.140      
  74.141      def VM_set_actions_after_reboot(self, session, vm_ref, action):
  74.142 -        if action not in XEN_API_ON_NORMAL_EXIST:
  74.143 +        if action not in XEN_API_ON_NORMAL_EXIT:
  74.144              return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
  74.145          return self.VM_set('actions_after_reboot', session, vm_ref, action)
  74.146      
  74.147 @@ -1319,14 +1299,16 @@ class XendAPI(object):
  74.148          if 'HVM_boot_params' not in dom.info:
  74.149              dom.info['HVM_boot_params'] = {}
  74.150          dom.info['HVM_boot_params'][key] = value
  74.151 -        return xen_api_success_void()
  74.152 +        return self._VM_save(dom)
  74.153  
  74.154      def VM_remove_from_HVM_boot_params(self, session, vm_ref, key):
  74.155          dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
  74.156          if 'HVM_boot_params' in dom.info \
  74.157                 and key in dom.info['HVM_boot_params']:
  74.158              del dom.info['HVM_boot_params'][key]
  74.159 -        return xen_api_success_void()
  74.160 +            return self._VM_save(dom)
  74.161 +        else:
  74.162 +            return xen_api_success_void()
  74.163  
  74.164      def VM_set_PV_bootloader(self, session, vm_ref, value):
  74.165          return self.VM_set('PV_bootloader', session, vm_ref, value)
  74.166 @@ -1343,40 +1325,42 @@ class XendAPI(object):
  74.167      def VM_set_PV_bootloader_args(self, session, vm_ref, value):
  74.168          return self.VM_set('PV_bootloader_args', session, vm_ref, value)
  74.169  
  74.170 -    def VM_set_platform_std_VGA(self, session, vm_ref, value):
  74.171 -        return self.VM_set('platform_std_vga', session, vm_ref, value)
  74.172 -    
  74.173 -    def VM_set_platform_serial(self, session, vm_ref, value):
  74.174 -        return self.VM_set('platform_serial', session, vm_ref, value)
  74.175 -
  74.176 -    def VM_set_platform_keymap(self, session, vm_ref, value):
  74.177 -        return self.VM_set('platform_keymap', session, vm_ref, value)
  74.178 +    def VM_set_platform(self, session, vm_ref, value):
  74.179 +        return self.VM_set('platform', session, vm_ref, value)
  74.180      
  74.181 -    def VM_set_platform_localtime(self, session, vm_ref, value):
  74.182 -        return self.VM_set('platform_localtime', session, vm_ref, value)
  74.183 -    
  74.184 -    def VM_set_platform_clock_offset(self, session, vm_ref, value):
  74.185 -        return self.VM_set('platform_clock_offset', session, vm_ref, value)
  74.186 -    
  74.187 -    def VM_set_platform_enable_audio(self, session, vm_ref, value):
  74.188 -        return self.VM_set('platform_enable_audio', session, vm_ref, value)
  74.189 -    
  74.190 +    def VM_add_to_platform(self, session, vm_ref, key, value):
  74.191 +        dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
  74.192 +        plat = dom.get_platform()
  74.193 +        plat[key] = value
  74.194 +        return self.VM_set_platform(session, vm_ref, plat)
  74.195 +
  74.196 +    def VM_remove_from_platform(self, session, vm_ref, key):
  74.197 +        dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
  74.198 +        plat = dom.get_platform()
  74.199 +        if key in plat:
  74.200 +            del plat[key]
  74.201 +            return self.VM_set_platform(session, vm_ref, plat)
  74.202 +        else:
  74.203 +            return xen_api_success_void()
  74.204 +
  74.205      def VM_set_other_config(self, session, vm_ref, value):
  74.206 -        return self.VM_set('otherconfig', session, vm_ref, value)
  74.207 +        return self.VM_set('other_config', session, vm_ref, value)
  74.208  
  74.209      def VM_add_to_other_config(self, session, vm_ref, key, value):
  74.210          dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
  74.211 -        if dom and 'otherconfig' in dom.info:
  74.212 -            dom.info['otherconfig'][key] = value
  74.213 -        return xen_api_success_void()
  74.214 +        if dom and 'other_config' in dom.info:
  74.215 +            dom.info['other_config'][key] = value
  74.216 +        return self._VM_save(dom)
  74.217  
  74.218      def VM_remove_from_other_config(self, session, vm_ref, key):
  74.219          dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
  74.220 -        if dom and 'otherconfig' in dom.info \
  74.221 -               and key in dom.info['otherconfig']:
  74.222 -            del dom.info['otherconfig'][key]
  74.223 -        return xen_api_success_void()        
  74.224 -    
  74.225 +        if dom and 'other_config' in dom.info \
  74.226 +               and key in dom.info['other_config']:
  74.227 +            del dom.info['other_config'][key]
  74.228 +            return self._VM_save(dom)
  74.229 +        else:
  74.230 +            return xen_api_success_void()
  74.231 +
  74.232      # class methods
  74.233      def VM_get_all(self, session):
  74.234          refs = [d.get_uuid() for d in XendDomain.instance().list('all')]
  74.235 @@ -1437,12 +1421,7 @@ class XendAPI(object):
  74.236              'PV_bootloader_args': xeninfo.info.get('PV_bootloader_args'),
  74.237              'HVM_boot_policy': xeninfo.info.get('HVM_boot_policy'),
  74.238              'HVM_boot_params': xeninfo.info.get('HVM_boot_params'),
  74.239 -            'platform_std_VGA': xeninfo.get_platform_std_vga(),
  74.240 -            'platform_serial': xeninfo.get_platform_serial(),
  74.241 -            'platform_localtime': xeninfo.get_platform_localtime(),
  74.242 -            'platform_clock_offset': xeninfo.get_platform_clock_offset(),
  74.243 -            'platform_enable_audio': xeninfo.get_platform_enable_audio(),
  74.244 -            'platform_keymap': xeninfo.get_platform_keymap(),
  74.245 +            'platform': xeninfo.get_platform(),
  74.246              'PCI_bus': xeninfo.get_pci_bus(),
  74.247              'tools_version': xeninfo.get_tools_version(),
  74.248              'other_config': xeninfo.info.get('other_config', {}),
  74.249 @@ -1486,10 +1465,13 @@ class XendAPI(object):
  74.250                                       start_paused = start_paused)
  74.251      
  74.252      def VM_start(self, session, vm_ref, start_paused):
  74.253 -        return XendTask.log_progress(0, 100, do_vm_func,
  74.254 -                                     "domain_start", vm_ref,
  74.255 -                                     start_paused = start_paused)
  74.256 -    
  74.257 +        try:
  74.258 +            return XendTask.log_progress(0, 100, do_vm_func,
  74.259 +                                         "domain_start", vm_ref,
  74.260 +                                         start_paused = start_paused)
  74.261 +        except HVMRequired, exn:
  74.262 +            return xen_api_error(['VM_HVM_REQUIRED', vm_ref])
  74.263 +
  74.264      def VM_suspend(self, session, vm_ref):
  74.265          return XendTask.log_progress(0, 100, do_vm_func,
  74.266                                       "domain_suspend", vm_ref)
  74.267 @@ -1754,13 +1736,13 @@ class XendAPI(object):
  74.268  
  74.269      # Xen API: Class VDI
  74.270      # ----------------------------------------------------------------
  74.271 -    VDI_attr_ro = ['VBDs',
  74.272 +    VDI_attr_ro = ['SR',
  74.273 +                   'VBDs',
  74.274                     'physical_utilisation',
  74.275                     'sector_size',
  74.276                     'type']
  74.277      VDI_attr_rw = ['name_label',
  74.278                     'name_description',
  74.279 -                   'SR',
  74.280                     'virtual_size',
  74.281                     'sharable',
  74.282                     'read_only']
  74.283 @@ -1812,9 +1794,6 @@ class XendAPI(object):
  74.284          self._get_VDI(vdi_ref).name_description = value
  74.285          return xen_api_success_void()
  74.286  
  74.287 -    def VDI_set_SR(self, session, vdi_ref, value):
  74.288 -        return xen_api_error(XEND_ERROR_UNSUPPORTED)
  74.289 -
  74.290      def VDI_set_virtual_size(self, session, vdi_ref, value):
  74.291          return xen_api_error(XEND_ERROR_UNSUPPORTED)
  74.292  
  74.293 @@ -1929,7 +1908,7 @@ class XendAPI(object):
  74.294                   XendDomain.POWER_STATE_NAMES[dom.state]])
  74.295              from xen.xend.server import tpmif
  74.296              tpmif.destroy_vtpmstate(dom.getName())
  74.297 -            return xen_api_success(True)
  74.298 +            return xen_api_success_void()
  74.299          else:
  74.300              return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
  74.301  
    75.1 --- a/tools/python/xen/xend/XendCheckpoint.py	Mon Mar 12 09:43:48 2007 -0600
    75.2 +++ b/tools/python/xen/xend/XendCheckpoint.py	Mon Mar 12 10:07:08 2007 -0600
    75.3 @@ -74,9 +74,13 @@ def save(fd, dominfo, network, live, dst
    75.4  
    75.5          image_cfg = dominfo.info.get('image', {})
    75.6          hvm = image_cfg.has_key('hvm')
    75.7 +        stdvga = 0
    75.8  
    75.9          if hvm:
   75.10              log.info("save hvm domain")
   75.11 +            if image_cfg['hvm']['devices']['stdvga'] == 1:
   75.12 +                stdvga = 1
   75.13 +
   75.14          # xc_save takes three customization parameters: maxit, max_f, and
   75.15          # flags the last controls whether or not save is 'live', while the
   75.16          # first two further customize behaviour when 'live' save is
   75.17 @@ -84,7 +88,8 @@ def save(fd, dominfo, network, live, dst
   75.18          # libxenguest; see the comments and/or code in xc_linux_save() for
   75.19          # more information.
   75.20          cmd = [xen.util.auxbin.pathTo(XC_SAVE), str(fd),
   75.21 -               str(dominfo.getDomid()), "0", "0", str(int(live) | (int(hvm) << 2)) ]
   75.22 +               str(dominfo.getDomid()), "0", "0", 
   75.23 +               str(int(live) | (int(hvm) << 2) | (int(stdvga) << 3)) ]
   75.24          log.debug("[xc_save]: %s", string.join(cmd))
   75.25  
   75.26          def saveInputHandler(line, tochild):
    76.1 --- a/tools/python/xen/xend/XendConfig.py	Mon Mar 12 09:43:48 2007 -0600
    76.2 +++ b/tools/python/xen/xend/XendConfig.py	Mon Mar 12 10:07:08 2007 -0600
    76.3 @@ -12,7 +12,7 @@
    76.4  # License along with this library; if not, write to the Free Software
    76.5  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    76.6  #============================================================================
    76.7 -# Copyright (C) 2006 XenSource Ltd
    76.8 +# Copyright (C) 2006-2007 XenSource Ltd
    76.9  #============================================================================
   76.10  
   76.11  import logging
   76.12 @@ -111,22 +111,18 @@ XENAPI_CFG_TO_LEGACY_CFG = {
   76.13      'actions_after_shutdown': 'on_poweroff',
   76.14      'actions_after_reboot': 'on_reboot',
   76.15      'actions_after_crash': 'on_crash', 
   76.16 -    'platform_localtime': 'localtime',
   76.17      'PV_bootloader': 'bootloader',
   76.18      'PV_bootloader_args': 'bootloader_args',
   76.19  }
   76.20  
   76.21  LEGACY_CFG_TO_XENAPI_CFG = reverse_dict(XENAPI_CFG_TO_LEGACY_CFG)
   76.22  
   76.23 -# Mapping from XendConfig configuration keys to the old
   76.24 -# legacy configuration keys that are found in the 'image'
   76.25 -# SXP object.
   76.26 -XENAPI_HVM_CFG = {
   76.27 -    'platform_std_vga': 'stdvga',
   76.28 -    'platform_serial' : 'serial',
   76.29 -    'platform_localtime': 'localtime',
   76.30 -    'platform_keymap' : 'keymap'
   76.31 -}    
   76.32 +# Platform configuration keys.
   76.33 +XENAPI_PLATFORM_CFG = [ 'acpi', 'apic', 'device_model', 'display', 'fda',
   76.34 +                        'fdb', 'keymap', 'isa', 'localtime', 'nographic',
   76.35 +                        'pae', 'serial', 'sdl', 'soundhw','stdvga', 'usb',
   76.36 +                        'usbdevice', 'vnc', 'vncconsole', 'vncdisplay',
   76.37 +                        'vnclisten', 'vncpasswd', 'vncunused', 'xauthority']
   76.38  
   76.39  # List of XendConfig configuration keys that have no direct equivalent
   76.40  # in the old world.
   76.41 @@ -151,7 +147,6 @@ XENAPI_CFG_TYPES = {
   76.42      'actions_after_shutdown': str,
   76.43      'actions_after_reboot': str,
   76.44      'actions_after_crash': str,
   76.45 -    'tpm_backend': int,    
   76.46      'PV_bootloader': str,
   76.47      'PV_kernel': str,
   76.48      'PV_ramdisk': str,
   76.49 @@ -159,15 +154,10 @@ XENAPI_CFG_TYPES = {
   76.50      'PV_bootloader_args': str,
   76.51      'HVM_boot_policy': str,
   76.52      'HVM_boot_params': dict,
   76.53 -    'platform_std_vga': bool0,
   76.54 -    'platform_serial': str,
   76.55 -    'platform_localtime': bool0,
   76.56 -    'platform_clock_offset': bool0,
   76.57 -    'platform_enable_audio': bool0,
   76.58 -    'platform_keymap': str,
   76.59 -    'pci_bus': str,
   76.60 +    'PCI_bus': str,
   76.61 +    'platform': dict,
   76.62      'tools_version': dict,
   76.63 -    'otherconfig': dict,
   76.64 +    'other_config': dict,
   76.65  }
   76.66  
   76.67  # List of legacy configuration keys that have no equivalent in the
   76.68 @@ -237,44 +227,7 @@ LEGACY_XENSTORE_VM_PARAMS = [
   76.69      'on_xend_stop',
   76.70  ]
   76.71  
   76.72 -LEGACY_IMAGE_CFG = [
   76.73 -    ('root', str),
   76.74 -    ('ip', str),
   76.75 -    ('nographic', int),
   76.76 -    ('vnc', int),
   76.77 -    ('sdl', int),
   76.78 -    ('vncdisplay', int),
   76.79 -    ('vncunused', int),
   76.80 -    ('vncpasswd', str),
   76.81 -    ('vnclisten', str),
   76.82 -]
   76.83 -
   76.84 -LEGACY_IMAGE_HVM_CFG = [
   76.85 -    ('device_model', str),
   76.86 -    ('display', str),
   76.87 -    ('xauthority', str),
   76.88 -    ('vncconsole', int),
   76.89 -    ('pae', int),
   76.90 -    ('apic', int),
   76.91 -]
   76.92 -
   76.93 -LEGACY_IMAGE_HVM_DEVICES_CFG = [
   76.94 -    ('acpi', int),    
   76.95 -    ('boot', str),
   76.96 -    ('fda', str),
   76.97 -    ('fdb', str),
   76.98 -    ('isa', int),
   76.99 -    ('keymap', str),    
  76.100 -    ('localtime', int),    
  76.101 -    ('serial', str),
  76.102 -    ('stdvga', int),
  76.103 -    ('soundhw', str),
  76.104 -    ('usb', int),
  76.105 -    ('usbdevice', str),    
  76.106 -    ('vcpus', int),
  76.107 -]
  76.108 -
  76.109 -LEGACY_DM = '/usr/lib/xen/bin/qemu-dm'
  76.110 +DEFAULT_DM = '/usr/lib/xen/bin/qemu-dm'
  76.111  
  76.112  ##
  76.113  ## Config Choices
  76.114 @@ -316,7 +269,6 @@ class XendConfig(dict):
  76.115              self._sxp_to_xapi_unsupported(sxp_obj)
  76.116          elif xapi:
  76.117              self.update_with_xenapi_config(xapi)
  76.118 -            self._add_xapi_unsupported(xapi)
  76.119          elif dominfo:
  76.120              # output from xc.domain_getinfo
  76.121              self._dominfo_to_xapi(dominfo)
  76.122 @@ -363,7 +315,6 @@ class XendConfig(dict):
  76.123              'memory_dynamic_max': 0,
  76.124              'memory_actual': 0,
  76.125              'devices': {},
  76.126 -            'image': {},
  76.127              'security': None,
  76.128              'on_xend_start': 'ignore',
  76.129              'on_xend_stop': 'ignore',
  76.130 @@ -377,6 +328,7 @@ class XendConfig(dict):
  76.131              'vbd_refs': [],
  76.132              'vtpm_refs': [],
  76.133              'other_config': {},
  76.134 +            'platform': {}
  76.135          }
  76.136          
  76.137          return defaults
  76.138 @@ -417,12 +369,23 @@ class XendConfig(dict):
  76.139          if 'name_label' not in self:
  76.140              self['name_label'] = 'Domain-' + self['uuid']
  76.141  
  76.142 +    def _platform_sanity_check(self):
  76.143 +        if self.is_hvm():
  76.144 +            if 'device_model' not in self['platform']:
  76.145 +                self['platform']['device_model'] = DEFAULT_DM
  76.146 +
  76.147 +            # Compatibility hack, can go away soon.
  76.148 +            if 'soundhw' not in self['platform'] and \
  76.149 +               self['platform'].get('enable_audio'):
  76.150 +                self['platform']['soundhw'] = 'sb16'
  76.151 +
  76.152      def validate(self):
  76.153          self._uuid_sanity_check()
  76.154          self._name_sanity_check()
  76.155          self._memory_sanity_check()
  76.156          self._actions_sanity_check()
  76.157          self._vcpus_sanity_check()
  76.158 +        self._platform_sanity_check()
  76.159  
  76.160      def _dominfo_to_xapi(self, dominfo):
  76.161          self['domid'] = dominfo['domid']
  76.162 @@ -498,6 +461,18 @@ class XendConfig(dict):
  76.163                      log.warn("Unable to parse key %s: %s: %s" %
  76.164                               (key, str(val), e))
  76.165  
  76.166 +        if 'platform' not in cfg:
  76.167 +            cfg['platform'] = {}
  76.168 +        localtime = sxp.child_value(sxp_cfg, 'localtime')
  76.169 +        if localtime is not None:
  76.170 +            cfg['platform']['localtime'] = localtime
  76.171 +
  76.172 +        # Compatibility hack -- can go soon.
  76.173 +        for key in XENAPI_PLATFORM_CFG:
  76.174 +            val = sxp.child_value(sxp_cfg, "platform_" + key, None)
  76.175 +            if val is not None:
  76.176 +                self['platform'][key] = val
  76.177 +
  76.178          # Compatibility hack -- can go soon.
  76.179          boot_order = sxp.child_value(sxp_cfg, 'HVM_boot')
  76.180          if boot_order:
  76.181 @@ -652,10 +627,9 @@ class XendConfig(dict):
  76.182              self.update_with_image_sxp(image_sxp)
  76.183  
  76.184          # Convert Legacy HVM parameters to Xen API configuration
  76.185 -        self['platform_std_vga'] = bool0(cfg.get('stdvga', 0))
  76.186 -        self['platform_serial'] = str(cfg.get('serial', ''))
  76.187 -        self['platform_localtime'] = bool0(cfg.get('localtime', 0))
  76.188 -        self['platform_enable_audio'] = bool0(cfg.get('soundhw', 0))
  76.189 +        for key in XENAPI_PLATFORM_CFG:
  76.190 +            if key in cfg:
  76.191 +                self['platform'][key] = cfg[key]
  76.192  
  76.193          # make sure a sane maximum is set
  76.194          if self['memory_static_max'] <= 0:
  76.195 @@ -672,7 +646,7 @@ class XendConfig(dict):
  76.196          self['vtpm_refs'] = cfg.get('vtpm_refs', [])
  76.197  
  76.198          # coalesce hvm vnc frame buffer with vfb config
  76.199 -        if self['image']['type'] == 'hvm' and self['image'].get('vnc', 0):
  76.200 +        if self.is_hvm() and self['platform'].get('vnc', 0):
  76.201              # add vfb device if it isn't there already
  76.202              has_rfb = False
  76.203              for console_uuid in self['console_refs']:
  76.204 @@ -685,11 +659,11 @@ class XendConfig(dict):
  76.205  
  76.206              if not has_rfb:
  76.207                  dev_config = ['vfb']
  76.208 -                # copy VNC related params from image config to vfb dev conf
  76.209 +                # copy VNC related params from platform config to vfb dev conf
  76.210                  for key in ['vncpasswd', 'vncunused', 'vncdisplay',
  76.211                              'vnclisten']:
  76.212 -                    if key in self['image']:
  76.213 -                        dev_config.append([key, self['image'][key]])
  76.214 +                    if key in self['platform']:
  76.215 +                        dev_config.append([key, self['platform'][key]])
  76.216  
  76.217                  self.device_add('vfb', cfg_sxp = dev_config)
  76.218  
  76.219 @@ -706,39 +680,19 @@ class XendConfig(dict):
  76.220          # the image (as well as HVM images)
  76.221          image_sxp = sxp.child_value(sxp_cfg, 'image', [])
  76.222          if image_sxp:
  76.223 -            image = {}
  76.224 -            image['type'] = sxp.name(image_sxp)
  76.225 -            for arg, conv in LEGACY_IMAGE_CFG:
  76.226 -                val = sxp.child_value(image_sxp, arg, None)
  76.227 -                if val != None:
  76.228 -                    image[arg] = conv(val)
  76.229 -
  76.230 -            image_hvm = {}
  76.231 -            for arg, conv in LEGACY_IMAGE_HVM_CFG:
  76.232 -                val = sxp.child_value(image_sxp, arg, None)
  76.233 -                if val != None:
  76.234 -                    image_hvm[arg] = conv(val)
  76.235 -                    
  76.236 -            image_hvm_devices = {}
  76.237 -            for arg, conv in LEGACY_IMAGE_HVM_DEVICES_CFG:
  76.238 -                val = sxp.child_value(image_sxp, arg, None)
  76.239 -                if val != None:
  76.240 -                    image_hvm_devices[arg] = conv(val)
  76.241 -
  76.242 -            if image_hvm or image_hvm_devices:
  76.243 -                image['hvm'] = image_hvm
  76.244 -                image['hvm']['devices'] = image_hvm_devices
  76.245 -
  76.246 +            image_type = sxp.name(image_sxp)
  76.247 +            if image_type != 'hvm' and image_type != 'linux':
  76.248 +                self['platform']['image_type'] = image_type
  76.249 +            
  76.250 +            for key in XENAPI_PLATFORM_CFG:
  76.251 +                val = sxp.child_value(image_sxp, key, None)
  76.252 +                if val is not None:
  76.253 +                    self['platform'][key] = val
  76.254 +            
  76.255              notes = sxp.children(image_sxp, 'notes')
  76.256              if notes:
  76.257 -                image['notes'] = self.notes_from_sxp(notes[0])
  76.258 -
  76.259 -            self['image'] = image
  76.260 +                self['notes'] = self.notes_from_sxp(notes[0])
  76.261  
  76.262 -            for apikey, imgkey in XENAPI_HVM_CFG.items():
  76.263 -                val = sxp.child_value(image_sxp, imgkey, None)
  76.264 -                if val != None:
  76.265 -                    self[apikey] = val
  76.266              self._hvm_boot_params_from_sxp(image_sxp)
  76.267  
  76.268          # extract backend value
  76.269 @@ -774,33 +728,6 @@ class XendConfig(dict):
  76.270          _set_cfg_if_exists('up_time')
  76.271          _set_cfg_if_exists('status') # TODO, deprecated  
  76.272  
  76.273 -    def _add_xapi_unsupported(self, xapi_dict):
  76.274 -        """Updates the configuration object with entries that are not
  76.275 -        officially supported by the Xen API but is required for
  76.276 -        the rest of Xend to function.
  76.277 -        """
  76.278 -
  76.279 -        # populate image
  76.280 -        if 'image' in xapi_dict:
  76.281 -            self['image'].update(xapi_dict['image'])
  76.282 -        else:
  76.283 -            hvm = self['HVM_boot_policy'] != ''
  76.284 -            self['image']['type'] = hvm and 'hvm' or 'linux'
  76.285 -            if hvm:
  76.286 -                self['image']['hvm'] = {'devices': {}}
  76.287 -                for xapi, cfgapi in XENAPI_HVM_CFG.items():
  76.288 -                    if xapi in self:
  76.289 -                        self['image']['hvm']['devices'][cfgapi] = self[xapi]
  76.290 -
  76.291 -                # currently unsupported options
  76.292 -                self['image']['hvm']['device_model'] = LEGACY_DM
  76.293 -                self['image']['vnc'] = 0
  76.294 -                self['image']['hvm']['pae'] = 1
  76.295 -
  76.296 -                if self['platform_enable_audio']:
  76.297 -                    self['image']['hvm']['devices']['soundhw'] = 'sb16'
  76.298 -
  76.299 -
  76.300      def _get_old_state_string(self):
  76.301          """Returns the old xm state string.
  76.302          @rtype: string
  76.303 @@ -890,9 +817,7 @@ class XendConfig(dict):
  76.304              if self.has_key(legacy) and self[legacy] not in (None, []):
  76.305                  sxpr.append([legacy, self[legacy]])
  76.306  
  76.307 -        if 'image' in self and self['image']:
  76.308 -            sxpr.append(['image', self.image_sxpr()])
  76.309 -
  76.310 +        sxpr.append(['image', self.image_sxpr()])
  76.311          sxpr.append(['status', domain.state])
  76.312          sxpr.append(['memory_dynamic_min',  self.get('memory_dynamic_min')])
  76.313          sxpr.append(['memory_dynamic_max',  self.get('memory_dynamic_max')])
  76.314 @@ -1339,7 +1264,7 @@ class XendConfig(dict):
  76.315      def image_sxpr(self):
  76.316          """Returns a backwards compatible image SXP expression that is
  76.317          used in xenstore's /vm/<uuid>/image value and xm list."""
  76.318 -        image = [self['image'].get('type', 'linux')]
  76.319 +        image = [self.image_type()]
  76.320          if self.has_key('PV_kernel'):
  76.321              image.append(['kernel', self['PV_kernel']])
  76.322          if self.has_key('PV_ramdisk') and self['PV_ramdisk']:
  76.323 @@ -1347,28 +1272,12 @@ class XendConfig(dict):
  76.324          if self.has_key('PV_args') and self['PV_args']:
  76.325              image.append(['args', self['PV_args']])
  76.326  
  76.327 -        for arg, conv in LEGACY_IMAGE_CFG:
  76.328 -            if self['image'].has_key(arg):
  76.329 -                image.append([arg, self['image'][arg]])
  76.330 -
  76.331 -        if 'hvm' in self['image']:
  76.332 -            for arg, conv in LEGACY_IMAGE_HVM_CFG:
  76.333 -                if self['image']['hvm'].get(arg):
  76.334 -                    image.append([arg, conv(self['image']['hvm'][arg])])
  76.335 +        for key in XENAPI_PLATFORM_CFG:
  76.336 +            if key in self['platform']:
  76.337 +                image.append([key, self['platform'][key]])
  76.338  
  76.339 -        if 'hvm' in self['image'] and 'devices' in self['image']['hvm']:
  76.340 -            for arg, conv in LEGACY_IMAGE_HVM_DEVICES_CFG:
  76.341 -                val = self['image']['hvm']['devices'].get(arg)
  76.342 -                if val != None:
  76.343 -                    try:
  76.344 -                        if conv: val = conv(val)
  76.345 -                    except (ValueError, TypeError):
  76.346 -                        if type(val) == bool: val = int(val)
  76.347 -                            
  76.348 -                    image.append([arg, val])
  76.349 -
  76.350 -        if 'notes' in self['image']:
  76.351 -            image.append(self.notes_sxp(self['image']['notes']))
  76.352 +        if 'notes' in self:
  76.353 +            image.append(self.notes_sxp(self['notes']))
  76.354  
  76.355          return image
  76.356  
  76.357 @@ -1399,57 +1308,24 @@ class XendConfig(dict):
  76.358              self['PV_ramdisk'] = sxp.child_value(image_sxp, 'ramdisk','')
  76.359              self['PV_args'] = kernel_args
  76.360  
  76.361 -        # Store image SXP in python dictionary format
  76.362 -        image = {}
  76.363 -        image['type'] = sxp.name(image_sxp)
  76.364 -        for arg, conv in LEGACY_IMAGE_CFG:
  76.365 -            val = sxp.child_value(image_sxp, arg, None)
  76.366 -            if val != None:
  76.367 -                image[arg] = conv(val)
  76.368 -
  76.369 -        image_hvm = {}
  76.370 -        for arg, conv in LEGACY_IMAGE_HVM_CFG:
  76.371 -            val = sxp.child_value(image_sxp, arg, None)
  76.372 -            if val != None:
  76.373 -                image_hvm[arg] = conv(val)
  76.374 -                    
  76.375 -        image_hvm_devices = {}
  76.376 -        for arg, conv in LEGACY_IMAGE_HVM_DEVICES_CFG:
  76.377 -            val = sxp.child_value(image_sxp, arg, None)
  76.378 -            if val != None:
  76.379 -                try:
  76.380 -                    image_hvm_devices[arg] = conv(val)
  76.381 -                except (ValueError, TypeError):
  76.382 -                    image_hvm_devices[arg] = val
  76.383 -                        
  76.384 -
  76.385 -        if image_hvm or image_hvm_devices:
  76.386 -            image['hvm'] = image_hvm
  76.387 -            image['hvm']['devices'] = image_hvm_devices
  76.388 +        for key in XENAPI_PLATFORM_CFG:
  76.389 +            val = sxp.child_value(image_sxp, key, None)
  76.390 +            if val is not None:
  76.391 +                self['platform'][key] = val
  76.392  
  76.393          notes = sxp.children(image_sxp, 'notes')
  76.394          if notes:
  76.395 -            image['notes'] = self.notes_from_sxp(notes[0])
  76.396 -
  76.397 -        self['image'] = image
  76.398 +            self['notes'] = self.notes_from_sxp(notes[0])
  76.399  
  76.400 -        for apikey, imgkey in XENAPI_HVM_CFG.items():
  76.401 -            val = sxp.child_value(image_sxp, imgkey, None)
  76.402 -            if val != None:
  76.403 -                type_conv = XENAPI_CFG_TYPES[apikey]
  76.404 -                if callable(type_conv):
  76.405 -                    self[apikey] = type_conv(val)
  76.406 -                else:
  76.407 -                    self[apikey] = val
  76.408          self._hvm_boot_params_from_sxp(image_sxp)
  76.409  
  76.410      def set_notes(self, notes):
  76.411          'Add parsed elfnotes to image'
  76.412 -        self['image']['notes'] = notes
  76.413 +        self['notes'] = notes
  76.414  
  76.415      def get_notes(self):
  76.416          try:
  76.417 -            return self['image']['notes'] or {}
  76.418 +            return self['notes'] or {}
  76.419          except KeyError:
  76.420              return {}
  76.421  
  76.422 @@ -1471,11 +1347,9 @@ class XendConfig(dict):
  76.423              self['HVM_boot_policy'] = 'BIOS order'
  76.424              self['HVM_boot_params'] = { 'order' : boot }
  76.425  
  76.426 +    def is_hvm(self):
  76.427 +        return self['HVM_boot_policy'] != ''
  76.428  
  76.429 -#
  76.430 -# debugging 
  76.431 -#
  76.432 -
  76.433 -if __name__ == "__main__":
  76.434 -    pass
  76.435 -    
  76.436 +    def image_type(self):
  76.437 +        stored_type = self['platform'].get('image_type')
  76.438 +        return stored_type or (self.is_hvm() and 'hvm' or 'linux')
    77.1 --- a/tools/python/xen/xend/XendDomain.py	Mon Mar 12 09:43:48 2007 -0600
    77.2 +++ b/tools/python/xen/xend/XendDomain.py	Mon Mar 12 10:07:08 2007 -0600
    77.3 @@ -495,7 +495,7 @@ class XendDomain:
    77.4              self._refresh(refresh_shutdown = False)
    77.5              dom = self.domain_lookup_nr(domid)
    77.6              if not dom:
    77.7 -                raise XendInvalidDomain("No domain named '%s'." % str(domid))
    77.8 +                raise XendInvalidDomain(str(domid))
    77.9              return dom
   77.10          finally:
   77.11              self.domains_lock.release()
    78.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Mon Mar 12 09:43:48 2007 -0600
    78.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Mon Mar 12 10:07:08 2007 -0600
    78.3 @@ -13,7 +13,7 @@
    78.4  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    78.5  #============================================================================
    78.6  # Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
    78.7 -# Copyright (C) 2005, 2006 XenSource Ltd
    78.8 +# Copyright (C) 2005-2007 XenSource Ltd
    78.9  #============================================================================
   78.10  
   78.11  """Representation of a single domain.
   78.12 @@ -176,14 +176,8 @@ def recreate(info, priv):
   78.13          vm._storeVmDetails()
   78.14          vm._storeDomDetails()
   78.15          
   78.16 -    if vm.info['image']: # Only dom0 should be without an image entry when
   78.17 -                         # recreating, but we cope with missing ones
   78.18 -                         # elsewhere just in case.
   78.19 -        vm.image = image.create(vm,
   78.20 -                                vm.info,
   78.21 -                                vm.info['image'],
   78.22 -                                vm.info['devices'])
   78.23 -        vm.image.recreate()
   78.24 +    vm.image = image.create(vm, vm.info)
   78.25 +    vm.image.recreate()
   78.26  
   78.27      vm._registerWatches()
   78.28      vm.refreshShutdown(xeninfo)
   78.29 @@ -448,9 +442,7 @@ class XendDomainInfo:
   78.30          self.storeDom("control/shutdown", reason)
   78.31  
   78.32          ## shutdown hypercall for hvm domain desides xenstore write
   78.33 -        image_cfg = self.info.get('image', {})
   78.34 -        hvm = image_cfg.has_key('hvm')
   78.35 -        if hvm:
   78.36 +        if self.info.is_hvm():
   78.37              for code in DOMAIN_SHUTDOWN_REASONS.keys():
   78.38                  if DOMAIN_SHUTDOWN_REASONS[code] == reason:
   78.39                      break
   78.40 @@ -781,7 +773,6 @@ class XendDomainInfo:
   78.41              'name':               self.info['name_label'],
   78.42              'console/limit':      str(xoptions.get_console_limit() * 1024),
   78.43              'memory/target':      str(self.info['memory_static_min'] * 1024),
   78.44 -            'control/platform-feature-multiprocessor-suspend': str(1)
   78.45              }
   78.46  
   78.47          def f(n, v):
   78.48 @@ -796,6 +787,9 @@ class XendDomainInfo:
   78.49          f('store/port',       self.store_port)
   78.50          f('store/ring-ref',   self.store_mfn)
   78.51  
   78.52 +        if arch.type == "x86":
   78.53 +            f('control/platform-feature-multiprocessor-suspend', True)
   78.54 +
   78.55          # elfnotes
   78.56          for n, v in self.info.get_notes().iteritems():
   78.57              n = n.lower().replace('_', '-')
   78.58 @@ -1387,9 +1381,7 @@ class XendDomainInfo:
   78.59  
   78.60          self.shutdownStartTime = None
   78.61  
   78.62 -        image_cfg = self.info.get('image', {})
   78.63 -        hvm = image_cfg.has_key('hvm')
   78.64 -
   78.65 +        hvm = self.info.is_hvm()
   78.66          if hvm:
   78.67              info = xc.xeninfo()
   78.68              if 'hvm' not in info['xen_caps']:
   78.69 @@ -1436,14 +1428,8 @@ class XendDomainInfo:
   78.70  
   78.71          self._configureBootloader()
   78.72  
   78.73 -        if not self._infoIsSet('image'):
   78.74 -            raise VmError('Missing image in configuration')
   78.75 -
   78.76          try:
   78.77 -            self.image = image.create(self,
   78.78 -                                      self.info,
   78.79 -                                      self.info['image'],
   78.80 -                                      self.info['devices'])
   78.81 +            self.image = image.create(self, self.info)
   78.82  
   78.83              localtime = self.info.get('platform_localtime', False)
   78.84              if localtime:
   78.85 @@ -1503,9 +1489,15 @@ class XendDomainInfo:
   78.86              self.info['start_time'] = time.time()
   78.87  
   78.88              self._stateSet(DOM_STATE_RUNNING)
   78.89 -        except (RuntimeError, VmError), exn:
   78.90 +        except VmError, exn:
   78.91              log.exception("XendDomainInfo.initDomain: exception occurred")
   78.92 -            self.image.cleanupBootloading()
   78.93 +            if self.image:
   78.94 +                self.image.cleanupBootloading()
   78.95 +            raise exn
   78.96 +        except RuntimeError, exn:
   78.97 +            log.exception("XendDomainInfo.initDomain: exception occurred")
   78.98 +            if self.image:
   78.99 +                self.image.cleanupBootloading()
  78.100              raise VmError(str(exn))
  78.101  
  78.102  
  78.103 @@ -1572,13 +1564,8 @@ class XendDomainInfo:
  78.104          self.console_mfn = console_mfn
  78.105  
  78.106          self._introduceDomain()
  78.107 -        image_cfg = self.info.get('image', {})
  78.108 -        hvm = image_cfg.has_key('hvm')
  78.109 -        if hvm:
  78.110 -            self.image = image.create(self,
  78.111 -                    self.info,
  78.112 -                    self.info['image'],
  78.113 -                    self.info['devices'])
  78.114 +        if self.info.is_hvm():
  78.115 +            self.image = image.create(self, self.info)
  78.116              if self.image:
  78.117                  self.image.createDeviceModel(True)
  78.118                  self.image.register_shutdown_watch()
  78.119 @@ -1740,11 +1727,7 @@ class XendDomainInfo:
  78.120  
  78.121          if boot:
  78.122              # HVM booting.
  78.123 -            self.info['image']['type'] = 'hvm'
  78.124 -            if not 'devices' in self.info['image']:
  78.125 -                self.info['image']['devices'] = {}
  78.126 -            self.info['image']['devices']['boot'] = \
  78.127 -                self.info['HVM_boot_params'].get('order', 'dc')
  78.128 +            pass
  78.129          elif not blexec and kernel:
  78.130              # Boot from dom0.  Nothing left to do -- the kernel and ramdisk
  78.131              # will be picked up by image.py.
  78.132 @@ -1908,10 +1891,9 @@ class XendDomainInfo:
  78.133              if self._infoIsSet(info_key):
  78.134                  to_store[key] = str(self.info[info_key])
  78.135  
  78.136 -        if self.info.get('image'):
  78.137 -            image_sxpr = self.info.image_sxpr()
  78.138 -            if image_sxpr:
  78.139 -                to_store['image'] = sxp.to_string(image_sxpr)
  78.140 +        image_sxpr = self.info.image_sxpr()
  78.141 +        if image_sxpr:
  78.142 +            to_store['image'] = sxp.to_string(image_sxpr)
  78.143  
  78.144          if self._infoIsSet('security'):
  78.145              secinfo = self.info['security']
  78.146 @@ -2072,18 +2054,8 @@ class XendDomainInfo:
  78.147          return retval
  78.148      def get_power_state(self):
  78.149          return XEN_API_VM_POWER_STATE[self.state]
  78.150 -    def get_platform_std_vga(self):
  78.151 -        return self.info.get('platform_std_vga', False)    
  78.152 -    def get_platform_serial(self):
  78.153 -        return self.info.get('platform_serial', '')
  78.154 -    def get_platform_localtime(self):
  78.155 -        return self.info.get('platform_localtime', False)
  78.156 -    def get_platform_clock_offset(self):
  78.157 -        return self.info.get('platform_clock_offset', False)
  78.158 -    def get_platform_enable_audio(self):
  78.159 -        return self.info.get('platform_enable_audio', False)
  78.160 -    def get_platform_keymap(self):
  78.161 -        return self.info.get('platform_keymap', '')
  78.162 +    def get_platform(self):
  78.163 +        return self.info.get('platform', {})    
  78.164      def get_pci_bus(self):
  78.165          return self.info.get('pci_bus', '')
  78.166      def get_tools_version(self):
    79.1 --- a/tools/python/xen/xend/XendError.py	Mon Mar 12 09:43:48 2007 -0600
    79.2 +++ b/tools/python/xen/xend/XendError.py	Mon Mar 12 10:07:08 2007 -0600
    79.3 @@ -13,6 +13,7 @@
    79.4  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    79.5  #============================================================================
    79.6  # Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
    79.7 +# Copyright (c) 2006, 2007 XenSource Inc.
    79.8  #============================================================================
    79.9  
   79.10  from xmlrpclib import Fault
   79.11 @@ -55,6 +56,12 @@ class VmError(XendError):
   79.12      """Vm construction error."""
   79.13      pass
   79.14  
   79.15 +class HVMRequired(VmError):
   79.16 +    def __init__(self):
   79.17 +        XendError.__init__(self,
   79.18 +                           'HVM guest support is unavailable: is VT/AMD-V '
   79.19 +                           'supported by your CPU and enabled in your BIOS?')
   79.20 +
   79.21  
   79.22  XEND_ERROR_AUTHENTICATION_FAILED = ('ELUSER', 'Authentication Failed')
   79.23  XEND_ERROR_SESSION_INVALID       = ('EPERMDENIED', 'Session Invalid')
    80.1 --- a/tools/python/xen/xend/XendNode.py	Mon Mar 12 09:43:48 2007 -0600
    80.2 +++ b/tools/python/xen/xend/XendNode.py	Mon Mar 12 10:07:08 2007 -0600
    80.3 @@ -95,15 +95,12 @@ class XendNode:
    80.4                  self.cpus[u] = {'uuid': u, 'number': i }
    80.5  
    80.6          for u in self.cpus.keys():
    80.7 -            log.error(self.cpus[u])
    80.8              number = self.cpus[u]['number']
    80.9              # We can run off the end of the cpuinfo list if domain0 does not
   80.10              # have #vcpus == #pcpus. In that case we just replicate one that's
   80.11              # in the hash table.
   80.12              if not cpuinfo.has_key(number):
   80.13                  number = cpuinfo.keys()[0]
   80.14 -            log.error(number)
   80.15 -            log.error(cpuinfo)
   80.16              if arch.type == "x86":
   80.17                  self.cpus[u].update(
   80.18                      { 'host'     : self.uuid,
   80.19 @@ -453,6 +450,12 @@ class XendNode:
   80.20                  return pif.network
   80.21          raise Exception('Bridge %s is not connected to a network' % bridge)
   80.22  
   80.23 +    #
   80.24 +    # Debug keys.
   80.25 +    #
   80.26 +
   80.27 +    def send_debug_keys(self, keys):
   80.28 +        return self.xc.send_debug_keys(keys)
   80.29  
   80.30      #
   80.31      # Getting host information.
    81.1 --- a/tools/python/xen/xend/image.py	Mon Mar 12 09:43:48 2007 -0600
    81.2 +++ b/tools/python/xen/xend/image.py	Mon Mar 12 10:07:08 2007 -0600
    81.3 @@ -13,7 +13,7 @@
    81.4  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    81.5  #============================================================================
    81.6  # Copyright (C) 2005 Mike Wray <mike.wray@hp.com>
    81.7 -# Copyright (C) 2005 XenSource Ltd
    81.8 +# Copyright (C) 2005-2007 XenSource Ltd
    81.9  #============================================================================
   81.10  
   81.11  
   81.12 @@ -24,7 +24,7 @@ import signal
   81.13  
   81.14  import xen.lowlevel.xc
   81.15  from xen.xend.XendConstants import REVERSE_DOMAIN_SHUTDOWN_REASONS
   81.16 -from xen.xend.XendError import VmError, XendError
   81.17 +from xen.xend.XendError import VmError, XendError, HVMRequired
   81.18  from xen.xend.XendLogging import log
   81.19  from xen.xend.XendOptions import instance as xenopts
   81.20  from xen.xend.server.netif import randomMAC
   81.21 @@ -36,13 +36,12 @@ xc = xen.lowlevel.xc.xc()
   81.22  MAX_GUEST_CMDLINE = 1024
   81.23  
   81.24  
   81.25 -def create(vm, vmConfig, imageConfig, deviceConfig):
   81.26 +def create(vm, vmConfig):
   81.27      """Create an image handler for a vm.
   81.28  
   81.29      @return ImageHandler instance
   81.30      """
   81.31 -    return findImageHandlerClass(imageConfig)(vm, vmConfig, imageConfig,
   81.32 -                                              deviceConfig)
   81.33 +    return findImageHandlerClass(vmConfig)(vm, vmConfig)
   81.34  
   81.35  
   81.36  class ImageHandler:
   81.37 @@ -65,7 +64,7 @@ class ImageHandler:
   81.38      ostype = None
   81.39  
   81.40  
   81.41 -    def __init__(self, vm, vmConfig, imageConfig, deviceConfig):
   81.42 +    def __init__(self, vm, vmConfig):
   81.43          self.vm = vm
   81.44  
   81.45          self.bootloader = False
   81.46 @@ -73,9 +72,9 @@ class ImageHandler:
   81.47          self.ramdisk = None
   81.48          self.cmdline = None
   81.49  
   81.50 -        self.configure(vmConfig, imageConfig, deviceConfig)
   81.51 +        self.configure(vmConfig)
   81.52  
   81.53 -    def configure(self, vmConfig, imageConfig, _):
   81.54 +    def configure(self, vmConfig):
   81.55          """Config actions common to all unix-like domains."""
   81.56          if '_temp_using_bootloader' in vmConfig:
   81.57              self.bootloader = True
   81.58 @@ -262,30 +261,29 @@ class HVMImageHandler(ImageHandler):
   81.59  
   81.60      ostype = "hvm"
   81.61  
   81.62 -    def __init__(self, vm, vmConfig, imageConfig, deviceConfig):
   81.63 -        ImageHandler.__init__(self, vm, vmConfig, imageConfig, deviceConfig)
   81.64 +    def __init__(self, vm, vmConfig):
   81.65 +        ImageHandler.__init__(self, vm, vmConfig)
   81.66          self.shutdownWatch = None
   81.67          self.rebootFeatureWatch = None
   81.68  
   81.69 -    def configure(self, vmConfig, imageConfig, deviceConfig):
   81.70 -        ImageHandler.configure(self, vmConfig, imageConfig, deviceConfig)
   81.71 +    def configure(self, vmConfig):
   81.72 +        ImageHandler.configure(self, vmConfig)
   81.73  
   81.74          if not self.kernel:
   81.75              self.kernel = '/usr/lib/xen/boot/hvmloader'
   81.76  
   81.77          info = xc.xeninfo()
   81.78          if 'hvm' not in info['xen_caps']:
   81.79 -            raise VmError("HVM guest support is unavailable: is VT/AMD-V "
   81.80 -                          "supported by your CPU and enabled in your BIOS?")
   81.81 +            raise HVMRequired()
   81.82  
   81.83          self.dmargs = self.parseDeviceModelArgs(vmConfig)
   81.84 -        self.device_model = imageConfig['hvm'].get('device_model')
   81.85 +        self.device_model = vmConfig['platform'].get('device_model')
   81.86          if not self.device_model:
   81.87              raise VmError("hvm: missing device model")
   81.88          
   81.89 -        self.display = imageConfig['hvm'].get('display')
   81.90 -        self.xauthority = imageConfig['hvm'].get('xauthority')
   81.91 -        self.vncconsole = imageConfig['hvm'].get('vncconsole')
   81.92 +        self.display = vmConfig['platform'].get('display')
   81.93 +        self.xauthority = vmConfig['platform'].get('xauthority')
   81.94 +        self.vncconsole = vmConfig['platform'].get('vncconsole')
   81.95  
   81.96          self.vm.storeVm(("image/dmargs", " ".join(self.dmargs)),
   81.97                          ("image/device-model", self.device_model),
   81.98 @@ -293,9 +291,9 @@ class HVMImageHandler(ImageHandler):
   81.99  
  81.100          self.pid = None
  81.101  
  81.102 -        self.pae  = imageConfig['hvm'].get('pae', 0)
  81.103 -        self.apic  = imageConfig['hvm'].get('apic', 0)
  81.104 -        self.acpi  = imageConfig['hvm']['devices'].get('acpi', 0)
  81.105 +        self.pae  = int(vmConfig['platform'].get('pae',  0))
  81.106 +        self.apic = int(vmConfig['platform'].get('apic', 0))
  81.107 +        self.acpi = int(vmConfig['platform'].get('acpi', 0))
  81.108          
  81.109  
  81.110      def buildDomain(self):
  81.111 @@ -331,11 +329,10 @@ class HVMImageHandler(ImageHandler):
  81.112                     'localtime', 'serial', 'stdvga', 'isa',
  81.113                     'acpi', 'usb', 'usbdevice', 'keymap' ]
  81.114          
  81.115 -        hvmDeviceConfig = vmConfig['image']['hvm']['devices']
  81.116          ret = ['-vcpus', str(self.vm.getVCpuCount())]
  81.117  
  81.118          for a in dmargs:
  81.119 -            v = hvmDeviceConfig.get(a)
  81.120 +            v = vmConfig['platform'].get(a)
  81.121  
  81.122              # python doesn't allow '-' in variable names
  81.123              if a == 'stdvga': a = 'std-vga'
  81.124 @@ -395,14 +392,14 @@ class HVMImageHandler(ImageHandler):
  81.125          # Find RFB console device, and if it exists, make QEMU enable
  81.126          # the VNC console.
  81.127          #
  81.128 -        if vmConfig['image'].get('nographic'):
  81.129 +        if vmConfig['platform'].get('nographic'):
  81.130              # skip vnc init if nographic is set
  81.131              ret.append('-nographic')
  81.132              return ret
  81.133  
  81.134          vnc_config = {}
  81.135 -        has_vnc = int(vmConfig['image'].get('vnc', 0)) != 0
  81.136 -        has_sdl = int(vmConfig['image'].get('sdl', 0)) != 0
  81.137 +        has_vnc = int(vmConfig['platform'].get('vnc', 0)) != 0
  81.138 +        has_sdl = int(vmConfig['platform'].get('sdl', 0)) != 0
  81.139          for dev_uuid in vmConfig['console_refs']:
  81.140              dev_type, dev_info = vmConfig['devices'][dev_uuid]
  81.141              if dev_type == 'vfb':
  81.142 @@ -414,8 +411,8 @@ class HVMImageHandler(ImageHandler):
  81.143              if not vnc_config:
  81.144                  for key in ('vncunused', 'vnclisten', 'vncdisplay',
  81.145                              'vncpasswd'):
  81.146 -                    if key in vmConfig['image']:
  81.147 -                        vnc_config[key] = vmConfig['image'][key]
  81.148 +                    if key in vmConfig['platform']:
  81.149 +                        vnc_config[key] = vmConfig['platform'][key]
  81.150  
  81.151              if not vnc_config.get('vncunused', 0) and \
  81.152                     vnc_config.get('vncdisplay', 0):
  81.153 @@ -634,9 +631,7 @@ def findImageHandlerClass(image):
  81.154      @param image config
  81.155      @return ImageHandler subclass or None
  81.156      """
  81.157 -    image_type = image['type']
  81.158 -    if image_type is None:
  81.159 -        raise VmError('missing image type')
  81.160 +    image_type = image.image_type()
  81.161      try:
  81.162          return _handlers[arch.type][image_type]
  81.163      except KeyError:
    82.1 --- a/tools/python/xen/xend/server/XMLRPCServer.py	Mon Mar 12 09:43:48 2007 -0600
    82.2 +++ b/tools/python/xen/xend/server/XMLRPCServer.py	Mon Mar 12 10:07:08 2007 -0600
    82.3 @@ -157,7 +157,7 @@ class XMLRPCServer:
    82.4                      self.server.register_function(fn, "xend.domain.%s" % name[7:])
    82.5  
    82.6          # Functions in XendNode and XendDmesg
    82.7 -        for type, lst, n in [(XendNode, ['info'], 'node'),
    82.8 +        for type, lst, n in [(XendNode, ['info', 'send_debug_keys'], 'node'),
    82.9                               (XendDmesg, ['info', 'clear'], 'node.dmesg')]:
   82.10              inst = type.instance()
   82.11              for name in lst:
    83.1 --- a/tools/python/xen/xm/XenAPI.py	Mon Mar 12 09:43:48 2007 -0600
    83.2 +++ b/tools/python/xen/xm/XenAPI.py	Mon Mar 12 10:07:08 2007 -0600
    83.3 @@ -155,7 +155,7 @@ class Session(xen.util.xmlrpclib2.Server
    83.4  
    83.5  def _parse_result(result):
    83.6      if type(result) != dict or 'Status' not in result:
    83.7 -        raise xmlrpclib.Fault(500, 'Missing Status in response from server')
    83.8 +        raise xmlrpclib.Fault(500, 'Missing Status in response from server' + result)
    83.9      if result['Status'] == 'Success':
   83.10          if 'Value' in result:
   83.11              return result['Value']
    84.1 --- a/tools/python/xen/xm/main.py	Mon Mar 12 09:43:48 2007 -0600
    84.2 +++ b/tools/python/xen/xm/main.py	Mon Mar 12 10:07:08 2007 -0600
    84.3 @@ -25,6 +25,7 @@ import atexit
    84.4  import cmd
    84.5  import os
    84.6  import pprint
    84.7 +import readline
    84.8  import shlex
    84.9  import sys
   84.10  import re
   84.11 @@ -133,6 +134,7 @@ SUBCOMMAND_HELP = {
   84.12      'sched-credit': ('[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]]',
   84.13                       'Get/set credit scheduler parameters.'),
   84.14      'sysrq'       : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
   84.15 +    'debug-keys'  : ('<Keys>', 'Send debug keys to Xen.'),
   84.16      'trigger'     : ('<Domain> <nmi|reset|init> [<VCPU>]',
   84.17                       'Send a trigger to a domain.'),
   84.18      'vcpu-list'   : ('[<Domain>]',
   84.19 @@ -260,7 +262,6 @@ common_commands = [
   84.20      "shutdown",
   84.21      "start",
   84.22      "suspend",
   84.23 -    "trigger",
   84.24      "top",
   84.25      "unpause",
   84.26      "uptime",
   84.27 @@ -300,6 +301,7 @@ domain_commands = [
   84.28      ]
   84.29  
   84.30  host_commands = [
   84.31 +    "debug-keys",
   84.32      "dmesg",
   84.33      "info",
   84.34      "log",
   84.35 @@ -557,6 +559,10 @@ class Shell(cmd.Cmd):
   84.36              for f in res:
   84.37                  setattr(Shell, 'do_' + f, self.default)
   84.38  
   84.39 +    def preloop(self):
   84.40 +        cmd.Cmd.preloop(self)
   84.41 +        readline.set_completer_delims(' ')
   84.42 +
   84.43      def default(self, line):
   84.44          words = shlex.split(line)
   84.45          if len(words) > 0 and words[0] == 'xm':
   84.46 @@ -576,9 +582,9 @@ class Shell(cmd.Cmd):
   84.47          return False
   84.48  
   84.49      def completedefault(self, text, line, begidx, endidx):
   84.50 -        cmd = line.split(' ')[0]
   84.51 -        clas, func = cmd.split('.')
   84.52 -        if begidx != len(cmd) + 1 or \
   84.53 +        words = shlex.split(line[:begidx])
   84.54 +        clas, func = words[0].split('.')
   84.55 +        if len(words) > 1 or \
   84.56             func.startswith('get_by_') or \
   84.57             func == 'get_all':
   84.58              return []
   84.59 @@ -1395,6 +1401,10 @@ def xm_trigger(args):
   84.60      
   84.61      server.xend.domain.send_trigger(dom, trigger, vcpu)
   84.62  
   84.63 +def xm_debug_keys(args):
   84.64 +    arg_check(args, "debug-keys", 1)
   84.65 +    server.xend.node.send_debug_keys(str(args[0]))
   84.66 +
   84.67  def xm_top(args):
   84.68      arg_check(args, "top", 0)
   84.69  
   84.70 @@ -1738,6 +1748,7 @@ commands = {
   84.71      "pause": xm_pause,
   84.72      "unpause": xm_unpause,
   84.73      # host commands
   84.74 +    "debug-keys": xm_debug_keys,
   84.75      "dmesg": xm_dmesg,
   84.76      "info": xm_info,
   84.77      "log": xm_log,
   84.78 @@ -1881,7 +1892,7 @@ def _run_cmd(cmd, cmd_name, args):
   84.79              err("Domain '%s' does not exist." % ex.faultString)
   84.80          else:
   84.81              err(ex.faultString)
   84.82 -        _usage(cmd_name)
   84.83 +            _usage(cmd_name)
   84.84      except xmlrpclib.ProtocolError, ex:
   84.85          if ex.errcode == -1:
   84.86              print  >>sys.stderr, (
    85.1 --- a/tools/python/xen/xm/messages/en/xen-xm.po	Mon Mar 12 09:43:48 2007 -0600
    85.2 +++ b/tools/python/xen/xm/messages/en/xen-xm.po	Mon Mar 12 10:07:08 2007 -0600
    85.3 @@ -19,7 +19,7 @@
    85.4  msgid ""
    85.5  msgstr ""
    85.6  "Project-Id-Version: Xen-xm 3.0\n"
    85.7 -"PO-Revision-Date: 2007-02-20 15:22+0000\n"
    85.8 +"PO-Revision-Date: 2007-03-10 23:17+0000\n"
    85.9  "Last-Translator: Ewan Mellor <ewan@xensource.com>\n"
   85.10  "Language-Team: xen-devel <xen-devel@lists.xensource.com>\n"
   85.11  "MIME-Version: 1.0\n"
   85.12 @@ -61,3 +61,6 @@ msgstr "The VLAN tag you gave (%(1)s) is
   85.13  
   85.14  msgid "VM_BAD_POWER_STATE"
   85.15  msgstr "The VM must be %(2)s to perform the requested operation (it is currently %(3)s)."
   85.16 +
   85.17 +msgid "VM_HVM_REQUIRED"
   85.18 +msgstr "HVM guest support is unavailable: is VT/AMD-V supported by your CPU and enabled in your BIOS?"
    86.1 --- a/tools/xm-test/tests/vtpm/09_vtpm-xapi.py	Mon Mar 12 09:43:48 2007 -0600
    86.2 +++ b/tools/xm-test/tests/vtpm/09_vtpm-xapi.py	Mon Mar 12 10:07:08 2007 -0600
    86.3 @@ -113,7 +113,7 @@ if not re.search("PCR-00:",run["output"]
    86.4      FAIL("1. Virtual TPM is not working correctly on /dev/vtpm on backend side: \n%s" % run["output"])
    86.5  
    86.6  try:
    86.7 -    rc = session.xenapi.VTPM.destroy(vtpm_uuid)
    86.8 +    session.xenapi.VTPM.destroy(vtpm_uuid)
    86.9      #Should never get here
   86.10      FAIL("Could destroy vTPM while VM is running")
   86.11  except:
   86.12 @@ -124,7 +124,7 @@ if rc:
   86.13      FAIL("Could not suspend VM")
   86.14  
   86.15  try:
   86.16 -    rc = session.xenapi.VTPM.destroy(vtpm_uuid)
   86.17 +    session.xenapi.VTPM.destroy(vtpm_uuid)
   86.18      #May not throw an exception in 'suspend' state
   86.19  except:
   86.20      pass
   86.21 @@ -150,8 +150,9 @@ if not re.search("PCR-00:",run["output"]
   86.22  
   86.23  domain.stop()
   86.24  
   86.25 -rc = session.xenapi.VTPM.destroy(vtpm_uuid)
   86.26 -if not rc:
   86.27 +try:
   86.28 +    session.xenapi.VTPM.destroy(vtpm_uuid)
   86.29 +except:
   86.30      FAIL("Could NOT destroy vTPM while domain is halted.")
   86.31  
   86.32  domain.destroy()
    87.1 --- a/xen/arch/ia64/xen/xensetup.c	Mon Mar 12 09:43:48 2007 -0600
    87.2 +++ b/xen/arch/ia64/xen/xensetup.c	Mon Mar 12 10:07:08 2007 -0600
    87.3 @@ -543,8 +543,6 @@ printk("num_online_cpus=%d, max_cpus=%d\
    87.4  
    87.5      domain0_ready = 1;
    87.6  
    87.7 -    schedulers_start();
    87.8 -
    87.9      domain_unpause_by_systemcontroller(dom0);
   87.10  
   87.11      startup_cpu_idle_loop();
    88.1 --- a/xen/arch/powerpc/domain.c	Mon Mar 12 09:43:48 2007 -0600
    88.2 +++ b/xen/arch/powerpc/domain.c	Mon Mar 12 10:07:08 2007 -0600
    88.3 @@ -142,6 +142,8 @@ void free_vcpu_struct(struct vcpu *v)
    88.4  
    88.5  int vcpu_initialise(struct vcpu *v)
    88.6  {
    88.7 +    /* Guests by default have a 100Hz ticker. */
    88.8 +    v->periodic_period = MILLISECS(10);
    88.9      return 0;
   88.10  }
   88.11  
    89.1 --- a/xen/arch/powerpc/setup.c	Mon Mar 12 09:43:48 2007 -0600
    89.2 +++ b/xen/arch/powerpc/setup.c	Mon Mar 12 10:07:08 2007 -0600
    89.3 @@ -365,9 +365,6 @@ static void __init __start_xen(multiboot
    89.4          kick_secondary_cpus(max_cpus);
    89.5      }
    89.6  
    89.7 -    /* Secondary processors must be online before we call this.  */
    89.8 -    schedulers_start();
    89.9 -
   89.10      /* This cannot be called before secondary cpus are marked online.  */
   89.11      percpu_free_unused_areas();
   89.12  
    90.1 --- a/xen/arch/x86/apic.c	Mon Mar 12 09:43:48 2007 -0600
    90.2 +++ b/xen/arch/x86/apic.c	Mon Mar 12 10:07:08 2007 -0600
    90.3 @@ -1023,6 +1023,13 @@ int reprogram_timer(s_time_t timeout)
    90.4      u64         apic_tmict;
    90.5  
    90.6      /*
    90.7 +     * If we don't have local APIC then we just poll the timer list off the
    90.8 +     * PIT interrupt.
    90.9 +     */
   90.10 +    if ( !cpu_has_apic )
   90.11 +        return 1;
   90.12 +
   90.13 +    /*
   90.14       * We use this value because we don't trust zero (we think it may just
   90.15       * cause an immediate interrupt). At least this is guaranteed to hold it
   90.16       * off for ages (esp. since the clock ticks on bus clock, not cpu clock!).
   90.17 @@ -1044,13 +1051,6 @@ int reprogram_timer(s_time_t timeout)
   90.18          return 0;
   90.19      }
   90.20  
   90.21 -    /*
   90.22 -     * If we don't have local APIC then we just poll the timer list off the
   90.23 -     * PIT interrupt. Cheesy but good enough to work on eg. VMware :-)
   90.24 -     */
   90.25 -    if ( !cpu_has_apic )
   90.26 -        return 1;
   90.27 -
   90.28      /* conversion to bus units */
   90.29      apic_tmict = (((u64)bus_scale) * expire)>>18;
   90.30  
    91.1 --- a/xen/arch/x86/domain.c	Mon Mar 12 09:43:48 2007 -0600
    91.2 +++ b/xen/arch/x86/domain.c	Mon Mar 12 10:07:08 2007 -0600
    91.3 @@ -350,6 +350,9 @@ int vcpu_initialise(struct vcpu *v)
    91.4      }
    91.5      else
    91.6      {
    91.7 +        /* PV guests by default have a 100Hz ticker. */
    91.8 +        v->periodic_period = MILLISECS(10);
    91.9 +
   91.10          /* PV guests get an emulated PIT too for video BIOSes to use. */
   91.11          if ( !is_idle_domain(d) && (v->vcpu_id == 0) )
   91.12              pit_init(v, cpu_khz);
   91.13 @@ -457,8 +460,10 @@ int arch_domain_create(struct domain *d)
   91.14   fail:
   91.15      free_xenheap_page(d->shared_info);
   91.16  #ifdef __x86_64__
   91.17 -    free_domheap_page(virt_to_page(d->arch.mm_perdomain_l2));
   91.18 -    free_domheap_page(virt_to_page(d->arch.mm_perdomain_l3));
   91.19 +    if ( d->arch.mm_perdomain_l2 )
   91.20 +        free_domheap_page(virt_to_page(d->arch.mm_perdomain_l2));
   91.21 +    if ( d->arch.mm_perdomain_l3 )
   91.22 +        free_domheap_page(virt_to_page(d->arch.mm_perdomain_l3));
   91.23  #endif
   91.24      free_xenheap_pages(d->arch.mm_perdomain_pt, pdpt_order);
   91.25      return rc;
    92.1 --- a/xen/arch/x86/domctl.c	Mon Mar 12 09:43:48 2007 -0600
    92.2 +++ b/xen/arch/x86/domctl.c	Mon Mar 12 10:07:08 2007 -0600
    92.3 @@ -145,6 +145,12 @@ long arch_do_domctl(
    92.4          }
    92.5  
    92.6          arr32 = alloc_xenheap_page();
    92.7 +        if ( !arr32 )
    92.8 +        {
    92.9 +            ret = -ENOMEM;
   92.10 +            put_domain(d);
   92.11 +            break;
   92.12 +        }
   92.13   
   92.14          ret = 0;
   92.15          for ( n = 0; n < num; )
   92.16 @@ -157,7 +163,7 @@ long arch_do_domctl(
   92.17                                          domctl->u.getpageframeinfo2.array,
   92.18                                          n, k) )
   92.19              {
   92.20 -                ret = -EINVAL;
   92.21 +                ret = -EFAULT;
   92.22                  break;
   92.23              }
   92.24       
   92.25 @@ -201,7 +207,7 @@ long arch_do_domctl(
   92.26              if ( copy_to_guest_offset(domctl->u.getpageframeinfo2.array,
   92.27                                        n, arr32, k) )
   92.28              {
   92.29 -                ret = -EINVAL;
   92.30 +                ret = -EFAULT;
   92.31                  break;
   92.32              }
   92.33  
    93.1 --- a/xen/arch/x86/hvm/hvm.c	Mon Mar 12 09:43:48 2007 -0600
    93.2 +++ b/xen/arch/x86/hvm/hvm.c	Mon Mar 12 10:07:08 2007 -0600
    93.3 @@ -146,6 +146,48 @@ void hvm_do_resume(struct vcpu *v)
    93.4      }
    93.5  }
    93.6  
    93.7 +/* Called from the tools when saving a domain to make sure the io
    93.8 + * request-response ring is entirely empty. */
    93.9 +static int hvmop_drain_io(
   93.10 +    XEN_GUEST_HANDLE(xen_hvm_drain_io_t) uop)
   93.11 +{
   93.12 +    struct xen_hvm_drain_io op;
   93.13 +    struct domain *d;
   93.14 +    struct vcpu *v;
   93.15 +    ioreq_t *p;
   93.16 +    int rc;
   93.17 +
   93.18 +    if ( copy_from_guest(&op, uop, 1) )
   93.19 +        return -EFAULT;
   93.20 +
   93.21 +    if ( !IS_PRIV(current->domain) )
   93.22 +        return -EPERM;
   93.23 +
   93.24 +    d = rcu_lock_domain_by_id(op.domid);
   93.25 +    if ( d == NULL )
   93.26 +        return -ESRCH;
   93.27 +
   93.28 +    rc = -EINVAL;
   93.29 +    /* Can't do this to yourself, or to a domain without an ioreq ring */
   93.30 +    if ( d == current->domain || !is_hvm_domain(d) || get_sp(d) == NULL )
   93.31 +        goto out;
   93.32 +
   93.33 +    rc = 0;
   93.34 +
   93.35 +    domain_pause(d);  /* It's not safe to do this to running vcpus */
   93.36 +    for_each_vcpu(d, v)
   93.37 +    {
   93.38 +        p = &get_vio(v->domain, v->vcpu_id)->vp_ioreq;
   93.39 +        if ( p->state == STATE_IORESP_READY )
   93.40 +            hvm_io_assist(v);
   93.41 +    }
   93.42 +    domain_unpause(d);
   93.43 +
   93.44 + out:
   93.45 +    rcu_unlock_domain(d);
   93.46 +    return rc;
   93.47 +}
   93.48 +
   93.49  int hvm_domain_initialise(struct domain *d)
   93.50  {
   93.51      int rc;
   93.52 @@ -161,7 +203,8 @@ int hvm_domain_initialise(struct domain 
   93.53      spin_lock_init(&d->arch.hvm_domain.buffered_io_lock);
   93.54      spin_lock_init(&d->arch.hvm_domain.irq_lock);
   93.55  
   93.56 -    rc = paging_enable(d, PG_SH_enable|PG_refcounts|PG_translate|PG_external);
   93.57 +    /* paging support will be determined inside paging.c */
   93.58 +    rc = paging_enable(d, PG_refcounts|PG_translate|PG_external);
   93.59      if ( rc != 0 )
   93.60          return rc;
   93.61  
   93.62 @@ -379,7 +422,7 @@ void hvm_triple_fault(void)
   93.63   */
   93.64  static int __hvm_copy(void *buf, paddr_t addr, int size, int dir, int virt)
   93.65  {
   93.66 -    unsigned long mfn;
   93.67 +    unsigned long gfn, mfn;
   93.68      char *p;
   93.69      int count, todo;
   93.70  
   93.71 @@ -389,9 +432,11 @@ static int __hvm_copy(void *buf, paddr_t
   93.72          count = min_t(int, PAGE_SIZE - (addr & ~PAGE_MASK), todo);
   93.73  
   93.74          if ( virt )
   93.75 -            mfn = get_mfn_from_gpfn(paging_gva_to_gfn(current, addr));
   93.76 +            gfn = paging_gva_to_gfn(current, addr);
   93.77          else
   93.78 -            mfn = get_mfn_from_gpfn(addr >> PAGE_SHIFT);
   93.79 +            gfn = addr >> PAGE_SHIFT;
   93.80 +        
   93.81 +        mfn = get_mfn_from_gpfn(gfn);
   93.82  
   93.83          if ( mfn == INVALID_MFN )
   93.84              return todo;
   93.85 @@ -399,14 +444,15 @@ static int __hvm_copy(void *buf, paddr_t
   93.86          p = (char *)map_domain_page(mfn) + (addr & ~PAGE_MASK);
   93.87  
   93.88          if ( dir )
   93.89 +        {
   93.90              memcpy(p, buf, count); /* dir == TRUE:  *to* guest */
   93.91 +            mark_dirty(current->domain, mfn);
   93.92 +        }
   93.93          else
   93.94              memcpy(buf, p, count); /* dir == FALSE: *from guest */
   93.95  
   93.96          unmap_domain_page(p);
   93.97          
   93.98 -        mark_dirty(current->domain, mfn);
   93.99 -
  93.100          addr += count;
  93.101          buf  += count;
  93.102          todo -= count;
  93.103 @@ -912,6 +958,12 @@ long do_hvm_op(unsigned long op, XEN_GUE
  93.104              guest_handle_cast(arg, xen_hvm_set_pci_link_route_t));
  93.105          break;
  93.106  
  93.107 +    case HVMOP_drain_io:
  93.108 +        rc = hvmop_drain_io(
  93.109 +            guest_handle_cast(arg, xen_hvm_drain_io_t));
  93.110 +        break;
  93.111 +
  93.112 +
  93.113      default:
  93.114      {
  93.115          gdprintk(XENLOG_WARNING, "Bad HVM op %ld.\n", op);
    94.1 --- a/xen/arch/x86/hvm/rtc.c	Mon Mar 12 09:43:48 2007 -0600
    94.2 +++ b/xen/arch/x86/hvm/rtc.c	Mon Mar 12 10:07:08 2007 -0600
    94.3 @@ -174,6 +174,11 @@ static void rtc_copy_date(RTCState *s)
    94.4  {
    94.5      const struct tm *tm = &s->current_tm;
    94.6  
    94.7 +    if (s->time_offset_seconds != s->pt.vcpu->domain->time_offset_seconds) {
    94.8 +        s->current_tm = gmtime(get_localtime(s->pt.vcpu->domain));
    94.9 +        s->time_offset_seconds = s->pt.vcpu->domain->time_offset_seconds;
   94.10 +    }
   94.11 +
   94.12      s->hw.cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec);
   94.13      s->hw.cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min);
   94.14      if ( s->hw.cmos_data[RTC_REG_B] & RTC_24H )
   94.15 @@ -211,10 +216,16 @@ static int get_days_in_month(int month, 
   94.16  }
   94.17  
   94.18  /* update 'tm' to the next second */
   94.19 -static void rtc_next_second(struct tm *tm)
   94.20 +static void rtc_next_second(RTCState *s)
   94.21  {
   94.22 +    struct tm *tm = &s->current_tm;
   94.23      int days_in_month;
   94.24  
   94.25 +    if (s->time_offset_seconds != s->pt.vcpu->domain->time_offset_seconds) {
   94.26 +        s->current_tm = gmtime(get_localtime(s->pt.vcpu->domain));
   94.27 +        s->time_offset_seconds = s->pt.vcpu->domain->time_offset_seconds;
   94.28 +    }
   94.29 +
   94.30      tm->tm_sec++;
   94.31      if ((unsigned)tm->tm_sec >= 60) {
   94.32          tm->tm_sec = 0;
   94.33 @@ -258,7 +269,7 @@ static void rtc_update_second(void *opaq
   94.34      }
   94.35      else
   94.36      {
   94.37 -        rtc_next_second(&s->current_tm);
   94.38 +        rtc_next_second(s);
   94.39          
   94.40          if ( !(s->hw.cmos_data[RTC_REG_B] & RTC_SET) )
   94.41              s->hw.cmos_data[RTC_REG_A] |= RTC_UIP;
    95.1 --- a/xen/arch/x86/hvm/svm/svm.c	Mon Mar 12 09:43:48 2007 -0600
    95.2 +++ b/xen/arch/x86/hvm/svm/svm.c	Mon Mar 12 10:07:08 2007 -0600
    95.3 @@ -49,6 +49,7 @@
    95.4  #include <public/sched.h>
    95.5  #include <asm/hvm/vpt.h>
    95.6  #include <asm/hvm/trace.h>
    95.7 +#include <asm/hap.h>
    95.8  
    95.9  #define SVM_EXTRA_DEBUG
   95.10  
   95.11 @@ -76,6 +77,10 @@ static void *root_vmcb[NR_CPUS] __read_m
   95.12  /* physical address of above for host VMSAVE/VMLOAD */
   95.13  u64 root_vmcb_pa[NR_CPUS] __read_mostly;
   95.14  
   95.15 +/* hardware assisted paging bits */
   95.16 +extern int opt_hap_enabled;
   95.17 +extern int hap_capable_system;
   95.18 +
   95.19  static inline void svm_inject_exception(struct vcpu *v, int trap, 
   95.20                                          int ev, int error_code)
   95.21  {
   95.22 @@ -102,22 +107,10 @@ static inline void svm_inject_exception(
   95.23  static void stop_svm(void)
   95.24  {
   95.25      u32 eax, edx;    
   95.26 -    int cpu = smp_processor_id();
   95.27 -
   95.28      /* We turn off the EFER_SVME bit. */
   95.29      rdmsr(MSR_EFER, eax, edx);
   95.30      eax &= ~EFER_SVME;
   95.31      wrmsr(MSR_EFER, eax, edx);
   95.32 - 
   95.33 -    /* release the HSA */
   95.34 -    free_host_save_area(hsa[cpu]);
   95.35 -    hsa[cpu] = NULL;
   95.36 -    wrmsr(MSR_K8_VM_HSAVE_PA, 0, 0 );
   95.37 -
   95.38 -    /* free up the root vmcb */
   95.39 -    free_vmcb(root_vmcb[cpu]);
   95.40 -    root_vmcb[cpu] = NULL;
   95.41 -    root_vmcb_pa[cpu] = 0;
   95.42  }
   95.43  
   95.44  static void svm_store_cpu_guest_regs(
   95.45 @@ -240,7 +233,9 @@ static inline int long_mode_do_msr_write
   95.46          /*
   95.47           * Check for EFER.LME transitions from 0->1 or 1->0.  Do the
   95.48           * sanity checks and then make sure that both EFER.LME and
   95.49 -         * EFER.LMA are cleared.
   95.50 +         * EFER.LMA are cleared. (EFER.LME can't be set in the vmcb
   95.51 +         * until the guest also sets CR0.PG, since even if the guest has
   95.52 +         * paging "disabled", the vmcb's CR0 always has PG set.)
   95.53           */
   95.54          if ( (msr_content & EFER_LME) && !svm_lme_is_set(v) )
   95.55          {
   95.56 @@ -269,10 +264,12 @@ static inline int long_mode_do_msr_write
   95.57  
   95.58              vmcb->efer &= ~(EFER_LME | EFER_LMA);
   95.59          }
   95.60 +
   95.61  #endif /* __x86_64__ */
   95.62  
   95.63          /* update the guest EFER's shadow with the intended value */
   95.64          v->arch.hvm_svm.cpu_shadow_efer = msr_content;
   95.65 +
   95.66          break;
   95.67  
   95.68  #ifdef __x86_64__
   95.69 @@ -902,6 +899,10 @@ static void arch_svm_do_launch(struct vc
   95.70  {
   95.71      svm_do_launch(v);
   95.72  
   95.73 +    if ( paging_mode_hap(v->domain) ) {
   95.74 +        v->arch.hvm_svm.vmcb->h_cr3 = pagetable_get_paddr(v->domain->arch.phys_table);
   95.75 +    }
   95.76 +
   95.77      if ( v->vcpu_id != 0 )
   95.78      {
   95.79          cpu_user_regs_t *regs = &current->arch.guest_context.user_regs;
   95.80 @@ -1008,6 +1009,21 @@ static struct hvm_function_table svm_fun
   95.81      .event_injection_faulted = svm_event_injection_faulted
   95.82  };
   95.83  
   95.84 +void svm_npt_detect(void)
   95.85 +{
   95.86 +    u32 eax, ebx, ecx, edx;
   95.87 +
   95.88 +    /* check CPUID for nested paging support */
   95.89 +    cpuid(0x8000000A, &eax, &ebx, &ecx, &edx);
   95.90 +    if ( edx & 0x01 ) { /* nested paging */
   95.91 +        hap_capable_system = 1;
   95.92 +    }
   95.93 +    else if ( opt_hap_enabled ) {
   95.94 +        printk(" nested paging is not supported by this CPU.\n");
   95.95 +        hap_capable_system = 0; /* no nested paging, we disable flag. */
   95.96 +    }
   95.97 +}
   95.98 +
   95.99  int start_svm(void)
  95.100  {
  95.101      u32 eax, ecx, edx;
  95.102 @@ -1030,22 +1046,26 @@ int start_svm(void)
  95.103          return 0;
  95.104      }
  95.105  
  95.106 -    if (!(hsa[cpu] = alloc_host_save_area()))
  95.107 -        return 0;
  95.108 +    if (!hsa[cpu])
  95.109 +        if (!(hsa[cpu] = alloc_host_save_area()))
  95.110 +            return 0;
  95.111      
  95.112      rdmsr(MSR_EFER, eax, edx);
  95.113      eax |= EFER_SVME;
  95.114      wrmsr(MSR_EFER, eax, edx);
  95.115      printk("AMD SVM Extension is enabled for cpu %d.\n", cpu );
  95.116  
  95.117 +    svm_npt_detect();
  95.118 +
  95.119      /* Initialize the HSA for this core */
  95.120      phys_hsa = (u64) virt_to_maddr(hsa[cpu]);
  95.121      phys_hsa_lo = (u32) phys_hsa;
  95.122      phys_hsa_hi = (u32) (phys_hsa >> 32);    
  95.123      wrmsr(MSR_K8_VM_HSAVE_PA, phys_hsa_lo, phys_hsa_hi);
  95.124    
  95.125 -    if (!(root_vmcb[cpu] = alloc_vmcb())) 
  95.126 -        return 0;
  95.127 +    if (!root_vmcb[cpu])
  95.128 +        if (!(root_vmcb[cpu] = alloc_vmcb())) 
  95.129 +            return 0;
  95.130      root_vmcb_pa[cpu] = virt_to_maddr(root_vmcb[cpu]);
  95.131  
  95.132      if (cpu == 0)
  95.133 @@ -1074,6 +1094,18 @@ void arch_svm_do_resume(struct vcpu *v)
  95.134      }
  95.135  }
  95.136  
  95.137 +static int svm_do_nested_pgfault(paddr_t gpa, struct cpu_user_regs *regs)
  95.138 +{
  95.139 +    if (mmio_space(gpa)) {
  95.140 +        handle_mmio(gpa);
  95.141 +        return 1;
  95.142 +    }
  95.143 +
  95.144 +    /* We should not reach here. Otherwise, P2M table is not correct.*/
  95.145 +    return 0;
  95.146 +}
  95.147 +
  95.148 +
  95.149  static int svm_do_page_fault(unsigned long va, struct cpu_user_regs *regs) 
  95.150  {
  95.151      HVM_DBG_LOG(DBG_LEVEL_VMMU, 
  95.152 @@ -1700,6 +1732,52 @@ static void svm_io_instruction(struct vc
  95.153      }
  95.154  }
  95.155  
  95.156 +static int npt_set_cr0(unsigned long value) 
  95.157 +{
  95.158 +    struct vcpu *v = current;
  95.159 +    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
  95.160 +  
  95.161 +    ASSERT(vmcb);
  95.162 +
  95.163 +    /* ET is reserved and should be always be 1*/
  95.164 +    value |= X86_CR0_ET;
  95.165 +
  95.166 +    /* Check whether the guest is about to turn on long mode. 
  95.167 +     * If it is, set EFER.LME and EFER.LMA.  Update the shadow EFER.LMA
  95.168 +     * bit too, so svm_long_mode_enabled() will work.
  95.169 +     */
  95.170 +    if ( (value & X86_CR0_PG) && svm_lme_is_set(v) &&
  95.171 +         (vmcb->cr4 & X86_CR4_PAE) && (vmcb->cr0 & X86_CR0_PE) )
  95.172 +    {
  95.173 +        v->arch.hvm_svm.cpu_shadow_efer |= EFER_LMA;
  95.174 +        vmcb->efer |= EFER_LMA | EFER_LME;
  95.175 +    }
  95.176 +
  95.177 +    /* Whenever CR0.PG is cleared under long mode, LMA will be cleared 
  95.178 +     * immediatly. We emulate this process for svm_long_mode_enabled().
  95.179 +     */
  95.180 +    if ( (value & (X86_CR0_PE | X86_CR0_PG)) == X86_CR0_PE )
  95.181 +    {
  95.182 +        if ( svm_long_mode_enabled(v) )
  95.183 +        {
  95.184 +            v->arch.hvm_svm.cpu_shadow_efer &= ~EFER_LMA;
  95.185 +        }
  95.186 +    }
  95.187 +    
  95.188 +    vmcb->cr0 = value | X86_CR0_WP;
  95.189 +    v->arch.hvm_svm.cpu_shadow_cr0 = value;
  95.190 +
  95.191 +    /* TS cleared? Then initialise FPU now. */
  95.192 +    if ( !(value & X86_CR0_TS) ) {
  95.193 +        setup_fpu(v);
  95.194 +        vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM;
  95.195 +    }
  95.196 +    
  95.197 +    paging_update_paging_modes(v);
  95.198 +    
  95.199 +    return 1;
  95.200 +}
  95.201 +
  95.202  static int svm_set_cr0(unsigned long value)
  95.203  {
  95.204      struct vcpu *v = current;
  95.205 @@ -1797,6 +1875,85 @@ static int svm_set_cr0(unsigned long val
  95.206      return 1;
  95.207  }
  95.208  
  95.209 +//
  95.210 +// nested paging functions
  95.211 +//
  95.212 +
  95.213 +static int npt_mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
  95.214 +{  
  95.215 +    unsigned long value;
  95.216 +    struct vcpu *v = current;
  95.217 +    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
  95.218 +    struct vlapic *vlapic = vcpu_vlapic(v);
  95.219 +
  95.220 +    ASSERT(vmcb);
  95.221 +
  95.222 +    value = get_reg(gpreg, regs, vmcb);
  95.223 +
  95.224 +    switch (cr) {
  95.225 +    case 0:
  95.226 +        return npt_set_cr0(value);
  95.227 +
  95.228 +    case 3:
  95.229 +        vmcb->cr3 = value;
  95.230 +        v->arch.hvm_svm.cpu_cr3 = value;
  95.231 +        break;
  95.232 +
  95.233 +    case 4: /* CR4 */
  95.234 +        vmcb->cr4 = value;
  95.235 +        v->arch.hvm_svm.cpu_shadow_cr4 = value;
  95.236 +        paging_update_paging_modes(v);
  95.237 +        break;
  95.238 +
  95.239 +    case 8:
  95.240 +        vlapic_set_reg(vlapic, APIC_TASKPRI, ((value & 0x0F) << 4));
  95.241 +        vmcb->vintr.fields.tpr = value & 0x0F;
  95.242 +        break;
  95.243 +
  95.244 +    default:
  95.245 +        gdprintk(XENLOG_ERR, "invalid cr: %d\n", cr);
  95.246 +        domain_crash(v->domain);
  95.247 +        return 0;
  95.248 +    }
  95.249 +    
  95.250 +    return 1;
  95.251 +}
  95.252 +
  95.253 +static void npt_mov_from_cr(int cr, int gp, struct cpu_user_regs *regs)
  95.254 +{
  95.255 +    unsigned long value = 0;
  95.256 +    struct vcpu *v = current;
  95.257 +    struct vmcb_struct *vmcb;
  95.258 +    struct vlapic *vlapic = vcpu_vlapic(v);
  95.259 +
  95.260 +    vmcb = v->arch.hvm_svm.vmcb;
  95.261 +    ASSERT(vmcb);
  95.262 +
  95.263 +    switch(cr) {
  95.264 +    case 0:
  95.265 +        value = (unsigned long) v->arch.hvm_svm.cpu_shadow_cr0;
  95.266 +        break;
  95.267 +    case 2:
  95.268 +        value = vmcb->cr2;
  95.269 +        break;
  95.270 +    case 3:
  95.271 +        value = (unsigned long) v->arch.hvm_svm.cpu_cr3;
  95.272 +        break;
  95.273 +    case 4:
  95.274 +        value = (unsigned long) v->arch.hvm_svm.cpu_shadow_cr4;
  95.275 +       break;
  95.276 +    case 8:
  95.277 +        value = (unsigned long)vlapic_get_reg(vlapic, APIC_TASKPRI);
  95.278 +        value = (value & 0xF0) >> 4;
  95.279 +        break;
  95.280 +    default:
  95.281 +        domain_crash(v->domain);
  95.282 +        return;
  95.283 +    }
  95.284 +    
  95.285 +    set_reg(gp, value, regs, vmcb);
  95.286 +}
  95.287 +
  95.288  /*
  95.289   * Read from control registers. CR0 and CR4 are read from the shadow.
  95.290   */
  95.291 @@ -2043,12 +2200,18 @@ static int svm_cr_access(struct vcpu *v,
  95.292      {
  95.293      case INSTR_MOV2CR:
  95.294          gpreg = decode_src_reg(prefix, buffer[index+2]);
  95.295 -        result = mov_to_cr(gpreg, cr, regs);
  95.296 +        if ( paging_mode_hap(v->domain) )
  95.297 +            result = npt_mov_to_cr(gpreg, cr, regs);
  95.298 +        else
  95.299 +            result = mov_to_cr(gpreg, cr, regs);
  95.300          break;
  95.301  
  95.302      case INSTR_MOVCR2:
  95.303          gpreg = decode_src_reg(prefix, buffer[index+2]);
  95.304 -        mov_from_cr(cr, gpreg, regs);
  95.305 +        if ( paging_mode_hap(v->domain) )
  95.306 +            npt_mov_from_cr(cr, gpreg, regs);
  95.307 +        else
  95.308 +            mov_from_cr(cr, gpreg, regs);
  95.309          break;
  95.310  
  95.311      case INSTR_CLTS:
  95.312 @@ -2075,7 +2238,10 @@ static int svm_cr_access(struct vcpu *v,
  95.313          if (svm_dbg_on)
  95.314              printk("CR0-LMSW CR0 - New value=%lx\n", value);
  95.315  
  95.316 -        result = svm_set_cr0(value);
  95.317 +        if ( paging_mode_hap(v->domain) )
  95.318 +            result = npt_set_cr0(value);
  95.319 +        else
  95.320 +            result = svm_set_cr0(value);
  95.321          break;
  95.322  
  95.323      case INSTR_SMSW:
  95.324 @@ -2359,6 +2525,11 @@ static int svm_do_vmmcall_reset_to_realm
  95.325      vmcb->cr4 = SVM_CR4_HOST_MASK;
  95.326      v->arch.hvm_svm.cpu_shadow_cr4 = 0;
  95.327  
  95.328 +    if ( paging_mode_hap(v->domain) ) {
  95.329 +        vmcb->cr0 = v->arch.hvm_svm.cpu_shadow_cr0;
  95.330 +        vmcb->cr4 = v->arch.hvm_svm.cpu_shadow_cr4;
  95.331 +    }
  95.332 +
  95.333      /* This will jump to ROMBIOS */
  95.334      vmcb->rip = 0xFFF0;
  95.335  
  95.336 @@ -3042,6 +3213,15 @@ asmlinkage void svm_vmexit_handler(struc
  95.337          hvm_triple_fault();
  95.338          break;
  95.339  
  95.340 +    case VMEXIT_NPF:
  95.341 +    {
  95.342 +        regs->error_code = vmcb->exitinfo1;
  95.343 +        if ( !svm_do_nested_pgfault(vmcb->exitinfo2, regs) ) {
  95.344 +            domain_crash(v->domain);
  95.345 +        }
  95.346 +        break;
  95.347 +    }
  95.348 +
  95.349      default:
  95.350      exit_and_crash:
  95.351          gdprintk(XENLOG_ERR, "unexpected VMEXIT: exit reason = 0x%x, "
    96.1 --- a/xen/arch/x86/hvm/svm/vmcb.c	Mon Mar 12 09:43:48 2007 -0600
    96.2 +++ b/xen/arch/x86/hvm/svm/vmcb.c	Mon Mar 12 10:07:08 2007 -0600
    96.3 @@ -79,11 +79,6 @@ struct host_save_area *alloc_host_save_a
    96.4      return hsa;
    96.5  }
    96.6  
    96.7 -void free_host_save_area(struct host_save_area *hsa)
    96.8 -{
    96.9 -    free_xenheap_page(hsa);
   96.10 -}
   96.11 -
   96.12  static int construct_vmcb(struct vcpu *v)
   96.13  {
   96.14      struct arch_svm_struct *arch_svm = &v->arch.hvm_svm;
   96.15 @@ -201,6 +196,13 @@ static int construct_vmcb(struct vcpu *v
   96.16  
   96.17      arch_svm->vmcb->exception_intercepts = MONITOR_DEFAULT_EXCEPTION_BITMAP;
   96.18  
   96.19 +    if ( paging_mode_hap(v->domain) ) {
   96.20 +        vmcb->cr0 = arch_svm->cpu_shadow_cr0;
   96.21 +        vmcb->np_enable = 1; /* enable nested paging */
   96.22 +        vmcb->g_pat = 0x0007040600070406ULL; /* guest PAT */
   96.23 +        vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_PG;
   96.24 +    }
   96.25 +
   96.26      return 0;
   96.27  }
   96.28  
   96.29 @@ -310,7 +312,8 @@ void svm_dump_vmcb(const char *from, str
   96.30      printk("KernGSBase = 0x%016llx PAT = 0x%016llx \n", 
   96.31             (unsigned long long) vmcb->kerngsbase,
   96.32             (unsigned long long) vmcb->g_pat);
   96.33 -    
   96.34 +    printk("H_CR3 = 0x%016llx\n", (unsigned long long)vmcb->h_cr3);
   96.35 +
   96.36      /* print out all the selectors */
   96.37      svm_dump_sel("CS", &vmcb->cs);
   96.38      svm_dump_sel("DS", &vmcb->ds);
    97.1 --- a/xen/arch/x86/mm/Makefile	Mon Mar 12 09:43:48 2007 -0600
    97.2 +++ b/xen/arch/x86/mm/Makefile	Mon Mar 12 10:07:08 2007 -0600
    97.3 @@ -1,4 +1,5 @@
    97.4  subdir-y += shadow
    97.5 +subdir-y += hap
    97.6  
    97.7  obj-y += paging.o
    97.8  obj-y += p2m.o
    98.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    98.2 +++ b/xen/arch/x86/mm/hap/Makefile	Mon Mar 12 10:07:08 2007 -0600
    98.3 @@ -0,0 +1,2 @@
    98.4 +obj-y += hap.o
    98.5 +obj-y += support.o
    99.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    99.2 +++ b/xen/arch/x86/mm/hap/hap.c	Mon Mar 12 10:07:08 2007 -0600
    99.3 @@ -0,0 +1,708 @@
    99.4 +/******************************************************************************
    99.5 + * arch/x86/mm/hap/hap.c
    99.6 + *
    99.7 + * hardware assisted paging
    99.8 + * Copyright (c) 2007 Advanced Micro Devices (Wei Huang)
    99.9 + * Parts of this code are Copyright (c) 2007 by XenSource Inc.
   99.10 + *
   99.11 + * This program is free software; you can redistribute it and/or modify
   99.12 + * it under the terms of the GNU General Public License as published by
   99.13 + * the Free Software Foundation; either version 2 of the License, or
   99.14 + * (at your option) any later version.
   99.15 + *
   99.16 + * This program is distributed in the hope that it will be useful,
   99.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   99.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   99.19 + * GNU General Public License for more details.
   99.20 + *
   99.21 + * You should have received a copy of the GNU General Public License
   99.22 + * along with this program; if not, write to the Free Software
   99.23 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   99.24 + */
   99.25 +
   99.26 +#include <xen/config.h>
   99.27 +#include <xen/types.h>
   99.28 +#include <xen/mm.h>
   99.29 +#include <xen/trace.h>
   99.30 +#include <xen/sched.h>
   99.31 +#include <xen/perfc.h>
   99.32 +#include <xen/irq.h>
   99.33 +#include <xen/domain_page.h>
   99.34 +#include <xen/guest_access.h>
   99.35 +#include <xen/keyhandler.h>
   99.36 +#include <asm/event.h>
   99.37 +#include <asm/page.h>
   99.38 +#include <asm/current.h>
   99.39 +#include <asm/flushtlb.h>
   99.40 +#include <asm/shared.h>
   99.41 +#include <asm/hap.h>
   99.42 +#include <asm/paging.h>
   99.43 +#include <asm/domain.h>
   99.44 +
   99.45 +#include "private.h"
   99.46 +
   99.47 +/* Override macros from asm/page.h to make them work with mfn_t */
   99.48 +#undef mfn_to_page
   99.49 +#define mfn_to_page(_m) (frame_table + mfn_x(_m))
   99.50 +#undef mfn_valid
   99.51 +#define mfn_valid(_mfn) (mfn_x(_mfn) < max_page)
   99.52 +#undef page_to_mfn
   99.53 +#define page_to_mfn(_pg) (_mfn((_pg) - frame_table))
   99.54 +
   99.55 +/************************************************/
   99.56 +/*             HAP SUPPORT FUNCTIONS            */
   99.57 +/************************************************/
   99.58 +mfn_t hap_alloc(struct domain *d, unsigned long backpointer)
   99.59 +{
   99.60 +    struct page_info *sp = NULL;
   99.61 +    void *p;
   99.62 +
   99.63 +    ASSERT(hap_locked_by_me(d));
   99.64 +
   99.65 +    sp = list_entry(d->arch.paging.hap.freelists.next, struct page_info, list);
   99.66 +    list_del(&sp->list);
   99.67 +    d->arch.paging.hap.free_pages -= 1;
   99.68 +
   99.69 +    /* Now safe to clear the page for reuse */
   99.70 +    p = hap_map_domain_page(page_to_mfn(sp));
   99.71 +    ASSERT(p != NULL);
   99.72 +    clear_page(p);
   99.73 +    hap_unmap_domain_page(p);
   99.74 +
   99.75 +    return page_to_mfn(sp);
   99.76 +}
   99.77 +
   99.78 +void hap_free(struct domain *d, mfn_t smfn)
   99.79 +{
   99.80 +    struct page_info *sp = mfn_to_page(smfn); 
   99.81 +
   99.82 +    ASSERT(hap_locked_by_me(d));
   99.83 +
   99.84 +    d->arch.paging.hap.free_pages += 1;
   99.85 +    list_add_tail(&sp->list, &d->arch.paging.hap.freelists);
   99.86 +}
   99.87 +
   99.88 +static int hap_alloc_p2m_pages(struct domain *d)
   99.89 +{
   99.90 +    struct page_info *pg;
   99.91 +
   99.92 +    ASSERT(hap_locked_by_me(d));
   99.93 +
   99.94 +    pg = mfn_to_page(hap_alloc(d, 0));
   99.95 +    d->arch.paging.hap.p2m_pages += 1;
   99.96 +    d->arch.paging.hap.total_pages -= 1;
   99.97 +    
   99.98 +    page_set_owner(pg, d);
   99.99 +    pg->count_info = 1;
  99.100 +    list_add_tail(&pg->list, &d->arch.paging.hap.p2m_freelist);
  99.101 +
  99.102 +    return 1;
  99.103 +}
  99.104 +
  99.105 +struct page_info * hap_alloc_p2m_page(struct domain *d)
  99.106 +{
  99.107 +    struct list_head *entry;
  99.108 +    struct page_info *pg;
  99.109 +    mfn_t mfn;
  99.110 +    void *p;
  99.111 +
  99.112 +    hap_lock(d);
  99.113 +    
  99.114 +    if ( list_empty(&d->arch.paging.hap.p2m_freelist) && 
  99.115 +         !hap_alloc_p2m_pages(d) ) {
  99.116 +        hap_unlock(d);
  99.117 +        return NULL;
  99.118 +    }
  99.119 +    entry = d->arch.paging.hap.p2m_freelist.next;
  99.120 +    list_del(entry);
  99.121 +    
  99.122 +    hap_unlock(d);
  99.123 +
  99.124 +    pg = list_entry(entry, struct page_info, list);
  99.125 +    mfn = page_to_mfn(pg);
  99.126 +    p = hap_map_domain_page(mfn);
  99.127 +    clear_page(p);
  99.128 +    hap_unmap_domain_page(p);
  99.129 +
  99.130 +    return pg;
  99.131 +}
  99.132 +
  99.133 +void hap_free_p2m_page(struct domain *d, struct page_info *pg)
  99.134 +{
  99.135 +    ASSERT(page_get_owner(pg) == d);
  99.136 +    /* Should have just the one ref we gave it in alloc_p2m_page() */
  99.137 +    if ( (pg->count_info & PGC_count_mask) != 1 ) {
  99.138 +        HAP_ERROR("Odd p2m page count c=%#x t=%"PRtype_info"\n",
  99.139 +                  pg->count_info, pg->u.inuse.type_info);
  99.140 +    }
  99.141 +    /* Free should not decrement domain's total allocation, since 
  99.142 +     * these pages were allocated without an owner. */
  99.143 +    page_set_owner(pg, NULL); 
  99.144 +    free_domheap_pages(pg, 0);
  99.145 +    d->arch.paging.hap.p2m_pages--;
  99.146 +}
  99.147 +
  99.148 +/* Return the size of the pool, rounded up to the nearest MB */
  99.149 +static unsigned int
  99.150 +hap_get_allocation(struct domain *d)
  99.151 +{
  99.152 +    unsigned int pg = d->arch.paging.hap.total_pages;
  99.153 +
  99.154 +    HERE_I_AM;
  99.155 +    return ((pg >> (20 - PAGE_SHIFT))
  99.156 +            + ((pg & ((1 << (20 - PAGE_SHIFT)) - 1)) ? 1 : 0));
  99.157 +}
  99.158 +
  99.159 +/* Set the pool of pages to the required number of pages.
  99.160 + * Returns 0 for success, non-zero for failure. */
  99.161 +static unsigned int
  99.162 +hap_set_allocation(struct domain *d, unsigned int pages, int *preempted)
  99.163 +{
  99.164 +    struct page_info *sp;
  99.165 +
  99.166 +    ASSERT(hap_locked_by_me(d));
  99.167 +
  99.168 +    while ( d->arch.paging.hap.total_pages != pages ) {
  99.169 +        if ( d->arch.paging.hap.total_pages < pages ) {
  99.170 +            /* Need to allocate more memory from domheap */
  99.171 +            sp = alloc_domheap_pages(NULL, 0, 0);
  99.172 +            if ( sp == NULL ) {
  99.173 +                HAP_PRINTK("failed to allocate hap pages.\n");
  99.174 +                return -ENOMEM;
  99.175 +            }
  99.176 +            d->arch.paging.hap.free_pages += 1;
  99.177 +            d->arch.paging.hap.total_pages += 1;
  99.178 +            list_add_tail(&sp->list, &d->arch.paging.hap.freelists);
  99.179 +        }
  99.180 +        else if ( d->arch.paging.hap.total_pages > pages ) {
  99.181 +            /* Need to return memory to domheap */
  99.182 +            ASSERT(!list_empty(&d->arch.paging.hap.freelists));
  99.183 +            sp = list_entry(d->arch.paging.hap.freelists.next,
  99.184 +                            struct page_info, list);
  99.185 +            list_del(&sp->list);
  99.186 +            d->arch.paging.hap.free_pages -= 1;
  99.187 +            d->arch.paging.hap.total_pages -= 1;
  99.188 +            free_domheap_pages(sp, 0);
  99.189 +        }
  99.190 +        
  99.191 +        /* Check to see if we need to yield and try again */
  99.192 +        if ( preempted && hypercall_preempt_check() ) {
  99.193 +            *preempted = 1;
  99.194 +            return 0;
  99.195 +        }
  99.196 +    }
  99.197 +
  99.198 +    return 0;
  99.199 +}
  99.200 +
  99.201 +#if CONFIG_PAGING_LEVELS == 4
  99.202 +void hap_install_xen_entries_in_l4(struct vcpu *v, mfn_t gl4mfn, mfn_t sl4mfn)
  99.203 +{
  99.204 +    struct domain *d = v->domain;
  99.205 +    l4_pgentry_t *sl4e;
  99.206 +
  99.207 +    sl4e = hap_map_domain_page(sl4mfn);
  99.208 +    ASSERT(sl4e != NULL);
  99.209 +
  99.210 +    /* Copy the common Xen mappings from the idle domain */
  99.211 +    memcpy(&sl4e[ROOT_PAGETABLE_FIRST_XEN_SLOT],
  99.212 +           &idle_pg_table[ROOT_PAGETABLE_FIRST_XEN_SLOT],
  99.213 +           ROOT_PAGETABLE_XEN_SLOTS * sizeof(l4_pgentry_t));
  99.214 +
  99.215 +    /* Install the per-domain mappings for this domain */
  99.216 +    sl4e[l4_table_offset(PERDOMAIN_VIRT_START)] =
  99.217 +        l4e_from_pfn(mfn_x(page_to_mfn(virt_to_page(d->arch.mm_perdomain_l3))),
  99.218 +                     __PAGE_HYPERVISOR);
  99.219 +
  99.220 +    sl4e[l4_table_offset(LINEAR_PT_VIRT_START)] =
  99.221 +        l4e_from_pfn(mfn_x(gl4mfn), __PAGE_HYPERVISOR);
  99.222 +
  99.223 +    /* install domain-specific P2M table */
  99.224 +    sl4e[l4_table_offset(RO_MPT_VIRT_START)] =
  99.225 +        l4e_from_pfn(mfn_x(pagetable_get_mfn(d->arch.phys_table)),
  99.226 +                     __PAGE_HYPERVISOR);
  99.227 +
  99.228 +    hap_unmap_domain_page(sl4e);
  99.229 +}
  99.230 +#endif /* CONFIG_PAGING_LEVELS == 4 */
  99.231 +
  99.232 +#if CONFIG_PAGING_LEVELS == 3
  99.233 +void hap_install_xen_entries_in_l2h(struct vcpu *v, mfn_t sl2hmfn)
  99.234 +{
  99.235 +    struct domain *d = v->domain;
  99.236 +    l2_pgentry_t *sl2e;
  99.237 +
  99.238 +    int i;
  99.239 +
  99.240 +    sl2e = hap_map_domain_page(sl2hmfn);
  99.241 +    ASSERT(sl2e != NULL);
  99.242 +    
  99.243 +    /* Copy the common Xen mappings from the idle domain */
  99.244 +    memcpy(&sl2e[L2_PAGETABLE_FIRST_XEN_SLOT & (L2_PAGETABLE_ENTRIES-1)],
  99.245 +           &idle_pg_table_l2[L2_PAGETABLE_FIRST_XEN_SLOT],
  99.246 +           L2_PAGETABLE_XEN_SLOTS * sizeof(l2_pgentry_t));
  99.247 +
  99.248 +    /* Install the per-domain mappings for this domain */
  99.249 +    for ( i = 0; i < PDPT_L2_ENTRIES; i++ )
  99.250 +        sl2e[l2_table_offset(PERDOMAIN_VIRT_START) + i] =
  99.251 +            l2e_from_pfn(
  99.252 +                         mfn_x(page_to_mfn(virt_to_page(d->arch.mm_perdomain_pt) + i)),
  99.253 +                         __PAGE_HYPERVISOR);
  99.254 +    
  99.255 +    for ( i = 0; i < HAP_L3_PAGETABLE_ENTRIES; i++ )
  99.256 +        sl2e[l2_table_offset(LINEAR_PT_VIRT_START) + i] =
  99.257 +            l2e_empty();
  99.258 +
  99.259 +    if ( paging_mode_translate(d) )
  99.260 +    {
  99.261 +        /* Install the domain-specific p2m table */
  99.262 +        l3_pgentry_t *p2m;
  99.263 +        ASSERT(pagetable_get_pfn(d->arch.phys_table) != 0);
  99.264 +        p2m = hap_map_domain_page(pagetable_get_mfn(d->arch.phys_table));
  99.265 +        for ( i = 0; i < MACHPHYS_MBYTES>>1; i++ )
  99.266 +        {
  99.267 +            sl2e[l2_table_offset(RO_MPT_VIRT_START) + i] =
  99.268 +                (l3e_get_flags(p2m[i]) & _PAGE_PRESENT)
  99.269 +                ? l2e_from_pfn(mfn_x(_mfn(l3e_get_pfn(p2m[i]))),
  99.270 +                                      __PAGE_HYPERVISOR)
  99.271 +                : l2e_empty();
  99.272 +        }
  99.273 +        hap_unmap_domain_page(p2m);
  99.274 +    }
  99.275 +
  99.276 +    hap_unmap_domain_page(sl2e);
  99.277 +}
  99.278 +#endif
  99.279 +
  99.280 +#if CONFIG_PAGING_LEVELS == 2
  99.281 +void hap_install_xen_entries_in_l2(struct vcpu *v, mfn_t gl2mfn, mfn_t sl2mfn)
  99.282 +{
  99.283 +    struct domain *d = v->domain;
  99.284 +    l2_pgentry_t *sl2e;
  99.285 +    int i;
  99.286 +
  99.287 +    sl2e = hap_map_domain_page(sl2mfn);
  99.288 +    ASSERT(sl2e != NULL);
  99.289 +    
  99.290 +    /* Copy the common Xen mappings from the idle domain */
  99.291 +    memcpy(&sl2e[L2_PAGETABLE_FIRST_XEN_SLOT],
  99.292 +           &idle_pg_table[L2_PAGETABLE_FIRST_XEN_SLOT],
  99.293 +           L2_PAGETABLE_XEN_SLOTS * sizeof(l2_pgentry_t));
  99.294 +
  99.295 +    /* Install the per-domain mappings for this domain */
  99.296 +    for ( i = 0; i < PDPT_L2_ENTRIES; i++ )
  99.297 +        sl2e[l2_table_offset(PERDOMAIN_VIRT_START) + i] =
  99.298 +            l2e_from_pfn(
  99.299 +                mfn_x(page_to_mfn(virt_to_page(d->arch.mm_perdomain_pt) + i)),
  99.300 +                __PAGE_HYPERVISOR);
  99.301 +
  99.302 +
  99.303 +    sl2e[l2_table_offset(LINEAR_PT_VIRT_START)] =
  99.304 +        l2e_from_pfn(mfn_x(gl2mfn), __PAGE_HYPERVISOR);
  99.305 +
  99.306 +    /* install domain-specific P2M table */
  99.307 +    sl2e[l2_table_offset(RO_MPT_VIRT_START)] =
  99.308 +        l2e_from_pfn(mfn_x(pagetable_get_mfn(d->arch.phys_table)),
  99.309 +                            __PAGE_HYPERVISOR);
  99.310 +
  99.311 +    hap_unmap_domain_page(sl2e);
  99.312 +}
  99.313 +#endif
  99.314 +
  99.315 +mfn_t hap_make_monitor_table(struct vcpu *v)
  99.316 +{
  99.317 +    struct domain *d = v->domain;
  99.318 +
  99.319 +    ASSERT(pagetable_get_pfn(v->arch.monitor_table) == 0);
  99.320 +
  99.321 +#if CONFIG_PAGING_LEVELS == 4
  99.322 +    {
  99.323 +        mfn_t m4mfn;
  99.324 +        m4mfn = hap_alloc(d, 0);
  99.325 +        hap_install_xen_entries_in_l4(v, m4mfn, m4mfn);
  99.326 +        return m4mfn;
  99.327 +    }
  99.328 +#elif CONFIG_PAGING_LEVELS == 3
  99.329 +    {
  99.330 +        mfn_t m3mfn, m2mfn; 
  99.331 +        l3_pgentry_t *l3e;
  99.332 +        l2_pgentry_t *l2e;
  99.333 +        int i;
  99.334 +
  99.335 +        m3mfn = hap_alloc(d, 0);
  99.336 +
  99.337 +        /* Install a monitor l2 table in slot 3 of the l3 table.
  99.338 +         * This is used for all Xen entries, including linear maps
  99.339 +         */
  99.340 +        m2mfn = hap_alloc(d, 0);
  99.341 +        l3e = hap_map_domain_page(m3mfn);
  99.342 +        l3e[3] = l3e_from_pfn(mfn_x(m2mfn), _PAGE_PRESENT);
  99.343 +        hap_install_xen_entries_in_l2h(v, m2mfn);
  99.344 +        /* Install the monitor's own linear map */
  99.345 +        l2e = hap_map_domain_page(m2mfn);
  99.346 +        for ( i = 0; i < L3_PAGETABLE_ENTRIES; i++ )
  99.347 +            l2e[l2_table_offset(LINEAR_PT_VIRT_START) + i] =
  99.348 +                (l3e_get_flags(l3e[i]) & _PAGE_PRESENT) 
  99.349 +                ? l2e_from_pfn(l3e_get_pfn(l3e[i]), __PAGE_HYPERVISOR) 
  99.350 +                : l2e_empty();
  99.351 +        hap_unmap_domain_page(l2e);
  99.352 +        hap_unmap_domain_page(l3e);
  99.353 +
  99.354 +        HAP_PRINTK("new monitor table: %#lx\n", mfn_x(m3mfn));
  99.355 +        return m3mfn;
  99.356 +    }
  99.357 +#else
  99.358 +    {
  99.359 +        mfn_t m2mfn;
  99.360 +        
  99.361 +        m2mfn = hap_alloc(d, 0);
  99.362 +        hap_install_xen_entries_in_l2(v, m2mfn, m2mfn);
  99.363 +    
  99.364 +        return m2mfn;
  99.365 +    }
  99.366 +#endif
  99.367 +}
  99.368 +
  99.369 +void hap_destroy_monitor_table(struct vcpu* v, mfn_t mmfn)
  99.370 +{
  99.371 +    struct domain *d = v->domain;
  99.372 +
  99.373 +#if CONFIG_PAGING_LEVELS == 4
  99.374 +    /* Need to destroy the l3 monitor page in slot 0 too */
  99.375 +    {
  99.376 +        mfn_t m3mfn;
  99.377 +        l4_pgentry_t *l4e = hap_map_domain_page(mmfn);
  99.378 +        ASSERT(l4e_get_flags(l4e[0]) & _PAGE_PRESENT);
  99.379 +        m3mfn = _mfn(l4e_get_pfn(l4e[0]));
  99.380 +        hap_free(d, m3mfn);
  99.381 +        hap_unmap_domain_page(l4e);
  99.382 +    }
  99.383 +#elif CONFIG_PAGING_LEVELS == 3
  99.384 +    /* Need to destroy the l2 monitor page in slot 4 too */
  99.385 +    {
  99.386 +        l3_pgentry_t *l3e = hap_map_domain_page(mmfn);
  99.387 +        ASSERT(l3e_get_flags(l3e[3]) & _PAGE_PRESENT);
  99.388 +        hap_free(d, _mfn(l3e_get_pfn(l3e[3])));
  99.389 +        hap_unmap_domain_page(l3e);
  99.390 +    }
  99.391 +#endif
  99.392 +
  99.393 +    /* Put the memory back in the pool */
  99.394 +    hap_free(d, mmfn);
  99.395 +}
  99.396 +
  99.397 +/************************************************/
  99.398 +/*          HAP DOMAIN LEVEL FUNCTIONS          */
  99.399 +/************************************************/
  99.400 +void hap_domain_init(struct domain *d)
  99.401 +{
  99.402 +    hap_lock_init(d);
  99.403 +    INIT_LIST_HEAD(&d->arch.paging.hap.freelists);
  99.404 +    INIT_LIST_HEAD(&d->arch.paging.hap.p2m_freelist);
  99.405 +}
  99.406 +
  99.407 +/* return 0 for success, -errno for failure */
  99.408 +int hap_enable(struct domain *d, u32 mode)
  99.409 +{
  99.410 +    unsigned int old_pages;
  99.411 +    int rv = 0;
  99.412 +
  99.413 +    HERE_I_AM;
  99.414 +
  99.415 +    domain_pause(d);
  99.416 +    /* error check */
  99.417 +    if ( (d == current->domain) ) {
  99.418 +        rv = -EINVAL;
  99.419 +        goto out;
  99.420 +    }
  99.421 +
  99.422 +    old_pages = d->arch.paging.hap.total_pages;
  99.423 +    if ( old_pages == 0 ) {
  99.424 +        unsigned int r;
  99.425 +        hap_lock(d);
  99.426 +        r = hap_set_allocation(d, 256, NULL);
  99.427 +        hap_unlock(d);
  99.428 +        if ( r != 0 ) {
  99.429 +            hap_set_allocation(d, 0, NULL);
  99.430 +            rv = -ENOMEM;
  99.431 +            goto out;
  99.432 +        }
  99.433 +    }
  99.434 +
  99.435 +    /* allocate P2m table */
  99.436 +    if ( mode & PG_translate ) {
  99.437 +        rv = p2m_alloc_table(d, hap_alloc_p2m_page, hap_free_p2m_page);
  99.438 +        if ( rv != 0 )
  99.439 +            goto out;
  99.440 +    }
  99.441 +
  99.442 +    d->arch.paging.mode = mode | PG_SH_enable;
  99.443 +
  99.444 + out:
  99.445 +    domain_unpause(d);
  99.446 +    return rv;
  99.447 +}
  99.448 +
  99.449 +void hap_final_teardown(struct domain *d)
  99.450 +{
  99.451 +    HERE_I_AM;
  99.452 +
  99.453 +    if ( d->arch.paging.hap.total_pages != 0 )
  99.454 +        hap_teardown(d);
  99.455 +
  99.456 +    p2m_teardown(d);
  99.457 +}
  99.458 +
  99.459 +void hap_teardown(struct domain *d)
  99.460 +{
  99.461 +    struct vcpu *v;
  99.462 +    mfn_t mfn;
  99.463 +    HERE_I_AM;
  99.464 +
  99.465 +    ASSERT(test_bit(_DOMF_dying, &d->domain_flags));
  99.466 +    ASSERT(d != current->domain);
  99.467 +
  99.468 +    if ( !hap_locked_by_me(d) )
  99.469 +        hap_lock(d); /* Keep various asserts happy */
  99.470 +
  99.471 +    if ( paging_mode_enabled(d) ) {
  99.472 +        /* release the monitor table held by each vcpu */
  99.473 +        for_each_vcpu(d, v) {
  99.474 +            if ( v->arch.paging.mode && paging_mode_external(d) ) {
  99.475 +                mfn = pagetable_get_mfn(v->arch.monitor_table);
  99.476 +                if ( mfn_valid(mfn) && (mfn_x(mfn) != 0) )
  99.477 +                    hap_destroy_monitor_table(v, mfn);
  99.478 +                v->arch.monitor_table = pagetable_null();
  99.479 +            }
  99.480 +        }
  99.481 +    }
  99.482 +
  99.483 +    if ( d->arch.paging.hap.total_pages != 0 ) {
  99.484 +        HAP_PRINTK("teardown of domain %u starts."
  99.485 +                      "  pages total = %u, free = %u, p2m=%u\n",
  99.486 +                      d->domain_id,
  99.487 +                      d->arch.paging.hap.total_pages,
  99.488 +                      d->arch.paging.hap.free_pages,
  99.489 +                      d->arch.paging.hap.p2m_pages);
  99.490 +        hap_set_allocation(d, 0, NULL);
  99.491 +        HAP_PRINTK("teardown done."
  99.492 +                      "  pages total = %u, free = %u, p2m=%u\n",
  99.493 +                      d->arch.paging.hap.total_pages,
  99.494 +                      d->arch.paging.hap.free_pages,
  99.495 +                      d->arch.paging.hap.p2m_pages);
  99.496 +        ASSERT(d->arch.paging.hap.total_pages == 0);
  99.497 +    }
  99.498 +    
  99.499 +    d->arch.paging.mode &= ~PG_log_dirty;
  99.500 +
  99.501 +    hap_unlock(d);
  99.502 +}
  99.503 +
  99.504 +int hap_domctl(struct domain *d, xen_domctl_shadow_op_t *sc,
  99.505 +               XEN_GUEST_HANDLE(void) u_domctl)
  99.506 +{
  99.507 +    int rc, preempted = 0;
  99.508 +
  99.509 +    HERE_I_AM;
  99.510 +
  99.511 +    if ( unlikely(d == current->domain) ) {
  99.512 +        gdprintk(XENLOG_INFO, "Don't try to do a hap op on yourself!\n");
  99.513 +        return -EINVAL;
  99.514 +    }
  99.515 +    
  99.516 +    switch ( sc->op ) {
  99.517 +    case XEN_DOMCTL_SHADOW_OP_OFF:
  99.518 +    case XEN_DOMCTL_SHADOW_OP_ENABLE_TEST:
  99.519 +    case XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY:
  99.520 +    case XEN_DOMCTL_SHADOW_OP_ENABLE_TRANSLATE:
  99.521 +    case XEN_DOMCTL_SHADOW_OP_CLEAN:
  99.522 +    case XEN_DOMCTL_SHADOW_OP_PEEK:
  99.523 +    case XEN_DOMCTL_SHADOW_OP_ENABLE:
  99.524 +        HAP_ERROR("Bad hap domctl op %u\n", sc->op);
  99.525 +        domain_crash(d);
  99.526 +        return -EINVAL;
  99.527 +    case XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION:
  99.528 +        hap_lock(d);
  99.529 +        rc = hap_set_allocation(d, sc->mb << (20 - PAGE_SHIFT), &preempted);
  99.530 +        hap_unlock(d);
  99.531 +        if ( preempted )
  99.532 +            /* Not finished.  Set up to re-run the call. */
  99.533 +            rc = hypercall_create_continuation(__HYPERVISOR_domctl, "h", 
  99.534 +                                               u_domctl);
  99.535 +        else
  99.536 +            /* Finished.  Return the new allocation */
  99.537 +            sc->mb = hap_get_allocation(d);
  99.538 +        return rc;
  99.539 +    case XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION:
  99.540 +        sc->mb = hap_get_allocation(d);
  99.541 +        return 0;
  99.542 +    default:
  99.543 +        HAP_ERROR("Bad hap domctl op %u\n", sc->op);
  99.544 +        return -EINVAL;
  99.545 +    }
  99.546 +}
  99.547 +
  99.548 +void hap_vcpu_init(struct vcpu *v)
  99.549 +{
  99.550 +    v->arch.paging.mode = &hap_paging_real_mode;
  99.551 +}
  99.552 +/************************************************/
  99.553 +/*          HAP PAGING MODE FUNCTIONS           */
  99.554 +/************************************************/
  99.555 +/* In theory, hap should not intercept guest page fault. This function can 
  99.556 + * be recycled to handle host/nested page fault, if needed.
  99.557 + */
  99.558 +int hap_page_fault(struct vcpu *v, unsigned long va, 
  99.559 +                   struct cpu_user_regs *regs)
  99.560 +{
  99.561 +    HERE_I_AM;
  99.562 +    domain_crash(v->domain);
  99.563 +    return 0;
  99.564 +}
  99.565 +
  99.566 +/* called when guest issues a invlpg request. 
  99.567 + * Return 1 if need to issue page invalidation on CPU; Return 0 if does not
  99.568 + * need to do so.
  99.569 + */
  99.570 +int hap_invlpg(struct vcpu *v, unsigned long va)
  99.571 +{
  99.572 +    HERE_I_AM;
  99.573 +    return 0;
  99.574 +}
  99.575 +
  99.576 +void hap_update_cr3(struct vcpu *v, int do_locking)
  99.577 +{
  99.578 +    struct domain *d = v->domain;
  99.579 +    mfn_t gmfn;
  99.580 +
  99.581 +    HERE_I_AM;
  99.582 +    /* Don't do anything on an uninitialised vcpu */
  99.583 +    if ( !is_hvm_domain(d) && !test_bit(_VCPUF_initialised, &v->vcpu_flags) ) {
  99.584 +        ASSERT(v->arch.cr3 == 0);
  99.585 +        return;
  99.586 +    }
  99.587 +
  99.588 +    if ( do_locking )
  99.589 +        hap_lock(v->domain);
  99.590 +    
  99.591 +    ASSERT(hap_locked_by_me(v->domain));
  99.592 +    ASSERT(v->arch.paging.mode);
  99.593 +    
  99.594 +    gmfn = pagetable_get_mfn(v->arch.guest_table);
  99.595 +
  99.596 +    make_cr3(v, pagetable_get_pfn(v->arch.monitor_table));
  99.597 +    
  99.598 +    hvm_update_guest_cr3(v, pagetable_get_paddr(v->arch.monitor_table));
  99.599 +
  99.600 +    HAP_PRINTK("d=%u v=%u guest_table=%05lx, monitor_table = %05lx\n", 
  99.601 +               d->domain_id, v->vcpu_id, 
  99.602 +               (unsigned long)pagetable_get_pfn(v->arch.guest_table),
  99.603 +               (unsigned long)pagetable_get_pfn(v->arch.monitor_table));
  99.604 +
  99.605 +    flush_tlb_mask(d->domain_dirty_cpumask);
  99.606 +
  99.607 +    if ( do_locking )
  99.608 +        hap_unlock(v->domain);
  99.609 +}
  99.610 +
  99.611 +void hap_update_paging_modes(struct vcpu *v)
  99.612 +{
  99.613 +    struct domain *d;
  99.614 +
  99.615 +    HERE_I_AM;
  99.616 +
  99.617 +    d = v->domain;
  99.618 +    hap_lock(d);
  99.619 +
  99.620 +    /* update guest paging mode. Note that we rely on hvm functions to detect
  99.621 +     * guest's paging mode. So, make sure the shadow registers (CR0, CR4, EFER)
  99.622 +     * reflect guest's status correctly.
  99.623 +     */
  99.624 +    if ( hvm_paging_enabled(v) ) {
  99.625 +        if ( hvm_long_mode_enabled(v) )
  99.626 +            v->arch.paging.mode = &hap_paging_long_mode;
  99.627 +        else if ( hvm_pae_enabled(v) )
  99.628 +            v->arch.paging.mode = &hap_paging_pae_mode;
  99.629 +        else
  99.630 +            v->arch.paging.mode = &hap_paging_protected_mode;
  99.631 +    }
  99.632 +    else {
  99.633 +        v->arch.paging.mode = &hap_paging_real_mode;
  99.634 +    }
  99.635 +
  99.636 +    v->arch.paging.translate_enabled = !!hvm_paging_enabled(v);    
  99.637 +
  99.638 +    /* use p2m map */
  99.639 +    v->arch.guest_table =
  99.640 +        pagetable_from_pfn(pagetable_get_pfn(d->arch.phys_table));
  99.641 +
  99.642 +    if ( pagetable_is_null(v->arch.monitor_table) ) {
  99.643 +        mfn_t mmfn = hap_make_monitor_table(v);
  99.644 +        v->arch.monitor_table = pagetable_from_mfn(mmfn);
  99.645 +        make_cr3(v, mfn_x(mmfn));
  99.646 +    }
  99.647 +
  99.648 +    flush_tlb_mask(d->domain_dirty_cpumask);
  99.649 +    hap_unlock(d);
  99.650 +}
  99.651 +
  99.652 +void 
  99.653 +hap_write_p2m_entry(struct vcpu *v, unsigned long gfn, l1_pgentry_t *p,
  99.654 +                    l1_pgentry_t new, unsigned int level)
  99.655 +{
  99.656 +    hap_lock(v->domain);
  99.657 +    safe_write_pte(p, new);
  99.658 +    hap_unlock(v->domain);
  99.659 +}
  99.660 +
  99.661 +/* Entry points into this mode of the hap code. */
  99.662 +struct paging_mode hap_paging_real_mode = {
  99.663 +    .page_fault             = hap_page_fault, 
  99.664 +    .invlpg                 = hap_invlpg,
  99.665 +    .gva_to_gfn             = hap_gva_to_gfn_real_mode,
  99.666 +    .update_cr3             = hap_update_cr3,
  99.667 +    .update_paging_modes    = hap_update_paging_modes,
  99.668 +    .write_p2m_entry        = hap_write_p2m_entry,
  99.669 +    .guest_levels           = 1
  99.670 +};
  99.671 +
  99.672 +struct paging_mode hap_paging_protected_mode = {
  99.673 +    .page_fault             = hap_page_fault, 
  99.674 +    .invlpg                 = hap_invlpg,
  99.675 +    .gva_to_gfn             = hap_gva_to_gfn_protected_mode,
  99.676 +    .update_cr3             = hap_update_cr3,
  99.677 +    .update_paging_modes    = hap_update_paging_modes,
  99.678 +    .write_p2m_entry        = hap_write_p2m_entry,
  99.679 +    .guest_levels           = 2
  99.680 +};
  99.681 +
  99.682 +struct paging_mode hap_paging_pae_mode = {
  99.683 +    .page_fault             = hap_page_fault, 
  99.684 +    .invlpg                 = hap_invlpg,
  99.685 +    .gva_to_gfn             = hap_gva_to_gfn_pae_mode,
  99.686 +    .update_cr3             = hap_update_cr3,
  99.687 +    .update_paging_modes    = hap_update_paging_modes,
  99.688 +    .write_p2m_entry        = hap_write_p2m_entry,
  99.689 +    .guest_levels           = 3
  99.690 +};
  99.691 +
  99.692 +struct paging_mode hap_paging_long_mode = {
  99.693 +    .page_fault             = hap_page_fault, 
  99.694 +    .invlpg                 = hap_invlpg,
  99.695 +    .gva_to_gfn             = hap_gva_to_gfn_long_mode,
  99.696 +    .update_cr3             = hap_update_cr3,
  99.697 +    .update_paging_modes    = hap_update_paging_modes,
  99.698 +    .write_p2m_entry        = hap_write_p2m_entry,
  99.699 +    .guest_levels           = 4
  99.700 +};
  99.701 +
  99.702 +/*
  99.703 + * Local variables:
  99.704 + * mode: C
  99.705 + * c-set-style: "BSD"
  99.706 + * c-basic-offset: 4
  99.707 + * indent-tabs-mode: nil
  99.708 + * End:
  99.709 + */
  99.710 +
  99.711 +
   100.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   100.2 +++ b/xen/arch/x86/mm/hap/private.h	Mon Mar 12 10:07:08 2007 -0600
   100.3 @@ -0,0 +1,112 @@
   100.4 +/*
   100.5 + * arch/x86/mm/hap/private.h
   100.6 + *
   100.7 + * Copyright (c) 2007, AMD Corporation (Wei Huang)
   100.8 + *
   100.9 + * This program is free software; you can redistribute it and/or modify it
  100.10 + * under the terms and conditions of the GNU General Public License,
  100.11 + * version 2, as published by the Free Software Foundation.
  100.12 + *
  100.13 + * This program is distributed in the hope it will be useful, but WITHOUT
  100.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  100.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  100.16 + * more details.
  100.17 + *
  100.18 + * You should have received a copy of the GNU General Public License along with
  100.19 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  100.20 + * Place - Suite 330, Boston, MA 02111-1307 USA.
  100.21 + *
  100.22 + */
  100.23 +#ifndef __HAP_PRIVATE_H__
  100.24 +#define __HAP_PRIVATE_H__
  100.25 +
  100.26 +#include <asm/flushtlb.h>
  100.27 +#include <asm/hvm/support.h>
  100.28 +
  100.29 +/********************************************/
  100.30 +/*          GUEST TRANSLATION FUNCS         */
  100.31 +/********************************************/
  100.32 +unsigned long hap_gva_to_gfn_real_mode(struct vcpu *v, unsigned long gva);
  100.33 +unsigned long hap_gva_to_gfn_protected_mode(struct vcpu *v, unsigned long gva);
  100.34 +unsigned long hap_gva_to_gfn_pae_mode(struct vcpu *v, unsigned long gva);
  100.35 +unsigned long hap_gva_to_gfn_long_mode(struct vcpu *v, unsigned long gva);
  100.36 +/********************************************/
  100.37 +/*            MISC DEFINITIONS              */
  100.38 +/********************************************/
  100.39 +
  100.40 +/* PT_SHIFT describes the amount by which a virtual address is shifted right 
  100.41 + * to right justify the portion to be used for indexing into a page 
  100.42 + * table, given the guest memory model (i.e. number of levels) and the level 
  100.43 + * of the page table being accessed. The idea is from Virtual Iron's code.
  100.44 + */
  100.45 +static const int PT_SHIFT[][5] =
  100.46 +  {   /*     ------  level ------           nr_levels  */
  100.47 +    /*         1     2     3     4                   */
  100.48 +    {    0,    0,    0,    0,    0},   /* 0 not used */
  100.49 +    {    0,    0,    0,    0,    0},   /* 1 not used */
  100.50 +    {    0,   12,   22,    0,    0},   /* 2  */
  100.51 +    {    0,   12,   21,   30,    0},   /* 3  */
  100.52 +    {    0,   12,   21,   30,   39}    /* 4  */
  100.53 +  };
  100.54 +
  100.55 +/* PT_ENTRIES describes the number of entries in a page table, given the 
  100.56 + * memory model (i.e. number of levels) and the level of the page table 
  100.57 + * being considered. This idea from Virtual Iron's shadow code*/
  100.58 +static const int PT_ENTRIES[][5] =
  100.59 +  {   /*     ------  level ------           nr_levels  */
  100.60 +    /*         1     2     3     4                   */
  100.61 +    {    0,    0,    0,    0,    0},   /* 0 not used */
  100.62 +    {    0,    0,    0,    0,    0},   /* 1 not used */
  100.63 +    {    0, 1024, 1024,    0,    0},   /* 2  */
  100.64 +    {    0,  512,  512,    4,    0},   /* 3  */
  100.65 +    {    0,  512,  512,  512,  512}    /* 4  */
  100.66 +  };
  100.67 +
  100.68 +/********************************************/
  100.69 +/*       PAGING DEFINITION FOR GUEST        */
  100.70 +/********************************************/
  100.71 +#define PHYSICAL_PAGE_4K_SIZE (1UL << 12)
  100.72 +#define PHYSICAL_PAGE_2M_SIZE (1UL << 21)
  100.73 +#define PHYSICAL_PAGE_4M_SIZE (1UL << 22)
  100.74 +#define PHYSICAL_PAGE_4K_MASK ( ~(PHYSICAL_PAGE_4K_SIZE - 1) )
  100.75 +#define PHYSICAL_PAGE_2M_MASK ( ~(PHYSICAL_PAGE_2M_SIZE - 1) )
  100.76 +#define PHYSICAL_PAGE_4M_MASK ( ~(PHYSICAL_PAGE_4M_SIZE - 1) )
  100.77 +
  100.78 +/* long mode physical address mask */
  100.79 +#define PHYSICAL_ADDR_BITS_LM    52
  100.80 +#define PHYSICAL_ADDR_MASK_LM    ((1UL << PHYSICAL_ADDR_BITS_LM)-1)
  100.81 +#define PHYSICAL_ADDR_2M_MASK_LM (PHYSICAL_PAGE_2M_MASK & PHYSICAL_ADDR_MASK_LM)
  100.82 +#define PHYSICAL_ADDR_4K_MASK_LM (PHYSICAL_PAGE_4K_MASK & PHYSICAL_ADDR_MASK_LM)
  100.83 +
  100.84 +#define PAGE_NX_BIT      (1ULL << 63)
  100.85 +/************************************************/
  100.86 +/*        PAGETABLE RELATED VARIABLES           */
  100.87 +/************************************************/
  100.88 +#if CONFIG_PAGING_LEVELS == 2
  100.89 +#define HAP_L1_PAGETABLE_ENTRIES    1024
  100.90 +#define HAP_L2_PAGETABLE_ENTRIES    1024
  100.91 +#define HAP_L1_PAGETABLE_SHIFT        12
  100.92 +#define HAP_L2_PAGETABLE_SHIFT        22
  100.93 +#endif
  100.94 +
  100.95 +#if CONFIG_PAGING_LEVELS == 3
  100.96 +#define HAP_L1_PAGETABLE_ENTRIES     512
  100.97 +#define HAP_L2_PAGETABLE_ENTRIES     512
  100.98 +#define HAP_L3_PAGETABLE_ENTRIES       4
  100.99 +#define HAP_L1_PAGETABLE_SHIFT        12
 100.100 +#define HAP_L2_PAGETABLE_SHIFT        21
 100.101 +#define HAP_L3_PAGETABLE_SHIFT        30
 100.102 +#endif
 100.103 +
 100.104 +#if CONFIG_PAGING_LEVELS == 4
 100.105 +#define HAP_L1_PAGETABLE_ENTRIES     512
 100.106 +#define HAP_L2_PAGETABLE_ENTRIES     512
 100.107 +#define HAP_L3_PAGETABLE_ENTRIES     512
 100.108 +#define HAP_L4_PAGETABLE_ENTRIES     512
 100.109 +#define HAP_L1_PAGETABLE_SHIFT        12
 100.110 +#define HAP_L2_PAGETABLE_SHIFT        21
 100.111 +#define HAP_L3_PAGETABLE_SHIFT        30
 100.112 +#define HAP_L4_PAGETABLE_SHIFT        39
 100.113 +#endif
 100.114 +
 100.115 +#endif /* __SVM_NPT_H__ */
   101.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   101.2 +++ b/xen/arch/x86/mm/hap/support.c	Mon Mar 12 10:07:08 2007 -0600
   101.3 @@ -0,0 +1,334 @@
   101.4 +/*
   101.5 + * arch/x86/mm/hap/support.c
   101.6 + * 
   101.7 + * guest page table walker
   101.8 + * Copyright (c) 2007, AMD Corporation (Wei Huang)
   101.9 + *
  101.10 + * This program is free software; you can redistribute it and/or modify it
  101.11 + * under the terms and conditions of the GNU General Public License,
  101.12 + * version 2, as published by the Free Software Foundation.
  101.13 + *
  101.14 + * This program is distributed in the hope it will be useful, but WITHOUT
  101.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  101.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  101.17 + * more details.
  101.18 + *
  101.19 + * You should have received a copy of the GNU General Public License along with
  101.20 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  101.21 + * Place - Suite 330, Boston, MA 02111-1307 USA.
  101.22 + *
  101.23 + */
  101.24 +
  101.25 +#include <xen/config.h>
  101.26 +#include <xen/types.h>
  101.27 +#include <xen/mm.h>
  101.28 +#include <xen/domain_page.h>
  101.29 +#include <asm/page.h>
  101.30 +#include <xen/event.h>
  101.31 +#include <xen/sched.h>
  101.32 +#include <asm/hvm/svm/vmcb.h>
  101.33 +#include <asm/domain.h>
  101.34 +#include <asm/shadow.h>
  101.35 +#include <asm/hap.h>
  101.36 +
  101.37 +#include "private.h"
  101.38 +#include "../page-guest32.h"
  101.39 +
  101.40 +/*******************************************/
  101.41 +/*      Platform Specific Functions        */
  101.42 +/*******************************************/
  101.43 +
  101.44 +/* Translate guest virtual address to guest physical address. Specifically
  101.45 + * for real mode guest. 
  101.46 + */
  101.47 +unsigned long hap_gva_to_gfn_real_mode(struct vcpu *v, unsigned long gva)
  101.48 +{
  101.49 +    HERE_I_AM;
  101.50 +    return ((paddr_t)gva >> PAGE_SHIFT);
  101.51 +}
  101.52 +
  101.53 +/* Translate guest virtual address to guest physical address. Specifically
  101.54 + * for protected guest. 
  101.55 + */
  101.56 +unsigned long hap_gva_to_gfn_protected_mode(struct vcpu *v, unsigned long gva)
  101.57 +{
  101.58 +    unsigned long gcr3 = hvm_get_guest_ctrl_reg(v, 3);
  101.59 +    int mode = 2; /* two-level guest */
  101.60 +    int lev, index;
  101.61 +    paddr_t gpa = 0;
  101.62 +    unsigned long gpfn, mfn;
  101.63 +    int success = 1;
  101.64 +    l2_pgentry_32_t *l2e; /* guest page entry size is 32-bit */
  101.65 +    l1_pgentry_32_t *l1e;
  101.66 +
  101.67 +    HERE_I_AM;
  101.68 +
  101.69 +    gpfn = (gcr3 >> PAGE_SHIFT);
  101.70 +    for ( lev = mode; lev >= 1; lev-- ) {
  101.71 +        mfn = get_mfn_from_gpfn( gpfn );
  101.72 +        if ( mfn == INVALID_MFN ) {
  101.73 +            HAP_PRINTK("bad pfn=0x%lx from gva=0x%lx at lev%d\n", gpfn, gva, 
  101.74 +                       lev);
  101.75 +            success = 0;
  101.76 +            break;
  101.77 +        }
  101.78 +        index = (gva >> PT_SHIFT[mode][lev]) & (PT_ENTRIES[mode][lev]-1);
  101.79 +
  101.80 +        if ( lev == 2 ) {
  101.81 +            l2e = map_domain_page( mfn );
  101.82 +            HAP_PRINTK("l2 page table entry is %ulx at index = %d\n", 
  101.83 +                       l2e[index].l2, index);
  101.84 +            if ( !(l2e_get_flags_32(l2e[index]) & _PAGE_PRESENT) ) {
  101.85 +                HAP_PRINTK("Level 2 entry not present at index = %d\n", index);
  101.86 +                success = 0;
  101.87 +            }
  101.88 +
  101.89 +            if ( l2e_get_flags_32(l2e[index]) & _PAGE_PSE ) { /* handle PSE */
  101.90 +                HAP_PRINTK("guest page table is PSE\n");
  101.91 +                if ( l2e_get_intpte(l2e[index]) & 0x001FE000UL ) { /*[13:20] */
  101.92 +                    printk("guest physical memory size is too large!\n");
  101.93 +                    domain_crash(v->domain);
  101.94 +                }
  101.95 +                gpa = (l2e_get_intpte(l2e[index]) & PHYSICAL_PAGE_4M_MASK) + 
  101.96 +                    (gva & ~PHYSICAL_PAGE_4M_MASK);
  101.97 +                unmap_domain_page(l2e);
  101.98 +                break; /* last level page table, return from here */
  101.99 +            }
 101.100 +            else {
 101.101 +                gpfn = l2e_get_pfn( l2e[index] );
 101.102 +            }
 101.103 +            unmap_domain_page(l2e);
 101.104 +        }
 101.105 +
 101.106 +        if ( lev == 1 ) {
 101.107 +            l1e = map_domain_page( mfn );
 101.108 +            HAP_PRINTK("l1 page table entry is %ulx at index = %d\n", 
 101.109 +                       l1e[index].l1, index);
 101.110 +            if ( !(l1e_get_flags_32(l1e[index]) & _PAGE_PRESENT) ) {
 101.111 +                HAP_PRINTK("Level 1 entry not present at index = %d\n", index);
 101.112 +                success = 0;
 101.113 +            }
 101.114 +            gpfn = l1e_get_pfn( l1e[index] );
 101.115 +            gpa = (l1e_get_intpte(l1e[index]) & PHYSICAL_PAGE_4K_MASK) + 
 101.116 +                (gva & ~PHYSICAL_PAGE_4K_MASK);	    
 101.117 +            unmap_domain_page(l1e);
 101.118 +        }
 101.119 +
 101.120 +        if ( !success ) /* error happened, jump out */
 101.121 +            break;
 101.122 +    }
 101.123 +
 101.124 +    HAP_PRINTK("success = %d, gva = %lx, gpa = %lx\n", success, gva, gpa);
 101.125 +
 101.126 +    if ( !success ) /* error happened */
 101.127 +        return INVALID_GFN;
 101.128 +    else
 101.129 +        return ((paddr_t)gpa >> PAGE_SHIFT);
 101.130 +}
 101.131 +
 101.132 +
 101.133 +
 101.134 +/* Translate guest virtual address to guest physical address. Specifically
 101.135 + * for PAE mode guest. 
 101.136 + */
 101.137 +unsigned long hap_gva_to_gfn_pae_mode(struct vcpu *v, unsigned long gva)
 101.138 +{
 101.139 +#if CONFIG_PAGING_LEVELS >= 3
 101.140 +    unsigned long gcr3 = hvm_get_guest_ctrl_reg(v, 3);
 101.141 +    int mode = 3; /* three-level guest */
 101.142 +    int lev, index;
 101.143 +    paddr_t gpa = 0;
 101.144 +    unsigned long gpfn, mfn;
 101.145 +    int success = 1;
 101.146 +    l1_pgentry_t *l1e;
 101.147 +    l2_pgentry_t *l2e;
 101.148 +    l3_pgentry_t *l3e;
 101.149 +    
 101.150 +    HERE_I_AM;
 101.151 +
 101.152 +    gpfn = (gcr3 >> PAGE_SHIFT);
 101.153 +    for ( lev = mode; lev >= 1; lev-- ) {
 101.154 +        mfn = get_mfn_from_gpfn( gpfn );
 101.155 +        if ( mfn == INVALID_MFN ) {
 101.156 +            HAP_PRINTK("bad pfn=0x%lx from gva=0x%lx at lev%d\n", gpfn, gva, 
 101.157 +                       lev);
 101.158 +            success = 0;
 101.159 +            break;
 101.160 +        }
 101.161 +        index = (gva >> PT_SHIFT[mode][lev]) & (PT_ENTRIES[mode][lev]-1);
 101.162 +
 101.163 +        if ( lev == 3 ) {
 101.164 +            l3e = map_domain_page( mfn );
 101.165 +            index += ( ((gcr3 >> 5 ) & 127 ) * 4 );
 101.166 +            if ( !(l3e_get_flags(l3e[index]) & _PAGE_PRESENT) ) {
 101.167 +                HAP_PRINTK("Level 3 entry not present at index = %d\n", index);
 101.168 +                success = 0;
 101.169 +            }
 101.170 +            gpfn = l3e_get_pfn( l3e[index] );
 101.171 +            unmap_domain_page(l3e);
 101.172 +        }
 101.173 +
 101.174 +        if ( lev == 2 ) {
 101.175 +            l2e = map_domain_page( mfn );
 101.176 +            if ( !(l2e_get_flags(l2e[index]) & _PAGE_PRESENT) ) {
 101.177 +                HAP_PRINTK("Level 2 entry not present at index = %d\n", index);
 101.178 +                success = 0;
 101.179 +            }
 101.180 +
 101.181 +            if ( l2e_get_flags(l2e[index]) & _PAGE_PSE ) { /* handle PSE */
 101.182 +                HAP_PRINTK("guest page table is PSE\n");
 101.183 +                gpa = (l2e_get_intpte(l2e[index]) & PHYSICAL_PAGE_2M_MASK) + 
 101.184 +                    (gva & ~PHYSICAL_PAGE_2M_MASK);
 101.185 +                unmap_domain_page(l2e);
 101.186 +                break; /* last level page table, jump out from here */
 101.187 +            }
 101.188 +            else { 
 101.189 +                gpfn = l2e_get_pfn(l2e[index]);
 101.190 +            }
 101.191 +            unmap_domain_page(l2e);
 101.192 +        }
 101.193 +
 101.194 +        if ( lev == 1 ) {
 101.195 +            l1e = map_domain_page( mfn );
 101.196 +            if ( !(l1e_get_flags(l1e[index]) & _PAGE_PRESENT) ) {
 101.197 +                HAP_PRINTK("Level 1 entry not present at index = %d\n", index);
 101.198 +                success = 0;
 101.199 +            }
 101.200 +            gpfn = l1e_get_pfn( l1e[index] );
 101.201 +            gpa = (l1e_get_intpte(l1e[index]) & PHYSICAL_PAGE_4K_MASK) + 
 101.202 +                (gva & ~PHYSICAL_PAGE_4K_MASK);
 101.203 +            unmap_domain_page(l1e);
 101.204 +        }
 101.205 +
 101.206 +        if ( success != 1 ) /* error happened, jump out */
 101.207 +            break;
 101.208 +    }
 101.209 +
 101.210 +    gpa &= ~PAGE_NX_BIT; /* clear NX bit of guest physical address */
 101.211 +    HAP_PRINTK("success = %d, gva = %lx, gpa = %lx\n", success, gva, gpa);
 101.212 +
 101.213 +    if ( !success )
 101.214 +        return INVALID_GFN;
 101.215 +    else
 101.216 +        return ((paddr_t)gpa >> PAGE_SHIFT);
 101.217 +#else
 101.218 +    HERE_I_AM;
 101.219 +    printk("guest paging level (3) is greater than host paging level!\n");
 101.220 +    domain_crash(v->domain);
 101.221 +    return INVALID_GFN;
 101.222 +#endif
 101.223 +}
 101.224 +
 101.225 +
 101.226 +
 101.227 +/* Translate guest virtual address to guest physical address. Specifically
 101.228 + * for long mode guest. 
 101.229 + */
 101.230 +unsigned long hap_gva_to_gfn_long_mode(struct vcpu *v, unsigned long gva)
 101.231 +{
 101.232 +#if CONFIG_PAGING_LEVELS == 4
 101.233 +    unsigned long gcr3 = hvm_get_guest_ctrl_reg(v, 3);
 101.234 +    int mode = 4; /* four-level guest */
 101.235 +    int lev, index;
 101.236 +    paddr_t gpa = 0;
 101.237 +    unsigned long gpfn, mfn;
 101.238 +    int success = 1;
 101.239 +    l4_pgentry_t *l4e;
 101.240 +    l3_pgentry_t *l3e;
 101.241 +    l2_pgentry_t *l2e;
 101.242 +    l1_pgentry_t *l1e;
 101.243 +
 101.244 +    HERE_I_AM;
 101.245 +
 101.246 +    gpfn = (gcr3 >> PAGE_SHIFT);
 101.247 +    for ( lev = mode; lev >= 1; lev-- ) {
 101.248 +        mfn = get_mfn_from_gpfn( gpfn );
 101.249 +        if ( mfn == INVALID_MFN ) {
 101.250 +            HAP_PRINTK("bad pfn=0x%lx from gva=0x%lx at lev%d\n", gpfn, gva, 
 101.251 +                       lev);
 101.252 +            success = 0;
 101.253 +            break;
 101.254 +        }
 101.255 +        index = (gva >> PT_SHIFT[mode][lev]) & (PT_ENTRIES[mode][lev]-1);
 101.256 +
 101.257 +        if ( lev == 4 ) {
 101.258 +            l4e = map_domain_page( mfn );
 101.259 +            if ( !(l4e_get_flags(l4e[index]) & _PAGE_PRESENT) ) {
 101.260 +                HAP_PRINTK("Level 4 entry not present at index = %d\n", index);
 101.261 +                success = 0;
 101.262 +            }
 101.263 +            gpfn = l4e_get_pfn( l4e[index] );
 101.264 +            unmap_domain_page(l4e);
 101.265 +        }
 101.266 +
 101.267 +        if ( lev == 3 ) {
 101.268 +            l3e = map_domain_page( mfn );
 101.269 +            if ( !(l3e_get_flags(l3e[index]) & _PAGE_PRESENT) ) {
 101.270 +                HAP_PRINTK("Level 3 entry not present at index = %d\n", index);
 101.271 +                success = 0;
 101.272 +            }
 101.273 +            gpfn = l3e_get_pfn( l3e[index] );
 101.274 +            unmap_domain_page(l3e);
 101.275 +        }
 101.276 +
 101.277 +        if ( lev == 2 ) {
 101.278 +            l2e = map_domain_page( mfn );
 101.279 +            if ( !(l2e_get_flags(l2e[index]) & _PAGE_PRESENT) ) {
 101.280 +                HAP_PRINTK("Level 2 entry not present at index = %d\n", index);
 101.281 +                success = 0;
 101.282 +            }
 101.283 +
 101.284 +            if ( l2e_get_flags(l2e[index]) & _PAGE_PSE ) { /* handle PSE */
 101.285 +                HAP_PRINTK("guest page table is PSE\n");
 101.286 +                gpa = (l2e_get_intpte(l2e[index]) & PHYSICAL_ADDR_2M_MASK_LM) 
 101.287 +                    + (gva & ~PHYSICAL_PAGE_2M_MASK);
 101.288 +                unmap_domain_page(l2e);
 101.289 +                break; /* last level page table, jump out from here */
 101.290 +            }
 101.291 +            else { 
 101.292 +                gpfn = l2e_get_pfn(l2e[index]);
 101.293 +            }
 101.294 +            unmap_domain_page(l2e);
 101.295 +        }
 101.296 +
 101.297 +        if ( lev == 1 ) {
 101.298 +            l1e = map_domain_page( mfn );
 101.299 +            if ( !(l1e_get_flags(l1e[index]) & _PAGE_PRESENT) ) {
 101.300 +                HAP_PRINTK("Level 1 entry not present at index = %d\n", index);
 101.301 +                success = 0;
 101.302 +            }
 101.303 +            gpfn = l1e_get_pfn( l1e[index] );
 101.304 +            gpa = (l1e_get_intpte(l1e[index]) & PHYSICAL_ADDR_4K_MASK_LM) + 
 101.305 +                (gva & ~PHYSICAL_PAGE_4K_MASK);
 101.306 +            unmap_domain_page(l1e);
 101.307 +        }
 101.308 +
 101.309 +        if ( success != 1 ) /* error happened, jump out */
 101.310 +            break;
 101.311 +    }
 101.312 +
 101.313 +    gpa &= ~PAGE_NX_BIT; /* clear NX bit of guest physical address */
 101.314 +    HAP_PRINTK("success = %d, gva = %lx, gpa = %lx\n", success, gva, gpa);
 101.315 +
 101.316 +    if ( !success )
 101.317 +        return INVALID_GFN;
 101.318 +    else
 101.319 +        return ((paddr_t)gpa >> PAGE_SHIFT);
 101.320 +#else
 101.321 +    HERE_I_AM;
 101.322 +    printk("guest paging level (4) is greater than host paging level!\n");
 101.323 +    domain_crash(v->domain);
 101.324 +    return INVALID_GFN;
 101.325 +#endif
 101.326 +}
 101.327 +
 101.328 +/*
 101.329 + * Local variables:
 101.330 + * mode: C
 101.331 + * c-set-style: "BSD"
 101.332 + * c-basic-offset: 4
 101.333 + * tab-width: 4
 101.334 + * indent-tabs-mode: nil
 101.335 + * End:
 101.336 + */
 101.337 +
   102.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   102.2 +++ b/xen/arch/x86/mm/page-guest32.h	Mon Mar 12 10:07:08 2007 -0600
   102.3 @@ -0,0 +1,100 @@
   102.4 +
   102.5 +#ifndef __X86_PAGE_GUEST_H__
   102.6 +#define __X86_PAGE_GUEST_H__
   102.7 +
   102.8 +#ifndef __ASSEMBLY__
   102.9 +# include <asm/types.h>
  102.10 +#endif
  102.11 +
  102.12 +#define PAGETABLE_ORDER_32         10
  102.13 +#define L1_PAGETABLE_ENTRIES_32    (1<<PAGETABLE_ORDER_32)
  102.14 +#define L2_PAGETABLE_ENTRIES_32    (1<<PAGETABLE_ORDER_32)
  102.15 +#define ROOT_PAGETABLE_ENTRIES_32  L2_PAGETABLE_ENTRIES_32
  102.16 +
  102.17 +
  102.18 +#define L1_PAGETABLE_SHIFT_32 12
  102.19 +#define L2_PAGETABLE_SHIFT_32 22
  102.20 +
  102.21 +/* Extract flags into 12-bit integer, or turn 12-bit flags into a pte mask. */
  102.22 +
  102.23 +#ifndef __ASSEMBLY__
  102.24 +
  102.25 +typedef u32 intpte_32_t;
  102.26 +
  102.27 +typedef struct { intpte_32_t l1; } l1_pgentry_32_t;
  102.28 +typedef struct { intpte_32_t l2; } l2_pgentry_32_t;
  102.29 +typedef l2_pgentry_t root_pgentry_32_t;
  102.30 +#endif
  102.31 +
  102.32 +#define get_pte_flags_32(x) ((u32)(x) & 0xFFF)
  102.33 +#define put_pte_flags_32(x) ((intpte_32_t)(x))
  102.34 +
  102.35 +/* Get pte access flags (unsigned int). */
  102.36 +#define l1e_get_flags_32(x)           (get_pte_flags_32((x).l1))
  102.37 +#define l2e_get_flags_32(x)           (get_pte_flags_32((x).l2))
  102.38 +
  102.39 +#define l1e_get_paddr_32(x)           \
  102.40 +    ((paddr_t)(((x).l1 & (PADDR_MASK&PAGE_MASK))))
  102.41 +#define l2e_get_paddr_32(x)           \
  102.42 +    ((paddr_t)(((x).l2 & (PADDR_MASK&PAGE_MASK))))
  102.43 +
  102.44 +/* Construct an empty pte. */
  102.45 +#define l1e_empty_32()                ((l1_pgentry_32_t) { 0 })
  102.46 +#define l2e_empty_32()                ((l2_pgentry_32_t) { 0 })
  102.47 +
  102.48 +/* Construct a pte from a pfn and access flags. */
  102.49 +#define l1e_from_pfn_32(pfn, flags)   \
  102.50 +    ((l1_pgentry_32_t) { ((intpte_32_t)(pfn) << PAGE_SHIFT) | put_pte_flags_32(flags) })
  102.51 +#define l2e_from_pfn_32(pfn, flags)   \
  102.52 +    ((l2_pgentry_32_t) { ((intpte_32_t)(pfn) << PAGE_SHIFT) | put_pte_flags_32(flags) })
  102.53 +
  102.54 +/* Construct a pte from a physical address and access flags. */
  102.55 +#ifndef __ASSEMBLY__
  102.56 +static inline l1_pgentry_32_t l1e_from_paddr_32(paddr_t pa, unsigned int flags)
  102.57 +{
  102.58 +    ASSERT((pa & ~(PADDR_MASK & PAGE_MASK)) == 0);
  102.59 +    return (l1_pgentry_32_t) { pa | put_pte_flags_32(flags) };
  102.60 +}
  102.61 +static inline l2_pgentry_32_t l2e_from_paddr_32(paddr_t pa, unsigned int flags)
  102.62 +{
  102.63 +    ASSERT((pa & ~(PADDR_MASK & PAGE_MASK)) == 0);
  102.64 +    return (l2_pgentry_32_t) { pa | put_pte_flags_32(flags) };
  102.65 +}
  102.66 +#endif /* !__ASSEMBLY__ */
  102.67 +
  102.68 +
  102.69 +/* Construct a pte from a page pointer and access flags. */
  102.70 +#define l1e_from_page_32(page, flags) (l1e_from_pfn_32(page_to_mfn(page),(flags)))
  102.71 +#define l2e_from_page_32(page, flags) (l2e_from_pfn_32(page_to_mfn(page),(flags)))
  102.72 +
  102.73 +/* Add extra flags to an existing pte. */
  102.74 +#define l1e_add_flags_32(x, flags)    ((x).l1 |= put_pte_flags_32(flags))
  102.75 +#define l2e_add_flags_32(x, flags)    ((x).l2 |= put_pte_flags_32(flags))
  102.76 +
  102.77 +/* Remove flags from an existing pte. */
  102.78 +#define l1e_remove_flags_32(x, flags) ((x).l1 &= ~put_pte_flags_32(flags))
  102.79 +#define l2e_remove_flags_32(x, flags) ((x).l2 &= ~put_pte_flags_32(flags))
  102.80 +
  102.81 +/* Check if a pte's page mapping or significant access flags have changed. */
  102.82 +#define l1e_has_changed_32(x,y,flags) \
  102.83 +    ( !!(((x).l1 ^ (y).l1) & ((PADDR_MASK&PAGE_MASK)|put_pte_flags_32(flags))) )
  102.84 +#define l2e_has_changed_32(x,y,flags) \
  102.85 +    ( !!(((x).l2 ^ (y).l2) & ((PADDR_MASK&PAGE_MASK)|put_pte_flags_32(flags))) )
  102.86 +
  102.87 +/* Given a virtual address, get an entry offset into a page table. */
  102.88 +#define l1_table_offset_32(a)         \
  102.89 +    (((a) >> L1_PAGETABLE_SHIFT_32) & (L1_PAGETABLE_ENTRIES_32 - 1))
  102.90 +#define l2_table_offset_32(a)         \
  102.91 +    (((a) >> L2_PAGETABLE_SHIFT_32) & (L2_PAGETABLE_ENTRIES_32 - 1))
  102.92 +
  102.93 +#endif /* __X86_PAGE_GUEST_H__ */
  102.94 +
  102.95 +/*
  102.96 + * Local variables:
  102.97 + * mode: C
  102.98 + * c-set-style: "BSD"
  102.99 + * c-basic-offset: 4
 102.100 + * tab-width: 4
 102.101 + * indent-tabs-mode: nil
 102.102 + * End:
 102.103 + */
   103.1 --- a/xen/arch/x86/mm/paging.c	Mon Mar 12 09:43:48 2007 -0600
   103.2 +++ b/xen/arch/x86/mm/paging.c	Mon Mar 12 10:07:08 2007 -0600
   103.3 @@ -24,10 +24,12 @@
   103.4  #include <asm/paging.h>
   103.5  #include <asm/shadow.h>
   103.6  #include <asm/p2m.h>
   103.7 +#include <asm/hap.h>
   103.8  
   103.9  /* Xen command-line option to enable hardware-assisted paging */
  103.10  int opt_hap_enabled = 0; 
  103.11  boolean_param("hap", opt_hap_enabled);
  103.12 +int hap_capable_system = 0;
  103.13  
  103.14  /* Printouts */
  103.15  #define PAGING_PRINTK(_f, _a...)                                     \
  103.16 @@ -46,12 +48,18 @@ void paging_domain_init(struct domain *d
  103.17  {
  103.18      p2m_init(d);
  103.19      shadow_domain_init(d);
  103.20 +
  103.21 +    if ( opt_hap_enabled && hap_capable_system && is_hvm_domain(d) )
  103.22 +        hap_domain_init(d);
  103.23  }
  103.24  
  103.25  /* vcpu paging struct initialization goes here */
  103.26  void paging_vcpu_init(struct vcpu *v)
  103.27  {
  103.28 -    shadow_vcpu_init(v);
  103.29 +    if ( opt_hap_enabled && hap_capable_system && is_hvm_vcpu(v) )
  103.30 +        hap_vcpu_init(v);
  103.31 +    else
  103.32 +        shadow_vcpu_init(v);
  103.33  }
  103.34  
  103.35  
  103.36 @@ -59,32 +67,38 @@ int paging_domctl(struct domain *d, xen_
  103.37                    XEN_GUEST_HANDLE(void) u_domctl)
  103.38  {
  103.39      /* Here, dispatch domctl to the appropriate paging code */
  103.40 -    return shadow_domctl(d, sc, u_domctl);
  103.41 +    if ( opt_hap_enabled && hap_capable_system && is_hvm_domain(d) )
  103.42 +        return hap_domctl(d, sc, u_domctl);
  103.43 +    else
  103.44 +        return shadow_domctl(d, sc, u_domctl);
  103.45  }
  103.46  
  103.47  /* Call when destroying a domain */
  103.48  void paging_teardown(struct domain *d)
  103.49  {
  103.50 -    shadow_teardown(d);
  103.51 -    /* Call other modes' teardown code here */    
  103.52 +    if ( opt_hap_enabled && hap_capable_system && is_hvm_domain(d) )
  103.53 +        hap_teardown(d);
  103.54 +    else
  103.55 +        shadow_teardown(d);
  103.56  }
  103.57  
  103.58  /* Call once all of the references to the domain have gone away */
  103.59  void paging_final_teardown(struct domain *d)
  103.60  {
  103.61 -    shadow_teardown(d);
  103.62 -    /* Call other modes' final teardown code here */
  103.63 +    if ( opt_hap_enabled && hap_capable_system && is_hvm_domain(d) )
  103.64 +        hap_final_teardown(d);
  103.65 +    else
  103.66 +        shadow_final_teardown(d);
  103.67  }
  103.68  
  103.69  /* Enable an arbitrary paging-assistance mode.  Call once at domain
  103.70   * creation. */
  103.71  int paging_enable(struct domain *d, u32 mode)
  103.72  {
  103.73 -    if ( mode & PG_SH_enable ) 
  103.74 -        return shadow_enable(d, mode);
  103.75 +    if ( opt_hap_enabled && hap_capable_system && is_hvm_domain(d) )
  103.76 +        return hap_enable(d, mode | PG_HAP_enable);
  103.77      else
  103.78 -        /* No other modes supported yet */
  103.79 -        return -EINVAL; 
  103.80 +        return shadow_enable(d, mode | PG_SH_enable);
  103.81  }
  103.82  
  103.83  /* Print paging-assistance info to the console */
   104.1 --- a/xen/arch/x86/mm/shadow/common.c	Mon Mar 12 09:43:48 2007 -0600
   104.2 +++ b/xen/arch/x86/mm/shadow/common.c	Mon Mar 12 10:07:08 2007 -0600
   104.3 @@ -802,7 +802,7 @@ void shadow_prealloc(struct domain *d, u
   104.4      v = current;
   104.5      if ( v->domain != d )
   104.6          v = d->vcpu[0];
   104.7 -    ASSERT(v != NULL);
   104.8 +    ASSERT(v != NULL); /* Shouldn't have enabled shadows if we've no vcpus  */
   104.9  
  104.10      /* Stage one: walk the list of pinned pages, unpinning them */
  104.11      perfc_incrc(shadow_prealloc_1);
  104.12 @@ -861,7 +861,9 @@ static void shadow_blow_tables(struct do
  104.13      struct vcpu *v = d->vcpu[0];
  104.14      mfn_t smfn;
  104.15      int i;
  104.16 -    
  104.17 +
  104.18 +    ASSERT(v != NULL);
  104.19 +
  104.20      /* Pass one: unpin all pinned pages */
  104.21      list_for_each_backwards_safe(l,t, &d->arch.paging.shadow.pinned_shadows)
  104.22      {
  104.23 @@ -1129,6 +1131,7 @@ shadow_free_p2m_page(struct domain *d, s
  104.24          SHADOW_ERROR("Odd p2m page count c=%#x t=%"PRtype_info"\n",
  104.25                       pg->count_info, pg->u.inuse.type_info);
  104.26      }
  104.27 +    pg->count_info = 0;
  104.28      /* Free should not decrement domain's total allocation, since 
  104.29       * these pages were allocated without an owner. */
  104.30      page_set_owner(pg, NULL); 
  104.31 @@ -1243,6 +1246,9 @@ static unsigned int sh_set_allocation(st
  104.32              list_del(&sp->list);
  104.33              d->arch.paging.shadow.free_pages -= 1<<SHADOW_MAX_ORDER;
  104.34              d->arch.paging.shadow.total_pages -= 1<<SHADOW_MAX_ORDER;
  104.35 +            for ( j = 0; j < 1<<SHADOW_MAX_ORDER; j++ ) 
  104.36 +                /* Keep the page allocator happy */
  104.37 +                ((struct page_info *)sp)[j].count_info = 0;
  104.38              free_domheap_pages((struct page_info *)sp, SHADOW_MAX_ORDER);
  104.39          }
  104.40  
  104.41 @@ -2989,6 +2995,13 @@ int shadow_domctl(struct domain *d,
  104.42          return 0;
  104.43      }
  104.44  
  104.45 +    if ( unlikely(d->vcpu[0] == NULL) )
  104.46 +    {
  104.47 +        SHADOW_ERROR("Shadow op on a domain (%u) with no vcpus\n",
  104.48 +                     d->domain_id);
  104.49 +        return -EINVAL;
  104.50 +    }
  104.51 +
  104.52      switch ( sc->op )
  104.53      {
  104.54      case XEN_DOMCTL_SHADOW_OP_OFF:
   105.1 --- a/xen/arch/x86/mm/shadow/page-guest32.h	Mon Mar 12 09:43:48 2007 -0600
   105.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   105.3 @@ -1,100 +0,0 @@
   105.4 -
   105.5 -#ifndef __X86_PAGE_GUEST_H__
   105.6 -#define __X86_PAGE_GUEST_H__
   105.7 -
   105.8 -#ifndef __ASSEMBLY__
   105.9 -# include <asm/types.h>
  105.10 -#endif
  105.11 -
  105.12 -#define PAGETABLE_ORDER_32         10
  105.13 -#define L1_PAGETABLE_ENTRIES_32    (1<<PAGETABLE_ORDER_32)
  105.14 -#define L2_PAGETABLE_ENTRIES_32    (1<<PAGETABLE_ORDER_32)
  105.15 -#define ROOT_PAGETABLE_ENTRIES_32  L2_PAGETABLE_ENTRIES_32
  105.16 -
  105.17 -
  105.18 -#define L1_PAGETABLE_SHIFT_32 12
  105.19 -#define L2_PAGETABLE_SHIFT_32 22
  105.20 -
  105.21 -/* Extract flags into 12-bit integer, or turn 12-bit flags into a pte mask. */
  105.22 -
  105.23 -#ifndef __ASSEMBLY__
  105.24 -
  105.25 -typedef u32 intpte_32_t;
  105.26 -
  105.27 -typedef struct { intpte_32_t l1; } l1_pgentry_32_t;
  105.28 -typedef struct { intpte_32_t l2; } l2_pgentry_32_t;
  105.29 -typedef l2_pgentry_t root_pgentry_32_t;
  105.30 -#endif
  105.31 -
  105.32 -#define get_pte_flags_32(x) ((u32)(x) & 0xFFF)
  105.33 -#define put_pte_flags_32(x) ((intpte_32_t)(x))
  105.34 -
  105.35 -/* Get pte access flags (unsigned int). */
  105.36 -#define l1e_get_flags_32(x)           (get_pte_flags_32((x).l1))
  105.37 -#define l2e_get_flags_32(x)           (get_pte_flags_32((x).l2))
  105.38 -
  105.39 -#define l1e_get_paddr_32(x)           \
  105.40 -    ((paddr_t)(((x).l1 & (PADDR_MASK&PAGE_MASK))))
  105.41 -#define l2e_get_paddr_32(x)           \
  105.42 -    ((paddr_t)(((x).l2 & (PADDR_MASK&PAGE_MASK))))
  105.43 -
  105.44 -/* Construct an empty pte. */
  105.45 -#define l1e_empty_32()                ((l1_pgentry_32_t) { 0 })
  105.46 -#define l2e_empty_32()                ((l2_pgentry_32_t) { 0 })
  105.47 -
  105.48 -/* Construct a pte from a pfn and access flags. */
  105.49 -#define l1e_from_pfn_32(pfn, flags)   \
  105.50 -    ((l1_pgentry_32_t) { ((intpte_32_t)(pfn) << PAGE_SHIFT) | put_pte_flags_32(flags) })
  105.51 -#define l2e_from_pfn_32(pfn, flags)   \
  105.52 -    ((l2_pgentry_32_t) { ((intpte_32_t)(pfn) << PAGE_SHIFT) | put_pte_flags_32(flags) })
  105.53 -
  105.54 -/* Construct a pte from a physical address and access flags. */
  105.55 -#ifndef __ASSEMBLY__
  105.56 -static inline l1_pgentry_32_t l1e_from_paddr_32(paddr_t pa, unsigned int flags)
  105.57 -{
  105.58 -    ASSERT((pa & ~(PADDR_MASK & PAGE_MASK)) == 0);
  105.59 -    return (l1_pgentry_32_t) { pa | put_pte_flags_32(flags) };
  105.60 -}
  105.61 -static inline l2_pgentry_32_t l2e_from_paddr_32(paddr_t pa, unsigned int flags)
  105.62 -{
  105.63 -    ASSERT((pa & ~(PADDR_MASK & PAGE_MASK)) == 0);
  105.64 -    return (l2_pgentry_32_t) { pa | put_pte_flags_32(flags) };
  105.65 -}
  105.66 -#endif /* !__ASSEMBLY__ */
  105.67 -
  105.68 -
  105.69 -/* Construct a pte from a page pointer and access flags. */
  105.70 -#define l1e_from_page_32(page, flags) (l1e_from_pfn_32(page_to_mfn(page),(flags)))
  105.71 -#define l2e_from_page_32(page, flags) (l2e_from_pfn_32(page_to_mfn(page),(flags)))
  105.72 -
  105.73 -/* Add extra flags to an existing pte. */
  105.74 -#define l1e_add_flags_32(x, flags)    ((x).l1 |= put_pte_flags_32(flags))
  105.75 -#define l2e_add_flags_32(x, flags)    ((x).l2 |= put_pte_flags_32(flags))
  105.76 -
  105.77 -/* Remove flags from an existing pte. */
  105.78 -#define l1e_remove_flags_32(x, flags) ((x).l1 &= ~put_pte_flags_32(flags))
  105.79 -#define l2e_remove_flags_32(x, flags) ((x).l2 &= ~put_pte_flags_32(flags))
  105.80 -
  105.81 -/* Check if a pte's page mapping or significant access flags have changed. */
  105.82 -#define l1e_has_changed_32(x,y,flags) \
  105.83 -    ( !!(((x).l1 ^ (y).l1) & ((PADDR_MASK&PAGE_MASK)|put_pte_flags_32(flags))) )
  105.84 -#define l2e_has_changed_32(x,y,flags) \
  105.85 -    ( !!(((x).l2 ^ (y).l2) & ((PADDR_MASK&PAGE_MASK)|put_pte_flags_32(flags))) )
  105.86 -
  105.87 -/* Given a virtual address, get an entry offset into a page table. */
  105.88 -#define l1_table_offset_32(a)         \
  105.89 -    (((a) >> L1_PAGETABLE_SHIFT_32) & (L1_PAGETABLE_ENTRIES_32 - 1))
  105.90 -#define l2_table_offset_32(a)         \
  105.91 -    (((a) >> L2_PAGETABLE_SHIFT_32) & (L2_PAGETABLE_ENTRIES_32 - 1))
  105.92 -
  105.93 -#endif /* __X86_PAGE_GUEST_H__ */
  105.94 -
  105.95 -/*
  105.96 - * Local variables:
  105.97 - * mode: C
  105.98 - * c-set-style: "BSD"
  105.99 - * c-basic-offset: 4
 105.100 - * tab-width: 4
 105.101 - * indent-tabs-mode: nil
 105.102 - * End:
 105.103 - */
   106.1 --- a/xen/arch/x86/mm/shadow/types.h	Mon Mar 12 09:43:48 2007 -0600
   106.2 +++ b/xen/arch/x86/mm/shadow/types.h	Mon Mar 12 10:07:08 2007 -0600
   106.3 @@ -235,7 +235,7 @@ static inline shadow_l4e_t shadow_l4e_fr
   106.4  
   106.5  #if GUEST_PAGING_LEVELS == 2
   106.6  
   106.7 -#include "page-guest32.h"
   106.8 +#include "../page-guest32.h"
   106.9  
  106.10  #define GUEST_L1_PAGETABLE_ENTRIES     1024
  106.11  #define GUEST_L2_PAGETABLE_ENTRIES     1024
   107.1 --- a/xen/arch/x86/setup.c	Mon Mar 12 09:43:48 2007 -0600
   107.2 +++ b/xen/arch/x86/setup.c	Mon Mar 12 10:07:08 2007 -0600
   107.3 @@ -195,13 +195,13 @@ static void __init percpu_free_unused_ar
   107.4  
   107.5      /* Find first unused CPU number. */
   107.6      for ( i = 0; i < NR_CPUS; i++ )
   107.7 -        if ( !cpu_online(i) )
   107.8 +        if ( !cpu_possible(i) )
   107.9              break;
  107.10      first_unused = i;
  107.11  
  107.12 -    /* Check that there are no holes in cpu_online_map. */
  107.13 +    /* Check that there are no holes in cpu_possible_map. */
  107.14      for ( ; i < NR_CPUS; i++ )
  107.15 -        BUG_ON(cpu_online(i));
  107.16 +        BUG_ON(cpu_possible(i));
  107.17  
  107.18  #ifndef MEMORY_GUARD
  107.19      init_xenheap_pages(__pa(__per_cpu_start) + (first_unused << PERCPU_SHIFT),
  107.20 @@ -717,8 +717,6 @@ void __init __start_xen(multiboot_info_t
  107.21  
  107.22      do_initcalls();
  107.23  
  107.24 -    schedulers_start();
  107.25 -
  107.26      if ( opt_watchdog ) 
  107.27          watchdog_enable();
  107.28  
   108.1 --- a/xen/common/compat/domain.c	Mon Mar 12 09:43:48 2007 -0600
   108.2 +++ b/xen/common/compat/domain.c	Mon Mar 12 10:07:08 2007 -0600
   108.3 @@ -55,6 +55,10 @@ int compat_vcpu_op(int cmd, int vcpuid, 
   108.4      case VCPUOP_up:
   108.5      case VCPUOP_down:
   108.6      case VCPUOP_is_up:
   108.7 +    case VCPUOP_set_periodic_timer:
   108.8 +    case VCPUOP_stop_periodic_timer:
   108.9 +    case VCPUOP_set_singleshot_timer:
  108.10 +    case VCPUOP_stop_singleshot_timer:
  108.11          rc = do_vcpu_op(cmd, vcpuid, arg);
  108.12          break;
  108.13  
   109.1 --- a/xen/common/domain.c	Mon Mar 12 09:43:48 2007 -0600
   109.2 +++ b/xen/common/domain.c	Mon Mar 12 10:07:08 2007 -0600
   109.3 @@ -267,6 +267,9 @@ void domain_kill(struct domain *d)
   109.4      domain_relinquish_resources(d);
   109.5      put_domain(d);
   109.6  
   109.7 +    /* Kick page scrubbing after domain_relinquish_resources(). */
   109.8 +    page_scrub_kick();
   109.9 +
  109.10      send_guest_global_virq(dom0, VIRQ_DOM_EXC);
  109.11  }
  109.12  
  109.13 @@ -543,16 +546,12 @@ long do_vcpu_op(int cmd, int vcpuid, XEN
  109.14      {
  109.15      case VCPUOP_initialise:
  109.16          if ( (ctxt = xmalloc(struct vcpu_guest_context)) == NULL )
  109.17 -        {
  109.18 -            rc = -ENOMEM;
  109.19 -            break;
  109.20 -        }
  109.21 +            return -ENOMEM;
  109.22  
  109.23          if ( copy_from_guest(ctxt, arg, 1) )
  109.24          {
  109.25              xfree(ctxt);
  109.26 -            rc = -EFAULT;
  109.27 -            break;
  109.28 +            return -EFAULT;
  109.29          }
  109.30  
  109.31          LOCK_BIGLOCK(d);
  109.32 @@ -566,9 +565,11 @@ long do_vcpu_op(int cmd, int vcpuid, XEN
  109.33  
  109.34      case VCPUOP_up:
  109.35          if ( !test_bit(_VCPUF_initialised, &v->vcpu_flags) )
  109.36 -            rc = -EINVAL;
  109.37 -        else if ( test_and_clear_bit(_VCPUF_down, &v->vcpu_flags) )
  109.38 +            return -EINVAL;
  109.39 +
  109.40 +        if ( test_and_clear_bit(_VCPUF_down, &v->vcpu_flags) )
  109.41              vcpu_wake(v);
  109.42 +
  109.43          break;
  109.44  
  109.45      case VCPUOP_down:
  109.46 @@ -589,6 +590,63 @@ long do_vcpu_op(int cmd, int vcpuid, XEN
  109.47          break;
  109.48      }
  109.49  
  109.50 +    case VCPUOP_set_periodic_timer:
  109.51 +    {
  109.52 +        struct vcpu_set_periodic_timer set;
  109.53 +
  109.54 +        if ( copy_from_guest(&set, arg, 1) )
  109.55 +            return -EFAULT;
  109.56 +
  109.57 +        if ( set.period_ns < MILLISECS(1) )
  109.58 +            return -EINVAL;
  109.59 +
  109.60 +        v->periodic_period = set.period_ns;
  109.61 +        vcpu_force_reschedule(v);
  109.62 +
  109.63 +        break;
  109.64 +    }
  109.65 +
  109.66 +    case VCPUOP_stop_periodic_timer:
  109.67 +    {
  109.68 +        v->periodic_period = 0;
  109.69 +        vcpu_force_reschedule(v);
  109.70 +        break;
  109.71 +    }
  109.72 +
  109.73 +    case VCPUOP_set_singleshot_timer:
  109.74 +    {
  109.75 +        struct vcpu_set_singleshot_timer set;
  109.76 +
  109.77 +        if ( v != current )
  109.78 +            return -EINVAL;
  109.79 +
  109.80 +        if ( copy_from_guest(&set, arg, 1) )
  109.81 +            return -EFAULT;
  109.82 +
  109.83 +        if ( (set.flags & VCPU_SSHOTTMR_future) &&
  109.84 +             (set.timeout_abs_ns < NOW()) )
  109.85 +            return -ETIME;
  109.86 +
  109.87 +        if ( v->singleshot_timer.cpu != smp_processor_id() )
  109.88 +        {
  109.89 +            stop_timer(&v->singleshot_timer);
  109.90 +            v->singleshot_timer.cpu = smp_processor_id();
  109.91 +        }
  109.92 +
  109.93 +        set_timer(&v->singleshot_timer, set.timeout_abs_ns);
  109.94 +
  109.95 +        break;
  109.96 +    }
  109.97 +
  109.98 +    case VCPUOP_stop_singleshot_timer:
  109.99 +    {
 109.100 +        if ( v != current )
 109.101 +            return -EINVAL;
 109.102 +
 109.103 +        stop_timer(&v->singleshot_timer);
 109.104 +        break;
 109.105 +    }
 109.106 +
 109.107      default:
 109.108          rc = arch_do_vcpu_op(cmd, v, arg);
 109.109          break;
   110.1 --- a/xen/common/event_channel.c	Mon Mar 12 09:43:48 2007 -0600
   110.2 +++ b/xen/common/event_channel.c	Mon Mar 12 10:07:08 2007 -0600
   110.3 @@ -560,6 +560,9 @@ void send_guest_global_virq(struct domai
   110.4  
   110.5      ASSERT(virq_is_global(virq));
   110.6  
   110.7 +    if ( unlikely(d == NULL) )
   110.8 +        return;
   110.9 +
  110.10      v = d->vcpu[0];
  110.11      if ( unlikely(v == NULL) )
  110.12          return;
   111.1 --- a/xen/common/keyhandler.c	Mon Mar 12 09:43:48 2007 -0600
   111.2 +++ b/xen/common/keyhandler.c	Mon Mar 12 10:07:08 2007 -0600
   111.3 @@ -47,7 +47,7 @@ void handle_keypress(unsigned char key, 
   111.4  {
   111.5      irq_keyhandler_t *h;
   111.6  
   111.7 -    if ( key_table[key].flags & KEYHANDLER_IRQ_CALLBACK )
   111.8 +    if ( !in_irq() || (key_table[key].flags & KEYHANDLER_IRQ_CALLBACK) )
   111.9      {
  111.10          console_start_log_everything();
  111.11          if ( (h = key_table[key].u.irq_handler) != NULL )
  111.12 @@ -135,12 +135,25 @@ static void cpuset_print(char *set, int 
  111.13      *set++ = '\0';
  111.14  }
  111.15  
  111.16 +static void periodic_timer_print(char *str, int size, uint64_t period)
  111.17 +{
  111.18 +    if ( period == 0 )
  111.19 +    {
  111.20 +        strlcpy(str, "No periodic timer", size);
  111.21 +        return;
  111.22 +    }
  111.23 +
  111.24 +    snprintf(str, size,
  111.25 +             "%u Hz periodic timer (period %u ms)",
  111.26 +             1000000000/(int)period, (int)period/1000000);
  111.27 +}
  111.28 +
  111.29  static void dump_domains(unsigned char key)
  111.30  {
  111.31      struct domain *d;
  111.32      struct vcpu   *v;
  111.33      s_time_t       now = NOW();
  111.34 -    char           cpuset[100];
  111.35 +    char           tmpstr[100];
  111.36  
  111.37      printk("'%c' pressed -> dumping domain info (now=0x%X:%08X)\n", key,
  111.38             (u32)(now>>32), (u32)now);
  111.39 @@ -150,11 +163,11 @@ static void dump_domains(unsigned char k
  111.40      for_each_domain ( d )
  111.41      {
  111.42          printk("General information for domain %u:\n", d->domain_id);
  111.43 -        cpuset_print(cpuset, sizeof(cpuset), d->domain_dirty_cpumask);
  111.44 +        cpuset_print(tmpstr, sizeof(tmpstr), d->domain_dirty_cpumask);
  111.45          printk("    flags=%lx refcnt=%d nr_pages=%d xenheap_pages=%d "
  111.46                 "dirty_cpus=%s\n",
  111.47                 d->domain_flags, atomic_read(&d->refcnt),
  111.48 -               d->tot_pages, d->xenheap_pages, cpuset);
  111.49 +               d->tot_pages, d->xenheap_pages, tmpstr);
  111.50          printk("    handle=%02x%02x%02x%02x-%02x%02x-%02x%02x-"
  111.51                 "%02x%02x-%02x%02x%02x%02x%02x%02x vm_assist=%08lx\n",
  111.52                 d->handle[ 0], d->handle[ 1], d->handle[ 2], d->handle[ 3],
  111.53 @@ -179,18 +192,21 @@ static void dump_domains(unsigned char k
  111.54                     v->vcpu_flags,
  111.55                     vcpu_info(v, evtchn_upcall_pending),
  111.56                     vcpu_info(v, evtchn_upcall_mask));
  111.57 -            cpuset_print(cpuset, sizeof(cpuset), v->vcpu_dirty_cpumask);
  111.58 -            printk("dirty_cpus=%s ", cpuset);
  111.59 -            cpuset_print(cpuset, sizeof(cpuset), v->cpu_affinity);
  111.60 -            printk("cpu_affinity=%s\n", cpuset);
  111.61 +            cpuset_print(tmpstr, sizeof(tmpstr), v->vcpu_dirty_cpumask);
  111.62 +            printk("dirty_cpus=%s ", tmpstr);
  111.63 +            cpuset_print(tmpstr, sizeof(tmpstr), v->cpu_affinity);
  111.64 +            printk("cpu_affinity=%s\n", tmpstr);
  111.65              arch_dump_vcpu_info(v);
  111.66 +            periodic_timer_print(tmpstr, sizeof(tmpstr), v->periodic_period);
  111.67 +            printk("    %s\n", tmpstr);
  111.68              printk("    Notifying guest (virq %d, port %d, stat %d/%d/%d)\n",
  111.69                     VIRQ_DEBUG, v->virq_to_evtchn[VIRQ_DEBUG],
  111.70                     test_bit(v->virq_to_evtchn[VIRQ_DEBUG], 
  111.71                              shared_info_addr(d, evtchn_pending)),
  111.72                     test_bit(v->virq_to_evtchn[VIRQ_DEBUG], 
  111.73                              shared_info_addr(d, evtchn_mask)),
  111.74 -                   test_bit(v->virq_to_evtchn[VIRQ_DEBUG]/BITS_PER_GUEST_LONG(d),
  111.75 +                   test_bit(v->virq_to_evtchn[VIRQ_DEBUG] /
  111.76 +                            BITS_PER_GUEST_LONG(d),
  111.77                              vcpu_info_addr(v, evtchn_pending_sel)));
  111.78              send_guest_vcpu_virq(v, VIRQ_DEBUG);
  111.79          }
   112.1 --- a/xen/common/page_alloc.c	Mon Mar 12 09:43:48 2007 -0600
   112.2 +++ b/xen/common/page_alloc.c	Mon Mar 12 10:07:08 2007 -0600
   112.3 @@ -49,7 +49,7 @@ string_param("badpage", opt_badpage);
   112.4   * Bit width of the DMA heap.
   112.5   */
   112.6  static unsigned int  dma_bitsize = CONFIG_DMA_BITSIZE;
   112.7 -static unsigned long max_dma_mfn = (1UL << (CONFIG_DMA_BITSIZE - PAGE_SHIFT)) - 1;
   112.8 +static unsigned long max_dma_mfn = (1UL<<(CONFIG_DMA_BITSIZE-PAGE_SHIFT))-1;
   112.9  static void parse_dma_bits(char *s)
  112.10  {
  112.11      unsigned int v = simple_strtol(s, NULL, 0);
  112.12 @@ -345,6 +345,7 @@ static struct page_info *alloc_heap_page
  112.13      unsigned int i, j, zone;
  112.14      unsigned int node = cpu_to_node(cpu), num_nodes = num_online_nodes();
  112.15      unsigned long request = 1UL << order;
  112.16 +    cpumask_t extra_cpus_mask, mask;
  112.17      struct page_info *pg;
  112.18  
  112.19      ASSERT(node >= 0);
  112.20 @@ -403,6 +404,29 @@ static struct page_info *alloc_heap_page
  112.21  
  112.22      spin_unlock(&heap_lock);
  112.23  
  112.24 +    cpus_clear(mask);
  112.25 +
  112.26 +    for ( i = 0; i < (1 << order); i++ )
  112.27 +    {
  112.28 +        /* Reference count must continuously be zero for free pages. */
  112.29 +        BUG_ON(pg[i].count_info != 0);
  112.30 +
  112.31 +        /* Add in any extra CPUs that need flushing because of this page. */
  112.32 +        cpus_andnot(extra_cpus_mask, pg[i].u.free.cpumask, mask);
  112.33 +        tlbflush_filter(extra_cpus_mask, pg[i].tlbflush_timestamp);
  112.34 +        cpus_or(mask, mask, extra_cpus_mask);
  112.35 +
  112.36 +        /* Initialise fields which have other uses for free pages. */
  112.37 +        pg[i].u.inuse.type_info = 0;
  112.38 +        page_set_owner(&pg[i], NULL);
  112.39 +    }
  112.40 +
  112.41 +    if ( unlikely(!cpus_empty(mask)) )
  112.42 +    {
  112.43 +        perfc_incrc(need_flush_tlb_flush);
  112.44 +        flush_tlb_mask(mask);
  112.45 +    }
  112.46 +
  112.47      return pg;
  112.48  }
  112.49  
  112.50 @@ -411,13 +435,28 @@ static void free_heap_pages(
  112.51      unsigned int zone, struct page_info *pg, unsigned int order)
  112.52  {
  112.53      unsigned long mask;
  112.54 -    unsigned int node = phys_to_nid(page_to_maddr(pg));
  112.55 +    unsigned int i, node = phys_to_nid(page_to_maddr(pg));
  112.56 +    struct domain *d;
  112.57  
  112.58      ASSERT(zone < NR_ZONES);
  112.59      ASSERT(order <= MAX_ORDER);
  112.60      ASSERT(node >= 0);
  112.61      ASSERT(node < num_online_nodes());
  112.62  
  112.63 +    for ( i = 0; i < (1 << order); i++ )
  112.64 +    {
  112.65 +        BUG_ON(pg[i].count_info != 0);
  112.66 +        if ( (d = page_get_owner(&pg[i])) != NULL )
  112.67 +        {
  112.68 +            pg[i].tlbflush_timestamp = tlbflush_current_time();
  112.69 +            pg[i].u.free.cpumask     = d->domain_dirty_cpumask;
  112.70 +        }
  112.71 +        else
  112.72 +        {
  112.73 +            cpus_clear(pg[i].u.free.cpumask);
  112.74 +        }
  112.75 +    }
  112.76 +
  112.77      spin_lock(&heap_lock);
  112.78  
  112.79      map_free(page_to_mfn(pg), 1 << order);
  112.80 @@ -554,7 +593,7 @@ void end_boot_allocator(void)
  112.81  /*
  112.82   * Scrub all unallocated pages in all heap zones. This function is more
  112.83   * convoluted than appears necessary because we do not want to continuously
  112.84 - * hold the lock or disable interrupts while scrubbing very large memory areas.
  112.85 + * hold the lock while scrubbing very large memory areas.
  112.86   */
  112.87  void scrub_heap_pages(void)
  112.88  {
  112.89 @@ -575,7 +614,7 @@ void scrub_heap_pages(void)
  112.90          if ( (mfn % ((100*1024*1024)/PAGE_SIZE)) == 0 )
  112.91              printk(".");
  112.92  
  112.93 -        spin_lock_irq(&heap_lock);
  112.94 +        spin_lock(&heap_lock);
  112.95  
  112.96          /* Re-check page status with lock held. */
  112.97          if ( !allocated_in_map(mfn) )
  112.98 @@ -595,7 +634,7 @@ void scrub_heap_pages(void)
  112.99              }
 112.100          }
 112.101  
 112.102 -        spin_unlock_irq(&heap_lock);
 112.103 +        spin_unlock(&heap_lock);
 112.104      }
 112.105  
 112.106      printk("done.\n");
 112.107 @@ -609,8 +648,6 @@ void scrub_heap_pages(void)
 112.108  
 112.109  void init_xenheap_pages(paddr_t ps, paddr_t pe)
 112.110  {
 112.111 -    unsigned long flags;
 112.112 -
 112.113      ps = round_pgup(ps);
 112.114      pe = round_pgdown(pe);
 112.115      if ( pe <= ps )
 112.116 @@ -625,34 +662,22 @@ void init_xenheap_pages(paddr_t ps, padd
 112.117      if ( !IS_XEN_HEAP_FRAME(maddr_to_page(pe)) )
 112.118          pe -= PAGE_SIZE;
 112.119  
 112.120 -    local_irq_save(flags);
 112.121      init_heap_pages(MEMZONE_XEN, maddr_to_page(ps), (pe - ps) >> PAGE_SHIFT);
 112.122 -    local_irq_restore(flags);
 112.123  }
 112.124  
 112.125  
 112.126  void *alloc_xenheap_pages(unsigned int order)
 112.127  {
 112.128 -    unsigned long flags;
 112.129      struct page_info *pg;
 112.130 -    int i;
 112.131  
 112.132 -    local_irq_save(flags);
 112.133 +    ASSERT(!in_irq());
 112.134 +
 112.135      pg = alloc_heap_pages(MEMZONE_XEN, MEMZONE_XEN, smp_processor_id(), order);
 112.136 -    local_irq_restore(flags);
 112.137 -
 112.138      if ( unlikely(pg == NULL) )
 112.139          goto no_memory;
 112.140  
 112.141      memguard_unguard_range(page_to_virt(pg), 1 << (order + PAGE_SHIFT));
 112.142  
 112.143 -    for ( i = 0; i < (1 << order); i++ )
 112.144 -    {
 112.145 -        pg[i].count_info        = 0;
 112.146 -        pg[i].u.inuse._domain   = 0;
 112.147 -        pg[i].u.inuse.type_info = 0;
 112.148 -    }
 112.149 -
 112.150      return page_to_virt(pg);
 112.151  
 112.152   no_memory:
 112.153 @@ -663,16 +688,14 @@ void *alloc_xenheap_pages(unsigned int o
 112.154  
 112.155  void free_xenheap_pages(void *v, unsigned int order)
 112.156  {
 112.157 -    unsigned long flags;
 112.158 +    ASSERT(!in_irq());
 112.159  
 112.160      if ( v == NULL )
 112.161          return;
 112.162  
 112.163 -    memguard_guard_range(v, 1 << (order + PAGE_SHIFT));    
 112.164 +    memguard_guard_range(v, 1 << (order + PAGE_SHIFT));
 112.165  
 112.166 -    local_irq_save(flags);
 112.167      free_heap_pages(MEMZONE_XEN, virt_to_page(v), order);
 112.168 -    local_irq_restore(flags);
 112.169  }
 112.170  
 112.171  
 112.172 @@ -762,8 +785,6 @@ struct page_info *__alloc_domheap_pages(
 112.173      unsigned int memflags)
 112.174  {
 112.175      struct page_info *pg = NULL;
 112.176 -    cpumask_t mask;
 112.177 -    unsigned long i;
 112.178      unsigned int bits = memflags >> _MEMF_bits, zone_hi = NR_ZONES - 1;
 112.179  
 112.180      ASSERT(!in_irq());
 112.181 @@ -792,38 +813,10 @@ struct page_info *__alloc_domheap_pages(
 112.182              return NULL;
 112.183      }
 112.184  
 112.185 -    if ( pg == NULL )
 112.186 -        if ( (pg = alloc_heap_pages(MEMZONE_XEN + 1,
 112.187 -                                    zone_hi,
 112.188 -                                    cpu, order)) == NULL )
 112.189 -            return NULL;
 112.190 -
 112.191 -    mask = pg->u.free.cpumask;
 112.192 -    tlbflush_filter(mask, pg->tlbflush_timestamp);
 112.193 -
 112.194 -    pg->count_info        = 0;
 112.195 -    pg->u.inuse._domain   = 0;
 112.196 -    pg->u.inuse.type_info = 0;
 112.197 -
 112.198 -    for ( i = 1; i < (1 << order); i++ )
 112.199 -    {
 112.200 -        /* Add in any extra CPUs that need flushing because of this page. */
 112.201 -        cpumask_t extra_cpus_mask;
 112.202 -        cpus_andnot(extra_cpus_mask, pg[i].u.free.cpumask, mask);
 112.203 -        tlbflush_filter(extra_cpus_mask, pg[i].tlbflush_timestamp);
 112.204 -        cpus_or(mask, mask, extra_cpus_mask);
 112.205 -
 112.206 -        pg[i].count_info        = 0;
 112.207 -        pg[i].u.inuse._domain   = 0;
 112.208 -        pg[i].u.inuse.type_info = 0;
 112.209 -        page_set_owner(&pg[i], NULL);
 112.210 -    }
 112.211 -
 112.212 -    if ( unlikely(!cpus_empty(mask)) )
 112.213 -    {
 112.214 -        perfc_incrc(need_flush_tlb_flush);
 112.215 -        flush_tlb_mask(mask);
 112.216 -    }
 112.217 +    if ( (pg == NULL) &&
 112.218 +         ((pg = alloc_heap_pages(MEMZONE_XEN + 1, zone_hi,
 112.219 +                                 cpu, order)) == NULL) )
 112.220 +         return NULL;
 112.221  
 112.222      if ( (d != NULL) && assign_pages(d, pg, order, memflags) )
 112.223      {
 112.224 @@ -867,10 +860,7 @@ void free_domheap_pages(struct page_info
 112.225  
 112.226          for ( i = 0; i < (1 << order); i++ )
 112.227          {
 112.228 -            shadow_drop_references(d, &pg[i]);
 112.229 -            ASSERT((pg[i].u.inuse.type_info & PGT_count_mask) == 0);
 112.230 -            pg[i].tlbflush_timestamp  = tlbflush_current_time();
 112.231 -            pg[i].u.free.cpumask      = d->domain_dirty_cpumask;
 112.232 +            BUG_ON((pg[i].u.inuse.type_info & PGT_count_mask) != 0);
 112.233              list_del(&pg[i].list);
 112.234          }
 112.235  
 112.236 @@ -892,6 +882,7 @@ void free_domheap_pages(struct page_info
 112.237               */
 112.238              for ( i = 0; i < (1 << order); i++ )
 112.239              {
 112.240 +                page_set_owner(&pg[i], NULL);
 112.241                  spin_lock(&page_scrub_lock);
 112.242                  list_add(&pg[i].list, &page_scrub_list);
 112.243                  scrub_pages++;
 112.244 @@ -902,8 +893,6 @@ void free_domheap_pages(struct page_info
 112.245      else
 112.246      {
 112.247          /* Freeing anonymous domain-heap pages. */
 112.248 -        for ( i = 0; i < (1 << order); i++ )
 112.249 -            cpus_clear(pg[i].u.free.cpumask);
 112.250          free_heap_pages(pfn_dom_zone_type(page_to_mfn(pg)), pg, order);
 112.251          drop_dom_ref = 0;
 112.252      }
 112.253 @@ -981,6 +970,8 @@ static __init int pagealloc_keyhandler_i
 112.254   * PAGE SCRUBBING
 112.255   */
 112.256  
 112.257 +static DEFINE_PER_CPU(struct timer, page_scrub_timer);
 112.258 +
 112.259  static void page_scrub_softirq(void)
 112.260  {
 112.261      struct list_head *ent;
 112.262 @@ -989,7 +980,7 @@ static void page_scrub_softirq(void)
 112.263      int               i;
 112.264      s_time_t          start = NOW();
 112.265  
 112.266 -    /* Aim to do 1ms of work (ten percent of a 10ms jiffy). */
 112.267 +    /* Aim to do 1ms of work every 10ms. */
 112.268      do {
 112.269          spin_lock(&page_scrub_lock);
 112.270  
 112.271 @@ -1025,6 +1016,13 @@ static void page_scrub_softirq(void)
 112.272              free_heap_pages(pfn_dom_zone_type(page_to_mfn(pg)), pg, 0);
 112.273          }
 112.274      } while ( (NOW() - start) < MILLISECS(1) );
 112.275 +
 112.276 +    set_timer(&this_cpu(page_scrub_timer), NOW() + MILLISECS(10));
 112.277 +}
 112.278 +
 112.279 +static void page_scrub_timer_fn(void *unused)
 112.280 +{
 112.281 +    page_scrub_schedule_work();
 112.282  }
 112.283  
 112.284  unsigned long avail_scrub_pages(void)
 112.285 @@ -1060,6 +1058,10 @@ static __init int register_heap_trigger(
 112.286  
 112.287  static __init int page_scrub_init(void)
 112.288  {
 112.289 +    int cpu;
 112.290 +    for_each_cpu ( cpu )
 112.291 +        init_timer(&per_cpu(page_scrub_timer, cpu),
 112.292 +                   page_scrub_timer_fn, NULL, cpu);
 112.293      open_softirq(PAGE_SCRUB_SOFTIRQ, page_scrub_softirq);
 112.294      return 0;
 112.295  }
   113.1 --- a/xen/common/sched_credit.c	Mon Mar 12 09:43:48 2007 -0600
   113.2 +++ b/xen/common/sched_credit.c	Mon Mar 12 10:07:08 2007 -0600
   113.3 @@ -186,6 +186,8 @@
   113.4  struct csched_pcpu {
   113.5      struct list_head runq;
   113.6      uint32_t runq_sort_last;
   113.7 +    struct timer ticker;
   113.8 +    unsigned int tick;
   113.9  };
  113.10  
  113.11  /*
  113.12 @@ -245,7 +247,7 @@ struct csched_private {
  113.13   */
  113.14  static struct csched_private csched_priv;
  113.15  
  113.16 -
  113.17 +static void csched_tick(void *_cpu);
  113.18  
  113.19  static inline int
  113.20  __cycle_cpu(int cpu, const cpumask_t *mask)
  113.21 @@ -362,12 +364,13 @@ csched_pcpu_init(int cpu)
  113.22      if ( csched_priv.master >= csched_priv.ncpus )
  113.23          csched_priv.master = cpu;
  113.24  
  113.25 +    init_timer(&spc->ticker, csched_tick, (void *)(unsigned long)cpu, cpu);
  113.26      INIT_LIST_HEAD(&spc->runq);
  113.27      spc->runq_sort_last = csched_priv.runq_sort;
  113.28      per_cpu(schedule_data, cpu).sched_priv = spc;
  113.29  
  113.30      /* Start off idling... */
  113.31 -    BUG_ON( !is_idle_vcpu(per_cpu(schedule_data, cpu).curr) );
  113.32 +    BUG_ON(!is_idle_vcpu(per_cpu(schedule_data, cpu).curr));
  113.33      cpu_set(cpu, csched_priv.idlers);
  113.34  
  113.35      spin_unlock_irqrestore(&csched_priv.lock, flags);
  113.36 @@ -1013,8 +1016,13 @@ csched_acct(void)
  113.37  }
  113.38  
  113.39  static void
  113.40 -csched_tick(unsigned int cpu)
  113.41 +csched_tick(void *_cpu)
  113.42  {
  113.43 +    unsigned int cpu = (unsigned long)_cpu;
  113.44 +    struct csched_pcpu *spc = CSCHED_PCPU(cpu);
  113.45 +
  113.46 +    spc->tick++;
  113.47 +
  113.48      /*
  113.49       * Accounting for running VCPU
  113.50       */
  113.51 @@ -1028,7 +1036,7 @@ csched_tick(unsigned int cpu)
  113.52       * we could distribute or at the very least cycle the duty.
  113.53       */
  113.54      if ( (csched_priv.master == cpu) &&
  113.55 -         (per_cpu(schedule_data, cpu).tick % CSCHED_TICKS_PER_ACCT) == 0 )
  113.56 +         (spc->tick % CSCHED_TICKS_PER_ACCT) == 0 )
  113.57      {
  113.58          csched_acct();
  113.59      }
  113.60 @@ -1041,6 +1049,8 @@ csched_tick(unsigned int cpu)
  113.61       * once per accounting period (currently 30 milliseconds).
  113.62       */
  113.63      csched_runq_sort(cpu);
  113.64 +
  113.65 +    set_timer(&spc->ticker, NOW() + MILLISECS(CSCHED_MSECS_PER_TICK));
  113.66  }
  113.67  
  113.68  static struct csched_vcpu *
  113.69 @@ -1248,8 +1258,7 @@ csched_dump_pcpu(int cpu)
  113.70      spc = CSCHED_PCPU(cpu);
  113.71      runq = &spc->runq;
  113.72  
  113.73 -    printk(" tick=%lu, sort=%d, sibling=0x%lx, core=0x%lx\n",
  113.74 -            per_cpu(schedule_data, cpu).tick,
  113.75 +    printk(" sort=%d, sibling=0x%lx, core=0x%lx\n",
  113.76              spc->runq_sort_last,
  113.77              cpu_sibling_map[cpu].bits[0],
  113.78              cpu_core_map[cpu].bits[0]);
  113.79 @@ -1341,6 +1350,22 @@ csched_init(void)
  113.80      CSCHED_STATS_RESET();
  113.81  }
  113.82  
  113.83 +/* Tickers cannot be kicked until SMP subsystem is alive. */
  113.84 +static __init int csched_start_tickers(void)
  113.85 +{
  113.86 +    struct csched_pcpu *spc;
  113.87 +    unsigned int cpu;
  113.88 +
  113.89 +    for_each_online_cpu ( cpu )
  113.90 +    {
  113.91 +        spc = CSCHED_PCPU(cpu);
  113.92 +        set_timer(&spc->ticker, NOW() + MILLISECS(CSCHED_MSECS_PER_TICK));
  113.93 +    }
  113.94 +
  113.95 +    return 0;
  113.96 +}
  113.97 +__initcall(csched_start_tickers);
  113.98 +
  113.99  
 113.100  struct scheduler sched_credit_def = {
 113.101      .name           = "SMP Credit Scheduler",
 113.102 @@ -1359,7 +1384,6 @@ struct scheduler sched_credit_def = {
 113.103      .adjust         = csched_dom_cntl,
 113.104  
 113.105      .pick_cpu       = csched_cpu_pick,
 113.106 -    .tick           = csched_tick,
 113.107      .do_schedule    = csched_schedule,
 113.108  
 113.109      .dump_cpu_state = csched_dump_pcpu,
   114.1 --- a/xen/common/schedule.c	Mon Mar 12 09:43:48 2007 -0600
   114.2 +++ b/xen/common/schedule.c	Mon Mar 12 10:07:08 2007 -0600
   114.3 @@ -45,8 +45,8 @@ boolean_param("dom0_vcpus_pin", opt_dom0
   114.4  
   114.5  /* Various timer handlers. */
   114.6  static void s_timer_fn(void *unused);
   114.7 -static void t_timer_fn(void *unused);
   114.8 -static void vcpu_timer_fn(void *data);
   114.9 +static void vcpu_periodic_timer_fn(void *data);
  114.10 +static void vcpu_singleshot_timer_fn(void *data);
  114.11  static void poll_timer_fn(void *data);
  114.12  
  114.13  /* This is global for now so that private implementations can reach it */
  114.14 @@ -66,9 +66,6 @@ static struct scheduler ops;
  114.15           (( ops.fn != NULL ) ? ops.fn( __VA_ARGS__ )      \
  114.16            : (typeof(ops.fn(__VA_ARGS__)))0 )
  114.17  
  114.18 -/* Per-CPU periodic timer sends an event to the currently-executing domain. */
  114.19 -static DEFINE_PER_CPU(struct timer, t_timer);
  114.20 -
  114.21  static inline void vcpu_runstate_change(
  114.22      struct vcpu *v, int new_state, s_time_t new_entry_time)
  114.23  {
  114.24 @@ -113,9 +110,13 @@ int sched_init_vcpu(struct vcpu *v, unsi
  114.25      else
  114.26          cpus_setall(v->cpu_affinity);
  114.27  
  114.28 -    /* Initialise the per-domain timers. */
  114.29 -    init_timer(&v->timer, vcpu_timer_fn, v, v->processor);
  114.30 -    init_timer(&v->poll_timer, poll_timer_fn, v, v->processor);
  114.31 +    /* Initialise the per-vcpu timers. */
  114.32 +    init_timer(&v->periodic_timer, vcpu_periodic_timer_fn,
  114.33 +               v, v->processor);
  114.34 +    init_timer(&v->singleshot_timer, vcpu_singleshot_timer_fn,
  114.35 +               v, v->processor);
  114.36 +    init_timer(&v->poll_timer, poll_timer_fn,
  114.37 +               v, v->processor);
  114.38  
  114.39      /* Idle VCPUs are scheduled immediately. */
  114.40      if ( is_idle_domain(d) )
  114.41 @@ -132,7 +133,8 @@ int sched_init_vcpu(struct vcpu *v, unsi
  114.42  
  114.43  void sched_destroy_vcpu(struct vcpu *v)
  114.44  {
  114.45 -    kill_timer(&v->timer);
  114.46 +    kill_timer(&v->periodic_timer);
  114.47 +    kill_timer(&v->singleshot_timer);
  114.48      kill_timer(&v->poll_timer);
  114.49      SCHED_OP(destroy_vcpu, v);
  114.50  }
  114.51 @@ -223,10 +225,29 @@ static void vcpu_migrate(struct vcpu *v)
  114.52      vcpu_wake(v);
  114.53  }
  114.54  
  114.55 +/*
  114.56 + * Force a VCPU through a deschedule/reschedule path.
  114.57 + * For example, using this when setting the periodic timer period means that
  114.58 + * most periodic-timer state need only be touched from within the scheduler
  114.59 + * which can thus be done without need for synchronisation.
  114.60 + */
  114.61 +void vcpu_force_reschedule(struct vcpu *v)
  114.62 +{
  114.63 +    vcpu_schedule_lock_irq(v);
  114.64 +    if ( test_bit(_VCPUF_running, &v->vcpu_flags) )
  114.65 +        set_bit(_VCPUF_migrating, &v->vcpu_flags);
  114.66 +    vcpu_schedule_unlock_irq(v);
  114.67 +
  114.68 +    if ( test_bit(_VCPUF_migrating, &v->vcpu_flags) )
  114.69 +    {
  114.70 +        vcpu_sleep_nosync(v);
  114.71 +        vcpu_migrate(v);
  114.72 +    }
  114.73 +}
  114.74 +
  114.75  int vcpu_set_affinity(struct vcpu *v, cpumask_t *affinity)
  114.76  {
  114.77      cpumask_t online_affinity;
  114.78 -    unsigned long flags;
  114.79  
  114.80      if ( (v->domain->domain_id == 0) && opt_dom0_vcpus_pin )
  114.81          return -EINVAL;
  114.82 @@ -235,13 +256,13 @@ int vcpu_set_affinity(struct vcpu *v, cp
  114.83      if ( cpus_empty(online_affinity) )
  114.84          return -EINVAL;
  114.85  
  114.86 -    vcpu_schedule_lock_irqsave(v, flags);
  114.87 +    vcpu_schedule_lock_irq(v);
  114.88  
  114.89      v->cpu_affinity = *affinity;
  114.90      if ( !cpu_isset(v->processor, v->cpu_affinity) )
  114.91          set_bit(_VCPUF_migrating, &v->vcpu_flags);
  114.92  
  114.93 -    vcpu_schedule_unlock_irqrestore(v, flags);
  114.94 +    vcpu_schedule_unlock_irq(v);
  114.95  
  114.96      if ( test_bit(_VCPUF_migrating, &v->vcpu_flags) )
  114.97      {
  114.98 @@ -450,7 +471,7 @@ ret_t do_sched_op(int cmd, XEN_GUEST_HAN
  114.99  
 114.100  #ifndef COMPAT
 114.101  
 114.102 -/* Per-domain one-shot-timer hypercall. */
 114.103 +/* Per-vcpu oneshot-timer hypercall. */
 114.104  long do_set_timer_op(s_time_t timeout)
 114.105  {
 114.106      struct vcpu *v = current;
 114.107 @@ -458,7 +479,7 @@ long do_set_timer_op(s_time_t timeout)
 114.108  
 114.109      if ( timeout == 0 )
 114.110      {
 114.111 -        stop_timer(&v->timer);
 114.112 +        stop_timer(&v->singleshot_timer);
 114.113      }
 114.114      else if ( unlikely(timeout < 0) || /* overflow into 64th bit? */
 114.115                unlikely((offset > 0) && ((uint32_t)(offset >> 50) != 0)) )
 114.116 @@ -474,14 +495,20 @@ long do_set_timer_op(s_time_t timeout)
 114.117           * timeout in this case can burn a lot of CPU. We therefore go for a
 114.118           * reasonable middleground of triggering a timer event in 100ms.
 114.119           */
 114.120 -        gdprintk(XENLOG_INFO, "Warning: huge timeout set by domain %d (vcpu %d):"
 114.121 -                " %"PRIx64"\n",
 114.122 +        gdprintk(XENLOG_INFO, "Warning: huge timeout set by domain %d "
 114.123 +                "(vcpu %d): %"PRIx64"\n",
 114.124                  v->domain->domain_id, v->vcpu_id, (uint64_t)timeout);
 114.125 -        set_timer(&v->timer, NOW() + MILLISECS(100));
 114.126 +        set_timer(&v->singleshot_timer, NOW() + MILLISECS(100));
 114.127      }
 114.128      else
 114.129      {
 114.130 -        set_timer(&v->timer, timeout);
 114.131 +        if ( v->singleshot_timer.cpu != smp_processor_id() )
 114.132 +        {
 114.133 +            stop_timer(&v->singleshot_timer);
 114.134 +            v->singleshot_timer.cpu = smp_processor_id();
 114.135 +        }
 114.136 +
 114.137 +        set_timer(&v->singleshot_timer, timeout);
 114.138      }
 114.139  
 114.140      return 0;
 114.141 @@ -540,6 +567,28 @@ long sched_adjust(struct domain *d, stru
 114.142      return 0;
 114.143  }
 114.144  
 114.145 +static void vcpu_periodic_timer_work(struct vcpu *v)
 114.146 +{
 114.147 +    s_time_t now = NOW();
 114.148 +    uint64_t periodic_next_event;
 114.149 +
 114.150 +    ASSERT(!active_timer(&v->periodic_timer));
 114.151 +
 114.152 +    if ( v->periodic_period == 0 )
 114.153 +        return;
 114.154 +
 114.155 +    periodic_next_event = v->periodic_last_event + v->periodic_period;
 114.156 +    if ( now > periodic_next_event )
 114.157 +    {
 114.158 +        send_timer_event(v);
 114.159 +        v->periodic_last_event = now;
 114.160 +        periodic_next_event = now + v->periodic_period;
 114.161 +    }
 114.162 +
 114.163 +    v->periodic_timer.cpu = smp_processor_id();
 114.164 +    set_timer(&v->periodic_timer, periodic_next_event);
 114.165 +}
 114.166 +
 114.167  /* 
 114.168   * The main function
 114.169   * - deschedule the current domain (scheduler independent).
 114.170 @@ -606,14 +655,13 @@ static void schedule(void)
 114.171  
 114.172      perfc_incrc(sched_ctx);
 114.173  
 114.174 -    prev->sleep_tick = sd->tick;
 114.175 +    stop_timer(&prev->periodic_timer);
 114.176  
 114.177      /* Ensure that the domain has an up-to-date time base. */
 114.178      if ( !is_idle_vcpu(next) )
 114.179      {
 114.180          update_vcpu_system_time(next);
 114.181 -        if ( next->sleep_tick != sd->tick )
 114.182 -            send_timer_event(next);
 114.183 +        vcpu_periodic_timer_work(next);
 114.184      }
 114.185  
 114.186      TRACE_4D(TRC_SCHED_SWITCH,
 114.187 @@ -631,13 +679,6 @@ void context_saved(struct vcpu *prev)
 114.188          vcpu_migrate(prev);
 114.189  }
 114.190  
 114.191 -/****************************************************************************
 114.192 - * Timers: the scheduler utilises a number of timers
 114.193 - * - s_timer: per CPU timer for preemption and scheduling decisions
 114.194 - * - t_timer: per CPU periodic timer to send timer interrupt to current dom
 114.195 - * - dom_timer: per domain timer to specifiy timeout values
 114.196 - ****************************************************************************/
 114.197 -
 114.198  /* The scheduler timer: force a run through the scheduler */
 114.199  static void s_timer_fn(void *unused)
 114.200  {
 114.201 @@ -645,28 +686,15 @@ static void s_timer_fn(void *unused)
 114.202      perfc_incrc(sched_irq);
 114.203  }
 114.204  
 114.205 -/* Periodic tick timer: send timer event to current domain */
 114.206 -static void t_timer_fn(void *unused)
 114.207 +/* Per-VCPU periodic timer function: sends a virtual timer interrupt. */
 114.208 +static void vcpu_periodic_timer_fn(void *data)
 114.209  {
 114.210 -    struct vcpu *v   = current;
 114.211 -
 114.212 -    this_cpu(schedule_data).tick++;
 114.213 -
 114.214 -    if ( !is_idle_vcpu(v) )
 114.215 -    {
 114.216 -        update_vcpu_system_time(v);
 114.217 -        send_timer_event(v);
 114.218 -    }
 114.219 -
 114.220 -    page_scrub_schedule_work();
 114.221 -
 114.222 -    SCHED_OP(tick, smp_processor_id());
 114.223 -
 114.224 -    set_timer(&this_cpu(t_timer), NOW() + MILLISECS(10));
 114.225 +    struct vcpu *v = data;
 114.226 +    vcpu_periodic_timer_work(v);
 114.227  }
 114.228  
 114.229 -/* Per-VCPU timer function: sends a virtual timer interrupt. */
 114.230 -static void vcpu_timer_fn(void *data)
 114.231 +/* Per-VCPU single-shot timer function: sends a virtual timer interrupt. */
 114.232 +static void vcpu_singleshot_timer_fn(void *data)
 114.233  {
 114.234      struct vcpu *v = data;
 114.235      send_timer_event(v);
 114.236 @@ -691,7 +719,6 @@ void __init scheduler_init(void)
 114.237      {
 114.238          spin_lock_init(&per_cpu(schedule_data, i).schedule_lock);
 114.239          init_timer(&per_cpu(schedule_data, i).s_timer, s_timer_fn, NULL, i);
 114.240 -        init_timer(&per_cpu(t_timer, i), t_timer_fn, NULL, i);
 114.241      }
 114.242  
 114.243      for ( i = 0; schedulers[i] != NULL; i++ )
 114.244 @@ -708,16 +735,6 @@ void __init scheduler_init(void)
 114.245      SCHED_OP(init);
 114.246  }
 114.247  
 114.248 -/*
 114.249 - * Start a scheduler for each CPU
 114.250 - * This has to be done *after* the timers, e.g., APICs, have been initialised
 114.251 - */
 114.252 -void schedulers_start(void) 
 114.253 -{   
 114.254 -    t_timer_fn(0);
 114.255 -    smp_call_function((void *)t_timer_fn, NULL, 1, 1);
 114.256 -}
 114.257 -
 114.258  void dump_runq(unsigned char key)
 114.259  {
 114.260      s_time_t      now = NOW();
   115.1 --- a/xen/common/sysctl.c	Mon Mar 12 09:43:48 2007 -0600
   115.2 +++ b/xen/common/sysctl.c	Mon Mar 12 10:07:08 2007 -0600
   115.3 @@ -18,6 +18,7 @@
   115.4  #include <xen/console.h>
   115.5  #include <xen/iocap.h>
   115.6  #include <xen/guest_access.h>
   115.7 +#include <xen/keyhandler.h>
   115.8  #include <asm/current.h>
   115.9  #include <public/sysctl.h>
  115.10  
  115.11 @@ -121,6 +122,20 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysc
  115.12      break;
  115.13  #endif
  115.14  
  115.15 +    case XEN_SYSCTL_debug_keys:
  115.16 +    {
  115.17 +        char c;
  115.18 +        uint32_t i;
  115.19 +
  115.20 +        for ( i = 0; i < op->u.debug_keys.nr_keys; i++ )
  115.21 +        {
  115.22 +            if ( copy_from_guest_offset(&c, op->u.debug_keys.keys, i, 1) )
  115.23 +                return -EFAULT;
  115.24 +            handle_keypress(c, guest_cpu_user_regs());
  115.25 +        }
  115.26 +    }
  115.27 +    break;
  115.28 +
  115.29      default:
  115.30          ret = arch_do_sysctl(op, u_sysctl);
  115.31          break;
   116.1 --- a/xen/common/xmalloc.c	Mon Mar 12 09:43:48 2007 -0600
   116.2 +++ b/xen/common/xmalloc.c	Mon Mar 12 10:07:08 2007 -0600
   116.3 @@ -33,6 +33,8 @@
   116.4  #include <xen/timer.h>
   116.5  #include <xen/cache.h>
   116.6  #include <xen/prefetch.h>
   116.7 +#include <xen/irq.h>
   116.8 +#include <xen/smp.h>
   116.9  
  116.10  /*
  116.11   * XMALLOC_DEBUG:
  116.12 @@ -175,6 +177,8 @@ void *_xmalloc(size_t size, size_t align
  116.13      struct xmalloc_hdr *i;
  116.14      unsigned long flags;
  116.15  
  116.16 +    ASSERT(!in_irq());
  116.17 +
  116.18      /* We currently always return cacheline aligned. */
  116.19      BUG_ON(align > SMP_CACHE_BYTES);
  116.20  
  116.21 @@ -213,6 +217,8 @@ void xfree(void *p)
  116.22      unsigned long flags;
  116.23      struct xmalloc_hdr *i, *tmp, *hdr;
  116.24  
  116.25 +    ASSERT(!in_irq());
  116.26 +
  116.27      if ( p == NULL )
  116.28          return;
  116.29  
   117.1 --- a/xen/drivers/char/console.c	Mon Mar 12 09:43:48 2007 -0600
   117.2 +++ b/xen/drivers/char/console.c	Mon Mar 12 10:07:08 2007 -0600
   117.3 @@ -399,6 +399,8 @@ static void __putstr(const char *str)
   117.4          vga_putchar(c);
   117.5          putchar_console_ring(c);
   117.6      }
   117.7 +
   117.8 +    send_guest_global_virq(dom0, VIRQ_CON_RING);
   117.9  }
  117.10  
  117.11  static int printk_prefix_check(char *p, char **pp)
   118.1 --- a/xen/include/asm-x86/domain.h	Mon Mar 12 09:43:48 2007 -0600
   118.2 +++ b/xen/include/asm-x86/domain.h	Mon Mar 12 10:07:08 2007 -0600
   118.3 @@ -104,6 +104,21 @@ struct shadow_vcpu {
   118.4  };
   118.5  
   118.6  /************************************************/
   118.7 +/*            hardware assisted paging          */
   118.8 +/************************************************/
   118.9 +struct hap_domain {
  118.10 +    spinlock_t        lock;
  118.11 +    int               locker;
  118.12 +    const char       *locker_function;
  118.13 +    
  118.14 +    struct list_head  freelists;
  118.15 +    struct list_head  p2m_freelist;
  118.16 +    unsigned int      total_pages;  /* number of pages allocated */
  118.17 +    unsigned int      free_pages;   /* number of pages on freelists */
  118.18 +    unsigned int      p2m_pages;    /* number of pages allocates to p2m */
  118.19 +};
  118.20 +
  118.21 +/************************************************/
  118.22  /*       p2m handling                           */
  118.23  /************************************************/
  118.24  
  118.25 @@ -135,6 +150,7 @@ struct paging_domain {
  118.26      struct shadow_domain shadow;
  118.27  
  118.28      /* Other paging assistance code will have structs here */
  118.29 +    struct hap_domain    hap;
  118.30  };
  118.31  
  118.32  struct paging_vcpu {
   119.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   119.2 +++ b/xen/include/asm-x86/hap.h	Mon Mar 12 10:07:08 2007 -0600
   119.3 @@ -0,0 +1,122 @@
   119.4 +/******************************************************************************
   119.5 + * include/asm-x86/hap.h
   119.6 + *
   119.7 + * hardware-assisted paging
   119.8 + * Copyright (c) 2007 Advanced Micro Devices (Wei Huang)
   119.9 + * 
  119.10 + * Parts of this code are Copyright (c) 2006 by XenSource Inc.
  119.11 + * Parts of this code are Copyright (c) 2006 by Michael A Fetterman
  119.12 + * Parts based on earlier work by Michael A Fetterman, Ian Pratt et al.
  119.13 + *
  119.14 + * This program is free software; you can redistribute it and/or modify
  119.15 + * it under the terms of the GNU General Public License as published by
  119.16 + * the Free Software Foundation; either version 2 of the License, or
  119.17 + * (at your option) any later version.
  119.18 + *
  119.19 + * This program is distributed in the hope that it will be useful,
  119.20 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  119.21 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  119.22 + * GNU General Public License for more details.
  119.23 + *
  119.24 + * You should have received a copy of the GNU General Public License
  119.25 + * along with this program; if not, write to the Free Software
  119.26 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  119.27 + */
  119.28 +
  119.29 +#ifndef _XEN_HAP_H
  119.30 +#define _XEN_HAP_H
  119.31 +
  119.32 +#define HERE_I_AM                                                     \
  119.33 +    debugtrace_printk("HERE I AM: %s %s %d\n", __func__, __FILE__, __LINE__)
  119.34 +#define HAP_PRINTK(_f, _a...)                                         \
  119.35 +    debugtrace_printk("hap: %s(): " _f, __func__, ##_a)
  119.36 +#define HAP_ERROR(_f, _a...)                                          \
  119.37 +    printk("hap error: %s(): " _f, __func__, ##_a)
  119.38 +
  119.39 +/************************************************/
  119.40 +/*          hap domain page mapping             */
  119.41 +/************************************************/
  119.42 +static inline void *
  119.43 +hap_map_domain_page(mfn_t mfn)
  119.44 +{
  119.45 +    return map_domain_page(mfn_x(mfn));
  119.46 +}
  119.47 +
  119.48 +static inline void
  119.49 +hap_unmap_domain_page(void *p)
  119.50 +{
  119.51 +    unmap_domain_page(p);
  119.52 +}
  119.53 +
  119.54 +static inline void *
  119.55 +hap_map_domain_page_global(mfn_t mfn)
  119.56 +{
  119.57 +    return map_domain_page_global(mfn_x(mfn));
  119.58 +}
  119.59 +
  119.60 +static inline void 
  119.61 +hap_unmap_domain_page_global(void *p) 
  119.62 +{
  119.63 +    unmap_domain_page_global(p);
  119.64 +}
  119.65 +
  119.66 +/************************************************/
  119.67 +/*           locking for hap code               */
  119.68 +/************************************************/
  119.69 +#define hap_lock_init(_d)                                   \
  119.70 +    do {                                                    \
  119.71 +        spin_lock_init(&(_d)->arch.paging.hap.lock);        \
  119.72 +        (_d)->arch.paging.hap.locker = -1;                  \
  119.73 +        (_d)->arch.paging.hap.locker_function = "nobody";   \
  119.74 +    } while (0)
  119.75 +
  119.76 +#define hap_locked_by_me(_d)                     \
  119.77 +    (current->processor == (_d)->arch.paging.hap.locker)
  119.78 +
  119.79 +#define hap_lock(_d)                                                       \
  119.80 +    do {                                                                   \
  119.81 +        if ( unlikely((_d)->arch.paging.hap.locker == current->processor) )\
  119.82 +        {                                                                  \
  119.83 +            printk("Error: hap lock held by %s\n",                         \
  119.84 +                   (_d)->arch.paging.hap.locker_function);                 \
  119.85 +            BUG();                                                         \
  119.86 +        }                                                                  \
  119.87 +        spin_lock(&(_d)->arch.paging.hap.lock);                            \
  119.88 +        ASSERT((_d)->arch.paging.hap.locker == -1);                        \
  119.89 +        (_d)->arch.paging.hap.locker = current->processor;                 \
  119.90 +        (_d)->arch.paging.hap.locker_function = __func__;                  \
  119.91 +    } while (0)
  119.92 +
  119.93 +#define hap_unlock(_d)                                              \
  119.94 +    do {                                                            \
  119.95 +        ASSERT((_d)->arch.paging.hap.locker == current->processor); \
  119.96 +        (_d)->arch.paging.hap.locker = -1;                          \
  119.97 +        (_d)->arch.paging.hap.locker_function = "nobody";           \
  119.98 +        spin_unlock(&(_d)->arch.paging.hap.lock);                   \
  119.99 +    } while (0)
 119.100 +
 119.101 +/************************************************/
 119.102 +/*        hap domain level functions            */
 119.103 +/************************************************/
 119.104 +void  hap_domain_init(struct domain *d);
 119.105 +int   hap_domctl(struct domain *d, xen_domctl_shadow_op_t *sc,
 119.106 +                 XEN_GUEST_HANDLE(void) u_domctl);
 119.107 +int   hap_enable(struct domain *d, u32 mode);
 119.108 +void  hap_final_teardown(struct domain *d);
 119.109 +void  hap_teardown(struct domain *d);
 119.110 +void  hap_vcpu_init(struct vcpu *v);
 119.111 +
 119.112 +extern struct paging_mode hap_paging_real_mode;
 119.113 +extern struct paging_mode hap_paging_protected_mode;
 119.114 +extern struct paging_mode hap_paging_pae_mode;
 119.115 +extern struct paging_mode hap_paging_long_mode;
 119.116 +#endif /* XEN_HAP_H */
 119.117 +
 119.118 +/*
 119.119 + * Local variables:
 119.120 + * mode: C
 119.121 + * c-set-style: "BSD"
 119.122 + * c-basic-offset: 4
 119.123 + * indent-tabs-mode: nil
 119.124 + * End:
 119.125 + */
   120.1 --- a/xen/include/asm-x86/hvm/svm/vmcb.h	Mon Mar 12 09:43:48 2007 -0600
   120.2 +++ b/xen/include/asm-x86/hvm/svm/vmcb.h	Mon Mar 12 10:07:08 2007 -0600
   120.3 @@ -460,7 +460,6 @@ struct arch_svm_struct {
   120.4  struct vmcb_struct *alloc_vmcb(void);
   120.5  struct host_save_area *alloc_host_save_area(void);
   120.6  void free_vmcb(struct vmcb_struct *vmcb);
   120.7 -void free_host_save_area(struct host_save_area *hsa);
   120.8  
   120.9  int  svm_create_vmcb(struct vcpu *v);
  120.10  void svm_destroy_vmcb(struct vcpu *v);
   121.1 --- a/xen/include/asm-x86/hvm/vpt.h	Mon Mar 12 09:43:48 2007 -0600
   121.2 +++ b/xen/include/asm-x86/hvm/vpt.h	Mon Mar 12 10:07:08 2007 -0600
   121.3 @@ -92,6 +92,7 @@ typedef struct RTCState {
   121.4      struct timer second_timer;
   121.5      struct timer second_timer2;
   121.6      struct periodic_time pt;
   121.7 +    int32_t time_offset_seconds;
   121.8  } RTCState;
   121.9  
  121.10  #define FREQUENCE_PMTIMER  3579545  /* Timer should run at 3.579545 MHz */
   122.1 --- a/xen/include/asm-x86/paging.h	Mon Mar 12 09:43:48 2007 -0600
   122.2 +++ b/xen/include/asm-x86/paging.h	Mon Mar 12 10:07:08 2007 -0600
   122.3 @@ -273,7 +273,7 @@ static inline void paging_write_p2m_entr
   122.4      struct vcpu *v = current;
   122.5      if ( v->domain != d )
   122.6          v = d->vcpu[0];
   122.7 -    if ( likely(paging_mode_enabled(d) && v->arch.paging.mode != NULL) )
   122.8 +    if ( likely(v && paging_mode_enabled(d) && v->arch.paging.mode != NULL) )
   122.9      {
  122.10          return v->arch.paging.mode->write_p2m_entry(v, gfn, p, new, level);
  122.11      }
   123.1 --- a/xen/include/public/hvm/hvm_op.h	Mon Mar 12 09:43:48 2007 -0600
   123.2 +++ b/xen/include/public/hvm/hvm_op.h	Mon Mar 12 10:07:08 2007 -0600
   123.3 @@ -70,4 +70,12 @@ struct xen_hvm_set_pci_link_route {
   123.4  typedef struct xen_hvm_set_pci_link_route xen_hvm_set_pci_link_route_t;
   123.5  DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_pci_link_route_t);
   123.6  
   123.7 +/* Drain all outstanding qemu-dm IO responses from a domain's ioreq ring. */
   123.8 +#define HVMOP_drain_io            5
   123.9 +struct xen_hvm_drain_io {
  123.10 +    domid_t  domid;
  123.11 +};
  123.12 +typedef struct xen_hvm_drain_io xen_hvm_drain_io_t;
  123.13 +DEFINE_XEN_GUEST_HANDLE(xen_hvm_drain_io_t);
  123.14 +
  123.15  #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
   124.1 --- a/xen/include/public/sysctl.h	Mon Mar 12 09:43:48 2007 -0600
   124.2 +++ b/xen/include/public/sysctl.h	Mon Mar 12 10:07:08 2007 -0600
   124.3 @@ -140,6 +140,18 @@ struct xen_sysctl_getdomaininfolist {
   124.4  typedef struct xen_sysctl_getdomaininfolist xen_sysctl_getdomaininfolist_t;
   124.5  DEFINE_XEN_GUEST_HANDLE(xen_sysctl_getdomaininfolist_t);
   124.6  
   124.7 +/*
   124.8 + * Inject debug keys into Xen.
   124.9 + */
  124.10 +#define XEN_SYSCTL_debug_keys        7
  124.11 +struct xen_sysctl_debug_keys {
  124.12 +    /* IN variables. */
  124.13 +    XEN_GUEST_HANDLE_64(char) keys;
  124.14 +    uint32_t nr_keys;
  124.15 +};
  124.16 +typedef struct xen_sysctl_debug_keys xen_sysctl_debug_keys_t;
  124.17 +DEFINE_XEN_GUEST_HANDLE(xen_sysctl_debug_keys_t);
  124.18 +
  124.19  struct xen_sysctl {
  124.20      uint32_t cmd;
  124.21      uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */
  124.22 @@ -150,6 +162,7 @@ struct xen_sysctl {
  124.23          struct xen_sysctl_sched_id          sched_id;
  124.24          struct xen_sysctl_perfc_op          perfc_op;
  124.25          struct xen_sysctl_getdomaininfolist getdomaininfolist;
  124.26 +        struct xen_sysctl_debug_keys        debug_keys;
  124.27          uint8_t                             pad[128];
  124.28      } u;
  124.29  };
   125.1 --- a/xen/include/public/vcpu.h	Mon Mar 12 09:43:48 2007 -0600
   125.2 +++ b/xen/include/public/vcpu.h	Mon Mar 12 10:07:08 2007 -0600
   125.3 @@ -42,13 +42,13 @@
   125.4   * @extra_arg == pointer to vcpu_guest_context structure containing initial
   125.5   *               state for the VCPU.
   125.6   */
   125.7 -#define VCPUOP_initialise           0
   125.8 +#define VCPUOP_initialise            0
   125.9  
  125.10  /*
  125.11   * Bring up a VCPU. This makes the VCPU runnable. This operation will fail
  125.12   * if the VCPU has not been initialised (VCPUOP_initialise).
  125.13   */
  125.14 -#define VCPUOP_up                   1
  125.15 +#define VCPUOP_up                    1
  125.16  
  125.17  /*
  125.18   * Bring down a VCPU (i.e., make it non-runnable).
  125.19 @@ -64,16 +64,16 @@
  125.20   *     practise to move a VCPU onto an 'idle' or default page table, LDT and
  125.21   *     GDT before bringing it down.
  125.22   */
  125.23 -#define VCPUOP_down                 2
  125.24 +#define VCPUOP_down                  2
  125.25  
  125.26  /* Returns 1 if the given VCPU is up. */
  125.27 -#define VCPUOP_is_up                3
  125.28 +#define VCPUOP_is_up                 3
  125.29  
  125.30  /*
  125.31   * Return information about the state and running time of a VCPU.
  125.32   * @extra_arg == pointer to vcpu_runstate_info structure.
  125.33   */
  125.34 -#define VCPUOP_get_runstate_info    4
  125.35 +#define VCPUOP_get_runstate_info     4
  125.36  struct vcpu_runstate_info {
  125.37      /* VCPU's current state (RUNSTATE_*). */
  125.38      int      state;
  125.39 @@ -128,6 +128,38 @@ struct vcpu_register_runstate_memory_are
  125.40      } addr;
  125.41  };
  125.42  typedef struct vcpu_register_runstate_memory_area vcpu_register_runstate_memory_area_t;
  125.43 +DEFINE_XEN_GUEST_HANDLE(vcpu_register_runstate_memory_area_t);
  125.44 +
  125.45 +/*
  125.46 + * Set or stop a VCPU's periodic timer. Every VCPU has one periodic timer
  125.47 + * which can be set via these commands. Periods smaller than one millisecond
  125.48 + * may not be supported.
  125.49 + */
  125.50 +#define VCPUOP_set_periodic_timer    6 /* arg == vcpu_set_periodic_timer_t */
  125.51 +#define VCPUOP_stop_periodic_timer   7 /* arg == NULL */
  125.52 +struct vcpu_set_periodic_timer {
  125.53 +    uint64_t period_ns;
  125.54 +};
  125.55 +typedef struct vcpu_set_periodic_timer vcpu_set_periodic_timer_t;
  125.56 +DEFINE_XEN_GUEST_HANDLE(vcpu_set_periodic_timer_t);
  125.57 +
  125.58 +/*
  125.59 + * Set or stop a VCPU's single-shot timer. Every VCPU has one single-shot
  125.60 + * timer which can be set via these commands.
  125.61 + */
  125.62 +#define VCPUOP_set_singleshot_timer  8 /* arg == vcpu_set_singleshot_timer_t */
  125.63 +#define VCPUOP_stop_singleshot_timer 9 /* arg == NULL */
  125.64 +struct vcpu_set_singleshot_timer {
  125.65 +    uint64_t timeout_abs_ns;   /* Absolute system time value in nanoseconds. */
  125.66 +    uint32_t flags;            /* VCPU_SSHOTTMR_??? */
  125.67 +};
  125.68 +typedef struct vcpu_set_singleshot_timer vcpu_set_singleshot_timer_t;
  125.69 +DEFINE_XEN_GUEST_HANDLE(vcpu_set_singleshot_timer_t);
  125.70 +
  125.71 +/* Flags to VCPUOP_set_singleshot_timer. */
  125.72 + /* Require the timeout to be in the future (return -ETIME if it's passed). */
  125.73 +#define _VCPU_SSHOTTMR_future (0)
  125.74 +#define VCPU_SSHOTTMR_future  (1U << _VCPU_SSHOTTMR_future)
  125.75  
  125.76  #endif /* __XEN_PUBLIC_VCPU_H__ */
  125.77  
   126.1 --- a/xen/include/public/xen.h	Mon Mar 12 09:43:48 2007 -0600
   126.2 +++ b/xen/include/public/xen.h	Mon Mar 12 10:07:08 2007 -0600
   126.3 @@ -131,6 +131,7 @@
   126.4  #define VIRQ_TBUF       4  /* G. (DOM0) Trace buffer has records available.  */
   126.5  #define VIRQ_DEBUGGER   6  /* G. (DOM0) A domain has paused for debugging.   */
   126.6  #define VIRQ_XENOPROF   7  /* V. XenOprofile interrupt: new sample available */
   126.7 +#define VIRQ_CON_RING   8  /* G. (DOM0) Bytes received on console            */
   126.8  
   126.9  /* Architecture-specific VIRQ definitions. */
  126.10  #define VIRQ_ARCH_0    16
   127.1 --- a/xen/include/xen/mm.h	Mon Mar 12 09:43:48 2007 -0600
   127.2 +++ b/xen/include/xen/mm.h	Mon Mar 12 10:07:08 2007 -0600
   127.3 @@ -92,6 +92,11 @@ extern struct list_head page_scrub_list;
   127.4          if ( !list_empty(&page_scrub_list) )    \
   127.5              raise_softirq(PAGE_SCRUB_SOFTIRQ);  \
   127.6      } while ( 0 )
   127.7 +#define page_scrub_kick()                                               \
   127.8 +    do {                                                                \
   127.9 +        if ( !list_empty(&page_scrub_list) )                            \
  127.10 +            cpumask_raise_softirq(cpu_online_map, PAGE_SCRUB_SOFTIRQ);  \
  127.11 +    } while ( 0 )
  127.12  unsigned long avail_scrub_pages(void);
  127.13  
  127.14  #include <asm/mm.h>
   128.1 --- a/xen/include/xen/sched-if.h	Mon Mar 12 09:43:48 2007 -0600
   128.2 +++ b/xen/include/xen/sched-if.h	Mon Mar 12 10:07:08 2007 -0600
   128.3 @@ -16,7 +16,6 @@ struct schedule_data {
   128.4      struct vcpu        *idle;           /* idle task for this cpu          */
   128.5      void               *sched_priv;
   128.6      struct timer        s_timer;        /* scheduling timer                */
   128.7 -    unsigned long       tick;           /* current periodic 'tick'         */
   128.8  } __cacheline_aligned;
   128.9  
  128.10  DECLARE_PER_CPU(struct schedule_data, schedule_data);
  128.11 @@ -61,7 +60,6 @@ struct scheduler {
  128.12      unsigned int sched_id;  /* ID for this scheduler             */
  128.13  
  128.14      void         (*init)           (void);
  128.15 -    void         (*tick)           (unsigned int cpu);
  128.16  
  128.17      int          (*init_domain)    (struct domain *);
  128.18      void         (*destroy_domain) (struct domain *);
   129.1 --- a/xen/include/xen/sched.h	Mon Mar 12 09:43:48 2007 -0600
   129.2 +++ b/xen/include/xen/sched.h	Mon Mar 12 10:07:08 2007 -0600
   129.3 @@ -79,8 +79,10 @@ struct vcpu
   129.4  
   129.5      struct vcpu     *next_in_list;
   129.6  
   129.7 -    struct timer     timer;         /* one-shot timer for timeout values */
   129.8 -    unsigned long    sleep_tick;    /* tick at which this vcpu started sleep */
   129.9 +    uint64_t         periodic_period;
  129.10 +    uint64_t         periodic_last_event;
  129.11 +    struct timer     periodic_timer;
  129.12 +    struct timer     singleshot_timer;
  129.13  
  129.14      struct timer     poll_timer;    /* timeout for SCHEDOP_poll */
  129.15  
  129.16 @@ -332,7 +334,6 @@ void __domain_crash_synchronous(void) __
  129.17  
  129.18  #define set_current_state(_s) do { current->state = (_s); } while (0)
  129.19  void scheduler_init(void);
  129.20 -void schedulers_start(void);
  129.21  int  sched_init_vcpu(struct vcpu *v, unsigned int processor);
  129.22  void sched_destroy_vcpu(struct vcpu *v);
  129.23  int  sched_init_domain(struct domain *d);
  129.24 @@ -497,6 +498,7 @@ void domain_pause_by_systemcontroller(st
  129.25  void domain_unpause_by_systemcontroller(struct domain *d);
  129.26  void cpu_init(void);
  129.27  
  129.28 +void vcpu_force_reschedule(struct vcpu *v);
  129.29  int vcpu_set_affinity(struct vcpu *v, cpumask_t *affinity);
  129.30  
  129.31  void vcpu_runstate_get(struct vcpu *v, struct vcpu_runstate_info *runstate);
   130.1 --- a/xen/include/xen/timer.h	Mon Mar 12 09:43:48 2007 -0600
   130.2 +++ b/xen/include/xen/timer.h	Mon Mar 12 10:07:08 2007 -0600
   130.3 @@ -35,7 +35,7 @@ struct timer {
   130.4   * The timer must *previously* have been initialised by init_timer(), or its
   130.5   * structure initialised to all-zeroes.
   130.6   */
   130.7 -static __inline__ int active_timer(struct timer *timer)
   130.8 +static inline int active_timer(struct timer *timer)
   130.9  {
  130.10      return (timer->heap_offset != 0);
  130.11  }
  130.12 @@ -46,7 +46,7 @@ static __inline__ int active_timer(struc
  130.13   * time (and multiple times) on an inactive timer. It must *never* execute
  130.14   * concurrently with any other operation on the same timer.
  130.15   */
  130.16 -static __inline__ void init_timer(
  130.17 +static inline void init_timer(
  130.18      struct timer *timer,
  130.19      void           (*function)(void *),
  130.20      void            *data,