ia64/xen-unstable

changeset 14762:eb3e430242ac

merge with xen-unstable.hg
author Alex Williamson <alex.williamson@hp.com>
date Fri Apr 06 10:08:30 2007 -0600 (2007-04-06)
parents 9ec7dadc98ba ef33477324f6
children cd3cfddcb055 aeb9a84e46d9
files tools/libxc/xc_hvm_restore.c tools/libxc/xc_linux_restore.c
line diff
     1.1 --- a/.hgignore	Fri Apr 06 10:06:30 2007 -0600
     1.2 +++ b/.hgignore	Fri Apr 06 10:08:30 2007 -0600
     1.3 @@ -14,6 +14,7 @@
     1.4  .*\.orig$
     1.5  .*\.rej$
     1.6  .*/a\.out$
     1.7 +.*/Modules\.symvers$
     1.8  .*/cscope\..*$
     1.9  ^cscope.*$
    1.10  ^[^/]*\.bz2$
     2.1 --- a/docs/Docs.mk	Fri Apr 06 10:06:30 2007 -0600
     2.2 +++ b/docs/Docs.mk	Fri Apr 06 10:08:30 2007 -0600
     2.3 @@ -6,6 +6,7 @@ LATEX2HTML	:= latex2html
     2.4  DOXYGEN		:= doxygen
     2.5  POD2MAN		:= pod2man
     2.6  DOT		:= dot
     2.7 +NEATO		:= neato
     2.8  
     2.9  pkgdocdir	:= /usr/share/doc/xen
    2.10  mandir		:= /usr/share/man
     3.1 --- a/docs/xen-api/Makefile	Fri Apr 06 10:06:30 2007 -0600
     3.2 +++ b/docs/xen-api/Makefile	Fri Apr 06 10:08:30 2007 -0600
     3.3 @@ -37,6 +37,9 @@ xenapi.dvi: $(TEX) $(EPS) $(EPSDOT)
     3.4  %.eps: %.dot
     3.5  	$(DOT) -Tps $< >$@
     3.6  
     3.7 +xenapi-datamodel-graph.eps: xenapi-datamodel-graph.dot
     3.8 +	$(NEATO) -Goverlap=false -Tps $< >$@
     3.9 +
    3.10  .PHONY: clean
    3.11  clean:
    3.12  	rm -f *.pdf *.ps *.dvi *.aux *.log $(EPSDOT)
     4.1 --- a/docs/xen-api/coversheet.tex	Fri Apr 06 10:06:30 2007 -0600
     4.2 +++ b/docs/xen-api/coversheet.tex	Fri Apr 06 10:08:30 2007 -0600
     4.3 @@ -1,5 +1,5 @@
     4.4  %
     4.5 -% Copyright (c) 2006 XenSource, Inc.
     4.6 +% Copyright (c) 2006-2007 XenSource, Inc.
     4.7  %
     4.8  % Permission is granted to copy, distribute and/or modify this document under
     4.9  % the terms of the GNU Free Documentation License, Version 1.2 or any later
    4.10 @@ -20,7 +20,7 @@
    4.11  \begin{center}
    4.12  \resizebox{8cm}{!}{\includegraphics{\coversheetlogo}}
    4.13  
    4.14 -\vspace{3cm}
    4.15 +\vspace{2cm}
    4.16  
    4.17  \begin{Huge}
    4.18    \doctitle{}
    4.19 @@ -37,9 +37,27 @@ Date: \datestring{}
    4.20  \begin{tabular}{rl}
    4.21  \docauthors{}
    4.22  \end{tabular}
    4.23 -
    4.24  \end{Large}
    4.25  \end{center}
    4.26 +\vspace{.5cm}
    4.27 +\begin{large}
    4.28 +\textbf{Contributors:}
    4.29 +\begin{multicols}{2}{
    4.30 +Stefan Berger, IBM \\
    4.31 +Daniel Berrang\'e, Red Hat \\
    4.32 +Gareth Bestor, IBM \\
    4.33 +Hollis Blanchard, IBM \\
    4.34 +Mike Day, IBM \\
    4.35 +Jim Fehlig, Novell \\
    4.36 +Jon Harrop, XenSource \\
    4.37 +Vincent Hanquez, XenSource \\
    4.38 +John Levon, Sun Microsystems \\
    4.39 +Jon Ludlam, XenSource \\
    4.40 +Alastair Tse, XenSource \\
    4.41 +Daniel Veillard, Red Hat \\
    4.42 +Tom Wilkie, University of Cambridge}
    4.43 +\end{multicols}
    4.44 +\end{large}
    4.45  
    4.46  \vfill
    4.47  
     5.1 --- a/docs/xen-api/presentation.tex	Fri Apr 06 10:06:30 2007 -0600
     5.2 +++ b/docs/xen-api/presentation.tex	Fri Apr 06 10:08:30 2007 -0600
     5.3 @@ -1,5 +1,5 @@
     5.4  %
     5.5 -% Copyright (c) 2006 XenSource, Inc.
     5.6 +% Copyright (c) 2006-2007 XenSource, Inc.
     5.7  %
     5.8  % Permission is granted to copy, distribute and/or modify this document under
     5.9  % the terms of the GNU Free Documentation License, Version 1.2 or any later
     6.1 --- a/docs/xen-api/vm-lifecycle.tex	Fri Apr 06 10:06:30 2007 -0600
     6.2 +++ b/docs/xen-api/vm-lifecycle.tex	Fri Apr 06 10:08:30 2007 -0600
     6.3 @@ -1,5 +1,5 @@
     6.4  %
     6.5 -% Copyright (c) 2006 XenSource, Inc.
     6.6 +% Copyright (c) 2006-2007 XenSource, Inc.
     6.7  %
     6.8  % Permission is granted to copy, distribute and/or modify this document under
     6.9  % the terms of the GNU Free Documentation License, Version 1.2 or any later
     7.1 --- a/docs/xen-api/wire-protocol.tex	Fri Apr 06 10:06:30 2007 -0600
     7.2 +++ b/docs/xen-api/wire-protocol.tex	Fri Apr 06 10:08:30 2007 -0600
     7.3 @@ -1,5 +1,5 @@
     7.4  %
     7.5 -% Copyright (c) 2006 XenSource, Inc.
     7.6 +% Copyright (c) 2006-2007 XenSource, Inc.
     7.7  %
     7.8  % Permission is granted to copy, distribute and/or modify this document under
     7.9  % the terms of the GNU Free Documentation License, Version 1.2 or any later
     8.1 --- a/docs/xen-api/xenapi-coversheet.tex	Fri Apr 06 10:06:30 2007 -0600
     8.2 +++ b/docs/xen-api/xenapi-coversheet.tex	Fri Apr 06 10:08:30 2007 -0600
     8.3 @@ -1,5 +1,5 @@
     8.4  %
     8.5 -% Copyright (c) 2006 XenSource, Inc.
     8.6 +% Copyright (c) 2006-2007 XenSource, Inc.
     8.7  %
     8.8  % Permission is granted to copy, distribute and/or modify this document under
     8.9  % the terms of the GNU Free Documentation License, Version 1.2 or any later
    8.10 @@ -12,26 +12,24 @@
    8.11  %
    8.12  
    8.13  %% Document title
    8.14 -\newcommand{\doctitle}{Xen Management API Draft}
    8.15 +\newcommand{\doctitle}{Xen Management API}
    8.16  
    8.17  \newcommand{\coversheetlogo}{xen.eps}
    8.18  
    8.19  %% Document date
    8.20 -\newcommand{\datestring}{25th August 2006}
    8.21 +\newcommand{\datestring}{5th April 2007}
    8.22  
    8.23 -\newcommand{\releasestatement}{Open Preview Release\\Comments are welcome!}
    8.24 +\newcommand{\releasestatement}{Candidate for Release\\Comments are welcome!}
    8.25  
    8.26  %% Document revision
    8.27 -\newcommand{\revstring}{API Revision 0.4.3 (Draft for discussion)}
    8.28 +\newcommand{\revstring}{API Revision 0.9.0}
    8.29  
    8.30  %% Document authors
    8.31  \newcommand{\docauthors}{
    8.32  Ewan Mellor: & {\tt ewan@xensource.com} \\
    8.33  Richard Sharp: & {\tt richard.sharp@xensource.com} \\
    8.34 -David Scott: & {\tt david.scott@xensource.com} \\
    8.35 -Jon Harrop: & {\tt jon.harrop@xensource.com}
    8.36 -}
    8.37 -\newcommand{\legalnotice}{Copyright \copyright{} 2006 XenSource, Inc.\\ \\
    8.38 +David Scott: & {\tt david.scott@xensource.com}}
    8.39 +\newcommand{\legalnotice}{Copyright \copyright{} 2006-2007 XenSource, Inc.\\ \\
    8.40  Permission is granted to copy, distribute and/or modify this document under
    8.41  the terms of the GNU Free Documentation License, Version 1.2 or any later
    8.42  version published by the Free Software Foundation; with no Invariant Sections,
     9.1 --- a/docs/xen-api/xenapi-datamodel-graph.dot	Fri Apr 06 10:06:30 2007 -0600
     9.2 +++ b/docs/xen-api/xenapi-datamodel-graph.dot	Fri Apr 06 10:08:30 2007 -0600
     9.3 @@ -1,18 +1,39 @@
     9.4 -digraph g{
     9.5 -node [ shape=box ]; session [ URL="session.html" ] task [ URL="task.html" ] VM [ URL="VM.html" ] host [ URL="host.html" ] host_cpu [ URL="host_cpu.html" ] network [ URL="network.html" ] VIF [ URL="VIF.html" ] PIF [ URL="PIF.html" ] SR [ URL="SR.html" ] VDI [ URL="VDI.html" ] VBD [ URL="VBD.html" ] VTPM [ URL="VTPM.html" ] console [ URL="console.html" ] user [ URL="user.html" ] debug [ URL="debug.html" ];
     9.6 -session -> host [ label="this_host(1)" ]
     9.7 -session -> user [ label="this_user(1)" ]
     9.8 -host -> VM [ color="blue", arrowhead="crow", arrowtail="none" ]
     9.9 -host -> host_cpu [ color="blue", arrowhead="crow", arrowtail="none" ]
    9.10 -VIF -> VM [ color="blue", arrowhead="none", arrowtail="crow" ]
    9.11 -VIF -> network [ color="blue", arrowhead="none", arrowtail="crow" ]
    9.12 -PIF -> host [ color="blue", arrowhead="none", arrowtail="crow" ]
    9.13 -PIF -> network [ color="blue", arrowhead="none", arrowtail="crow" ]
    9.14 -SR -> VDI [ color="blue", arrowhead="crow", arrowtail="none" ]
    9.15 -VDI -> VBD [ color="blue", arrowhead="crow", arrowtail="none" ]
    9.16 -VDI -> VDI [ color="blue", arrowhead="none", arrowtail="crow" ]
    9.17 -VBD -> VM [ color="blue", arrowhead="none", arrowtail="crow" ]
    9.18 -VTPM -> VM [ label="backend(1)" ]
    9.19 -VTPM -> VM [ color="blue", arrowhead="none", arrowtail="crow" ]
    9.20 -console -> VM [ color="blue", arrowhead="none", arrowtail="crow" ]
    9.21 +#
    9.22 +# Copyright (c) 2006-2007 XenSource, Inc.
    9.23 +#
    9.24 +# Permission is granted to copy, distribute and/or modify this document under
    9.25 +# the terms of the GNU Free Documentation License, Version 1.2 or any later
    9.26 +# version published by the Free Software Foundation; with no Invariant
    9.27 +# Sections, no Front-Cover Texts and no Back-Cover Texts.  A copy of the
    9.28 +# license is included in the section entitled
    9.29 +# "GNU Free Documentation License" or the file fdl.tex.
    9.30 +#
    9.31 +
    9.32 +digraph "Xen-API Class Diagram" {
    9.33 +fontname="Verdana";
    9.34 +
    9.35 +node [ shape=box ]; session VM host network VIF PIF SR VDI VBD PBD user;
    9.36 +node [shape=ellipse]; PIF_metrics VIF_metrics VM_metrics VBD_metrics PBD_metrics VM_guest_metrics host_metrics;
    9.37 +node [shape=box]; host_cpu console
    9.38 +session -> host [ arrowhead="none" ]
    9.39 +session -> user [ arrowhead="none" ]
    9.40 +VM -> VM_metrics [ arrowhead="none" ]
    9.41 +VM -> VM_guest_metrics [ arrowhead="none" ]
    9.42 +VM -> console [ arrowhead="crow" ]
    9.43 +host -> PBD [ arrowhead="crow", arrowtail="none" ]
    9.44 +host -> host_metrics [ arrowhead="none" ]
    9.45 +host -> host_cpu [ arrowhead="none" ]
    9.46 +VIF -> VM [ arrowhead="none", arrowtail="crow" ]
    9.47 +VIF -> network [ arrowhead="none", arrowtail="crow" ]
    9.48 +VIF -> VIF_metrics [ arrowhead="none" ]
    9.49 +PIF -> host [ arrowhead="none", arrowtail="crow" ]
    9.50 +PIF -> network [ arrowhead="none", arrowtail="crow" ]
    9.51 +PIF -> PIF_metrics [ arrowhead="none" ]
    9.52 +SR -> PBD [ arrowhead="crow", arrowtail="none" ]
    9.53 +PBD -> PBD_metrics [ arrowhead="none" ]
    9.54 +SR -> VDI [ arrowhead="crow", arrowtail="none" ]
    9.55 +VDI -> VBD [ arrowhead="crow", arrowtail="none" ]
    9.56 +VBD -> VM [ arrowhead="none", arrowtail="crow" ]
    9.57 +VTPM -> VM [ arrowhead="none", arrowtail="crow" ]
    9.58 +VBD -> VBD_metrics [ arrowhead="none" ]
    9.59  }
    10.1 --- a/docs/xen-api/xenapi-datamodel.tex	Fri Apr 06 10:06:30 2007 -0600
    10.2 +++ b/docs/xen-api/xenapi-datamodel.tex	Fri Apr 06 10:08:30 2007 -0600
    10.3 @@ -1,5 +1,5 @@
    10.4  %
    10.5 -% Copyright (c) 2006 XenSource, Inc.
    10.6 +% Copyright (c) 2006-2007 XenSource, Inc.
    10.7  %
    10.8  % Permission is granted to copy, distribute and/or modify this document under
    10.9  % the terms of the GNU Free Documentation License, Version 1.2 or any later
   10.10 @@ -512,7 +512,6 @@ Quals & Field & Type & Description \\
   10.11  $\mathit{RO}_\mathit{run}$ &  {\tt progress} & int & if the task is still pending, this field contains the estimated percentage complete (0-100). If task has completed (successfully or unsuccessfully) this should be 100. \\
   10.12  $\mathit{RO}_\mathit{run}$ &  {\tt type} & string & if the task has completed successfully, this field contains the type of the encoded result (i.e. name of the class whose reference is in the result field). Undefined otherwise. \\
   10.13  $\mathit{RO}_\mathit{run}$ &  {\tt result} & string & if the task has completed successfully, this field contains the result value (either Void or an object reference). Undefined otherwise. \\
   10.14 -$\mathit{RO}_\mathit{run}$ &  {\tt error\_code} & int & if the task has failed, this field contains the error code. Undefined otherwise. \\
   10.15  $\mathit{RO}_\mathit{run}$ &  {\tt error\_info} & string Set & if the task has failed, this field contains the set of associated error strings. Undefined otherwise. \\
   10.16  $\mathit{RO}_\mathit{run}$ &  {\tt allowed\_operations} & (task\_allowed\_operations) Set & Operations allowed on this task \\
   10.17  \hline
   10.18 @@ -833,38 +832,6 @@ value of the field
   10.19  \vspace{0.3cm}
   10.20  \vspace{0.3cm}
   10.21  \vspace{0.3cm}
   10.22 -\subsubsection{RPC name:~get\_error\_code}
   10.23 -
   10.24 -{\bf Overview:} 
   10.25 -Get the error\_code field of the given task.
   10.26 -
   10.27 - \noindent {\bf Signature:} 
   10.28 -\begin{verbatim} int get_error_code (session_id s, task ref self)\end{verbatim}
   10.29 -
   10.30 -
   10.31 -\noindent{\bf Arguments:}
   10.32 -
   10.33 - 
   10.34 -\vspace{0.3cm}
   10.35 -\begin{tabular}{|c|c|p{7cm}|}
   10.36 - \hline
   10.37 -{\bf type} & {\bf name} & {\bf description} \\ \hline
   10.38 -{\tt task ref } & self & reference to the object \\ \hline 
   10.39 -
   10.40 -\end{tabular}
   10.41 -
   10.42 -\vspace{0.3cm}
   10.43 -
   10.44 - \noindent {\bf Return Type:} 
   10.45 -{\tt 
   10.46 -int
   10.47 -}
   10.48 -
   10.49 -
   10.50 -value of the field
   10.51 -\vspace{0.3cm}
   10.52 -\vspace{0.3cm}
   10.53 -\vspace{0.3cm}
   10.54  \subsubsection{RPC name:~get\_error\_info}
   10.55  
   10.56  {\bf Overview:} 
   10.57 @@ -4952,6 +4919,27 @@ dmesg string
   10.58  \vspace{0.3cm}
   10.59  \vspace{0.3cm}
   10.60  \vspace{0.3cm}
   10.61 +\subsubsection{RPC name:~list\_methods}
   10.62 +
   10.63 +{\bf Overview:} 
   10.64 +List all supported methods.
   10.65 +
   10.66 + \noindent {\bf Signature:} 
   10.67 +\begin{verbatim} (string Set) list_methods (session_id s)\end{verbatim}
   10.68 +
   10.69 +
   10.70 +\vspace{0.3cm}
   10.71 +
   10.72 + \noindent {\bf Return Type:} 
   10.73 +{\tt 
   10.74 +string Set
   10.75 +}
   10.76 +
   10.77 +
   10.78 +The name of every supported method.
   10.79 +\vspace{0.3cm}
   10.80 +\vspace{0.3cm}
   10.81 +\vspace{0.3cm}
   10.82  \subsubsection{RPC name:~get\_all}
   10.83  
   10.84  {\bf Overview:} 
   10.85 @@ -9190,51 +9178,35 @@ Quals & Field & Type & Description \\
   10.86  $\mathit{RO}_\mathit{run}$ &  {\tt physical\_utilisation} & int & physical space currently utilised on this storage repository (in bytes). Note that for sparse disk formats, physical\_utilisation may be less than virtual\_allocation \\
   10.87  $\mathit{RO}_\mathit{ins}$ &  {\tt physical\_size} & int & total physical size of the repository (in bytes) \\
   10.88  $\mathit{RO}_\mathit{ins}$ &  {\tt type} & string & type of the storage repository \\
   10.89 -$\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 \\
   10.90 +$\mathit{RO}_\mathit{ins}$ &  {\tt content\_type} & string & the type of the SR's content, if required (e.g. ISOs) \\
   10.91  \hline
   10.92  \end{longtable}
   10.93  \subsection{RPCs associated with class: SR}
   10.94 -\subsubsection{RPC name:~clone}
   10.95 -
   10.96 -{\bf Overview:} 
   10.97 -Take an exact copy of the Storage Repository;
   10.98 -        the cloned storage repository has the same type as its parent
   10.99 -
  10.100 - \noindent {\bf Signature:} 
  10.101 -\begin{verbatim} (SR ref) clone (session_id s, SR ref sr, string loc, string name)\end{verbatim}
  10.102 -
  10.103 -
  10.104 -\noindent{\bf Arguments:}
  10.105 -
  10.106 - 
  10.107 -\vspace{0.3cm}
  10.108 -\begin{tabular}{|c|c|p{7cm}|}
  10.109 - \hline
  10.110 -{\bf type} & {\bf name} & {\bf description} \\ \hline
  10.111 -{\tt SR ref } & sr & The Storage Repository to clone \\ \hline 
  10.112 -
  10.113 -{\tt string } & loc & The location string that defines where the new storage repository will be located \\ \hline 
  10.114 -
  10.115 -{\tt string } & name & The name of the new storage repository \\ \hline 
  10.116 -
  10.117 -\end{tabular}
  10.118 -
  10.119 -\vspace{0.3cm}
  10.120 -
  10.121 - \noindent {\bf Return Type:} 
  10.122 -{\tt 
  10.123 -SR ref
  10.124 -}
  10.125 -
  10.126 -
  10.127 -The ID of the newly created Storage Repository.
  10.128 +\subsubsection{RPC name:~get\_supported\_types}
  10.129 +
  10.130 +{\bf Overview:} 
  10.131 +Return a set of all the SR types supported by the system.
  10.132 +
  10.133 + \noindent {\bf Signature:} 
  10.134 +\begin{verbatim} (string Set) get_supported_types (session_id s)\end{verbatim}
  10.135 +
  10.136 +
  10.137 +\vspace{0.3cm}
  10.138 +
  10.139 + \noindent {\bf Return Type:} 
  10.140 +{\tt 
  10.141 +string Set
  10.142 +}
  10.143 +
  10.144 +
  10.145 +the supported SR types
  10.146  \vspace{0.3cm}
  10.147  \vspace{0.3cm}
  10.148  \vspace{0.3cm}
  10.149  \subsubsection{RPC name:~get\_all}
  10.150  
  10.151  {\bf Overview:} 
  10.152 -Return a list of all the Storage Repositories known to the system
  10.153 +Return a list of all the SRs known to the system.
  10.154  
  10.155   \noindent {\bf Signature:} 
  10.156  \begin{verbatim} ((SR ref) Set) get_all (session_id s)\end{verbatim}
  10.157 @@ -9248,7 +9220,7 @@ Return a list of all the Storage Reposit
  10.158  }
  10.159  
  10.160  
  10.161 -A list of all the IDs of all the Storage Repositories
  10.162 +references to all objects
  10.163  \vspace{0.3cm}
  10.164  \vspace{0.3cm}
  10.165  \vspace{0.3cm}
  10.166 @@ -9608,13 +9580,13 @@ value of the field
  10.167  \vspace{0.3cm}
  10.168  \vspace{0.3cm}
  10.169  \vspace{0.3cm}
  10.170 -\subsubsection{RPC name:~get\_location}
  10.171 -
  10.172 -{\bf Overview:} 
  10.173 -Get the location field of the given SR.
  10.174 -
  10.175 - \noindent {\bf Signature:} 
  10.176 -\begin{verbatim} string get_location (session_id s, SR ref self)\end{verbatim}
  10.177 +\subsubsection{RPC name:~get\_content\_type}
  10.178 +
  10.179 +{\bf Overview:} 
  10.180 +Get the content\_type field of the given SR.
  10.181 +
  10.182 + \noindent {\bf Signature:} 
  10.183 +\begin{verbatim} string get_content_type (session_id s, SR ref self)\end{verbatim}
  10.184  
  10.185  
  10.186  \noindent{\bf Arguments:}
  10.187 @@ -9640,70 +9612,6 @@ value of the field
  10.188  \vspace{0.3cm}
  10.189  \vspace{0.3cm}
  10.190  \vspace{0.3cm}
  10.191 -\subsubsection{RPC name:~create}
  10.192 -
  10.193 -{\bf Overview:} 
  10.194 -Create a new SR instance, and return its handle.
  10.195 -
  10.196 - \noindent {\bf Signature:} 
  10.197 -\begin{verbatim} (SR ref) create (session_id s, SR record args)\end{verbatim}
  10.198 -
  10.199 -
  10.200 -\noindent{\bf Arguments:}
  10.201 -
  10.202 - 
  10.203 -\vspace{0.3cm}
  10.204 -\begin{tabular}{|c|c|p{7cm}|}
  10.205 - \hline
  10.206 -{\bf type} & {\bf name} & {\bf description} \\ \hline
  10.207 -{\tt SR record } & args & All constructor arguments \\ \hline 
  10.208 -
  10.209 -\end{tabular}
  10.210 -
  10.211 -\vspace{0.3cm}
  10.212 -
  10.213 - \noindent {\bf Return Type:} 
  10.214 -{\tt 
  10.215 -SR ref
  10.216 -}
  10.217 -
  10.218 -
  10.219 -reference to the newly created object
  10.220 -\vspace{0.3cm}
  10.221 -\vspace{0.3cm}
  10.222 -\vspace{0.3cm}
  10.223 -\subsubsection{RPC name:~destroy}
  10.224 -
  10.225 -{\bf Overview:} 
  10.226 -Destroy the specified SR instance.
  10.227 -
  10.228 - \noindent {\bf Signature:} 
  10.229 -\begin{verbatim} void destroy (session_id s, SR ref self)\end{verbatim}
  10.230 -
  10.231 -
  10.232 -\noindent{\bf Arguments:}
  10.233 -
  10.234 - 
  10.235 -\vspace{0.3cm}
  10.236 -\begin{tabular}{|c|c|p{7cm}|}
  10.237 - \hline
  10.238 -{\bf type} & {\bf name} & {\bf description} \\ \hline
  10.239 -{\tt SR ref } & self & reference to the object \\ \hline 
  10.240 -
  10.241 -\end{tabular}
  10.242 -
  10.243 -\vspace{0.3cm}
  10.244 -
  10.245 - \noindent {\bf Return Type:} 
  10.246 -{\tt 
  10.247 -void
  10.248 -}
  10.249 -
  10.250 -
  10.251 -
  10.252 -\vspace{0.3cm}
  10.253 -\vspace{0.3cm}
  10.254 -\vspace{0.3cm}
  10.255  \subsubsection{RPC name:~get\_by\_uuid}
  10.256  
  10.257  {\bf Overview:} 
  10.258 @@ -9828,73 +9736,6 @@ Quals & Field & Type & Description \\
  10.259  \hline
  10.260  \end{longtable}
  10.261  \subsection{RPCs associated with class: VDI}
  10.262 -\subsubsection{RPC name:~snapshot}
  10.263 -
  10.264 -{\bf Overview:} 
  10.265 -Take an exact copy of the VDI; the snapshot lives in the same Storage
  10.266 -Repository as its parent.
  10.267 -
  10.268 - \noindent {\bf Signature:} 
  10.269 -\begin{verbatim} (VDI ref) snapshot (session_id s, VDI ref vdi)\end{verbatim}
  10.270 -
  10.271 -
  10.272 -\noindent{\bf Arguments:}
  10.273 -
  10.274 - 
  10.275 -\vspace{0.3cm}
  10.276 -\begin{tabular}{|c|c|p{7cm}|}
  10.277 - \hline
  10.278 -{\bf type} & {\bf name} & {\bf description} \\ \hline
  10.279 -{\tt VDI ref } & vdi & The VDI to snapshot \\ \hline 
  10.280 -
  10.281 -\end{tabular}
  10.282 -
  10.283 -\vspace{0.3cm}
  10.284 -
  10.285 - \noindent {\bf Return Type:} 
  10.286 -{\tt 
  10.287 -VDI ref
  10.288 -}
  10.289 -
  10.290 -
  10.291 -The ID of the newly created VDI.
  10.292 -\vspace{0.3cm}
  10.293 -\vspace{0.3cm}
  10.294 -\vspace{0.3cm}
  10.295 -\subsubsection{RPC name:~resize}
  10.296 -
  10.297 -{\bf Overview:} 
  10.298 -Resize the vdi to the size.
  10.299 -
  10.300 - \noindent {\bf Signature:} 
  10.301 -\begin{verbatim} void resize (session_id s, VDI ref vdi, int size)\end{verbatim}
  10.302 -
  10.303 -
  10.304 -\noindent{\bf Arguments:}
  10.305 -
  10.306 - 
  10.307 -\vspace{0.3cm}
  10.308 -\begin{tabular}{|c|c|p{7cm}|}
  10.309 - \hline
  10.310 -{\bf type} & {\bf name} & {\bf description} \\ \hline
  10.311 -{\tt VDI ref } & vdi & The VDI to resize \\ \hline 
  10.312 -
  10.313 -{\tt int } & size & The new size of the VDI \\ \hline 
  10.314 -
  10.315 -\end{tabular}
  10.316 -
  10.317 -\vspace{0.3cm}
  10.318 -
  10.319 - \noindent {\bf Return Type:} 
  10.320 -{\tt 
  10.321 -void
  10.322 -}
  10.323 -
  10.324 -
  10.325 -
  10.326 -\vspace{0.3cm}
  10.327 -\vspace{0.3cm}
  10.328 -\vspace{0.3cm}
  10.329  \subsubsection{RPC name:~get\_all}
  10.330  
  10.331  {\bf Overview:} 
  10.332 @@ -11988,7 +11829,7 @@ Quals & Field & Type & Description \\
  10.333  $\mathit{RO}_\mathit{run}$ &  {\tt uuid} & string & unique identifier/object reference \\
  10.334  $\mathit{RO}_\mathit{ins}$ &  {\tt host} & host ref & physical machine on which the pbd is available \\
  10.335  $\mathit{RO}_\mathit{ins}$ &  {\tt SR} & SR ref & the storage repository that the pbd realises \\
  10.336 -$\mathit{RO}_\mathit{ins}$ &  {\tt device\_config} & (string $\rightarrow$ string) Map & a config string that is provided to the host's SR-backend-driver \\
  10.337 +$\mathit{RO}_\mathit{ins}$ &  {\tt device\_config} & (string $\rightarrow$ string) Map & a config string to string map that is provided to the host's SR-backend-driver \\
  10.338  $\mathit{RO}_\mathit{run}$ &  {\tt currently\_attached} & bool & is the SR currently attached on this host? \\
  10.339  \hline
  10.340  \end{longtable}
    11.1 --- a/docs/xen-api/xenapi.tex	Fri Apr 06 10:06:30 2007 -0600
    11.2 +++ b/docs/xen-api/xenapi.tex	Fri Apr 06 10:08:30 2007 -0600
    11.3 @@ -1,5 +1,5 @@
    11.4  %
    11.5 -% Copyright (c) 2006 XenSource, Inc.
    11.6 +% Copyright (c) 2006-2007 XenSource, Inc.
    11.7  %
    11.8  % Permission is granted to copy, distribute and/or modify this document under
    11.9  % the terms of the GNU Free Documentation License, Version 1.2 or any later
   11.10 @@ -17,6 +17,7 @@
   11.11  \usepackage{graphics}
   11.12  \usepackage{longtable}
   11.13  \usepackage{fancyhdr}
   11.14 +\usepackage{multicol}
   11.15  
   11.16  \setlength\topskip{0cm}
   11.17  \setlength\topmargin{0cm}
   11.18 @@ -40,17 +41,10 @@ This document contains a description of 
   11.19  remotely configuring and controlling virtualised guests running on a
   11.20  Xen-enabled host. 
   11.21  
   11.22 -~
   11.23 -
   11.24 -{\bf \large This document is an early draft for discussion purposes only.}
   11.25 -
   11.26 -~
   11.27 -
   11.28  \input{presentation}
   11.29  
   11.30  \include{wire-protocol}
   11.31  \include{vm-lifecycle}
   11.32 -\include{todo}
   11.33  \include{xenapi-datamodel}
   11.34  \include{fdl}
   11.35  
    12.1 --- a/extras/mini-os/xenbus/xenbus.c	Fri Apr 06 10:06:30 2007 -0600
    12.2 +++ b/extras/mini-os/xenbus/xenbus.c	Fri Apr 06 10:08:30 2007 -0600
    12.3 @@ -178,6 +178,7 @@ static void release_xenbus_id(int id)
    12.4  {
    12.5      BUG_ON(!req_info[id].in_use);
    12.6      spin_lock(&req_lock);
    12.7 +    req_info[id].in_use = 0;
    12.8      nr_live_reqs--;
    12.9      req_info[id].in_use = 0;
   12.10      if (nr_live_reqs == NR_REQS - 1)
   12.11 @@ -335,6 +336,7 @@ xenbus_msg_reply(int type,
   12.12      xb_write(type, id, trans, io, nr_reqs);
   12.13  
   12.14      schedule();
   12.15 +    remove_waiter(w);
   12.16      wake(current);
   12.17  
   12.18      rep = req_info[id].reply;
    13.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S	Fri Apr 06 10:06:30 2007 -0600
    13.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S	Fri Apr 06 10:08:30 2007 -0600
    13.3 @@ -142,7 +142,7 @@ ENTRY(cpu_gdt_table)
    13.4  	.quad 0x0000000000000000	/* 0xf0 - unused */
    13.5  	.quad 0x0000000000000000	/* 0xf8 - GDT entry 31: double-fault TSS */
    13.6  
    13.7 -#ifdef CONFIG_XEN_COMPAT_030002
    13.8 +#if CONFIG_XEN_COMPAT <= 0x030002
    13.9  /*
   13.10   * __xen_guest information
   13.11   */
   13.12 @@ -180,18 +180,18 @@ ENTRY(cpu_gdt_table)
   13.13  #endif
   13.14  	.ascii	",LOADER=generic"
   13.15  	.byte	0
   13.16 -#endif /* CONFIG_XEN_COMPAT_030002 */
   13.17 +#endif /* CONFIG_XEN_COMPAT <= 0x030002 */
   13.18  
   13.19  
   13.20  	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS,       .asciz, "linux")	
   13.21  	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION,  .asciz, "2.6")
   13.22  	ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION,    .asciz, "xen-3.0")
   13.23  	ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE,      .long,  __PAGE_OFFSET)
   13.24 -#ifdef CONFIG_XEN_COMPAT_030002
   13.25 +#if CONFIG_XEN_COMPAT <= 0x030002
   13.26  	ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .long,  __PAGE_OFFSET)
   13.27  #else
   13.28  	ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .long,  0)
   13.29 -#endif /* !CONFIG_XEN_COMPAT_030002 */
   13.30 +#endif
   13.31  	ELFNOTE(Xen, XEN_ELFNOTE_ENTRY,          .long,  startup_32)
   13.32  	ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, .long,  hypercall_page)
   13.33  	ELFNOTE(Xen, XEN_ELFNOTE_HV_START_LOW,   .long,  HYPERVISOR_VIRT_START)
    14.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c	Fri Apr 06 10:06:30 2007 -0600
    14.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c	Fri Apr 06 10:08:30 2007 -0600
    14.3 @@ -1010,7 +1010,7 @@ static void stop_hz_timer(void)
    14.4  	singleshot.timeout_abs_ns = jiffies_to_st(j);
    14.5  	singleshot.flags = 0;
    14.6  	rc = HYPERVISOR_vcpu_op(VCPUOP_set_singleshot_timer, cpu, &singleshot);
    14.7 -#ifdef CONFIG_XEN_COMPAT_030004
    14.8 +#if CONFIG_XEN_COMPAT <= 0x030004
    14.9  	if (rc) {
   14.10  		BUG_ON(rc != -ENOSYS);
   14.11  		rc = HYPERVISOR_set_timer_op(singleshot.timeout_abs_ns);
    15.1 --- a/linux-2.6-xen-sparse/arch/i386/mach-xen/setup.c	Fri Apr 06 10:06:30 2007 -0600
    15.2 +++ b/linux-2.6-xen-sparse/arch/i386/mach-xen/setup.c	Fri Apr 06 10:08:30 2007 -0600
    15.3 @@ -114,7 +114,7 @@ void __init machine_specific_arch_setup(
    15.4  	ret = HYPERVISOR_callback_op(CALLBACKOP_register, &event);
    15.5  	if (ret == 0)
    15.6  		ret = HYPERVISOR_callback_op(CALLBACKOP_register, &failsafe);
    15.7 -#ifdef CONFIG_XEN_COMPAT_030002
    15.8 +#if CONFIG_XEN_COMPAT <= 0x030002
    15.9  	if (ret == -ENOSYS)
   15.10  		ret = HYPERVISOR_set_callbacks(
   15.11  			event.address.cs, event.address.eip,
   15.12 @@ -123,7 +123,7 @@ void __init machine_specific_arch_setup(
   15.13  	BUG_ON(ret);
   15.14  
   15.15  	ret = HYPERVISOR_callback_op(CALLBACKOP_register, &nmi_cb);
   15.16 -#ifdef CONFIG_XEN_COMPAT_030002
   15.17 +#if CONFIG_XEN_COMPAT <= 0x030002
   15.18  	if (ret == -ENOSYS) {
   15.19  		static struct xennmi_callback __initdata cb = {
   15.20  			.handler_address = (unsigned long)nmi
    16.1 --- a/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c	Fri Apr 06 10:06:30 2007 -0600
    16.2 +++ b/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c	Fri Apr 06 10:08:30 2007 -0600
    16.3 @@ -303,7 +303,7 @@ int xen_create_contiguous_region(
    16.4  		set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i,
    16.5  			INVALID_P2M_ENTRY);
    16.6  	}
    16.7 -	if (HYPERVISOR_multicall(cr_mcl, i))
    16.8 +	if (HYPERVISOR_multicall_check(cr_mcl, i, NULL))
    16.9  		BUG();
   16.10  
   16.11  	/* 2. Get a new contiguous memory extent. */
   16.12 @@ -312,7 +312,7 @@ int xen_create_contiguous_region(
   16.13  	success = (exchange.nr_exchanged == (1UL << order));
   16.14  	BUG_ON(!success && ((exchange.nr_exchanged != 0) || (rc == 0)));
   16.15  	BUG_ON(success && (rc != 0));
   16.16 -#ifdef CONFIG_XEN_COMPAT_030002
   16.17 +#if CONFIG_XEN_COMPAT <= 0x030002
   16.18  	if (unlikely(rc == -ENOSYS)) {
   16.19  		/* Compatibility when XENMEM_exchange is unsupported. */
   16.20  		if (HYPERVISOR_memory_op(XENMEM_decrease_reservation,
   16.21 @@ -342,7 +342,7 @@ int xen_create_contiguous_region(
   16.22  	cr_mcl[i - 1].args[MULTI_UVMFLAGS_INDEX] = order
   16.23  						   ? UVMF_TLB_FLUSH|UVMF_ALL
   16.24  						   : UVMF_INVLPG|UVMF_ALL;
   16.25 -	if (HYPERVISOR_multicall(cr_mcl, i))
   16.26 +	if (HYPERVISOR_multicall_check(cr_mcl, i, NULL))
   16.27  		BUG();
   16.28  
   16.29  	if (success)
   16.30 @@ -400,7 +400,7 @@ void xen_destroy_contiguous_region(unsig
   16.31  			INVALID_P2M_ENTRY);
   16.32  		out_frames[i] = (__pa(vstart) >> PAGE_SHIFT) + i;
   16.33  	}
   16.34 -	if (HYPERVISOR_multicall(cr_mcl, i))
   16.35 +	if (HYPERVISOR_multicall_check(cr_mcl, i, NULL))
   16.36  		BUG();
   16.37  
   16.38  	/* 3. Do the exchange for non-contiguous MFNs. */
   16.39 @@ -408,7 +408,7 @@ void xen_destroy_contiguous_region(unsig
   16.40  	success = (exchange.nr_exchanged == 1);
   16.41  	BUG_ON(!success && ((exchange.nr_exchanged != 0) || (rc == 0)));
   16.42  	BUG_ON(success && (rc != 0));
   16.43 -#ifdef CONFIG_XEN_COMPAT_030002
   16.44 +#if CONFIG_XEN_COMPAT <= 0x030002
   16.45  	if (unlikely(rc == -ENOSYS)) {
   16.46  		/* Compatibility when XENMEM_exchange is unsupported. */
   16.47  		if (HYPERVISOR_memory_op(XENMEM_decrease_reservation,
   16.48 @@ -432,7 +432,7 @@ void xen_destroy_contiguous_region(unsig
   16.49  	cr_mcl[i - 1].args[MULTI_UVMFLAGS_INDEX] = order
   16.50  						   ? UVMF_TLB_FLUSH|UVMF_ALL
   16.51  						   : UVMF_INVLPG|UVMF_ALL;
   16.52 -	if (HYPERVISOR_multicall(cr_mcl, i))
   16.53 +	if (HYPERVISOR_multicall_check(cr_mcl, i, NULL))
   16.54  		BUG();
   16.55  
   16.56  	balloon_unlock(flags);
    17.1 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S	Fri Apr 06 10:06:30 2007 -0600
    17.2 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S	Fri Apr 06 10:08:30 2007 -0600
    17.3 @@ -201,6 +201,19 @@ rff_trace:
    17.4  END(ret_from_fork)
    17.5  
    17.6  /*
    17.7 + * initial frame state for interrupts and exceptions
    17.8 + */
    17.9 +	.macro _frame ref
   17.10 +	CFI_STARTPROC simple
   17.11 +	CFI_DEF_CFA rsp,SS+8-\ref
   17.12 +	/*CFI_REL_OFFSET ss,SS-\ref*/
   17.13 +	CFI_REL_OFFSET rsp,RSP-\ref
   17.14 +	/*CFI_REL_OFFSET rflags,EFLAGS-\ref*/
   17.15 +	/*CFI_REL_OFFSET cs,CS-\ref*/
   17.16 +	CFI_REL_OFFSET rip,RIP-\ref
   17.17 +	.endm
   17.18 +
   17.19 +/*
   17.20   * System call entry. Upto 6 arguments in registers are supported.
   17.21   *
   17.22   * SYSCALL does not save anything on the stack and does not change the
   17.23 @@ -232,10 +245,7 @@ END(ret_from_fork)
   17.24   */ 			 		
   17.25  
   17.26  ENTRY(system_call)
   17.27 -	CFI_STARTPROC	simple
   17.28 -	CFI_DEF_CFA	rsp,PDA_STACKOFFSET
   17.29 -	CFI_REGISTER	rip,rcx
   17.30 -	/*CFI_REGISTER	rflags,r11*/
   17.31 +	_frame (RIP-0x10)
   17.32  	SAVE_ARGS -8,0
   17.33  	movq  %rax,ORIG_RAX-ARGOFFSET(%rsp) 
   17.34  	/*
   17.35 @@ -273,9 +283,7 @@ sysret_check:
   17.36  	 */
   17.37  	TRACE_IRQS_ON
   17.38          XEN_UNBLOCK_EVENTS(%rsi)                
   17.39 -	CFI_REGISTER	rip,rcx
   17.40  	RESTORE_ARGS 0,8,0
   17.41 -	/*CFI_REGISTER	rflags,r11*/
   17.42          HYPERVISOR_IRET VGCF_IN_SYSCALL
   17.43  
   17.44  	/* Handle reschedules */
   17.45 @@ -505,24 +513,16 @@ ENTRY(stub_rt_sigreturn)
   17.46  	CFI_ENDPROC
   17.47  END(stub_rt_sigreturn)
   17.48  
   17.49 -/*
   17.50 - * initial frame state for interrupts and exceptions
   17.51 - */
   17.52 -	.macro _frame ref
   17.53 -	CFI_STARTPROC simple
   17.54 -	CFI_DEF_CFA rsp,SS+8-\ref
   17.55 -	/*CFI_REL_OFFSET ss,SS-\ref*/
   17.56 -	CFI_REL_OFFSET rsp,RSP-\ref
   17.57 -	/*CFI_REL_OFFSET rflags,EFLAGS-\ref*/
   17.58 -	/*CFI_REL_OFFSET cs,CS-\ref*/
   17.59 -	CFI_REL_OFFSET rip,RIP-\ref
   17.60 -	.endm
   17.61 +/* initial frame state for interrupts (and exceptions without error code) */
   17.62 +#define INTR_FRAME _frame (RIP-0x10); \
   17.63 +	CFI_REL_OFFSET rcx,0; \
   17.64 +	CFI_REL_OFFSET r11,8
   17.65  
   17.66 -/* initial frame state for interrupts (and exceptions without error code) */
   17.67 -#define INTR_FRAME _frame RIP
   17.68  /* initial frame state for exceptions with error code (and interrupts with
   17.69     vector already pushed) */
   17.70 -#define XCPT_FRAME _frame ORIG_RAX
   17.71 +#define XCPT_FRAME _frame (RIP-0x18); \
   17.72 +	CFI_REL_OFFSET rcx,0; \
   17.73 +	CFI_REL_OFFSET r11,8
   17.74  
   17.75  /* 
   17.76   * Interrupt exit.
   17.77 @@ -599,8 +599,9 @@ retint_kernel:
   17.78  #endif	
   17.79  
   17.80  	CFI_ENDPROC
   17.81 -END(common_interrupt)
   17.82 +END(retint_check)
   17.83  	
   17.84 +#ifndef CONFIG_XEN
   17.85  /*
   17.86   * APIC interrupts.
   17.87   */		
   17.88 @@ -613,7 +614,6 @@ END(common_interrupt)
   17.89  	CFI_ENDPROC
   17.90  	.endm
   17.91  
   17.92 -#ifndef CONFIG_XEN
   17.93  ENTRY(thermal_interrupt)
   17.94  	apicinterrupt THERMAL_APIC_VECTOR,smp_thermal_interrupt
   17.95  END(thermal_interrupt)
   17.96 @@ -668,12 +668,16 @@ END(spurious_interrupt)
   17.97  	.macro zeroentry sym
   17.98  	INTR_FRAME
   17.99          movq (%rsp),%rcx
  17.100 +	CFI_RESTORE rcx
  17.101          movq 8(%rsp),%r11
  17.102 +	CFI_RESTORE r11
  17.103          addq $0x10,%rsp /* skip rcx and r11 */
  17.104 +	CFI_ADJUST_CFA_OFFSET -0x10
  17.105  	pushq $0	/* push error code/oldrax */ 
  17.106  	CFI_ADJUST_CFA_OFFSET 8
  17.107  	pushq %rax	/* push real oldrax to the rdi slot */ 
  17.108  	CFI_ADJUST_CFA_OFFSET 8
  17.109 +	CFI_REL_OFFSET rax,0
  17.110  	leaq  \sym(%rip),%rax
  17.111  	jmp error_entry
  17.112  	CFI_ENDPROC
  17.113 @@ -682,10 +686,14 @@ END(spurious_interrupt)
  17.114  	.macro errorentry sym
  17.115  	XCPT_FRAME
  17.116          movq (%rsp),%rcx
  17.117 +	CFI_RESTORE rcx
  17.118          movq 8(%rsp),%r11
  17.119 +	CFI_RESTORE r11
  17.120          addq $0x10,%rsp /* rsp points to the error code */
  17.121 +	CFI_ADJUST_CFA_OFFSET -0x10
  17.122  	pushq %rax
  17.123  	CFI_ADJUST_CFA_OFFSET 8
  17.124 +	CFI_REL_OFFSET rax,0
  17.125  	leaq  \sym(%rip),%rax
  17.126  	jmp error_entry
  17.127  	CFI_ENDPROC
  17.128 @@ -799,6 +807,7 @@ paranoid_schedule\trace:
  17.129   */ 		  				
  17.130  ENTRY(error_entry)
  17.131  	_frame RDI
  17.132 +	CFI_REL_OFFSET rax,0
  17.133  	/* rdi slot contains rax, oldrax contains error code */
  17.134  	cld	
  17.135  	subq  $14*8,%rsp
  17.136 @@ -806,6 +815,7 @@ ENTRY(error_entry)
  17.137  	movq %rsi,13*8(%rsp)
  17.138  	CFI_REL_OFFSET	rsi,RSI
  17.139  	movq 14*8(%rsp),%rsi	/* load rax from rdi slot */
  17.140 +	CFI_REGISTER	rax,rsi
  17.141  	movq %rdx,12*8(%rsp)
  17.142  	CFI_REL_OFFSET	rdx,RDX
  17.143  	movq %rcx,11*8(%rsp)
  17.144 @@ -839,6 +849,7 @@ ENTRY(error_entry)
  17.145  #endif        
  17.146  error_call_handler:
  17.147  	movq %rdi, RDI(%rsp)            
  17.148 +	CFI_REL_OFFSET	rdi,RDI
  17.149  	movq %rsp,%rdi
  17.150  	movq ORIG_RAX(%rsp),%rsi	# get error code 
  17.151  	movq $-1,ORIG_RAX(%rsp)
  17.152 @@ -1186,7 +1197,7 @@ END(int3)
  17.153  
  17.154  ENTRY(overflow)
  17.155  	zeroentry do_overflow
  17.156 -END(debug)
  17.157 +END(overflow)
  17.158  
  17.159  ENTRY(bounds)
  17.160  	zeroentry do_bounds
    18.1 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/head-xen.S	Fri Apr 06 10:06:30 2007 -0600
    18.2 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/head-xen.S	Fri Apr 06 10:08:30 2007 -0600
    18.3 @@ -33,9 +33,6 @@
    18.4  startup_64:
    18.5  ENTRY(_start)
    18.6  	movq $(init_thread_union+THREAD_SIZE-8),%rsp
    18.7 -	/* zero EFLAGS after setting rsp */
    18.8 -	pushq $0
    18.9 -	popfq
   18.10  
   18.11  	/* rsi is pointer to startup info structure.
   18.12  	   pass it to C */
   18.13 @@ -155,7 +152,7 @@ gdt_end:
   18.14  ENTRY(empty_zero_page)
   18.15  	.skip PAGE_SIZE
   18.16  
   18.17 -#ifdef CONFIG_XEN_COMPAT_030002
   18.18 +#if CONFIG_XEN_COMPAT <= 0x030002
   18.19  /*
   18.20   * __xen_guest information
   18.21   */
   18.22 @@ -187,17 +184,17 @@ ENTRY(empty_zero_page)
   18.23  	.ascii	         "|supervisor_mode_kernel"
   18.24  	.ascii	",LOADER=generic"
   18.25  	.byte	0
   18.26 -#endif /* CONFIG_XEN_COMPAT_030002 */
   18.27 +#endif /* CONFIG_XEN_COMPAT <= 0x030002 */
   18.28  	
   18.29  	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS,       .asciz, "linux")
   18.30  	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION,  .asciz, "2.6")
   18.31  	ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION,    .asciz, "xen-3.0")
   18.32  	ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE,      .quad,  __START_KERNEL_map)
   18.33 -#ifdef CONFIG_XEN_COMPAT_030002
   18.34 +#if CONFIG_XEN_COMPAT <= 0x030002
   18.35  	ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .quad,  __START_KERNEL_map)
   18.36  #else
   18.37  	ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   .quad,  0)
   18.38 -#endif /* !CONFIG_XEN_COMPAT_030002 */
   18.39 +#endif
   18.40  	ELFNOTE(Xen, XEN_ELFNOTE_ENTRY,          .quad,  startup_64)
   18.41  	ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, .quad,  hypercall_page)
   18.42  	ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID,   .quad,  _PAGE_PRESENT,_PAGE_PRESENT)
    19.1 --- a/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c	Fri Apr 06 10:06:30 2007 -0600
    19.2 +++ b/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c	Fri Apr 06 10:08:30 2007 -0600
    19.3 @@ -54,7 +54,7 @@
    19.4  struct dma_mapping_ops* dma_ops;
    19.5  EXPORT_SYMBOL(dma_ops);
    19.6  
    19.7 -#ifdef CONFIG_XEN_COMPAT_030002
    19.8 +#if CONFIG_XEN_COMPAT <= 0x030002
    19.9  unsigned int __kernel_page_user;
   19.10  EXPORT_SYMBOL(__kernel_page_user);
   19.11  #endif
   19.12 @@ -551,7 +551,7 @@ void __init xen_init_pt(void)
   19.13  	addr = page[pud_index(__START_KERNEL_map)];
   19.14  	addr_to_page(addr, page);
   19.15  
   19.16 -#ifdef CONFIG_XEN_COMPAT_030002
   19.17 +#if CONFIG_XEN_COMPAT <= 0x030002
   19.18  	/* On Xen 3.0.2 and older we may need to explicitly specify _PAGE_USER
   19.19  	   in kernel PTEs. We check that here. */
   19.20  	if (HYPERVISOR_xen_version(XENVER_version, NULL) <= 0x30000) {
    20.1 --- a/linux-2.6-xen-sparse/drivers/xen/Kconfig	Fri Apr 06 10:06:30 2007 -0600
    20.2 +++ b/linux-2.6-xen-sparse/drivers/xen/Kconfig	Fri Apr 06 10:08:30 2007 -0600
    20.3 @@ -235,13 +235,12 @@ choice
    20.4  
    20.5  endchoice
    20.6  
    20.7 -config XEN_COMPAT_030002
    20.8 -	bool
    20.9 -	default XEN_COMPAT_030002_AND_LATER
   20.10 -
   20.11 -config XEN_COMPAT_030004
   20.12 -	bool
   20.13 -	default XEN_COMPAT_030002_AND_LATER || XEN_COMPAT_030004_AND_LATER
   20.14 +config XEN_COMPAT
   20.15 +	hex
   20.16 +	default 0xffffff if XEN_COMPAT_LATEST_ONLY
   20.17 +	default 0x030004 if XEN_COMPAT_030004_AND_LATER
   20.18 +	default 0x030002 if XEN_COMPAT_030002_AND_LATER
   20.19 +	default 0
   20.20  
   20.21  endmenu
   20.22  
    21.1 --- a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c	Fri Apr 06 10:06:30 2007 -0600
    21.2 +++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c	Fri Apr 06 10:08:30 2007 -0600
    21.3 @@ -48,14 +48,21 @@
    21.4  #include <asm/hypervisor.h>
    21.5  #include <xen/balloon.h>
    21.6  #include <xen/interface/memory.h>
    21.7 +#include <asm/maddr.h>
    21.8 +#include <asm/page.h>
    21.9  #include <asm/pgalloc.h>
   21.10  #include <asm/pgtable.h>
   21.11  #include <asm/uaccess.h>
   21.12  #include <asm/tlb.h>
   21.13 +#include <linux/highmem.h>
   21.14  #include <linux/list.h>
   21.15  #include <xen/xenbus.h>
   21.16  #include "common.h"
   21.17  
   21.18 +#ifdef HAVE_XEN_PLATFORM_COMPAT_H
   21.19 +#include <xen/platform-compat.h>
   21.20 +#endif
   21.21 +
   21.22  #ifdef CONFIG_PROC_FS
   21.23  static struct proc_dir_entry *balloon_pde;
   21.24  #endif
   21.25 @@ -217,6 +224,7 @@ static int increase_reservation(unsigned
   21.26  
   21.27  		set_phys_to_machine(pfn, frame_list[i]);
   21.28  
   21.29 +#ifdef CONFIG_XEN
   21.30  		/* Link back into the page tables if not highmem. */
   21.31  		if (pfn < max_low_pfn) {
   21.32  			int ret;
   21.33 @@ -226,6 +234,7 @@ static int increase_reservation(unsigned
   21.34  				0);
   21.35  			BUG_ON(ret);
   21.36  		}
   21.37 +#endif
   21.38  
   21.39  		/* Relinquish the page back to the allocator. */
   21.40  		ClearPageReserved(page);
   21.41 @@ -271,9 +280,11 @@ static int decrease_reservation(unsigned
   21.42  		if (!PageHighMem(page)) {
   21.43  			v = phys_to_virt(pfn << PAGE_SHIFT);
   21.44  			scrub_pages(v, 1);
   21.45 +#ifdef CONFIG_XEN
   21.46  			ret = HYPERVISOR_update_va_mapping(
   21.47  				(unsigned long)v, __pte_ma(0), 0);
   21.48  			BUG_ON(ret);
   21.49 +#endif
   21.50  		}
   21.51  #ifdef CONFIG_XEN_SCRUB_PAGES
   21.52  		else {
   21.53 @@ -284,9 +295,11 @@ static int decrease_reservation(unsigned
   21.54  #endif
   21.55  	}
   21.56  
   21.57 +#ifdef CONFIG_XEN
   21.58  	/* Ensure that ballooned highmem pages don't have kmaps. */
   21.59  	kmap_flush_unused();
   21.60  	flush_tlb_all();
   21.61 +#endif
   21.62  
   21.63  	balloon_lock(flags);
   21.64  
   21.65 @@ -446,7 +459,7 @@ static struct notifier_block xenstore_no
   21.66  
   21.67  static int __init balloon_init(void)
   21.68  {
   21.69 -#ifdef CONFIG_X86
   21.70 +#if defined(CONFIG_X86) && defined(CONFIG_XEN) 
   21.71  	unsigned long pfn;
   21.72  	struct page *page;
   21.73  #endif
   21.74 @@ -456,8 +469,12 @@ static int __init balloon_init(void)
   21.75  
   21.76  	IPRINTK("Initialising balloon driver.\n");
   21.77  
   21.78 +#ifdef CONFIG_XEN
   21.79  	bs.current_pages = min(xen_start_info->nr_pages, max_pfn);
   21.80  	totalram_pages   = bs.current_pages;
   21.81 +#else 
   21.82 +	bs.current_pages = totalram_pages; 
   21.83 +#endif
   21.84  	bs.target_pages  = bs.current_pages;
   21.85  	bs.balloon_low   = 0;
   21.86  	bs.balloon_high  = 0;
   21.87 @@ -479,7 +496,7 @@ static int __init balloon_init(void)
   21.88  #endif
   21.89  	balloon_sysfs_init();
   21.90  
   21.91 -#ifdef CONFIG_X86
   21.92 +#if defined(CONFIG_X86) && defined(CONFIG_XEN) 
   21.93  	/* Initialise the balloon with excess memory space. */
   21.94  	for (pfn = xen_start_info->nr_pages; pfn < max_pfn; pfn++) {
   21.95  		page = pfn_to_page(pfn);
   21.96 @@ -498,6 +515,14 @@ static int __init balloon_init(void)
   21.97  
   21.98  subsys_initcall(balloon_init);
   21.99  
  21.100 +static void balloon_exit(void) 
  21.101 +{
  21.102 +    /* XXX - release balloon here */
  21.103 +    return; 
  21.104 +}
  21.105 +
  21.106 +module_exit(balloon_exit); 
  21.107 +
  21.108  void balloon_update_driver_allowance(long delta)
  21.109  {
  21.110  	unsigned long flags;
  21.111 @@ -507,6 +532,7 @@ void balloon_update_driver_allowance(lon
  21.112  	balloon_unlock(flags);
  21.113  }
  21.114  
  21.115 +#ifdef CONFIG_XEN
  21.116  static int dealloc_pte_fn(
  21.117  	pte_t *pte, struct page *pmd_page, unsigned long addr, void *data)
  21.118  {
  21.119 @@ -524,6 +550,7 @@ static int dealloc_pte_fn(
  21.120  	BUG_ON(ret != 1);
  21.121  	return 0;
  21.122  }
  21.123 +#endif
  21.124  
  21.125  struct page **alloc_empty_pages_and_pagevec(int nr_pages)
  21.126  {
  21.127 @@ -559,8 +586,13 @@ struct page **alloc_empty_pages_and_page
  21.128  			if (ret == 1)
  21.129  				ret = 0; /* success */
  21.130  		} else {
  21.131 +#ifdef CONFIG_XEN
  21.132  			ret = apply_to_page_range(&init_mm, vaddr, PAGE_SIZE,
  21.133  						  dealloc_pte_fn, NULL);
  21.134 +#else
  21.135 +			/* Cannot handle non-auto translate mode. */
  21.136 +			ret = 1;
  21.137 +#endif
  21.138  		}
  21.139  
  21.140  		if (ret != 0) {
  21.141 @@ -576,7 +608,9 @@ struct page **alloc_empty_pages_and_page
  21.142  
  21.143   out:
  21.144  	schedule_work(&balloon_worker);
  21.145 +#ifdef CONFIG_XEN
  21.146  	flush_tlb_all();
  21.147 +#endif
  21.148  	return pagevec;
  21.149  
  21.150   err:
    22.1 --- a/linux-2.6-xen-sparse/drivers/xen/balloon/sysfs.c	Fri Apr 06 10:06:30 2007 -0600
    22.2 +++ b/linux-2.6-xen-sparse/drivers/xen/balloon/sysfs.c	Fri Apr 06 10:08:30 2007 -0600
    22.3 @@ -29,10 +29,16 @@
    22.4   */
    22.5  
    22.6  #include <linux/capability.h>
    22.7 +#include <linux/errno.h>
    22.8  #include <linux/stat.h>
    22.9 +#include <linux/string.h>
   22.10  #include <linux/sysdev.h>
   22.11  #include "common.h"
   22.12  
   22.13 +#ifdef HAVE_XEN_PLATFORM_COMPAT_H
   22.14 +#include <xen/platform-compat.h>
   22.15 +#endif
   22.16 +
   22.17  #define BALLOON_CLASS_NAME "memory"
   22.18  
   22.19  #define BALLOON_SHOW(name, format, args...)			\
    23.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c	Fri Apr 06 10:06:30 2007 -0600
    23.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c	Fri Apr 06 10:08:30 2007 -0600
    23.3 @@ -661,9 +661,10 @@ void do_blkif_request(request_queue_t *r
    23.4  		if (RING_FULL(&info->ring))
    23.5  			goto wait;
    23.6  
    23.7 -		DPRINTK("do_blk_req %p: cmd %p, sec %lx, "
    23.8 +		DPRINTK("do_blk_req %p: cmd %p, sec %llx, "
    23.9  			"(%u/%li) buffer:%p [%s]\n",
   23.10 -			req, req->cmd, req->sector, req->current_nr_sectors,
   23.11 +			req, req->cmd, (long long)req->sector,
   23.12 +			req->current_nr_sectors,
   23.13  			req->nr_sectors, req->buffer,
   23.14  			rq_data_dir(req) ? "write" : "read");
   23.15  
    24.1 --- a/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c	Fri Apr 06 10:06:30 2007 -0600
    24.2 +++ b/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c	Fri Apr 06 10:08:30 2007 -0600
    24.3 @@ -7,7 +7,6 @@
    24.4  #include <xen/interface/kexec.h>
    24.5  #include <linux/mm.h>
    24.6  #include <linux/bootmem.h>
    24.7 -#include <asm/hypercall.h>
    24.8  
    24.9  extern void machine_kexec_setup_load_arg(xen_kexec_image_t *xki, 
   24.10  					 struct kimage *image);
    25.1 --- a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c	Fri Apr 06 10:06:30 2007 -0600
    25.2 +++ b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c	Fri Apr 06 10:08:30 2007 -0600
    25.3 @@ -9,6 +9,10 @@
    25.4  #include <xen/xenbus.h>
    25.5  #include <linux/kthread.h>
    25.6  
    25.7 +#ifdef HAVE_XEN_PLATFORM_COMPAT_H
    25.8 +#include <xen/platform-compat.h>
    25.9 +#endif
   25.10 +
   25.11  MODULE_LICENSE("Dual BSD/GPL");
   25.12  
   25.13  #define SHUTDOWN_INVALID  -1
    26.1 --- a/linux-2.6-xen-sparse/drivers/xen/core/xen_proc.c	Fri Apr 06 10:06:30 2007 -0600
    26.2 +++ b/linux-2.6-xen-sparse/drivers/xen/core/xen_proc.c	Fri Apr 06 10:08:30 2007 -0600
    26.3 @@ -1,4 +1,5 @@
    26.4  
    26.5 +#include <linux/module.h>
    26.6  #include <linux/proc_fs.h>
    26.7  #include <xen/xen_proc.h>
    26.8  
    26.9 @@ -12,7 +13,11 @@ struct proc_dir_entry *create_xen_proc_e
   26.10  	return create_proc_entry(name, mode, xen_base);
   26.11  }
   26.12  
   26.13 +EXPORT_SYMBOL_GPL(create_xen_proc_entry); 
   26.14 +
   26.15  void remove_xen_proc_entry(const char *name)
   26.16  {
   26.17  	remove_proc_entry(name, xen_base);
   26.18  }
   26.19 +
   26.20 +EXPORT_SYMBOL_GPL(remove_xen_proc_entry); 
    27.1 --- a/linux-2.6-xen-sparse/drivers/xen/fbfront/xenfb.c	Fri Apr 06 10:06:30 2007 -0600
    27.2 +++ b/linux-2.6-xen-sparse/drivers/xen/fbfront/xenfb.c	Fri Apr 06 10:08:30 2007 -0600
    27.3 @@ -24,6 +24,7 @@
    27.4  #include <linux/module.h>
    27.5  #include <linux/vmalloc.h>
    27.6  #include <linux/mm.h>
    27.7 +#include <linux/mutex.h>
    27.8  #include <asm/hypervisor.h>
    27.9  #include <xen/evtchn.h>
   27.10  #include <xen/interface/io/fbif.h>
    28.1 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c	Fri Apr 06 10:06:30 2007 -0600
    28.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c	Fri Apr 06 10:08:30 2007 -0600
    28.3 @@ -1511,7 +1511,7 @@ static void netif_release_rx_bufs(struct
    28.4  	struct sk_buff *skb;
    28.5  	unsigned long mfn;
    28.6  	int xfer = 0, noxfer = 0, unused = 0;
    28.7 -	int id, ref;
    28.8 +	int id, ref, rc;
    28.9  
   28.10  	if (np->copying_receiver) {
   28.11  		WPRINTK("%s: fix me for copying receiver.\n", __FUNCTION__);
   28.12 @@ -1579,7 +1579,9 @@ static void netif_release_rx_bufs(struct
   28.13  			mcl->args[2] = 0;
   28.14  			mcl->args[3] = DOMID_SELF;
   28.15  			mcl++;
   28.16 -			HYPERVISOR_multicall(np->rx_mcl, mcl - np->rx_mcl);
   28.17 +			rc = HYPERVISOR_multicall_check(
   28.18 +				np->rx_mcl, mcl - np->rx_mcl, NULL);
   28.19 +			BUG_ON(rc);
   28.20  		}
   28.21  	}
   28.22  
    29.1 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h	Fri Apr 06 10:06:30 2007 -0600
    29.2 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h	Fri Apr 06 10:08:30 2007 -0600
    29.3 @@ -238,7 +238,7 @@ HYPERVISOR_memory_op(
    29.4  
    29.5  static inline int
    29.6  HYPERVISOR_multicall(
    29.7 -	void *call_list, int nr_calls)
    29.8 +	multicall_entry_t *call_list, int nr_calls)
    29.9  {
   29.10  	return _hypercall2(int, multicall, call_list, nr_calls);
   29.11  }
   29.12 @@ -261,7 +261,7 @@ HYPERVISOR_event_channel_op(
   29.13  {
   29.14  	int rc = _hypercall2(int, event_channel_op, cmd, arg);
   29.15  
   29.16 -#ifdef CONFIG_XEN_COMPAT_030002
   29.17 +#if CONFIG_XEN_COMPAT <= 0x030002
   29.18  	if (unlikely(rc == -ENOSYS)) {
   29.19  		struct evtchn_op op;
   29.20  		op.cmd = cmd;
   29.21 @@ -301,7 +301,7 @@ HYPERVISOR_physdev_op(
   29.22  {
   29.23  	int rc = _hypercall2(int, physdev_op, cmd, arg);
   29.24  
   29.25 -#ifdef CONFIG_XEN_COMPAT_030002
   29.26 +#if CONFIG_XEN_COMPAT <= 0x030002
   29.27  	if (unlikely(rc == -ENOSYS)) {
   29.28  		struct physdev_op op;
   29.29  		op.cmd = cmd;
   29.30 @@ -358,7 +358,7 @@ HYPERVISOR_suspend(
   29.31  	int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown,
   29.32  			     &sched_shutdown, srec);
   29.33  
   29.34 -#ifdef CONFIG_XEN_COMPAT_030002
   29.35 +#if CONFIG_XEN_COMPAT <= 0x030002
   29.36  	if (rc == -ENOSYS)
   29.37  		rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown,
   29.38  				 SHUTDOWN_suspend, srec);
    30.1 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h	Fri Apr 06 10:06:30 2007 -0600
    30.2 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h	Fri Apr 06 10:08:30 2007 -0600
    30.3 @@ -122,7 +122,13 @@ void xen_destroy_contiguous_region(
    30.4  /* Turn jiffies into Xen system time. */
    30.5  u64 jiffies_to_st(unsigned long jiffies);
    30.6  
    30.7 -#include <asm/hypercall.h>
    30.8 +#ifdef CONFIG_XEN_SCRUB_PAGES
    30.9 +#define scrub_pages(_p,_n) memset((void *)(_p), 0, (_n) << PAGE_SHIFT)
   30.10 +#else
   30.11 +#define scrub_pages(_p,_n) ((void)0)
   30.12 +#endif
   30.13 +
   30.14 +#include <xen/hypercall.h>
   30.15  
   30.16  #if defined(CONFIG_X86_64)
   30.17  #define MULTI_UVMFLAGS_INDEX 2
   30.18 @@ -140,7 +146,7 @@ HYPERVISOR_yield(
   30.19  {
   30.20  	int rc = HYPERVISOR_sched_op(SCHEDOP_yield, NULL);
   30.21  
   30.22 -#ifdef CONFIG_XEN_COMPAT_030002
   30.23 +#if CONFIG_XEN_COMPAT <= 0x030002
   30.24  	if (rc == -ENOSYS)
   30.25  		rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0);
   30.26  #endif
   30.27 @@ -154,7 +160,7 @@ HYPERVISOR_block(
   30.28  {
   30.29  	int rc = HYPERVISOR_sched_op(SCHEDOP_block, NULL);
   30.30  
   30.31 -#ifdef CONFIG_XEN_COMPAT_030002
   30.32 +#if CONFIG_XEN_COMPAT <= 0x030002
   30.33  	if (rc == -ENOSYS)
   30.34  		rc = HYPERVISOR_sched_op_compat(SCHEDOP_block, 0);
   30.35  #endif
   30.36 @@ -172,7 +178,7 @@ HYPERVISOR_shutdown(
   30.37  
   30.38  	int rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
   30.39  
   30.40 -#ifdef CONFIG_XEN_COMPAT_030002
   30.41 +#if CONFIG_XEN_COMPAT <= 0x030002
   30.42  	if (rc == -ENOSYS)
   30.43  		rc = HYPERVISOR_sched_op_compat(SCHEDOP_shutdown, reason);
   30.44  #endif
   30.45 @@ -192,7 +198,7 @@ HYPERVISOR_poll(
   30.46  	set_xen_guest_handle(sched_poll.ports, ports);
   30.47  
   30.48  	rc = HYPERVISOR_sched_op(SCHEDOP_poll, &sched_poll);
   30.49 -#ifdef CONFIG_XEN_COMPAT_030002
   30.50 +#if CONFIG_XEN_COMPAT <= 0x030002
   30.51  	if (rc == -ENOSYS)
   30.52  		rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0);
   30.53  #endif
    31.1 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/maddr.h	Fri Apr 06 10:06:30 2007 -0600
    31.2 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/maddr.h	Fri Apr 06 10:08:30 2007 -0600
    31.3 @@ -158,7 +158,7 @@ static inline paddr_t pte_machine_to_phy
    31.4  #define pfn_to_mfn(pfn) (pfn)
    31.5  #define mfn_to_pfn(mfn) (mfn)
    31.6  #define mfn_to_local_pfn(mfn) (mfn)
    31.7 -#define set_phys_to_machine(pfn, mfn) BUG_ON((pfn) != (mfn))
    31.8 +#define set_phys_to_machine(pfn, mfn) ((void)0)
    31.9  #define phys_to_machine_mapping_valid(pfn) (1)
   31.10  #define phys_to_machine(phys) ((maddr_t)(phys))
   31.11  #define machine_to_phys(mach) ((paddr_t)(mach))
    32.1 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/page.h	Fri Apr 06 10:06:30 2007 -0600
    32.2 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/page.h	Fri Apr 06 10:08:30 2007 -0600
    32.3 @@ -45,12 +45,6 @@
    32.4  })
    32.5  #define HAVE_ARCH_FREE_PAGE
    32.6  
    32.7 -#ifdef CONFIG_XEN_SCRUB_PAGES
    32.8 -#define scrub_pages(_p,_n) memset((void *)(_p), 0, (_n) << PAGE_SHIFT)
    32.9 -#else
   32.10 -#define scrub_pages(_p,_n) ((void)0)
   32.11 -#endif
   32.12 -
   32.13  #ifdef CONFIG_X86_USE_3DNOW
   32.14  
   32.15  #include <asm/mmx.h>
   32.16 @@ -108,7 +102,7 @@ static inline unsigned long long pte_val
   32.17  static inline unsigned long long pmd_val(pmd_t x)
   32.18  {
   32.19  	unsigned long long ret = x.pmd;
   32.20 -#ifdef CONFIG_XEN_COMPAT_030002
   32.21 +#if CONFIG_XEN_COMPAT <= 0x030002
   32.22  	if (ret) ret = pte_machine_to_phys(ret) | _PAGE_PRESENT;
   32.23  #else
   32.24  	if (ret & _PAGE_PRESENT) ret = pte_machine_to_phys(ret);
   32.25 @@ -140,7 +134,7 @@ typedef struct { unsigned long pgprot; }
   32.26  static inline unsigned long pgd_val(pgd_t x)
   32.27  {
   32.28  	unsigned long ret = x.pgd;
   32.29 -#ifdef CONFIG_XEN_COMPAT_030002
   32.30 +#if CONFIG_XEN_COMPAT <= 0x030002
   32.31  	if (ret) ret = machine_to_phys(ret) | _PAGE_PRESENT;
   32.32  #else
   32.33  	if (ret & _PAGE_PRESENT) ret = machine_to_phys(ret);
   32.34 @@ -203,10 +197,10 @@ extern int page_is_ram(unsigned long pag
   32.35  #endif
   32.36  #define __KERNEL_START		(__PAGE_OFFSET + __PHYSICAL_START)
   32.37  
   32.38 -#ifdef CONFIG_XEN_COMPAT_030002
   32.39 +#if CONFIG_XEN_COMPAT <= 0x030002
   32.40  #undef LOAD_OFFSET
   32.41  #define LOAD_OFFSET		0
   32.42 -#endif /* CONFIG_XEN_COMPAT_030002 */
   32.43 +#endif
   32.44  
   32.45  #define PAGE_OFFSET		((unsigned long)__PAGE_OFFSET)
   32.46  #define VMALLOC_RESERVE		((unsigned long)__VMALLOC_RESERVE)
    33.1 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-2level.h	Fri Apr 06 10:06:30 2007 -0600
    33.2 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-2level.h	Fri Apr 06 10:08:30 2007 -0600
    33.3 @@ -36,8 +36,37 @@
    33.4  #define pte_clear(mm,addr,xp)	do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
    33.5  #define pmd_clear(xp)	do { set_pmd(xp, __pmd(0)); } while (0)
    33.6  
    33.7 -#define ptep_get_and_clear(mm,addr,xp)	__pte_ma(xchg(&(xp)->pte_low, 0))
    33.8 +#define pte_none(x) (!(x).pte_low)
    33.9 +
   33.10 +static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
   33.11 +{
   33.12 +	pte_t pte = *ptep;
   33.13 +	if (!pte_none(pte)) {
   33.14 +		if (mm != &init_mm)
   33.15 +			pte = __pte_ma(xchg(&ptep->pte_low, 0));
   33.16 +		else
   33.17 +			HYPERVISOR_update_va_mapping(addr, __pte(0), 0);
   33.18 +	}
   33.19 +	return pte;
   33.20 +}
   33.21 +
   33.22 +#define ptep_clear_flush(vma, addr, ptep)			\
   33.23 +({								\
   33.24 +	pte_t *__ptep = (ptep);					\
   33.25 +	pte_t __res = *__ptep;					\
   33.26 +	if (!pte_none(__res) &&					\
   33.27 +	    ((vma)->vm_mm != current->mm ||			\
   33.28 +	     HYPERVISOR_update_va_mapping(addr, __pte(0),	\
   33.29 +			(unsigned long)(vma)->vm_mm->cpu_vm_mask.bits| \
   33.30 +				UVMF_INVLPG|UVMF_MULTI))) {	\
   33.31 +		__ptep->pte_low = 0;				\
   33.32 +		flush_tlb_page(vma, addr);			\
   33.33 +	}							\
   33.34 +	__res;							\
   33.35 +})
   33.36 +
   33.37  #define pte_same(a, b)		((a).pte_low == (b).pte_low)
   33.38 +
   33.39  #define __pte_mfn(_pte) ((_pte).pte_low >> PAGE_SHIFT)
   33.40  #define pte_mfn(_pte) ((_pte).pte_low & _PAGE_PRESENT ? \
   33.41  	__pte_mfn(_pte) : pfn_to_mfn(__pte_mfn(_pte)))
   33.42 @@ -46,7 +75,6 @@
   33.43  
   33.44  #define pte_page(_pte) pfn_to_page(pte_pfn(_pte))
   33.45  
   33.46 -#define pte_none(x)		(!(x).pte_low)
   33.47  #define pfn_pte(pfn, prot)	__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
   33.48  #define pfn_pmd(pfn, prot)	__pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
   33.49  
    34.1 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-3level.h	Fri Apr 06 10:06:30 2007 -0600
    34.2 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-3level.h	Fri Apr 06 10:08:30 2007 -0600
    34.3 @@ -99,6 +99,11 @@ static inline void pud_clear (pud_t * pu
    34.4  #define pmd_offset(pud, address) ((pmd_t *) pud_page(*(pud)) + \
    34.5  			pmd_index(address))
    34.6  
    34.7 +static inline int pte_none(pte_t pte)
    34.8 +{
    34.9 +	return !(pte.pte_low | pte.pte_high);
   34.10 +}
   34.11 +
   34.12  /*
   34.13   * For PTEs and PDEs, we must clear the P-bit first when clearing a page table
   34.14   * entry, so clear the bottom half first and enforce ordering with a compiler
   34.15 @@ -106,24 +111,50 @@ static inline void pud_clear (pud_t * pu
   34.16   */
   34.17  static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
   34.18  {
   34.19 -	ptep->pte_low = 0;
   34.20 -	smp_wmb();
   34.21 -	ptep->pte_high = 0;
   34.22 +	if ((mm != current->mm && mm != &init_mm)
   34.23 +	    || HYPERVISOR_update_va_mapping(addr, __pte(0), 0)) {
   34.24 +		ptep->pte_low = 0;
   34.25 +		smp_wmb();
   34.26 +		ptep->pte_high = 0;
   34.27 +	}
   34.28  }
   34.29  
   34.30  #define pmd_clear(xp)	do { set_pmd(xp, __pmd(0)); } while (0)
   34.31  
   34.32  static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
   34.33  {
   34.34 -	pte_t res;
   34.35 +	pte_t pte = *ptep;
   34.36 +	if (!pte_none(pte)) {
   34.37 +		if (mm != &init_mm) {
   34.38 +			uint64_t val = pte_val_ma(pte);
   34.39 +			if (__cmpxchg64(ptep, val, 0) != val) {
   34.40 +				/* xchg acts as a barrier before the setting of the high bits */
   34.41 +				pte.pte_low = xchg(&ptep->pte_low, 0);
   34.42 +				pte.pte_high = ptep->pte_high;
   34.43 +				ptep->pte_high = 0;
   34.44 +			}
   34.45 +		} else
   34.46 +			HYPERVISOR_update_va_mapping(addr, __pte(0), 0);
   34.47 +	}
   34.48 +	return pte;
   34.49 +}
   34.50  
   34.51 -	/* xchg acts as a barrier before the setting of the high bits */
   34.52 -	res.pte_low = xchg(&ptep->pte_low, 0);
   34.53 -	res.pte_high = ptep->pte_high;
   34.54 -	ptep->pte_high = 0;
   34.55 -
   34.56 -	return res;
   34.57 -}
   34.58 +#define ptep_clear_flush(vma, addr, ptep)			\
   34.59 +({								\
   34.60 +	pte_t *__ptep = (ptep);					\
   34.61 +	pte_t __res = *__ptep;					\
   34.62 +	if (!pte_none(__res) &&					\
   34.63 +	    ((vma)->vm_mm != current->mm ||			\
   34.64 +	     HYPERVISOR_update_va_mapping(addr,	__pte(0),	\
   34.65 +			(unsigned long)(vma)->vm_mm->cpu_vm_mask.bits| \
   34.66 +				UVMF_INVLPG|UVMF_MULTI))) {	\
   34.67 +		__ptep->pte_low = 0;				\
   34.68 +		smp_wmb();					\
   34.69 +		__ptep->pte_high = 0;				\
   34.70 +		flush_tlb_page(vma, addr);			\
   34.71 +	}							\
   34.72 +	__res;							\
   34.73 +})
   34.74  
   34.75  static inline int pte_same(pte_t a, pte_t b)
   34.76  {
   34.77 @@ -132,11 +163,6 @@ static inline int pte_same(pte_t a, pte_
   34.78  
   34.79  #define pte_page(x)	pfn_to_page(pte_pfn(x))
   34.80  
   34.81 -static inline int pte_none(pte_t pte)
   34.82 -{
   34.83 -	return !pte.pte_low && !pte.pte_high;
   34.84 -}
   34.85 -
   34.86  #define __pte_mfn(_pte) (((_pte).pte_low >> PAGE_SHIFT) | \
   34.87  			 ((_pte).pte_high << (32-PAGE_SHIFT)))
   34.88  #define pte_mfn(_pte) ((_pte).pte_low & _PAGE_PRESENT ? \
    35.1 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable.h	Fri Apr 06 10:06:30 2007 -0600
    35.2 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable.h	Fri Apr 06 10:08:30 2007 -0600
    35.3 @@ -210,9 +210,13 @@ extern unsigned long pg0[];
    35.4  
    35.5  /* To avoid harmful races, pmd_none(x) should check only the lower when PAE */
    35.6  #define pmd_none(x)	(!(unsigned long)pmd_val(x))
    35.7 +#ifdef CONFIG_XEN_COMPAT_030002
    35.8  /* pmd_present doesn't just test the _PAGE_PRESENT bit since wr.p.t.
    35.9     can temporarily clear it. */
   35.10  #define pmd_present(x)	(pmd_val(x))
   35.11 +#else
   35.12 +#define pmd_present(x)	(pmd_val(x) & _PAGE_PRESENT)
   35.13 +#endif
   35.14  #define pmd_bad(x)	((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER & ~_PAGE_PRESENT)) != (_KERNPG_TABLE & ~_PAGE_PRESENT))
   35.15  
   35.16  
   35.17 @@ -252,36 +256,47 @@ static inline pte_t pte_mkhuge(pte_t pte
   35.18  # include <asm/pgtable-2level.h>
   35.19  #endif
   35.20  
   35.21 -static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
   35.22 -{
   35.23 -	if (!pte_dirty(*ptep))
   35.24 -		return 0;
   35.25 -	return test_and_clear_bit(_PAGE_BIT_DIRTY, &ptep->pte_low);
   35.26 -}
   35.27 +#define ptep_test_and_clear_dirty(vma, addr, ptep)			\
   35.28 +({									\
   35.29 +	pte_t __pte = *(ptep);						\
   35.30 +	int __ret = pte_dirty(__pte);					\
   35.31 +	if (__ret) {							\
   35.32 +		__pte = pte_mkclean(__pte);				\
   35.33 +		if ((vma)->vm_mm != current->mm ||			\
   35.34 +		    HYPERVISOR_update_va_mapping(addr, __pte, 0))	\
   35.35 +			(ptep)->pte_low = __pte.pte_low;		\
   35.36 +	}								\
   35.37 +	__ret;								\
   35.38 +})
   35.39  
   35.40 -static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
   35.41 -{
   35.42 -	if (!pte_young(*ptep))
   35.43 -		return 0;
   35.44 -	return test_and_clear_bit(_PAGE_BIT_ACCESSED, &ptep->pte_low);
   35.45 -}
   35.46 +#define ptep_test_and_clear_young(vma, addr, ptep)			\
   35.47 +({									\
   35.48 +	pte_t __pte = *(ptep);						\
   35.49 +	int __ret = pte_young(__pte);					\
   35.50 +	if (__ret)							\
   35.51 +		__pte = pte_mkold(__pte);				\
   35.52 +		if ((vma)->vm_mm != current->mm ||			\
   35.53 +		    HYPERVISOR_update_va_mapping(addr, __pte, 0))	\
   35.54 +			(ptep)->pte_low = __pte.pte_low;		\
   35.55 +	__ret;								\
   35.56 +})
   35.57  
   35.58 -static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long addr, pte_t *ptep, int full)
   35.59 -{
   35.60 -	pte_t pte;
   35.61 -	if (full) {
   35.62 -		pte = *ptep;
   35.63 -		pte_clear(mm, addr, ptep);
   35.64 -	} else {
   35.65 -		pte = ptep_get_and_clear(mm, addr, ptep);
   35.66 -	}
   35.67 -	return pte;
   35.68 -}
   35.69 +#define ptep_get_and_clear_full(mm, addr, ptep, full)			\
   35.70 +	((full) ? ({							\
   35.71 +		pte_t __res = *(ptep);					\
   35.72 +		if (test_bit(PG_pinned, &virt_to_page((mm)->pgd)->flags)) \
   35.73 +			xen_l1_entry_update(ptep, __pte(0));		\
   35.74 +		else							\
   35.75 +			*(ptep) = __pte(0);				\
   35.76 +		__res;							\
   35.77 +	 }) :								\
   35.78 +	 ptep_get_and_clear(mm, addr, ptep))
   35.79  
   35.80  static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
   35.81  {
   35.82 -	if (pte_write(*ptep))
   35.83 -		clear_bit(_PAGE_BIT_RW, &ptep->pte_low);
   35.84 +	pte_t pte = *ptep;
   35.85 +	if (pte_write(pte))
   35.86 +		set_pte_at(mm, addr, ptep, pte_wrprotect(pte));
   35.87  }
   35.88  
   35.89  /*
   35.90 @@ -418,6 +433,20 @@ extern void noexec_setup(const char *str
   35.91  #define pte_unmap_nested(pte) do { } while (0)
   35.92  #endif
   35.93  
   35.94 +#define __HAVE_ARCH_PTEP_ESTABLISH
   35.95 +#define ptep_establish(vma, address, ptep, pteval)			\
   35.96 +	do {								\
   35.97 +		if ( likely((vma)->vm_mm == current->mm) ) {		\
   35.98 +			BUG_ON(HYPERVISOR_update_va_mapping(address,	\
   35.99 +				pteval,					\
  35.100 +				(unsigned long)(vma)->vm_mm->cpu_vm_mask.bits| \
  35.101 +					UVMF_INVLPG|UVMF_MULTI));	\
  35.102 +		} else {						\
  35.103 +			xen_l1_entry_update(ptep, pteval);		\
  35.104 +			flush_tlb_page(vma, address);			\
  35.105 +		}							\
  35.106 +	} while (0)
  35.107 +
  35.108  /*
  35.109   * The i386 doesn't have any external MMU info: the kernel page
  35.110   * tables contain all the necessary information.
  35.111 @@ -430,27 +459,12 @@ extern void noexec_setup(const char *str
  35.112   */
  35.113  #define update_mmu_cache(vma,address,pte) do { } while (0)
  35.114  #define  __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
  35.115 -#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
  35.116 -	do {								  \
  35.117 -		if (__dirty) {						  \
  35.118 -			if ( likely((__vma)->vm_mm == current->mm) ) {	  \
  35.119 -				BUG_ON(HYPERVISOR_update_va_mapping(__address, \
  35.120 -					__entry,			  \
  35.121 -					(unsigned long)(__vma)->vm_mm->cpu_vm_mask.bits| \
  35.122 -					UVMF_INVLPG|UVMF_MULTI));	  \
  35.123 -			} else {					  \
  35.124 -				xen_l1_entry_update(__ptep, __entry);	  \
  35.125 -				flush_tlb_page(__vma, __address);	  \
  35.126 -			}						  \
  35.127 -		}							  \
  35.128 +#define ptep_set_access_flags(vma, address, ptep, entry, dirty)		\
  35.129 +	do {								\
  35.130 +		if (dirty)						\
  35.131 +			ptep_establish(vma, address, ptep, entry);	\
  35.132  	} while (0)
  35.133  
  35.134 -#define __HAVE_ARCH_PTEP_ESTABLISH
  35.135 -#define ptep_establish(__vma, __address, __ptep, __entry)		\
  35.136 -do {				  					\
  35.137 -	ptep_set_access_flags(__vma, __address, __ptep, __entry, 1);	\
  35.138 -} while (0)
  35.139 -
  35.140  #include <xen/features.h>
  35.141  void make_lowmem_page_readonly(void *va, unsigned int feature);
  35.142  void make_lowmem_page_writable(void *va, unsigned int feature);
  35.143 @@ -508,6 +522,7 @@ direct_remap_pfn_range(vma,from,pfn,size
  35.144  #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
  35.145  #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
  35.146  #define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
  35.147 +#define __HAVE_ARCH_PTEP_CLEAR_FLUSH
  35.148  #define __HAVE_ARCH_PTEP_SET_WRPROTECT
  35.149  #define __HAVE_ARCH_PTE_SAME
  35.150  #include <asm-generic/pgtable.h>
    36.1 --- a/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h	Fri Apr 06 10:06:30 2007 -0600
    36.2 +++ b/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h	Fri Apr 06 10:08:30 2007 -0600
    36.3 @@ -55,7 +55,7 @@ extern int running_on_xen;
    36.4  #include <xen/interface/event_channel.h>
    36.5  #include <xen/interface/physdev.h>
    36.6  #include <xen/interface/sched.h>
    36.7 -#include <asm/hypercall.h>
    36.8 +#include <xen/hypercall.h>
    36.9  #include <asm/ptrace.h>
   36.10  #include <asm/page.h>
   36.11  
    37.1 --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h	Fri Apr 06 10:06:30 2007 -0600
    37.2 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h	Fri Apr 06 10:08:30 2007 -0600
    37.3 @@ -241,7 +241,7 @@ HYPERVISOR_memory_op(
    37.4  
    37.5  static inline int
    37.6  HYPERVISOR_multicall(
    37.7 -	void *call_list, int nr_calls)
    37.8 +	multicall_entry_t *call_list, int nr_calls)
    37.9  {
   37.10  	return _hypercall2(int, multicall, call_list, nr_calls);
   37.11  }
   37.12 @@ -259,7 +259,7 @@ HYPERVISOR_event_channel_op(
   37.13  {
   37.14  	int rc = _hypercall2(int, event_channel_op, cmd, arg);
   37.15  
   37.16 -#ifdef CONFIG_XEN_COMPAT_030002
   37.17 +#if CONFIG_XEN_COMPAT <= 0x030002
   37.18  	if (unlikely(rc == -ENOSYS)) {
   37.19  		struct evtchn_op op;
   37.20  		op.cmd = cmd;
   37.21 @@ -299,7 +299,7 @@ HYPERVISOR_physdev_op(
   37.22  {
   37.23  	int rc = _hypercall2(int, physdev_op, cmd, arg);
   37.24  
   37.25 -#ifdef CONFIG_XEN_COMPAT_030002
   37.26 +#if CONFIG_XEN_COMPAT <= 0x030002
   37.27  	if (unlikely(rc == -ENOSYS)) {
   37.28  		struct physdev_op op;
   37.29  		op.cmd = cmd;
   37.30 @@ -359,7 +359,7 @@ HYPERVISOR_suspend(
   37.31  	int rc = _hypercall3(int, sched_op, SCHEDOP_shutdown,
   37.32  			     &sched_shutdown, srec);
   37.33  
   37.34 -#ifdef CONFIG_XEN_COMPAT_030002
   37.35 +#if CONFIG_XEN_COMPAT <= 0x030002
   37.36  	if (rc == -ENOSYS)
   37.37  		rc = _hypercall3(int, sched_op_compat, SCHEDOP_shutdown,
   37.38  				 SHUTDOWN_suspend, srec);
    38.1 --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/maddr.h	Fri Apr 06 10:06:30 2007 -0600
    38.2 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/maddr.h	Fri Apr 06 10:08:30 2007 -0600
    38.3 @@ -140,7 +140,7 @@ static inline paddr_t pte_machine_to_phy
    38.4  #define pfn_to_mfn(pfn) (pfn)
    38.5  #define mfn_to_pfn(mfn) (mfn)
    38.6  #define mfn_to_local_pfn(mfn) (mfn)
    38.7 -#define set_phys_to_machine(pfn, mfn) BUG_ON((pfn) != (mfn))
    38.8 +#define set_phys_to_machine(pfn, mfn) ((void)0)
    38.9  #define phys_to_machine_mapping_valid(pfn) (1)
   38.10  #define phys_to_machine(phys) ((maddr_t)(phys))
   38.11  #define machine_to_phys(mach) ((paddr_t)(mach))
    39.1 --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/page.h	Fri Apr 06 10:06:30 2007 -0600
    39.2 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/page.h	Fri Apr 06 10:08:30 2007 -0600
    39.3 @@ -24,12 +24,6 @@
    39.4  })
    39.5  #define HAVE_ARCH_FREE_PAGE
    39.6  
    39.7 -#ifdef CONFIG_XEN_SCRUB_PAGES
    39.8 -#define scrub_pages(_p,_n) memset((void *)(_p), 0, (_n) << PAGE_SHIFT)
    39.9 -#else
   39.10 -#define scrub_pages(_p,_n) ((void)0)
   39.11 -#endif
   39.12 -
   39.13  /* PAGE_SHIFT determines the page size */
   39.14  #define PAGE_SHIFT	12
   39.15  #ifdef __ASSEMBLY__
   39.16 @@ -110,7 +104,7 @@ typedef struct { unsigned long pgprot; }
   39.17  static inline unsigned long pmd_val(pmd_t x)
   39.18  {
   39.19  	unsigned long ret = x.pmd;
   39.20 -#ifdef CONFIG_XEN_COMPAT_030002
   39.21 +#if CONFIG_XEN_COMPAT <= 0x030002
   39.22  	if (ret) ret = pte_machine_to_phys(ret) | _PAGE_PRESENT;
   39.23  #else
   39.24  	if (ret & _PAGE_PRESENT) ret = pte_machine_to_phys(ret);
   39.25 @@ -172,10 +166,10 @@ static inline pgd_t __pgd(unsigned long 
   39.26  #define __PAGE_OFFSET           0xffff880000000000
   39.27  #endif /* !__ASSEMBLY__ */
   39.28  
   39.29 -#ifdef CONFIG_XEN_COMPAT_030002
   39.30 +#if CONFIG_XEN_COMPAT <= 0x030002
   39.31  #undef LOAD_OFFSET
   39.32  #define LOAD_OFFSET		0
   39.33 -#endif /* CONFIG_XEN_COMPAT_030002 */
   39.34 +#endif
   39.35  
   39.36  /* to align the pointer to the (next) page boundary */
   39.37  #define PAGE_ALIGN(addr)	(((addr)+PAGE_SIZE-1)&PAGE_MASK)
    40.1 --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h	Fri Apr 06 10:06:30 2007 -0600
    40.2 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h	Fri Apr 06 10:08:30 2007 -0600
    40.3 @@ -93,11 +93,6 @@ extern unsigned long empty_zero_page[PAG
    40.4  #define pgd_none(x)	(!pgd_val(x))
    40.5  #define pud_none(x)	(!pud_val(x))
    40.6  
    40.7 -#define set_pte_batched(pteptr, pteval) \
    40.8 -	queue_l1_entry_update(pteptr, (pteval))
    40.9 -
   40.10 -extern inline int pud_present(pud_t pud)	{ return !pud_none(pud); }
   40.11 -
   40.12  static inline void set_pte(pte_t *dst, pte_t val)
   40.13  {
   40.14  	*dst = val;
   40.15 @@ -123,41 +118,6 @@ static inline void pgd_clear (pgd_t * pg
   40.16  #define pud_page(pud) \
   40.17      ((unsigned long) __va(pud_val(pud) & PHYSICAL_PAGE_MASK))
   40.18  
   40.19 -/*
   40.20 - * A note on implementation of this atomic 'get-and-clear' operation.
   40.21 - * This is actually very simple because Xen Linux can only run on a single
   40.22 - * processor. Therefore, we cannot race other processors setting the 'accessed'
   40.23 - * or 'dirty' bits on a page-table entry.
   40.24 - * Even if pages are shared between domains, that is not a problem because
   40.25 - * each domain will have separate page tables, with their own versions of
   40.26 - * accessed & dirty state.
   40.27 - */
   40.28 -#define ptep_get_and_clear(mm,addr,xp)	__pte_ma(xchg(&(xp)->pte, 0))
   40.29 -
   40.30 -#if 0
   40.31 -static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *xp)
   40.32 -{
   40.33 -        pte_t pte = *xp;
   40.34 -        if (pte.pte)
   40.35 -                set_pte(xp, __pte_ma(0));
   40.36 -        return pte;
   40.37 -}
   40.38 -#endif
   40.39 -
   40.40 -struct mm_struct;
   40.41 -
   40.42 -static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long addr, pte_t *ptep, int full)
   40.43 -{
   40.44 -	pte_t pte;
   40.45 -	if (full) {
   40.46 -		pte = *ptep;
   40.47 -		*ptep = __pte(0);
   40.48 -	} else {
   40.49 -		pte = ptep_get_and_clear(mm, addr, ptep);
   40.50 -	}
   40.51 -	return pte;
   40.52 -}
   40.53 -
   40.54  #define pte_same(a, b)		((a).pte == (b).pte)
   40.55  
   40.56  #define pte_pgprot(a)	(__pgprot((a).pte & ~PHYSICAL_PAGE_MASK))
   40.57 @@ -205,7 +165,7 @@ static inline pte_t ptep_get_and_clear_f
   40.58  #define _PAGE_PROTNONE	0x080	/* If not present */
   40.59  #define _PAGE_NX        (1UL<<_PAGE_BIT_NX)
   40.60  
   40.61 -#ifdef CONFIG_XEN_COMPAT_030002
   40.62 +#if CONFIG_XEN_COMPAT <= 0x030002
   40.63  extern unsigned int __kernel_page_user;
   40.64  #else
   40.65  #define __kernel_page_user 0
   40.66 @@ -318,6 +278,46 @@ static inline pte_t pfn_pte(unsigned lon
   40.67  	return __pte(pte);
   40.68  }
   40.69  
   40.70 +static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
   40.71 +{
   40.72 +	pte_t pte = *ptep;
   40.73 +	if (!pte_none(pte)) {
   40.74 +		if (mm != &init_mm)
   40.75 +			pte = __pte_ma(xchg(&ptep->pte, 0));
   40.76 +		else
   40.77 +			HYPERVISOR_update_va_mapping(addr, __pte(0), 0);
   40.78 +	}
   40.79 +	return pte;
   40.80 +}
   40.81 +
   40.82 +static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long addr, pte_t *ptep, int full)
   40.83 +{
   40.84 +	if (full) {
   40.85 +		pte_t pte = *ptep;
   40.86 +		if (mm->context.pinned)
   40.87 +			xen_l1_entry_update(ptep, __pte(0));
   40.88 +		else
   40.89 +			*ptep = __pte(0);
   40.90 +		return pte;
   40.91 +	}
   40.92 +	return ptep_get_and_clear(mm, addr, ptep);
   40.93 +}
   40.94 +
   40.95 +#define ptep_clear_flush(vma, addr, ptep)			\
   40.96 +({								\
   40.97 +	pte_t *__ptep = (ptep);					\
   40.98 +	pte_t __res = *__ptep;					\
   40.99 +	if (!pte_none(__res) &&					\
  40.100 +	    ((vma)->vm_mm != current->mm ||			\
  40.101 +	     HYPERVISOR_update_va_mapping(addr,	__pte(0), 	\
  40.102 +			(unsigned long)(vma)->vm_mm->cpu_vm_mask.bits| \
  40.103 +				UVMF_INVLPG|UVMF_MULTI))) {	\
  40.104 +		__ptep->pte = 0;				\
  40.105 +		flush_tlb_page(vma, addr);			\
  40.106 +	}							\
  40.107 +	__res;							\
  40.108 +})
  40.109 +
  40.110  /*
  40.111   * The following only work if pte_present() is true.
  40.112   * Undefined behaviour if not..
  40.113 @@ -346,31 +346,29 @@ static inline pte_t pte_mkyoung(pte_t pt
  40.114  static inline pte_t pte_mkwrite(pte_t pte)	{ __pte_val(pte) |= _PAGE_RW; return pte; }
  40.115  static inline pte_t pte_mkhuge(pte_t pte)	{ __pte_val(pte) |= _PAGE_PSE; return pte; }
  40.116  
  40.117 -struct vm_area_struct;
  40.118 +#define ptep_test_and_clear_dirty(vma, addr, ptep)			\
  40.119 +({									\
  40.120 +	pte_t __pte = *(ptep);						\
  40.121 +	int __ret = pte_dirty(__pte);					\
  40.122 +	if (__ret)							\
  40.123 +		set_pte_at((vma)->vm_mm, addr, ptep, pte_mkclean(__pte)); \
  40.124 +	__ret;								\
  40.125 +})
  40.126  
  40.127 -static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
  40.128 -{
  40.129 -	pte_t pte = *ptep;
  40.130 -	int ret = pte_dirty(pte);
  40.131 -	if (ret)
  40.132 -		set_pte(ptep, pte_mkclean(pte));
  40.133 -	return ret;
  40.134 -}
  40.135 -
  40.136 -static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
  40.137 -{
  40.138 -	pte_t pte = *ptep;
  40.139 -	int ret = pte_young(pte);
  40.140 -	if (ret)
  40.141 -		set_pte(ptep, pte_mkold(pte));
  40.142 -	return ret;
  40.143 -}
  40.144 +#define ptep_test_and_clear_young(vma, addr, ptep)			\
  40.145 +({									\
  40.146 +	pte_t __pte = *(ptep);						\
  40.147 +	int __ret = pte_young(__pte);					\
  40.148 +	if (__ret)							\
  40.149 +		set_pte_at((vma)->vm_mm, addr, ptep, pte_mkold(__pte)); \
  40.150 +	__ret;								\
  40.151 +})
  40.152  
  40.153  static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
  40.154  {
  40.155  	pte_t pte = *ptep;
  40.156  	if (pte_write(pte))
  40.157 -		set_pte(ptep, pte_wrprotect(pte));
  40.158 +		set_pte_at(mm, addr, ptep, pte_wrprotect(pte));
  40.159  }
  40.160  
  40.161  /*
  40.162 @@ -403,6 +401,7 @@ static inline int pmd_large(pmd_t pte) {
  40.163  /* to find an entry in a page-table-directory. */
  40.164  #define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
  40.165  #define pud_offset(pgd, address) ((pud_t *) pgd_page(*(pgd)) + pud_index(address))
  40.166 +#define pud_present(pud) (pud_val(pud) & _PAGE_PRESENT)
  40.167  
  40.168  /* PMD  - Level 2 access */
  40.169  #define pmd_page_kernel(pmd) ((unsigned long) __va(pmd_val(pmd) & PTE_MASK))
  40.170 @@ -412,9 +411,13 @@ static inline int pmd_large(pmd_t pte) {
  40.171  #define pmd_offset(dir, address) ((pmd_t *) pud_page(*(dir)) + \
  40.172                                    pmd_index(address))
  40.173  #define pmd_none(x)	(!pmd_val(x))
  40.174 +#ifdef CONFIG_XEN_COMPAT_030002
  40.175  /* pmd_present doesn't just test the _PAGE_PRESENT bit since wr.p.t.
  40.176     can temporarily clear it. */
  40.177  #define pmd_present(x)	(pmd_val(x))
  40.178 +#else
  40.179 +#define pmd_present(x)	(pmd_val(x) & _PAGE_PRESENT)
  40.180 +#endif
  40.181  #define pmd_clear(xp)	do { set_pmd(xp, __pmd(0)); } while (0)
  40.182  #define pmd_bad(x) ((pmd_val(x) & ~(PTE_MASK | _PAGE_USER | _PAGE_PRESENT)) \
  40.183  		    != (_KERNPG_TABLE & ~(_PAGE_USER | _PAGE_PRESENT)))
  40.184 @@ -468,25 +471,34 @@ static inline pte_t pte_modify(pte_t pte
  40.185  
  40.186  #define update_mmu_cache(vma,address,pte) do { } while (0)
  40.187  
  40.188 +/*
  40.189 + * Rules for using ptep_establish: the pte MUST be a user pte, and
  40.190 + * must be a present->present transition.
  40.191 + */
  40.192 +#define __HAVE_ARCH_PTEP_ESTABLISH
  40.193 +#define ptep_establish(vma, address, ptep, pteval)			\
  40.194 +	do {								\
  40.195 +		if ( likely((vma)->vm_mm == current->mm) ) {		\
  40.196 +			BUG_ON(HYPERVISOR_update_va_mapping(address,	\
  40.197 +				pteval,					\
  40.198 +				(unsigned long)(vma)->vm_mm->cpu_vm_mask.bits| \
  40.199 +					UVMF_INVLPG|UVMF_MULTI));	\
  40.200 +		} else {						\
  40.201 +			xen_l1_entry_update(ptep, pteval);		\
  40.202 +			flush_tlb_page(vma, address);			\
  40.203 +		}							\
  40.204 +	} while (0)
  40.205 +
  40.206  /* We only update the dirty/accessed state if we set
  40.207   * the dirty bit by hand in the kernel, since the hardware
  40.208   * will do the accessed bit for us, and we don't want to
  40.209   * race with other CPU's that might be updating the dirty
  40.210   * bit at the same time. */
  40.211  #define  __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
  40.212 -#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
  40.213 -	do {								  \
  40.214 -		if (__dirty) {						  \
  40.215 -			if ( likely((__vma)->vm_mm == current->mm) ) {	  \
  40.216 -				BUG_ON(HYPERVISOR_update_va_mapping(__address, \
  40.217 -					__entry,			  \
  40.218 -					(unsigned long)(__vma)->vm_mm->cpu_vm_mask.bits| \
  40.219 -						UVMF_INVLPG|UVMF_MULTI)); \
  40.220 -			} else {					  \
  40.221 -				xen_l1_entry_update(__ptep, __entry);	  \
  40.222 -				flush_tlb_page(__vma, __address);	  \
  40.223 -			}						  \
  40.224 -		}							  \
  40.225 +#define ptep_set_access_flags(vma, address, ptep, entry, dirty)		\
  40.226 +	do {								\
  40.227 +		if (dirty)						\
  40.228 +			ptep_establish(vma, address, ptep, entry);	\
  40.229  	} while (0)
  40.230  
  40.231  /* Encode and de-code a swap entry */
  40.232 @@ -506,6 +518,8 @@ extern int kern_addr_valid(unsigned long
  40.233  
  40.234  #define DOMID_LOCAL (0xFFFFU)
  40.235  
  40.236 +struct vm_area_struct;
  40.237 +
  40.238  int direct_remap_pfn_range(struct vm_area_struct *vma,
  40.239                              unsigned long address,
  40.240                              unsigned long mfn,
  40.241 @@ -551,6 +565,7 @@ int touch_pte_range(struct mm_struct *mm
  40.242  #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
  40.243  #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
  40.244  #define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
  40.245 +#define __HAVE_ARCH_PTEP_CLEAR_FLUSH
  40.246  #define __HAVE_ARCH_PTEP_SET_WRPROTECT
  40.247  #define __HAVE_ARCH_PTE_SAME
  40.248  #include <asm-generic/pgtable.h>
    41.1 --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h	Fri Apr 06 10:06:30 2007 -0600
    41.2 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/setup_arch_post.h	Fri Apr 06 10:08:30 2007 -0600
    41.3 @@ -39,7 +39,7 @@ static void __init machine_specific_arch
    41.4  		ret = HYPERVISOR_callback_op(CALLBACKOP_register, &failsafe);
    41.5  	if (ret == 0)
    41.6  		ret = HYPERVISOR_callback_op(CALLBACKOP_register, &syscall);
    41.7 -#ifdef CONFIG_XEN_COMPAT_030002
    41.8 +#if CONFIG_XEN_COMPAT <= 0x030002
    41.9  	if (ret == -ENOSYS)
   41.10  		ret = HYPERVISOR_set_callbacks(
   41.11  			event.address,
   41.12 @@ -50,7 +50,7 @@ static void __init machine_specific_arch
   41.13  
   41.14  #ifdef CONFIG_X86_LOCAL_APIC
   41.15  	ret = HYPERVISOR_callback_op(CALLBACKOP_register, &nmi_cb);
   41.16 -#ifdef CONFIG_XEN_COMPAT_030002
   41.17 +#if CONFIG_XEN_COMPAT <= 0x030002
   41.18  	if (ret == -ENOSYS) {
   41.19  		static struct xennmi_callback __initdata cb = {
   41.20  			.handler_address = (unsigned long)nmi
    42.1 --- a/linux-2.6-xen-sparse/include/xen/hvm.h	Fri Apr 06 10:06:30 2007 -0600
    42.2 +++ b/linux-2.6-xen-sparse/include/xen/hvm.h	Fri Apr 06 10:08:30 2007 -0600
    42.3 @@ -3,7 +3,6 @@
    42.4  #define XEN_HVM_H__
    42.5  
    42.6  #include <xen/interface/hvm/params.h>
    42.7 -#include <asm/hypercall.h>
    42.8  
    42.9  static inline unsigned long hvm_get_parameter(int idx)
   42.10  {
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/linux-2.6-xen-sparse/include/xen/hypercall.h	Fri Apr 06 10:08:30 2007 -0600
    43.3 @@ -0,0 +1,24 @@
    43.4 +#ifndef __XEN_HYPERCALL_H__
    43.5 +#define __XEN_HYPERCALL_H__
    43.6 +
    43.7 +#include <asm/hypercall.h>
    43.8 +
    43.9 +static inline int
   43.10 +HYPERVISOR_multicall_check(
   43.11 +	multicall_entry_t *call_list, int nr_calls,
   43.12 +	const unsigned long *rc_list)
   43.13 +{
   43.14 +	int rc = HYPERVISOR_multicall(call_list, nr_calls);
   43.15 +
   43.16 +	if (unlikely(rc < 0))
   43.17 +		return rc;
   43.18 +	BUG_ON(rc);
   43.19 +
   43.20 +	for ( ; nr_calls > 0; --nr_calls, ++call_list)
   43.21 +		if (unlikely(call_list->result != (rc_list ? *rc_list++ : 0)))
   43.22 +			return nr_calls;
   43.23 +
   43.24 +	return 0;
   43.25 +}
   43.26 +
   43.27 +#endif /* __XEN_HYPERCALL_H__ */
    44.1 --- a/tools/ioemu/hw/xen_platform.c	Fri Apr 06 10:06:30 2007 -0600
    44.2 +++ b/tools/ioemu/hw/xen_platform.c	Fri Apr 06 10:08:30 2007 -0600
    44.3 @@ -29,16 +29,10 @@
    44.4  
    44.5  extern FILE *logfile;
    44.6  
    44.7 -static void platform_ioport_write(void *opaque, uint32_t addr, uint32_t val)
    44.8 -{
    44.9 -    if (val == 0)
   44.10 -        qemu_invalidate_map_cache();
   44.11 -}
   44.12 -
   44.13  static void platform_ioport_map(PCIDevice *pci_dev, int region_num,
   44.14                                  uint32_t addr, uint32_t size, int type)
   44.15  {
   44.16 -    register_ioport_write(addr, 1, 1, platform_ioport_write, NULL);
   44.17 +    /* nothing yet */
   44.18  }
   44.19  
   44.20  static uint32_t platform_mmio_read(void *opaque, target_phys_addr_t addr)
    45.1 --- a/tools/ioemu/target-i386-dm/exec-dm.c	Fri Apr 06 10:06:30 2007 -0600
    45.2 +++ b/tools/ioemu/target-i386-dm/exec-dm.c	Fri Apr 06 10:08:30 2007 -0600
    45.3 @@ -431,14 +431,8 @@ static inline int paddr_is_ram(target_ph
    45.4  {
    45.5      /* Is this guest physical address RAM-backed? */
    45.6  #if defined(CONFIG_DM) && (defined(__i386__) || defined(__x86_64__))
    45.7 -    if (ram_size <= HVM_BELOW_4G_RAM_END)
    45.8 -        /* RAM is contiguous */
    45.9 -        return (addr < ram_size);
   45.10 -    else
   45.11 -        /* There is RAM below and above the MMIO hole */
   45.12 -        return ((addr < HVM_BELOW_4G_MMIO_START) ||
   45.13 -                ((addr >= HVM_BELOW_4G_MMIO_START + HVM_BELOW_4G_MMIO_LENGTH)
   45.14 -                 && (addr < ram_size + HVM_BELOW_4G_MMIO_LENGTH)));
   45.15 +    return ((addr < HVM_BELOW_4G_MMIO_START) ||
   45.16 +            (addr >= HVM_BELOW_4G_MMIO_START + HVM_BELOW_4G_MMIO_LENGTH));
   45.17  #else
   45.18      return (addr < ram_size);
   45.19  #endif
    46.1 --- a/tools/ioemu/target-i386-dm/helper2.c	Fri Apr 06 10:06:30 2007 -0600
    46.2 +++ b/tools/ioemu/target-i386-dm/helper2.c	Fri Apr 06 10:08:30 2007 -0600
    46.3 @@ -136,9 +136,6 @@ void cpu_reset(CPUX86State *env)
    46.4      int xcHandle;
    46.5      int sts;
    46.6  
    46.7 -    /* pause domain first, to avoid repeated reboot request*/
    46.8 -    xc_domain_pause(xc_handle, domid);
    46.9 -
   46.10      xcHandle = xc_interface_open();
   46.11      if (xcHandle < 0)
   46.12          fprintf(logfile, "Cannot acquire xenctrl handle\n");
   46.13 @@ -509,8 +506,11 @@ void __handle_ioreq(CPUState *env, ioreq
   46.14          cpu_ioreq_xchg(env, req);
   46.15          break;
   46.16      case IOREQ_TYPE_TIMEOFFSET:
   46.17 -	cpu_ioreq_timeoffset(env, req);
   46.18 -	break;
   46.19 +        cpu_ioreq_timeoffset(env, req);
   46.20 +        break;
   46.21 +    case IOREQ_TYPE_INVALIDATE:
   46.22 +        qemu_invalidate_map_cache();
   46.23 +        break;
   46.24      default:
   46.25          hw_error("Invalid ioreq type 0x%x\n", req->type);
   46.26      }
   46.27 @@ -597,6 +597,7 @@ int main_loop(void)
   46.28      extern int suspend_requested;
   46.29      CPUState *env = cpu_single_env;
   46.30      int evtchn_fd = xc_evtchn_fd(xce_handle);
   46.31 +    char qemu_file[20];
   46.32  
   46.33      buffered_io_timer = qemu_new_timer(rt_clock, handle_buffered_io,
   46.34  				       cpu_single_env);
   46.35 @@ -604,52 +605,23 @@ int main_loop(void)
   46.36  
   46.37      qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, env);
   46.38  
   46.39 -    while (1) {
   46.40 -        if (vm_running) {
   46.41 -            if (shutdown_requested)
   46.42 -                break;
   46.43 -            if (reset_requested) {
   46.44 -                qemu_system_reset();
   46.45 -                reset_requested = 0;
   46.46 -            }
   46.47 -            if (suspend_requested) {
   46.48 -                fprintf(logfile, "device model received suspend signal!\n");
   46.49 -                break;
   46.50 -            }
   46.51 -        }
   46.52 -
   46.53 +    while (!(vm_running && suspend_requested))
   46.54          /* Wait up to 10 msec. */
   46.55          main_loop_wait(10);
   46.56 -    }
   46.57 -    if (!suspend_requested)
   46.58 -        destroy_hvm_domain();
   46.59 -    else {
   46.60 -        char qemu_file[20];
   46.61 -        ioreq_t *req;
   46.62 -        int rc;
   46.63 +
   46.64 +    fprintf(logfile, "device model received suspend signal!\n");
   46.65  
   46.66 -        sprintf(qemu_file, "/tmp/xen.qemu-dm.%d", domid);
   46.67 -        xc_domain_pause(xc_handle, domid);
   46.68 +    /* Pull all outstanding ioreqs through the system */
   46.69 +    handle_buffered_io(env);
   46.70 +    main_loop_wait(1); /* For the select() on events */
   46.71  
   46.72 -        /* Pull all outstanding ioreqs through the system */
   46.73 -        handle_buffered_io(env);
   46.74 -        main_loop_wait(1); /* For the select() on events */
   46.75 -        
   46.76 -        /* Stop the IDE thread */
   46.77 -        ide_stop_dma_thread();
   46.78 +    /* Stop the IDE thread */
   46.79 +    ide_stop_dma_thread();
   46.80  
   46.81 -        /* Make sure that all outstanding IO responses are handled too */ 
   46.82 -        if ( xc_hvm_drain_io(xc_handle, domid) != 0 )
   46.83 -        {
   46.84 -            fprintf(stderr, "error clearing ioreq rings (%s)\n", 
   46.85 -                    strerror(errno));
   46.86 -            return -1;
   46.87 -        }
   46.88 -
   46.89 -        /* Save the device state */
   46.90 -        if (qemu_savevm(qemu_file) < 0)
   46.91 -            fprintf(stderr, "qemu save fail.\n");
   46.92 -    }
   46.93 +    /* Save the device state */
   46.94 +    sprintf(qemu_file, "/tmp/xen.qemu-dm.%d", domid);
   46.95 +    if (qemu_savevm(qemu_file) < 0)
   46.96 +        fprintf(stderr, "qemu save fail.\n");
   46.97  
   46.98      return 0;
   46.99  }
    47.1 --- a/tools/ioemu/vl.c	Fri Apr 06 10:06:30 2007 -0600
    47.2 +++ b/tools/ioemu/vl.c	Fri Apr 06 10:08:30 2007 -0600
    47.3 @@ -88,6 +88,7 @@
    47.4  
    47.5  #include "exec-all.h"
    47.6  
    47.7 +#include <xen/hvm/params.h>
    47.8  #define DEFAULT_NETWORK_SCRIPT "/etc/xen/qemu-ifup"
    47.9  #define DEFAULT_BRIDGE "xenbr0"
   47.10  
   47.11 @@ -5886,7 +5887,8 @@ int set_mm_mapping(int xc_handle, uint32
   47.12  
   47.13  void suspend(int sig)
   47.14  {
   47.15 -   fprintf(logfile, "suspend sig handler called with requested=%d!\n", suspend_requested);
   47.16 +    fprintf(logfile, "suspend sig handler called with requested=%d!\n",
   47.17 +            suspend_requested);
   47.18      if (sig != SIGUSR1)
   47.19          fprintf(logfile, "suspend signal dismatch, get sig=%d!\n", sig);
   47.20      suspend_requested = 1;
   47.21 @@ -5900,33 +5902,29 @@ static unsigned long nr_buckets;
   47.22  static unsigned long last_address_index = ~0UL;
   47.23  static uint8_t      *last_address_vaddr;
   47.24  
   47.25 -static int qemu_map_cache_init(unsigned long nr_pages)
   47.26 -{
   47.27 -    unsigned long max_pages = MAX_MCACHE_SIZE >> PAGE_SHIFT;
   47.28 -    int i;
   47.29 -
   47.30 -    if (nr_pages < max_pages)
   47.31 -        max_pages = nr_pages;
   47.32 -
   47.33 -    nr_buckets   = max_pages + (1UL << (MCACHE_BUCKET_SHIFT - PAGE_SHIFT)) - 1;
   47.34 -    nr_buckets >>= (MCACHE_BUCKET_SHIFT - PAGE_SHIFT);
   47.35 +static int qemu_map_cache_init(void)
   47.36 +{
   47.37 +    unsigned long size;
   47.38 +
   47.39 +    nr_buckets = (((MAX_MCACHE_SIZE >> PAGE_SHIFT) +
   47.40 +                   (1UL << (MCACHE_BUCKET_SHIFT - PAGE_SHIFT)) - 1) >>
   47.41 +                  (MCACHE_BUCKET_SHIFT - PAGE_SHIFT));
   47.42      fprintf(logfile, "qemu_map_cache_init nr_buckets = %lx\n", nr_buckets);
   47.43  
   47.44 -    mapcache_entry = malloc(nr_buckets * sizeof(struct map_cache));
   47.45 -    if (mapcache_entry == NULL) {
   47.46 +    /*
   47.47 +     * Use mmap() directly: lets us allocate a big hash table with no up-front
   47.48 +     * cost in storage space. The OS will allocate memory only for the buckets
   47.49 +     * that we actually use. All others will contain all zeroes.
   47.50 +     */
   47.51 +    size = nr_buckets * sizeof(struct map_cache);
   47.52 +    size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
   47.53 +    mapcache_entry = mmap(NULL, size, PROT_READ|PROT_WRITE,
   47.54 +                          MAP_SHARED|MAP_ANONYMOUS, 0, 0);
   47.55 +    if (mapcache_entry == MAP_FAILED) {
   47.56          errno = ENOMEM;
   47.57          return -1;
   47.58      }
   47.59  
   47.60 -    memset(mapcache_entry, 0, nr_buckets * sizeof(struct map_cache));
   47.61 -
   47.62 -    /*
   47.63 -     * To avoid ENOMEM from xc_map_foreign_batch() at runtime, we
   47.64 -     * pre-fill all the map caches in advance.
   47.65 -     */
   47.66 -    for (i = 0; i < nr_buckets; i++)
   47.67 -       (void)qemu_map_cache(((target_phys_addr_t)i) << MCACHE_BUCKET_SHIFT);
   47.68 -
   47.69      return 0;
   47.70  }
   47.71  
   47.72 @@ -6038,11 +6036,14 @@ int main(int argc, char **argv)
   47.73      QEMUMachine *machine;
   47.74      char usb_devices[MAX_USB_CMDLINE][128];
   47.75      int usb_devices_index;
   47.76 -    unsigned long nr_pages, tmp_nr_pages, shared_page_nr;
   47.77 -    xen_pfn_t *page_array;
   47.78 +    unsigned long ioreq_pfn;
   47.79      extern void *shared_page;
   47.80      extern void *buffered_io_page;
   47.81 +#ifdef __ia64__
   47.82 +    unsigned long nr_pages;
   47.83 +    xen_pfn_t *page_array;
   47.84      extern void *buffered_pio_page;
   47.85 +#endif
   47.86  
   47.87      char qemu_dm_logfilename[64];
   47.88  
   47.89 @@ -6592,47 +6593,36 @@ int main(int argc, char **argv)
   47.90  
   47.91      xc_handle = xc_interface_open();
   47.92  
   47.93 -    nr_pages = ram_size/PAGE_SIZE;
   47.94 -    tmp_nr_pages = nr_pages;
   47.95 -
   47.96  #if defined(__i386__) || defined(__x86_64__)
   47.97 -    if (ram_size > HVM_BELOW_4G_RAM_END) {
   47.98 -        tmp_nr_pages += HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT;
   47.99 -        shared_page_nr = (HVM_BELOW_4G_RAM_END >> PAGE_SHIFT) - 1;
  47.100 -    } else
  47.101 -        shared_page_nr = nr_pages - 1;
  47.102 -#endif
  47.103 -
  47.104 -#if defined(__i386__) || defined(__x86_64__)
  47.105 -
  47.106 -    if ( qemu_map_cache_init(tmp_nr_pages) )
  47.107 -    {
  47.108 +
  47.109 +    if (qemu_map_cache_init()) {
  47.110          fprintf(logfile, "qemu_map_cache_init returned: error %d\n", errno);
  47.111          exit(-1);
  47.112      }
  47.113  
  47.114 +    xc_get_hvm_param(xc_handle, domid, HVM_PARAM_IOREQ_PFN, &ioreq_pfn);
  47.115 +    fprintf(logfile, "shared page at pfn %lx\n", ioreq_pfn);
  47.116      shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
  47.117 -                                       PROT_READ|PROT_WRITE, shared_page_nr);
  47.118 +                                       PROT_READ|PROT_WRITE, ioreq_pfn);
  47.119      if (shared_page == NULL) {
  47.120          fprintf(logfile, "map shared IO page returned error %d\n", errno);
  47.121          exit(-1);
  47.122      }
  47.123  
  47.124 -    fprintf(logfile, "shared page at pfn:%lx\n", shared_page_nr);
  47.125 -
  47.126 +    xc_get_hvm_param(xc_handle, domid, HVM_PARAM_BUFIOREQ_PFN, &ioreq_pfn);
  47.127 +    fprintf(logfile, "buffered io page at pfn %lx\n", ioreq_pfn);
  47.128      buffered_io_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
  47.129 -                                            PROT_READ|PROT_WRITE,
  47.130 -                                            shared_page_nr - 2);
  47.131 +                                            PROT_READ|PROT_WRITE, ioreq_pfn);
  47.132      if (buffered_io_page == NULL) {
  47.133          fprintf(logfile, "map buffered IO page returned error %d\n", errno);
  47.134          exit(-1);
  47.135      }
  47.136  
  47.137 -    fprintf(logfile, "buffered io page at pfn:%lx\n", shared_page_nr - 2);
  47.138 -
  47.139  #elif defined(__ia64__)
  47.140  
  47.141 -    page_array = (xen_pfn_t *)malloc(tmp_nr_pages * sizeof(xen_pfn_t));
  47.142 +    nr_pages = ram_size/PAGE_SIZE;
  47.143 +
  47.144 +    page_array = (xen_pfn_t *)malloc(nr_pages * sizeof(xen_pfn_t));
  47.145      if (page_array == NULL) {
  47.146          fprintf(logfile, "malloc returned error %d\n", errno);
  47.147          exit(-1);
  47.148 @@ -6650,7 +6640,7 @@ int main(int argc, char **argv)
  47.149                                         PROT_READ|PROT_WRITE,
  47.150                                         BUFFER_PIO_PAGE_START >> PAGE_SHIFT);
  47.151  
  47.152 -    for (i = 0; i < tmp_nr_pages; i++)
  47.153 +    for (i = 0; i < nr_pages; i++)
  47.154          page_array[i] = i;
  47.155  	
  47.156      /* VTI will not use memory between 3G~4G, so we just pass a legal pfn
    48.1 --- a/tools/ioemu/xenstore.c	Fri Apr 06 10:06:30 2007 -0600
    48.2 +++ b/tools/ioemu/xenstore.c	Fri Apr 06 10:08:30 2007 -0600
    48.3 @@ -248,12 +248,8 @@ void xenstore_process_logdirty_event(voi
    48.4          key = (key_t) strtoull(key_terminated, NULL, 16);
    48.5  
    48.6          /* Figure out how bit the log-dirty bitmaps are */
    48.7 -        logdirty_bitmap_size = ((phys_ram_size + 0x20 
    48.8 -                                 - (vga_ram_size + bios_size)) 
    48.9 -                                >> (TARGET_PAGE_BITS)); /* nr of bits in map*/
   48.10 -        if (logdirty_bitmap_size > HVM_BELOW_4G_MMIO_START >> TARGET_PAGE_BITS)
   48.11 -            logdirty_bitmap_size += 
   48.12 -                HVM_BELOW_4G_MMIO_LENGTH >> TARGET_PAGE_BITS; /* still bits */
   48.13 +        logdirty_bitmap_size = xc_memory_op(xc_handle, 
   48.14 +                                            XENMEM_maximum_gpfn, &domid) + 1;
   48.15          logdirty_bitmap_size = ((logdirty_bitmap_size + HOST_LONG_BITS - 1)
   48.16                                  / HOST_LONG_BITS); /* longs */
   48.17          logdirty_bitmap_size *= sizeof (unsigned long); /* bytes */
   48.18 @@ -272,7 +268,7 @@ void xenstore_process_logdirty_event(voi
   48.19  
   48.20          /* Double-check that the bitmaps are the size we expect */
   48.21          if (logdirty_bitmap_size != *(uint32_t *)seg) {
   48.22 -            fprintf(logfile, "Log-dirty: got %lu, calc %lu\n", 
   48.23 +            fprintf(logfile, "Log-dirty: got %u, calc %lu\n", 
   48.24                      *(uint32_t *)seg, logdirty_bitmap_size);
   48.25              return;
   48.26          }
   48.27 @@ -304,7 +300,7 @@ void xenstore_process_logdirty_event(voi
   48.28          fprintf(logfile, "Log-dirty: bad next-active entry: %s\n", act);
   48.29          exit(1);
   48.30      }
   48.31 -    logdirty_bitmap = seg + i * logdirty_bitmap_size;
   48.32 +    logdirty_bitmap = (unsigned long *)(seg + i * logdirty_bitmap_size);
   48.33  
   48.34      /* Ack that we've switched */
   48.35      xs_write(xsh, XBT_NULL, active_path, act, len);
   48.36 @@ -612,7 +608,7 @@ int xenstore_vm_write(int domid, char *k
   48.37  
   48.38      path = xs_get_domain_path(xsh, domid);
   48.39      if (path == NULL) {
   48.40 -	fprintf(logfile, "xs_get_domain_path(%d): error\n");
   48.41 +	fprintf(logfile, "xs_get_domain_path: error\n");
   48.42  	goto out;
   48.43      }
   48.44  
    49.1 --- a/tools/libxc/Makefile	Fri Apr 06 10:06:30 2007 -0600
    49.2 +++ b/tools/libxc/Makefile	Fri Apr 06 10:08:30 2007 -0600
    49.3 @@ -26,8 +26,8 @@ CTRL_SRCS-$(CONFIG_X86_Linux) += xc_ptra
    49.4  
    49.5  GUEST_SRCS-y :=
    49.6  GUEST_SRCS-y += xg_private.c
    49.7 -GUEST_SRCS-$(CONFIG_MIGRATE) += xc_linux_restore.c xc_linux_save.c
    49.8 -GUEST_SRCS-$(CONFIG_HVM) += xc_hvm_build.c xc_hvm_restore.c xc_hvm_save.c
    49.9 +GUEST_SRCS-$(CONFIG_MIGRATE) += xc_domain_restore.c xc_linux_save.c
   49.10 +GUEST_SRCS-$(CONFIG_HVM) += xc_hvm_build.c xc_hvm_save.c
   49.11  
   49.12  # symlink libelf from xen/common/libelf/
   49.13  LIBELF_SRCS := libelf-tools.c libelf-loader.c
    50.1 --- a/tools/libxc/ia64/xc_ia64_linux_restore.c	Fri Apr 06 10:06:30 2007 -0600
    50.2 +++ b/tools/libxc/ia64/xc_ia64_linux_restore.c	Fri Apr 06 10:08:30 2007 -0600
    50.3 @@ -20,9 +20,6 @@ static unsigned long p2m_size;
    50.4  /* number of 'in use' pfns in the guest (i.e. #P2M entries with a valid mfn) */
    50.5  static unsigned long nr_pfns;
    50.6  
    50.7 -/* largest possible value of nr_pfns (i.e. domain's maximum memory size) */
    50.8 -static unsigned long max_nr_pfns;
    50.9 -
   50.10  static ssize_t
   50.11  read_exact(int fd, void *buf, size_t count)
   50.12  {
   50.13 @@ -62,10 +59,10 @@ read_page(int xc_handle, int io_fd, uint
   50.14  }
   50.15  
   50.16  int
   50.17 -xc_linux_restore(int xc_handle, int io_fd, uint32_t dom,
   50.18 -                 unsigned long p2msize, unsigned long maxnrpfns,
   50.19 +xc_domain_restore(int xc_handle, int io_fd, uint32_t dom,
   50.20                   unsigned int store_evtchn, unsigned long *store_mfn,
   50.21 -                 unsigned int console_evtchn, unsigned long *console_mfn)
   50.22 +                 unsigned int console_evtchn, unsigned long *console_mfn,
   50.23 +                 unsigned int hvm, unsigned int pae)
   50.24  {
   50.25      DECLARE_DOMCTL;
   50.26      int rc = 1, i;
   50.27 @@ -85,12 +82,19 @@ xc_linux_restore(int xc_handle, int io_f
   50.28      /* A temporary mapping of the guest's start_info page. */
   50.29      start_info_t *start_info;
   50.30  
   50.31 -    p2m_size = p2msize;
   50.32 -    max_nr_pfns = maxnrpfns;
   50.33 +    if (hvm) {
   50.34 +        ERROR("HVM Restore is unsupported");
   50.35 +        goto out;
   50.36 +    }
   50.37  
   50.38      /* For info only */
   50.39      nr_pfns = 0;
   50.40  
   50.41 +    if ( !read_exact(io_fd, &p2m_size, sizeof(unsigned long)) )
   50.42 +    {
   50.43 +        ERROR("read: p2m_size");
   50.44 +        goto out;
   50.45 +    }
   50.46      DPRINTF("xc_linux_restore start: p2m_size = %lx\n", p2m_size);
   50.47  
   50.48      if (!read_exact(io_fd, &ver, sizeof(unsigned long))) {
   50.49 @@ -108,11 +112,6 @@ xc_linux_restore(int xc_handle, int io_f
   50.50          return 1;
   50.51      }
   50.52  
   50.53 -    if (xc_domain_setmaxmem(xc_handle, dom, PFN_TO_KB(max_nr_pfns)) != 0) {
   50.54 -        errno = ENOMEM;
   50.55 -        goto out;
   50.56 -    }
   50.57 -
   50.58      /* Get pages.  */
   50.59      page_array = malloc(p2m_size * sizeof(unsigned long));
   50.60      if (page_array == NULL) {
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/tools/libxc/xc_domain_restore.c	Fri Apr 06 10:08:30 2007 -0600
    51.3 @@ -0,0 +1,1086 @@
    51.4 +/******************************************************************************
    51.5 + * xc_domain_restore.c
    51.6 + *
    51.7 + * Restore the state of a guest session.
    51.8 + *
    51.9 + * Copyright (c) 2003, K A Fraser.
   51.10 + * Copyright (c) 2006, Intel Corporation
   51.11 + * Copyright (c) 2007, XenSource Inc.
   51.12 + *
   51.13 + * This program is free software; you can redistribute it and/or modify it
   51.14 + * under the terms and conditions of the GNU General Public License,
   51.15 + * version 2, as published by the Free Software Foundation.
   51.16 + *
   51.17 + * This program is distributed in the hope it will be useful, but WITHOUT
   51.18 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   51.19 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   51.20 + * more details.
   51.21 + *
   51.22 + * You should have received a copy of the GNU General Public License along with
   51.23 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
   51.24 + * Place - Suite 330, Boston, MA 02111-1307 USA.
   51.25 + *
   51.26 + */
   51.27 +
   51.28 +#include <stdlib.h>
   51.29 +#include <unistd.h>
   51.30 +
   51.31 +#include "xg_private.h"
   51.32 +#include "xg_save_restore.h"
   51.33 +#include "xc_dom.h"
   51.34 +
   51.35 +#include <xen/hvm/ioreq.h>
   51.36 +#include <xen/hvm/params.h>
   51.37 +
   51.38 +/* max mfn of the current host machine */
   51.39 +static unsigned long max_mfn;
   51.40 +
   51.41 +/* virtual starting address of the hypervisor */
   51.42 +static unsigned long hvirt_start;
   51.43 +
   51.44 +/* #levels of page tables used by the current guest */
   51.45 +static unsigned int pt_levels;
   51.46 +
   51.47 +/* number of pfns this guest has (i.e. number of entries in the P2M) */
   51.48 +static unsigned long p2m_size;
   51.49 +
   51.50 +/* number of 'in use' pfns in the guest (i.e. #P2M entries with a valid mfn) */
   51.51 +static unsigned long nr_pfns;
   51.52 +
   51.53 +/* Live mapping of the table mapping each PFN to its current MFN. */
   51.54 +static xen_pfn_t *live_p2m = NULL;
   51.55 +
   51.56 +/* A table mapping each PFN to its new MFN. */
   51.57 +static xen_pfn_t *p2m = NULL;
   51.58 +
   51.59 +/* A table of P2M mappings in the current region */
   51.60 +static xen_pfn_t *p2m_batch = NULL;
   51.61 +
   51.62 +static ssize_t
   51.63 +read_exact(int fd, void *buf, size_t count)
   51.64 +{
   51.65 +    int r = 0, s;
   51.66 +    unsigned char *b = buf;
   51.67 +
   51.68 +    while (r < count) {
   51.69 +        s = read(fd, &b[r], count - r);
   51.70 +        if ((s == -1) && (errno == EINTR))
   51.71 +            continue;
   51.72 +        if (s <= 0) {
   51.73 +            break;
   51.74 +        }
   51.75 +        r += s;
   51.76 +    }
   51.77 +
   51.78 +    return (r == count) ? 1 : 0;
   51.79 +}
   51.80 +
   51.81 +/*
   51.82 +** In the state file (or during transfer), all page-table pages are
   51.83 +** converted into a 'canonical' form where references to actual mfns
   51.84 +** are replaced with references to the corresponding pfns.
   51.85 +** This function inverts that operation, replacing the pfn values with
   51.86 +** the (now known) appropriate mfn values.
   51.87 +*/
   51.88 +static int uncanonicalize_pagetable(int xc_handle, uint32_t dom, 
   51.89 +                                    unsigned long type, void *page)
   51.90 +{
   51.91 +    int i, pte_last;
   51.92 +    unsigned long pfn;
   51.93 +    uint64_t pte;
   51.94 +    int nr_mfns = 0; 
   51.95 +
   51.96 +    pte_last = PAGE_SIZE / ((pt_levels == 2)? 4 : 8);
   51.97 +
   51.98 +    /* First pass: work out how many (if any) MFNs we need to alloc */
   51.99 +    for(i = 0; i < pte_last; i++) {
  51.100 +        
  51.101 +        if(pt_levels == 2)
  51.102 +            pte = ((uint32_t *)page)[i];
  51.103 +        else
  51.104 +            pte = ((uint64_t *)page)[i];
  51.105 +        
  51.106 +        /* XXX SMH: below needs fixing for PROT_NONE etc */
  51.107 +        if(!(pte & _PAGE_PRESENT))
  51.108 +            continue; 
  51.109 +        
  51.110 +        pfn = (pte >> PAGE_SHIFT) & MFN_MASK_X86;
  51.111 +        
  51.112 +        if(pfn >= p2m_size) {
  51.113 +            /* This "page table page" is probably not one; bail. */
  51.114 +            ERROR("Frame number in type %lu page table is out of range: "
  51.115 +                  "i=%d pfn=0x%lx p2m_size=%lu",
  51.116 +                  type >> 28, i, pfn, p2m_size);
  51.117 +            return 0;
  51.118 +        }
  51.119 +        
  51.120 +        if(p2m[pfn] == INVALID_P2M_ENTRY) {
  51.121 +            /* Have a 'valid' PFN without a matching MFN - need to alloc */
  51.122 +            p2m_batch[nr_mfns++] = pfn; 
  51.123 +        }
  51.124 +    }
  51.125 +    
  51.126 +    
  51.127 +    /* Allocate the requistite number of mfns */
  51.128 +    if (nr_mfns && xc_domain_memory_populate_physmap(
  51.129 +            xc_handle, dom, nr_mfns, 0, 0, p2m_batch) != 0) { 
  51.130 +        ERROR("Failed to allocate memory for batch.!\n"); 
  51.131 +        errno = ENOMEM;
  51.132 +        return 0; 
  51.133 +    }
  51.134 +    
  51.135 +    /* Second pass: uncanonicalize each present PTE */
  51.136 +    nr_mfns = 0;
  51.137 +    for(i = 0; i < pte_last; i++) {
  51.138 +
  51.139 +        if(pt_levels == 2)
  51.140 +            pte = ((uint32_t *)page)[i];
  51.141 +        else
  51.142 +            pte = ((uint64_t *)page)[i];
  51.143 +        
  51.144 +        /* XXX SMH: below needs fixing for PROT_NONE etc */
  51.145 +        if(!(pte & _PAGE_PRESENT))
  51.146 +            continue;
  51.147 +        
  51.148 +        pfn = (pte >> PAGE_SHIFT) & MFN_MASK_X86;
  51.149 +        
  51.150 +        if(p2m[pfn] == INVALID_P2M_ENTRY)
  51.151 +            p2m[pfn] = p2m_batch[nr_mfns++];
  51.152 +
  51.153 +        pte &= ~MADDR_MASK_X86;
  51.154 +        pte |= (uint64_t)p2m[pfn] << PAGE_SHIFT;
  51.155 +
  51.156 +        if(pt_levels == 2)
  51.157 +            ((uint32_t *)page)[i] = (uint32_t)pte;
  51.158 +        else
  51.159 +            ((uint64_t *)page)[i] = (uint64_t)pte;
  51.160 +    }
  51.161 +
  51.162 +    return 1;
  51.163 +}
  51.164 +
  51.165 +
  51.166 +/* Load the p2m frame list, plus potential extended info chunk */
  51.167 +static xen_pfn_t * load_p2m_frame_list(int io_fd, int *pae_extended_cr3)
  51.168 +{
  51.169 +    xen_pfn_t *p2m_frame_list;
  51.170 +    vcpu_guest_context_t ctxt;
  51.171 +
  51.172 +    if (!(p2m_frame_list = malloc(P2M_FL_SIZE))) {
  51.173 +        ERROR("Couldn't allocate p2m_frame_list array");
  51.174 +        return NULL;
  51.175 +    }
  51.176 +    
  51.177 +    /* Read first entry of P2M list, or extended-info signature (~0UL). */
  51.178 +    if (!read_exact(io_fd, p2m_frame_list, sizeof(long))) {
  51.179 +            ERROR("read extended-info signature failed");
  51.180 +            return NULL;
  51.181 +        }
  51.182 +    
  51.183 +    if (p2m_frame_list[0] == ~0UL) {
  51.184 +        uint32_t tot_bytes;
  51.185 +        
  51.186 +        /* Next 4 bytes: total size of following extended info. */
  51.187 +        if (!read_exact(io_fd, &tot_bytes, sizeof(tot_bytes))) {
  51.188 +            ERROR("read extended-info size failed");
  51.189 +            return NULL;
  51.190 +        }
  51.191 +        
  51.192 +        while (tot_bytes) {
  51.193 +            uint32_t chunk_bytes;
  51.194 +            char     chunk_sig[4];
  51.195 +            
  51.196 +            /* 4-character chunk signature + 4-byte remaining chunk size. */
  51.197 +            if (!read_exact(io_fd, chunk_sig, sizeof(chunk_sig)) ||
  51.198 +                !read_exact(io_fd, &chunk_bytes, sizeof(chunk_bytes))) {
  51.199 +                ERROR("read extended-info chunk signature failed");
  51.200 +                return NULL;
  51.201 +            }
  51.202 +            tot_bytes -= 8;
  51.203 +            
  51.204 +            /* VCPU context structure? */
  51.205 +            if (!strncmp(chunk_sig, "vcpu", 4)) {
  51.206 +                if (!read_exact(io_fd, &ctxt, sizeof(ctxt))) {
  51.207 +                    ERROR("read extended-info vcpu context failed");
  51.208 +                    return NULL;
  51.209 +                }
  51.210 +                tot_bytes   -= sizeof(struct vcpu_guest_context);
  51.211 +                chunk_bytes -= sizeof(struct vcpu_guest_context);
  51.212 +                
  51.213 +                if (ctxt.vm_assist & (1UL << VMASST_TYPE_pae_extended_cr3))
  51.214 +                    *pae_extended_cr3 = 1;
  51.215 +            }
  51.216 +            
  51.217 +            /* Any remaining bytes of this chunk: read and discard. */
  51.218 +            while (chunk_bytes) {
  51.219 +                unsigned long sz = chunk_bytes;
  51.220 +                if ( sz > P2M_FL_SIZE )
  51.221 +                    sz = P2M_FL_SIZE;
  51.222 +                if (!read_exact(io_fd, p2m_frame_list, sz)) {
  51.223 +                    ERROR("read-and-discard extended-info chunk bytes failed");
  51.224 +                    return NULL;
  51.225 +                }
  51.226 +                chunk_bytes -= sz;
  51.227 +                tot_bytes   -= sz;
  51.228 +            }
  51.229 +        }
  51.230 +        
  51.231 +        /* Now read the real first entry of P2M list. */
  51.232 +        if (!read_exact(io_fd, p2m_frame_list, sizeof(long))) {
  51.233 +            ERROR("read first entry of p2m_frame_list failed");
  51.234 +            return NULL;
  51.235 +        }
  51.236 +    }
  51.237 +    
  51.238 +    /* First entry is already read into the p2m array. */
  51.239 +    if (!read_exact(io_fd, &p2m_frame_list[1], P2M_FL_SIZE - sizeof(long))) {
  51.240 +            ERROR("read p2m_frame_list failed");
  51.241 +            return NULL;
  51.242 +    }
  51.243 +    
  51.244 +    return p2m_frame_list;
  51.245 +}
  51.246 +
  51.247 +
  51.248 +
  51.249 +int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom,
  51.250 +                      unsigned int store_evtchn, unsigned long *store_mfn,
  51.251 +                      unsigned int console_evtchn, unsigned long *console_mfn,
  51.252 +                      unsigned int hvm, unsigned int pae)
  51.253 +{
  51.254 +    DECLARE_DOMCTL;
  51.255 +    int rc = 1, i, j, n, m, pae_extended_cr3 = 0;
  51.256 +    unsigned long mfn, pfn;
  51.257 +    unsigned int prev_pc, this_pc;
  51.258 +    int verify = 0;
  51.259 +    int nraces = 0;
  51.260 +
  51.261 +    /* The new domain's shared-info frame number. */
  51.262 +    unsigned long shared_info_frame;
  51.263 +    unsigned char shared_info_page[PAGE_SIZE]; /* saved contents from file */
  51.264 +    shared_info_t *shared_info = (shared_info_t *)shared_info_page;
  51.265 +
  51.266 +    /* A copy of the CPU context of the guest. */
  51.267 +    vcpu_guest_context_t ctxt;
  51.268 +
  51.269 +    /* A table containing the type of each PFN (/not/ MFN!). */
  51.270 +    unsigned long *pfn_type = NULL;
  51.271 +
  51.272 +    /* A table of MFNs to map in the current region */
  51.273 +    xen_pfn_t *region_mfn = NULL;
  51.274 +
  51.275 +    /* Types of the pfns in the current region */
  51.276 +    unsigned long region_pfn_type[MAX_BATCH_SIZE];
  51.277 +
  51.278 +    /* A temporary mapping, and a copy, of one frame of guest memory. */
  51.279 +    unsigned long *page = NULL;
  51.280 +
  51.281 +    /* A copy of the pfn-to-mfn table frame list. */
  51.282 +    xen_pfn_t *p2m_frame_list = NULL;
  51.283 +    
  51.284 +    /* A temporary mapping of the guest's start_info page. */
  51.285 +    start_info_t *start_info;
  51.286 +
  51.287 +    /* Our mapping of the current region (batch) */
  51.288 +    char *region_base;
  51.289 +
  51.290 +    xc_mmu_t *mmu = NULL;
  51.291 +
  51.292 +    /* used by debug verify code */
  51.293 +    unsigned long buf[PAGE_SIZE/sizeof(unsigned long)];
  51.294 +
  51.295 +    struct mmuext_op pin[MAX_PIN_BATCH];
  51.296 +    unsigned int nr_pins;
  51.297 +
  51.298 +    uint64_t vcpumap = 1ULL;
  51.299 +    unsigned int max_vcpu_id = 0;
  51.300 +    int new_ctxt_format = 0;
  51.301 +
  51.302 +    /* Magic frames in HVM guests: ioreqs and xenstore comms. */
  51.303 +    uint64_t magic_pfns[3]; /* ioreq_pfn, bufioreq_pfn, store_pfn */
  51.304 +
  51.305 +    /* Buffer for holding HVM context */
  51.306 +    uint8_t *hvm_buf = NULL;
  51.307 +
  51.308 +    /* For info only */
  51.309 +    nr_pfns = 0;
  51.310 +
  51.311 +    if ( !read_exact(io_fd, &p2m_size, sizeof(unsigned long)) )
  51.312 +    {
  51.313 +        ERROR("read: p2m_size");
  51.314 +        goto out;
  51.315 +    }
  51.316 +    DPRINTF("xc_domain_restore start: p2m_size = %lx\n", p2m_size);
  51.317 +
  51.318 +    if ( !hvm )
  51.319 +    {
  51.320 +        /*
  51.321 +         * XXX For now, 32bit dom0's can only save/restore 32bit domUs
  51.322 +         * on 64bit hypervisors.
  51.323 +         */
  51.324 +        memset(&domctl, 0, sizeof(domctl));
  51.325 +        domctl.domain = dom;
  51.326 +        domctl.cmd    = XEN_DOMCTL_set_address_size;
  51.327 +        domctl.u.address_size.size = sizeof(unsigned long) * 8;
  51.328 +        rc = do_domctl(xc_handle, &domctl);
  51.329 +        if ( rc != 0 ) {
  51.330 +            ERROR("Unable to set guest address size.");
  51.331 +            goto out;
  51.332 +        }
  51.333 +        rc = 1;
  51.334 +    }
  51.335 +
  51.336 +    if(!get_platform_info(xc_handle, dom,
  51.337 +                          &max_mfn, &hvirt_start, &pt_levels)) {
  51.338 +        ERROR("Unable to get platform info.");
  51.339 +        return 1;
  51.340 +    }
  51.341 +
  51.342 +    if (lock_pages(&ctxt, sizeof(ctxt))) {
  51.343 +        /* needed for build domctl, but might as well do early */
  51.344 +        ERROR("Unable to lock ctxt");
  51.345 +        return 1;
  51.346 +    }
  51.347 +
  51.348 +    /* Load the p2m frame list, plus potential extended info chunk */
  51.349 +    if ( !hvm ) 
  51.350 +    {
  51.351 +        p2m_frame_list = load_p2m_frame_list(io_fd, &pae_extended_cr3);
  51.352 +        if ( !p2m_frame_list )
  51.353 +            goto out;
  51.354 +    }
  51.355 +
  51.356 +    /* We want zeroed memory so use calloc rather than malloc. */
  51.357 +    p2m        = calloc(p2m_size, sizeof(xen_pfn_t));
  51.358 +    pfn_type   = calloc(p2m_size, sizeof(unsigned long));
  51.359 +    region_mfn = calloc(MAX_BATCH_SIZE, sizeof(xen_pfn_t));
  51.360 +    p2m_batch  = calloc(MAX_BATCH_SIZE, sizeof(xen_pfn_t));
  51.361 +
  51.362 +    if ((p2m == NULL) || (pfn_type == NULL) ||
  51.363 +        (region_mfn == NULL) || (p2m_batch == NULL)) {
  51.364 +        ERROR("memory alloc failed");
  51.365 +        errno = ENOMEM;
  51.366 +        goto out;
  51.367 +    }
  51.368 +
  51.369 +    if (lock_pages(region_mfn, sizeof(xen_pfn_t) * MAX_BATCH_SIZE)) {
  51.370 +        ERROR("Could not lock region_mfn");
  51.371 +        goto out;
  51.372 +    }
  51.373 +
  51.374 +    if (lock_pages(p2m_batch, sizeof(xen_pfn_t) * MAX_BATCH_SIZE)) {
  51.375 +        ERROR("Could not lock p2m_batch");
  51.376 +        goto out;
  51.377 +    }
  51.378 +
  51.379 +    /* Get the domain's shared-info frame. */
  51.380 +    domctl.cmd = XEN_DOMCTL_getdomaininfo;
  51.381 +    domctl.domain = (domid_t)dom;
  51.382 +    if (xc_domctl(xc_handle, &domctl) < 0) {
  51.383 +        ERROR("Could not get information on new domain");
  51.384 +        goto out;
  51.385 +    }
  51.386 +    shared_info_frame = domctl.u.getdomaininfo.shared_info_frame;
  51.387 +
  51.388 +    /* Mark all PFNs as invalid; we allocate on demand */
  51.389 +    for ( pfn = 0; pfn < p2m_size; pfn++ )
  51.390 +        p2m[pfn] = INVALID_P2M_ENTRY;
  51.391 +
  51.392 +    if(!(mmu = xc_init_mmu_updates(xc_handle, dom))) {
  51.393 +        ERROR("Could not initialise for MMU updates");
  51.394 +        goto out;
  51.395 +    }
  51.396 +
  51.397 +    DPRINTF("Reloading memory pages:   0%%\n");
  51.398 +
  51.399 +    /*
  51.400 +     * Now simply read each saved frame into its new machine frame.
  51.401 +     * We uncanonicalise page tables as we go.
  51.402 +     */
  51.403 +    prev_pc = 0;
  51.404 +
  51.405 +    n = m = 0;
  51.406 +    while (1) {
  51.407 +
  51.408 +        int j, nr_mfns = 0; 
  51.409 +
  51.410 +        this_pc = (n * 100) / p2m_size;
  51.411 +        if ( (this_pc - prev_pc) >= 5 )
  51.412 +        {
  51.413 +            PPRINTF("\b\b\b\b%3d%%", this_pc);
  51.414 +            prev_pc = this_pc;
  51.415 +        }
  51.416 +
  51.417 +        if (!read_exact(io_fd, &j, sizeof(int))) {
  51.418 +            ERROR("Error when reading batch size");
  51.419 +            goto out;
  51.420 +        }
  51.421 +
  51.422 +        PPRINTF("batch %d\n",j);
  51.423 +
  51.424 +        if (j == -1) {
  51.425 +            verify = 1;
  51.426 +            DPRINTF("Entering page verify mode\n");
  51.427 +            continue;
  51.428 +        }
  51.429 +
  51.430 +        if (j == -2) {
  51.431 +            new_ctxt_format = 1;
  51.432 +            if (!read_exact(io_fd, &max_vcpu_id, sizeof(int)) ||
  51.433 +                (max_vcpu_id >= 64) ||
  51.434 +                !read_exact(io_fd, &vcpumap, sizeof(uint64_t))) {
  51.435 +                ERROR("Error when reading max_vcpu_id");
  51.436 +                goto out;
  51.437 +            }
  51.438 +            continue;
  51.439 +        }
  51.440 +
  51.441 +        if (j == 0)
  51.442 +            break;  /* our work here is done */
  51.443 +
  51.444 +        if (j > MAX_BATCH_SIZE) {
  51.445 +            ERROR("Max batch size exceeded. Giving up.");
  51.446 +            goto out;
  51.447 +        }
  51.448 +
  51.449 +        if (!read_exact(io_fd, region_pfn_type, j*sizeof(unsigned long))) {
  51.450 +            ERROR("Error when reading region pfn types");
  51.451 +            goto out;
  51.452 +        }
  51.453 +
  51.454 +        /* First pass for this batch: work out how much memory to alloc */
  51.455 +        nr_mfns = 0; 
  51.456 +        for ( i = 0; i < j; i++ )
  51.457 +        {
  51.458 +            unsigned long pfn, pagetype;
  51.459 +            pfn      = region_pfn_type[i] & ~XEN_DOMCTL_PFINFO_LTAB_MASK;
  51.460 +            pagetype = region_pfn_type[i] &  XEN_DOMCTL_PFINFO_LTAB_MASK;
  51.461 +
  51.462 +            if ( (pagetype != XEN_DOMCTL_PFINFO_XTAB) && 
  51.463 +                 (p2m[pfn] == INVALID_P2M_ENTRY) )
  51.464 +            {
  51.465 +                /* Have a live PFN which hasn't had an MFN allocated */
  51.466 +                p2m_batch[nr_mfns++] = pfn; 
  51.467 +            }
  51.468 +        } 
  51.469 +
  51.470 +
  51.471 +        /* Now allocate a bunch of mfns for this batch */
  51.472 +        if (nr_mfns && xc_domain_memory_populate_physmap(
  51.473 +                xc_handle, dom, nr_mfns, 0, 0, p2m_batch) != 0) { 
  51.474 +            ERROR("Failed to allocate memory for batch.!\n"); 
  51.475 +            errno = ENOMEM;
  51.476 +            goto out;
  51.477 +        }
  51.478 +
  51.479 +        /* Second pass for this batch: update p2m[] and region_mfn[] */
  51.480 +        nr_mfns = 0; 
  51.481 +        for ( i = 0; i < j; i++ )
  51.482 +        {
  51.483 +            unsigned long pfn, pagetype;
  51.484 +            pfn      = region_pfn_type[i] & ~XEN_DOMCTL_PFINFO_LTAB_MASK;
  51.485 +            pagetype = region_pfn_type[i] &  XEN_DOMCTL_PFINFO_LTAB_MASK;
  51.486 +
  51.487 +            if ( pagetype == XEN_DOMCTL_PFINFO_XTAB)
  51.488 +                region_mfn[i] = ~0UL; /* map will fail but we don't care */
  51.489 +            else 
  51.490 +            {
  51.491 +                if (p2m[pfn] == INVALID_P2M_ENTRY) {
  51.492 +                    /* We just allocated a new mfn above; update p2m */
  51.493 +                    p2m[pfn] = p2m_batch[nr_mfns++]; 
  51.494 +                    nr_pfns++; 
  51.495 +                }
  51.496 +
  51.497 +                /* setup region_mfn[] for batch map.
  51.498 +                 * For HVM guests, this interface takes PFNs, not MFNs */
  51.499 +                region_mfn[i] = hvm ? pfn : p2m[pfn]; 
  51.500 +            }
  51.501 +        } 
  51.502 +
  51.503 +        /* Map relevant mfns */
  51.504 +        region_base = xc_map_foreign_batch(
  51.505 +            xc_handle, dom, PROT_WRITE, region_mfn, j);
  51.506 +
  51.507 +        if ( region_base == NULL )
  51.508 +        {
  51.509 +            ERROR("map batch failed");
  51.510 +            goto out;
  51.511 +        }
  51.512 +
  51.513 +        for ( i = 0; i < j; i++ )
  51.514 +        {
  51.515 +            void *page;
  51.516 +            unsigned long pagetype;
  51.517 +
  51.518 +            pfn      = region_pfn_type[i] & ~XEN_DOMCTL_PFINFO_LTAB_MASK;
  51.519 +            pagetype = region_pfn_type[i] &  XEN_DOMCTL_PFINFO_LTAB_MASK;
  51.520 +
  51.521 +            if ( pagetype == XEN_DOMCTL_PFINFO_XTAB )
  51.522 +                /* a bogus/unmapped page: skip it */
  51.523 +                continue;
  51.524 +
  51.525 +            if ( pfn > p2m_size )
  51.526 +            {
  51.527 +                ERROR("pfn out of range");
  51.528 +                goto out;
  51.529 +            }
  51.530 +
  51.531 +            pfn_type[pfn] = pagetype;
  51.532 +
  51.533 +            mfn = p2m[pfn];
  51.534 +
  51.535 +            /* In verify mode, we use a copy; otherwise we work in place */
  51.536 +            page = verify ? (void *)buf : (region_base + i*PAGE_SIZE);
  51.537 +
  51.538 +            if (!read_exact(io_fd, page, PAGE_SIZE)) {
  51.539 +                ERROR("Error when reading page (type was %lx)", pagetype);
  51.540 +                goto out;
  51.541 +            }
  51.542 +
  51.543 +            pagetype &= XEN_DOMCTL_PFINFO_LTABTYPE_MASK;
  51.544 +
  51.545 +            if ( (pagetype >= XEN_DOMCTL_PFINFO_L1TAB) && 
  51.546 +                 (pagetype <= XEN_DOMCTL_PFINFO_L4TAB) )
  51.547 +            {
  51.548 +                /*
  51.549 +                ** A page table page - need to 'uncanonicalize' it, i.e.
  51.550 +                ** replace all the references to pfns with the corresponding
  51.551 +                ** mfns for the new domain.
  51.552 +                **
  51.553 +                ** On PAE we need to ensure that PGDs are in MFNs < 4G, and
  51.554 +                ** so we may need to update the p2m after the main loop.
  51.555 +                ** Hence we defer canonicalization of L1s until then.
  51.556 +                */
  51.557 +                if ((pt_levels != 3) ||
  51.558 +                    pae_extended_cr3 ||
  51.559 +                    (pagetype != XEN_DOMCTL_PFINFO_L1TAB)) {
  51.560 +
  51.561 +                    if (!uncanonicalize_pagetable(xc_handle, dom, 
  51.562 +                                                  pagetype, page)) {
  51.563 +                        /*
  51.564 +                        ** Failing to uncanonicalize a page table can be ok
  51.565 +                        ** under live migration since the pages type may have
  51.566 +                        ** changed by now (and we'll get an update later).
  51.567 +                        */
  51.568 +                        DPRINTF("PT L%ld race on pfn=%08lx mfn=%08lx\n",
  51.569 +                                pagetype >> 28, pfn, mfn);
  51.570 +                        nraces++;
  51.571 +                        continue;
  51.572 +                    } 
  51.573 +                }
  51.574 +            }
  51.575 +            else if ( pagetype != XEN_DOMCTL_PFINFO_NOTAB )
  51.576 +            {
  51.577 +                ERROR("Bogus page type %lx page table is out of range: "
  51.578 +                    "i=%d p2m_size=%lu", pagetype, i, p2m_size);
  51.579 +                goto out;
  51.580 +
  51.581 +            }
  51.582 +
  51.583 +
  51.584 +            if (verify) {
  51.585 +
  51.586 +                int res = memcmp(buf, (region_base + i*PAGE_SIZE), PAGE_SIZE);
  51.587 +
  51.588 +                if (res) {
  51.589 +
  51.590 +                    int v;
  51.591 +
  51.592 +                    DPRINTF("************** pfn=%lx type=%lx gotcs=%08lx "
  51.593 +                            "actualcs=%08lx\n", pfn, pfn_type[pfn],
  51.594 +                            csum_page(region_base + i*PAGE_SIZE),
  51.595 +                            csum_page(buf));
  51.596 +
  51.597 +                    for (v = 0; v < 4; v++) {
  51.598 +
  51.599 +                        unsigned long *p = (unsigned long *)
  51.600 +                            (region_base + i*PAGE_SIZE);
  51.601 +                        if (buf[v] != p[v])
  51.602 +                            DPRINTF("    %d: %08lx %08lx\n", v, buf[v], p[v]);
  51.603 +                    }
  51.604 +                }
  51.605 +            }
  51.606 +
  51.607 +            if (!hvm 
  51.608 +                && xc_add_mmu_update(xc_handle, mmu,
  51.609 +                                     (((unsigned long long)mfn) << PAGE_SHIFT)
  51.610 +                                     | MMU_MACHPHYS_UPDATE, pfn)) {
  51.611 +                ERROR("failed machpys update mfn=%lx pfn=%lx", mfn, pfn);
  51.612 +                goto out;
  51.613 +            }
  51.614 +        } /* end of 'batch' for loop */
  51.615 +
  51.616 +        munmap(region_base, j*PAGE_SIZE);
  51.617 +        n+= j; /* crude stats */
  51.618 +
  51.619 +        /* 
  51.620 +         * Discard cache for portion of file read so far up to last
  51.621 +         *  page boundary every 16MB or so.
  51.622 +         */
  51.623 +        m += j;
  51.624 +        if ( m > MAX_PAGECACHE_USAGE )
  51.625 +        {
  51.626 +            discard_file_cache(io_fd, 0 /* no flush */);
  51.627 +            m = 0;
  51.628 +        }
  51.629 +    }
  51.630 +
  51.631 +    /*
  51.632 +     * Ensure we flush all machphys updates before potential PAE-specific
  51.633 +     * reallocations below.
  51.634 +     */
  51.635 +    if (!hvm && xc_finish_mmu_updates(xc_handle, mmu)) {
  51.636 +        ERROR("Error doing finish_mmu_updates()");
  51.637 +        goto out;
  51.638 +    }
  51.639 +
  51.640 +    DPRINTF("Received all pages (%d races)\n", nraces);
  51.641 +
  51.642 +    if ( hvm ) 
  51.643 +    {
  51.644 +        uint32_t rec_len;
  51.645 +
  51.646 +        /* Set HVM-specific parameters */
  51.647 +        if ( !read_exact(io_fd, magic_pfns, sizeof(magic_pfns)) )
  51.648 +        {
  51.649 +            ERROR("error reading magic page addresses");
  51.650 +            goto out;
  51.651 +        }
  51.652 +        
  51.653 +        /* These comms pages need to be zeroed at the start of day */
  51.654 +        if ( xc_clear_domain_page(xc_handle, dom, magic_pfns[0]) ||
  51.655 +             xc_clear_domain_page(xc_handle, dom, magic_pfns[1]) ||
  51.656 +             xc_clear_domain_page(xc_handle, dom, magic_pfns[2]) )
  51.657 +        {
  51.658 +            ERROR("error zeroing magic pages");
  51.659 +            goto out;
  51.660 +        }
  51.661 +        
  51.662 +        xc_set_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN, magic_pfns[0]);
  51.663 +        xc_set_hvm_param(xc_handle, dom, HVM_PARAM_BUFIOREQ_PFN, magic_pfns[1]);
  51.664 +        xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, magic_pfns[2]);
  51.665 +        xc_set_hvm_param(xc_handle, dom, HVM_PARAM_PAE_ENABLED, pae);
  51.666 +        xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_EVTCHN, store_evtchn);
  51.667 +        *store_mfn = magic_pfns[2];
  51.668 +
  51.669 +        /* Read vcpu contexts */
  51.670 +        for (i = 0; i <= max_vcpu_id; i++) 
  51.671 +        {
  51.672 +            if (!(vcpumap & (1ULL << i)))
  51.673 +                continue;
  51.674 +
  51.675 +            if ( !read_exact(io_fd, &(ctxt), sizeof(ctxt)) )
  51.676 +            {
  51.677 +                ERROR("error read vcpu context.\n");
  51.678 +                goto out;
  51.679 +            }
  51.680 +            
  51.681 +            if ( (rc = xc_vcpu_setcontext(xc_handle, dom, i, &ctxt)) )
  51.682 +            {
  51.683 +                ERROR("Could not set vcpu context, rc=%d", rc);
  51.684 +                goto out;
  51.685 +            }
  51.686 +            rc = 1;
  51.687 +        }
  51.688 +
  51.689 +        /* Read HVM context */
  51.690 +        if ( !read_exact(io_fd, &rec_len, sizeof(uint32_t)) )
  51.691 +        {
  51.692 +            ERROR("error read hvm context size!\n");
  51.693 +            goto out;
  51.694 +        }
  51.695 +        
  51.696 +        hvm_buf = malloc(rec_len);
  51.697 +        if ( hvm_buf == NULL )
  51.698 +        {
  51.699 +            ERROR("memory alloc for hvm context buffer failed");
  51.700 +            errno = ENOMEM;
  51.701 +            goto out;
  51.702 +        }
  51.703 +        
  51.704 +        if ( !read_exact(io_fd, hvm_buf, rec_len) )
  51.705 +        {
  51.706 +            ERROR("error loading the HVM context");
  51.707 +            goto out;
  51.708 +        }
  51.709 +        
  51.710 +        rc = xc_domain_hvm_setcontext(xc_handle, dom, hvm_buf, rec_len);
  51.711 +        if ( rc ) 
  51.712 +            ERROR("error setting the HVM context");
  51.713 +       
  51.714 +        goto out;
  51.715 +    }
  51.716 +
  51.717 +    /* Non-HVM guests only from here on */
  51.718 +
  51.719 +    if ((pt_levels == 3) && !pae_extended_cr3) {
  51.720 +
  51.721 +        /*
  51.722 +        ** XXX SMH on PAE we need to ensure PGDs are in MFNs < 4G. This
  51.723 +        ** is a little awkward and involves (a) finding all such PGDs and
  51.724 +        ** replacing them with 'lowmem' versions; (b) upating the p2m[]
  51.725 +        ** with the new info; and (c) canonicalizing all the L1s using the
  51.726 +        ** (potentially updated) p2m[].
  51.727 +        **
  51.728 +        ** This is relatively slow (and currently involves two passes through
  51.729 +        ** the pfn_type[] array), but at least seems to be correct. May wish
  51.730 +        ** to consider more complex approaches to optimize this later.
  51.731 +        */
  51.732 +
  51.733 +        int j, k;
  51.734 +        
  51.735 +        /* First pass: find all L3TABs current in > 4G mfns and get new mfns */
  51.736 +        for ( i = 0; i < p2m_size; i++ )
  51.737 +        {
  51.738 +            if ( ((pfn_type[i] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK) ==
  51.739 +                  XEN_DOMCTL_PFINFO_L3TAB) &&
  51.740 +                 (p2m[i] > 0xfffffUL) )
  51.741 +            {
  51.742 +                unsigned long new_mfn;
  51.743 +                uint64_t l3ptes[4];
  51.744 +                uint64_t *l3tab;
  51.745 +
  51.746 +                l3tab = (uint64_t *)
  51.747 +                    xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
  51.748 +                                         PROT_READ, p2m[i]);
  51.749 +
  51.750 +                for(j = 0; j < 4; j++)
  51.751 +                    l3ptes[j] = l3tab[j];
  51.752 +
  51.753 +                munmap(l3tab, PAGE_SIZE);
  51.754 +
  51.755 +                if (!(new_mfn=xc_make_page_below_4G(xc_handle, dom, p2m[i]))) {
  51.756 +                    ERROR("Couldn't get a page below 4GB :-(");
  51.757 +                    goto out;
  51.758 +                }
  51.759 +
  51.760 +                p2m[i] = new_mfn;
  51.761 +                if (xc_add_mmu_update(xc_handle, mmu,
  51.762 +                                      (((unsigned long long)new_mfn)
  51.763 +                                       << PAGE_SHIFT) |
  51.764 +                                      MMU_MACHPHYS_UPDATE, i)) {
  51.765 +                    ERROR("Couldn't m2p on PAE root pgdir");
  51.766 +                    goto out;
  51.767 +                }
  51.768 +
  51.769 +                l3tab = (uint64_t *)
  51.770 +                    xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
  51.771 +                                         PROT_READ | PROT_WRITE, p2m[i]);
  51.772 +
  51.773 +                for(j = 0; j < 4; j++)
  51.774 +                    l3tab[j] = l3ptes[j];
  51.775 +
  51.776 +                munmap(l3tab, PAGE_SIZE);
  51.777 +
  51.778 +            }
  51.779 +        }
  51.780 +
  51.781 +        /* Second pass: find all L1TABs and uncanonicalize them */
  51.782 +        j = 0;
  51.783 +
  51.784 +        for ( i = 0; i < p2m_size; i++ )
  51.785 +        {
  51.786 +            if ( ((pfn_type[i] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK) ==
  51.787 +                  XEN_DOMCTL_PFINFO_L1TAB) )
  51.788 +            {
  51.789 +                region_mfn[j] = p2m[i];
  51.790 +                j++;
  51.791 +            }
  51.792 +
  51.793 +            if(i == (p2m_size-1) || j == MAX_BATCH_SIZE) {
  51.794 +
  51.795 +                if (!(region_base = xc_map_foreign_batch(
  51.796 +                          xc_handle, dom, PROT_READ | PROT_WRITE,
  51.797 +                          region_mfn, j))) {
  51.798 +                    ERROR("map batch failed");
  51.799 +                    goto out;
  51.800 +                }
  51.801 +
  51.802 +                for(k = 0; k < j; k++) {
  51.803 +                    if(!uncanonicalize_pagetable(xc_handle, dom, 
  51.804 +                                                 XEN_DOMCTL_PFINFO_L1TAB,
  51.805 +                                                 region_base + k*PAGE_SIZE)) {
  51.806 +                        ERROR("failed uncanonicalize pt!");
  51.807 +                        goto out;
  51.808 +                    }
  51.809 +                }
  51.810 +
  51.811 +                munmap(region_base, j*PAGE_SIZE);
  51.812 +                j = 0;
  51.813 +            }
  51.814 +        }
  51.815 +
  51.816 +        if (xc_finish_mmu_updates(xc_handle, mmu)) {
  51.817 +            ERROR("Error doing finish_mmu_updates()");
  51.818 +            goto out;
  51.819 +        }
  51.820 +    }
  51.821 +
  51.822 +    /*
  51.823 +     * Pin page tables. Do this after writing to them as otherwise Xen
  51.824 +     * will barf when doing the type-checking.
  51.825 +     */
  51.826 +    nr_pins = 0;
  51.827 +    for ( i = 0; i < p2m_size; i++ )
  51.828 +    {
  51.829 +        if ( (pfn_type[i] & XEN_DOMCTL_PFINFO_LPINTAB) == 0 )
  51.830 +            continue;
  51.831 +
  51.832 +        switch ( pfn_type[i] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK )
  51.833 +        {
  51.834 +        case XEN_DOMCTL_PFINFO_L1TAB:
  51.835 +            pin[nr_pins].cmd = MMUEXT_PIN_L1_TABLE;
  51.836 +            break;
  51.837 +
  51.838 +        case XEN_DOMCTL_PFINFO_L2TAB:
  51.839 +            pin[nr_pins].cmd = MMUEXT_PIN_L2_TABLE;
  51.840 +            break;
  51.841 +
  51.842 +        case XEN_DOMCTL_PFINFO_L3TAB:
  51.843 +            pin[nr_pins].cmd = MMUEXT_PIN_L3_TABLE;
  51.844 +            break;
  51.845 +
  51.846 +        case XEN_DOMCTL_PFINFO_L4TAB:
  51.847 +            pin[nr_pins].cmd = MMUEXT_PIN_L4_TABLE;
  51.848 +            break;
  51.849 +
  51.850 +        default:
  51.851 +            continue;
  51.852 +        }
  51.853 +
  51.854 +        pin[nr_pins].arg1.mfn = p2m[i];
  51.855 +        nr_pins++;
  51.856 +
  51.857 +        /* Batch full? Then flush. */
  51.858 +        if (nr_pins == MAX_PIN_BATCH) {
  51.859 +            if (xc_mmuext_op(xc_handle, pin, nr_pins, dom) < 0) {
  51.860 +                ERROR("Failed to pin batch of %d page tables", nr_pins);
  51.861 +                goto out;
  51.862 +            }
  51.863 +            nr_pins = 0;
  51.864 +        }
  51.865 +    }
  51.866 +
  51.867 +    /* Flush final partial batch. */
  51.868 +    if ((nr_pins != 0) && (xc_mmuext_op(xc_handle, pin, nr_pins, dom) < 0)) {
  51.869 +        ERROR("Failed to pin batch of %d page tables", nr_pins);
  51.870 +        goto out;
  51.871 +    }
  51.872 +
  51.873 +    DPRINTF("\b\b\b\b100%%\n");
  51.874 +    DPRINTF("Memory reloaded (%ld pages)\n", nr_pfns);
  51.875 +
  51.876 +    /* Get the list of PFNs that are not in the psuedo-phys map */
  51.877 +    {
  51.878 +        unsigned int count;
  51.879 +        unsigned long *pfntab;
  51.880 +        int nr_frees, rc;
  51.881 +
  51.882 +        if (!read_exact(io_fd, &count, sizeof(count))) {
  51.883 +            ERROR("Error when reading pfn count");
  51.884 +            goto out;
  51.885 +        }
  51.886 +
  51.887 +        if(!(pfntab = malloc(sizeof(unsigned long) * count))) {
  51.888 +            ERROR("Out of memory");
  51.889 +            goto out;
  51.890 +        }
  51.891 +
  51.892 +        if (!read_exact(io_fd, pfntab, sizeof(unsigned long)*count)) {
  51.893 +            ERROR("Error when reading pfntab");
  51.894 +            goto out;
  51.895 +        }
  51.896 +
  51.897 +        nr_frees = 0; 
  51.898 +        for (i = 0; i < count; i++) {
  51.899 +
  51.900 +            unsigned long pfn = pfntab[i];
  51.901 +
  51.902 +            if(p2m[pfn] != INVALID_P2M_ENTRY) {
  51.903 +                /* pfn is not in physmap now, but was at some point during 
  51.904 +                   the save/migration process - need to free it */
  51.905 +                pfntab[nr_frees++] = p2m[pfn];
  51.906 +                p2m[pfn]  = INVALID_P2M_ENTRY; // not in pseudo-physical map
  51.907 +            }
  51.908 +        }
  51.909 +
  51.910 +        if (nr_frees > 0) {
  51.911 +
  51.912 +            struct xen_memory_reservation reservation = {
  51.913 +                .nr_extents   = nr_frees,
  51.914 +                .extent_order = 0,
  51.915 +                .domid        = dom
  51.916 +            };
  51.917 +            set_xen_guest_handle(reservation.extent_start, pfntab);
  51.918 +
  51.919 +            if ((rc = xc_memory_op(xc_handle, XENMEM_decrease_reservation,
  51.920 +                                   &reservation)) != nr_frees) {
  51.921 +                ERROR("Could not decrease reservation : %d", rc);
  51.922 +                goto out;
  51.923 +            } else
  51.924 +                DPRINTF("Decreased reservation by %d pages\n", count);
  51.925 +        }
  51.926 +    }
  51.927 +
  51.928 +    for (i = 0; i <= max_vcpu_id; i++) {
  51.929 +        if (!(vcpumap & (1ULL << i)))
  51.930 +            continue;
  51.931 +
  51.932 +        if (!read_exact(io_fd, &ctxt, sizeof(ctxt))) {
  51.933 +            ERROR("Error when reading ctxt %d", i);
  51.934 +            goto out;
  51.935 +        }
  51.936 +
  51.937 +        if ( !new_ctxt_format )
  51.938 +            ctxt.flags |= VGCF_online;
  51.939 +
  51.940 +        if (i == 0) {
  51.941 +            /*
  51.942 +             * Uncanonicalise the suspend-record frame number and poke
  51.943 +             * resume record.
  51.944 +             */
  51.945 +            pfn = ctxt.user_regs.edx;
  51.946 +            if ((pfn >= p2m_size) ||
  51.947 +                (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB)) {
  51.948 +                ERROR("Suspend record frame number is bad");
  51.949 +                goto out;
  51.950 +            }
  51.951 +            ctxt.user_regs.edx = mfn = p2m[pfn];
  51.952 +            start_info = xc_map_foreign_range(
  51.953 +                xc_handle, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, mfn);
  51.954 +            start_info->nr_pages = p2m_size;
  51.955 +            start_info->shared_info = shared_info_frame << PAGE_SHIFT;
  51.956 +            start_info->flags = 0;
  51.957 +            *store_mfn = start_info->store_mfn = p2m[start_info->store_mfn];
  51.958 +            start_info->store_evtchn = store_evtchn;
  51.959 +            start_info->console.domU.mfn = p2m[start_info->console.domU.mfn];
  51.960 +            start_info->console.domU.evtchn = console_evtchn;
  51.961 +            *console_mfn = start_info->console.domU.mfn;
  51.962 +            munmap(start_info, PAGE_SIZE);
  51.963 +        }
  51.964 +
  51.965 +        /* Uncanonicalise each GDT frame number. */
  51.966 +        if (ctxt.gdt_ents > 8192) {
  51.967 +            ERROR("GDT entry count out of range");
  51.968 +            goto out;
  51.969 +        }
  51.970 +
  51.971 +        for (j = 0; (512*j) < ctxt.gdt_ents; j++) {
  51.972 +            pfn = ctxt.gdt_frames[j];
  51.973 +            if ((pfn >= p2m_size) ||
  51.974 +                (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB)) {
  51.975 +                ERROR("GDT frame number is bad");
  51.976 +                goto out;
  51.977 +            }
  51.978 +            ctxt.gdt_frames[j] = p2m[pfn];
  51.979 +        }
  51.980 +
  51.981 +        /* Uncanonicalise the page table base pointer. */
  51.982 +        pfn = xen_cr3_to_pfn(ctxt.ctrlreg[3]);
  51.983 +
  51.984 +        if (pfn >= p2m_size) {
  51.985 +            ERROR("PT base is bad: pfn=%lu p2m_size=%lu type=%08lx",
  51.986 +                  pfn, p2m_size, pfn_type[pfn]);
  51.987 +            goto out;
  51.988 +        }
  51.989 +
  51.990 +        if ( (pfn_type[pfn] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK) !=
  51.991 +             ((unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT) ) {
  51.992 +            ERROR("PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx",
  51.993 +                  pfn, p2m_size, pfn_type[pfn],
  51.994 +                  (unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT);
  51.995 +            goto out;
  51.996 +        }
  51.997 +
  51.998 +        ctxt.ctrlreg[3] = xen_pfn_to_cr3(p2m[pfn]);
  51.999 +
 51.1000 +        /* Guest pagetable (x86/64) stored in otherwise-unused CR1. */
 51.1001 +        if ( (pt_levels == 4) && ctxt.ctrlreg[1] )
 51.1002 +        {
 51.1003 +            pfn = xen_cr3_to_pfn(ctxt.ctrlreg[1]);
 51.1004 +
 51.1005 +            if (pfn >= p2m_size) {
 51.1006 +                ERROR("User PT base is bad: pfn=%lu p2m_size=%lu type=%08lx",
 51.1007 +                      pfn, p2m_size, pfn_type[pfn]);
 51.1008 +                goto out;
 51.1009 +            }
 51.1010 +
 51.1011 +            if ( (pfn_type[pfn] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK) !=
 51.1012 +                 ((unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT) ) {
 51.1013 +                ERROR("User PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx",
 51.1014 +                      pfn, p2m_size, pfn_type[pfn],
 51.1015 +                      (unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT);
 51.1016 +                goto out;
 51.1017 +            }
 51.1018 +
 51.1019 +            ctxt.ctrlreg[1] = xen_pfn_to_cr3(p2m[pfn]);
 51.1020 +        }
 51.1021 +
 51.1022 +        domctl.cmd = XEN_DOMCTL_setvcpucontext;
 51.1023 +        domctl.domain = (domid_t)dom;
 51.1024 +        domctl.u.vcpucontext.vcpu = i;
 51.1025 +        set_xen_guest_handle(domctl.u.vcpucontext.ctxt, &ctxt);
 51.1026 +        rc = xc_domctl(xc_handle, &domctl);
 51.1027 +        if (rc != 0) {
 51.1028 +            ERROR("Couldn't build vcpu%d", i);
 51.1029 +            goto out;
 51.1030 +        }
 51.1031 +        rc = 1;
 51.1032 +    }
 51.1033 +
 51.1034 +    if (!read_exact(io_fd, shared_info_page, PAGE_SIZE)) {
 51.1035 +        ERROR("Error when reading shared info page");
 51.1036 +        goto out;
 51.1037 +    }
 51.1038 +
 51.1039 +    /* clear any pending events and the selector */
 51.1040 +    memset(&(shared_info->evtchn_pending[0]), 0,
 51.1041 +           sizeof (shared_info->evtchn_pending));
 51.1042 +    for ( i = 0; i < MAX_VIRT_CPUS; i++ )
 51.1043 +        shared_info->vcpu_info[i].evtchn_pending_sel = 0;
 51.1044 +
 51.1045 +    /* Copy saved contents of shared-info page. No checking needed. */
 51.1046 +    page = xc_map_foreign_range(
 51.1047 +        xc_handle, dom, PAGE_SIZE, PROT_WRITE, shared_info_frame);
 51.1048 +    memcpy(page, shared_info, PAGE_SIZE);
 51.1049 +    munmap(page, PAGE_SIZE);
 51.1050 +
 51.1051 +    /* Uncanonicalise the pfn-to-mfn table frame-number list. */
 51.1052 +    for (i = 0; i < P2M_FL_ENTRIES; i++) {
 51.1053 +        pfn = p2m_frame_list[i];
 51.1054 +        if ((pfn >= p2m_size) || (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB)) {
 51.1055 +            ERROR("PFN-to-MFN frame number is bad");
 51.1056 +            goto out;
 51.1057 +        }
 51.1058 +
 51.1059 +        p2m_frame_list[i] = p2m[pfn];
 51.1060 +    }
 51.1061 +
 51.1062 +    /* Copy the P2M we've constructed to the 'live' P2M */
 51.1063 +    if (!(live_p2m = xc_map_foreign_batch(xc_handle, dom, PROT_WRITE,
 51.1064 +                                          p2m_frame_list, P2M_FL_ENTRIES))) {
 51.1065 +        ERROR("Couldn't map p2m table");
 51.1066 +        goto out;
 51.1067 +    }
 51.1068 +
 51.1069 +    memcpy(live_p2m, p2m, ROUNDUP(p2m_size * sizeof(xen_pfn_t), PAGE_SHIFT));
 51.1070 +    munmap(live_p2m, ROUNDUP(p2m_size * sizeof(xen_pfn_t), PAGE_SHIFT));
 51.1071 +
 51.1072 +    DPRINTF("Domain ready to be built.\n");
 51.1073 +    rc = 0;
 51.1074 +
 51.1075 + out:
 51.1076 +    if ( (rc != 0) && (dom != 0) )
 51.1077 +        xc_domain_destroy(xc_handle, dom);
 51.1078 +    free(mmu);
 51.1079 +    free(p2m);
 51.1080 +    free(pfn_type);
 51.1081 +    free(hvm_buf);
 51.1082 +
 51.1083 +    /* discard cache for save file  */
 51.1084 +    discard_file_cache(io_fd, 1 /*flush*/);
 51.1085 +
 51.1086 +    DPRINTF("Restore exit with rc=%d\n", rc);
 51.1087 +    
 51.1088 +    return rc;
 51.1089 +}
    52.1 --- a/tools/libxc/xc_hvm_restore.c	Fri Apr 06 10:06:30 2007 -0600
    52.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.3 @@ -1,360 +0,0 @@
    52.4 -/******************************************************************************
    52.5 - * xc_hvm_restore.c
    52.6 - *
    52.7 - * Restore the state of a HVM guest.
    52.8 - *
    52.9 - * Copyright (c) 2003, K A Fraser.
   52.10 - * Copyright (c) 2006 Intel Corperation
   52.11 - * rewriten for hvm guest by Zhai Edwin <edwin.zhai@intel.com>
   52.12 - *
   52.13 - * This program is free software; you can redistribute it and/or modify it
   52.14 - * under the terms and conditions of the GNU General Public License,
   52.15 - * version 2, as published by the Free Software Foundation.
   52.16 - *
   52.17 - * This program is distributed in the hope it will be useful, but WITHOUT
   52.18 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   52.19 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   52.20 - * more details.
   52.21 - *
   52.22 - * You should have received a copy of the GNU General Public License along with
   52.23 - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
   52.24 - * Place - Suite 330, Boston, MA 02111-1307 USA.
   52.25 - *
   52.26 - */
   52.27 -
   52.28 -#include <stdlib.h>
   52.29 -#include <unistd.h>
   52.30 -
   52.31 -#include "xg_private.h"
   52.32 -#include "xg_save_restore.h"
   52.33 -
   52.34 -#include <xen/hvm/ioreq.h>
   52.35 -#include <xen/hvm/params.h>
   52.36 -#include <xen/hvm/e820.h>
   52.37 -
   52.38 -/* max mfn of the whole machine */
   52.39 -static unsigned long max_mfn;
   52.40 -
   52.41 -/* virtual starting address of the hypervisor */
   52.42 -static unsigned long hvirt_start;
   52.43 -
   52.44 -/* #levels of page tables used by the currrent guest */
   52.45 -static unsigned int pt_levels;
   52.46 -
   52.47 -/* A list of PFNs that exist, used when allocating memory to the guest */
   52.48 -static xen_pfn_t *pfns = NULL;
   52.49 -
   52.50 -static ssize_t
   52.51 -read_exact(int fd, void *buf, size_t count)
   52.52 -{
   52.53 -    int r = 0, s;
   52.54 -    unsigned char *b = buf;
   52.55 -
   52.56 -    while (r < count) {
   52.57 -        s = read(fd, &b[r], count - r);
   52.58 -        if ((s == -1) && (errno == EINTR))
   52.59 -            continue;
   52.60 -        if (s <= 0) {
   52.61 -            break;
   52.62 -        }
   52.63 -        r += s;
   52.64 -    }
   52.65 -
   52.66 -    return (r == count) ? 1 : 0;
   52.67 -}
   52.68 -
   52.69 -int xc_hvm_restore(int xc_handle, int io_fd,
   52.70 -                     uint32_t dom, unsigned long max_pfn,
   52.71 -                     unsigned int store_evtchn, unsigned long *store_mfn,
   52.72 -                     unsigned int pae, unsigned int apic)
   52.73 -{
   52.74 -    DECLARE_DOMCTL;
   52.75 -
   52.76 -    /* A copy of the CPU context of the guest. */
   52.77 -    vcpu_guest_context_t ctxt;
   52.78 -
   52.79 -    char *region_base;
   52.80 -
   52.81 -    unsigned long buf[PAGE_SIZE/sizeof(unsigned long)];
   52.82 -
   52.83 -    xc_dominfo_t info;
   52.84 -    unsigned int rc = 1, n, i;
   52.85 -    uint32_t rec_len, nr_vcpus;
   52.86 -    uint8_t *hvm_buf = NULL;
   52.87 -    unsigned long long v_end;
   52.88 -    unsigned long shared_page_nr;
   52.89 -
   52.90 -    unsigned long pfn;
   52.91 -    unsigned int prev_pc, this_pc;
   52.92 -    int verify = 0;
   52.93 -
   52.94 -    /* Types of the pfns in the current region */
   52.95 -    unsigned long region_pfn_type[MAX_BATCH_SIZE];
   52.96 -
   52.97 -    /* The size of an array big enough to contain all guest pfns */
   52.98 -    unsigned long pfn_array_size = max_pfn + 1;
   52.99 -
  52.100 -    /* Number of pages of memory the guest has.  *Not* the same as max_pfn. */
  52.101 -    unsigned long nr_pages = max_pfn;
  52.102 -    /* MMIO hole doesn't contain RAM */
  52.103 -    if ( nr_pages >= HVM_BELOW_4G_MMIO_START >> PAGE_SHIFT ) 
  52.104 -        nr_pages -= HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT; 
  52.105 -    /* VGA hole doesn't contain RAM */
  52.106 -    nr_pages -= 0x20;
  52.107 -
  52.108 -    /* XXX: Unlikely to be true, but matches previous behaviour. :( */
  52.109 -    v_end = (nr_pages + 0x20) << PAGE_SHIFT;
  52.110 -
  52.111 -    DPRINTF("xc_hvm_restore:dom=%d, nr_pages=0x%lx, store_evtchn=%d, "
  52.112 -            "*store_mfn=%ld, pae=%u, apic=%u.\n", 
  52.113 -            dom, nr_pages, store_evtchn, *store_mfn, pae, apic);
  52.114 -
  52.115 -    if(!get_platform_info(xc_handle, dom,
  52.116 -                          &max_mfn, &hvirt_start, &pt_levels)) {
  52.117 -        ERROR("Unable to get platform info.");
  52.118 -        return 1;
  52.119 -    }
  52.120 -
  52.121 -    DPRINTF("xc_hvm_restore start: nr_pages = %lx, max_pfn = %lx, "
  52.122 -            "max_mfn = %lx, hvirt_start=%lx, pt_levels=%d\n",
  52.123 -            nr_pages, max_pfn, max_mfn, hvirt_start, pt_levels);
  52.124 -
  52.125 -    if (mlock(&ctxt, sizeof(ctxt))) {
  52.126 -        /* needed for build dom0 op, but might as well do early */
  52.127 -        ERROR("Unable to mlock ctxt");
  52.128 -        return 1;
  52.129 -    }
  52.130 -
  52.131 -
  52.132 -    pfns = malloc(pfn_array_size * sizeof(xen_pfn_t));
  52.133 -    if (pfns == NULL) {
  52.134 -        ERROR("memory alloc failed");
  52.135 -        errno = ENOMEM;
  52.136 -        goto out;
  52.137 -    }
  52.138 -
  52.139 -    if(xc_domain_setmaxmem(xc_handle, dom, PFN_TO_KB(nr_pages)) != 0) {
  52.140 -        errno = ENOMEM;
  52.141 -        goto out;
  52.142 -    }
  52.143 -
  52.144 -    for ( i = 0; i < pfn_array_size; i++ )
  52.145 -        pfns[i] = i;
  52.146 -    for ( i = HVM_BELOW_4G_RAM_END >> PAGE_SHIFT; i < pfn_array_size; i++ )
  52.147 -        pfns[i] += HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT;
  52.148 -
  52.149 -    /* Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000. */
  52.150 -    rc = xc_domain_memory_populate_physmap(
  52.151 -        xc_handle, dom, (nr_pages > 0xa0) ? 0xa0 : nr_pages,
  52.152 -        0, 0, &pfns[0x00]);
  52.153 -    if ( (rc == 0) && (nr_pages > 0xc0) )
  52.154 -        rc = xc_domain_memory_populate_physmap(
  52.155 -            xc_handle, dom, nr_pages - 0xa0, 0, 0, &pfns[0xc0]);
  52.156 -    if ( rc != 0 )
  52.157 -    {
  52.158 -        PERROR("Could not allocate memory for HVM guest.\n");
  52.159 -        goto out;
  52.160 -    }
  52.161 -
  52.162 -
  52.163 -    /**********XXXXXXXXXXXXXXXX******************/
  52.164 -    if (xc_domain_getinfo(xc_handle, dom, 1, &info) != 1) {
  52.165 -        ERROR("Could not get domain info");
  52.166 -        return 1;
  52.167 -    }
  52.168 -
  52.169 -    domctl.cmd = XEN_DOMCTL_getdomaininfo;
  52.170 -    domctl.domain = (domid_t)dom;
  52.171 -    if (xc_domctl(xc_handle, &domctl) < 0) {
  52.172 -        ERROR("Could not get information on new domain");
  52.173 -        goto out;
  52.174 -    }
  52.175 -
  52.176 -    prev_pc = 0;
  52.177 -
  52.178 -    n = 0;
  52.179 -    while (1) {
  52.180 -
  52.181 -        int j;
  52.182 -
  52.183 -        this_pc = (n * 100) / nr_pages;
  52.184 -        if ( (this_pc - prev_pc) >= 5 )
  52.185 -        {
  52.186 -            PPRINTF("\b\b\b\b%3d%%", this_pc);
  52.187 -            prev_pc = this_pc;
  52.188 -        }
  52.189 -
  52.190 -        if (!read_exact(io_fd, &j, sizeof(int))) {
  52.191 -            ERROR("HVM restore Error when reading batch size");
  52.192 -            goto out;
  52.193 -        }
  52.194 -
  52.195 -        PPRINTF("batch %d\n",j);
  52.196 -
  52.197 -        if (j == -1) {
  52.198 -            verify = 1;
  52.199 -            DPRINTF("Entering page verify mode\n");
  52.200 -            continue;
  52.201 -        }
  52.202 -
  52.203 -        if (j == 0)
  52.204 -            break;  /* our work here is done */
  52.205 -
  52.206 -        if (j > MAX_BATCH_SIZE) {
  52.207 -            ERROR("Max batch size exceeded. Giving up.");
  52.208 -            goto out;
  52.209 -        }
  52.210 -
  52.211 -        if (!read_exact(io_fd, region_pfn_type, j*sizeof(unsigned long))) {
  52.212 -            ERROR("Error when reading region pfn types");
  52.213 -            goto out;
  52.214 -        }
  52.215 -
  52.216 -        region_base = xc_map_foreign_batch(
  52.217 -            xc_handle, dom, PROT_WRITE, region_pfn_type, j);
  52.218 -
  52.219 -        for ( i = 0; i < j; i++ )
  52.220 -        {
  52.221 -            void *page;
  52.222 -
  52.223 -            pfn = region_pfn_type[i];
  52.224 -            if ( pfn & XEN_DOMCTL_PFINFO_LTAB_MASK )
  52.225 -                continue;
  52.226 -
  52.227 -            if ( pfn > max_pfn )
  52.228 -            {
  52.229 -                ERROR("pfn out of range");
  52.230 -                goto out;
  52.231 -            }
  52.232 -
  52.233 -            if ( pfn >= 0xa0 && pfn < 0xc0) {
  52.234 -                ERROR("hvm restore:pfn in vga hole");
  52.235 -                goto out;
  52.236 -            }
  52.237 -
  52.238 -
  52.239 -            /* In verify mode, we use a copy; otherwise we work in place */
  52.240 -            page = verify ? (void *)buf : (region_base + i*PAGE_SIZE);
  52.241 -
  52.242 -            if (!read_exact(io_fd, page, PAGE_SIZE)) {
  52.243 -                ERROR("Error when reading page (%x)", i);
  52.244 -                goto out;
  52.245 -            }
  52.246 -
  52.247 -            if (verify) {
  52.248 -
  52.249 -                int res = memcmp(buf, (region_base + i*PAGE_SIZE), PAGE_SIZE);
  52.250 -
  52.251 -                if (res) {
  52.252 -
  52.253 -                    int v;
  52.254 -
  52.255 -                    DPRINTF("************** pfn=%lx gotcs=%08lx "
  52.256 -                            "actualcs=%08lx\n", pfn, 
  52.257 -                            csum_page(region_base + i*PAGE_SIZE),
  52.258 -                            csum_page(buf));
  52.259 -
  52.260 -                    for (v = 0; v < 4; v++) {
  52.261 -
  52.262 -                        unsigned long *p = (unsigned long *)
  52.263 -                            (region_base + i*PAGE_SIZE);
  52.264 -                        if (buf[v] != p[v])
  52.265 -                            DPRINTF("    %d: %08lx %08lx\n", v, buf[v], p[v]);
  52.266 -                    }
  52.267 -                }
  52.268 -            }
  52.269 -
  52.270 -        } /* end of 'batch' for loop */
  52.271 -        munmap(region_base, j*PAGE_SIZE);
  52.272 -        n+= j; /* crude stats */
  52.273 -
  52.274 -    }/*while 1*/
  52.275 -    
  52.276 -    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_PAE_ENABLED, pae);
  52.277 -    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_EVTCHN, store_evtchn);
  52.278 -
  52.279 -    if ( v_end > HVM_BELOW_4G_RAM_END )
  52.280 -        shared_page_nr = (HVM_BELOW_4G_RAM_END >> PAGE_SHIFT) - 1;
  52.281 -    else
  52.282 -        shared_page_nr = (v_end >> PAGE_SHIFT) - 1;
  52.283 -
  52.284 -    /* Ensure we clear these pages */
  52.285 -    if ( xc_clear_domain_page(xc_handle, dom, shared_page_nr) ||
  52.286 -         xc_clear_domain_page(xc_handle, dom, shared_page_nr-1) ||
  52.287 -         xc_clear_domain_page(xc_handle, dom, shared_page_nr-2) ) {
  52.288 -        rc = -1;
  52.289 -        goto out;
  52.290 -    }
  52.291 -
  52.292 -    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, shared_page_nr-1);
  52.293 -    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_BUFIOREQ_PFN, shared_page_nr-2);
  52.294 -    xc_set_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN, shared_page_nr);
  52.295 -
  52.296 -    /* caculate the store_mfn , wrong val cause hang when introduceDomain */
  52.297 -    *store_mfn = (v_end >> PAGE_SHIFT) - 2;
  52.298 -    DPRINTF("hvm restore: calculate new store_mfn=0x%lx, v_end=0x%llx.\n", 
  52.299 -            *store_mfn, v_end);
  52.300 -
  52.301 -    if (!read_exact(io_fd, &nr_vcpus, sizeof(uint32_t))) {
  52.302 -        ERROR("error read nr vcpu !\n");
  52.303 -        goto out;
  52.304 -    }
  52.305 -    DPRINTF("hvm restore:get nr_vcpus=%d.\n", nr_vcpus);
  52.306 -
  52.307 -    for (i =0; i < nr_vcpus; i++) {
  52.308 -        if (!read_exact(io_fd, &rec_len, sizeof(uint32_t))) {
  52.309 -            ERROR("error read vcpu context size!\n");
  52.310 -            goto out;
  52.311 -        }
  52.312 -        if (rec_len != sizeof(ctxt)) {
  52.313 -            ERROR("vcpu context size dismatch!\n");
  52.314 -            goto out;
  52.315 -        }
  52.316 -
  52.317 -        if (!read_exact(io_fd, &(ctxt), sizeof(ctxt))) {
  52.318 -            ERROR("error read vcpu context.\n");
  52.319 -            goto out;
  52.320 -        }
  52.321 -
  52.322 -        if ( (rc = xc_vcpu_setcontext(xc_handle, dom, i, &ctxt)) ) {
  52.323 -            ERROR("Could not set vcpu context, rc=%d", rc);
  52.324 -            goto out;
  52.325 -        }
  52.326 -    }
  52.327 -
  52.328 -    /* restore hvm context including pic/pit/shpage */
  52.329 -    if (!read_exact(io_fd, &rec_len, sizeof(uint32_t))) {
  52.330 -        ERROR("error read hvm context size!\n");
  52.331 -        goto out;
  52.332 -    }
  52.333 -
  52.334 -    hvm_buf = malloc(rec_len);
  52.335 -    if (hvm_buf == NULL) {
  52.336 -        ERROR("memory alloc for hvm context buffer failed");
  52.337 -        errno = ENOMEM;
  52.338 -        goto out;
  52.339 -    }
  52.340 -
  52.341 -    if (!read_exact(io_fd, hvm_buf, rec_len)) {
  52.342 -        ERROR("error read hvm buffer!\n");
  52.343 -        goto out;
  52.344 -    }
  52.345 -
  52.346 -    if (( rc = xc_domain_hvm_setcontext(xc_handle, dom, hvm_buf, rec_len))) {
  52.347 -        ERROR("error set hvm buffer!\n");
  52.348 -        goto out;
  52.349 -    }
  52.350 -
  52.351 -    rc = 0;
  52.352 -    goto out;
  52.353 -
  52.354 - out:
  52.355 -    if ( (rc != 0) && (dom != 0) )
  52.356 -        xc_domain_destroy(xc_handle, dom);
  52.357 -    free(pfns);
  52.358 -    free(hvm_buf);
  52.359 -
  52.360 -    DPRINTF("Restore exit with rc=%d\n", rc);
  52.361 -
  52.362 -    return rc;
  52.363 -}
    53.1 --- a/tools/libxc/xc_hvm_save.c	Fri Apr 06 10:06:30 2007 -0600
    53.2 +++ b/tools/libxc/xc_hvm_save.c	Fri Apr 06 10:08:30 2007 -0600
    53.3 @@ -45,37 +45,11 @@
    53.4  #define DEF_MAX_ITERS   29   /* limit us to 30 times round loop   */
    53.5  #define DEF_MAX_FACTOR   3   /* never send more than 3x nr_pfns   */
    53.6  
    53.7 -/* max mfn of the whole machine */
    53.8 -static unsigned long max_mfn;
    53.9 -
   53.10 -/* virtual starting address of the hypervisor */
   53.11 -static unsigned long hvirt_start;
   53.12 -
   53.13 -/* #levels of page tables used by the current guest */
   53.14 -static unsigned int pt_levels;
   53.15 -
   53.16  /* Shared-memory bitmaps for getting log-dirty bits from qemu */
   53.17  static unsigned long *qemu_bitmaps[2];
   53.18  static int qemu_active;
   53.19  static int qemu_non_active;
   53.20  
   53.21 -int xc_hvm_drain_io(int handle, domid_t dom)
   53.22 -{
   53.23 -    DECLARE_HYPERCALL;
   53.24 -    xen_hvm_drain_io_t arg;
   53.25 -    int rc;
   53.26 -
   53.27 -    hypercall.op     = __HYPERVISOR_hvm_op;
   53.28 -    hypercall.arg[0] = HVMOP_drain_io;
   53.29 -    hypercall.arg[1] = (unsigned long)&arg;
   53.30 -    arg.domid = dom;
   53.31 -    if ( lock_pages(&arg, sizeof(arg)) != 0 )
   53.32 -        return -1;
   53.33 -    rc = do_xen_hypercall(handle, &hypercall);
   53.34 -    unlock_pages(&arg, sizeof(arg));
   53.35 -    return rc;
   53.36 -}
   53.37 -
   53.38  /*
   53.39  ** During (live) save/migrate, we maintain a number of bitmaps to track
   53.40  ** which pages we have to send, to fixup, and to skip.
   53.41 @@ -291,9 +265,8 @@ int xc_hvm_save(int xc_handle, int io_fd
   53.42      xc_dominfo_t info;
   53.43  
   53.44      int rc = 1, i, j, last_iter, iter = 0;
   53.45 -    int live  = (flags & XCFLAGS_LIVE);
   53.46 -    int debug = (flags & XCFLAGS_DEBUG);
   53.47 -    int stdvga = (flags & XCFLAGS_STDVGA);
   53.48 +    int live  = !!(flags & XCFLAGS_LIVE);
   53.49 +    int debug = !!(flags & XCFLAGS_DEBUG);
   53.50      int sent_last_iter, skip_this_iter;
   53.51  
   53.52      /* The highest guest-physical frame number used by the current guest */
   53.53 @@ -302,8 +275,8 @@ int xc_hvm_save(int xc_handle, int io_fd
   53.54      /* The size of an array big enough to contain all guest pfns */
   53.55      unsigned long pfn_array_size;
   53.56  
   53.57 -    /* Other magic frames: ioreqs and xenstore comms */
   53.58 -    unsigned long ioreq_pfn, bufioreq_pfn, store_pfn;
   53.59 +    /* Magic frames: ioreqs and xenstore comms. */
   53.60 +    uint64_t magic_pfns[3]; /* ioreq_pfn, bufioreq_pfn, store_pfn */
   53.61  
   53.62      /* A copy of the CPU context of the guest. */
   53.63      vcpu_guest_context_t ctxt;
   53.64 @@ -330,122 +303,97 @@ int xc_hvm_save(int xc_handle, int io_fd
   53.65  
   53.66      xc_shadow_op_stats_t stats;
   53.67  
   53.68 -    unsigned long total_sent    = 0;
   53.69 +    unsigned long total_sent = 0;
   53.70 +
   53.71 +    uint64_t vcpumap = 1ULL;
   53.72  
   53.73      DPRINTF("xc_hvm_save: dom=%d, max_iters=%d, max_factor=%d, flags=0x%x, "
   53.74              "live=%d, debug=%d.\n", dom, max_iters, max_factor, flags,
   53.75              live, debug);
   53.76      
   53.77      /* If no explicit control parameters given, use defaults */
   53.78 -    if(!max_iters)
   53.79 -        max_iters = DEF_MAX_ITERS;
   53.80 -    if(!max_factor)
   53.81 -        max_factor = DEF_MAX_FACTOR;
   53.82 +    max_iters  = max_iters  ? : DEF_MAX_ITERS;
   53.83 +    max_factor = max_factor ? : DEF_MAX_FACTOR;
   53.84  
   53.85      initialize_mbit_rate();
   53.86  
   53.87 -    if(!get_platform_info(xc_handle, dom,
   53.88 -                          &max_mfn, &hvirt_start, &pt_levels)) {
   53.89 -        ERROR("HVM:Unable to get platform info.");
   53.90 -        return 1;
   53.91 -    }
   53.92 -
   53.93 -    if (xc_domain_getinfo(xc_handle, dom, 1, &info) != 1) {
   53.94 -        ERROR("HVM:Could not get domain info");
   53.95 +    if ( xc_domain_getinfo(xc_handle, dom, 1, &info) != 1 )
   53.96 +    {
   53.97 +        ERROR("HVM: Could not get domain info");
   53.98          return 1;
   53.99      }
  53.100      nr_vcpus = info.nr_online_vcpus;
  53.101  
  53.102 -    if (mlock(&ctxt, sizeof(ctxt))) {
  53.103 -        ERROR("HVM:Unable to mlock ctxt");
  53.104 +    if ( mlock(&ctxt, sizeof(ctxt)) )
  53.105 +    {
  53.106 +        ERROR("HVM: Unable to mlock ctxt");
  53.107          return 1;
  53.108      }
  53.109  
  53.110      /* Only have to worry about vcpu 0 even for SMP */
  53.111 -    if (xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt)) {
  53.112 -        ERROR("HVM:Could not get vcpu context");
  53.113 -        goto out;
  53.114 -    }
  53.115 -
  53.116 -    /* cheesy sanity check */
  53.117 -    if ((info.max_memkb >> (PAGE_SHIFT - 10)) > max_mfn) {
  53.118 -        ERROR("Invalid HVM state record -- pfn count out of range: %lu",
  53.119 -            (info.max_memkb >> (PAGE_SHIFT - 10)));
  53.120 +    if ( xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt) )
  53.121 +    {
  53.122 +        ERROR("HVM: Could not get vcpu context");
  53.123          goto out;
  53.124      }
  53.125  
  53.126 -    if ( xc_get_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, &store_pfn)
  53.127 -         || xc_get_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN, &ioreq_pfn)
  53.128 -         || xc_get_hvm_param(xc_handle, dom, 
  53.129 -                             HVM_PARAM_BUFIOREQ_PFN, &bufioreq_pfn) )
  53.130 +    DPRINTF("saved hvm domain info: max_memkb=0x%lx, nr_pages=0x%lx\n",
  53.131 +            info.max_memkb, info.nr_pages); 
  53.132 +
  53.133 +    if ( live )
  53.134      {
  53.135 -        ERROR("HVM: Could not read magic PFN parameters");
  53.136 -        goto out;
  53.137 -    }
  53.138 -    DPRINTF("saved hvm domain info:max_memkb=0x%lx, max_mfn=0x%lx, "
  53.139 -            "nr_pages=0x%lx\n", info.max_memkb, max_mfn, info.nr_pages); 
  53.140 -
  53.141 -    if (live) {
  53.142 -        
  53.143 -        if (xc_shadow_control(xc_handle, dom,
  53.144 -                              XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY,
  53.145 -                              NULL, 0, NULL, 0, NULL) < 0) {
  53.146 +        /* Live suspend. Enable log-dirty mode. */
  53.147 +        if ( xc_shadow_control(xc_handle, dom,
  53.148 +                               XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY,
  53.149 +                               NULL, 0, NULL, 0, NULL) < 0 )
  53.150 +        {
  53.151              ERROR("Couldn't enable shadow mode");
  53.152              goto out;
  53.153          }
  53.154  
  53.155 -        last_iter = 0;
  53.156 -
  53.157          DPRINTF("hvm domain live migration debug start: logdirty enable.\n");
  53.158 -    } else {
  53.159 -        /* This is a non-live suspend. Issue the call back to get the
  53.160 -           domain suspended */
  53.161 -
  53.162 -        last_iter = 1;
  53.163 -
  53.164 -        /* suspend hvm domain */
  53.165 -        if (suspend_and_state(suspend, xc_handle, io_fd, dom, &info, &ctxt)) {
  53.166 +    }
  53.167 +    else
  53.168 +    {
  53.169 +        /* This is a non-live suspend. Suspend the domain .*/
  53.170 +        if ( suspend_and_state(suspend, xc_handle, io_fd, dom, &info, &ctxt) )
  53.171 +        {
  53.172              ERROR("HVM Domain appears not to have suspended");
  53.173              goto out;
  53.174          }
  53.175      }
  53.176  
  53.177 -    DPRINTF("after 1st handle hvm domain nr_pages=0x%lx, "
  53.178 -            "max_memkb=0x%lx, live=%d.\n",
  53.179 -            info.nr_pages, info.max_memkb, live);
  53.180 +    last_iter = !live;
  53.181 +
  53.182 +    max_pfn = xc_memory_op(xc_handle, XENMEM_maximum_gpfn, &dom);
  53.183  
  53.184 -    /* Calculate the highest PFN of "normal" memory:
  53.185 -     * HVM memory is sequential except for the VGA and MMIO holes. */
  53.186 -    max_pfn = info.nr_pages - 1;
  53.187 -    /* If the domain has a Cirrus framebuffer and we haven't already 
  53.188 -     * suspended qemu-dm, it will have 8MB of framebuffer memory 
  53.189 -     * still allocated, which we don't want to copy: qemu will save it 
  53.190 -     * for us later */
  53.191 -    if ( live && !stdvga )
  53.192 -        max_pfn -= 0x800;
  53.193 -    /* Skip the VGA hole from 0xa0000 to 0xc0000 */
  53.194 -    max_pfn += 0x20;
  53.195 -    /* Skip the MMIO hole: 256MB just below 4GB */
  53.196 -    if ( max_pfn >= (HVM_BELOW_4G_MMIO_START >> PAGE_SHIFT) )
  53.197 -        max_pfn += (HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT); 
  53.198 +    DPRINTF("after 1st handle hvm domain max_pfn=0x%lx, "
  53.199 +            "max_memkb=0x%lx, live=%d.\n",
  53.200 +            max_pfn, info.max_memkb, live);
  53.201  
  53.202      /* Size of any array that covers 0 ... max_pfn */
  53.203      pfn_array_size = max_pfn + 1;
  53.204 +    if ( !write_exact(io_fd, &pfn_array_size, sizeof(unsigned long)) )
  53.205 +    {
  53.206 +        ERROR("Error when writing to state file (1)");
  53.207 +        goto out;
  53.208 +    }
  53.209 +    
  53.210  
  53.211      /* pretend we sent all the pages last iteration */
  53.212      sent_last_iter = pfn_array_size;
  53.213  
  53.214      /* calculate the power of 2 order of pfn_array_size, e.g.
  53.215         15->4 16->4 17->5 */
  53.216 -    for (i = pfn_array_size-1, order_nr = 0; i ; i >>= 1, order_nr++)
  53.217 +    for ( i = pfn_array_size-1, order_nr = 0; i ; i >>= 1, order_nr++ )
  53.218          continue;
  53.219  
  53.220      /* Setup to_send / to_fix and to_skip bitmaps */
  53.221      to_send = malloc(BITMAP_SIZE);
  53.222      to_skip = malloc(BITMAP_SIZE);
  53.223  
  53.224 -
  53.225 -    if (live) {
  53.226 +    if ( live )
  53.227 +    {
  53.228          /* Get qemu-dm logging dirty pages too */
  53.229          void *seg = init_qemu_maps(dom, BITMAP_SIZE);
  53.230          qemu_bitmaps[0] = seg;
  53.231 @@ -462,44 +410,40 @@ int xc_hvm_save(int xc_handle, int io_fd
  53.232      }
  53.233      hvm_buf = malloc(hvm_buf_size);
  53.234  
  53.235 -    if (!to_send ||!to_skip ||!hvm_buf) {
  53.236 +    if ( !to_send || !to_skip || !hvm_buf )
  53.237 +    {
  53.238          ERROR("Couldn't allocate memory");
  53.239          goto out;
  53.240      }
  53.241  
  53.242      memset(to_send, 0xff, BITMAP_SIZE);
  53.243  
  53.244 -    if (lock_pages(to_send, BITMAP_SIZE)) {
  53.245 +    if ( lock_pages(to_send, BITMAP_SIZE) )
  53.246 +    {
  53.247          ERROR("Unable to lock to_send");
  53.248          return 1;
  53.249      }
  53.250  
  53.251      /* (to fix is local only) */
  53.252 -    if (lock_pages(to_skip, BITMAP_SIZE)) {
  53.253 +    if ( lock_pages(to_skip, BITMAP_SIZE) )
  53.254 +    {
  53.255          ERROR("Unable to lock to_skip");
  53.256          return 1;
  53.257      }
  53.258  
  53.259      analysis_phase(xc_handle, dom, pfn_array_size, to_skip, 0);
  53.260  
  53.261 -
  53.262      /* We want zeroed memory so use calloc rather than malloc. */
  53.263      pfn_batch = calloc(MAX_BATCH_SIZE, sizeof(*pfn_batch));
  53.264 -
  53.265 -    if (pfn_batch == NULL) {
  53.266 +    if ( pfn_batch == NULL )
  53.267 +    {
  53.268          ERROR("failed to alloc memory for pfn_batch array");
  53.269          errno = ENOMEM;
  53.270          goto out;
  53.271      }
  53.272  
  53.273 -    /* Start writing out the saved-domain record. */
  53.274 -    if (!write_exact(io_fd, &max_pfn, sizeof(unsigned long))) {
  53.275 -        ERROR("write: max_pfn");
  53.276 -        goto out;
  53.277 -    }
  53.278 -
  53.279 -    while(1) {
  53.280 -
  53.281 +    for ( ; ; )
  53.282 +    {
  53.283          unsigned int prev_pc, sent_this_iter, N, batch;
  53.284  
  53.285          iter++;
  53.286 @@ -510,51 +454,56 @@ int xc_hvm_save(int xc_handle, int io_fd
  53.287  
  53.288          DPRINTF("Saving HVM domain memory pages: iter %d   0%%", iter);
  53.289  
  53.290 -        while( N < pfn_array_size ){
  53.291 -
  53.292 +        while ( N < pfn_array_size )
  53.293 +        {
  53.294              unsigned int this_pc = (N * 100) / pfn_array_size;
  53.295              int rc;
  53.296  
  53.297 -            if ((this_pc - prev_pc) >= 5) {
  53.298 +            if ( (this_pc - prev_pc) >= 5 )
  53.299 +            {
  53.300                  DPRINTF("\b\b\b\b%3d%%", this_pc);
  53.301                  prev_pc = this_pc;
  53.302              }
  53.303  
  53.304 -            /* slightly wasteful to peek the whole array evey time,
  53.305 -               but this is fast enough for the moment. */
  53.306 -            if (!last_iter && (rc = xc_shadow_control(
  53.307 +            if ( !last_iter )
  53.308 +            {
  53.309 +                /* Slightly wasteful to peek the whole array evey time,
  53.310 +                   but this is fast enough for the moment. */
  53.311 +                rc = xc_shadow_control(
  53.312                      xc_handle, dom, XEN_DOMCTL_SHADOW_OP_PEEK, to_skip, 
  53.313 -                    pfn_array_size, NULL, 0, NULL)) != pfn_array_size) {
  53.314 -                ERROR("Error peeking HVM shadow bitmap");
  53.315 -                goto out;
  53.316 +                    pfn_array_size, NULL, 0, NULL);
  53.317 +                if ( rc != pfn_array_size )
  53.318 +                {
  53.319 +                    ERROR("Error peeking HVM shadow bitmap");
  53.320 +                    goto out;
  53.321 +                }
  53.322              }
  53.323  
  53.324 -
  53.325              /* load pfn_batch[] with the mfn of all the pages we're doing in
  53.326                 this batch. */
  53.327 -            for (batch = 0; batch < MAX_BATCH_SIZE && N < pfn_array_size; N++){
  53.328 -
  53.329 +            for ( batch = 0;
  53.330 +                  (batch < MAX_BATCH_SIZE) && (N < pfn_array_size);
  53.331 +                  N++ )
  53.332 +            {
  53.333                  int n = permute(N, pfn_array_size, order_nr);
  53.334  
  53.335 -                if (0&&debug) {
  53.336 +                if ( 0 && debug )
  53.337                      DPRINTF("%d pfn= %08lx %d \n",
  53.338                              iter, (unsigned long)n, test_bit(n, to_send));
  53.339 -                }
  53.340  
  53.341 -                if (!last_iter && test_bit(n, to_send)&& test_bit(n, to_skip))
  53.342 +                if ( !last_iter &&
  53.343 +                     test_bit(n, to_send) &&
  53.344 +                     test_bit(n, to_skip) )
  53.345                      skip_this_iter++; /* stats keeping */
  53.346  
  53.347 -                if (!((test_bit(n, to_send) && !test_bit(n, to_skip)) ||
  53.348 -                      (test_bit(n, to_send) && last_iter)))
  53.349 +                if ( !((test_bit(n, to_send) && !test_bit(n, to_skip)) ||
  53.350 +                       (test_bit(n, to_send) && last_iter)) )
  53.351                      continue;
  53.352  
  53.353                  /* Skip PFNs that aren't really there */
  53.354 -                if ((n >= 0xa0 && n < 0xc0) /* VGA hole */
  53.355 -                    || (n >= (HVM_BELOW_4G_MMIO_START >> PAGE_SHIFT)
  53.356 -                        && n < (1ULL << 32) >> PAGE_SHIFT) /* 4G MMIO hole */
  53.357 -                    || n == store_pfn
  53.358 -                    || n == ioreq_pfn
  53.359 -                    || n == bufioreq_pfn)
  53.360 +                if ( (n >= 0xa0 && n < 0xc0) /* VGA hole */
  53.361 +                     || (n >= (HVM_BELOW_4G_MMIO_START >> PAGE_SHIFT) &&
  53.362 +                         n < (1ULL << 32) >> PAGE_SHIFT) /* 4G MMIO hole */ )
  53.363                      continue;
  53.364  
  53.365                  /*
  53.366 @@ -568,24 +517,27 @@ int xc_hvm_save(int xc_handle, int io_fd
  53.367                  batch++;
  53.368              }
  53.369  
  53.370 -            if (batch == 0)
  53.371 +            if ( batch == 0 )
  53.372                  goto skip; /* vanishingly unlikely... */
  53.373  
  53.374 -            /* map_foreign use pfns now !*/
  53.375 -            if ((region_base = xc_map_foreign_batch(
  53.376 -                     xc_handle, dom, PROT_READ, pfn_batch, batch)) == 0) {
  53.377 +            region_base = xc_map_foreign_batch(
  53.378 +                xc_handle, dom, PROT_READ, pfn_batch, batch);
  53.379 +            if ( region_base == 0 )
  53.380 +            {
  53.381                  ERROR("map batch failed");
  53.382                  goto out;
  53.383              }
  53.384  
  53.385              /* write num of pfns */
  53.386 -            if(!write_exact(io_fd, &batch, sizeof(unsigned int))) {
  53.387 +            if ( !write_exact(io_fd, &batch, sizeof(unsigned int)) )
  53.388 +            {
  53.389                  ERROR("Error when writing to state file (2)");
  53.390                  goto out;
  53.391              }
  53.392  
  53.393              /* write all the pfns */
  53.394 -            if(!write_exact(io_fd, pfn_batch, sizeof(unsigned long)*batch)) {
  53.395 +            if ( !write_exact(io_fd, pfn_batch, sizeof(unsigned long)*batch) )
  53.396 +            {
  53.397                  ERROR("Error when writing to state file (3)");
  53.398                  goto out;
  53.399              }
  53.400 @@ -615,21 +567,23 @@ int xc_hvm_save(int xc_handle, int io_fd
  53.401          DPRINTF("\r %d: sent %d, skipped %d, ",
  53.402                  iter, sent_this_iter, skip_this_iter );
  53.403  
  53.404 -        if (last_iter) {
  53.405 +        if ( last_iter )
  53.406 +        {
  53.407              print_stats( xc_handle, dom, sent_this_iter, &stats, 1);
  53.408 -
  53.409              DPRINTF("Total pages sent= %ld (%.2fx)\n",
  53.410                      total_sent, ((float)total_sent)/pfn_array_size );
  53.411          }
  53.412  
  53.413 -        if (last_iter && debug){
  53.414 +        if ( last_iter && debug )
  53.415 +        {
  53.416              int minusone = -1;
  53.417              memset(to_send, 0xff, BITMAP_SIZE);
  53.418              debug = 0;
  53.419              DPRINTF("Entering debug resend-all mode\n");
  53.420  
  53.421              /* send "-1" to put receiver into debug mode */
  53.422 -            if(!write_exact(io_fd, &minusone, sizeof(int))) {
  53.423 +            if ( !write_exact(io_fd, &minusone, sizeof(int)) )
  53.424 +            {
  53.425                  ERROR("Error when writing to state file (6)");
  53.426                  goto out;
  53.427              }
  53.428 @@ -637,22 +591,22 @@ int xc_hvm_save(int xc_handle, int io_fd
  53.429              continue;
  53.430          }
  53.431  
  53.432 -        if (last_iter) break;
  53.433 -
  53.434 -        if (live) {
  53.435 -
  53.436 +        if ( last_iter )
  53.437 +            break;
  53.438  
  53.439 -            if(
  53.440 -                ((sent_this_iter > sent_last_iter) && RATE_IS_MAX()) ||
  53.441 -                (iter >= max_iters) ||
  53.442 -                (sent_this_iter+skip_this_iter < 50) ||
  53.443 -                (total_sent > pfn_array_size*max_factor) ) {
  53.444 -
  53.445 +        if ( live )
  53.446 +        {
  53.447 +            if ( ((sent_this_iter > sent_last_iter) && RATE_IS_MAX()) ||
  53.448 +                 (iter >= max_iters) ||
  53.449 +                 (sent_this_iter+skip_this_iter < 50) ||
  53.450 +                 (total_sent > pfn_array_size*max_factor) )
  53.451 +            {
  53.452                  DPRINTF("Start last iteration for HVM domain\n");
  53.453                  last_iter = 1;
  53.454  
  53.455 -                if (suspend_and_state(suspend, xc_handle, io_fd, dom, &info,
  53.456 -                                      &ctxt)) {
  53.457 +                if ( suspend_and_state(suspend, xc_handle, io_fd, dom, &info,
  53.458 +                                       &ctxt))
  53.459 +                {
  53.460                      ERROR("Domain appears not to have suspended");
  53.461                      goto out;
  53.462                  }
  53.463 @@ -662,25 +616,30 @@ int xc_hvm_save(int xc_handle, int io_fd
  53.464                          (unsigned long)ctxt.user_regs.edx);
  53.465              }
  53.466  
  53.467 -            if (xc_shadow_control(xc_handle, dom, 
  53.468 -                                  XEN_DOMCTL_SHADOW_OP_CLEAN, to_send, 
  53.469 -                                  pfn_array_size, NULL, 
  53.470 -                                  0, &stats) != pfn_array_size) {
  53.471 +            if ( xc_shadow_control(xc_handle, dom, 
  53.472 +                                   XEN_DOMCTL_SHADOW_OP_CLEAN, to_send, 
  53.473 +                                   pfn_array_size, NULL, 
  53.474 +                                   0, &stats) != pfn_array_size )
  53.475 +            {
  53.476                  ERROR("Error flushing shadow PT");
  53.477                  goto out;
  53.478              }
  53.479  
  53.480              /* Pull in the dirty bits from qemu too */
  53.481 -            if (!last_iter) {
  53.482 +            if ( !last_iter )
  53.483 +            {
  53.484                  qemu_active = qemu_non_active;
  53.485                  qemu_non_active = qemu_active ? 0 : 1;
  53.486                  qemu_flip_buffer(dom, qemu_active);
  53.487 -                for (j = 0; j < BITMAP_SIZE / sizeof(unsigned long); j++) {
  53.488 +                for ( j = 0; j < BITMAP_SIZE / sizeof(unsigned long); j++ )
  53.489 +                {
  53.490                      to_send[j] |= qemu_bitmaps[qemu_non_active][j];
  53.491                      qemu_bitmaps[qemu_non_active][j] = 0;
  53.492                  }
  53.493 -            } else {
  53.494 -                for (j = 0; j < BITMAP_SIZE / sizeof(unsigned long); j++) 
  53.495 +            }
  53.496 +            else
  53.497 +            {
  53.498 +                for ( j = 0; j < BITMAP_SIZE / sizeof(unsigned long); j++ )
  53.499                      to_send[j] |= qemu_bitmaps[qemu_active][j];
  53.500              }
  53.501  
  53.502 @@ -688,61 +647,96 @@ int xc_hvm_save(int xc_handle, int io_fd
  53.503  
  53.504              print_stats(xc_handle, dom, sent_this_iter, &stats, 1);
  53.505          }
  53.506 -
  53.507 -
  53.508      } /* end of while 1 */
  53.509  
  53.510  
  53.511      DPRINTF("All HVM memory is saved\n");
  53.512  
  53.513 +    {
  53.514 +        struct {
  53.515 +            int minustwo;
  53.516 +            int max_vcpu_id;
  53.517 +            uint64_t vcpumap;
  53.518 +        } chunk = { -2, info.max_vcpu_id };
  53.519 +
  53.520 +        if (info.max_vcpu_id >= 64) {
  53.521 +            ERROR("Too many VCPUS in guest!");
  53.522 +            goto out;
  53.523 +        }
  53.524 +
  53.525 +        for (i = 1; i <= info.max_vcpu_id; i++) {
  53.526 +            xc_vcpuinfo_t vinfo;
  53.527 +            if ((xc_vcpu_getinfo(xc_handle, dom, i, &vinfo) == 0) &&
  53.528 +                vinfo.online)
  53.529 +                vcpumap |= 1ULL << i;
  53.530 +        }
  53.531 +
  53.532 +        chunk.vcpumap = vcpumap;
  53.533 +        if(!write_exact(io_fd, &chunk, sizeof(chunk))) {
  53.534 +            ERROR("Error when writing to state file (errno %d)", errno);
  53.535 +            goto out;
  53.536 +        }
  53.537 +    }
  53.538 +
  53.539      /* Zero terminate */
  53.540      i = 0;
  53.541 -    if (!write_exact(io_fd, &i, sizeof(int))) {
  53.542 +    if ( !write_exact(io_fd, &i, sizeof(int)) )
  53.543 +    {
  53.544          ERROR("Error when writing to state file (6)");
  53.545          goto out;
  53.546      }
  53.547  
  53.548 -
  53.549 -    /* save vcpu/vmcs context */
  53.550 -    if (!write_exact(io_fd, &nr_vcpus, sizeof(uint32_t))) {
  53.551 -        ERROR("error write nr vcpus");
  53.552 +    /* Save magic-page locations. */
  53.553 +    memset(magic_pfns, 0, sizeof(magic_pfns));
  53.554 +    xc_get_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN,
  53.555 +                     (unsigned long *)&magic_pfns[0]);
  53.556 +    xc_get_hvm_param(xc_handle, dom, HVM_PARAM_BUFIOREQ_PFN,
  53.557 +                     (unsigned long *)&magic_pfns[1]);
  53.558 +    xc_get_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN,
  53.559 +                     (unsigned long *)&magic_pfns[2]);
  53.560 +    if ( !write_exact(io_fd, magic_pfns, sizeof(magic_pfns)) )
  53.561 +    {
  53.562 +        ERROR("Error when writing to state file (7)");
  53.563          goto out;
  53.564      }
  53.565  
  53.566 -    /*XXX: need a online map to exclude down cpu */
  53.567 -    for (i = 0; i < nr_vcpus; i++) {
  53.568 +    /* save vcpu/vmcs contexts */
  53.569 +    for ( i = 0; i < nr_vcpus; i++ )
  53.570 +    {
  53.571 +        if (!(vcpumap & (1ULL << i)))
  53.572 +            continue;
  53.573  
  53.574 -        if (xc_vcpu_getcontext(xc_handle, dom, i, &ctxt)) {
  53.575 +        if ( xc_vcpu_getcontext(xc_handle, dom, i, &ctxt) )
  53.576 +        {
  53.577              ERROR("HVM:Could not get vcpu context");
  53.578              goto out;
  53.579          }
  53.580  
  53.581 -        rec_size = sizeof(ctxt);
  53.582 -        DPRINTF("write %d vcpucontext of total %d.\n", i, nr_vcpus); 
  53.583 -        if (!write_exact(io_fd, &rec_size, sizeof(uint32_t))) {
  53.584 -            ERROR("error write vcpu ctxt size");
  53.585 -            goto out;
  53.586 -        }
  53.587 -
  53.588 -        if (!write_exact(io_fd, &(ctxt), sizeof(ctxt)) ) {
  53.589 -            ERROR("write vmcs failed!\n");
  53.590 +        DPRINTF("write vcpu %d context.\n", i); 
  53.591 +        if ( !write_exact(io_fd, &(ctxt), sizeof(ctxt)) )
  53.592 +        {
  53.593 +            ERROR("write vcpu context failed!\n");
  53.594              goto out;
  53.595          }
  53.596      }
  53.597  
  53.598      if ( (rec_size = xc_domain_hvm_getcontext(xc_handle, dom, hvm_buf, 
  53.599 -                                              hvm_buf_size)) == -1) {
  53.600 +                                              hvm_buf_size)) == -1 )
  53.601 +    {
  53.602          ERROR("HVM:Could not get hvm buffer");
  53.603          goto out;
  53.604      }
  53.605  
  53.606 -    if (!write_exact(io_fd, &rec_size, sizeof(uint32_t))) {
  53.607 +    if ( !write_exact(io_fd, &rec_size, sizeof(uint32_t)) )
  53.608 +    {
  53.609          ERROR("error write hvm buffer size");
  53.610          goto out;
  53.611      }
  53.612  
  53.613 -    if ( !write_exact(io_fd, hvm_buf, rec_size) ) {
  53.614 +    if ( !write_exact(io_fd, hvm_buf, rec_size) )
  53.615 +    {
  53.616          ERROR("write HVM info failed!\n");
  53.617 +        goto out;
  53.618      }
  53.619  
  53.620      /* Success! */
  53.621 @@ -750,12 +744,11 @@ int xc_hvm_save(int xc_handle, int io_fd
  53.622  
  53.623   out:
  53.624  
  53.625 -    if (live) {
  53.626 -        if(xc_shadow_control(xc_handle, dom, 
  53.627 -                             XEN_DOMCTL_SHADOW_OP_OFF,
  53.628 -                             NULL, 0, NULL, 0, NULL) < 0) {
  53.629 +    if ( live )
  53.630 +    {
  53.631 +        if ( xc_shadow_control(xc_handle, dom, XEN_DOMCTL_SHADOW_OP_OFF,
  53.632 +                               NULL, 0, NULL, 0, NULL) < 0 )
  53.633              DPRINTF("Warning - couldn't disable shadow mode");
  53.634 -        }
  53.635      }
  53.636  
  53.637      free(hvm_buf);
    54.1 --- a/tools/libxc/xc_linux_restore.c	Fri Apr 06 10:06:30 2007 -0600
    54.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.3 @@ -1,962 +0,0 @@
    54.4 -/******************************************************************************
    54.5 - * xc_linux_restore.c
    54.6 - *
    54.7 - * Restore the state of a Linux session.
    54.8 - *
    54.9 - * Copyright (c) 2003, K A Fraser.
   54.10 - */
   54.11 -
   54.12 -#include <stdlib.h>
   54.13 -#include <unistd.h>
   54.14 -
   54.15 -#include "xg_private.h"
   54.16 -#include "xg_save_restore.h"
   54.17 -#include "xc_dom.h"
   54.18 -
   54.19 -/* max mfn of the current host machine */
   54.20 -static unsigned long max_mfn;
   54.21 -
   54.22 -/* virtual starting address of the hypervisor */
   54.23 -static unsigned long hvirt_start;
   54.24 -
   54.25 -/* #levels of page tables used by the current guest */
   54.26 -static unsigned int pt_levels;
   54.27 -
   54.28 -/* number of pfns this guest has (i.e. number of entries in the P2M) */
   54.29 -static unsigned long p2m_size;
   54.30 -
   54.31 -/* number of 'in use' pfns in the guest (i.e. #P2M entries with a valid mfn) */
   54.32 -static unsigned long nr_pfns;
   54.33 -
   54.34 -/* largest possible value of nr_pfns (i.e. domain's maximum memory size) */
   54.35 -static unsigned long max_nr_pfns;
   54.36 -
   54.37 -/* Live mapping of the table mapping each PFN to its current MFN. */
   54.38 -static xen_pfn_t *live_p2m = NULL;
   54.39 -
   54.40 -/* A table mapping each PFN to its new MFN. */
   54.41 -static xen_pfn_t *p2m = NULL;
   54.42 -
   54.43 -/* A table of P2M mappings in the current region */
   54.44 -static xen_pfn_t *p2m_batch = NULL;
   54.45 -
   54.46 -static ssize_t
   54.47 -read_exact(int fd, void *buf, size_t count)
   54.48 -{
   54.49 -    int r = 0, s;
   54.50 -    unsigned char *b = buf;
   54.51 -
   54.52 -    while (r < count) {
   54.53 -        s = read(fd, &b[r], count - r);
   54.54 -        if ((s == -1) && (errno == EINTR))
   54.55 -            continue;
   54.56 -        if (s <= 0) {
   54.57 -            break;
   54.58 -        }
   54.59 -        r += s;
   54.60 -    }
   54.61 -
   54.62 -    return (r == count) ? 1 : 0;
   54.63 -}
   54.64 -
   54.65 -/*
   54.66 -** In the state file (or during transfer), all page-table pages are
   54.67 -** converted into a 'canonical' form where references to actual mfns
   54.68 -** are replaced with references to the corresponding pfns.
   54.69 -** This function inverts that operation, replacing the pfn values with
   54.70 -** the (now known) appropriate mfn values.
   54.71 -*/
   54.72 -static int uncanonicalize_pagetable(int xc_handle, uint32_t dom, 
   54.73 -                                    unsigned long type, void *page)
   54.74 -{
   54.75 -    int i, pte_last;
   54.76 -    unsigned long pfn;
   54.77 -    uint64_t pte;
   54.78 -    int nr_mfns = 0; 
   54.79 -
   54.80 -    pte_last = PAGE_SIZE / ((pt_levels == 2)? 4 : 8);
   54.81 -
   54.82 -    /* First pass: work out how many (if any) MFNs we need to alloc */
   54.83 -    for(i = 0; i < pte_last; i++) {
   54.84 -        
   54.85 -        if(pt_levels == 2)
   54.86 -            pte = ((uint32_t *)page)[i];
   54.87 -        else
   54.88 -            pte = ((uint64_t *)page)[i];
   54.89 -        
   54.90 -        /* XXX SMH: below needs fixing for PROT_NONE etc */
   54.91 -        if(!(pte & _PAGE_PRESENT))
   54.92 -            continue; 
   54.93 -        
   54.94 -        pfn = (pte >> PAGE_SHIFT) & MFN_MASK_X86;
   54.95 -        
   54.96 -        if(pfn >= p2m_size) {
   54.97 -            /* This "page table page" is probably not one; bail. */
   54.98 -            ERROR("Frame number in type %lu page table is out of range: "
   54.99 -                  "i=%d pfn=0x%lx p2m_size=%lu",
  54.100 -                  type >> 28, i, pfn, p2m_size);
  54.101 -            return 0;
  54.102 -        }
  54.103 -        
  54.104 -        if(p2m[pfn] == INVALID_P2M_ENTRY) {
  54.105 -            /* Have a 'valid' PFN without a matching MFN - need to alloc */
  54.106 -            p2m_batch[nr_mfns++] = pfn; 
  54.107 -        }
  54.108 -    }
  54.109 -    
  54.110 -    
  54.111 -    /* Alllocate the requistite number of mfns */
  54.112 -    if (nr_mfns && xc_domain_memory_populate_physmap(
  54.113 -            xc_handle, dom, nr_mfns, 0, 0, p2m_batch) != 0) { 
  54.114 -        ERROR("Failed to allocate memory for batch.!\n"); 
  54.115 -        errno = ENOMEM;
  54.116 -        return 0; 
  54.117 -    }
  54.118 -    
  54.119 -    /* Second pass: uncanonicalize each present PTE */
  54.120 -    nr_mfns = 0;
  54.121 -    for(i = 0; i < pte_last; i++) {
  54.122 -
  54.123 -        if(pt_levels == 2)
  54.124 -            pte = ((uint32_t *)page)[i];
  54.125 -        else
  54.126 -            pte = ((uint64_t *)page)[i];
  54.127 -        
  54.128 -        /* XXX SMH: below needs fixing for PROT_NONE etc */
  54.129 -        if(!(pte & _PAGE_PRESENT))
  54.130 -            continue;
  54.131 -        
  54.132 -        pfn = (pte >> PAGE_SHIFT) & MFN_MASK_X86;
  54.133 -        
  54.134 -        if(p2m[pfn] == INVALID_P2M_ENTRY)
  54.135 -            p2m[pfn] = p2m_batch[nr_mfns++];
  54.136 -
  54.137 -        pte &= ~MADDR_MASK_X86;
  54.138 -        pte |= (uint64_t)p2m[pfn] << PAGE_SHIFT;
  54.139 -
  54.140 -        if(pt_levels == 2)
  54.141 -            ((uint32_t *)page)[i] = (uint32_t)pte;
  54.142 -        else
  54.143 -            ((uint64_t *)page)[i] = (uint64_t)pte;
  54.144 -    }
  54.145 -
  54.146 -    return 1;
  54.147 -}
  54.148 -
  54.149 -
  54.150 -int xc_linux_restore(int xc_handle, int io_fd, uint32_t dom,
  54.151 -                     unsigned long p2msize, unsigned long maxnrpfns,
  54.152 -                     unsigned int store_evtchn, unsigned long *store_mfn,
  54.153 -                     unsigned int console_evtchn, unsigned long *console_mfn)
  54.154 -{
  54.155 -    DECLARE_DOMCTL;
  54.156 -    int rc = 1, i, j, n, m, pae_extended_cr3 = 0;
  54.157 -    unsigned long mfn, pfn;
  54.158 -    unsigned int prev_pc, this_pc;
  54.159 -    int verify = 0;
  54.160 -    int nraces = 0;
  54.161 -
  54.162 -    /* The new domain's shared-info frame number. */
  54.163 -    unsigned long shared_info_frame;
  54.164 -    unsigned char shared_info_page[PAGE_SIZE]; /* saved contents from file */
  54.165 -    shared_info_t *shared_info = (shared_info_t *)shared_info_page;
  54.166 -
  54.167 -    /* A copy of the CPU context of the guest. */
  54.168 -    vcpu_guest_context_t ctxt;
  54.169 -
  54.170 -    /* A table containing the type of each PFN (/not/ MFN!). */
  54.171 -    unsigned long *pfn_type = NULL;
  54.172 -
  54.173 -    /* A table of MFNs to map in the current region */
  54.174 -    xen_pfn_t *region_mfn = NULL;
  54.175 -
  54.176 -    /* Types of the pfns in the current region */
  54.177 -    unsigned long region_pfn_type[MAX_BATCH_SIZE];
  54.178 -
  54.179 -    /* A temporary mapping, and a copy, of one frame of guest memory. */
  54.180 -    unsigned long *page = NULL;
  54.181 -
  54.182 -    /* A copy of the pfn-to-mfn table frame list. */
  54.183 -    xen_pfn_t *p2m_frame_list = NULL;
  54.184 -
  54.185 -    /* A temporary mapping of the guest's start_info page. */
  54.186 -    start_info_t *start_info;
  54.187 -
  54.188 -    /* Our mapping of the current region (batch) */
  54.189 -    char *region_base;
  54.190 -
  54.191 -    xc_mmu_t *mmu = NULL;
  54.192 -
  54.193 -    /* used by debug verify code */
  54.194 -    unsigned long buf[PAGE_SIZE/sizeof(unsigned long)];
  54.195 -
  54.196 -    struct mmuext_op pin[MAX_PIN_BATCH];
  54.197 -    unsigned int nr_pins;
  54.198 -
  54.199 -    uint64_t vcpumap = 1ULL;
  54.200 -    unsigned int max_vcpu_id = 0;
  54.201 -    int new_ctxt_format = 0;
  54.202 -
  54.203 -    p2m_size    = p2msize;
  54.204 -    max_nr_pfns = maxnrpfns;
  54.205 -
  54.206 -    /* For info only */
  54.207 -    nr_pfns = 0;
  54.208 -
  54.209 -    DPRINTF("xc_linux_restore start: p2m_size = %lx\n", p2m_size);
  54.210 -
  54.211 -    /*
  54.212 -     * XXX For now, 32bit dom0's can only save/restore 32bit domUs
  54.213 -     * on 64bit hypervisors.
  54.214 -     */
  54.215 -    memset(&domctl, 0, sizeof(domctl));
  54.216 -    domctl.domain = dom;
  54.217 -    domctl.cmd    = XEN_DOMCTL_set_address_size;
  54.218 -    domctl.u.address_size.size = sizeof(unsigned long) * 8;
  54.219 -    rc = do_domctl(xc_handle, &domctl);
  54.220 -    if ( rc != 0 ) {
  54.221 -	ERROR("Unable to set guest address size.");
  54.222 -	goto out;
  54.223 -    }
  54.224 -
  54.225 -    if(!get_platform_info(xc_handle, dom,
  54.226 -                          &max_mfn, &hvirt_start, &pt_levels)) {
  54.227 -        ERROR("Unable to get platform info.");
  54.228 -        return 1;
  54.229 -    }
  54.230 -
  54.231 -    if (lock_pages(&ctxt, sizeof(ctxt))) {
  54.232 -        /* needed for build domctl, but might as well do early */
  54.233 -        ERROR("Unable to lock ctxt");
  54.234 -        return 1;
  54.235 -    }
  54.236 -
  54.237 -    if (!(p2m_frame_list = malloc(P2M_FL_SIZE))) {
  54.238 -        ERROR("Couldn't allocate p2m_frame_list array");
  54.239 -        goto out;
  54.240 -    }
  54.241 -
  54.242 -    /* Read first entry of P2M list, or extended-info signature (~0UL). */
  54.243 -    if (!read_exact(io_fd, p2m_frame_list, sizeof(long))) {
  54.244 -        ERROR("read extended-info signature failed");
  54.245 -        goto out;
  54.246 -    }
  54.247 -
  54.248 -    if (p2m_frame_list[0] == ~0UL) {
  54.249 -        uint32_t tot_bytes;
  54.250 -
  54.251 -        /* Next 4 bytes: total size of following extended info. */
  54.252 -        if (!read_exact(io_fd, &tot_bytes, sizeof(tot_bytes))) {
  54.253 -            ERROR("read extended-info size failed");
  54.254 -            goto out;
  54.255 -        }
  54.256 -
  54.257 -        while (tot_bytes) {
  54.258 -            uint32_t chunk_bytes;
  54.259 -            char     chunk_sig[4];
  54.260 -
  54.261 -            /* 4-character chunk signature + 4-byte remaining chunk size. */
  54.262 -            if (!read_exact(io_fd, chunk_sig, sizeof(chunk_sig)) ||
  54.263 -                !read_exact(io_fd, &chunk_bytes, sizeof(chunk_bytes))) {
  54.264 -                ERROR("read extended-info chunk signature failed");
  54.265 -                goto out;
  54.266 -            }
  54.267 -            tot_bytes -= 8;
  54.268 -
  54.269 -            /* VCPU context structure? */
  54.270 -            if (!strncmp(chunk_sig, "vcpu", 4)) {
  54.271 -                if (!read_exact(io_fd, &ctxt, sizeof(ctxt))) {
  54.272 -                    ERROR("read extended-info vcpu context failed");
  54.273 -                    goto out;
  54.274 -                }
  54.275 -                tot_bytes   -= sizeof(struct vcpu_guest_context);
  54.276 -                chunk_bytes -= sizeof(struct vcpu_guest_context);
  54.277 -
  54.278 -                if (ctxt.vm_assist & (1UL << VMASST_TYPE_pae_extended_cr3))
  54.279 -                    pae_extended_cr3 = 1;
  54.280 -            }
  54.281 -
  54.282 -            /* Any remaining bytes of this chunk: read and discard. */
  54.283 -            while (chunk_bytes) {
  54.284 -                unsigned long sz = chunk_bytes;
  54.285 -                if ( sz > P2M_FL_SIZE )
  54.286 -                    sz = P2M_FL_SIZE;
  54.287 -                if (!read_exact(io_fd, p2m_frame_list, sz)) {
  54.288 -                    ERROR("read-and-discard extended-info chunk bytes failed");
  54.289 -                    goto out;
  54.290 -                }
  54.291 -                chunk_bytes -= sz;
  54.292 -                tot_bytes   -= sz;
  54.293 -            }
  54.294 -        }
  54.295 -
  54.296 -        /* Now read the real first entry of P2M list. */
  54.297 -        if (!read_exact(io_fd, p2m_frame_list, sizeof(long))) {
  54.298 -            ERROR("read first entry of p2m_frame_list failed");
  54.299 -            goto out;
  54.300 -        }
  54.301 -    }
  54.302 -
  54.303 -    /* First entry is already read into the p2m array. */
  54.304 -    if (!read_exact(io_fd, &p2m_frame_list[1], P2M_FL_SIZE - sizeof(long))) {
  54.305 -        ERROR("read p2m_frame_list failed");
  54.306 -        goto out;
  54.307 -    }
  54.308 -
  54.309 -    /* We want zeroed memory so use calloc rather than malloc. */
  54.310 -    p2m        = calloc(p2m_size, sizeof(xen_pfn_t));
  54.311 -    pfn_type   = calloc(p2m_size, sizeof(unsigned long));
  54.312 -    region_mfn = calloc(MAX_BATCH_SIZE, sizeof(xen_pfn_t));
  54.313 -    p2m_batch  = calloc(MAX_BATCH_SIZE, sizeof(xen_pfn_t));
  54.314 -
  54.315 -    if ((p2m == NULL) || (pfn_type == NULL) ||
  54.316 -        (region_mfn == NULL) || (p2m_batch == NULL)) {
  54.317 -        ERROR("memory alloc failed");
  54.318 -        errno = ENOMEM;
  54.319 -        goto out;
  54.320 -    }
  54.321 -
  54.322 -    if (lock_pages(region_mfn, sizeof(xen_pfn_t) * MAX_BATCH_SIZE)) {
  54.323 -        ERROR("Could not lock region_mfn");
  54.324 -        goto out;
  54.325 -    }
  54.326 -
  54.327 -    if (lock_pages(p2m_batch, sizeof(xen_pfn_t) * MAX_BATCH_SIZE)) {
  54.328 -        ERROR("Could not lock p2m_batch");
  54.329 -        goto out;
  54.330 -    }
  54.331 -
  54.332 -    /* Get the domain's shared-info frame. */
  54.333 -    domctl.cmd = XEN_DOMCTL_getdomaininfo;
  54.334 -    domctl.domain = (domid_t)dom;
  54.335 -    if (xc_domctl(xc_handle, &domctl) < 0) {
  54.336 -        ERROR("Could not get information on new domain");
  54.337 -        goto out;
  54.338 -    }
  54.339 -    shared_info_frame = domctl.u.getdomaininfo.shared_info_frame;
  54.340 -
  54.341 -    if (xc_domain_setmaxmem(xc_handle, dom, PFN_TO_KB(max_nr_pfns)) != 0) {
  54.342 -        errno = ENOMEM;
  54.343 -        goto out;
  54.344 -    }
  54.345 -
  54.346 -    /* Mark all PFNs as invalid; we allocate on demand */
  54.347 -    for ( pfn = 0; pfn < p2m_size; pfn++ )
  54.348 -        p2m[pfn] = INVALID_P2M_ENTRY;
  54.349 -
  54.350 -    if(!(mmu = xc_init_mmu_updates(xc_handle, dom))) {
  54.351 -        ERROR("Could not initialise for MMU updates");
  54.352 -        goto out;
  54.353 -    }
  54.354 -
  54.355 -    DPRINTF("Reloading memory pages:   0%%\n");
  54.356 -
  54.357 -    /*
  54.358 -     * Now simply read each saved frame into its new machine frame.
  54.359 -     * We uncanonicalise page tables as we go.
  54.360 -     */
  54.361 -    prev_pc = 0;
  54.362 -
  54.363 -    n = m = 0;
  54.364 -    while (1) {
  54.365 -
  54.366 -        int j, nr_mfns = 0; 
  54.367 -
  54.368 -        this_pc = (n * 100) / p2m_size;
  54.369 -        if ( (this_pc - prev_pc) >= 5 )
  54.370 -        {
  54.371 -            PPRINTF("\b\b\b\b%3d%%", this_pc);
  54.372 -            prev_pc = this_pc;
  54.373 -        }
  54.374 -
  54.375 -        if (!read_exact(io_fd, &j, sizeof(int))) {
  54.376 -            ERROR("Error when reading batch size");
  54.377 -            goto out;
  54.378 -        }
  54.379 -
  54.380 -        PPRINTF("batch %d\n",j);
  54.381 -
  54.382 -        if (j == -1) {
  54.383 -            verify = 1;
  54.384 -            DPRINTF("Entering page verify mode\n");
  54.385 -            continue;
  54.386 -        }
  54.387 -
  54.388 -        if (j == -2) {
  54.389 -            new_ctxt_format = 1;
  54.390 -            if (!read_exact(io_fd, &max_vcpu_id, sizeof(int)) ||
  54.391 -                (max_vcpu_id >= 64) ||
  54.392 -                !read_exact(io_fd, &vcpumap, sizeof(uint64_t))) {
  54.393 -                ERROR("Error when reading max_vcpu_id");
  54.394 -                goto out;
  54.395 -            }
  54.396 -            continue;
  54.397 -        }
  54.398 -
  54.399 -        if (j == 0)
  54.400 -            break;  /* our work here is done */
  54.401 -
  54.402 -        if (j > MAX_BATCH_SIZE) {
  54.403 -            ERROR("Max batch size exceeded. Giving up.");
  54.404 -            goto out;
  54.405 -        }
  54.406 -
  54.407 -        if (!read_exact(io_fd, region_pfn_type, j*sizeof(unsigned long))) {
  54.408 -            ERROR("Error when reading region pfn types");
  54.409 -            goto out;
  54.410 -        }
  54.411 -
  54.412 -        /* First pass for this batch: work out how much memory to alloc */
  54.413 -        nr_mfns = 0; 
  54.414 -        for ( i = 0; i < j; i++ )
  54.415 -        {
  54.416 -            unsigned long pfn, pagetype;
  54.417 -            pfn      = region_pfn_type[i] & ~XEN_DOMCTL_PFINFO_LTAB_MASK;
  54.418 -            pagetype = region_pfn_type[i] &  XEN_DOMCTL_PFINFO_LTAB_MASK;
  54.419 -
  54.420 -            if ( (pagetype != XEN_DOMCTL_PFINFO_XTAB) && 
  54.421 -                 (p2m[pfn] == INVALID_P2M_ENTRY) )
  54.422 -            {
  54.423 -                /* Have a live PFN which hasn't had an MFN allocated */
  54.424 -                p2m_batch[nr_mfns++] = pfn; 
  54.425 -            }
  54.426 -        } 
  54.427 -
  54.428 -
  54.429 -        /* Now allocate a bunch of mfns for this batch */
  54.430 -        if (nr_mfns && xc_domain_memory_populate_physmap(
  54.431 -                xc_handle, dom, nr_mfns, 0, 0, p2m_batch) != 0) { 
  54.432 -            ERROR("Failed to allocate memory for batch.!\n"); 
  54.433 -            errno = ENOMEM;
  54.434 -            goto out;
  54.435 -        }
  54.436 -
  54.437 -        /* Second pass for this batch: update p2m[] and region_mfn[] */
  54.438 -        nr_mfns = 0; 
  54.439 -        for ( i = 0; i < j; i++ )
  54.440 -        {
  54.441 -            unsigned long pfn, pagetype;
  54.442 -            pfn      = region_pfn_type[i] & ~XEN_DOMCTL_PFINFO_LTAB_MASK;
  54.443 -            pagetype = region_pfn_type[i] &  XEN_DOMCTL_PFINFO_LTAB_MASK;
  54.444 -
  54.445 -            if ( pagetype == XEN_DOMCTL_PFINFO_XTAB)
  54.446 -                region_mfn[i] = ~0UL; /* map will fail but we don't care */
  54.447 -            else 
  54.448 -            {
  54.449 -                if (p2m[pfn] == INVALID_P2M_ENTRY) {
  54.450 -                    /* We just allocated a new mfn above; update p2m */
  54.451 -                    p2m[pfn] = p2m_batch[nr_mfns++]; 
  54.452 -                    nr_pfns++; 
  54.453 -                }
  54.454 -
  54.455 -                /* setup region_mfn[] for batch map */
  54.456 -                region_mfn[i] = p2m[pfn]; 
  54.457 -            }
  54.458 -        } 
  54.459 -
  54.460 -        /* Map relevant mfns */
  54.461 -        region_base = xc_map_foreign_batch(
  54.462 -            xc_handle, dom, PROT_WRITE, region_mfn, j);
  54.463 -
  54.464 -        if ( region_base == NULL )
  54.465 -        {
  54.466 -            ERROR("map batch failed");
  54.467 -            goto out;
  54.468 -        }
  54.469 -
  54.470 -        for ( i = 0; i < j; i++ )
  54.471 -        {
  54.472 -            void *page;
  54.473 -            unsigned long pagetype;
  54.474 -
  54.475 -            pfn      = region_pfn_type[i] & ~XEN_DOMCTL_PFINFO_LTAB_MASK;
  54.476 -            pagetype = region_pfn_type[i] &  XEN_DOMCTL_PFINFO_LTAB_MASK;
  54.477 -
  54.478 -            if ( pagetype == XEN_DOMCTL_PFINFO_XTAB )
  54.479 -                /* a bogus/unmapped page: skip it */
  54.480 -                continue;
  54.481 -
  54.482 -            if ( pfn > p2m_size )
  54.483 -            {
  54.484 -                ERROR("pfn out of range");
  54.485 -                goto out;
  54.486 -            }
  54.487 -
  54.488 -            pfn_type[pfn] = pagetype;
  54.489 -
  54.490 -            mfn = p2m[pfn];
  54.491 -
  54.492 -            /* In verify mode, we use a copy; otherwise we work in place */
  54.493 -            page = verify ? (void *)buf : (region_base + i*PAGE_SIZE);
  54.494 -
  54.495 -            if (!read_exact(io_fd, page, PAGE_SIZE)) {
  54.496 -                ERROR("Error when reading page (type was %lx)", pagetype);
  54.497 -                goto out;
  54.498 -            }
  54.499 -
  54.500 -            pagetype &= XEN_DOMCTL_PFINFO_LTABTYPE_MASK;
  54.501 -
  54.502 -            if ( (pagetype >= XEN_DOMCTL_PFINFO_L1TAB) && 
  54.503 -                 (pagetype <= XEN_DOMCTL_PFINFO_L4TAB) )
  54.504 -            {
  54.505 -                /*
  54.506 -                ** A page table page - need to 'uncanonicalize' it, i.e.
  54.507 -                ** replace all the references to pfns with the corresponding
  54.508 -                ** mfns for the new domain.
  54.509 -                **
  54.510 -                ** On PAE we need to ensure that PGDs are in MFNs < 4G, and
  54.511 -                ** so we may need to update the p2m after the main loop.
  54.512 -                ** Hence we defer canonicalization of L1s until then.
  54.513 -                */
  54.514 -                if ((pt_levels != 3) ||
  54.515 -                    pae_extended_cr3 ||
  54.516 -                    (pagetype != XEN_DOMCTL_PFINFO_L1TAB)) {
  54.517 -
  54.518 -                    if (!uncanonicalize_pagetable(xc_handle, dom, 
  54.519 -                                                  pagetype, page)) {
  54.520 -                        /*
  54.521 -                        ** Failing to uncanonicalize a page table can be ok
  54.522 -                        ** under live migration since the pages type may have
  54.523 -                        ** changed by now (and we'll get an update later).
  54.524 -                        */
  54.525 -                        DPRINTF("PT L%ld race on pfn=%08lx mfn=%08lx\n",
  54.526 -                                pagetype >> 28, pfn, mfn);
  54.527 -                        nraces++;
  54.528 -                        continue;
  54.529 -                    } 
  54.530 -                }
  54.531 -            }
  54.532 -            else if ( pagetype != XEN_DOMCTL_PFINFO_NOTAB )
  54.533 -            {
  54.534 -                ERROR("Bogus page type %lx page table is out of range: "
  54.535 -                    "i=%d p2m_size=%lu", pagetype, i, p2m_size);
  54.536 -                goto out;
  54.537 -
  54.538 -            }
  54.539 -
  54.540 -
  54.541 -            if (verify) {
  54.542 -
  54.543 -                int res = memcmp(buf, (region_base + i*PAGE_SIZE), PAGE_SIZE);
  54.544 -
  54.545 -                if (res) {
  54.546 -
  54.547 -                    int v;
  54.548 -
  54.549 -                    DPRINTF("************** pfn=%lx type=%lx gotcs=%08lx "
  54.550 -                            "actualcs=%08lx\n", pfn, pfn_type[pfn],
  54.551 -                            csum_page(region_base + i*PAGE_SIZE),
  54.552 -                            csum_page(buf));
  54.553 -
  54.554 -                    for (v = 0; v < 4; v++) {
  54.555 -
  54.556 -                        unsigned long *p = (unsigned long *)
  54.557 -                            (region_base + i*PAGE_SIZE);
  54.558 -                        if (buf[v] != p[v])
  54.559 -                            DPRINTF("    %d: %08lx %08lx\n", v, buf[v], p[v]);
  54.560 -                    }
  54.561 -                }
  54.562 -            }
  54.563 -
  54.564 -            if (xc_add_mmu_update(xc_handle, mmu,
  54.565 -                                  (((unsigned long long)mfn) << PAGE_SHIFT)
  54.566 -                                  | MMU_MACHPHYS_UPDATE, pfn)) {
  54.567 -                ERROR("failed machpys update mfn=%lx pfn=%lx", mfn, pfn);
  54.568 -                goto out;
  54.569 -            }
  54.570 -        } /* end of 'batch' for loop */
  54.571 -
  54.572 -        munmap(region_base, j*PAGE_SIZE);
  54.573 -        n+= j; /* crude stats */
  54.574 -
  54.575 -        /* 
  54.576 -         * Discard cache for portion of file read so far up to last
  54.577 -         *  page boundary every 16MB or so.
  54.578 -         */
  54.579 -        m += j;
  54.580 -        if ( m > MAX_PAGECACHE_USAGE )
  54.581 -        {
  54.582 -            discard_file_cache(io_fd, 0 /* no flush */);
  54.583 -            m = 0;
  54.584 -        }
  54.585 -    }
  54.586 -
  54.587 -    /*
  54.588 -     * Ensure we flush all machphys updates before potential PAE-specific
  54.589 -     * reallocations below.
  54.590 -     */
  54.591 -    if (xc_finish_mmu_updates(xc_handle, mmu)) {
  54.592 -        ERROR("Error doing finish_mmu_updates()");
  54.593 -        goto out;
  54.594 -    }
  54.595 -
  54.596 -    DPRINTF("Received all pages (%d races)\n", nraces);
  54.597 -
  54.598 -    if ((pt_levels == 3) && !pae_extended_cr3) {
  54.599 -
  54.600 -        /*
  54.601 -        ** XXX SMH on PAE we need to ensure PGDs are in MFNs < 4G. This
  54.602 -        ** is a little awkward and involves (a) finding all such PGDs and
  54.603 -        ** replacing them with 'lowmem' versions; (b) upating the p2m[]
  54.604 -        ** with the new info; and (c) canonicalizing all the L1s using the
  54.605 -        ** (potentially updated) p2m[].
  54.606 -        **
  54.607 -        ** This is relatively slow (and currently involves two passes through
  54.608 -        ** the pfn_type[] array), but at least seems to be correct. May wish
  54.609 -        ** to consider more complex approaches to optimize this later.
  54.610 -        */
  54.611 -
  54.612 -        int j, k;
  54.613 -        
  54.614 -        /* First pass: find all L3TABs current in > 4G mfns and get new mfns */
  54.615 -        for ( i = 0; i < p2m_size; i++ )
  54.616 -        {
  54.617 -            if ( ((pfn_type[i] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK) ==
  54.618 -                  XEN_DOMCTL_PFINFO_L3TAB) &&
  54.619 -                 (p2m[i] > 0xfffffUL) )
  54.620 -            {
  54.621 -                unsigned long new_mfn;
  54.622 -                uint64_t l3ptes[4];
  54.623 -                uint64_t *l3tab;
  54.624 -
  54.625 -                l3tab = (uint64_t *)
  54.626 -                    xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
  54.627 -                                         PROT_READ, p2m[i]);
  54.628 -
  54.629 -                for(j = 0; j < 4; j++)
  54.630 -                    l3ptes[j] = l3tab[j];
  54.631 -
  54.632 -                munmap(l3tab, PAGE_SIZE);
  54.633 -
  54.634 -                if (!(new_mfn=xc_make_page_below_4G(xc_handle, dom, p2m[i]))) {
  54.635 -                    ERROR("Couldn't get a page below 4GB :-(");
  54.636 -                    goto out;
  54.637 -                }
  54.638 -
  54.639 -                p2m[i] = new_mfn;
  54.640 -                if (xc_add_mmu_update(xc_handle, mmu,
  54.641 -                                      (((unsigned long long)new_mfn)
  54.642 -                                       << PAGE_SHIFT) |
  54.643 -                                      MMU_MACHPHYS_UPDATE, i)) {
  54.644 -                    ERROR("Couldn't m2p on PAE root pgdir");
  54.645 -                    goto out;
  54.646 -                }
  54.647 -
  54.648 -                l3tab = (uint64_t *)
  54.649 -                    xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
  54.650 -                                         PROT_READ | PROT_WRITE, p2m[i]);
  54.651 -
  54.652 -                for(j = 0; j < 4; j++)
  54.653 -                    l3tab[j] = l3ptes[j];
  54.654 -
  54.655 -                munmap(l3tab, PAGE_SIZE);
  54.656 -
  54.657 -            }
  54.658 -        }
  54.659 -
  54.660 -        /* Second pass: find all L1TABs and uncanonicalize them */
  54.661 -        j = 0;
  54.662 -
  54.663 -        for ( i = 0; i < p2m_size; i++ )
  54.664 -        {
  54.665 -            if ( ((pfn_type[i] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK) ==
  54.666 -                  XEN_DOMCTL_PFINFO_L1TAB) )
  54.667 -            {
  54.668 -                region_mfn[j] = p2m[i];
  54.669 -                j++;
  54.670 -            }
  54.671 -
  54.672 -            if(i == (p2m_size-1) || j == MAX_BATCH_SIZE) {
  54.673 -
  54.674 -                if (!(region_base = xc_map_foreign_batch(
  54.675 -                          xc_handle, dom, PROT_READ | PROT_WRITE,
  54.676 -                          region_mfn, j))) {
  54.677 -                    ERROR("map batch failed");
  54.678 -                    goto out;
  54.679 -                }
  54.680 -
  54.681 -                for(k = 0; k < j; k++) {
  54.682 -                    if(!uncanonicalize_pagetable(xc_handle, dom, 
  54.683 -                                                 XEN_DOMCTL_PFINFO_L1TAB,
  54.684 -                                                 region_base + k*PAGE_SIZE)) {
  54.685 -                        ERROR("failed uncanonicalize pt!");
  54.686 -                        goto out;
  54.687 -                    }
  54.688 -                }
  54.689 -
  54.690 -                munmap(region_base, j*PAGE_SIZE);
  54.691 -                j = 0;
  54.692 -            }
  54.693 -        }
  54.694 -
  54.695 -        if (xc_finish_mmu_updates(xc_handle, mmu)) {
  54.696 -            ERROR("Error doing finish_mmu_updates()");
  54.697 -            goto out;
  54.698 -        }
  54.699 -    }
  54.700 -
  54.701 -    /*
  54.702 -     * Pin page tables. Do this after writing to them as otherwise Xen
  54.703 -     * will barf when doing the type-checking.
  54.704 -     */
  54.705 -    nr_pins = 0;
  54.706 -    for ( i = 0; i < p2m_size; i++ )
  54.707 -    {
  54.708 -        if ( (pfn_type[i] & XEN_DOMCTL_PFINFO_LPINTAB) == 0 )
  54.709 -            continue;
  54.710 -
  54.711 -        switch ( pfn_type[i] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK )
  54.712 -        {
  54.713 -        case XEN_DOMCTL_PFINFO_L1TAB:
  54.714 -            pin[nr_pins].cmd = MMUEXT_PIN_L1_TABLE;
  54.715 -            break;
  54.716 -
  54.717 -        case XEN_DOMCTL_PFINFO_L2TAB:
  54.718 -            pin[nr_pins].cmd = MMUEXT_PIN_L2_TABLE;
  54.719 -            break;
  54.720 -
  54.721 -        case XEN_DOMCTL_PFINFO_L3TAB:
  54.722 -            pin[nr_pins].cmd = MMUEXT_PIN_L3_TABLE;
  54.723 -            break;
  54.724 -
  54.725 -        case XEN_DOMCTL_PFINFO_L4TAB:
  54.726 -            pin[nr_pins].cmd = MMUEXT_PIN_L4_TABLE;
  54.727 -            break;
  54.728 -
  54.729 -        default:
  54.730 -            continue;
  54.731 -        }
  54.732 -
  54.733 -        pin[nr_pins].arg1.mfn = p2m[i];
  54.734 -        nr_pins++;
  54.735 -
  54.736 -        /* Batch full? Then flush. */
  54.737 -        if (nr_pins == MAX_PIN_BATCH) {
  54.738 -            if (xc_mmuext_op(xc_handle, pin, nr_pins, dom) < 0) {
  54.739 -                ERROR("Failed to pin batch of %d page tables", nr_pins);
  54.740 -                goto out;
  54.741 -            }
  54.742 -            nr_pins = 0;
  54.743 -        }
  54.744 -    }
  54.745 -
  54.746 -    /* Flush final partial batch. */
  54.747 -    if ((nr_pins != 0) && (xc_mmuext_op(xc_handle, pin, nr_pins, dom) < 0)) {
  54.748 -        ERROR("Failed to pin batch of %d page tables", nr_pins);
  54.749 -        goto out;
  54.750 -    }
  54.751 -
  54.752 -    DPRINTF("\b\b\b\b100%%\n");
  54.753 -    DPRINTF("Memory reloaded (%ld pages of max %ld)\n", nr_pfns, max_nr_pfns);
  54.754 -
  54.755 -    /* Get the list of PFNs that are not in the psuedo-phys map */
  54.756 -    {
  54.757 -        unsigned int count;
  54.758 -        unsigned long *pfntab;
  54.759 -        int nr_frees, rc;
  54.760 -
  54.761 -        if (!read_exact(io_fd, &count, sizeof(count))) {
  54.762 -            ERROR("Error when reading pfn count");
  54.763 -            goto out;
  54.764 -        }
  54.765 -
  54.766 -        if(!(pfntab = malloc(sizeof(unsigned long) * count))) {
  54.767 -            ERROR("Out of memory");
  54.768 -            goto out;
  54.769 -        }
  54.770 -
  54.771 -        if (!read_exact(io_fd, pfntab, sizeof(unsigned long)*count)) {
  54.772 -            ERROR("Error when reading pfntab");
  54.773 -            goto out;
  54.774 -        }
  54.775 -
  54.776 -        nr_frees = 0; 
  54.777 -        for (i = 0; i < count; i++) {
  54.778 -
  54.779 -            unsigned long pfn = pfntab[i];
  54.780 -
  54.781 -            if(p2m[pfn] != INVALID_P2M_ENTRY) {
  54.782 -                /* pfn is not in physmap now, but was at some point during 
  54.783 -                   the save/migration process - need to free it */
  54.784 -                pfntab[nr_frees++] = p2m[pfn];
  54.785 -                p2m[pfn]  = INVALID_P2M_ENTRY; // not in pseudo-physical map
  54.786 -            }
  54.787 -        }
  54.788 -
  54.789 -        if (nr_frees > 0) {
  54.790 -
  54.791 -            struct xen_memory_reservation reservation = {
  54.792 -                .nr_extents   = nr_frees,
  54.793 -                .extent_order = 0,
  54.794 -                .domid        = dom
  54.795 -            };
  54.796 -            set_xen_guest_handle(reservation.extent_start, pfntab);
  54.797 -
  54.798 -            if ((rc = xc_memory_op(xc_handle, XENMEM_decrease_reservation,
  54.799 -                                   &reservation)) != nr_frees) {
  54.800 -                ERROR("Could not decrease reservation : %d", rc);
  54.801 -                goto out;
  54.802 -            } else
  54.803 -                DPRINTF("Decreased reservation by %d pages\n", count);
  54.804 -        }
  54.805 -    }
  54.806 -
  54.807 -    for (i = 0; i <= max_vcpu_id; i++) {
  54.808 -        if (!(vcpumap & (1ULL << i)))
  54.809 -            continue;
  54.810 -
  54.811 -        if (!read_exact(io_fd, &ctxt, sizeof(ctxt))) {
  54.812 -            ERROR("Error when reading ctxt %d", i);
  54.813 -            goto out;
  54.814 -        }
  54.815 -
  54.816 -        if ( !new_ctxt_format )
  54.817 -            ctxt.flags |= VGCF_online;
  54.818 -
  54.819 -        if (i == 0) {
  54.820 -            /*
  54.821 -             * Uncanonicalise the suspend-record frame number and poke
  54.822 -             * resume record.
  54.823 -             */
  54.824 -            pfn = ctxt.user_regs.edx;
  54.825 -            if ((pfn >= p2m_size) ||
  54.826 -                (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB)) {
  54.827 -                ERROR("Suspend record frame number is bad");
  54.828 -                goto out;
  54.829 -            }
  54.830 -            ctxt.user_regs.edx = mfn = p2m[pfn];
  54.831 -            start_info = xc_map_foreign_range(
  54.832 -                xc_handle, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, mfn);
  54.833 -            start_info->nr_pages = p2m_size;
  54.834 -            start_info->shared_info = shared_info_frame << PAGE_SHIFT;
  54.835 -            start_info->flags = 0;
  54.836 -            *store_mfn = start_info->store_mfn = p2m[start_info->store_mfn];
  54.837 -            start_info->store_evtchn = store_evtchn;
  54.838 -            start_info->console.domU.mfn = p2m[start_info->console.domU.mfn];
  54.839 -            start_info->console.domU.evtchn = console_evtchn;
  54.840 -            *console_mfn = start_info->console.domU.mfn;
  54.841 -            munmap(start_info, PAGE_SIZE);
  54.842 -        }
  54.843 -
  54.844 -        /* Uncanonicalise each GDT frame number. */
  54.845 -        if (ctxt.gdt_ents > 8192) {
  54.846 -            ERROR("GDT entry count out of range");
  54.847 -            goto out;
  54.848 -        }
  54.849 -
  54.850 -        for (j = 0; (512*j) < ctxt.gdt_ents; j++) {
  54.851 -            pfn = ctxt.gdt_frames[j];
  54.852 -            if ((pfn >= p2m_size) ||
  54.853 -                (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB)) {
  54.854 -                ERROR("GDT frame number is bad");
  54.855 -                goto out;
  54.856 -            }
  54.857 -            ctxt.gdt_frames[j] = p2m[pfn];
  54.858 -        }
  54.859 -
  54.860 -        /* Uncanonicalise the page table base pointer. */
  54.861 -        pfn = xen_cr3_to_pfn(ctxt.ctrlreg[3]);
  54.862 -
  54.863 -        if (pfn >= p2m_size) {
  54.864 -            ERROR("PT base is bad: pfn=%lu p2m_size=%lu type=%08lx",
  54.865 -                  pfn, p2m_size, pfn_type[pfn]);
  54.866 -            goto out;
  54.867 -        }
  54.868 -
  54.869 -        if ( (pfn_type[pfn] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK) !=
  54.870 -             ((unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT) ) {
  54.871 -            ERROR("PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx",
  54.872 -                  pfn, p2m_size, pfn_type[pfn],
  54.873 -                  (unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT);
  54.874 -            goto out;
  54.875 -        }
  54.876 -
  54.877 -        ctxt.ctrlreg[3] = xen_pfn_to_cr3(p2m[pfn]);
  54.878 -
  54.879 -        /* Guest pagetable (x86/64) stored in otherwise-unused CR1. */
  54.880 -        if ( (pt_levels == 4) && ctxt.ctrlreg[1] )
  54.881 -        {
  54.882 -            pfn = xen_cr3_to_pfn(ctxt.ctrlreg[1]);
  54.883 -
  54.884 -            if (pfn >= p2m_size) {
  54.885 -                ERROR("User PT base is bad: pfn=%lu p2m_size=%lu type=%08lx",
  54.886 -                      pfn, p2m_size, pfn_type[pfn]);
  54.887 -                goto out;
  54.888 -            }
  54.889 -
  54.890 -            if ( (pfn_type[pfn] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK) !=
  54.891 -                 ((unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT) ) {
  54.892 -                ERROR("User PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx",
  54.893 -                      pfn, p2m_size, pfn_type[pfn],
  54.894 -                      (unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT);
  54.895 -                goto out;
  54.896 -            }
  54.897 -
  54.898 -            ctxt.ctrlreg[1] = xen_pfn_to_cr3(p2m[pfn]);
  54.899 -        }
  54.900 -
  54.901 -        domctl.cmd = XEN_DOMCTL_setvcpucontext;
  54.902 -        domctl.domain = (domid_t)dom;
  54.903 -        domctl.u.vcpucontext.vcpu = i;
  54.904 -        set_xen_guest_handle(domctl.u.vcpucontext.ctxt, &ctxt);
  54.905 -        rc = xc_domctl(xc_handle, &domctl);
  54.906 -        if (rc != 0) {
  54.907 -            ERROR("Couldn't build vcpu%d", i);
  54.908 -            goto out;
  54.909 -        }
  54.910 -    }
  54.911 -
  54.912 -    if (!read_exact(io_fd, shared_info_page, PAGE_SIZE)) {
  54.913 -        ERROR("Error when reading shared info page");
  54.914 -        goto out;
  54.915 -    }
  54.916 -
  54.917 -    /* clear any pending events and the selector */
  54.918 -    memset(&(shared_info->evtchn_pending[0]), 0,
  54.919 -           sizeof (shared_info->evtchn_pending));
  54.920 -    for ( i = 0; i < MAX_VIRT_CPUS; i++ )
  54.921 -        shared_info->vcpu_info[i].evtchn_pending_sel = 0;
  54.922 -
  54.923 -    /* Copy saved contents of shared-info page. No checking needed. */
  54.924 -    page = xc_map_foreign_range(
  54.925 -        xc_handle, dom, PAGE_SIZE, PROT_WRITE, shared_info_frame);
  54.926 -    memcpy(page, shared_info, PAGE_SIZE);
  54.927 -    munmap(page, PAGE_SIZE);
  54.928 -
  54.929 -    /* Uncanonicalise the pfn-to-mfn table frame-number list. */
  54.930 -    for (i = 0; i < P2M_FL_ENTRIES; i++) {
  54.931 -        pfn = p2m_frame_list[i];
  54.932 -        if ((pfn >= p2m_size) || (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB)) {
  54.933 -            ERROR("PFN-to-MFN frame number is bad");
  54.934 -            goto out;
  54.935 -        }
  54.936 -
  54.937 -        p2m_frame_list[i] = p2m[pfn];
  54.938 -    }
  54.939 -
  54.940 -    /* Copy the P2M we've constructed to the 'live' P2M */
  54.941 -    if (!(live_p2m = xc_map_foreign_batch(xc_handle, dom, PROT_WRITE,
  54.942 -                                          p2m_frame_list, P2M_FL_ENTRIES))) {
  54.943 -        ERROR("Couldn't map p2m table");
  54.944 -        goto out;
  54.945 -    }
  54.946 -
  54.947 -    memcpy(live_p2m, p2m, ROUNDUP(p2m_size * sizeof(xen_pfn_t), PAGE_SHIFT));
  54.948 -    munmap(live_p2m, ROUNDUP(p2m_size * sizeof(xen_pfn_t), PAGE_SHIFT));
  54.949 -
  54.950 -    DPRINTF("Domain ready to be built.\n");
  54.951 -
  54.952 - out:
  54.953 -    if ( (rc != 0) && (dom != 0) )
  54.954 -        xc_domain_destroy(xc_handle, dom);
  54.955 -    free(mmu);
  54.956 -    free(p2m);
  54.957 -    free(pfn_type);
  54.958 -
  54.959 -    /* discard cache for save file  */
  54.960 -    discard_file_cache(io_fd, 1 /*flush*/);
  54.961 -
  54.962 -    DPRINTF("Restore exit with rc=%d\n", rc);
  54.963 -    
  54.964 -    return rc;
  54.965 -}
    55.1 --- a/tools/libxc/xenguest.h	Fri Apr 06 10:06:30 2007 -0600
    55.2 +++ b/tools/libxc/xenguest.h	Fri Apr 06 10:08:30 2007 -0600
    55.3 @@ -38,32 +38,21 @@ int xc_hvm_save(int xc_handle, int io_fd
    55.4                  void (*qemu_flip_buffer)(int, int));
    55.5  
    55.6  /**
    55.7 - * This function will restore a saved domain running Linux.
    55.8 + * This function will restore a saved domain.
    55.9   *
   55.10   * @parm xc_handle a handle to an open hypervisor interface
   55.11   * @parm fd the file descriptor to restore a domain from
   55.12   * @parm dom the id of the domain
   55.13 - * @parm p2m_size number of pages the guest has (i.e. number entries in P2M)
   55.14 - * @parm max_nr_pfns domains maximum real memory allocation, in pages
   55.15   * @parm store_evtchn the store event channel for this domain to use
   55.16   * @parm store_mfn returned with the mfn of the store page
   55.17 + * @parm hvm non-zero if this is a HVM restore
   55.18 + * @parm pae non-zero if this HVM domain has PAE support enabled
   55.19   * @return 0 on success, -1 on failure
   55.20   */
   55.21 -int xc_linux_restore(int xc_handle, int io_fd, uint32_t dom,
   55.22 -                     unsigned long p2m_size, unsigned long max_nr_pfns,
   55.23 -                     unsigned int store_evtchn, unsigned long *store_mfn,
   55.24 -                     unsigned int console_evtchn, unsigned long *console_mfn);
   55.25 -
   55.26 -/**
   55.27 - * This function will restore a saved hvm domain running unmodified guest.
   55.28 - *
   55.29 - * @parm store_mfn pass mem size & returned with the mfn of the store page
   55.30 - * @return 0 on success, -1 on failure
   55.31 - */
   55.32 -int xc_hvm_restore(int xc_handle, int io_fd, uint32_t dom,
   55.33 -                      unsigned long max_pfn, unsigned int store_evtchn,
   55.34 -                      unsigned long *store_mfn, 
   55.35 -                      unsigned int pae, unsigned int apic);
   55.36 +int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom,
   55.37 +                      unsigned int store_evtchn, unsigned long *store_mfn,
   55.38 +                      unsigned int console_evtchn, unsigned long *console_mfn,
   55.39 +                      unsigned int hvm, unsigned int pae);
   55.40  
   55.41  /**
   55.42   * This function will create a domain for a paravirtualized Linux
   55.43 @@ -159,8 +148,6 @@ int xc_set_hvm_param(
   55.44  int xc_get_hvm_param(
   55.45      int handle, domid_t dom, int param, unsigned long *value);
   55.46  
   55.47 -int xc_hvm_drain_io(int handle, domid_t dom);
   55.48 -
   55.49  /* PowerPC specific. */
   55.50  int xc_prose_build(int xc_handle,
   55.51                     uint32_t domid,
    56.1 --- a/tools/libxc/xg_private.c	Fri Apr 06 10:06:30 2007 -0600
    56.2 +++ b/tools/libxc/xg_private.c	Fri Apr 06 10:08:30 2007 -0600
    56.3 @@ -209,16 +209,6 @@ unsigned long csum_page(void *page)
    56.4      return -1;
    56.5  }
    56.6  
    56.7 -__attribute__((weak)) 
    56.8 -    int xc_hvm_restore(int xc_handle, int io_fd, uint32_t dom,
    56.9 -                       unsigned long max_pfn, unsigned int store_evtchn,
   56.10 -                       unsigned long *store_mfn,
   56.11 -                       unsigned int pae, unsigned int apic)
   56.12 -{
   56.13 -    errno = ENOSYS;
   56.14 -    return -1;
   56.15 -}
   56.16 -
   56.17  __attribute__((weak)) int xc_get_hvm_param(
   56.18      int handle, domid_t dom, int param, unsigned long *value)
   56.19  {
   56.20 @@ -231,11 +221,6 @@ unsigned long csum_page(void *page)
   56.21      return -ENOSYS;
   56.22  }
   56.23  
   56.24 -__attribute__((weak)) int xc_hvm_drain_io(int handle, domid_t dom)
   56.25 -{
   56.26 -    return -ENOSYS;
   56.27 -}
   56.28 -
   56.29  /*
   56.30   * Local variables:
   56.31   * mode: C
    57.1 --- a/tools/libxen/include/xen_host.h	Fri Apr 06 10:06:30 2007 -0600
    57.2 +++ b/tools/libxen/include/xen_host.h	Fri Apr 06 10:08:30 2007 -0600
    57.3 @@ -436,6 +436,13 @@ xen_host_dmesg(xen_session *session, cha
    57.4  
    57.5  
    57.6  /**
    57.7 + * List all supported methods.
    57.8 + */
    57.9 +extern bool
   57.10 +xen_host_list_methods(xen_session *session, struct xen_string_set **result);
   57.11 +
   57.12 +
   57.13 +/**
   57.14   * Return a list of all the hosts known to the system.
   57.15   */
   57.16  extern bool
    58.1 --- a/tools/libxen/include/xen_sr.h	Fri Apr 06 10:06:30 2007 -0600
    58.2 +++ b/tools/libxen/include/xen_sr.h	Fri Apr 06 10:08:30 2007 -0600
    58.3 @@ -1,5 +1,5 @@
    58.4  /*
    58.5 - * Copyright (c) 2006, XenSource Inc.
    58.6 + * Copyright (c) 2006-2007, XenSource Inc.
    58.7   *
    58.8   * This library is free software; you can redistribute it and/or
    58.9   * modify it under the terms of the GNU Lesser General Public
   58.10 @@ -22,6 +22,7 @@
   58.11  #include "xen_common.h"
   58.12  #include "xen_pbd_decl.h"
   58.13  #include "xen_sr_decl.h"
   58.14 +#include "xen_string_set.h"
   58.15  #include "xen_vdi_decl.h"
   58.16  
   58.17  
   58.18 @@ -72,7 +73,7 @@ typedef struct xen_sr_record
   58.19      int64_t physical_utilisation;
   58.20      int64_t physical_size;
   58.21      char *type;
   58.22 -    char *location;
   58.23 +    char *content_type;
   58.24  } xen_sr_record;
   58.25  
   58.26  /**
   58.27 @@ -169,20 +170,6 @@ xen_sr_get_by_uuid(xen_session *session,
   58.28  
   58.29  
   58.30  /**
   58.31 - * Create a new SR instance, and return its handle.
   58.32 - */
   58.33 -extern bool
   58.34 -xen_sr_create(xen_session *session, xen_sr *result, xen_sr_record *record);
   58.35 -
   58.36 -
   58.37 -/**
   58.38 - * Destroy the specified SR instance.
   58.39 - */
   58.40 -extern bool
   58.41 -xen_sr_destroy(xen_session *session, xen_sr sr);
   58.42 -
   58.43 -
   58.44 -/**
   58.45   * Get all the SR instances with the given label.
   58.46   */
   58.47  extern bool
   58.48 @@ -253,10 +240,10 @@ xen_sr_get_type(xen_session *session, ch
   58.49  
   58.50  
   58.51  /**
   58.52 - * Get the location field of the given SR.
   58.53 + * Get the content_type field of the given SR.
   58.54   */
   58.55  extern bool
   58.56 -xen_sr_get_location(xen_session *session, char **result, xen_sr sr);
   58.57 +xen_sr_get_content_type(xen_session *session, char **result, xen_sr sr);
   58.58  
   58.59  
   58.60  /**
   58.61 @@ -274,11 +261,10 @@ xen_sr_set_name_description(xen_session 
   58.62  
   58.63  
   58.64  /**
   58.65 - * Take an exact copy of the Storage Repository; the cloned storage
   58.66 - * repository has the same type as its parent
   58.67 + * Return a set of all the SR types supported by the system.
   58.68   */
   58.69  extern bool
   58.70 -xen_sr_clone(xen_session *session, xen_sr *result, xen_sr sr, char *loc, char *name);
   58.71 +xen_sr_get_supported_types(xen_session *session, struct xen_string_set **result);
   58.72  
   58.73  
   58.74  /**
    59.1 --- a/tools/libxen/include/xen_vdi.h	Fri Apr 06 10:06:30 2007 -0600
    59.2 +++ b/tools/libxen/include/xen_vdi.h	Fri Apr 06 10:08:30 2007 -0600
    59.3 @@ -338,21 +338,6 @@ xen_vdi_remove_from_other_config(xen_ses
    59.4  
    59.5  
    59.6  /**
    59.7 - * Take an exact copy of the VDI; the snapshot lives in the same
    59.8 - * Storage Repository as its parent.
    59.9 - */
   59.10 -extern bool
   59.11 -xen_vdi_snapshot(xen_session *session, xen_vdi *result, xen_vdi vdi);
   59.12 -
   59.13 -
   59.14 -/**
   59.15 - * Resize the vdi to the size.
   59.16 - */
   59.17 -extern bool
   59.18 -xen_vdi_resize(xen_session *session, xen_vdi vdi, int64_t size);
   59.19 -
   59.20 -
   59.21 -/**
   59.22   * Return a list of all the VDIs known to the system.
   59.23   */
   59.24  extern bool
    60.1 --- a/tools/libxen/src/xen_common.c	Fri Apr 06 10:06:30 2007 -0600
    60.2 +++ b/tools/libxen/src/xen_common.c	Fri Apr 06 10:08:30 2007 -0600
    60.3 @@ -102,6 +102,9 @@ add_struct_value(const struct abstract_t
    60.4                            const char *),
    60.5                   const char *, xmlNode *);
    60.6  
    60.7 +static xmlNode *
    60.8 +add_container(xmlNode *parent, const char *name);
    60.9 +
   60.10  static void
   60.11  call_raw(xen_session *, const char *, abstract_value [], int,
   60.12           const abstract_type *, void *);
   60.13 @@ -1290,6 +1293,48 @@ make_body_add_type(enum abstract_typenam
   60.14      }
   60.15      break;
   60.16  
   60.17 +    case MAP:
   60.18 +    {
   60.19 +        const struct struct_member *member = v->type->members;
   60.20 +        arbitrary_map *map_val = v->u.struct_val;
   60.21 +        xmlNode *param_node = add_param_struct(params_node);
   60.22 +        for (size_t i = 0; i < map_val->size; i++) {
   60.23 +            enum abstract_typename typename_key = member[0].type->typename;
   60.24 +            enum abstract_typename typename_val = member[1].type->typename;
   60.25 +            int offset_key = member[0].offset;
   60.26 +            int offset_val = member[1].offset;
   60.27 +            int struct_size = v->type->struct_size;
   60.28 +
   60.29 +            switch (typename_key) {
   60.30 +            case STRING: {
   60.31 +                char **addr = (void *)(map_val + 1) +
   60.32 +                             (i * struct_size) +
   60.33 +                             offset_key;
   60.34 +                char *key = *addr;
   60.35 +
   60.36 +                switch (typename_val) {
   60.37 +                case STRING: {
   60.38 +                    char *val;
   60.39 +                    addr = (void *)(map_val + 1) +
   60.40 +                           (i * struct_size) +
   60.41 +                           offset_val;
   60.42 +                    val = *addr;
   60.43 +                    add_struct_member(param_node, key, "string", val);
   60.44 +                    break;
   60.45 +                }
   60.46 +                default:
   60.47 +                    assert(false);
   60.48 +                }
   60.49 +                break;
   60.50 +            }
   60.51 +            default:
   60.52 +                assert(false);
   60.53 +            }
   60.54 +        }
   60.55 +    }
   60.56 +    break;
   60.57 +
   60.58 +
   60.59      default:
   60.60          assert(false);
   60.61      }
    61.1 --- a/tools/libxen/src/xen_host.c	Fri Apr 06 10:06:30 2007 -0600
    61.2 +++ b/tools/libxen/src/xen_host.c	Fri Apr 06 10:08:30 2007 -0600
    61.3 @@ -740,6 +740,18 @@ xen_host_dmesg(xen_session *session, cha
    61.4  
    61.5  
    61.6  bool
    61.7 +xen_host_list_methods(xen_session *session, struct xen_string_set **result)
    61.8 +{
    61.9 +
   61.10 +    abstract_type result_type = abstract_type_string_set;
   61.11 +
   61.12 +    *result = NULL;
   61.13 +    xen_call_(session, "host.list_methods", NULL, 0, &result_type, result);
   61.14 +    return session->ok;
   61.15 +}
   61.16 +
   61.17 +
   61.18 +bool
   61.19  xen_host_get_all(xen_session *session, struct xen_host_set **result)
   61.20  {
   61.21  
    62.1 --- a/tools/libxen/src/xen_sr.c	Fri Apr 06 10:06:30 2007 -0600
    62.2 +++ b/tools/libxen/src/xen_sr.c	Fri Apr 06 10:08:30 2007 -0600
    62.3 @@ -1,5 +1,5 @@
    62.4  /*
    62.5 - * Copyright (c) 2006, XenSource Inc.
    62.6 + * Copyright (c) 2006-2007, XenSource Inc.
    62.7   *
    62.8   * This library is free software; you can redistribute it and/or
    62.9   * modify it under the terms of the GNU Lesser General Public
   62.10 @@ -65,9 +65,9 @@ static const struct_member xen_sr_record
   62.11          { .key = "type",
   62.12            .type = &abstract_type_string,
   62.13            .offset = offsetof(xen_sr_record, type) },
   62.14 -        { .key = "location",
   62.15 +        { .key = "content_type",
   62.16            .type = &abstract_type_string,
   62.17 -          .offset = offsetof(xen_sr_record, location) }
   62.18 +          .offset = offsetof(xen_sr_record, content_type) }
   62.19      };
   62.20  
   62.21  const abstract_type xen_sr_record_abstract_type_ =
   62.22 @@ -94,7 +94,7 @@ xen_sr_record_free(xen_sr_record *record
   62.23      xen_vdi_record_opt_set_free(record->vdis);
   62.24      xen_pbd_record_opt_set_free(record->pbds);
   62.25      free(record->type);
   62.26 -    free(record->location);
   62.27 +    free(record->content_type);
   62.28      free(record);
   62.29  }
   62.30  
   62.31 @@ -140,37 +140,6 @@ xen_sr_get_by_uuid(xen_session *session,
   62.32  
   62.33  
   62.34  bool
   62.35 -xen_sr_create(xen_session *session, xen_sr *result, xen_sr_record *record)
   62.36 -{
   62.37 -    abstract_value param_values[] =
   62.38 -        {
   62.39 -            { .type = &xen_sr_record_abstract_type_,
   62.40 -              .u.struct_val = record }
   62.41 -        };
   62.42 -
   62.43 -    abstract_type result_type = abstract_type_string;
   62.44 -
   62.45 -    *result = NULL;
   62.46 -    XEN_CALL_("SR.create");
   62.47 -    return session->ok;
   62.48 -}
   62.49 -
   62.50 -
   62.51 -bool
   62.52 -xen_sr_destroy(xen_session *session, xen_sr sr)
   62.53 -{
   62.54 -    abstract_value param_values[] =
   62.55 -        {
   62.56 -            { .type = &abstract_type_string,
   62.57 -              .u.string_val = sr }
   62.58 -        };
   62.59 -
   62.60 -    xen_call_(session, "SR.destroy", param_values, 1, NULL, NULL);
   62.61 -    return session->ok;
   62.62 -}
   62.63 -
   62.64 -
   62.65 -bool
   62.66  xen_sr_get_by_name_label(xen_session *session, struct xen_sr_set **result, char *label)
   62.67  {
   62.68      abstract_value param_values[] =
   62.69 @@ -239,6 +208,23 @@ xen_sr_get_vdis(xen_session *session, st
   62.70  
   62.71  
   62.72  bool
   62.73 +xen_sr_get_pbds(xen_session *session, struct xen_pbd_set **result, xen_sr sr)
   62.74 +{
   62.75 +    abstract_value param_values[] =
   62.76 +        {
   62.77 +            { .type = &abstract_type_string,
   62.78 +              .u.string_val = sr }
   62.79 +        };
   62.80 +
   62.81 +    abstract_type result_type = abstract_type_string_set;
   62.82 +
   62.83 +    *result = NULL;
   62.84 +    XEN_CALL_("SR.get_PBDs");
   62.85 +    return session->ok;
   62.86 +}
   62.87 +
   62.88 +
   62.89 +bool
   62.90  xen_sr_get_virtual_allocation(xen_session *session, int64_t *result, xen_sr sr)
   62.91  {
   62.92      abstract_value param_values[] =
   62.93 @@ -304,7 +290,7 @@ xen_sr_get_type(xen_session *session, ch
   62.94  
   62.95  
   62.96  bool
   62.97 -xen_sr_get_location(xen_session *session, char **result, xen_sr sr)
   62.98 +xen_sr_get_content_type(xen_session *session, char **result, xen_sr sr)
   62.99  {
  62.100      abstract_value param_values[] =
  62.101          {
  62.102 @@ -315,7 +301,7 @@ xen_sr_get_location(xen_session *session
  62.103      abstract_type result_type = abstract_type_string;
  62.104  
  62.105      *result = NULL;
  62.106 -    XEN_CALL_("SR.get_location");
  62.107 +    XEN_CALL_("SR.get_content_type");
  62.108      return session->ok;
  62.109  }
  62.110  
  62.111 @@ -353,22 +339,13 @@ xen_sr_set_name_description(xen_session 
  62.112  
  62.113  
  62.114  bool
  62.115 -xen_sr_clone(xen_session *session, xen_sr *result, xen_sr sr, char *loc, char *name)
  62.116 +xen_sr_get_supported_types(xen_session *session, struct xen_string_set **result)
  62.117  {
  62.118 -    abstract_value param_values[] =
  62.119 -        {
  62.120 -            { .type = &abstract_type_string,
  62.121 -              .u.string_val = sr },
  62.122 -            { .type = &abstract_type_string,
  62.123 -              .u.string_val = loc },
  62.124 -            { .type = &abstract_type_string,
  62.125 -              .u.string_val = name }
  62.126 -        };
  62.127  
  62.128 -    abstract_type result_type = abstract_type_string;
  62.129 +    abstract_type result_type = abstract_type_string_set;
  62.130  
  62.131      *result = NULL;
  62.132 -    XEN_CALL_("SR.clone");
  62.133 +    xen_call_(session, "SR.get_supported_types", NULL, 0, &result_type, result);
  62.134      return session->ok;
  62.135  }
  62.136  
    63.1 --- a/tools/libxen/src/xen_vdi.c	Fri Apr 06 10:06:30 2007 -0600
    63.2 +++ b/tools/libxen/src/xen_vdi.c	Fri Apr 06 10:08:30 2007 -0600
    63.3 @@ -508,39 +508,6 @@ xen_vdi_remove_from_other_config(xen_ses
    63.4  
    63.5  
    63.6  bool
    63.7 -xen_vdi_snapshot(xen_session *session, xen_vdi *result, xen_vdi vdi)
    63.8 -{
    63.9 -    abstract_value param_values[] =
   63.10 -        {
   63.11 -            { .type = &abstract_type_string,
   63.12 -              .u.string_val = vdi }
   63.13 -        };
   63.14 -
   63.15 -    abstract_type result_type = abstract_type_string;
   63.16 -
   63.17 -    *result = NULL;
   63.18 -    XEN_CALL_("VDI.snapshot");
   63.19 -    return session->ok;
   63.20 -}
   63.21 -
   63.22 -
   63.23 -bool
   63.24 -xen_vdi_resize(xen_session *session, xen_vdi vdi, int64_t size)
   63.25 -{
   63.26 -    abstract_value param_values[] =
   63.27 -        {
   63.28 -            { .type = &abstract_type_string,
   63.29 -              .u.string_val = vdi },
   63.30 -            { .type = &abstract_type_int,
   63.31 -              .u.int_val = size }
   63.32 -        };
   63.33 -
   63.34 -    xen_call_(session, "VDI.resize", param_values, 2, NULL, NULL);
   63.35 -    return session->ok;
   63.36 -}
   63.37 -
   63.38 -
   63.39 -bool
   63.40  xen_vdi_get_all(xen_session *session, struct xen_vdi_set **result)
   63.41  {
   63.42  
    64.1 --- a/tools/libxen/test/test_bindings.c	Fri Apr 06 10:06:30 2007 -0600
    64.2 +++ b/tools/libxen/test/test_bindings.c	Fri Apr 06 10:08:30 2007 -0600
    64.3 @@ -64,6 +64,7 @@ typedef struct
    64.4  
    64.5  static xen_vm create_new_vm(xen_session *session, bool hvm);
    64.6  static void print_session_info(xen_session *session);
    64.7 +static void print_methods(xen_session *session);
    64.8  static void print_vm_power_state(xen_session *session, xen_vm vm);
    64.9  static void print_vm_metrics(xen_session *session, xen_vm vm);
   64.10  
   64.11 @@ -166,6 +167,14 @@ int main(int argc, char **argv)
   64.12          return 1;
   64.13      }
   64.14  
   64.15 +    print_methods(session);
   64.16 +    if (!session->ok)
   64.17 +    {
   64.18 +        /* Error has been logged, just clean up. */
   64.19 +        CLEANUP;
   64.20 +        return 1;
   64.21 +    }
   64.22 +
   64.23      xen_vm vm;
   64.24      if (!xen_vm_get_by_uuid(session, &vm,
   64.25                              "00000000-0000-0000-0000-000000000000"))
   64.26 @@ -644,6 +653,40 @@ static void print_session_info(xen_sessi
   64.27  }
   64.28  
   64.29  
   64.30 +static int pstrcmp(const void *p1, const void *p2)
   64.31 +{
   64.32 +    return strcmp(*(char **)p1, *(char **)p2);
   64.33 +}
   64.34 +
   64.35 +
   64.36 +/**
   64.37 + * Print the list of supported methods.
   64.38 + */
   64.39 +static void print_methods(xen_session *session)
   64.40 +{
   64.41 +    xen_string_set *methods;
   64.42 +
   64.43 +    if (!xen_host_list_methods(session, &methods))
   64.44 +    {
   64.45 +        print_error(session);
   64.46 +        goto done;
   64.47 +    }
   64.48 +
   64.49 +    printf("%zd.\n", methods->size);
   64.50 +    qsort(methods->contents, methods->size, sizeof(char *), pstrcmp);
   64.51 +
   64.52 +    printf("Supported methods:\n");
   64.53 +    for (size_t i = 0; i < methods->size; i++)
   64.54 +    {
   64.55 +        printf("  %s\n", methods->contents[i]);
   64.56 +    }
   64.57 +    fflush(stdout);
   64.58 +
   64.59 +done:
   64.60 +    xen_string_set_free(methods);
   64.61 +}
   64.62 +
   64.63 +
   64.64  /**
   64.65   * Print the metrics for the given VM.
   64.66   */
    65.1 --- a/tools/python/xen/xend/XendAPI.py	Fri Apr 06 10:06:30 2007 -0600
    65.2 +++ b/tools/python/xen/xend/XendAPI.py	Fri Apr 06 10:08:30 2007 -0600
    65.3 @@ -26,20 +26,22 @@ import threading
    65.4  import time
    65.5  import xmlrpclib
    65.6  
    65.7 -from xen.xend import XendDomain, XendDomainInfo, XendNode, XendDmesg
    65.8 -from xen.xend import XendLogging, XendTaskManager
    65.9 -
   65.10 -from xen.xend.XendAPIVersion import *
   65.11 -from xen.xend.XendAuthSessions import instance as auth_manager
   65.12 -from xen.xend.XendError import *
   65.13 -from xen.xend.XendClient import ERROR_INVALID_DOMAIN
   65.14 -from xen.xend.XendLogging import log
   65.15 -from xen.xend.XendNetwork import XendNetwork
   65.16 -from xen.xend.XendTask import XendTask
   65.17 -from xen.xend.XendPIFMetrics import XendPIFMetrics
   65.18 -from xen.xend.XendVMMetrics import XendVMMetrics
   65.19 -
   65.20 -from xen.xend.XendAPIConstants import *
   65.21 +import XendDomain, XendDomainInfo, XendNode, XendDmesg
   65.22 +import XendLogging, XendTaskManager
   65.23 +
   65.24 +from XendAPIVersion import *
   65.25 +from XendAuthSessions import instance as auth_manager
   65.26 +from XendError import *
   65.27 +from XendClient import ERROR_INVALID_DOMAIN
   65.28 +from XendLogging import log
   65.29 +from XendNetwork import XendNetwork
   65.30 +from XendTask import XendTask
   65.31 +from XendPIFMetrics import XendPIFMetrics
   65.32 +from XendVMMetrics import XendVMMetrics
   65.33 +
   65.34 +import XendPBD
   65.35 +
   65.36 +from XendAPIConstants import *
   65.37  from xen.util.xmlrpclib2 import stringify
   65.38  
   65.39  from xen.util.blkif import blkdev_name_to_number
   65.40 @@ -394,6 +396,17 @@ def valid_sr(func):
   65.41             _check_ref(lambda r: XendNode.instance().is_valid_sr,
   65.42                        'SR', func, *args, **kwargs)
   65.43  
   65.44 +def valid_pbd(func):
   65.45 +    """Decorator to verify if pbd_ref is valid before calling
   65.46 +    method.
   65.47 +
   65.48 +    @param func: function with params: (self, session, pbd_ref)
   65.49 +    @rtype: callable object
   65.50 +    """
   65.51 +    return lambda *args, **kwargs: \
   65.52 +           _check_ref(lambda r: r in XendPBD.get_all_refs(),
   65.53 +                      'PBD', func, *args, **kwargs)
   65.54 +
   65.55  def valid_pif(func):
   65.56      """Decorator to verify if pif_ref is valid before calling
   65.57      method.
   65.58 @@ -479,6 +492,7 @@ classes = {
   65.59      'VTPM'         : valid_vtpm,
   65.60      'console'      : valid_console,
   65.61      'SR'           : valid_sr,
   65.62 +    'PBD'          : valid_pbd,
   65.63      'PIF'          : valid_pif,
   65.64      'PIF_metrics'  : valid_pif_metrics,
   65.65      'task'         : valid_task,
   65.66 @@ -488,6 +502,7 @@ classes = {
   65.67  autoplug_classes = {
   65.68      'network'     : XendNetwork,
   65.69      'VM_metrics'  : XendVMMetrics,
   65.70 +    'PBD'         : XendPBD.XendPBD,
   65.71      'PIF_metrics' : XendPIFMetrics,
   65.72  }
   65.73  
   65.74 @@ -774,7 +789,6 @@ class XendAPI(object):
   65.75                      'progress',
   65.76                      'type',
   65.77                      'result',
   65.78 -                    'error_code',
   65.79                      'error_info',
   65.80                      'allowed_operations',
   65.81                      'session'
   65.82 @@ -809,10 +823,6 @@ class XendAPI(object):
   65.83          task = XendTaskManager.get_task(task_ref)
   65.84          return xen_api_success(task.result)
   65.85  
   65.86 -    def task_get_error_code(self, session, task_ref):
   65.87 -        task = XendTaskManager.get_task(task_ref)
   65.88 -        return xen_api_success(task.error_code)
   65.89 -
   65.90      def task_get_error_info(self, session, task_ref):
   65.91          task = XendTaskManager.get_task(task_ref)
   65.92          return xen_api_success(task.error_info)
   65.93 @@ -843,6 +853,7 @@ class XendAPI(object):
   65.94  
   65.95      host_attr_ro = ['software_version',
   65.96                      'resident_VMs',
   65.97 +                    'PBDs',
   65.98                      'PIFs',
   65.99                      'host_CPUs',
  65.100                      'cpu_configuration',
  65.101 @@ -870,7 +881,8 @@ class XendAPI(object):
  65.102                      ('get_log', 'String'),
  65.103                      ('send_debug_keys', None)]
  65.104      
  65.105 -    host_funcs = [('get_by_name_label', 'Set(host)')]
  65.106 +    host_funcs = [('get_by_name_label', None),
  65.107 +                  ('list_methods', None)]
  65.108  
  65.109      # attributes
  65.110      def host_get_name_label(self, session, host_ref):
  65.111 @@ -913,6 +925,8 @@ class XendAPI(object):
  65.112          return xen_api_success(XendNode.instance().xen_version())
  65.113      def host_get_resident_VMs(self, session, host_ref):
  65.114          return xen_api_success(XendDomain.instance().get_domain_refs())
  65.115 +    def host_get_PBDs(self, _, ref):
  65.116 +        return xen_api_success(XendPBD.get_all_refs())
  65.117      def host_get_PIFs(self, session, ref):
  65.118          return xen_api_success(XendNode.instance().get_PIF_refs())
  65.119      def host_get_host_CPUs(self, session, host_ref):
  65.120 @@ -925,8 +939,6 @@ class XendAPI(object):
  65.121          return xen_api_success(['pygrub'])
  65.122      def host_get_sched_policy(self, _, host_ref):
  65.123          return xen_api_success(XendNode.instance().get_vcpus_policy())
  65.124 -    def host_set_sched_policy(self, _, host_ref, policy):
  65.125 -        return xen_api_todo()
  65.126      def host_get_cpu_configuration(self, _, host_ref):
  65.127          return xen_api_success(XendNode.instance().get_cpu_configuration())
  65.128      
  65.129 @@ -992,6 +1004,12 @@ class XendAPI(object):
  65.130              return xen_api_success((XendNode.instance().uuid,))
  65.131          return xen_api_success([])
  65.132      
  65.133 +    def host_list_methods(self, _):
  65.134 +        def _funcs():
  65.135 +            return [getattr(XendAPI, x) for x in XendAPI.__dict__]
  65.136 +
  65.137 +        return xen_api_success([x.api for x in _funcs()
  65.138 +                                if hasattr(x, 'api')])
  65.139  
  65.140      # Xen API: Class host_CPU
  65.141      # ----------------------------------------------------------------
  65.142 @@ -2061,8 +2079,8 @@ class XendAPI(object):
  65.143              vif_ref = dom.create_vif(vif_struct)
  65.144              xendom.managed_config_save(dom)
  65.145              return xen_api_success(vif_ref)
  65.146 -        except XendError:
  65.147 -            return xen_api_error(XEND_ERROR_TODO)
  65.148 +        except XendError, exn:
  65.149 +            return xen_api_error(['INTERNAL_ERROR', str(exn)])
  65.150            
  65.151      def VIF_destroy(self, session, vif_ref):
  65.152          xendom = XendDomain.instance()
  65.153 @@ -2169,7 +2187,7 @@ class XendAPI(object):
  65.154                     'other_config']
  65.155      VDI_attr_inst = VDI_attr_ro + VDI_attr_rw
  65.156  
  65.157 -    VDI_methods = [('snapshot', 'VDI'), ('destroy', None)]
  65.158 +    VDI_methods = [('destroy', None)]
  65.159      VDI_funcs = [('create', 'VDI'),
  65.160                    ('get_by_name_label', 'Set(VDI)')]
  65.161  
  65.162 @@ -2233,8 +2251,6 @@ class XendAPI(object):
  65.163          return xen_api_success_void()
  65.164  
  65.165      # Object Methods
  65.166 -    def VDI_snapshot(self, session, vdi_ref):
  65.167 -        return xen_api_todo()
  65.168      
  65.169      def VDI_destroy(self, session, vdi_ref):
  65.170          sr = XendNode.instance().get_sr_containing_vdi(vdi_ref)
  65.171 @@ -2349,8 +2365,8 @@ class XendAPI(object):
  65.172                  vtpm_ref = dom.create_vtpm(vtpm_struct)
  65.173                  xendom.managed_config_save(dom)
  65.174                  return xen_api_success(vtpm_ref)
  65.175 -            except XendError:
  65.176 -                return xen_api_error(XEND_ERROR_TODO)
  65.177 +            except XendError, exn:
  65.178 +                return xen_api_error(['INTERNAL_ERROR', str(exn)])
  65.179          else:
  65.180              return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
  65.181  
  65.182 @@ -2424,8 +2440,8 @@ class XendAPI(object):
  65.183              console_ref = dom.create_console(console_struct)
  65.184              xendom.managed_config_save(dom)
  65.185              return xen_api_success(console_ref)
  65.186 -        except XendError, e:
  65.187 -            return xen_api_error([XEND_ERROR_TODO, str(e)])
  65.188 +        except XendError, exn:
  65.189 +            return xen_api_error(['INTERNAL_ERROR', str(exn)])
  65.190  
  65.191      # Xen API: Class SR
  65.192      # ----------------------------------------------------------------
  65.193 @@ -2434,18 +2450,17 @@ class XendAPI(object):
  65.194                    'physical_utilisation',
  65.195                    'physical_size',
  65.196                    'type',
  65.197 -                  'location']
  65.198 +                  'content_type']
  65.199      
  65.200      SR_attr_rw = ['name_label',
  65.201                    'name_description']
  65.202      
  65.203      SR_attr_inst = ['physical_size',
  65.204                      'type',
  65.205 -                    'location',
  65.206                      'name_label',
  65.207                      'name_description']
  65.208      
  65.209 -    SR_methods = [('clone', 'SR'), ('destroy', None)]
  65.210 +    SR_methods = []
  65.211      SR_funcs = [('get_by_name_label', 'Set(SR)'),
  65.212                  ('get_by_uuid', 'SR')]
  65.213  
  65.214 @@ -2456,15 +2471,10 @@ class XendAPI(object):
  65.215      def SR_get_by_name_label(self, session, label):
  65.216          return xen_api_success(XendNode.instance().get_sr_by_name(label))
  65.217      
  65.218 -    def SR_create(self, session):
  65.219 -        return xen_api_error(XEND_ERROR_UNSUPPORTED)
  65.220 +    def SR_get_supported_types(self, _):
  65.221 +        return xen_api_success(['local', 'qcow_file'])
  65.222  
  65.223      # Class Methods
  65.224 -    def SR_clone(self, session, sr_ref):
  65.225 -        return xen_api_error(XEND_ERROR_UNSUPPORTED)
  65.226 -    
  65.227 -    def SR_destroy(self, session, sr_ref):
  65.228 -        return xen_api_error(XEND_ERROR_UNSUPPORTED)
  65.229      
  65.230      def SR_get_record(self, session, sr_ref):
  65.231          sr = XendNode.instance().get_sr(sr_ref)
  65.232 @@ -2497,8 +2507,8 @@ class XendAPI(object):
  65.233      def SR_get_type(self, _, ref):
  65.234          return self._get_SR_attr(ref, 'type')
  65.235  
  65.236 -    def SR_get_location(self, _, ref):
  65.237 -        return self._get_SR_attr(ref, 'location')
  65.238 +    def SR_get_content_type(self, _, ref):
  65.239 +        return self._get_SR_attr(ref, 'content_type')
  65.240  
  65.241      def SR_get_name_label(self, _, ref):
  65.242          return self._get_SR_attr(ref, 'name_label')
  65.243 @@ -2521,6 +2531,33 @@ class XendAPI(object):
  65.244          return xen_api_success_void()
  65.245  
  65.246  
  65.247 +    # Xen API: Class PBD
  65.248 +    # ----------------------------------------------------------------
  65.249 +
  65.250 +    PBD_attr_ro = ['host',
  65.251 +                   'SR',
  65.252 +                   'device_config',
  65.253 +                   'currently_attached']
  65.254 +    PBD_attr_rw = []
  65.255 +    PBD_methods = [('destroy', None)]
  65.256 +    PBD_funcs   = [('create', None)]
  65.257 +
  65.258 +    def PBD_get_all(self, _):
  65.259 +        return xen_api_success(XendPBD.get_all_refs())
  65.260 +
  65.261 +    def _PBD_get(self, _, ref):
  65.262 +        return XendPBD.get(ref)
  65.263 +
  65.264 +    def PBD_create(self, _, record):
  65.265 +        if 'uuid' in record:
  65.266 +            return xen_api_error(['VALUE_NOT_SUPPORTED',
  65.267 +                                  'uuid', record['uuid'],
  65.268 +                                  'You may not specify a UUID on creation'])
  65.269 +        new_uuid = XendPBD.XendPBD(record).get_uuid()
  65.270 +        XendNode.instance().save()
  65.271 +        return xen_api_success(new_uuid)
  65.272 +
  65.273 +
  65.274      # Xen API: Class event
  65.275      # ----------------------------------------------------------------
  65.276  
  65.277 @@ -2574,15 +2611,6 @@ class XendAPI(object):
  65.278          return xen_api_success({'uuid': debug_ref})
  65.279  
  65.280  
  65.281 -    def list_all_methods(self, _):
  65.282 -        def _funcs():
  65.283 -            return [getattr(XendAPI, x) for x in XendAPI.__dict__]
  65.284 -
  65.285 -        return xen_api_success([x.api for x in _funcs()
  65.286 -                                if hasattr(x, 'api')])
  65.287 -    list_all_methods.api = '_UNSUPPORTED_list_all_methods'
  65.288 -
  65.289 -
  65.290  class XendAPIAsyncProxy:
  65.291      """ A redirector for Async.Class.function calls to XendAPI
  65.292      but wraps the call for use with the XendTaskManager.
    66.1 --- a/tools/python/xen/xend/XendCheckpoint.py	Fri Apr 06 10:06:30 2007 -0600
    66.2 +++ b/tools/python/xen/xend/XendCheckpoint.py	Fri Apr 06 10:08:30 2007 -0600
    66.3 @@ -91,7 +91,7 @@ def save(fd, dominfo, network, live, dst
    66.4          # more information.
    66.5          cmd = [xen.util.auxbin.pathTo(XC_SAVE), str(fd),
    66.6                 str(dominfo.getDomid()), "0", "0", 
    66.7 -               str(int(live) | (int(hvm) << 2) | (int(stdvga) << 3)) ]
    66.8 +               str(int(live) | (int(hvm) << 2)) ]
    66.9          log.debug("[xc_save]: %s", string.join(cmd))
   66.10  
   66.11          def saveInputHandler(line, tochild):
   66.12 @@ -187,7 +187,6 @@ def restore(xd, fd, dominfo = None, paus
   66.13      assert console_port
   66.14  
   66.15      nr_pfns = (dominfo.getMemoryTarget() + 3) / 4 
   66.16 -    max_nr_pfns = (dominfo.getMemoryMaximum() + 3) / 4 
   66.17  
   66.18      # if hvm, pass mem size to calculate the store_mfn
   66.19      image_cfg = dominfo.info.get('image', {})
   66.20 @@ -202,27 +201,21 @@ def restore(xd, fd, dominfo = None, paus
   66.21          pae  = 0
   66.22  
   66.23      try:
   66.24 -        l = read_exact(fd, sizeof_unsigned_long,
   66.25 -                       "not a valid guest state file: pfn count read")
   66.26 -        p2m_size = unpack("L", l)[0]    # native sizeof long
   66.27 -
   66.28 -        if p2m_size > 16*1024*1024:     # XXX 
   66.29 -            raise XendError(
   66.30 -                "not a valid guest state file: pfn count out of range")
   66.31 -
   66.32          shadow = dominfo.info['shadow_memory']
   66.33 -        log.debug("restore:shadow=0x%x, _static_max=0x%x, _static_min=0x%x, "
   66.34 -                  "p2m_size=0x%x.", dominfo.info['shadow_memory'],
   66.35 +        log.debug("restore:shadow=0x%x, _static_max=0x%x, _static_min=0x%x, ",
   66.36 +                  dominfo.info['shadow_memory'],
   66.37                    dominfo.info['memory_static_max'],
   66.38 -                  dominfo.info['memory_static_min'], p2m_size)
   66.39 +                  dominfo.info['memory_static_min'])
   66.40  
   66.41          balloon.free(xc.pages_to_kib(nr_pfns) + shadow * 1024)
   66.42  
   66.43          shadow_cur = xc.shadow_mem_control(dominfo.getDomid(), shadow)
   66.44          dominfo.info['shadow_memory'] = shadow_cur
   66.45  
   66.46 +        xc.domain_setmaxmem(dominfo.getDomid(), dominfo.getMemoryMaximum())
   66.47 +
   66.48          cmd = map(str, [xen.util.auxbin.pathTo(XC_RESTORE),
   66.49 -                        fd, dominfo.getDomid(), p2m_size, max_nr_pfns, 
   66.50 +                        fd, dominfo.getDomid(),
   66.51                          store_port, console_port, int(is_hvm), pae, apic])
   66.52          log.debug("[xc_restore]: %s", string.join(cmd))
   66.53  
    67.1 --- a/tools/python/xen/xend/XendLocalStorageRepo.py	Fri Apr 06 10:06:30 2007 -0600
    67.2 +++ b/tools/python/xen/xend/XendLocalStorageRepo.py	Fri Apr 06 10:08:30 2007 -0600
    67.3 @@ -30,13 +30,13 @@ import sys
    67.4  import struct
    67.5  
    67.6  from xen.util import mkdir
    67.7 -from xen.xend import uuid
    67.8 -from xen.xend.XendError import XendError
    67.9 -from xen.xend.XendVDI import *
   67.10 -from xen.xend.XendTask import XendTask
   67.11 -from xen.xend.XendStorageRepository import XendStorageRepository
   67.12 -from xen.xend.XendStateStore import XendStateStore
   67.13 -from xen.xend.XendOptions import instance as xendoptions
   67.14 +import uuid
   67.15 +from XendError import XendError
   67.16 +from XendVDI import *
   67.17 +from XendTask import XendTask
   67.18 +from XendStorageRepository import XendStorageRepository
   67.19 +from XendStateStore import XendStateStore
   67.20 +from XendOptions import instance as xendoptions
   67.21  
   67.22  MB = 1024 * 1024
   67.23  
   67.24 @@ -58,8 +58,7 @@ class XendLocalStorageRepo(XendStorageRe
   67.25          """
   67.26  
   67.27          XendStorageRepository.__init__(self, sr_uuid, sr_type,
   67.28 -                                       name_label, name_description,
   67.29 -                                       '/')
   67.30 +                                       name_label, name_description)
   67.31          
   67.32          self.state = XendStateStore(xendoptions().get_xend_state_path()
   67.33                                      + '/local_sr')
    68.1 --- a/tools/python/xen/xend/XendNode.py	Fri Apr 06 10:06:30 2007 -0600
    68.2 +++ b/tools/python/xen/xend/XendNode.py	Fri Apr 06 10:08:30 2007 -0600
    68.3 @@ -22,17 +22,18 @@ import xen.lowlevel.xc
    68.4  
    68.5  from xen.util import Brctl
    68.6  
    68.7 -from xen.xend import uuid, arch
    68.8 -from xen.xend.XendError import *
    68.9 -from xen.xend.XendOptions import instance as xendoptions
   68.10 -from xen.xend.XendQCoWStorageRepo import XendQCoWStorageRepo
   68.11 -from xen.xend.XendLocalStorageRepo import XendLocalStorageRepo
   68.12 -from xen.xend.XendLogging import log
   68.13 -from xen.xend.XendPIF import *
   68.14 -from xen.xend.XendPIFMetrics import XendPIFMetrics
   68.15 -from xen.xend.XendNetwork import *
   68.16 -from xen.xend.XendStateStore import XendStateStore
   68.17 -from xen.xend.XendMonitor import XendMonitor
   68.18 +import uuid, arch
   68.19 +import XendPBD
   68.20 +from XendError import *
   68.21 +from XendOptions import instance as xendoptions
   68.22 +from XendQCoWStorageRepo import XendQCoWStorageRepo
   68.23 +from XendLocalStorageRepo import XendLocalStorageRepo
   68.24 +from XendLogging import log
   68.25 +from XendPIF import *
   68.26 +from XendPIFMetrics import XendPIFMetrics
   68.27 +from XendNetwork import *
   68.28 +from XendStateStore import XendStateStore
   68.29 +from XendMonitor import XendMonitor
   68.30  
   68.31  class XendNode:
   68.32      """XendNode - Represents a Domain 0 Host."""
   68.33 @@ -193,13 +194,14 @@ class XendNode:
   68.34          saved_srs = self.state_store.load_state('sr')
   68.35          if saved_srs:
   68.36              for sr_uuid, sr_cfg in saved_srs.items():
   68.37 +                log.error("SAved SRS %s %s", sr_uuid, sr_cfg['type'])
   68.38                  if sr_cfg['type'] == 'qcow_file':
   68.39                      self.srs[sr_uuid] = XendQCoWStorageRepo(sr_uuid)
   68.40 -                elif sr_cfg['type'] == 'local_image':
   68.41 +                elif sr_cfg['type'] == 'local':
   68.42                      self.srs[sr_uuid] = XendLocalStorageRepo(sr_uuid)
   68.43  
   68.44          # Create missing SRs if they don't exist
   68.45 -        if not self.get_sr_by_type('local_image'):
   68.46 +        if not self.get_sr_by_type('local'):
   68.47              image_sr_uuid = uuid.createString()
   68.48              self.srs[image_sr_uuid] = XendLocalStorageRepo(image_sr_uuid)
   68.49              
   68.50 @@ -207,6 +209,11 @@ class XendNode:
   68.51              qcow_sr_uuid = uuid.createString()
   68.52              self.srs[qcow_sr_uuid] = XendQCoWStorageRepo(qcow_sr_uuid)
   68.53  
   68.54 +        saved_pbds = self.state_store.load_state('pbd')
   68.55 +        if saved_pbds:
   68.56 +            for pbd_uuid, pbd_cfg in saved_pbds.items():
   68.57 +                pbd_cfg['uuid'] = pbd_uuid
   68.58 +                XendPBD.XendPBD(pbd_cfg)
   68.59  
   68.60  
   68.61      def network_create(self, record, persist = True, net_uuid = None):
   68.62 @@ -280,6 +287,7 @@ class XendNode:
   68.63          self.state_store.save_state('cpu', self.cpus)
   68.64          self.save_PIFs()
   68.65          self.save_networks()
   68.66 +        self.save_PBDs()
   68.67          self.save_SRs()
   68.68  
   68.69      def save_PIFs(self):
   68.70 @@ -292,6 +300,11 @@ class XendNode:
   68.71                              for k, v in self.networks.items()])
   68.72          self.state_store.save_state('network', net_records)
   68.73  
   68.74 +    def save_PBDs(self):
   68.75 +        pbd_records = dict([(v.get_uuid(), v.get_record())
   68.76 +                            for v in XendPBD.get_all()])
   68.77 +        self.state_store.save_state('pbd', pbd_records)
   68.78 +
   68.79      def save_SRs(self):
   68.80          sr_records = dict([(k, v.get_record(transient = False))
   68.81                              for k, v in self.srs.items()])
    69.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    69.2 +++ b/tools/python/xen/xend/XendPBD.py	Fri Apr 06 10:08:30 2007 -0600
    69.3 @@ -0,0 +1,79 @@
    69.4 +#============================================================================
    69.5 +# This library is free software; you can redistribute it and/or
    69.6 +# modify it under the terms of version 2.1 of the GNU Lesser General Public
    69.7 +# License as published by the Free Software Foundation.
    69.8 +#
    69.9 +# This library is distributed in the hope that it will be useful,
   69.10 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
   69.11 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   69.12 +# Lesser General Public License for more details.
   69.13 +#
   69.14 +# You should have received a copy of the GNU Lesser General Public
   69.15 +# License along with this library; if not, write to the Free Software
   69.16 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   69.17 +#============================================================================
   69.18 +# Copyright (c) 2007 Xensource Inc.
   69.19 +#============================================================================
   69.20 +
   69.21 +
   69.22 +import uuid
   69.23 +from XendLogging import log
   69.24 +
   69.25 +
   69.26 +attr_inst = ['uuid',
   69.27 +             'host',
   69.28 +             'SR',
   69.29 +             'device_config']
   69.30 +attr_ro = attr_inst + ['currently_attached']
   69.31 +
   69.32 +
   69.33 +_all = {}
   69.34 +
   69.35 +
   69.36 +def get(ref):
   69.37 +    return _all[ref]
   69.38 +
   69.39 +
   69.40 +def get_all():
   69.41 +    return _all.values()
   69.42 +
   69.43 +
   69.44 +def get_all_refs():
   69.45 +    return _all.keys()
   69.46 +
   69.47 +
   69.48 +def get_by_SR(sr_ref):
   69.49 +    return [k for (k, v) in _all.items() if v.get_SR() == sr_ref]
   69.50 +
   69.51 +
   69.52 +class XendPBD:
   69.53 +    """Physical block devices."""
   69.54 +    
   69.55 +    def __init__(self, record):
   69.56 +        if 'uuid' not in record:
   69.57 +            record['uuid'] = uuid.createString()
   69.58 +
   69.59 +        import XendAPI
   69.60 +        for v in attr_inst:
   69.61 +            setattr(self, v, record[v])
   69.62 +        self.currently_attached = True
   69.63 +        _all[record['uuid']] = self
   69.64 +
   69.65 +
   69.66 +    def destroy(self):
   69.67 +        if self.uuid in _all:
   69.68 +            del _all[self.uuid]
   69.69 +
   69.70 +
   69.71 +    def get_record(self):
   69.72 +        import XendAPI
   69.73 +        result = {}
   69.74 +        for v in attr_ro:
   69.75 +            result[v] = getattr(self, v)
   69.76 +        return result
   69.77 +
   69.78 +
   69.79 +for v in attr_ro:
   69.80 +    def f(v_):
   69.81 +        setattr(XendPBD, 'get_' + v_, lambda s: getattr(s, v_))
   69.82 +    f(v)
    70.1 --- a/tools/python/xen/xend/XendQCoWStorageRepo.py	Fri Apr 06 10:06:30 2007 -0600
    70.2 +++ b/tools/python/xen/xend/XendQCoWStorageRepo.py	Fri Apr 06 10:08:30 2007 -0600
    70.3 @@ -29,12 +29,13 @@ import sys
    70.4  import struct
    70.5  
    70.6  from xen.util import mkdir
    70.7 -from xen.xend import uuid
    70.8 -from xen.xend.XendError import XendError
    70.9 -from xen.xend.XendVDI import *
   70.10 -from xen.xend.XendTask import XendTask
   70.11 -from xen.xend.XendStorageRepository import XendStorageRepository
   70.12 -from xen.xend.XendOptions import instance as xendoptions
   70.13 +import uuid
   70.14 +import XendPBD
   70.15 +from XendError import XendError
   70.16 +from XendVDI import *
   70.17 +from XendTask import XendTask
   70.18 +from XendStorageRepository import XendStorageRepository
   70.19 +from XendOptions import instance as xendoptions
   70.20  
   70.21  XEND_STORAGE_NO_MAXIMUM = sys.maxint
   70.22  XEND_STORAGE_QCOW_FILENAME = "%s.qcow"
   70.23 @@ -72,7 +73,6 @@ class XendQCoWStorageRepo(XendStorageRep
   70.24                   sr_type = "qcow_file",
   70.25                   name_label = "QCoW",
   70.26                   name_description = "Xend QCoW Storage Repository",
   70.27 -                 location = xendoptions().get_xend_storage_path(),
   70.28                   storage_max = XEND_STORAGE_NO_MAXIMUM):
   70.29          """
   70.30          @keyword storage_max: Maximum disk space to use in bytes.
   70.31 @@ -85,9 +85,9 @@ class XendQCoWStorageRepo(XendStorageRep
   70.32          """
   70.33  
   70.34          XendStorageRepository.__init__(self, sr_uuid, sr_type, name_label,
   70.35 -                                       name_description, location,
   70.36 -                                       storage_max)
   70.37 +                                       name_description, storage_max)
   70.38          self.storage_free = 0
   70.39 +        self.location = xendoptions().get_xend_storage_path()
   70.40          self._refresh()
   70.41  
   70.42      def get_record(self, transient = True):
   70.43 @@ -98,8 +98,9 @@ class XendQCoWStorageRepo(XendStorageRep
   70.44                    'physical_utilisation': self.physical_utilisation,
   70.45                    'physical_size': self.physical_size,
   70.46                    'type': self.type,
   70.47 -                  'location': self.location,
   70.48 -                  'VDIs': self.images.keys()}
   70.49 +                  'content_type': self.content_type,
   70.50 +                  'VDIs': self.images.keys(),
   70.51 +                  'PBDs': XendPBD.get_by_SR(self.uuid)}
   70.52          
   70.53          if self.physical_size == XEND_STORAGE_NO_MAXIMUM:
   70.54              stfs = os.statvfs(self.location)
    71.1 --- a/tools/python/xen/xend/XendStateStore.py	Fri Apr 06 10:06:30 2007 -0600
    71.2 +++ b/tools/python/xen/xend/XendStateStore.py	Fri Apr 06 10:08:30 2007 -0600
    71.3 @@ -204,7 +204,7 @@ class XendStateStore:
    71.4                  if type(val) == dict:
    71.5                      for val_uuid in val.keys():
    71.6                          val_node = doc.createElement(key)
    71.7 -                        if key == 'other_config':
    71.8 +                        if key in ['other_config', 'device_config']:
    71.9                              val_node.setAttribute('key', str(val_uuid))
   71.10                              val_node.setAttribute('value', str(val[val_uuid]))
   71.11                          else:
    72.1 --- a/tools/python/xen/xend/XendStorageRepository.py	Fri Apr 06 10:06:30 2007 -0600
    72.2 +++ b/tools/python/xen/xend/XendStorageRepository.py	Fri Apr 06 10:08:30 2007 -0600
    72.3 @@ -22,8 +22,9 @@
    72.4  import threading
    72.5  import sys
    72.6  
    72.7 -from xen.xend.XendError import XendError
    72.8 -from xen.xend.XendVDI import *
    72.9 +from XendError import XendError
   72.10 +from XendVDI import *
   72.11 +import XendPBD
   72.12  
   72.13  XEND_STORAGE_NO_MAXIMUM = sys.maxint
   72.14  
   72.15 @@ -34,7 +35,6 @@ class XendStorageRepository:
   72.16                   sr_type = "unknown",
   72.17                   name_label = 'Unknown',
   72.18                   name_description = 'Not Implemented',
   72.19 -                 location = '',
   72.20                   storage_max = XEND_STORAGE_NO_MAXIMUM):
   72.21          """
   72.22          @keyword storage_max: Maximum disk space to use in bytes.
   72.23 @@ -49,7 +49,6 @@ class XendStorageRepository:
   72.24          # XenAPI Parameters
   72.25          self.uuid = uuid
   72.26          self.type = sr_type
   72.27 -        self.location = location
   72.28          self.name_label = name_label
   72.29          self.name_description = name_description
   72.30          self.images = {}
   72.31 @@ -57,6 +56,7 @@ class XendStorageRepository:
   72.32          self.physical_size = storage_max
   72.33          self.physical_utilisation = 0
   72.34          self.virtual_allocation = 0
   72.35 +        self.content_type = ''
   72.36   
   72.37          self.lock = threading.RLock()
   72.38  
   72.39 @@ -68,9 +68,10 @@ class XendStorageRepository:
   72.40                    'physical_utilisation': self.physical_utilisation,
   72.41                    'physical_size': self.physical_size,
   72.42                    'type': self.type,
   72.43 -                  'location': self.location,
   72.44 +                  'content_type': self.content_type,
   72.45                    'VDIs': self.images.keys()}
   72.46 -
   72.47 +        if not transient:
   72.48 +            retval ['PBDs'] = XendPBD.get_by_SR(self.uuid)
   72.49          return retval
   72.50  
   72.51  
    73.1 --- a/tools/python/xen/xend/XendTask.py	Fri Apr 06 10:06:30 2007 -0600
    73.2 +++ b/tools/python/xen/xend/XendTask.py	Fri Apr 06 10:08:30 2007 -0600
    73.3 @@ -24,7 +24,7 @@ class XendTask(threading.Thread):
    73.4      """Represents a Asynchronous Task used by Xen API.
    73.5  
    73.6      Basically proxies the callable object in a thread and returns the
    73.7 -    results via self.{type,result,error_code,error_info}.
    73.8 +    results via self.{type,result,error_info}.
    73.9  
   73.10      @cvar task_progress: Thread local storage for progress tracking.
   73.11                           It is a dict indexed by thread_id. Note that the
   73.12 @@ -71,7 +71,6 @@ class XendTask(threading.Thread):
   73.13          self.uuid = uuid
   73.14          
   73.15          self.result = None
   73.16 -        self.error_code = ''
   73.17          self.error_info = []
   73.18          
   73.19          self.name_label = label or func.__name__
   73.20 @@ -118,13 +117,11 @@ class XendTask(threading.Thread):
   73.21                  self.result = result['Value']
   73.22                  self.set_status(XEN_API_TASK_STATUS_TYPE[1])
   73.23              else:
   73.24 -                self.error_code = result['ErrorDescription'][0]
   73.25 -                self.error_info = result['ErrorDescription'][1:]
   73.26 +                self.error_info = result['ErrorDescription']
   73.27                  self.set_status(XEN_API_TASK_STATUS_TYPE[2])                
   73.28          except Exception, e:
   73.29              log.exception('Error running Async Task')
   73.30 -            self.error_code = 'INTERNAL ERROR'
   73.31 -            self.error_info = [str(e)]
   73.32 +            self.error_info = ['INTERNAL ERROR', str(e)]
   73.33              self.set_status(XEN_API_TASK_STATUS_TYPE[2])
   73.34  
   73.35          self.task_progress_lock.acquire()
   73.36 @@ -144,7 +141,6 @@ class XendTask(threading.Thread):
   73.37              'progress': self.get_progress(),
   73.38              'type': self.type,
   73.39              'result': self.result,
   73.40 -            'error_code': self.error_code,
   73.41              'error_info': self.error_info,
   73.42              'allowed_operations': {},
   73.43              'session': self.session,
    74.1 --- a/tools/python/xen/xend/image.py	Fri Apr 06 10:06:30 2007 -0600
    74.2 +++ b/tools/python/xen/xend/image.py	Fri Apr 06 10:08:30 2007 -0600
    74.3 @@ -426,11 +426,14 @@ class HVMImageHandler(ImageHandler):
    74.4          # Execute device model.
    74.5          #todo: Error handling
    74.6          args = [self.device_model]
    74.7 -        args = args + ([ "-d",  "%d" % self.vm.getDomid(),
    74.8 -                  "-m", "%s" % (self.getRequiredInitialReservation() / 1024)])
    74.9 +        args = args + ([ "-d",  "%d" % self.vm.getDomid() ])
   74.10 +        if arch.type == "ia64":
   74.11 +            args = args + ([ "-m", "%s" %
   74.12 +                             (self.getRequiredInitialReservation() / 1024) ])
   74.13          args = args + self.dmargs
   74.14          if restore:
   74.15 -            args = args + ([ "-loadvm", "/tmp/xen.qemu-dm.%d" % self.vm.getDomid() ])
   74.16 +            args = args + ([ "-loadvm", "/tmp/xen.qemu-dm.%d" %
   74.17 +                             self.vm.getDomid() ])
   74.18          env = dict(os.environ)
   74.19          if self.display:
   74.20              env['DISPLAY'] = self.display
    75.1 --- a/tools/python/xen/xm/main.py	Fri Apr 06 10:06:30 2007 -0600
    75.2 +++ b/tools/python/xen/xm/main.py	Fri Apr 06 10:08:30 2007 -0600
    75.3 @@ -591,7 +591,7 @@ class Shell(cmd.Cmd):
    75.4          self.prompt = "xm> "
    75.5          if serverType == SERVER_XEN_API:
    75.6              try:
    75.7 -                res = server.xenapi._UNSUPPORTED_list_all_methods()
    75.8 +                res = server.xenapi.host.list_methods()
    75.9                  for f in res:
   75.10                      setattr(Shell, 'do_' + f + ' ', self.default)
   75.11              except:
    76.1 --- a/tools/xcutils/xc_restore.c	Fri Apr 06 10:06:30 2007 -0600
    76.2 +++ b/tools/xcutils/xc_restore.c	Fri Apr 06 10:08:30 2007 -0600
    76.3 @@ -21,37 +21,31 @@ main(int argc, char **argv)
    76.4      unsigned int xc_fd, io_fd, domid, store_evtchn, console_evtchn;
    76.5      unsigned int hvm, pae, apic;
    76.6      int ret;
    76.7 -    unsigned long p2m_size, max_nr_pfns, store_mfn, console_mfn;
    76.8 +    unsigned long store_mfn, console_mfn;
    76.9  
   76.10 -    if (argc != 10)
   76.11 -        errx(1, "usage: %s iofd domid p2m_size max_nr_pfns store_evtchn "
   76.12 +    if ( argc != 8 )
   76.13 +        errx(1, "usage: %s iofd domid store_evtchn "
   76.14               "console_evtchn hvm pae apic", argv[0]);
   76.15  
   76.16      xc_fd = xc_interface_open();
   76.17 -    if (xc_fd < 0)
   76.18 +    if ( xc_fd < 0 )
   76.19          errx(1, "failed to open control interface");
   76.20  
   76.21      io_fd = atoi(argv[1]);
   76.22      domid = atoi(argv[2]);
   76.23 -    p2m_size = atoi(argv[3]);
   76.24 -    max_nr_pfns = atoi(argv[4]);
   76.25 -    store_evtchn = atoi(argv[5]);
   76.26 -    console_evtchn = atoi(argv[6]);
   76.27 -    hvm  = atoi(argv[7]);
   76.28 -    pae  = atoi(argv[8]);
   76.29 -    apic = atoi(argv[9]);
   76.30 +    store_evtchn = atoi(argv[3]);
   76.31 +    console_evtchn = atoi(argv[4]);
   76.32 +    hvm  = atoi(argv[5]);
   76.33 +    pae  = atoi(argv[6]);
   76.34 +    apic = atoi(argv[7]);
   76.35  
   76.36 -    if (hvm) {
   76.37 -        ret = xc_hvm_restore(xc_fd, io_fd, domid, max_nr_pfns, store_evtchn,
   76.38 -                &store_mfn, pae, apic);
   76.39 -    } else
   76.40 -        ret = xc_linux_restore(xc_fd, io_fd, domid, p2m_size,
   76.41 -                               max_nr_pfns, store_evtchn, &store_mfn,
   76.42 -                               console_evtchn, &console_mfn);
   76.43 +    ret = xc_domain_restore(xc_fd, io_fd, domid, store_evtchn, &store_mfn,
   76.44 +                            console_evtchn, &console_mfn, hvm, pae);
   76.45  
   76.46 -    if (ret == 0) {
   76.47 +    if ( ret == 0 )
   76.48 +    {
   76.49  	printf("store-mfn %li\n", store_mfn);
   76.50 -        if (!hvm)
   76.51 +        if ( !hvm )
   76.52              printf("console-mfn %li\n", console_mfn);
   76.53  	fflush(stdout);
   76.54      }
    77.1 --- a/unmodified_drivers/linux-2.6/Makefile	Fri Apr 06 10:06:30 2007 -0600
    77.2 +++ b/unmodified_drivers/linux-2.6/Makefile	Fri Apr 06 10:08:30 2007 -0600
    77.3 @@ -2,6 +2,7 @@ include $(M)/overrides.mk
    77.4  
    77.5  obj-m += platform-pci/
    77.6  obj-m += xenbus/
    77.7 +obj-m += balloon/
    77.8  obj-m += blkfront/
    77.9  obj-m += netfront/
   77.10  obj-m += util/
    78.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    78.2 +++ b/unmodified_drivers/linux-2.6/balloon/Kbuild	Fri Apr 06 10:08:30 2007 -0600
    78.3 @@ -0,0 +1,9 @@
    78.4 +include $(M)/overrides.mk
    78.5 +
    78.6 +obj-m  = xen-balloon.o
    78.7 +
    78.8 +EXTRA_CFLAGS += -I$(M)/platform-pci
    78.9 +
   78.10 +xen-balloon-objs =
   78.11 +xen-balloon-objs += balloon.o
   78.12 +xen-balloon-objs += sysfs.o
    79.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    79.2 +++ b/unmodified_drivers/linux-2.6/balloon/Makefile	Fri Apr 06 10:08:30 2007 -0600
    79.3 @@ -0,0 +1,3 @@
    79.4 +ifneq ($(KERNELRELEASE),)
    79.5 +include $(src)/Kbuild
    79.6 +endif
    80.1 --- a/unmodified_drivers/linux-2.6/compat-include/xen/platform-compat.h	Fri Apr 06 10:06:30 2007 -0600
    80.2 +++ b/unmodified_drivers/linux-2.6/compat-include/xen/platform-compat.h	Fri Apr 06 10:08:30 2007 -0600
    80.3 @@ -25,6 +25,10 @@
    80.4  #define NET_IP_ALIGN 0
    80.5  #endif
    80.6  
    80.7 +#if defined(_LINUX_SKBUFF_H) && !defined(CHECKSUM_HW)
    80.8 +#define CHECKSUM_HW CHECKSUM_PARTIAL
    80.9 +#endif
   80.10 +
   80.11  #if defined(_LINUX_ERR_H) && !defined(IS_ERR_VALUE)
   80.12  #define IS_ERR_VALUE(x) unlikely((x) > (unsigned long)-1000L)
   80.13  #endif
   80.14 @@ -36,7 +40,7 @@
   80.15  /* Some kernels have this typedef backported so we cannot reliably
   80.16   * detect based on version number, hence we forcibly #define it.
   80.17   */
   80.18 -#if defined(__LINUX_TYPES_H) || defined(__LINUX_GFP_H)
   80.19 +#if defined(__LINUX_TYPES_H) || defined(__LINUX_GFP_H) || defined(_LINUX_KERNEL_H)
   80.20  #define gfp_t unsigned
   80.21  #endif
   80.22  
   80.23 @@ -47,6 +51,14 @@
   80.24  #define atomic_notifier_call_chain(chain,val,v) notifier_call_chain(chain,val,v)
   80.25  #endif
   80.26  
   80.27 +#if defined(_LINUX_MM_H) && defined set_page_count
   80.28 +#define init_page_count(page) set_page_count(page, 1)
   80.29 +#endif
   80.30 +
   80.31 +#if defined(__LINUX_GFP_H) && !defined __GFP_NOMEMALLOC
   80.32 +#define __GFP_NOMEMALLOC 0
   80.33 +#endif
   80.34 +
   80.35  #if defined(_LINUX_FS_H) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)
   80.36  #define nonseekable_open(inode, filp) /* Nothing to do */
   80.37  #endif
   80.38 @@ -71,11 +83,19 @@ void *kzalloc(size_t size, int flags);
   80.39  #define end_that_request_last(req, uptodate) end_that_request_last(req)
   80.40  #endif
   80.41  
   80.42 +#if defined(_LINUX_CAPABILITY_H) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
   80.43 +#define capable(cap) (1)
   80.44 +#endif
   80.45 +
   80.46  #if defined(_LINUX_KERNEL_H) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
   80.47  extern char *kasprintf(gfp_t gfp, const char *fmt, ...)
   80.48         __attribute__ ((format (printf, 2, 3)));
   80.49  #endif
   80.50  
   80.51 +#if defined(_LINUX_SYSRQ_H) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)
   80.52 +#define handle_sysrq(x,y,z) handle_sysrq(x,y)
   80.53 +#endif
   80.54 +
   80.55  /*
   80.56   * This variable at present is referenced by netfront, but only in code that
   80.57   * is dead when running in hvm guests. To detect potential active uses of it
    81.1 --- a/unmodified_drivers/linux-2.6/mkbuildtree	Fri Apr 06 10:06:30 2007 -0600
    81.2 +++ b/unmodified_drivers/linux-2.6/mkbuildtree	Fri Apr 06 10:08:30 2007 -0600
    81.3 @@ -17,6 +17,9 @@ for d in $(find ${XL}/drivers/xen/ -maxd
    81.4      if ! echo $d | egrep -q back; then
    81.5          lndir $d $(basename $d) > /dev/null 2>&1
    81.6      fi
    81.7 +    if ! echo $d | egrep -q ball; then
    81.8 +        lndir $d $(basename $d) > /dev/null 2>&1
    81.9 +    fi
   81.10  done
   81.11  
   81.12  ln -sf ${XL}/drivers/xen/core/gnttab.c platform-pci
    82.1 --- a/unmodified_drivers/linux-2.6/overrides.mk	Fri Apr 06 10:06:30 2007 -0600
    82.2 +++ b/unmodified_drivers/linux-2.6/overrides.mk	Fri Apr 06 10:08:30 2007 -0600
    82.3 @@ -4,7 +4,8 @@
    82.4  #
    82.5  # (i.e. we need the native config for things like -mregparm, but
    82.6  # a Xen kernel to find the right headers)
    82.7 -EXTRA_CFLAGS += -D__XEN_INTERFACE_VERSION__=0x00030202
    82.8 +EXTRA_CFLAGS += -D__XEN_INTERFACE_VERSION__=0x00030205
    82.9 +EXTRA_CFLAGS += -DCONFIG_XEN_COMPAT=0xffffff
   82.10  EXTRA_CFLAGS += -I$(M)/include -I$(M)/compat-include -DHAVE_XEN_PLATFORM_COMPAT_H
   82.11  ifeq ($(ARCH),ia64)
   82.12    EXTRA_CFLAGS += -DCONFIG_VMX_GUEST
    83.1 --- a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c	Fri Apr 06 10:06:30 2007 -0600
    83.2 +++ b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c	Fri Apr 06 10:08:30 2007 -0600
    83.3 @@ -208,14 +208,6 @@ static uint64_t get_callback_via(struct 
    83.4  		((uint64_t)(pin - 1) & 3));
    83.5  }
    83.6  
    83.7 -/* Invalidate foreign mappings (e.g., in qemu-based device model). */
    83.8 -static uint16_t invlmap_port;
    83.9 -void xen_invalidate_foreign_mappings(void)
   83.10 -{
   83.11 -	outb(0, invlmap_port);
   83.12 -}
   83.13 -EXPORT_SYMBOL(xen_invalidate_foreign_mappings);
   83.14 -
   83.15  static int __devinit platform_pci_init(struct pci_dev *pdev,
   83.16  				       const struct pci_device_id *ent)
   83.17  {
   83.18 @@ -240,8 +232,6 @@ static int __devinit platform_pci_init(s
   83.19  		return -ENOENT;
   83.20  	}
   83.21  
   83.22 -	invlmap_port = ioaddr;
   83.23 -
   83.24  	if (request_mem_region(mmio_addr, mmio_len, DRV_NAME) == NULL)
   83.25  	{
   83.26  		printk(KERN_ERR ":MEM I/O resource 0x%lx @ 0x%lx busy\n",
    84.1 --- a/unmodified_drivers/linux-2.6/platform-pci/xen_support.c	Fri Apr 06 10:06:30 2007 -0600
    84.2 +++ b/unmodified_drivers/linux-2.6/platform-pci/xen_support.c	Fri Apr 06 10:08:30 2007 -0600
    84.3 @@ -59,12 +59,3 @@ void xen_machphys_update(unsigned long m
    84.4  }
    84.5  EXPORT_SYMBOL(xen_machphys_update);
    84.6  
    84.7 -void balloon_update_driver_allowance(long delta)
    84.8 -{
    84.9 -}
   84.10 -EXPORT_SYMBOL(balloon_update_driver_allowance);
   84.11 -
   84.12 -void balloon_release_driver_page(struct page *page)
   84.13 -{
   84.14 -}
   84.15 -EXPORT_SYMBOL(balloon_release_driver_page);
    85.1 --- a/xen/arch/x86/hvm/hvm.c	Fri Apr 06 10:06:30 2007 -0600
    85.2 +++ b/xen/arch/x86/hvm/hvm.c	Fri Apr 06 10:08:30 2007 -0600
    85.3 @@ -131,7 +131,7 @@ void hvm_do_resume(struct vcpu *v)
    85.4          switch ( p->state )
    85.5          {
    85.6          case STATE_IORESP_READY: /* IORESP_READY -> NONE */
    85.7 -            hvm_io_assist(v);
    85.8 +            hvm_io_assist();
    85.9              break;
   85.10          case STATE_IOREQ_READY:  /* IOREQ_{READY,INPROCESS} -> IORESP_READY */
   85.11          case STATE_IOREQ_INPROCESS:
   85.12 @@ -146,48 +146,6 @@ void hvm_do_resume(struct vcpu *v)
   85.13      }
   85.14  }
   85.15  
   85.16 -/* Called from the tools when saving a domain to make sure the io
   85.17 - * request-response ring is entirely empty. */
   85.18 -static int hvmop_drain_io(
   85.19 -    XEN_GUEST_HANDLE(xen_hvm_drain_io_t) uop)
   85.20 -{
   85.21 -    struct xen_hvm_drain_io op;
   85.22 -    struct domain *d;
   85.23 -    struct vcpu *v;
   85.24 -    ioreq_t *p;
   85.25 -    int rc;
   85.26 -
   85.27 -    if ( copy_from_guest(&op, uop, 1) )
   85.28 -        return -EFAULT;
   85.29 -
   85.30 -    if ( !IS_PRIV(current->domain) )
   85.31 -        return -EPERM;
   85.32 -
   85.33 -    d = rcu_lock_domain_by_id(op.domid);
   85.34 -    if ( d == NULL )
   85.35 -        return -ESRCH;
   85.36 -
   85.37 -    rc = -EINVAL;
   85.38 -    /* Can't do this to yourself, or to a domain without an ioreq ring */
   85.39 -    if ( d == current->domain || !is_hvm_domain(d) || get_sp(d) == NULL )
   85.40 -        goto out;
   85.41 -
   85.42 -    rc = 0;
   85.43 -
   85.44 -    domain_pause(d);  /* It's not safe to do this to running vcpus */
   85.45 -    for_each_vcpu(d, v)
   85.46 -    {
   85.47 -        p = &get_vio(v->domain, v->vcpu_id)->vp_ioreq;
   85.48 -        if ( p->state == STATE_IORESP_READY )
   85.49 -            hvm_io_assist(v);
   85.50 -    }
   85.51 -    domain_unpause(d);
   85.52 -
   85.53 - out:
   85.54 -    rcu_unlock_domain(d);
   85.55 -    return rc;
   85.56 -}
   85.57 -
   85.58  int hvm_domain_initialise(struct domain *d)
   85.59  {
   85.60      int rc;
   85.61 @@ -563,19 +521,13 @@ static hvm_hypercall_t *hvm_hypercall_ta
   85.62      HYPERCALL(hvm_op)
   85.63  };
   85.64  
   85.65 -void hvm_do_hypercall(struct cpu_user_regs *pregs)
   85.66 +static void __hvm_do_hypercall(struct cpu_user_regs *pregs)
   85.67  {
   85.68 -    if ( unlikely(ring_3(pregs)) )
   85.69 -    {
   85.70 -        pregs->eax = -EPERM;
   85.71 -        return;
   85.72 -    }
   85.73 -
   85.74      if ( (pregs->eax >= NR_hypercalls) || !hvm_hypercall_table[pregs->eax] )
   85.75      {
   85.76 -        gdprintk(XENLOG_WARNING, "HVM vcpu %d:%d did a bad hypercall %d.\n",
   85.77 -                current->domain->domain_id, current->vcpu_id,
   85.78 -                pregs->eax);
   85.79 +        if ( pregs->eax != __HYPERVISOR_grant_table_op )
   85.80 +            gdprintk(XENLOG_WARNING, "HVM vcpu %d:%d bad hypercall %d.\n",
   85.81 +                     current->domain->domain_id, current->vcpu_id, pregs->eax);
   85.82          pregs->eax = -ENOSYS;
   85.83          return;
   85.84      }
   85.85 @@ -641,20 +593,14 @@ static hvm_hypercall_t *hvm_hypercall32_
   85.86      HYPERCALL(event_channel_op)
   85.87  };
   85.88  
   85.89 -void hvm_do_hypercall(struct cpu_user_regs *pregs)
   85.90 +static void __hvm_do_hypercall(struct cpu_user_regs *pregs)
   85.91  {
   85.92 -    if ( unlikely(ring_3(pregs)) )
   85.93 -    {
   85.94 -        pregs->rax = -EPERM;
   85.95 -        return;
   85.96 -    }
   85.97 -
   85.98      pregs->rax = (uint32_t)pregs->eax; /* mask in case compat32 caller */
   85.99      if ( (pregs->rax >= NR_hypercalls) || !hvm_hypercall64_table[pregs->rax] )
  85.100      {
  85.101 -        gdprintk(XENLOG_WARNING, "HVM vcpu %d:%d did a bad hypercall %ld.\n",
  85.102 -                current->domain->domain_id, current->vcpu_id,
  85.103 -                pregs->rax);
  85.104 +        if ( pregs->rax != __HYPERVISOR_grant_table_op )
  85.105 +            gdprintk(XENLOG_WARNING, "HVM vcpu %d:%d bad hypercall %ld.\n",
  85.106 +                     current->domain->domain_id, current->vcpu_id, pregs->rax);
  85.107          pregs->rax = -ENOSYS;
  85.108          return;
  85.109      }
  85.110 @@ -679,6 +625,37 @@ void hvm_do_hypercall(struct cpu_user_re
  85.111  
  85.112  #endif /* defined(__x86_64__) */
  85.113  
  85.114 +int hvm_do_hypercall(struct cpu_user_regs *pregs)
  85.115 +{
  85.116 +    int flush, preempted;
  85.117 +    unsigned long old_eip;
  85.118 +
  85.119 +    if ( unlikely(ring_3(pregs)) )
  85.120 +    {
  85.121 +        pregs->eax = -EPERM;
  85.122 +        return 0;
  85.123 +    }
  85.124 +
  85.125 +    /*
  85.126 +     * NB. In future flush only on decrease_reservation.
  85.127 +     * For now we also need to flush when pages are added, as qemu-dm is not
  85.128 +     * yet capable of faulting pages into an existing valid mapcache bucket.
  85.129 +     */
  85.130 +    flush = ((uint32_t)pregs->eax == __HYPERVISOR_memory_op);
  85.131 +
  85.132 +    /* Check for preemption: RIP will be modified from this dummy value. */
  85.133 +    old_eip = pregs->eip;
  85.134 +    pregs->eip = 0xF0F0F0FF;
  85.135 +
  85.136 +    __hvm_do_hypercall(pregs);
  85.137 +
  85.138 +    preempted = (pregs->eip != 0xF0F0F0FF);
  85.139 +    pregs->eip = old_eip;
  85.140 +
  85.141 +    return (preempted ? HVM_HCALL_preempted :
  85.142 +            flush ? HVM_HCALL_invalidate : HVM_HCALL_completed);
  85.143 +}
  85.144 +
  85.145  void hvm_update_guest_cr3(struct vcpu *v, unsigned long guest_cr3)
  85.146  {
  85.147      v->arch.hvm_vcpu.hw_cr3 = guest_cr3;
  85.148 @@ -963,12 +940,6 @@ long do_hvm_op(unsigned long op, XEN_GUE
  85.149              guest_handle_cast(arg, xen_hvm_set_pci_link_route_t));
  85.150          break;
  85.151  
  85.152 -    case HVMOP_drain_io:
  85.153 -        rc = hvmop_drain_io(
  85.154 -            guest_handle_cast(arg, xen_hvm_drain_io_t));
  85.155 -        break;
  85.156 -
  85.157 -
  85.158      default:
  85.159      {
  85.160          gdprintk(XENLOG_WARNING, "Bad HVM op %ld.\n", op);
    86.1 --- a/xen/arch/x86/hvm/io.c	Fri Apr 06 10:06:30 2007 -0600
    86.2 +++ b/xen/arch/x86/hvm/io.c	Fri Apr 06 10:08:30 2007 -0600
    86.3 @@ -289,25 +289,11 @@ static void set_reg_value (int size, int
    86.4  
    86.5  long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs);
    86.6  
    86.7 -static inline void set_eflags_CF(int size, unsigned long v1,
    86.8 -                                 unsigned long v2, struct cpu_user_regs *regs)
    86.9 -{
   86.10 -    unsigned long mask;
   86.11 -
   86.12 -    if ( size == BYTE_64 )
   86.13 -        size = BYTE;
   86.14 -    ASSERT((size <= sizeof(mask)) && (size > 0));
   86.15 -
   86.16 -    mask = ~0UL >> (8 * (sizeof(mask) - size));
   86.17 -
   86.18 -    if ((v1 & mask) > (v2 & mask))
   86.19 -        regs->eflags |= X86_EFLAGS_CF;
   86.20 -    else
   86.21 -        regs->eflags &= ~X86_EFLAGS_CF;
   86.22 -}
   86.23 -
   86.24 -static inline void set_eflags_OF(int size, unsigned long v1,
   86.25 -                                 unsigned long v2, unsigned long v3,
   86.26 +static inline void set_eflags_CF(int size,
   86.27 +                                 unsigned int instr,
   86.28 +                                 unsigned long result,
   86.29 +                                 unsigned long src,
   86.30 +                                 unsigned long dst,
   86.31                                   struct cpu_user_regs *regs)
   86.32  {
   86.33      unsigned long mask;
   86.34 @@ -318,19 +304,62 @@ static inline void set_eflags_OF(int siz
   86.35  
   86.36      mask = ~0UL >> (8 * (sizeof(mask) - size));
   86.37  
   86.38 -    if ((v3 ^ v2) & (v3 ^ v1) & mask)
   86.39 -        regs->eflags |= X86_EFLAGS_OF;
   86.40 +    if ( instr == INSTR_ADD )
   86.41 +    {
   86.42 +        /* CF=1 <==> result is less than the augend and addend) */
   86.43 +        if ( (result & mask) < (dst & mask) )
   86.44 +        {
   86.45 +            ASSERT((result & mask) < (src & mask));
   86.46 +            regs->eflags |= X86_EFLAGS_CF;
   86.47 +        }
   86.48 +    }
   86.49 +    else
   86.50 +    {
   86.51 +        ASSERT( instr == INSTR_CMP || instr == INSTR_SUB );
   86.52 +        if ( (src & mask) > (dst & mask) )
   86.53 +            regs->eflags |= X86_EFLAGS_CF;
   86.54 +    }
   86.55  }
   86.56  
   86.57 -static inline void set_eflags_AF(int size, unsigned long v1,
   86.58 -                                 unsigned long v2, unsigned long v3,
   86.59 +static inline void set_eflags_OF(int size,
   86.60 +                                 unsigned int instr,
   86.61 +                                 unsigned long result,
   86.62 +                                 unsigned long src,
   86.63 +                                 unsigned long dst,
   86.64                                   struct cpu_user_regs *regs)
   86.65  {
   86.66 -    if ((v1 ^ v2 ^ v3) & 0x10)
   86.67 +    unsigned long mask;
   86.68 +
   86.69 +    if ( size == BYTE_64 )
   86.70 +        size = BYTE;
   86.71 +    ASSERT((size <= sizeof(mask)) && (size > 0));
   86.72 +
   86.73 +    mask =  1UL << ((8*size) - 1);
   86.74 +
   86.75 +    if ( instr == INSTR_ADD )
   86.76 +    {
   86.77 +        if ((src ^ result) & (dst ^ result) & mask);
   86.78 +            regs->eflags |= X86_EFLAGS_OF;
   86.79 +    }
   86.80 +    else
   86.81 +    {
   86.82 +        ASSERT(instr == INSTR_CMP || instr == INSTR_SUB);
   86.83 +        if ((dst ^ src) & (dst ^ result) & mask)
   86.84 +            regs->eflags |= X86_EFLAGS_OF;
   86.85 +    }
   86.86 +}
   86.87 +
   86.88 +static inline void set_eflags_AF(int size,
   86.89 +                                 unsigned long result,
   86.90 +                                 unsigned long src,
   86.91 +                                 unsigned long dst,
   86.92 +                                 struct cpu_user_regs *regs)
   86.93 +{
   86.94 +    if ((result ^ src ^ dst) & 0x10)
   86.95          regs->eflags |= X86_EFLAGS_AF;
   86.96  }
   86.97  
   86.98 -static inline void set_eflags_ZF(int size, unsigned long v1,
   86.99 +static inline void set_eflags_ZF(int size, unsigned long result,
  86.100                                   struct cpu_user_regs *regs)
  86.101  {
  86.102      unsigned long mask;
  86.103 @@ -341,11 +370,11 @@ static inline void set_eflags_ZF(int siz
  86.104  
  86.105      mask = ~0UL >> (8 * (sizeof(mask) - size));
  86.106  
  86.107 -    if ((v1 & mask) == 0)
  86.108 +    if ((result & mask) == 0)
  86.109          regs->eflags |= X86_EFLAGS_ZF;
  86.110  }
  86.111  
  86.112 -static inline void set_eflags_SF(int size, unsigned long v1,
  86.113 +static inline void set_eflags_SF(int size, unsigned long result,
  86.114                                   struct cpu_user_regs *regs)
  86.115  {
  86.116      unsigned long mask;
  86.117 @@ -354,9 +383,9 @@ static inline void set_eflags_SF(int siz
  86.118          size = BYTE;
  86.119      ASSERT((size <= sizeof(mask)) && (size > 0));
  86.120  
  86.121 -    mask = ~0UL >> (8 * (sizeof(mask) - size));
  86.122 +    mask = 1UL << ((8*size) - 1);
  86.123  
  86.124 -    if (v1 & mask)
  86.125 +    if (result & mask)
  86.126          regs->eflags |= X86_EFLAGS_SF;
  86.127  }
  86.128  
  86.129 @@ -379,10 +408,10 @@ static char parity_table[256] = {
  86.130      1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
  86.131  };
  86.132  
  86.133 -static inline void set_eflags_PF(int size, unsigned long v1,
  86.134 +static inline void set_eflags_PF(int size, unsigned long result,
  86.135                                   struct cpu_user_regs *regs)
  86.136  {
  86.137 -    if (parity_table[v1 & 0xFF])
  86.138 +    if (parity_table[result & 0xFF])
  86.139          regs->eflags |= X86_EFLAGS_PF;
  86.140  }
  86.141  
  86.142 @@ -454,7 +483,7 @@ static void hvm_mmio_assist(struct cpu_u
  86.143  {
  86.144      int sign = p->df ? -1 : 1;
  86.145      int size = -1, index = -1;
  86.146 -    unsigned long value = 0, diff = 0;
  86.147 +    unsigned long value = 0, result = 0;
  86.148      unsigned long src, dst;
  86.149  
  86.150      src = mmio_opp->operand[0];
  86.151 @@ -575,58 +604,15 @@ static void hvm_mmio_assist(struct cpu_u
  86.152          if (src & REGISTER) {
  86.153              index = operand_index(src);
  86.154              value = get_reg_value(size, index, 0, regs);
  86.155 -            diff = (unsigned long) p->data & value;
  86.156 +            result = (unsigned long) p->data & value;
  86.157          } else if (src & IMMEDIATE) {
  86.158              value = mmio_opp->immediate;
  86.159 -            diff = (unsigned long) p->data & value;
  86.160 -        } else if (src & MEMORY) {
  86.161 -            index = operand_index(dst);
  86.162 -            value = get_reg_value(size, index, 0, regs);
  86.163 -            diff = (unsigned long) p->data & value;
  86.164 -            set_reg_value(size, index, 0, regs, diff);
  86.165 -        }
  86.166 -        break;
  86.167 -
  86.168 -    case INSTR_ADD:
  86.169 -        if (src & REGISTER) {
  86.170 -            index = operand_index(src);
  86.171 -            value = get_reg_value(size, index, 0, regs);
  86.172 -            diff = (unsigned long) p->data + value;
  86.173 -        } else if (src & IMMEDIATE) {
  86.174 -            value = mmio_opp->immediate;
  86.175 -            diff = (unsigned long) p->data + value;
  86.176 +            result = (unsigned long) p->data & value;
  86.177          } else if (src & MEMORY) {
  86.178              index = operand_index(dst);
  86.179              value = get_reg_value(size, index, 0, regs);
  86.180 -            diff = (unsigned long) p->data + value;
  86.181 -            set_reg_value(size, index, 0, regs, diff);
  86.182 -        }
  86.183 -
  86.184 -        /*
  86.185 -         * The OF and CF flags are cleared; the SF, ZF, and PF
  86.186 -         * flags are set according to the result. The state of
  86.187 -         * the AF flag is undefined.
  86.188 -         */
  86.189 -        regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
  86.190 -                          X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
  86.191 -        set_eflags_ZF(size, diff, regs);
  86.192 -        set_eflags_SF(size, diff, regs);
  86.193 -        set_eflags_PF(size, diff, regs);
  86.194 -        break;
  86.195 -
  86.196 -    case INSTR_OR:
  86.197 -        if (src & REGISTER) {
  86.198 -            index = operand_index(src);
  86.199 -            value = get_reg_value(size, index, 0, regs);
  86.200 -            diff = (unsigned long) p->data | value;
  86.201 -        } else if (src & IMMEDIATE) {
  86.202 -            value = mmio_opp->immediate;
  86.203 -            diff = (unsigned long) p->data | value;
  86.204 -        } else if (src & MEMORY) {
  86.205 -            index = operand_index(dst);
  86.206 -            value = get_reg_value(size, index, 0, regs);
  86.207 -            diff = (unsigned long) p->data | value;
  86.208 -            set_reg_value(size, index, 0, regs, diff);
  86.209 +            result = (unsigned long) p->data & value;
  86.210 +            set_reg_value(size, index, 0, regs, result);
  86.211          }
  86.212  
  86.213          /*
  86.214 @@ -636,24 +622,55 @@ static void hvm_mmio_assist(struct cpu_u
  86.215           */
  86.216          regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
  86.217                            X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
  86.218 -        set_eflags_ZF(size, diff, regs);
  86.219 -        set_eflags_SF(size, diff, regs);
  86.220 -        set_eflags_PF(size, diff, regs);
  86.221 +        set_eflags_ZF(size, result, regs);
  86.222 +        set_eflags_SF(size, result, regs);
  86.223 +        set_eflags_PF(size, result, regs);
  86.224          break;
  86.225  
  86.226 -    case INSTR_XOR:
  86.227 +    case INSTR_ADD:
  86.228          if (src & REGISTER) {
  86.229              index = operand_index(src);
  86.230              value = get_reg_value(size, index, 0, regs);
  86.231 -            diff = (unsigned long) p->data ^ value;
  86.232 +            result = (unsigned long) p->data + value;
  86.233          } else if (src & IMMEDIATE) {
  86.234              value = mmio_opp->immediate;
  86.235 -            diff = (unsigned long) p->data ^ value;
  86.236 +            result = (unsigned long) p->data + value;
  86.237          } else if (src & MEMORY) {
  86.238              index = operand_index(dst);
  86.239              value = get_reg_value(size, index, 0, regs);
  86.240 -            diff = (unsigned long) p->data ^ value;
  86.241 -            set_reg_value(size, index, 0, regs, diff);
  86.242 +            result = (unsigned long) p->data + value;
  86.243 +            set_reg_value(size, index, 0, regs, result);
  86.244 +        }
  86.245 +
  86.246 +        /*
  86.247 +         * The CF, OF, SF, ZF, AF, and PF flags are set according
  86.248 +         * to the result
  86.249 +         */
  86.250 +        regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|X86_EFLAGS_AF|
  86.251 +                          X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
  86.252 +        set_eflags_CF(size, mmio_opp->instr, result, value,
  86.253 +                      (unsigned long) p->data, regs);
  86.254 +        set_eflags_OF(size, mmio_opp->instr, result, value,
  86.255 +                      (unsigned long) p->data, regs);
  86.256 +        set_eflags_AF(size, result, value, (unsigned long) p->data, regs);
  86.257 +        set_eflags_ZF(size, result, regs);
  86.258 +        set_eflags_SF(size, result, regs);
  86.259 +        set_eflags_PF(size, result, regs);
  86.260 +        break;
  86.261 +
  86.262 +    case INSTR_OR:
  86.263 +        if (src & REGISTER) {
  86.264 +            index = operand_index(src);
  86.265 +            value = get_reg_value(size, index, 0, regs);
  86.266 +            result = (unsigned long) p->data | value;
  86.267 +        } else if (src & IMMEDIATE) {
  86.268 +            value = mmio_opp->immediate;
  86.269 +            result = (unsigned long) p->data | value;
  86.270 +        } else if (src & MEMORY) {
  86.271 +            index = operand_index(dst);
  86.272 +            value = get_reg_value(size, index, 0, regs);
  86.273 +            result = (unsigned long) p->data | value;
  86.274 +            set_reg_value(size, index, 0, regs, result);
  86.275          }
  86.276  
  86.277          /*
  86.278 @@ -663,9 +680,36 @@ static void hvm_mmio_assist(struct cpu_u
  86.279           */
  86.280          regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
  86.281                            X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
  86.282 -        set_eflags_ZF(size, diff, regs);
  86.283 -        set_eflags_SF(size, diff, regs);
  86.284 -        set_eflags_PF(size, diff, regs);
  86.285 +        set_eflags_ZF(size, result, regs);
  86.286 +        set_eflags_SF(size, result, regs);
  86.287 +        set_eflags_PF(size, result, regs);
  86.288 +        break;
  86.289 +
  86.290 +    case INSTR_XOR:
  86.291 +        if (src & REGISTER) {
  86.292 +            index = operand_index(src);
  86.293 +            value = get_reg_value(size, index, 0, regs);
  86.294 +            result = (unsigned long) p->data ^ value;
  86.295 +        } else if (src & IMMEDIATE) {
  86.296 +            value = mmio_opp->immediate;
  86.297 +            result = (unsigned long) p->data ^ value;
  86.298 +        } else if (src & MEMORY) {
  86.299 +            index = operand_index(dst);
  86.300 +            value = get_reg_value(size, index, 0, regs);
  86.301 +            result = (unsigned long) p->data ^ value;
  86.302 +            set_reg_value(size, index, 0, regs, result);
  86.303 +        }
  86.304 +
  86.305 +        /*
  86.306 +         * The OF and CF flags are cleared; the SF, ZF, and PF
  86.307 +         * flags are set according to the result. The state of
  86.308 +         * the AF flag is undefined.
  86.309 +         */
  86.310 +        regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
  86.311 +                          X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
  86.312 +        set_eflags_ZF(size, result, regs);
  86.313 +        set_eflags_SF(size, result, regs);
  86.314 +        set_eflags_PF(size, result, regs);
  86.315          break;
  86.316  
  86.317      case INSTR_CMP:
  86.318 @@ -673,16 +717,16 @@ static void hvm_mmio_assist(struct cpu_u
  86.319          if (src & REGISTER) {
  86.320              index = operand_index(src);
  86.321              value = get_reg_value(size, index, 0, regs);
  86.322 -            diff = (unsigned long) p->data - value;
  86.323 +            result = (unsigned long) p->data - value;
  86.324          } else if (src & IMMEDIATE) {
  86.325              value = mmio_opp->immediate;
  86.326 -            diff = (unsigned long) p->data - value;
  86.327 +            result = (unsigned long) p->data - value;
  86.328          } else if (src & MEMORY) {
  86.329              index = operand_index(dst);
  86.330              value = get_reg_value(size, index, 0, regs);
  86.331 -            diff = value - (unsigned long) p->data;
  86.332 +            result = value - (unsigned long) p->data;
  86.333              if ( mmio_opp->instr == INSTR_SUB )
  86.334 -                set_reg_value(size, index, 0, regs, diff);
  86.335 +                set_reg_value(size, index, 0, regs, result);
  86.336          }
  86.337  
  86.338          /*
  86.339 @@ -691,12 +735,24 @@ static void hvm_mmio_assist(struct cpu_u
  86.340           */
  86.341          regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|X86_EFLAGS_AF|
  86.342                            X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
  86.343 -        set_eflags_CF(size, value, (unsigned long) p->data, regs);
  86.344 -        set_eflags_OF(size, diff, value, (unsigned long) p->data, regs);
  86.345 -        set_eflags_AF(size, diff, value, (unsigned long) p->data, regs);
  86.346 -        set_eflags_ZF(size, diff, regs);
  86.347 -        set_eflags_SF(size, diff, regs);
  86.348 -        set_eflags_PF(size, diff, regs);
  86.349 +        if ( src & (REGISTER | IMMEDIATE) )
  86.350 +        {
  86.351 +            set_eflags_CF(size, mmio_opp->instr, result, value,
  86.352 +                          (unsigned long) p->data, regs);
  86.353 +            set_eflags_OF(size, mmio_opp->instr, result, value,
  86.354 +                          (unsigned long) p->data, regs);
  86.355 +        }
  86.356 +        else
  86.357 +        {
  86.358 +            set_eflags_CF(size, mmio_opp->instr, result,
  86.359 +                          (unsigned long) p->data, value, regs);
  86.360 +            set_eflags_OF(size, mmio_opp->instr, result,
  86.361 +                          (unsigned long) p->data, value, regs);
  86.362 +        }
  86.363 +        set_eflags_AF(size, result, value, (unsigned long) p->data, regs);
  86.364 +        set_eflags_ZF(size, result, regs);
  86.365 +        set_eflags_SF(size, result, regs);
  86.366 +        set_eflags_PF(size, result, regs);
  86.367          break;
  86.368  
  86.369      case INSTR_TEST:
  86.370 @@ -709,16 +765,16 @@ static void hvm_mmio_assist(struct cpu_u
  86.371              index = operand_index(dst);
  86.372              value = get_reg_value(size, index, 0, regs);
  86.373          }
  86.374 -        diff = (unsigned long) p->data & value;
  86.375 +        result = (unsigned long) p->data & value;
  86.376  
  86.377          /*
  86.378           * Sets the SF, ZF, and PF status flags. CF and OF are set to 0
  86.379           */
  86.380          regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|
  86.381                            X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
  86.382 -        set_eflags_ZF(size, diff, regs);
  86.383 -        set_eflags_SF(size, diff, regs);
  86.384 -        set_eflags_PF(size, diff, regs);
  86.385 +        set_eflags_ZF(size, result, regs);
  86.386 +        set_eflags_SF(size, result, regs);
  86.387 +        set_eflags_PF(size, result, regs);
  86.388          break;
  86.389  
  86.390      case INSTR_BT:
  86.391 @@ -764,13 +820,14 @@ static void hvm_mmio_assist(struct cpu_u
  86.392      }
  86.393  }
  86.394  
  86.395 -void hvm_io_assist(struct vcpu *v)
  86.396 +void hvm_io_assist(void)
  86.397  {
  86.398      vcpu_iodata_t *vio;
  86.399      ioreq_t *p;
  86.400      struct cpu_user_regs *regs;
  86.401      struct hvm_io_op *io_opp;
  86.402      unsigned long gmfn;
  86.403 +    struct vcpu *v = current;
  86.404      struct domain *d = v->domain;
  86.405  
  86.406      io_opp = &v->arch.hvm_vcpu.io_op;
  86.407 @@ -788,10 +845,17 @@ void hvm_io_assist(struct vcpu *v)
  86.408  
  86.409      p->state = STATE_IOREQ_NONE;
  86.410  
  86.411 -    if ( p->type == IOREQ_TYPE_PIO )
  86.412 +    switch ( p->type )
  86.413 +    {
  86.414 +    case IOREQ_TYPE_INVALIDATE:
  86.415 +        goto out;
  86.416 +    case IOREQ_TYPE_PIO:
  86.417          hvm_pio_assist(regs, p, io_opp);
  86.418 -    else
  86.419 +        break;
  86.420 +    default:
  86.421          hvm_mmio_assist(regs, p, io_opp);
  86.422 +        break;
  86.423 +    }
  86.424  
  86.425      /* Copy register changes back into current guest state. */
  86.426      hvm_load_cpu_guest_regs(v, regs);
  86.427 @@ -804,6 +868,7 @@ void hvm_io_assist(struct vcpu *v)
  86.428          mark_dirty(d, gmfn);
  86.429      }
  86.430  
  86.431 + out:
  86.432      vcpu_end_shutdown_deferral(v);
  86.433  }
  86.434  
    87.1 --- a/xen/arch/x86/hvm/irq.c	Fri Apr 06 10:06:30 2007 -0600
    87.2 +++ b/xen/arch/x86/hvm/irq.c	Fri Apr 06 10:08:30 2007 -0600
    87.3 @@ -337,6 +337,21 @@ int is_isa_irq_masked(struct vcpu *v, in
    87.4              domain_vioapic(v->domain)->redirtbl[gsi].fields.mask);
    87.5  }
    87.6  
    87.7 +/*
    87.8 + * TODO: 1. Should not need special treatment of event-channel events.
    87.9 + *       2. Should take notice of interrupt shadows (or clear them).
   87.10 + */
   87.11 +int hvm_local_events_need_delivery(struct vcpu *v)
   87.12 +{
   87.13 +    int pending;
   87.14 +
   87.15 +    pending = (vcpu_info(v, evtchn_upcall_pending) || cpu_has_pending_irq(v));
   87.16 +    if ( unlikely(pending) )
   87.17 +        pending = hvm_interrupts_enabled(v); 
   87.18 +
   87.19 +    return pending;
   87.20 +}
   87.21 +
   87.22  #if 0 /* Keep for debugging */
   87.23  static void irq_dump(struct domain *d)
   87.24  {
    88.1 --- a/xen/arch/x86/hvm/platform.c	Fri Apr 06 10:06:30 2007 -0600
    88.2 +++ b/xen/arch/x86/hvm/platform.c	Fri Apr 06 10:08:30 2007 -0600
    88.3 @@ -865,7 +865,7 @@ void send_pio_req(unsigned long port, un
    88.4      if ( hvm_portio_intercept(p) )
    88.5      {
    88.6          p->state = STATE_IORESP_READY;
    88.7 -        hvm_io_assist(v);
    88.8 +        hvm_io_assist();
    88.9          return;
   88.10      }
   88.11  
   88.12 @@ -914,7 +914,7 @@ static void send_mmio_req(unsigned char 
   88.13      if ( hvm_mmio_intercept(p) || hvm_buffered_io_intercept(p) )
   88.14      {
   88.15          p->state = STATE_IORESP_READY;
   88.16 -        hvm_io_assist(v);
   88.17 +        hvm_io_assist();
   88.18          return;
   88.19      }
   88.20  
   88.21 @@ -941,6 +941,34 @@ void send_timeoffset_req(unsigned long t
   88.22          printk("Unsuccessful timeoffset update\n");
   88.23  }
   88.24  
   88.25 +/* Ask ioemu mapcache to invalidate mappings. */
   88.26 +void send_invalidate_req(void)
   88.27 +{
   88.28 +    struct vcpu *v = current;
   88.29 +    vcpu_iodata_t *vio;
   88.30 +    ioreq_t *p;
   88.31 +
   88.32 +    vio = get_vio(v->domain, v->vcpu_id);
   88.33 +    if ( vio == NULL )
   88.34 +    {
   88.35 +        printk("bad shared page: %lx\n", (unsigned long) vio);
   88.36 +        domain_crash_synchronous();
   88.37 +    }
   88.38 +
   88.39 +    p = &vio->vp_ioreq;
   88.40 +    if ( p->state != STATE_IOREQ_NONE )
   88.41 +        printk("WARNING: send invalidate req with something "
   88.42 +               "already pending (%d)?\n", p->state);
   88.43 +
   88.44 +    p->type = IOREQ_TYPE_INVALIDATE;
   88.45 +    p->size = 4;
   88.46 +    p->dir = IOREQ_WRITE;
   88.47 +    p->data = ~0UL; /* flush all */
   88.48 +    p->io_count++;
   88.49 +
   88.50 +    hvm_send_assist_req(v);
   88.51 +}
   88.52 +
   88.53  static void mmio_operands(int type, unsigned long gpa,
   88.54                            struct hvm_io_op *mmio_op,
   88.55                            unsigned char op_size)
    89.1 --- a/xen/arch/x86/hvm/svm/svm.c	Fri Apr 06 10:06:30 2007 -0600
    89.2 +++ b/xen/arch/x86/hvm/svm/svm.c	Fri Apr 06 10:08:30 2007 -0600
    89.3 @@ -131,66 +131,6 @@ static void svm_store_cpu_guest_regs(
    89.4      }
    89.5  }
    89.6  
    89.7 -
    89.8 -static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
    89.9 -{
   89.10 -    u64 msr_content = 0;
   89.11 -    struct vcpu *v = current;
   89.12 -    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
   89.13 -
   89.14 -    switch ((u32)regs->ecx)
   89.15 -    {
   89.16 -    case MSR_EFER:
   89.17 -        msr_content = v->arch.hvm_svm.cpu_shadow_efer;
   89.18 -        break;
   89.19 -
   89.20 -#ifdef __x86_64__
   89.21 -    case MSR_FS_BASE:
   89.22 -        msr_content = vmcb->fs.base;
   89.23 -        goto check_long_mode;
   89.24 -
   89.25 -    case MSR_GS_BASE:
   89.26 -        msr_content = vmcb->gs.base;
   89.27 -        goto check_long_mode;
   89.28 -
   89.29 -    case MSR_SHADOW_GS_BASE:
   89.30 -        msr_content = vmcb->kerngsbase;
   89.31 -    check_long_mode:
   89.32 -        if ( !svm_long_mode_enabled(v) )
   89.33 -        {
   89.34 -            svm_inject_exception(v, TRAP_gp_fault, 1, 0);
   89.35 -            return 0;
   89.36 -        }
   89.37 -        break;
   89.38 -#endif
   89.39 -
   89.40 -    case MSR_STAR:
   89.41 -        msr_content = vmcb->star;
   89.42 -        break;
   89.43 - 
   89.44 -    case MSR_LSTAR:
   89.45 -        msr_content = vmcb->lstar;
   89.46 -        break;
   89.47 - 
   89.48 -    case MSR_CSTAR:
   89.49 -        msr_content = vmcb->cstar;
   89.50 -        break;
   89.51 - 
   89.52 -    case MSR_SYSCALL_MASK:
   89.53 -        msr_content = vmcb->sfmask;
   89.54 -        break;
   89.55 -    default:
   89.56 -        return 0;
   89.57 -    }
   89.58 -
   89.59 -    HVM_DBG_LOG(DBG_LEVEL_2, "msr_content: %"PRIx64"\n",
   89.60 -                msr_content);
   89.61 -
   89.62 -    regs->eax = (u32)(msr_content >>  0);
   89.63 -    regs->edx = (u32)(msr_content >> 32);
   89.64 -    return 1;
   89.65 -}
   89.66 -
   89.67  static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
   89.68  {
   89.69      u64 msr_content = (u32)regs->eax | ((u64)regs->edx << 32);
   89.70 @@ -242,52 +182,12 @@ static inline int long_mode_do_msr_write
   89.71  
   89.72          break;
   89.73  
   89.74 -#ifdef __x86_64__
   89.75 -    case MSR_FS_BASE:
   89.76 -    case MSR_GS_BASE:
   89.77 -    case MSR_SHADOW_GS_BASE:
   89.78 -        if ( !svm_long_mode_enabled(v) )
   89.79 -            goto gp_fault;
   89.80 -
   89.81 -        if ( !is_canonical_address(msr_content) )
   89.82 -            goto uncanonical_address;
   89.83 -
   89.84 -        if ( ecx == MSR_FS_BASE )
   89.85 -            vmcb->fs.base = msr_content;
   89.86 -        else if ( ecx == MSR_GS_BASE )
   89.87 -            vmcb->gs.base = msr_content;
   89.88 -        else
   89.89 -            vmcb->kerngsbase = msr_content;
   89.90 -        break;
   89.91 -#endif
   89.92 - 
   89.93 -    case MSR_STAR:
   89.94 -        vmcb->star = msr_content;
   89.95 -        break;
   89.96 - 
   89.97 -    case MSR_LSTAR:
   89.98 -    case MSR_CSTAR:
   89.99 -        if ( !is_canonical_address(msr_content) )
  89.100 -            goto uncanonical_address;
  89.101 -
  89.102 -        if ( ecx == MSR_LSTAR )
  89.103 -            vmcb->lstar = msr_content;
  89.104 -        else
  89.105 -            vmcb->cstar = msr_content;
  89.106 -        break;
  89.107 - 
  89.108 -    case MSR_SYSCALL_MASK:
  89.109 -        vmcb->sfmask = msr_content;
  89.110 -        break;
  89.111 -
  89.112      default:
  89.113          return 0;
  89.114      }
  89.115  
  89.116      return 1;
  89.117  
  89.118 - uncanonical_address:
  89.119 -    HVM_DBG_LOG(DBG_LEVEL_1, "Not cano address of msr write %x\n", ecx);
  89.120   gp_fault:
  89.121      svm_inject_exception(v, TRAP_gp_fault, 1, 0);
  89.122      return 0;
  89.123 @@ -598,6 +498,12 @@ static int svm_realmode(struct vcpu *v)
  89.124      return (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE);
  89.125  }
  89.126  
  89.127 +static int svm_interrupts_enabled(struct vcpu *v)
  89.128 +{
  89.129 +    unsigned long eflags = v->arch.hvm_svm.vmcb->rflags;
  89.130 +    return !irq_masked(eflags); 
  89.131 +}
  89.132 +
  89.133  static int svm_guest_x86_mode(struct vcpu *v)
  89.134  {
  89.135      struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
  89.136 @@ -900,6 +806,7 @@ static struct hvm_function_table svm_fun
  89.137      .paging_enabled       = svm_paging_enabled,
  89.138      .long_mode_enabled    = svm_long_mode_enabled,
  89.139      .pae_enabled          = svm_pae_enabled,
  89.140 +    .interrupts_enabled   = svm_interrupts_enabled,
  89.141      .guest_x86_mode       = svm_guest_x86_mode,
  89.142      .get_guest_ctrl_reg   = svm_get_ctrl_reg,
  89.143      .get_segment_base     = svm_get_segment_base,
  89.144 @@ -2013,22 +1920,14 @@ static inline void svm_do_msr_access(
  89.145          case MSR_IA32_TIME_STAMP_COUNTER:
  89.146              msr_content = hvm_get_guest_time(v);
  89.147              break;
  89.148 -        case MSR_IA32_SYSENTER_CS:
  89.149 -            msr_content = vmcb->sysenter_cs;
  89.150 -            break;
  89.151 -        case MSR_IA32_SYSENTER_ESP: 
  89.152 -            msr_content = vmcb->sysenter_esp;
  89.153 -            break;
  89.154 -        case MSR_IA32_SYSENTER_EIP:     
  89.155 -            msr_content = vmcb->sysenter_eip;
  89.156 -            break;
  89.157          case MSR_IA32_APICBASE:
  89.158              msr_content = vcpu_vlapic(v)->hw.apic_base_msr;
  89.159              break;
  89.160 +        case MSR_EFER:
  89.161 +            msr_content = v->arch.hvm_svm.cpu_shadow_efer;
  89.162 +            break;
  89.163 +
  89.164          default:
  89.165 -            if (long_mode_do_msr_read(regs))
  89.166 -                goto done;
  89.167 -
  89.168              if ( rdmsr_hypervisor_regs(ecx, &eax, &edx) ||
  89.169                   rdmsr_safe(ecx, eax, edx) == 0 )
  89.170              {
  89.171 @@ -2061,15 +1960,6 @@ static inline void svm_do_msr_access(
  89.172              hvm_set_guest_time(v, msr_content);
  89.173              pt_reset(v);
  89.174              break;
  89.175 -        case MSR_IA32_SYSENTER_CS:
  89.176 -            vmcb->sysenter_cs = msr_content;
  89.177 -            break;
  89.178 -        case MSR_IA32_SYSENTER_ESP: 
  89.179 -            vmcb->sysenter_esp = msr_content;
  89.180 -            break;
  89.181 -        case MSR_IA32_SYSENTER_EIP:     
  89.182 -            vmcb->sysenter_eip = msr_content;
  89.183 -            break;
  89.184          case MSR_IA32_APICBASE:
  89.185              vlapic_msr_set(vcpu_vlapic(v), msr_content);
  89.186              break;
  89.187 @@ -2276,7 +2166,7 @@ asmlinkage void svm_vmexit_handler(struc
  89.188      unsigned long eip;
  89.189      struct vcpu *v = current;
  89.190      struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
  89.191 -    int inst_len;
  89.192 +    int inst_len, rc;
  89.193  
  89.194      exit_reason = vmcb->exitcode;
  89.195      save_svm_cpu_user_regs(v, regs);
  89.196 @@ -2385,8 +2275,13 @@ asmlinkage void svm_vmexit_handler(struc
  89.197          inst_len = __get_instruction_length(v, INSTR_VMCALL, NULL);
  89.198          ASSERT(inst_len > 0);
  89.199          HVMTRACE_1D(VMMCALL, v, regs->eax);
  89.200 -        __update_guest_eip(vmcb, inst_len);
  89.201 -        hvm_do_hypercall(regs);
  89.202 +        rc = hvm_do_hypercall(regs);
  89.203 +        if ( rc != HVM_HCALL_preempted )
  89.204 +        {
  89.205 +            __update_guest_eip(vmcb, inst_len);
  89.206 +            if ( rc == HVM_HCALL_invalidate )
  89.207 +                send_invalidate_req();
  89.208 +        }
  89.209          break;
  89.210  
  89.211      case VMEXIT_CR0_READ:
    90.1 --- a/xen/arch/x86/hvm/svm/vmcb.c	Fri Apr 06 10:06:30 2007 -0600
    90.2 +++ b/xen/arch/x86/hvm/svm/vmcb.c	Fri Apr 06 10:08:30 2007 -0600
    90.3 @@ -141,6 +141,14 @@ static int construct_vmcb(struct vcpu *v
    90.4  
    90.5      disable_intercept_for_msr((char *)arch_svm->msrpm, MSR_FS_BASE);
    90.6      disable_intercept_for_msr((char *)arch_svm->msrpm, MSR_GS_BASE);
    90.7 +    disable_intercept_for_msr((char *)arch_svm->msrpm, MSR_SHADOW_GS_BASE);
    90.8 +    disable_intercept_for_msr((char *)arch_svm->msrpm, MSR_CSTAR);
    90.9 +    disable_intercept_for_msr((char *)arch_svm->msrpm, MSR_LSTAR);
   90.10 +    disable_intercept_for_msr((char *)arch_svm->msrpm, MSR_STAR);
   90.11 +    disable_intercept_for_msr((char *)arch_svm->msrpm, MSR_SYSCALL_MASK);
   90.12 +    disable_intercept_for_msr((char *)arch_svm->msrpm, MSR_IA32_SYSENTER_CS);
   90.13 +    disable_intercept_for_msr((char *)arch_svm->msrpm, MSR_IA32_SYSENTER_ESP);
   90.14 +    disable_intercept_for_msr((char *)arch_svm->msrpm, MSR_IA32_SYSENTER_EIP);
   90.15  
   90.16      vmcb->msrpm_base_pa = (u64)virt_to_maddr(arch_svm->msrpm);
   90.17      vmcb->iopm_base_pa  = (u64)virt_to_maddr(hvm_io_bitmap);
    91.1 --- a/xen/arch/x86/hvm/vmx/vmx.c	Fri Apr 06 10:06:30 2007 -0600
    91.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c	Fri Apr 06 10:08:30 2007 -0600
    91.3 @@ -957,6 +957,13 @@ static int vmx_pae_enabled(struct vcpu *
    91.4      return (vmx_paging_enabled(v) && (cr4 & X86_CR4_PAE));
    91.5  }
    91.6  
    91.7 +static int vmx_interrupts_enabled(struct vcpu *v) 
    91.8 +{
    91.9 +    unsigned long eflags = __vmread(GUEST_RFLAGS); 
   91.10 +    return !irq_masked(eflags); 
   91.11 +}
   91.12 +
   91.13 +
   91.14  static void vmx_update_host_cr3(struct vcpu *v)
   91.15  {
   91.16      ASSERT( (v == current) || !vcpu_runnable(v) );
   91.17 @@ -1030,6 +1037,7 @@ static struct hvm_function_table vmx_fun
   91.18      .paging_enabled       = vmx_paging_enabled,
   91.19      .long_mode_enabled    = vmx_long_mode_enabled,
   91.20      .pae_enabled          = vmx_pae_enabled,
   91.21 +    .interrupts_enabled   = vmx_interrupts_enabled,
   91.22      .guest_x86_mode       = vmx_guest_x86_mode,
   91.23      .get_guest_ctrl_reg   = vmx_get_ctrl_reg,
   91.24      .get_segment_base     = vmx_get_segment_base,
   91.25 @@ -2618,10 +2626,16 @@ asmlinkage void vmx_vmexit_handler(struc
   91.26      }
   91.27      case EXIT_REASON_VMCALL:
   91.28      {
   91.29 +        int rc;
   91.30          HVMTRACE_1D(VMMCALL, v, regs->eax);
   91.31          inst_len = __get_instruction_length(); /* Safe: VMCALL */
   91.32 -        __update_guest_eip(inst_len);
   91.33 -        hvm_do_hypercall(regs);
   91.34 +        rc = hvm_do_hypercall(regs);
   91.35 +        if ( rc != HVM_HCALL_preempted )
   91.36 +        {
   91.37 +            __update_guest_eip(inst_len);
   91.38 +            if ( rc == HVM_HCALL_invalidate )
   91.39 +                send_invalidate_req();
   91.40 +        }
   91.41          break;
   91.42      }
   91.43      case EXIT_REASON_CR_ACCESS:
    92.1 --- a/xen/common/domain.c	Fri Apr 06 10:06:30 2007 -0600
    92.2 +++ b/xen/common/domain.c	Fri Apr 06 10:08:30 2007 -0600
    92.3 @@ -307,7 +307,7 @@ void domain_kill(struct domain *d)
    92.4      domain_pause(d);
    92.5  
    92.6      /* Already dying? Then bail. */
    92.7 -    if ( xchg(&d->is_dying, 1) )
    92.8 +    if ( test_and_set_bool(d->is_dying) )
    92.9      {
   92.10          domain_unpause(d);
   92.11          return;
   92.12 @@ -453,7 +453,7 @@ void domain_pause_for_debugger(void)
   92.13      struct vcpu *v;
   92.14  
   92.15      atomic_inc(&d->pause_count);
   92.16 -    if ( xchg(&d->is_paused_by_controller, 1) )
   92.17 +    if ( test_and_set_bool(d->is_paused_by_controller) )
   92.18          domain_unpause(d); /* race-free atomic_dec(&d->pause_count) */
   92.19  
   92.20      for_each_vcpu ( d, v )
   92.21 @@ -553,13 +553,13 @@ void domain_unpause(struct domain *d)
   92.22  void domain_pause_by_systemcontroller(struct domain *d)
   92.23  {
   92.24      domain_pause(d);
   92.25 -    if ( xchg(&d->is_paused_by_controller, 1) )
   92.26 +    if ( test_and_set_bool(d->is_paused_by_controller) )
   92.27          domain_unpause(d);
   92.28  }
   92.29  
   92.30  void domain_unpause_by_systemcontroller(struct domain *d)
   92.31  {
   92.32 -    if ( xchg(&d->is_paused_by_controller, 0) )
   92.33 +    if ( test_and_clear_bool(d->is_paused_by_controller) )
   92.34          domain_unpause(d);
   92.35  }
   92.36  
    93.1 --- a/xen/common/memory.c	Fri Apr 06 10:06:30 2007 -0600
    93.2 +++ b/xen/common/memory.c	Fri Apr 06 10:08:30 2007 -0600
    93.3 @@ -173,17 +173,6 @@ int guest_remove_page(struct domain *d, 
    93.4      if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
    93.5          put_page(page);
    93.6  
    93.7 -    if ( unlikely((page->count_info & PGC_count_mask) != 1) )
    93.8 -    {
    93.9 -        shadow_drop_references(d, page);
   93.10 -        /* We'll make this a guest-visible error in future, so take heed! */
   93.11 -        if ( (page->count_info & PGC_count_mask) != 1 )
   93.12 -            gdprintk(XENLOG_INFO, "Dom%d freeing in-use page %lx "
   93.13 -                     "(pseudophys %lx): count=%lx type=%lx\n",
   93.14 -                     d->domain_id, mfn, get_gpfn_from_mfn(mfn),
   93.15 -                     (unsigned long)page->count_info, page->u.inuse.type_info);
   93.16 -    }
   93.17 -
   93.18      guest_physmap_remove_page(d, gmfn, mfn);
   93.19  
   93.20      put_page(page);
    94.1 --- a/xen/common/schedule.c	Fri Apr 06 10:06:30 2007 -0600
    94.2 +++ b/xen/common/schedule.c	Fri Apr 06 10:08:30 2007 -0600
    94.3 @@ -461,7 +461,11 @@ ret_t do_sched_op(int cmd, XEN_GUEST_HAN
    94.4          if ( d == NULL )
    94.5              break;
    94.6  
    94.7 +        /* domain_pause() prevens any further execution in guest context. */
    94.8 +        domain_pause(d);
    94.9          domain_shutdown(d, (u8)sched_remote_shutdown.reason);
   94.10 +        domain_unpause(d);
   94.11 +
   94.12          rcu_unlock_domain(d);
   94.13          ret = 0;
   94.14  
    95.1 --- a/xen/drivers/char/ns16550.c	Fri Apr 06 10:06:30 2007 -0600
    95.2 +++ b/xen/drivers/char/ns16550.c	Fri Apr 06 10:08:30 2007 -0600
    95.3 @@ -239,7 +239,7 @@ static void ns16550_init_postirq(struct 
    95.4          uart->irqaction.name    = "ns16550";
    95.5          uart->irqaction.dev_id  = port;
    95.6          if ( (rc = setup_irq(uart->irq, &uart->irqaction)) != 0 )
    95.7 -            printk("ERROR: Failed to allocate na16550 IRQ %d\n", uart->irq);
    95.8 +            printk("ERROR: Failed to allocate ns16550 IRQ %d\n", uart->irq);
    95.9  
   95.10          /* Master interrupt enable; also keep DTR/RTS asserted. */
   95.11          ns_write_reg(uart, MCR, MCR_OUT2 | MCR_DTR | MCR_RTS);
    96.1 --- a/xen/include/asm-ia64/xentypes.h	Fri Apr 06 10:06:30 2007 -0600
    96.2 +++ b/xen/include/asm-ia64/xentypes.h	Fri Apr 06 10:08:30 2007 -0600
    96.3 @@ -5,6 +5,11 @@
    96.4  typedef unsigned long ssize_t;
    96.5  typedef unsigned long size_t;
    96.6  typedef long long loff_t;
    96.7 +
    96.8 +typedef char bool_t;
    96.9 +#define test_and_set_bool(b)   xchg(&(b), 1)
   96.10 +#define test_and_clear_bool(b) xchg(&(b), 0)
   96.11 +
   96.12  #endif /* !__ASSEMBLY__ */
   96.13  
   96.14  #endif /* _ASM_IA64_XENTYPES_H */
    97.1 --- a/xen/include/asm-powerpc/types.h	Fri Apr 06 10:06:30 2007 -0600
    97.2 +++ b/xen/include/asm-powerpc/types.h	Fri Apr 06 10:08:30 2007 -0600
    97.3 @@ -70,5 +70,9 @@ typedef u64 dma64_addr_t;
    97.4  
    97.5  typedef unsigned short xmem_bufctl_t;
    97.6  
    97.7 +typedef int bool_t;
    97.8 +#define test_and_set_bool(b)   xchg(&(b), 1)
    97.9 +#define test_and_clear_bool(b) xchg(&(b), 0)
   97.10 +
   97.11  #endif  /* __ASSEMBLY__ */
   97.12  #endif
    98.1 --- a/xen/include/asm-x86/event.h	Fri Apr 06 10:06:30 2007 -0600
    98.2 +++ b/xen/include/asm-x86/event.h	Fri Apr 06 10:08:30 2007 -0600
    98.3 @@ -35,12 +35,13 @@ static inline void vcpu_mark_events_pend
    98.4          vcpu_kick(v);
    98.5  }
    98.6  
    98.7 +int hvm_local_events_need_delivery(struct vcpu *v);
    98.8  static inline int local_events_need_delivery(void)
    98.9  {
   98.10      struct vcpu *v = current;
   98.11 -    return ((vcpu_info(v, evtchn_upcall_pending) &&
   98.12 -             !vcpu_info(v, evtchn_upcall_mask)) ||
   98.13 -            (is_hvm_vcpu(v) && cpu_has_pending_irq(v)));
   98.14 +    return (is_hvm_vcpu(v) ? hvm_local_events_need_delivery(v) :
   98.15 +            (vcpu_info(v, evtchn_upcall_pending) &&
   98.16 +             !vcpu_info(v, evtchn_upcall_mask)));
   98.17  }
   98.18  
   98.19  static inline int local_event_delivery_is_enabled(void)
    99.1 --- a/xen/include/asm-x86/hvm/hvm.h	Fri Apr 06 10:06:30 2007 -0600
    99.2 +++ b/xen/include/asm-x86/hvm/hvm.h	Fri Apr 06 10:08:30 2007 -0600
    99.3 @@ -93,13 +93,15 @@ struct hvm_function_table {
    99.4       * 1) determine whether paging is enabled,
    99.5       * 2) determine whether long mode is enabled,
    99.6       * 3) determine whether PAE paging is enabled,
    99.7 -     * 4) determine the mode the guest is running in,
    99.8 -     * 5) return the current guest control-register value
    99.9 -     * 6) return the current guest segment descriptor base
   99.10 +     * 4) determine whether interrupts are enabled or not,
   99.11 +     * 5) determine the mode the guest is running in,
   99.12 +     * 6) return the current guest control-register value
   99.13 +     * 7) return the current guest segment descriptor base
   99.14       */
   99.15      int (*paging_enabled)(struct vcpu *v);
   99.16      int (*long_mode_enabled)(struct vcpu *v);
   99.17      int (*pae_enabled)(struct vcpu *v);
   99.18 +    int (*interrupts_enabled)(struct vcpu *v);
   99.19      int (*guest_x86_mode)(struct vcpu *v);
   99.20      unsigned long (*get_guest_ctrl_reg)(struct vcpu *v, unsigned int num);
   99.21      unsigned long (*get_segment_base)(struct vcpu *v, enum x86_segment seg);
   99.22 @@ -190,6 +192,12 @@ hvm_pae_enabled(struct vcpu *v)
   99.23  }
   99.24  
   99.25  static inline int
   99.26 +hvm_interrupts_enabled(struct vcpu *v)
   99.27 +{
   99.28 +    return hvm_funcs.interrupts_enabled(v);
   99.29 +}
   99.30 +
   99.31 +static inline int
   99.32  hvm_guest_x86_mode(struct vcpu *v)
   99.33  {
   99.34      return hvm_funcs.guest_x86_mode(v);
   100.1 --- a/xen/include/asm-x86/hvm/io.h	Fri Apr 06 10:06:30 2007 -0600
   100.2 +++ b/xen/include/asm-x86/hvm/io.h	Fri Apr 06 10:08:30 2007 -0600
   100.3 @@ -147,9 +147,10 @@ static inline int irq_masked(unsigned lo
   100.4  extern void send_pio_req(unsigned long port, unsigned long count, int size,
   100.5                           paddr_t value, int dir, int df, int value_is_ptr);
   100.6  void send_timeoffset_req(unsigned long timeoff);
   100.7 +void send_invalidate_req(void);
   100.8  extern void handle_mmio(unsigned long gpa);
   100.9  extern void hvm_interrupt_post(struct vcpu *v, int vector, int type);
  100.10 -extern void hvm_io_assist(struct vcpu *v);
  100.11 +extern void hvm_io_assist(void);
  100.12  
  100.13  #endif /* __ASM_X86_HVM_IO_H__ */
  100.14  
   101.1 --- a/xen/include/asm-x86/hvm/support.h	Fri Apr 06 10:06:30 2007 -0600
   101.2 +++ b/xen/include/asm-x86/hvm/support.h	Fri Apr 06 10:08:30 2007 -0600
   101.3 @@ -228,7 +228,10 @@ int hvm_copy_from_guest_virt(void *buf, 
   101.4  void hvm_print_line(struct vcpu *v, const char c);
   101.5  void hlt_timer_fn(void *data);
   101.6  
   101.7 -void hvm_do_hypercall(struct cpu_user_regs *pregs);
   101.8 +#define HVM_HCALL_completed  0 /* hypercall completed - no further action */
   101.9 +#define HVM_HCALL_preempted  1 /* hypercall preempted - re-execute VMCALL */
  101.10 +#define HVM_HCALL_invalidate 2 /* invalidate ioemu-dm memory cache        */
  101.11 +int hvm_do_hypercall(struct cpu_user_regs *pregs);
  101.12  
  101.13  void hvm_hlt(unsigned long rflags);
  101.14  void hvm_triple_fault(void);
   102.1 --- a/xen/include/asm-x86/types.h	Fri Apr 06 10:06:30 2007 -0600
   102.2 +++ b/xen/include/asm-x86/types.h	Fri Apr 06 10:08:30 2007 -0600
   102.3 @@ -52,6 +52,10 @@ typedef unsigned long paddr_t;
   102.4  
   102.5  typedef unsigned long size_t;
   102.6  
   102.7 +typedef char bool_t;
   102.8 +#define test_and_set_bool(b)   xchg(&(b), 1)
   102.9 +#define test_and_clear_bool(b) xchg(&(b), 0)
  102.10 +
  102.11  #endif /* __ASSEMBLY__ */
  102.12  
  102.13  #if defined(__i386__)
   103.1 --- a/xen/include/public/acm.h	Fri Apr 06 10:06:30 2007 -0600
   103.2 +++ b/xen/include/public/acm.h	Fri Apr 06 10:08:30 2007 -0600
   103.3 @@ -124,7 +124,7 @@ struct acm_policy_version
   103.4  {
   103.5      uint32_t major;
   103.6      uint32_t minor;
   103.7 -} __attribute__((packed));
   103.8 +};
   103.9  
  103.10  
  103.11  /* each buffer consists of all policy information for
  103.12 @@ -145,12 +145,12 @@ struct acm_policy_buffer {
  103.13      uint32_t secondary_policy_code;
  103.14      uint32_t secondary_buffer_offset;
  103.15      struct acm_policy_version xml_pol_version; /* add in V3 */
  103.16 -} __attribute__((packed));
  103.17 +};
  103.18  
  103.19  
  103.20  struct acm_policy_reference_buffer {
  103.21      uint32_t len;
  103.22 -} __attribute__((packed));
  103.23 +};
  103.24  
  103.25  struct acm_chwall_policy_buffer {
  103.26      uint32_t policy_version; /* ACM_CHWALL_VERSION */
  103.27 @@ -162,7 +162,7 @@ struct acm_chwall_policy_buffer {
  103.28      uint32_t chwall_conflict_sets_offset;
  103.29      uint32_t chwall_running_types_offset;
  103.30      uint32_t chwall_conflict_aggregate_offset;
  103.31 -} __attribute__((packed));
  103.32 +};
  103.33  
  103.34  struct acm_ste_policy_buffer {
  103.35      uint32_t policy_version; /* ACM_STE_VERSION */
  103.36 @@ -170,7 +170,7 @@ struct acm_ste_policy_buffer {
  103.37      uint32_t ste_max_types;
  103.38      uint32_t ste_max_ssidrefs;
  103.39      uint32_t ste_ssid_offset;
  103.40 -} __attribute__((packed));
  103.41 +};
  103.42  
  103.43  struct acm_stats_buffer {
  103.44      uint32_t magic;
  103.45 @@ -179,7 +179,7 @@ struct acm_stats_buffer {
  103.46      uint32_t primary_stats_offset;
  103.47      uint32_t secondary_policy_code;
  103.48      uint32_t secondary_stats_offset;
  103.49 -} __attribute__((packed));
  103.50 +};
  103.51  
  103.52  struct acm_ste_stats_buffer {
  103.53      uint32_t ec_eval_count;
  103.54 @@ -188,7 +188,7 @@ struct acm_ste_stats_buffer {
  103.55      uint32_t gt_denied_count;
  103.56      uint32_t ec_cachehit_count;
  103.57      uint32_t gt_cachehit_count;
  103.58 -} __attribute__((packed));
  103.59 +};
  103.60  
  103.61  struct acm_ssid_buffer {
  103.62      uint32_t len;
  103.63 @@ -200,7 +200,7 @@ struct acm_ssid_buffer {
  103.64      uint32_t secondary_policy_code;
  103.65      uint32_t secondary_max_types;
  103.66      uint32_t secondary_types_offset;
  103.67 -} __attribute__((packed));
  103.68 +};
  103.69  
  103.70  #endif
  103.71  
   104.1 --- a/xen/include/public/foreign/Makefile	Fri Apr 06 10:06:30 2007 -0600
   104.2 +++ b/xen/include/public/foreign/Makefile	Fri Apr 06 10:08:30 2007 -0600
   104.3 @@ -13,7 +13,7 @@ clean:
   104.4  	rm -f checker checker.c $(XEN_TARGET_ARCH).size
   104.5  	rm -f *.pyc *.o *~
   104.6  
   104.7 -ifeq ($(CROSS_COMPILE),)
   104.8 +ifeq ($(CROSS_COMPILE)$(XEN_TARGET_ARCH),$(XEN_COMPILE_ARCH))
   104.9  check-headers: checker
  104.10  	./checker > $(XEN_TARGET_ARCH).size
  104.11  	diff -u reference.size $(XEN_TARGET_ARCH).size
   105.1 --- a/xen/include/public/hvm/hvm_op.h	Fri Apr 06 10:06:30 2007 -0600
   105.2 +++ b/xen/include/public/hvm/hvm_op.h	Fri Apr 06 10:08:30 2007 -0600
   105.3 @@ -70,12 +70,4 @@ struct xen_hvm_set_pci_link_route {
   105.4  typedef struct xen_hvm_set_pci_link_route xen_hvm_set_pci_link_route_t;
   105.5  DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_pci_link_route_t);
   105.6  
   105.7 -/* Drain all outstanding qemu-dm IO responses from a domain's ioreq ring. */
   105.8 -#define HVMOP_drain_io            5
   105.9 -struct xen_hvm_drain_io {
  105.10 -    domid_t  domid;
  105.11 -};
  105.12 -typedef struct xen_hvm_drain_io xen_hvm_drain_io_t;
  105.13 -DEFINE_XEN_GUEST_HANDLE(xen_hvm_drain_io_t);
  105.14 -
  105.15  #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
   106.1 --- a/xen/include/public/hvm/ioreq.h	Fri Apr 06 10:06:30 2007 -0600
   106.2 +++ b/xen/include/public/hvm/ioreq.h	Fri Apr 06 10:08:30 2007 -0600
   106.3 @@ -40,6 +40,7 @@
   106.4  #define IOREQ_TYPE_XCHG         5
   106.5  #define IOREQ_TYPE_ADD          6
   106.6  #define IOREQ_TYPE_TIMEOFFSET   7
   106.7 +#define IOREQ_TYPE_INVALIDATE   8 /* mapcache */
   106.8  
   106.9  /*
  106.10   * VMExit dispatcher should cooperate with instruction decoder to
   107.1 --- a/xen/include/xen/types.h	Fri Apr 06 10:06:30 2007 -0600
   107.2 +++ b/xen/include/xen/types.h	Fri Apr 06 10:08:30 2007 -0600
   107.3 @@ -20,8 +20,6 @@
   107.4  #define LONG_MIN        (-LONG_MAX - 1)
   107.5  #define ULONG_MAX       (~0UL)
   107.6  
   107.7 -typedef char bool_t;
   107.8 -
   107.9  /* bsd */
  107.10  typedef unsigned char           u_char;
  107.11  typedef unsigned short          u_short;