mirror of
https://github.com/xen-project/xen.git
synced 2026-10-30 03:00:05 +01:00
Merge with xen-unstable-ia64.hg
This commit is contained in:
commit
5aa99be215
67 files changed
+1177
-855
No files matched your search
+56
-52
@@ -9,7 +9,6 @@
|
||||
\latexhtml{\newcommand{\path}[1]{{\small {\tt #1}}}}{\newcommand{\path}[1]{{\tt #1}}}
|
||||
|
||||
|
||||
|
||||
\begin{document}
|
||||
|
||||
% TITLE PAGE
|
||||
@@ -21,24 +20,24 @@
|
||||
\vfill
|
||||
\vfill
|
||||
\begin{tabular}{l}
|
||||
{\Huge \bf Users' manual} \\[4mm]
|
||||
{\huge Xen v2.0 for x86} \\[80mm]
|
||||
{\Huge \bf Users' Manual} \\[4mm]
|
||||
{\huge Xen v3.0} \\[80mm]
|
||||
|
||||
{\Large Xen is Copyright (c) 2002-2004, The Xen Team} \\[3mm]
|
||||
{\Large Xen is Copyright (c) 2002-2005, The Xen Team} \\[3mm]
|
||||
{\Large University of Cambridge, UK} \\[20mm]
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
{\bf
|
||||
DISCLAIMER: This documentation is currently under active development
|
||||
and as such there may be mistakes and omissions --- watch out for
|
||||
these and please report any you find to the developer's mailing list.
|
||||
Contributions of material, suggestions and corrections are welcome.
|
||||
}
|
||||
{\bf DISCLAIMER: This documentation is currently under active
|
||||
development and as such there may be mistakes and omissions ---
|
||||
watch out for these and please report any you find to the
|
||||
developers' mailing list. Contributions of material, suggestions
|
||||
and corrections are welcome.}
|
||||
|
||||
\vfill
|
||||
\cleardoublepage
|
||||
|
||||
|
||||
% TABLE OF CONTENTS
|
||||
\pagestyle{plain}
|
||||
\pagenumbering{roman}
|
||||
@@ -46,6 +45,7 @@ Contributions of material, suggestions and corrections are welcome.
|
||||
\tableofcontents }
|
||||
\cleardoublepage
|
||||
|
||||
|
||||
% PREPARE FOR MAIN TEXT
|
||||
\pagenumbering{arabic}
|
||||
\raggedbottom
|
||||
@@ -68,7 +68,7 @@ Contributions of material, suggestions and corrections are welcome.
|
||||
%% Chapter Installation moved to installation.tex
|
||||
\include{src/user/installation}
|
||||
|
||||
%% Chapter Starting Additional Domains moved to start_addl_dom.tex
|
||||
%% Chapter Starting Additional Domains moved to start_addl_dom.tex
|
||||
\include{src/user/start_addl_dom}
|
||||
|
||||
%% Chapter Domain Management Tools moved to domain_mgmt.tex
|
||||
@@ -87,6 +87,9 @@ Contributions of material, suggestions and corrections are welcome.
|
||||
%% Chapter Domain Configuration moved to domain_configuration.tex
|
||||
\include{src/user/domain_configuration}
|
||||
|
||||
%% Chapter Securing Xen
|
||||
\include{src/user/securing_xen}
|
||||
|
||||
%% Chapter Build, Boot and Debug Options moved to build.tex
|
||||
\include{src/user/build}
|
||||
|
||||
@@ -99,25 +102,25 @@ that bug reports, suggestions and contributions related to the
|
||||
software (or the documentation) should be sent to the Xen developers'
|
||||
mailing list (address below).
|
||||
|
||||
|
||||
\section{Other Documentation}
|
||||
|
||||
For developers interested in porting operating systems to Xen, the
|
||||
{\em Xen Interface Manual} is distributed in the \path{docs/}
|
||||
directory of the Xen source distribution.
|
||||
\emph{Xen Interface Manual} is distributed in the \path{docs/}
|
||||
directory of the Xen source distribution.
|
||||
|
||||
%Various HOWTOs are available in \path{docs/HOWTOS} but this content is
|
||||
%being integrated into this manual.
|
||||
% Various HOWTOs are available in \path{docs/HOWTOS} but this content
|
||||
% is being integrated into this manual.
|
||||
|
||||
|
||||
\section{Online References}
|
||||
|
||||
The official Xen web site is found at:
|
||||
\begin{quote}
|
||||
{\tt http://www.cl.cam.ac.uk/netos/xen/}
|
||||
\begin{quote} {\tt http://www.cl.cam.ac.uk/netos/xen/}
|
||||
\end{quote}
|
||||
|
||||
This contains links to the latest versions of all on-line
|
||||
documentation (including the lateset version of the FAQ).
|
||||
This contains links to the latest versions of all online
|
||||
documentation, including the latest version of the FAQ.
|
||||
|
||||
|
||||
\section{Mailing Lists}
|
||||
@@ -126,17 +129,17 @@ There are currently four official Xen mailing lists:
|
||||
|
||||
\begin{description}
|
||||
\item[xen-devel@lists.xensource.com] Used for development
|
||||
discussions and bug reports. Subscribe at: \\
|
||||
{\small {\tt http://lists.xensource.com/xen-devel}}
|
||||
discussions and bug reports. Subscribe at: \\
|
||||
{\small {\tt http://lists.xensource.com/xen-devel}}
|
||||
\item[xen-users@lists.xensource.com] Used for installation and usage
|
||||
discussions and requests for help. Subscribe at: \\
|
||||
{\small {\tt http://lists.xensource.com/xen-users}}
|
||||
discussions and requests for help. Subscribe at: \\
|
||||
{\small {\tt http://lists.xensource.com/xen-users}}
|
||||
\item[xen-announce@lists.xensource.com] Used for announcements only.
|
||||
Subscribe at: \\
|
||||
{\small {\tt http://lists.xensource.com/xen-announce}}
|
||||
\item[xen-changelog@lists.xensource.com] Changelog feed
|
||||
from the unstable and 2.0 trees - developer oriented. Subscribe at: \\
|
||||
{\small {\tt http://lists.xensource.com/xen-changelog}}
|
||||
Subscribe at: \\
|
||||
{\small {\tt http://lists.xensource.com/xen-announce}}
|
||||
\item[xen-changelog@lists.xensource.com] Changelog feed
|
||||
from the unstable and 2.0 trees - developer oriented. Subscribe at: \\
|
||||
{\small {\tt http://lists.xensource.com/xen-changelog}}
|
||||
\end{description}
|
||||
|
||||
|
||||
@@ -149,11 +152,11 @@ from the unstable and 2.0 trees - developer oriented. Subscribe at: \\
|
||||
%% Chapter Installing Xen on Red Hat moved to redhat.tex
|
||||
\include{src/user/redhat}
|
||||
|
||||
|
||||
%% Chapter Glossary of Terms moved to glossary.tex
|
||||
\include{src/user/glossary}
|
||||
|
||||
|
||||
|
||||
\end{document}
|
||||
|
||||
|
||||
@@ -181,36 +184,35 @@ from the unstable and 2.0 trees - developer oriented. Subscribe at: \\
|
||||
%% # import xenctl.utils
|
||||
%% # help(xenctl.utils)
|
||||
|
||||
%% You can use these modules to write your own custom scripts or you can
|
||||
%% customise the scripts supplied in the Xen distribution.
|
||||
%% You can use these modules to write your own custom scripts or you
|
||||
%% can customise the scripts supplied in the Xen distribution.
|
||||
|
||||
|
||||
|
||||
% Explain about AGP GART
|
||||
|
||||
|
||||
%% If you're not intending to configure the new domain with an IP address
|
||||
%% on your LAN, then you'll probably want to use NAT. The
|
||||
%% 'xen_nat_enable' installs a few useful iptables rules into domain0 to
|
||||
%% enable NAT. [NB: We plan to support RSIP in future]
|
||||
|
||||
%% If you're not intending to configure the new domain with an IP
|
||||
%% address on your LAN, then you'll probably want to use NAT. The
|
||||
%% 'xen_nat_enable' installs a few useful iptables rules into domain0
|
||||
%% to enable NAT. [NB: We plan to support RSIP in future]
|
||||
|
||||
|
||||
|
||||
%% Installing the file systems from the CD
|
||||
%% =======================================
|
||||
|
||||
%% If you haven't got an existing Linux installation onto which you can
|
||||
%% just drop down the Xen and Xenlinux images, then the file systems on
|
||||
%% the CD provide a quick way of doing an install. However, you would be
|
||||
%% better off in the long run doing a proper install of your preferred
|
||||
%% distro and installing Xen onto that, rather than just doing the hack
|
||||
%% described below:
|
||||
%% If you haven't got an existing Linux installation onto which you
|
||||
%% can just drop down the Xen and Xenlinux images, then the file
|
||||
%% systems on the CD provide a quick way of doing an install. However,
|
||||
%% you would be better off in the long run doing a proper install of
|
||||
%% your preferred distro and installing Xen onto that, rather than
|
||||
%% just doing the hack described below:
|
||||
|
||||
%% Choose one or two partitions, depending on whether you want a separate
|
||||
%% /usr or not. Make file systems on it/them e.g.:
|
||||
%% mkfs -t ext3 /dev/hda3
|
||||
%% [or mkfs -t ext2 /dev/hda3 && tune2fs -j /dev/hda3 if using an old
|
||||
%% Choose one or two partitions, depending on whether you want a
|
||||
%% separate /usr or not. Make file systems on it/them e.g.:
|
||||
%% mkfs -t ext3 /dev/hda3
|
||||
%% [or mkfs -t ext2 /dev/hda3 && tune2fs -j /dev/hda3 if using an old
|
||||
%% version of mkfs]
|
||||
|
||||
%% Next, mount the file system(s) e.g.:
|
||||
@@ -224,12 +226,14 @@ from the unstable and 2.0 trees - developer oriented. Subscribe at: \\
|
||||
%% configuration. Changing the password file (etc/shadow) is probably a
|
||||
%% good idea too.
|
||||
|
||||
%% To install the usr file system, copy the file system from CD on /usr,
|
||||
%% though leaving out the "XenDemoCD" and "boot" directories:
|
||||
%% cd /usr && cp -a X11R6 etc java libexec root src bin dict kerberos local sbin tmp doc include lib man share /mnt/usr
|
||||
%% To install the usr file system, copy the file system from CD on
|
||||
%% /usr, though leaving out the "XenDemoCD" and "boot" directories:
|
||||
%% cd /usr && cp -a X11R6 etc java libexec root src bin dict kerberos
|
||||
%% local sbin tmp doc include lib man share /mnt/usr
|
||||
|
||||
%% If you intend to boot off these file systems (i.e. use them for
|
||||
%% domain 0), then you probably want to copy the /usr/boot directory on
|
||||
%% the cd over the top of the current symlink to /boot on your root
|
||||
%% filesystem (after deleting the current symlink) i.e.:
|
||||
%% domain 0), then you probably want to copy the /usr/boot
|
||||
%% directory on the cd over the top of the current symlink to /boot
|
||||
%% on your root filesystem (after deleting the current symlink)
|
||||
%% i.e.:
|
||||
%% cd /mnt/root ; rm boot ; cp -a /usr/boot .
|
||||
@@ -17,7 +17,7 @@ want to run more than one virtual machine; items marked `$*$' are only
|
||||
required if you wish to build from source.
|
||||
\begin{itemize}
|
||||
\item A working Linux distribution using the GRUB bootloader and
|
||||
running on a P6-class (or newer) CPU.
|
||||
running on a P6-class or newer CPU\@.
|
||||
\item [$\dag$] The \path{iproute2} package.
|
||||
\item [$\dag$] The Linux bridge-utils\footnote{Available from {\tt
|
||||
http://bridge.sourceforge.net}} (e.g., \path{/sbin/brctl})
|
||||
@@ -30,29 +30,29 @@ required if you wish to build from source.
|
||||
alternatively it can be installed by running `{\sl make
|
||||
install-twisted}' in the root of the Xen source tree.
|
||||
\item [$*$] Build tools (gcc v3.2.x or v3.3.x, binutils, GNU make).
|
||||
\item [$*$] Development installation of libcurl (e.g., libcurl-devel)
|
||||
\item [$*$] Development installation of zlib (e.g., zlib-dev).
|
||||
\item [$*$] Development installation of Python v2.2 or later (e.g.,
|
||||
\item [$*$] Development installation of libcurl (e.g.,\ libcurl-devel).
|
||||
\item [$*$] Development installation of zlib (e.g.,\ zlib-dev).
|
||||
\item [$*$] Development installation of Python v2.2 or later (e.g.,\
|
||||
python-dev).
|
||||
\item [$*$] \LaTeX\ and transfig are required to build the
|
||||
documentation.
|
||||
\end{itemize}
|
||||
|
||||
Once you have satisfied the relevant prerequisites, you can now
|
||||
install either a binary or source distribution of Xen.
|
||||
Once you have satisfied these prerequisites, you can now install
|
||||
either a binary or source distribution of Xen.
|
||||
|
||||
|
||||
\section{Installing from Binary Tarball}
|
||||
|
||||
Pre-built tarballs are available for download from the Xen download
|
||||
page
|
||||
\begin{quote} {\tt http://xen.sf.net}
|
||||
page:
|
||||
\begin{quote} {\tt http://www.xensource.com/downloads/}
|
||||
\end{quote}
|
||||
|
||||
Once you've downloaded the tarball, simply unpack and install:
|
||||
\begin{verbatim}
|
||||
# tar zxvf xen-2.0-install.tgz
|
||||
# cd xen-2.0-install
|
||||
# tar zxvf xen-3.0-install.tgz
|
||||
# cd xen-3.0-install
|
||||
# sh ./install.sh
|
||||
\end{verbatim}
|
||||
|
||||
@@ -62,48 +62,29 @@ as described in Section~\ref{s:configure}.
|
||||
|
||||
\section{Installing from Source}
|
||||
|
||||
This section describes how to obtain, build, and install Xen from
|
||||
This section describes how to obtain, build and install Xen from
|
||||
source.
|
||||
|
||||
\subsection{Obtaining the Source}
|
||||
|
||||
The Xen source tree is available as either a compressed source tar
|
||||
ball or as a clone of our master BitKeeper repository.
|
||||
The Xen source tree is available as either a compressed source tarball
|
||||
or as a clone of our master Mercurial repository.
|
||||
|
||||
\begin{description}
|
||||
\item[Obtaining the Source Tarball]\mbox{} \\
|
||||
Stable versions (and daily snapshots) of the Xen source tree are
|
||||
available as compressed tarballs from the Xen download page
|
||||
\begin{quote} {\tt http://xen.sf.net}
|
||||
Stable versions and daily snapshots of the Xen source tree are
|
||||
available from the Xen download page:
|
||||
\begin{quote} {\tt \tt http://www.xensource.com/downloads/}
|
||||
\end{quote}
|
||||
\item[Obtaining the source via Mercurial]\mbox{} \\
|
||||
The source tree may also be obtained via the public Mercurial
|
||||
repository hosted at:
|
||||
\begin{quote}{\tt http://xenbits.xensource.com}.
|
||||
\end{quote} See the instructions and the Getting Started Guide
|
||||
referenced at:
|
||||
\begin{quote}
|
||||
{\tt http://www.xensource.com/downloads/}.
|
||||
\end{quote}
|
||||
|
||||
\item[Using BitKeeper]\mbox{} \\
|
||||
If you wish to install Xen from a clone of our latest BitKeeper
|
||||
repository then you will need to install the BitKeeper tools.
|
||||
Download instructions for BitKeeper can be obtained by filling out
|
||||
the form at:
|
||||
\begin{quote} {\tt http://www.bitmover.com/cgi-bin/download.cgi}
|
||||
\end{quote}
|
||||
The public master BK repository for the 2.0 release lives at:
|
||||
\begin{quote} {\tt bk://xen.bkbits.net/xen-2.0.bk}
|
||||
\end{quote}
|
||||
You can use BitKeeper to download it and keep it updated with the
|
||||
latest features and fixes.
|
||||
|
||||
Change to the directory in which you want to put the source code, then
|
||||
run:
|
||||
\begin{verbatim}
|
||||
# bk clone bk://xen.bkbits.net/xen-2.0.bk
|
||||
\end{verbatim}
|
||||
|
||||
Under your current directory, a new directory named \path{xen-2.0.bk}
|
||||
has been created, which contains all the source code for Xen, the OS
|
||||
ports, and the control tools. You can update your repository with the
|
||||
latest changes at any time by running:
|
||||
\begin{verbatim}
|
||||
# cd xen-2.0.bk # to change into the local repository
|
||||
# bk pull # to update the repository
|
||||
\end{verbatim}
|
||||
\end{description}
|
||||
|
||||
% \section{The distribution}
|
||||
@@ -124,7 +105,7 @@ latest changes at any time by running:
|
||||
|
||||
\subsection{Building from Source}
|
||||
|
||||
The top-level Xen Makefile includes a target `world' that will do the
|
||||
The top-level Xen Makefile includes a target ``world'' that will do the
|
||||
following:
|
||||
|
||||
\begin{itemize}
|
||||
@@ -132,17 +113,17 @@ following:
|
||||
\item Build the control tools, including \xend.
|
||||
\item Download (if necessary) and unpack the Linux 2.6 source code,
|
||||
and patch it for use with Xen.
|
||||
\item Build a Linux kernel to use in domain 0 and a smaller
|
||||
\item Build a Linux kernel to use in domain~0 and a smaller
|
||||
unprivileged kernel, which can optionally be used for unprivileged
|
||||
virtual machines.
|
||||
\end{itemize}
|
||||
|
||||
After the build has completed you should have a top-level directory
|
||||
called \path{dist/} in which all resulting targets will be placed; of
|
||||
particular interest are the two kernels XenLinux kernel images, one
|
||||
with a `-xen0' extension which contains hardware device drivers and
|
||||
drivers for Xen's virtual devices, and one with a `-xenU' extension
|
||||
that just contains the virtual ones. These are found in
|
||||
called \path{dist/} in which all resulting targets will be placed. Of
|
||||
particular interest are the two XenLinux kernel images, one with a
|
||||
``-xen0'' extension which contains hardware device drivers and drivers
|
||||
for Xen's virtual devices, and one with a ``-xenU'' extension that
|
||||
just contains the virtual ones. These are found in
|
||||
\path{dist/install/boot/} along with the image for Xen itself and the
|
||||
configuration files used during the build.
|
||||
|
||||
@@ -150,17 +131,15 @@ The NetBSD port can be built using:
|
||||
\begin{quote}
|
||||
\begin{verbatim}
|
||||
# make netbsd20
|
||||
\end{verbatim}
|
||||
\end{quote}
|
||||
\end{verbatim}\end{quote}
|
||||
NetBSD port is built using a snapshot of the netbsd-2-0 cvs branch.
|
||||
The snapshot is downloaded as part of the build process, if it is not
|
||||
The snapshot is downloaded as part of the build process if it is not
|
||||
yet present in the \path{NETBSD\_SRC\_PATH} search path. The build
|
||||
process also downloads a toolchain which includes all the tools
|
||||
process also downloads a toolchain which includes all of the tools
|
||||
necessary to build the NetBSD kernel under Linux.
|
||||
|
||||
To customize further the set of kernels built you need to edit the
|
||||
top-level Makefile. Look for the line:
|
||||
|
||||
To customize the set of kernels built you need to edit the top-level
|
||||
Makefile. Look for the line:
|
||||
\begin{quote}
|
||||
\begin{verbatim}
|
||||
KERNELS ?= mk.linux-2.6-xen0 mk.linux-2.6-xenU
|
||||
@@ -189,7 +168,6 @@ kernel containing only virtual device drivers.
|
||||
%% After untaring the pristine kernel tree, the makefile uses the {\tt
|
||||
%% mkbuildtree} script to add the Xen patches to the kernel.
|
||||
|
||||
|
||||
%% \framebox{\parbox{5in}{
|
||||
%% {\bf Distro specific:} \\
|
||||
%% {\it Gentoo} --- if not using udev (most installations,
|
||||
@@ -201,7 +179,7 @@ kernel containing only virtual device drivers.
|
||||
% If you have an SMP machine you may wish to give the {\tt '-j4'}
|
||||
% argument to make to get a parallel build.
|
||||
|
||||
If you wish to build a customized XenLinux kernel (e.g. to support
|
||||
If you wish to build a customized XenLinux kernel (e.g.\ to support
|
||||
additional devices or enable distribution-required features), you can
|
||||
use the standard Linux configuration mechanisms, specifying that the
|
||||
architecture being built for is \path{xen}, e.g:
|
||||
@@ -215,21 +193,21 @@ architecture being built for is \path{xen}, e.g:
|
||||
\end{quote}
|
||||
|
||||
You can also copy an existing Linux configuration (\path{.config})
|
||||
into \path{linux-2.6.11-xen0} and execute:
|
||||
into e.g.\ \path{linux-2.6.11-xen0} and execute:
|
||||
\begin{quote}
|
||||
\begin{verbatim}
|
||||
# make ARCH=xen oldconfig
|
||||
\end{verbatim}
|
||||
\end{quote}
|
||||
|
||||
You may be prompted with some Xen-specific options; we advise
|
||||
You may be prompted with some Xen-specific options. We advise
|
||||
accepting the defaults for these options.
|
||||
|
||||
Note that the only difference between the two types of Linux kernel
|
||||
that are built is the configuration file used for each. The `U'
|
||||
Note that the only difference between the two types of Linux kernels
|
||||
that are built is the configuration file used for each. The ``U''
|
||||
suffixed (unprivileged) versions don't contain any of the physical
|
||||
hardware device drivers, leading to a 30\% reduction in size; hence
|
||||
you may prefer these for your non-privileged domains. The `0'
|
||||
you may prefer these for your non-privileged domains. The ``0''
|
||||
suffixed privileged versions can be used to boot the system, as well
|
||||
as in driver domains and unprivileged domains.
|
||||
|
||||
@@ -259,10 +237,10 @@ destinations.
|
||||
|
||||
The \path{dist/install/boot} directory will also contain the config
|
||||
files used for building the XenLinux kernels, and also versions of Xen
|
||||
and XenLinux kernels that contain debug symbols (\path{xen-syms-2.0.6}
|
||||
and \path{vmlinux-syms-2.6.11.11-xen0}) which are essential for
|
||||
interpreting crash dumps. Retain these files as the developers may
|
||||
wish to see them if you post on the mailing list.
|
||||
and XenLinux kernels that contain debug symbols such as
|
||||
(\path{xen-syms-2.0.6} and \path{vmlinux-syms-2.6.11.11-xen0}) which
|
||||
are essential for interpreting crash dumps. Retain these files as the
|
||||
developers may wish to see them if you post on the mailing list.
|
||||
|
||||
|
||||
\section{Configuration}
|
||||
@@ -280,23 +258,23 @@ distribution. The entry should look something like the following:
|
||||
|
||||
{\small
|
||||
\begin{verbatim}
|
||||
title Xen 2.0 / XenLinux 2.6
|
||||
kernel /boot/xen-2.0.gz dom0_mem=131072
|
||||
title Xen 3.0 / XenLinux 2.6
|
||||
kernel /boot/xen-3.0.gz dom0_mem=131072
|
||||
module /boot/vmlinuz-2.6-xen0 root=/dev/sda4 ro console=tty0
|
||||
\end{verbatim}
|
||||
}
|
||||
|
||||
The kernel line tells GRUB where to find Xen itself and what boot
|
||||
parameters should be passed to it (in this case, setting domain 0's
|
||||
parameters should be passed to it (in this case, setting the domain~0
|
||||
memory allocation in kilobytes and the settings for the serial port).
|
||||
For more details on the various Xen boot parameters see
|
||||
Section~\ref{s:xboot}.
|
||||
|
||||
The module line of the configuration describes the location of the
|
||||
XenLinux kernel that Xen should start and the parameters that should
|
||||
be passed to it (these are standard Linux parameters, identifying the
|
||||
be passed to it. Tthese are standard Linux parameters, identifying the
|
||||
root device and specifying it be initially mounted read only and
|
||||
instructing that console output be sent to the screen). Some
|
||||
instructing that console output be sent to the screen. Some
|
||||
distributions such as SuSE do not require the \path{ro} parameter.
|
||||
|
||||
%% \framebox{\parbox{5in}{
|
||||
@@ -307,25 +285,22 @@ distributions such as SuSE do not require the \path{ro} parameter.
|
||||
|
||||
|
||||
If you want to use an initrd, just add another \path{module} line to
|
||||
the configuration, as usual:
|
||||
|
||||
the configuration, like:
|
||||
{\small
|
||||
\begin{verbatim}
|
||||
module /boot/my_initrd.gz
|
||||
\end{verbatim}
|
||||
}
|
||||
|
||||
As always when installing a new kernel, it is recommended that you do
|
||||
not delete existing menu options from \path{menu.lst} --- you may want
|
||||
to boot your old Linux kernel in future, particularly if you have
|
||||
problems.
|
||||
When installing a new kernel, it is recommended that you do not delete
|
||||
existing menu options from \path{menu.lst}, as you may wish to boot
|
||||
your old Linux kernel in future, particularly if you have problems.
|
||||
|
||||
\subsection{Serial Console (optional)}
|
||||
|
||||
%% kernel /boot/xen-2.0.gz dom0_mem=131072 com1=115200,8n1
|
||||
%% module /boot/vmlinuz-2.6-xen0 root=/dev/sda4 ro
|
||||
|
||||
|
||||
In order to configure Xen serial console output, it is necessary to
|
||||
add an boot option to your GRUB config; e.g.\ replace the above kernel
|
||||
line with:
|
||||
@@ -343,24 +318,23 @@ One can also configure XenLinux to share the serial console; to
|
||||
achieve this append ``\path{console=ttyS0}'' to your module line.
|
||||
|
||||
If you wish to be able to log in over the XenLinux serial console it
|
||||
is necessary to add a line into \path{/etc/inittab}, just as per
|
||||
regular Linux. Simply add the line:
|
||||
is necessary to add a line into \path{/etc/inittab}. Add the line:
|
||||
\begin{quote} {\small {\tt c:2345:respawn:/sbin/mingetty ttyS0}}
|
||||
\end{quote}
|
||||
|
||||
and you should be able to log in. Note that to successfully log in as
|
||||
root over the serial line will require adding \path{ttyS0} to
|
||||
\path{/etc/securetty} in most modern distributions.
|
||||
and you should be able to log in. To successfully log in as root over
|
||||
the serial line will require adding \path{ttyS0} to
|
||||
\path{/etc/securetty} if it is not already there.
|
||||
|
||||
\subsection{TLS Libraries}
|
||||
|
||||
Users of the XenLinux 2.6 kernel should disable Thread Local Storage
|
||||
(e.g.\ by doing a \path{mv /lib/tls /lib/tls.disabled}) before
|
||||
attempting to run with a XenLinux kernel\footnote{If you boot without
|
||||
(TLS) (e.g.\ by doing a \path{mv /lib/tls /lib/tls.disabled}) before
|
||||
attempting to boot a XenLinux kernel\footnote{If you boot without
|
||||
first disabling TLS, you will get a warning message during the boot
|
||||
process. In this case, simply perform the rename after the machine
|
||||
is up and then run \texttt{/sbin/ldconfig} to make it take effect.}.
|
||||
You can always reenable it by restoring the directory to its original
|
||||
You can always reenable TLS by restoring the directory to its original
|
||||
location (i.e.\ \path{mv /lib/tls.disabled /lib/tls}).
|
||||
|
||||
The reason for this is that the current TLS implementation uses
|
||||
@@ -369,19 +343,19 @@ not disabled, an emulation mode is used within Xen which reduces
|
||||
performance substantially.
|
||||
|
||||
We hope that this issue can be resolved by working with Linux
|
||||
distribution vendors to implement a minor backward-compatible change
|
||||
distributions to implement a minor backward-compatible change
|
||||
to the TLS library.
|
||||
|
||||
|
||||
\section{Booting Xen}
|
||||
|
||||
It should now be possible to restart the system and use Xen. Reboot
|
||||
as usual but choose the new Xen option when the Grub screen appears.
|
||||
and choose the new Xen option when the Grub screen appears.
|
||||
|
||||
What follows should look much like a conventional Linux boot. The
|
||||
first portion of the output comes from Xen itself, supplying low level
|
||||
information about itself and the machine it is running on. The
|
||||
following portion of the output comes from XenLinux.
|
||||
information about itself and the underlying hardware. The last
|
||||
portion of the output comes from XenLinux.
|
||||
|
||||
You may see some errors during the XenLinux boot. These are not
|
||||
necessarily anything to worry about --- they may result from kernel
|
||||
@@ -389,5 +363,5 @@ configuration differences between your XenLinux kernel and the one you
|
||||
usually use.
|
||||
|
||||
When the boot completes, you should be able to log into your system as
|
||||
usual. If you are unable to log in to your system running Xen, you
|
||||
should still be able to reboot with your normal Linux kernel.
|
||||
usual. If you are unable to log in, you should still be able to
|
||||
reboot with your normal Linux kernel.
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
|
||||
Xen is a \emph{paravirtualising} virtual machine monitor (VMM), or
|
||||
`hypervisor', for the x86 processor architecture. Xen can securely
|
||||
``hypervisor'', for the x86 processor architecture. Xen can securely
|
||||
execute multiple virtual machines on a single physical system with
|
||||
close-to-native performance. The virtual machine technology
|
||||
facilitates enterprise-grade functionality, including:
|
||||
@@ -11,7 +11,7 @@ facilitates enterprise-grade functionality, including:
|
||||
\item Virtual machines with performance close to native hardware.
|
||||
\item Live migration of running virtual machines between physical
|
||||
hosts.
|
||||
\item Excellent hardware support (supports most Linux device drivers).
|
||||
\item Excellent hardware support. Supports most Linux device drivers.
|
||||
\item Sandboxed, re-startable device drivers.
|
||||
\end{itemize}
|
||||
|
||||
@@ -28,7 +28,7 @@ system kernels must explicitly support Xen, a key feature is that user
|
||||
space applications and libraries \emph{do not} require modification.
|
||||
|
||||
Xen support is available for increasingly many operating systems:
|
||||
right now, Linux and NetBSD are available for Xen 2.0.
|
||||
right now, Linux and NetBSD are available for Xen 3.0.
|
||||
A FreeBSD port is undergoing testing and will be incorporated into the
|
||||
release soon. Other OS ports, including Plan 9, are in progress. We
|
||||
hope that that arch-xen patches will be incorporated into the
|
||||
@@ -43,14 +43,14 @@ Possible usage scenarios for Xen include:
|
||||
\item [Multiple OS configurations.] Run multiple operating systems
|
||||
simultaneously, for instance for compatibility or QA purposes.
|
||||
\item [Server consolidation.] Move multiple servers onto a single
|
||||
physical host with performance and fault isolation provided at
|
||||
physical host with performance and fault isolation provided at the
|
||||
virtual machine boundaries.
|
||||
\item [Cluster computing.] Management at VM granularity provides more
|
||||
flexibility than separately managing each physical host, but better
|
||||
control and isolation than single-system image solutions,
|
||||
particularly by using live migration for load balancing.
|
||||
\item [Hardware support for custom OSes.] Allow development of new
|
||||
OSes while benefiting from the wide-ranging hardware support of
|
||||
OSes while benefitting from the wide-ranging hardware support of
|
||||
existing OSes such as Linux.
|
||||
\end{description}
|
||||
|
||||
@@ -58,44 +58,44 @@ Possible usage scenarios for Xen include:
|
||||
\section{Structure of a Xen-Based System}
|
||||
|
||||
A Xen system has multiple layers, the lowest and most privileged of
|
||||
which is Xen itself.
|
||||
which is Xen itself.
|
||||
|
||||
Xen in turn may host multiple \emph{guest} operating systems, each of
|
||||
which is executed within a secure virtual machine (in Xen terminology,
|
||||
a \emph{domain}). Domains are scheduled by Xen to make effective use
|
||||
of the available physical CPUs. Each guest OS manages its own
|
||||
applications, which includes responsibility for scheduling each
|
||||
application within the time allotted to the VM by Xen.
|
||||
Xen may host multiple \emph{guest} operating systems, each of which is
|
||||
executed within a secure virtual machine. In Xen terminology, a
|
||||
\emph{domain}. Domains are scheduled by Xen to make effective use of
|
||||
the available physical CPUs. Each guest OS manages its own
|
||||
applications. This management includes the responsibility of
|
||||
scheduling each application within the time allotted to the VM by Xen.
|
||||
|
||||
The first domain, \emph{domain 0}, is created automatically when the
|
||||
system boots and has special management privileges. Domain 0 builds
|
||||
The first domain, \emph{domain~0}, is created automatically when the
|
||||
system boots and has special management privileges. Domain~0 builds
|
||||
other domains and manages their virtual devices. It also performs
|
||||
administrative tasks such as suspending, resuming and migrating other
|
||||
virtual machines.
|
||||
|
||||
Within domain 0, a process called \emph{xend} runs to manage the
|
||||
system. \Xend is responsible for managing virtual machines and
|
||||
providing access to their consoles. Commands are issued to \xend over
|
||||
an HTTP interface, either from a command-line tool or from a web
|
||||
Within domain~0, a process called \emph{xend} runs to manage the
|
||||
system. \Xend\ is responsible for managing virtual machines and
|
||||
providing access to their consoles. Commands are issued to \xend\
|
||||
over an HTTP interface, either from a command-line tool or from a web
|
||||
browser.
|
||||
|
||||
|
||||
\section{Hardware Support}
|
||||
|
||||
Xen currently runs only on the x86 architecture, requiring a `P6' or
|
||||
newer processor (e.g. Pentium Pro, Celeron, Pentium II, Pentium III,
|
||||
Pentium IV, Xeon, AMD Athlon, AMD Duron). Multiprocessor machines are
|
||||
supported, and we also have basic support for HyperThreading (SMT),
|
||||
newer processor (e.g.\ Pentium Pro, Celeron, Pentium~II, Pentium~III,
|
||||
Pentium~IV, Xeon, AMD~Athlon, AMD~Duron). Multiprocessor machines are
|
||||
supported, and there is basic support for HyperThreading (SMT),
|
||||
although this remains a topic for ongoing research. A port
|
||||
specifically for x86/64 is in progress, although Xen already runs on
|
||||
such systems in 32-bit legacy mode. In addition a port to the IA64
|
||||
specifically for x86/64 is in progress. Xen already runs on such
|
||||
systems in 32-bit legacy mode. In addition, a port to the IA64
|
||||
architecture is approaching completion. We hope to add other
|
||||
architectures such as PPC and ARM in due course.
|
||||
|
||||
Xen can currently use up to 4GB of memory. It is possible for x86
|
||||
machines to address up to 64GB of physical memory but there are no
|
||||
current plans to support these systems: The x86/64 port is the planned
|
||||
route to supporting larger memory sizes.
|
||||
plans to support these systems: The x86/64 port is the planned route
|
||||
to supporting larger memory sizes.
|
||||
|
||||
Xen offloads most of the hardware support issues to the guest OS
|
||||
running in Domain~0. Xen itself contains only the code required to
|
||||
@@ -112,23 +112,22 @@ other hardware by configuring your XenLinux kernel in the normal way.
|
||||
|
||||
Xen was originally developed by the Systems Research Group at the
|
||||
University of Cambridge Computer Laboratory as part of the XenoServers
|
||||
project, funded by the UK-EPSRC.
|
||||
project, funded by the UK-EPSRC\@.
|
||||
|
||||
XenoServers aim to provide a `public infrastructure for global
|
||||
distributed computing', and Xen plays a key part in that, allowing us
|
||||
to efficiently partition a single machine to enable multiple
|
||||
independent clients to run their operating systems and applications in
|
||||
an environment providing protection, resource isolation and
|
||||
accounting. The project web page contains further information along
|
||||
with pointers to papers and technical reports:
|
||||
XenoServers aim to provide a ``public infrastructure for global
|
||||
distributed computing''. Xen plays a key part in that, allowing one to
|
||||
efficiently partition a single machine to enable multiple independent
|
||||
clients to run their operating systems and applications in an
|
||||
environment. This environment provides protection, resource isolation
|
||||
and accounting. The project web page contains further information
|
||||
along with pointers to papers and technical reports:
|
||||
\path{http://www.cl.cam.ac.uk/xeno}
|
||||
|
||||
Xen has since grown into a fully-fledged project in its own right,
|
||||
enabling us to investigate interesting research issues regarding the
|
||||
best techniques for virtualising resources such as the CPU, memory,
|
||||
disk and network. The project has been bolstered by support from
|
||||
Intel Research Cambridge, and HP Labs, who are now working closely
|
||||
with us.
|
||||
Xen has grown into a fully-fledged project in its own right, enabling
|
||||
us to investigate interesting research issues regarding the best
|
||||
techniques for virtualising resources such as the CPU, memory, disk
|
||||
and network. The project has been bolstered by support from Intel
|
||||
Research Cambridge and HP Labs, who are now working closely with us.
|
||||
|
||||
Xen was first described in a paper presented at SOSP in
|
||||
2003\footnote{\tt
|
||||
@@ -137,7 +136,7 @@ first public release (1.0) was made that October. Since then, Xen has
|
||||
significantly matured and is now used in production scenarios on many
|
||||
sites.
|
||||
|
||||
Xen 2.0 features greatly enhanced hardware support, configuration
|
||||
Xen 3.0 features greatly enhanced hardware support, configuration
|
||||
flexibility, usability and a larger complement of supported operating
|
||||
systems. This latest release takes Xen a step closer to becoming the
|
||||
definitive open source solution for virtualisation.
|
||||
@@ -0,0 +1,85 @@
|
||||
\chapter{Securing Xen}
|
||||
|
||||
This chapter describes how to secure a Xen system. It describes a number
|
||||
of scenarios and provides a corresponding set of best practices. It
|
||||
begins with a section devoted to understanding the security implications
|
||||
of a Xen system.
|
||||
|
||||
|
||||
\section{Xen Security Considerations}
|
||||
|
||||
When deploying a Xen system, one must be sure to secure the management
|
||||
domain (Domain-0) as much as possible. If the management domain is
|
||||
compromised, all other domains are also vulnerable. The following are a
|
||||
set of best practices for Domain-0:
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Run the smallest number of necessary services.} The less
|
||||
things that are present in a management partition, the better.
|
||||
Remember, a service running as root in the management domain has full
|
||||
access to all other domains on the system.
|
||||
\item \textbf{Use a firewall to restrict the traffic to the management
|
||||
domain.} A firewall with default-reject rules will help prevent
|
||||
attacks on the management domain.
|
||||
\item \textbf{Do not allow users to access Domain-0.} The Linux kernel
|
||||
has been known to have local-user root exploits. If you allow normal
|
||||
users to access Domain-0 (even as unprivileged users) you run the risk
|
||||
of a kernel exploit making all of your domains vulnerable.
|
||||
\end{enumerate}
|
||||
|
||||
\section{Security Scenarios}
|
||||
|
||||
|
||||
\subsection{The Isolated Management Network}
|
||||
|
||||
In this scenario, each node has two network cards in the cluster. One
|
||||
network card is connected to the outside world and one network card is a
|
||||
physically isolated management network specifically for Xen instances to
|
||||
use.
|
||||
|
||||
As long as all of the management partitions are trusted equally, this is
|
||||
the most secure scenario. No additional configuration is needed other
|
||||
than forcing Xend to bind to the management interface for relocation.
|
||||
|
||||
\textbf{FIXME:} What is the option to allow for this?
|
||||
|
||||
|
||||
\subsection{A Subnet Behind a Firewall}
|
||||
|
||||
In this scenario, each node has only one network card but the entire
|
||||
cluster sits behind a firewall. This firewall should do at least the
|
||||
following:
|
||||
|
||||
\begin{enumerate}
|
||||
\item Prevent IP spoofing from outside of the subnet.
|
||||
\item Prevent access to the relocation port of any of the nodes in the
|
||||
cluster except from within the cluster.
|
||||
\end{enumerate}
|
||||
|
||||
The following iptables rules can be used on each node to prevent
|
||||
migrations to that node from outside the subnet assuming the main
|
||||
firewall does not do this for you:
|
||||
|
||||
\begin{verbatim}
|
||||
# this command disables all access to the Xen relocation
|
||||
# port:
|
||||
iptables -A INPUT -p tcp --destination-port 8002 -j REJECT
|
||||
|
||||
# this command enables Xen relocations only from the specific
|
||||
# subnet:
|
||||
iptables -I INPUT -p tcp -{}-source 192.168.1.1/8 \
|
||||
--destination-port 8002 -j ACCEPT
|
||||
\end{verbatim}
|
||||
|
||||
\subsection{Nodes on an Untrusted Subnet}
|
||||
|
||||
Migration on an untrusted subnet is not safe in current versions of Xen.
|
||||
It may be possible to perform migrations through a secure tunnel via an
|
||||
VPN or SSH. The only safe option in the absence of a secure tunnel is to
|
||||
disable migration completely. The easiest way to do this is with
|
||||
iptables:
|
||||
|
||||
\begin{verbatim}
|
||||
# this command disables all access to the Xen relocation port
|
||||
iptables -A INPUT -p tcp -{}-destination-port 8002 -j REJECT
|
||||
\end{verbatim}
|
||||
@@ -40,8 +40,7 @@ configuration file. We provide two example files which you can use as
|
||||
a starting point:
|
||||
\begin{itemize}
|
||||
\item \path{/etc/xen/xmexample1} is a simple template configuration
|
||||
file for describing a single VM.
|
||||
|
||||
file for describing a single VM\@.
|
||||
\item \path{/etc/xen/xmexample2} file is a template description that
|
||||
is intended to be reused for multiple virtual machines. Setting the
|
||||
value of the \path{vmid} variable on the \path{xm} command line
|
||||
@@ -54,17 +53,17 @@ you may wish to edit include:
|
||||
\begin{quote}
|
||||
\begin{description}
|
||||
\item[kernel] Set this to the path of the kernel you compiled for use
|
||||
with Xen (e.g.\ \path{kernel = `/boot/vmlinuz-2.6-xenU'})
|
||||
with Xen (e.g.\ \path{kernel = ``/boot/vmlinuz-2.6-xenU''})
|
||||
\item[memory] Set this to the size of the domain's memory in megabytes
|
||||
(e.g.\ \path{memory = 64})
|
||||
\item[disk] Set the first entry in this list to calculate the offset
|
||||
of the domain's root partition, based on the domain ID. Set the
|
||||
of the domain's root partition, based on the domain ID\@. Set the
|
||||
second to the location of \path{/usr} if you are sharing it between
|
||||
domains (e.g.\ \path{disk = [`phy:your\_hard\_drive\%d,sda1,w' \%
|
||||
domains (e.g.\ \path{disk = ['phy:your\_hard\_drive\%d,sda1,w' \%
|
||||
(base\_partition\_number + vmid),
|
||||
`phy:your\_usr\_partition,sda6,r' ]}
|
||||
'phy:your\_usr\_partition,sda6,r' ]}
|
||||
\item[dhcp] Uncomment the dhcp variable, so that the domain will
|
||||
receive its IP address from a DHCP server (e.g.\ \path{dhcp=`dhcp'})
|
||||
receive its IP address from a DHCP server (e.g.\ \path{dhcp=``dhcp''})
|
||||
\end{description}
|
||||
\end{quote}
|
||||
|
||||
@@ -72,7 +71,7 @@ You may also want to edit the {\bf vif} variable in order to choose
|
||||
the MAC address of the virtual ethernet interface yourself. For
|
||||
example:
|
||||
\begin{quote}
|
||||
\verb_vif = [`mac=00:06:AA:F6:BB:B3']_
|
||||
\verb_vif = ['mac=00:06:AA:F6:BB:B3']_
|
||||
\end{quote}
|
||||
If you do not set this variable, \xend\ will automatically generate a
|
||||
random MAC address from an unused range.
|
||||
@@ -116,6 +115,7 @@ distribution once they have mastered the basics\footnote{ttylinux is
|
||||
section of the project's SourceForge site (see
|
||||
\path{http://sf.net/projects/xen/}).
|
||||
\item Create a configuration file like the following:
|
||||
\begin{quote}
|
||||
\begin{verbatim}
|
||||
kernel = "/boot/vmlinuz-2.6-xenU"
|
||||
memory = 64
|
||||
@@ -124,11 +124,14 @@ nics = 1
|
||||
ip = "1.2.3.4"
|
||||
disk = ['file:/path/to/ttylinux/rootfs,sda1,w']
|
||||
root = "/dev/sda1 ro"
|
||||
\end{verbatim}
|
||||
\end{verbatim}
|
||||
\end{quote}
|
||||
\item Now start the domain and connect to its console:
|
||||
\begin{quote}
|
||||
\begin{verbatim}
|
||||
xm create configfile -c
|
||||
\end{verbatim}
|
||||
\end{quote}
|
||||
\item Login as root, password root.
|
||||
\end{enumerate}
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ VM_MASK = 0x00020000
|
||||
#define evtchn_upcall_pending /* 0 */
|
||||
#define evtchn_upcall_mask 1
|
||||
|
||||
#define sizeof_vcpu_shift 3
|
||||
#define sizeof_vcpu_shift 4
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#define preempt_disable(reg) incl TI_preempt_count(reg)
|
||||
@@ -813,35 +813,9 @@ ENTRY(alignment_check)
|
||||
pushl $do_alignment_check
|
||||
jmp error_code
|
||||
|
||||
# This handler is special, because it gets an extra value on its stack,
|
||||
# which is the linear faulting address.
|
||||
# fastcall register usage: %eax = pt_regs, %edx = error code,
|
||||
# %ecx = fault address
|
||||
ENTRY(page_fault)
|
||||
pushl %ds
|
||||
pushl %eax
|
||||
xorl %eax, %eax
|
||||
pushl %ebp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %edx
|
||||
decl %eax /* eax = -1 */
|
||||
pushl %ecx
|
||||
pushl %ebx
|
||||
cld
|
||||
pushl %es
|
||||
# UNWIND_ESPFIX_STACK
|
||||
popl %edi
|
||||
movl ES(%esp), %ecx /* get the faulting address */
|
||||
movl ORIG_EAX(%esp), %edx /* get the error code */
|
||||
movl %eax, ORIG_EAX(%esp)
|
||||
movl %edi, ES(%esp)
|
||||
movl $(__KERNEL_DS),%eax
|
||||
movl %eax, %ds
|
||||
movl %eax, %es
|
||||
movl %esp,%eax /* pt_regs pointer */
|
||||
call do_page_fault
|
||||
jmp ret_from_exception
|
||||
pushl $do_page_fault
|
||||
jmp error_code
|
||||
|
||||
#ifdef CONFIG_X86_MCE
|
||||
ENTRY(machine_check)
|
||||
|
||||
@@ -650,7 +650,7 @@ fastcall void do_int3(struct pt_regs *regs, long error_code)
|
||||
|
||||
static inline void conditional_sti(struct pt_regs *regs)
|
||||
{
|
||||
if ((uint8_t)(regs->xcs >> 16) == 0)
|
||||
if (regs->eflags & (X86_EFLAGS_IF|VM_MASK))
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
@@ -972,7 +972,7 @@ void __init trap_init_f00f_bug(void)
|
||||
|
||||
|
||||
/*
|
||||
* NB. All these are "trap gates" (i.e. events_mask isn't cleared) except
|
||||
* NB. All these are "trap gates" (i.e. events_mask isn't set) except
|
||||
* for those that specify <dpl>|4 in the second field.
|
||||
*/
|
||||
static trap_info_t trap_table[] = {
|
||||
@@ -988,7 +988,7 @@ static trap_info_t trap_table[] = {
|
||||
{ 11, 0, __KERNEL_CS, (unsigned long)segment_not_present },
|
||||
{ 12, 0, __KERNEL_CS, (unsigned long)stack_segment },
|
||||
{ 13, 0, __KERNEL_CS, (unsigned long)general_protection },
|
||||
{ 14, 0, __KERNEL_CS, (unsigned long)page_fault },
|
||||
{ 14, 0|4, __KERNEL_CS, (unsigned long)page_fault },
|
||||
{ 15, 0, __KERNEL_CS, (unsigned long)fixup_4gb_segment },
|
||||
{ 16, 0, __KERNEL_CS, (unsigned long)coprocessor_error },
|
||||
{ 17, 0, __KERNEL_CS, (unsigned long)alignment_check },
|
||||
|
||||
@@ -208,6 +208,7 @@ fastcall void do_invalid_op(struct pt_regs *, unsigned long);
|
||||
static void dump_fault_path(unsigned long address)
|
||||
{
|
||||
unsigned long *p, page;
|
||||
unsigned long mfn;
|
||||
|
||||
preempt_disable();
|
||||
page = __pa(per_cpu(cur_pgd, smp_processor_id()));
|
||||
@@ -217,20 +218,22 @@ static void dump_fault_path(unsigned long address)
|
||||
p += (address >> 30) * 2;
|
||||
printk(KERN_ALERT "%08lx -> *pde = %08lx:%08lx\n", page, p[1], p[0]);
|
||||
if (p[0] & 1) {
|
||||
page = p[0] & PAGE_MASK;
|
||||
address &= 0x3fffffff;
|
||||
page = machine_to_phys(page);
|
||||
mfn = (p[0] >> PAGE_SHIFT) | ((p[1] & 0x7) << 20);
|
||||
page = mfn_to_pfn(mfn) << PAGE_SHIFT;
|
||||
p = (unsigned long *)__va(page);
|
||||
address &= 0x3fffffff;
|
||||
p += (address >> 21) * 2;
|
||||
printk(KERN_ALERT "%08lx -> *pme = %08lx:%08lx\n", page, p[1], p[0]);
|
||||
printk(KERN_ALERT "%08lx -> *pme = %08lx:%08lx\n",
|
||||
page, p[1], p[0]);
|
||||
#ifndef CONFIG_HIGHPTE
|
||||
if (p[0] & 1) {
|
||||
page = p[0] & PAGE_MASK;
|
||||
address &= 0x001fffff;
|
||||
page = machine_to_phys(page);
|
||||
mfn = (p[0] >> PAGE_SHIFT) | ((p[1] & 0x7) << 20);
|
||||
page = mfn_to_pfn(mfn) << PAGE_SHIFT;
|
||||
p = (unsigned long *) __va(page);
|
||||
address &= 0x001fffff;
|
||||
p += (address >> 12) * 2;
|
||||
printk(KERN_ALERT "%08lx -> *pte = %08lx:%08lx\n", page, p[1], p[0]);
|
||||
printk(KERN_ALERT "%08lx -> *pte = %08lx:%08lx\n",
|
||||
page, p[1], p[0]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -279,15 +282,18 @@ static void dump_fault_path(unsigned long address)
|
||||
* bit 1 == 0 means read, 1 means write
|
||||
* bit 2 == 0 means kernel, 1 means user-mode
|
||||
*/
|
||||
fastcall void do_page_fault(struct pt_regs *regs, unsigned long error_code,
|
||||
unsigned long address)
|
||||
fastcall void do_page_fault(struct pt_regs *regs, unsigned long error_code)
|
||||
{
|
||||
struct task_struct *tsk;
|
||||
struct mm_struct *mm;
|
||||
struct vm_area_struct * vma;
|
||||
unsigned long address;
|
||||
int write;
|
||||
siginfo_t info;
|
||||
|
||||
address = HYPERVISOR_shared_info->vcpu_data[
|
||||
smp_processor_id()].arch.cr2;
|
||||
|
||||
/* Set the "privileged fault" bit to something sane. */
|
||||
error_code &= ~4;
|
||||
error_code |= (regs->xcs & 2) << 1;
|
||||
@@ -297,11 +303,9 @@ fastcall void do_page_fault(struct pt_regs *regs, unsigned long error_code,
|
||||
if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
|
||||
SIGSEGV) == NOTIFY_STOP)
|
||||
return;
|
||||
#if 0
|
||||
/* It's safe to allow irq's after cr2 has been saved */
|
||||
if (regs->eflags & (X86_EFLAGS_IF|VM_MASK))
|
||||
local_irq_enable();
|
||||
#endif
|
||||
|
||||
tsk = current;
|
||||
|
||||
|
||||
@@ -342,8 +342,8 @@ int xen_create_contiguous_region(
|
||||
mfn = pte_mfn(*pte);
|
||||
BUG_ON(HYPERVISOR_update_va_mapping(
|
||||
vstart + (i*PAGE_SIZE), __pte_ma(0), 0));
|
||||
phys_to_machine_mapping[(__pa(vstart)>>PAGE_SHIFT)+i] =
|
||||
INVALID_P2M_ENTRY;
|
||||
set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i,
|
||||
INVALID_P2M_ENTRY);
|
||||
BUG_ON(HYPERVISOR_memory_op(
|
||||
XENMEM_decrease_reservation, &reservation) != 1);
|
||||
}
|
||||
@@ -361,7 +361,7 @@ int xen_create_contiguous_region(
|
||||
vstart + (i*PAGE_SIZE),
|
||||
pfn_pte_ma(mfn+i, PAGE_KERNEL), 0));
|
||||
xen_machphys_update(mfn+i, (__pa(vstart)>>PAGE_SHIFT)+i);
|
||||
phys_to_machine_mapping[(__pa(vstart)>>PAGE_SHIFT)+i] = mfn+i;
|
||||
set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, mfn+i);
|
||||
}
|
||||
|
||||
flush_tlb_all();
|
||||
@@ -383,7 +383,7 @@ int xen_create_contiguous_region(
|
||||
vstart + (i*PAGE_SIZE),
|
||||
pfn_pte_ma(mfn, PAGE_KERNEL), 0));
|
||||
xen_machphys_update(mfn, (__pa(vstart)>>PAGE_SHIFT)+i);
|
||||
phys_to_machine_mapping[(__pa(vstart)>>PAGE_SHIFT)+i] = mfn;
|
||||
set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, mfn);
|
||||
}
|
||||
|
||||
flush_tlb_all();
|
||||
@@ -422,8 +422,8 @@ void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order)
|
||||
mfn = pte_mfn(*pte);
|
||||
BUG_ON(HYPERVISOR_update_va_mapping(
|
||||
vstart + (i*PAGE_SIZE), __pte_ma(0), 0));
|
||||
phys_to_machine_mapping[(__pa(vstart)>>PAGE_SHIFT)+i] =
|
||||
INVALID_P2M_ENTRY;
|
||||
set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i,
|
||||
INVALID_P2M_ENTRY);
|
||||
BUG_ON(HYPERVISOR_memory_op(
|
||||
XENMEM_decrease_reservation, &reservation) != 1);
|
||||
}
|
||||
@@ -436,7 +436,7 @@ void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order)
|
||||
vstart + (i*PAGE_SIZE),
|
||||
pfn_pte_ma(mfn, PAGE_KERNEL), 0));
|
||||
xen_machphys_update(mfn, (__pa(vstart)>>PAGE_SHIFT)+i);
|
||||
phys_to_machine_mapping[(__pa(vstart)>>PAGE_SHIFT)+i] = mfn;
|
||||
set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, mfn);
|
||||
}
|
||||
|
||||
flush_tlb_all();
|
||||
|
||||
@@ -874,42 +874,8 @@ ENTRY(execve)
|
||||
ret
|
||||
CFI_ENDPROC
|
||||
|
||||
|
||||
/*
|
||||
* Copy error_entry because of the different stack frame
|
||||
*/
|
||||
ENTRY(page_fault)
|
||||
movq (%rsp),%rcx
|
||||
movq 8(%rsp),%r11
|
||||
addq $0x10,%rsp # now %rsp points to %cr2
|
||||
pushq %rax
|
||||
leaq do_page_fault(%rip),%rax
|
||||
cld
|
||||
subq $13*8,%rsp
|
||||
movq %rdx,12*8(%rsp) # save %rdx
|
||||
movq 13*8(%rsp),%rdx # load rax
|
||||
movq %rcx,11*8(%rsp)
|
||||
movq %rdx,10*8(%rsp) # store rax
|
||||
movq %rsi,13*8(%rsp) # now save %rsi
|
||||
movq 14*8(%rsp),%rdx # load %cr2, 3rd argument
|
||||
movq %r8, 9*8(%rsp)
|
||||
movq %r9, 8*8(%rsp)
|
||||
movq %r10,7*8(%rsp)
|
||||
movq %r11,6*8(%rsp)
|
||||
movq %rbx,5*8(%rsp)
|
||||
movq %rbp,4*8(%rsp)
|
||||
movq %r12,3*8(%rsp)
|
||||
movq %r13,2*8(%rsp)
|
||||
movq %r14,1*8(%rsp)
|
||||
movq %r15,(%rsp)
|
||||
#if 0
|
||||
cmpl $__KERNEL_CS,CS(%rsp)
|
||||
je error_kernelspace
|
||||
#endif
|
||||
/*
|
||||
* 1st and 2nd arguments are set by error_call_handler
|
||||
*/
|
||||
jmp error_call_handler
|
||||
errorentry do_page_fault
|
||||
|
||||
ENTRY(coprocessor_error)
|
||||
zeroentry do_coprocessor_error
|
||||
@@ -948,24 +914,15 @@ ENTRY(nmi)
|
||||
paranoid_exit:
|
||||
testl %ebx,%ebx /* swapgs needed? */
|
||||
jnz paranoid_restore
|
||||
testl $3,CS(%rsp)
|
||||
jnz paranoid_userspace
|
||||
paranoid_swapgs:
|
||||
/* swapgs */
|
||||
swapgs
|
||||
paranoid_restore:
|
||||
RESTORE_ALL 8
|
||||
/* iretq */
|
||||
iretq
|
||||
paranoid_userspace:
|
||||
GET_THREAD_INFO(%rcx)
|
||||
# movl threadinfo_flags(%rcx),%edx
|
||||
# testl $_TIF_NEED_RESCHED,%edx
|
||||
# jnz paranoid_resched
|
||||
# testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
|
||||
# jnz paranoid_signal
|
||||
# jmp paranoid_swapgs
|
||||
#paranoid_resched:
|
||||
#/* sti */
|
||||
# call schedule
|
||||
# jmp paranoid_exit
|
||||
#paranoid_signal:
|
||||
movl threadinfo_flags(%rcx),%ebx
|
||||
andl $_TIF_WORK_MASK,%ebx
|
||||
jz paranoid_swapgs
|
||||
@@ -975,13 +932,10 @@ paranoid_userspace:
|
||||
testl $_TIF_NEED_RESCHED,%ebx
|
||||
jnz paranoid_schedule
|
||||
movl %ebx,%edx /* arg3: thread flags */
|
||||
/* sti */
|
||||
# xorl %esi,%esi /* oldset */
|
||||
# movq %rsp,%rdi /* &pt_regs */
|
||||
sti
|
||||
xorl %esi,%esi /* arg2: oldset */
|
||||
movq %rsp,%rdi /* arg1: &pt_regs */
|
||||
call do_notify_resume
|
||||
# jmp paranoid_exit
|
||||
cli
|
||||
jmp paranoid_userspace
|
||||
paranoid_schedule:
|
||||
@@ -1057,4 +1011,3 @@ ENTRY(machine_check)
|
||||
ENTRY(call_debug)
|
||||
zeroentry do_call_debug
|
||||
|
||||
|
||||
@@ -905,30 +905,33 @@ void do_call_debug(struct pt_regs *regs)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* NB. All these are "interrupt gates" (i.e. events_mask is set) because we
|
||||
* specify <dpl>|4 in the second field.
|
||||
*/
|
||||
static trap_info_t trap_table[] = {
|
||||
{ 0, 0, (__KERNEL_CS|0x3), (unsigned long)divide_error },
|
||||
{ 1, 0, (__KERNEL_CS|0x3), (unsigned long)debug },
|
||||
{ 3, 3, (__KERNEL_CS|0x3), (unsigned long)int3 },
|
||||
{ 4, 3, (__KERNEL_CS|0x3), (unsigned long)overflow },
|
||||
{ 5, 3, (__KERNEL_CS|0x3), (unsigned long)bounds },
|
||||
{ 6, 0, (__KERNEL_CS|0x3), (unsigned long)invalid_op },
|
||||
{ 7, 0, (__KERNEL_CS|0x3), (unsigned long)device_not_available },
|
||||
{ 9, 0, (__KERNEL_CS|0x3), (unsigned long)coprocessor_segment_overrun},
|
||||
{ 10, 0, (__KERNEL_CS|0x3), (unsigned long)invalid_TSS },
|
||||
{ 11, 0, (__KERNEL_CS|0x3), (unsigned long)segment_not_present },
|
||||
{ 12, 0, (__KERNEL_CS|0x3), (unsigned long)stack_segment },
|
||||
{ 13, 0, (__KERNEL_CS|0x3), (unsigned long)general_protection },
|
||||
{ 14, 0, (__KERNEL_CS|0x3), (unsigned long)page_fault },
|
||||
{ 15, 0, (__KERNEL_CS|0x3), (unsigned long)spurious_interrupt_bug },
|
||||
{ 16, 0, (__KERNEL_CS|0x3), (unsigned long)coprocessor_error },
|
||||
{ 17, 0, (__KERNEL_CS|0x3), (unsigned long)alignment_check },
|
||||
{ 0, 0|4, (__KERNEL_CS|0x3), (unsigned long)divide_error },
|
||||
{ 1, 0|4, (__KERNEL_CS|0x3), (unsigned long)debug },
|
||||
{ 3, 3|4, (__KERNEL_CS|0x3), (unsigned long)int3 },
|
||||
{ 4, 3|4, (__KERNEL_CS|0x3), (unsigned long)overflow },
|
||||
{ 5, 3|4, (__KERNEL_CS|0x3), (unsigned long)bounds },
|
||||
{ 6, 0|4, (__KERNEL_CS|0x3), (unsigned long)invalid_op },
|
||||
{ 7, 0|4, (__KERNEL_CS|0x3), (unsigned long)device_not_available },
|
||||
{ 9, 0|4, (__KERNEL_CS|0x3), (unsigned long)coprocessor_segment_overrun},
|
||||
{ 10, 0|4, (__KERNEL_CS|0x3), (unsigned long)invalid_TSS },
|
||||
{ 11, 0|4, (__KERNEL_CS|0x3), (unsigned long)segment_not_present },
|
||||
{ 12, 0|4, (__KERNEL_CS|0x3), (unsigned long)stack_segment },
|
||||
{ 13, 0|4, (__KERNEL_CS|0x3), (unsigned long)general_protection },
|
||||
{ 14, 0|4, (__KERNEL_CS|0x3), (unsigned long)page_fault },
|
||||
{ 15, 0|4, (__KERNEL_CS|0x3), (unsigned long)spurious_interrupt_bug },
|
||||
{ 16, 0|4, (__KERNEL_CS|0x3), (unsigned long)coprocessor_error },
|
||||
{ 17, 0|4, (__KERNEL_CS|0x3), (unsigned long)alignment_check },
|
||||
#ifdef CONFIG_X86_MCE
|
||||
{ 18, 0, (__KERNEL_CS|0x3), (unsigned long)machine_check },
|
||||
{ 18, 0|4, (__KERNEL_CS|0x3), (unsigned long)machine_check },
|
||||
#endif
|
||||
{ 19, 0, (__KERNEL_CS|0x3), (unsigned long)simd_coprocessor_error },
|
||||
{ SYSCALL_VECTOR, 3, (__KERNEL_CS|0x3), (unsigned long)system_call },
|
||||
{ 19, 0|4, (__KERNEL_CS|0x3), (unsigned long)simd_coprocessor_error },
|
||||
#ifdef CONFIG_IA32_EMULATION
|
||||
{ IA32_SYSCALL_VECTOR, 3, (__KERNEL_CS|0x3), (unsigned long)ia32_syscall},
|
||||
{ IA32_SYSCALL_VECTOR, 3|4, (__KERNEL_CS|0x3), (unsigned long)ia32_syscall},
|
||||
#endif
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
@@ -128,8 +128,10 @@ EXPORT_SYMBOL(get_wchan);
|
||||
|
||||
EXPORT_SYMBOL(rtc_lock);
|
||||
|
||||
/* EXPORT_SYMBOL_GPL(set_nmi_callback);
|
||||
EXPORT_SYMBOL_GPL(unset_nmi_callback); */
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
EXPORT_SYMBOL_GPL(set_nmi_callback);
|
||||
EXPORT_SYMBOL_GPL(unset_nmi_callback);
|
||||
#endif
|
||||
|
||||
/* Export string functions. We normally rely on gcc builtin for most of these,
|
||||
but gcc sometimes decides not to inline them. */
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#define evtchn_upcall_pending 0
|
||||
#define evtchn_upcall_mask 1
|
||||
|
||||
#define sizeof_vcpu_shift 4
|
||||
#define sizeof_vcpu_shift 5
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
//#define preempt_disable(reg) incl threadinfo_preempt_count(reg)
|
||||
|
||||
@@ -318,12 +318,12 @@ int exception_trace = 1;
|
||||
* bit 2 == 0 means kernel, 1 means user-mode
|
||||
* bit 3 == 1 means fault was an instruction fetch
|
||||
*/
|
||||
asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code,
|
||||
unsigned long address)
|
||||
asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
|
||||
{
|
||||
struct task_struct *tsk;
|
||||
struct mm_struct *mm;
|
||||
struct vm_area_struct * vma;
|
||||
unsigned long address;
|
||||
const struct exception_table_entry *fixup;
|
||||
int write;
|
||||
siginfo_t info;
|
||||
@@ -342,6 +342,11 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* get the address */
|
||||
address = HYPERVISOR_shared_info->vcpu_data[
|
||||
smp_processor_id()].arch.cr2;
|
||||
|
||||
if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
|
||||
SIGSEGV) == NOTIFY_STOP)
|
||||
return;
|
||||
|
||||
@@ -210,7 +210,7 @@ static int increase_reservation(unsigned long nr_pages)
|
||||
BUG_ON(phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY);
|
||||
|
||||
/* Update P->M and M->P tables. */
|
||||
phys_to_machine_mapping[pfn] = mfn_list[i];
|
||||
set_phys_to_machine(pfn, mfn_list[i]);
|
||||
xen_machphys_update(mfn_list[i], pfn);
|
||||
|
||||
/* Link back into the page tables if not highmem. */
|
||||
@@ -295,7 +295,7 @@ static int decrease_reservation(unsigned long nr_pages)
|
||||
/* No more mappings: invalidate P2M and add to balloon. */
|
||||
for (i = 0; i < nr_pages; i++) {
|
||||
pfn = mfn_to_pfn(mfn_list[i]);
|
||||
phys_to_machine_mapping[pfn] = INVALID_P2M_ENTRY;
|
||||
set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
|
||||
balloon_append(pfn_to_page(pfn));
|
||||
}
|
||||
|
||||
@@ -515,8 +515,7 @@ static int dealloc_pte_fn(
|
||||
.domid = DOMID_SELF
|
||||
};
|
||||
set_pte_at(&init_mm, addr, pte, __pte_ma(0));
|
||||
phys_to_machine_mapping[__pa(addr) >> PAGE_SHIFT] =
|
||||
INVALID_P2M_ENTRY;
|
||||
set_phys_to_machine(__pa(addr) >> PAGE_SHIFT, INVALID_P2M_ENTRY);
|
||||
ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
|
||||
BUG_ON(ret != 1);
|
||||
return 0;
|
||||
|
||||
@@ -386,9 +386,9 @@ static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req)
|
||||
#ifdef __ia64__
|
||||
MMAP_VADDR(pending_idx,i) = gnttab_map_vaddr(map[i]);
|
||||
#else
|
||||
phys_to_machine_mapping[__pa(MMAP_VADDR(
|
||||
pending_idx, i)) >> PAGE_SHIFT] =
|
||||
FOREIGN_FRAME(map[i].dev_bus_addr>>PAGE_SHIFT);
|
||||
set_phys_to_machine(__pa(MMAP_VADDR(
|
||||
pending_idx, i)) >> PAGE_SHIFT,
|
||||
FOREIGN_FRAME(map[i].dev_bus_addr>>PAGE_SHIFT));
|
||||
#endif
|
||||
fas = req->frame_and_sects[i];
|
||||
seg[i].buf = map[i].dev_bus_addr |
|
||||
|
||||
@@ -777,8 +777,8 @@ static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req)
|
||||
/* Set the necessary mappings in p2m and in the VM_FOREIGN
|
||||
* vm_area_struct to allow user vaddr -> struct page lookups
|
||||
* to work. This is needed for direct IO to foreign pages. */
|
||||
phys_to_machine_mapping[__pa(kvaddr) >> PAGE_SHIFT] =
|
||||
FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT);
|
||||
set_phys_to_machine(__pa(kvaddr) >> PAGE_SHIFT,
|
||||
FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT));
|
||||
|
||||
offset = (uvaddr - blktap_vma->vm_start) >> PAGE_SHIFT;
|
||||
((struct page **)blktap_vma->vm_private_data)[offset] =
|
||||
|
||||
@@ -241,11 +241,7 @@ console_initcall(xen_console_init);
|
||||
#endif
|
||||
|
||||
/*** Useful function for console debugging -- goes straight to Xen. ***/
|
||||
#ifdef CONFIG_XEN_PRIVILEGED_GUEST
|
||||
asmlinkage int xprintk(const char *fmt, ...)
|
||||
#else
|
||||
asmlinkage int xprintk(const char *fmt, ...)
|
||||
#endif
|
||||
{
|
||||
va_list args;
|
||||
int printk_len;
|
||||
|
||||
@@ -248,8 +248,7 @@ static void net_rx_action(unsigned long unused)
|
||||
* Set the new P2M table entry before reassigning the old data
|
||||
* page. Heed the comment in pgtable-2level.h:pte_page(). :-)
|
||||
*/
|
||||
phys_to_machine_mapping[__pa(skb->data) >> PAGE_SHIFT] =
|
||||
new_mfn;
|
||||
set_phys_to_machine(__pa(skb->data) >> PAGE_SHIFT, new_mfn);
|
||||
|
||||
MULTI_update_va_mapping(mcl, vdata,
|
||||
pfn_pte_ma(new_mfn, PAGE_KERNEL), 0);
|
||||
@@ -631,9 +630,9 @@ static void net_tx_action(unsigned long unused)
|
||||
pending_idx;
|
||||
continue;
|
||||
}
|
||||
phys_to_machine_mapping[
|
||||
__pa(MMAP_VADDR(pending_idx)) >> PAGE_SHIFT] =
|
||||
FOREIGN_FRAME(mop->dev_bus_addr >> PAGE_SHIFT);
|
||||
set_phys_to_machine(
|
||||
__pa(MMAP_VADDR(pending_idx)) >> PAGE_SHIFT,
|
||||
FOREIGN_FRAME(mop->dev_bus_addr >> PAGE_SHIFT));
|
||||
grant_tx_ref[pending_idx] = mop->handle;
|
||||
|
||||
data_len = (txreq.size > PKT_PROT_LEN) ?
|
||||
|
||||
@@ -342,8 +342,7 @@ static void network_alloc_rx_buffers(struct net_device *dev)
|
||||
rx_pfn_array[i] = virt_to_mfn(skb->head);
|
||||
|
||||
/* Remove this page from map before passing back to Xen. */
|
||||
phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT]
|
||||
= INVALID_P2M_ENTRY;
|
||||
set_phys_to_machine(__pa(skb->head) >> PAGE_SHIFT, INVALID_P2M_ENTRY);
|
||||
|
||||
MULTI_update_va_mapping(rx_mcl+i, (unsigned long)skb->head,
|
||||
__pte(0), 0);
|
||||
@@ -570,7 +569,7 @@ static int netif_poll(struct net_device *dev, int *pbudget)
|
||||
pfn_pte_ma(mfn, PAGE_KERNEL), 0);
|
||||
mcl++;
|
||||
|
||||
phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] = mfn;
|
||||
set_phys_to_machine(__pa(skb->head) >> PAGE_SHIFT, mfn);
|
||||
|
||||
__skb_queue_tail(&rxq, skb);
|
||||
}
|
||||
|
||||
@@ -296,9 +296,8 @@ _packet_write(struct packet *pak,
|
||||
DPRINTK(" Grant table operation failure !\n");
|
||||
return 0;
|
||||
}
|
||||
phys_to_machine_mapping[__pa(MMAP_VADDR(tpmif,i)) >>
|
||||
PAGE_SHIFT] =
|
||||
FOREIGN_FRAME(map_op.dev_bus_addr >> PAGE_SHIFT);
|
||||
set_phys_to_machine(__pa(MMAP_VADDR(tpmif,i)) >> PAGE_SHIFT,
|
||||
FOREIGN_FRAME(map_op.dev_bus_addr >> PAGE_SHIFT));
|
||||
|
||||
tocopy = MIN(size - offset, PAGE_SIZE);
|
||||
|
||||
|
||||
@@ -86,6 +86,11 @@ static inline unsigned long mfn_to_pfn(unsigned long mfn)
|
||||
return pfn;
|
||||
}
|
||||
|
||||
static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
|
||||
{
|
||||
phys_to_machine_mapping[pfn] = mfn;
|
||||
}
|
||||
|
||||
/* Definitions for machine and pseudophysical addresses. */
|
||||
#ifdef CONFIG_X86_PAE
|
||||
typedef unsigned long long paddr_t;
|
||||
|
||||
@@ -88,6 +88,11 @@ static inline unsigned long mfn_to_pfn(unsigned long mfn)
|
||||
return pfn;
|
||||
}
|
||||
|
||||
static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
|
||||
{
|
||||
phys_to_machine_mapping[pfn] = mfn;
|
||||
}
|
||||
|
||||
/* Definitions for machine and pseudophysical addresses. */
|
||||
typedef unsigned long paddr_t;
|
||||
typedef unsigned long maddr_t;
|
||||
|
||||
@@ -16,29 +16,38 @@
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# network (start|stop|status) {VAR=VAL}*
|
||||
# network-bridge (start|stop|status) {VAR=VAL}*
|
||||
#
|
||||
# Vars:
|
||||
#
|
||||
# vifnum Virtual device number to use (default 0). Numbers >=1
|
||||
# vifnum Virtual device number to use (default 0). Numbers >=8
|
||||
# require the netback driver to have nloopbacks set to a
|
||||
# higher value than its default of 1.
|
||||
# higher value than its default of 8.
|
||||
# bridge The bridge to use (default xenbr${vifnum}).
|
||||
# netdev The interface to add to the bridge (default eth${vifnum}).
|
||||
# antispoof Whether to use iptables to prevent spoofing (default no).
|
||||
#
|
||||
# Internal Vars:
|
||||
# pdev="p${netdev}"
|
||||
# vdev="veth${vifnum}"
|
||||
# vif0="vif0.${vifnum}"
|
||||
#
|
||||
# start:
|
||||
# Creates the bridge and enslaves netdev to it.
|
||||
# Copies the IP addresses from netdev to the bridge.
|
||||
# Deletes the routes to netdev and adds them on bridge.
|
||||
# Creates the bridge
|
||||
# Copies the IP and MAC addresses from netdev to vdev
|
||||
# Renames netdev to be pdev
|
||||
# Renames vdev to be netdev
|
||||
# Enslaves pdev, vdev to bridge
|
||||
#
|
||||
# stop:
|
||||
# Removes netdev from the bridge.
|
||||
# Deletes the routes to bridge and adds them to netdev.
|
||||
# Removes netdev from the bridge
|
||||
# Transfers addresses, routes from netdev to pdev
|
||||
# Renames netdev to vdev
|
||||
# Renames pdev to netdev
|
||||
# Deletes bridge
|
||||
#
|
||||
# status:
|
||||
# Print ifconfig for netdev and bridge.
|
||||
# Print routes.
|
||||
# Print addresses, interfaces, routes
|
||||
#
|
||||
#============================================================================
|
||||
|
||||
@@ -97,7 +106,7 @@ s/inet/ip addr add/
|
||||
s@\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+/[0-9]\+\)@\1@
|
||||
s/${src}/dev ${dst}/
|
||||
" | sh -e
|
||||
# Remove automatic routes on destionation device
|
||||
# Remove automatic routes on destination device
|
||||
ip route list | sed -ne "
|
||||
/dev ${dst}\( \|$\)/ {
|
||||
s/^/ip route del /
|
||||
@@ -105,17 +114,6 @@ s/${src}/dev ${dst}/
|
||||
}" | sh -e
|
||||
}
|
||||
|
||||
# Usage: del_addrs src
|
||||
del_addrs () {
|
||||
local src=$1
|
||||
ip addr show dev ${src} | egrep '^ *inet ' | sed -e "
|
||||
s/inet/ip addr del/
|
||||
s@\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\)/[0-9]\+@\1@
|
||||
s/${src}/dev ${src}/
|
||||
" | sh -e
|
||||
ip link set dev ${dst} up
|
||||
}
|
||||
|
||||
# Usage: transfer_routes src dst
|
||||
# Get all IP routes to device $src, delete them, and
|
||||
# add the same routes to device $dst.
|
||||
|
||||
@@ -35,7 +35,11 @@ vcpus=1
|
||||
|
||||
# Optionally define mac and/or bridge for the network interfaces.
|
||||
# Random MACs are assigned if not given.
|
||||
#vif = [ 'mac=aa:00:00:00:00:11, bridge=xenbr0' ]
|
||||
# nics default is 1
|
||||
#vif = [ 'type=ioemu, mac=aa:00:00:00:00:11, bridge=xenbr0' ]
|
||||
nics=1
|
||||
# type=ioemu specify the NIC is an ioemu device not netfront
|
||||
vif = [ 'type=ioemu, bridge=xenbr0' ]
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Define the disk devices you want the domain to have access to, and
|
||||
@@ -117,6 +121,11 @@ vncviewer=1
|
||||
#nographic=0
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# serial port re-direct to pty deivce, /dev/pts/n
|
||||
# then xm console or minicom can connect
|
||||
#serial='pty'
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# enable ne2000, default = 0(use pcnet)
|
||||
ne2000=0
|
||||
|
||||
@@ -7,7 +7,7 @@ INSTALL_DIR := $(DESTDIR)/usr/$(LIBDIR)/xen/bin
|
||||
TARGET_PATH=$(SRC_PATH)/target-$(TARGET_ARCH)
|
||||
VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw:$(SRC_PATH)/audio
|
||||
DEFINES=-I. -I$(TARGET_PATH) -I$(SRC_PATH)
|
||||
DEFINES+= -I$(XEN_ROOT)/tools/libxc
|
||||
DEFINES+= -I$(XEN_ROOT)/tools/libxc -I$(XEN_ROOT)/tools/xenstore
|
||||
ifdef CONFIG_USER_ONLY
|
||||
VPATH+=:$(SRC_PATH)/linux-user
|
||||
DEFINES+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ARCH)
|
||||
@@ -188,7 +188,7 @@ endif
|
||||
#########################################################
|
||||
|
||||
DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
|
||||
LIBS+=-lm -L../../libxc -lxenctrl -lxenguest
|
||||
LIBS+=-lm -L../../libxc -lxenctrl -lxenguest -L../../xenstore -lxenstore
|
||||
ifndef CONFIG_USER_ONLY
|
||||
LIBS+=-lz
|
||||
endif
|
||||
|
||||
@@ -7,4 +7,4 @@ echo 'config qemu network with xen bridge for '
|
||||
echo $*
|
||||
|
||||
ifconfig $1 0.0.0.0 up
|
||||
brctl addif xenbr0 $1
|
||||
brctl addif $2 $1
|
||||
+56
-2
@@ -76,6 +76,7 @@
|
||||
#endif /* CONFIG_SDL */
|
||||
|
||||
#include "xenctrl.h"
|
||||
#include "xs.h"
|
||||
#include "exec-all.h"
|
||||
|
||||
//#define DO_TB_FLUSH
|
||||
@@ -123,6 +124,7 @@ int domid = -1;
|
||||
static char network_script[1024];
|
||||
int pit_min_timer_count = 0;
|
||||
int nb_nics;
|
||||
char bridge[16];
|
||||
NetDriverState nd_table[MAX_NICS];
|
||||
QEMUTimer *gui_timer;
|
||||
QEMUTimer *polling_timer;
|
||||
@@ -1171,6 +1173,48 @@ CharDriverState *qemu_chr_open_stdio(void)
|
||||
return chr;
|
||||
}
|
||||
|
||||
int store_console_dev(int domid, char *pts)
|
||||
{
|
||||
int xc_handle;
|
||||
unsigned int len = 0;
|
||||
struct xs_handle *xs;
|
||||
char *path;
|
||||
|
||||
xs = xs_daemon_open();
|
||||
if (xs == NULL) {
|
||||
fprintf(logfile, "Could not contact XenStore\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
xc_handle = xc_interface_open();
|
||||
if (xc_handle == -1) {
|
||||
fprintf(logfile, "xc_interface_open() error\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
path = xs_get_domain_path(xs, domid);
|
||||
if (path == NULL) {
|
||||
fprintf(logfile, "xs_get_domain_path() error\n");
|
||||
return -1;
|
||||
}
|
||||
path = realloc(path, strlen(path) + strlen("/console/tty") + 1);
|
||||
if (path == NULL) {
|
||||
fprintf(logfile, "realloc error\n");
|
||||
return -1;
|
||||
}
|
||||
strcat(path, "/console/tty");
|
||||
if (!xs_write(xs, NULL, path, pts, strlen(pts))) {
|
||||
fprintf(logfile, "xs_write for console fail");
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(path);
|
||||
xs_daemon_close(xs);
|
||||
close(xc_handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(__linux__)
|
||||
CharDriverState *qemu_chr_open_pty(void)
|
||||
{
|
||||
@@ -1182,6 +1226,7 @@ CharDriverState *qemu_chr_open_pty(void)
|
||||
return NULL;
|
||||
}
|
||||
fprintf(stderr, "char device redirected to %s\n", slave_name);
|
||||
store_console_dev(domid, slave_name);
|
||||
return qemu_chr_open_fd(master_fd, master_fd);
|
||||
}
|
||||
#else
|
||||
@@ -1542,7 +1587,7 @@ static void tun_add_read_packet(NetDriverState *nd,
|
||||
static int net_tun_init(NetDriverState *nd)
|
||||
{
|
||||
int pid, status;
|
||||
char *args[3];
|
||||
char *args[4];
|
||||
char **parg;
|
||||
extern int highest_fds;
|
||||
|
||||
@@ -1558,6 +1603,7 @@ static int net_tun_init(NetDriverState *nd)
|
||||
parg = args;
|
||||
*parg++ = network_script;
|
||||
*parg++ = nd->ifname;
|
||||
*parg++ = bridge;
|
||||
*parg++ = NULL;
|
||||
execv(network_script, args);
|
||||
exit(1);
|
||||
@@ -2163,6 +2209,7 @@ void help(void)
|
||||
"Network options:\n"
|
||||
"-nics n simulate 'n' network cards [default=1]\n"
|
||||
"-macaddr addr set the mac address of the first interface\n"
|
||||
"-bridge br set the bridge interface for nic\n"
|
||||
"-n script set tap/tun network init script [default=%s]\n"
|
||||
"-tun-fd fd use this fd as already opened tap/tun interface\n"
|
||||
#ifdef CONFIG_SLIRP
|
||||
@@ -2253,6 +2300,7 @@ enum {
|
||||
|
||||
QEMU_OPTION_nics,
|
||||
QEMU_OPTION_macaddr,
|
||||
QEMU_OPTION_bridge,
|
||||
QEMU_OPTION_n,
|
||||
QEMU_OPTION_tun_fd,
|
||||
QEMU_OPTION_user_net,
|
||||
@@ -2323,6 +2371,7 @@ const QEMUOption qemu_options[] = {
|
||||
|
||||
{ "nics", HAS_ARG, QEMU_OPTION_nics},
|
||||
{ "macaddr", HAS_ARG, QEMU_OPTION_macaddr},
|
||||
{ "bridge", HAS_ARG, QEMU_OPTION_bridge},
|
||||
{ "n", HAS_ARG, QEMU_OPTION_n },
|
||||
{ "tun-fd", HAS_ARG, QEMU_OPTION_tun_fd },
|
||||
#ifdef CONFIG_SLIRP
|
||||
@@ -2701,7 +2750,9 @@ int main(int argc, char **argv)
|
||||
break;
|
||||
case QEMU_OPTION_nographic:
|
||||
pstrcpy(monitor_device, sizeof(monitor_device), "stdio");
|
||||
pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "stdio");
|
||||
if(!strcmp(serial_devices[0], "vc"))
|
||||
pstrcpy(serial_devices[0], sizeof(serial_devices[0]),
|
||||
"stdio");
|
||||
nographic = 1;
|
||||
break;
|
||||
#ifdef CONFIG_VNC
|
||||
@@ -2779,6 +2830,9 @@ int main(int argc, char **argv)
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case QEMU_OPTION_bridge:
|
||||
pstrcpy(bridge, sizeof(bridge), optarg);
|
||||
break;
|
||||
case QEMU_OPTION_macaddr:
|
||||
{
|
||||
const char *p;
|
||||
|
||||
@@ -102,6 +102,7 @@ install: build
|
||||
$(INSTALL_DATA) libxenguest.a $(DESTDIR)/usr/$(LIBDIR)
|
||||
ln -sf libxenguest.so.$(MAJOR).$(MINOR) $(DESTDIR)/usr/$(LIBDIR)/libxenguest.so.$(MAJOR)
|
||||
ln -sf libxenguest.so.$(MAJOR) $(DESTDIR)/usr/$(LIBDIR)/libxenguest.so
|
||||
$(INSTALL_DATA) xenguest.h $(DESTDIR)/usr/include
|
||||
|
||||
.PHONY: TAGS clean rpm install all
|
||||
|
||||
|
||||
@@ -565,8 +565,10 @@ static int setup_guest(int xc_handle,
|
||||
return 0;
|
||||
|
||||
error_out:
|
||||
free(mmu);
|
||||
free(page_array);
|
||||
if ( mmu != NULL )
|
||||
free(mmu);
|
||||
if ( page_array != NULL )
|
||||
free(page_array);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -627,7 +629,7 @@ int xc_vmx_build(int xc_handle,
|
||||
|
||||
if ( mlock(&st_ctxt, sizeof(st_ctxt) ) )
|
||||
{
|
||||
PERROR("xc_vmx_build: ctxt mlock failed");
|
||||
PERROR("%s: ctxt mlock failed", __func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -661,7 +663,8 @@ int xc_vmx_build(int xc_handle,
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
free(image);
|
||||
if ( image != NULL )
|
||||
free(image);
|
||||
|
||||
ctxt->flags = VGCF_VMX_GUEST;
|
||||
/* FPU is set up to default initial state. */
|
||||
@@ -707,7 +710,8 @@ int xc_vmx_build(int xc_handle,
|
||||
return rc;
|
||||
|
||||
error_out:
|
||||
free(image);
|
||||
if ( image != NULL )
|
||||
free(image);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ if os.path.exists("/usr/include/reiserfs/reiserfs.h"):
|
||||
fsys_mods.append(reiser)
|
||||
fsys_pkgs.append("grub.fsys.reiser")
|
||||
|
||||
pkgs = ['grub', 'grub.fsys']
|
||||
pkgs.extend(fsys_pkgs)
|
||||
setup(name='pygrub',
|
||||
version='0.3',
|
||||
description='Boot loader that looks a lot like grub for Xen',
|
||||
@@ -42,8 +44,7 @@ setup(name='pygrub',
|
||||
license='GPL',
|
||||
package_dir={'grub': 'src'},
|
||||
scripts = ["src/pygrub"],
|
||||
packages=['grub',
|
||||
'grub.fsys'].extend(fsys_pkgs),
|
||||
packages=pkgs,
|
||||
ext_modules = fsys_mods
|
||||
)
|
||||
|
||||
+11
-9
@@ -89,8 +89,8 @@ def get_active_offset(file):
|
||||
buf = os.read(fd, 512)
|
||||
for poff in (446, 462, 478, 494): # partition offsets
|
||||
# active partition has 0x80 as the first byte
|
||||
if struct.unpack("<c", buf[p:p+1]) == ('\x80',):
|
||||
return struct.unpack("<", buf[p+8:p+12])[0] * SECTOR_SIZE
|
||||
if struct.unpack("<c", buf[poff:poff+1]) == ('\x80',):
|
||||
return struct.unpack("<L", buf[poff+8:poff+12])[0] * SECTOR_SIZE
|
||||
return -1
|
||||
|
||||
def get_config(fn):
|
||||
@@ -113,11 +113,13 @@ def get_config(fn):
|
||||
break
|
||||
|
||||
if fs is not None:
|
||||
if fs.file_exist("/boot/grub/menu.lst"):
|
||||
grubfile = "/boot/grub/menu.lst"
|
||||
elif fs.file_exist("/boot/grub/grub.conf"):
|
||||
grubfile = "/boot/grub/grub.conf"
|
||||
else:
|
||||
grubfile = None
|
||||
for f in ("/boot/grub/menu.lst", "/boot/grub/grub.conf",
|
||||
"/grub/menu.lst", "/grub/grub.conf"):
|
||||
if fs.file_exist(f):
|
||||
grubfile = f
|
||||
break
|
||||
if grubfile is None:
|
||||
raise RuntimeError, "we couldn't find /boot/grub{menu.lst,grub.conf} " + \
|
||||
"in the image provided. halt!"
|
||||
f = fs.open_file(grubfile)
|
||||
@@ -169,7 +171,7 @@ def main(cf = None):
|
||||
# if c == ord('q'):
|
||||
# selected = -1
|
||||
# break
|
||||
elif c == ord('c'):
|
||||
if c == ord('c'):
|
||||
# FIXME: needs to go to command line mode
|
||||
continue
|
||||
elif c == ord('a'):
|
||||
@@ -261,7 +263,7 @@ if __name__ == "__main__":
|
||||
|
||||
offset = 0
|
||||
if is_disk_image(file):
|
||||
offset = get_active_offset(fn)
|
||||
offset = get_active_offset(file)
|
||||
if offset == -1:
|
||||
raise RuntimeError, "Unable to find active partition on disk"
|
||||
|
||||
|
||||
@@ -258,6 +258,7 @@ class VmxImageHandler(ImageHandler):
|
||||
log.debug("args: %s, val: %s" % (a,v))
|
||||
|
||||
# Handle disk/network related options
|
||||
mac = None
|
||||
for (name, info) in deviceConfig:
|
||||
if name == 'vbd':
|
||||
uname = sxp.child_value(info, 'uname')
|
||||
@@ -276,11 +277,21 @@ class VmxImageHandler(ImageHandler):
|
||||
ret.append("-%s" % vbddev)
|
||||
ret.append("%s" % vbdparam)
|
||||
if name == 'vif':
|
||||
type = sxp.child_value(info, 'type')
|
||||
if type != 'ioemu':
|
||||
continue
|
||||
if mac != None:
|
||||
continue
|
||||
mac = sxp.child_value(info, 'mac')
|
||||
bridge = sxp.child_value(info, 'bridge')
|
||||
if mac == None:
|
||||
mac = randomMAC()
|
||||
if bridge == None:
|
||||
bridge = 'xenbr0'
|
||||
ret.append("-macaddr")
|
||||
ret.append("%s" % mac)
|
||||
ret.append("-bridge")
|
||||
ret.append("%s" % bridge)
|
||||
if name == 'vtpm':
|
||||
instance = sxp.child_value(info, 'instance')
|
||||
ret.append("-instance")
|
||||
|
||||
@@ -71,6 +71,9 @@ class NetifController(DevController):
|
||||
script = os.path.join(xroot.network_script_dir,
|
||||
sxp.child_value(config, 'script',
|
||||
xroot.get_vif_script()))
|
||||
type = sxp.child_value(config, 'type')
|
||||
if type == 'ioemu':
|
||||
return (None,{},{})
|
||||
bridge = sxp.child_value(config, 'bridge')
|
||||
mac = sxp.child_value(config, 'mac')
|
||||
ipaddr = _get_config_ipaddr(config)
|
||||
|
||||
@@ -255,10 +255,11 @@ gopts.var('ipaddr', val="IPADDR",
|
||||
fn=append_value, default=[],
|
||||
use="Add an IP address to the domain.")
|
||||
|
||||
gopts.var('vif', val="mac=MAC,be_mac=MAC,bridge=BRIDGE,script=SCRIPT,backend=DOM,vifname=NAME",
|
||||
gopts.var('vif', val="type=TYPE,mac=MAC,be_mac=MAC,bridge=BRIDGE,script=SCRIPT,backend=DOM,vifname=NAME",
|
||||
fn=append_value, default=[],
|
||||
use="""Add a network interface with the given MAC address and bridge.
|
||||
The vif is configured by calling the given configuration script.
|
||||
If type is not specified, default is netfront not ioemu device.
|
||||
If mac is not specified a random MAC address is used.
|
||||
The MAC address of the backend interface can be selected with be_mac.
|
||||
If not specified then the network backend chooses it's own MAC address.
|
||||
@@ -356,10 +357,6 @@ gopts.var('cdrom', val='FILE',
|
||||
fn=set_value, default='',
|
||||
use="Path to cdrom")
|
||||
|
||||
gopts.var('macaddr', val='MACADDR',
|
||||
fn=set_value, default='',
|
||||
use="Macaddress of the first network interface")
|
||||
|
||||
gopts.var('boot', val="a|b|c|d",
|
||||
fn=set_value, default='c',
|
||||
use="Default boot device")
|
||||
@@ -512,6 +509,7 @@ def configure_vifs(config_devs, vals):
|
||||
backend = d.get('backend')
|
||||
ip = d.get('ip')
|
||||
vifname = d.get('vifname')
|
||||
type = d.get('type')
|
||||
else:
|
||||
mac = None
|
||||
be_mac = None
|
||||
@@ -520,6 +518,7 @@ def configure_vifs(config_devs, vals):
|
||||
backend = None
|
||||
ip = None
|
||||
vifname = None
|
||||
type = None
|
||||
config_vif = ['vif']
|
||||
if mac:
|
||||
config_vif.append(['mac', mac])
|
||||
@@ -535,6 +534,8 @@ def configure_vifs(config_devs, vals):
|
||||
config_vif.append(['backend', backend])
|
||||
if ip:
|
||||
config_vif.append(['ip', ip])
|
||||
if type:
|
||||
config_vif.append(['type', type])
|
||||
config_devs.append(['device', config_vif])
|
||||
|
||||
def configure_vfr(config, vals):
|
||||
@@ -549,7 +550,7 @@ def configure_vmx(config_image, vals):
|
||||
"""Create the config for VMX devices.
|
||||
"""
|
||||
args = [ 'device_model', 'vcpus', 'cdrom', 'boot', 'fda', 'fdb',
|
||||
'localtime', 'serial', 'macaddr', 'stdvga', 'isa', 'nographic',
|
||||
'localtime', 'serial', 'stdvga', 'isa', 'nographic',
|
||||
'vnc', 'vncviewer', 'sdl', 'display', 'ne2000', 'lapic']
|
||||
for a in args:
|
||||
if (vals.__dict__[a]):
|
||||
@@ -662,7 +663,7 @@ def preprocess_vifs(vals):
|
||||
(k, v) = b.strip().split('=', 1)
|
||||
k = k.strip()
|
||||
v = v.strip()
|
||||
if k not in ['mac', 'be_mac', 'bridge', 'script', 'backend', 'ip', 'vifname']:
|
||||
if k not in ['type', 'mac', 'be_mac', 'bridge', 'script', 'backend', 'ip', 'vifname']:
|
||||
err('Invalid vif specifier: ' + vif)
|
||||
d[k] = v
|
||||
vifs.append(d)
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ extern int eventchn_fd; /* in xenstored_domain.c */
|
||||
static bool verbose;
|
||||
LIST_HEAD(connections);
|
||||
static int tracefd = -1;
|
||||
static int reopen_log_pipe[2];
|
||||
static char *tracefile = NULL;
|
||||
static TDB_CONTEXT *tdb_ctx;
|
||||
|
||||
@@ -243,21 +244,35 @@ void trace(const char *fmt, ...)
|
||||
talloc_free(str);
|
||||
}
|
||||
|
||||
void reopen_log()
|
||||
{
|
||||
if (!tracefile)
|
||||
return;
|
||||
|
||||
if (tracefd > 0)
|
||||
close(tracefd);
|
||||
tracefd = open(tracefile, O_WRONLY|O_CREAT|O_APPEND, 0600);
|
||||
if (tracefd < 0) {
|
||||
perror("Could not open tracefile");
|
||||
return;
|
||||
}
|
||||
write(tracefd, "\n***\n", strlen("\n***\n"));
|
||||
/**
|
||||
* Signal handler for SIGHUP, which requests that the trace log is reopened
|
||||
* (in the main loop). A single byte is written to reopen_log_pipe, to awaken
|
||||
* the select() in the main loop.
|
||||
*/
|
||||
static void trigger_reopen_log(int signal __attribute__((unused)))
|
||||
{
|
||||
char c = 'A';
|
||||
write(reopen_log_pipe[1], &c, 1);
|
||||
}
|
||||
|
||||
|
||||
static void reopen_log()
|
||||
{
|
||||
if (tracefile) {
|
||||
if (tracefd > 0)
|
||||
close(tracefd);
|
||||
|
||||
tracefd = open(tracefile, O_WRONLY|O_CREAT|O_APPEND, 0600);
|
||||
|
||||
if (tracefd < 0)
|
||||
perror("Could not open tracefile");
|
||||
else
|
||||
write(tracefd, "\n***\n", strlen("\n***\n"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool write_messages(struct connection *conn)
|
||||
{
|
||||
int ret;
|
||||
@@ -331,29 +346,33 @@ static int destroy_conn(void *_conn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void set_fd(int fd, fd_set *set, int *max)
|
||||
{
|
||||
FD_SET(fd, set);
|
||||
if (fd > *max)
|
||||
*max = fd;
|
||||
}
|
||||
|
||||
|
||||
static int initialize_set(fd_set *inset, fd_set *outset, int sock, int ro_sock)
|
||||
{
|
||||
struct connection *i;
|
||||
int max;
|
||||
int max = -1;
|
||||
|
||||
FD_ZERO(inset);
|
||||
FD_ZERO(outset);
|
||||
FD_SET(sock, inset);
|
||||
max = sock;
|
||||
FD_SET(ro_sock, inset);
|
||||
if (ro_sock > max)
|
||||
max = ro_sock;
|
||||
FD_SET(eventchn_fd, inset);
|
||||
if (eventchn_fd > max)
|
||||
max = eventchn_fd;
|
||||
|
||||
set_fd(sock, inset, &max);
|
||||
set_fd(ro_sock, inset, &max);
|
||||
set_fd(eventchn_fd, inset, &max);
|
||||
set_fd(reopen_log_pipe[0], inset, &max);
|
||||
list_for_each_entry(i, &connections, list) {
|
||||
if (i->domain)
|
||||
continue;
|
||||
FD_SET(i->fd, inset);
|
||||
set_fd(i->fd, inset, &max);
|
||||
if (!list_empty(&i->out_list))
|
||||
FD_SET(i->fd, outset);
|
||||
if (i->fd > max)
|
||||
max = i->fd;
|
||||
}
|
||||
return max;
|
||||
}
|
||||
@@ -1570,6 +1589,10 @@ int main(int argc, char *argv[])
|
||||
|| listen(*ro_sock, 1) != 0)
|
||||
barf_perror("Could not listen on sockets");
|
||||
|
||||
if (pipe(reopen_log_pipe)) {
|
||||
barf_perror("pipe");
|
||||
}
|
||||
|
||||
/* Setup the database */
|
||||
setup_structure();
|
||||
|
||||
@@ -1592,7 +1615,7 @@ int main(int argc, char *argv[])
|
||||
close(STDERR_FILENO);
|
||||
}
|
||||
|
||||
signal(SIGHUP, reopen_log);
|
||||
signal(SIGHUP, trigger_reopen_log);
|
||||
|
||||
#ifdef TESTING
|
||||
signal(SIGUSR1, stop_failtest);
|
||||
@@ -1612,6 +1635,12 @@ int main(int argc, char *argv[])
|
||||
barf_perror("Select failed");
|
||||
}
|
||||
|
||||
if (FD_ISSET(reopen_log_pipe[0], &inset)) {
|
||||
char c;
|
||||
read(reopen_log_pipe[0], &c, 1);
|
||||
reopen_log();
|
||||
}
|
||||
|
||||
if (FD_ISSET(*sock, &inset))
|
||||
accept_connection(*sock, true);
|
||||
|
||||
|
||||
Regular → Executable
+64
-64
@@ -23,13 +23,13 @@
|
||||
a _very_ specific value, set in the PROMPT
|
||||
variable of this script
|
||||
"""
|
||||
import sys;
|
||||
import os;
|
||||
import pty;
|
||||
import tty;
|
||||
import termios;
|
||||
import fcntl;
|
||||
import select;
|
||||
import sys
|
||||
import os
|
||||
import pty
|
||||
import tty
|
||||
import termios
|
||||
import fcntl
|
||||
import select
|
||||
|
||||
from Test import *
|
||||
|
||||
@@ -52,15 +52,15 @@ class XmConsole:
|
||||
are included in the history buffer
|
||||
"""
|
||||
|
||||
self.TIMEOUT = 30;
|
||||
self.PROMPT = "@%@%> ";
|
||||
self.domain = domain;
|
||||
self.historyBuffer = [];
|
||||
self.historyLines = 0;
|
||||
self.historyLimit = historyLimit;
|
||||
self.historySaveAll = historySaveAll;
|
||||
self.historySaveCmds = historySaveCmds;
|
||||
self.debugMe = False;
|
||||
self.TIMEOUT = 30
|
||||
self.PROMPT = "@%@%> "
|
||||
self.domain = domain
|
||||
self.historyBuffer = []
|
||||
self.historyLines = 0
|
||||
self.historyLimit = historyLimit
|
||||
self.historySaveAll = historySaveAll
|
||||
self.historySaveCmds = historySaveCmds
|
||||
self.debugMe = False
|
||||
self.limit = None
|
||||
|
||||
consoleCmd = ["/usr/sbin/xm", "xm", "console", domain]
|
||||
@@ -68,62 +68,62 @@ class XmConsole:
|
||||
if verbose:
|
||||
print "Console executing: " + str(consoleCmd)
|
||||
|
||||
pid, fd = pty.fork();
|
||||
pid, fd = pty.fork()
|
||||
|
||||
if pid == 0:
|
||||
os.execvp("/usr/sbin/xm", consoleCmd[1:]);
|
||||
os.execvp("/usr/sbin/xm", consoleCmd[1:])
|
||||
|
||||
self.consolePid = pid;
|
||||
self.consoleFd = fd;
|
||||
self.consolePid = pid
|
||||
self.consoleFd = fd
|
||||
|
||||
tty.setraw(self.consoleFd, termios.TCSANOW);
|
||||
tty.setraw(self.consoleFd, termios.TCSANOW)
|
||||
|
||||
bytes = self.__chewall(self.consoleFd)
|
||||
if bytes < 0:
|
||||
raise ConsoleError("Console didn't respond")
|
||||
|
||||
def __addToHistory(self, line):
|
||||
self.historyBuffer.append(line);
|
||||
self.historyLines += 1;
|
||||
self.historyBuffer.append(line)
|
||||
self.historyLines += 1
|
||||
if self.historyLines > self.historyLimit:
|
||||
self.historyBuffer = self.historyBuffer[1:];
|
||||
self.historyLines -= 1;
|
||||
self.historyBuffer = self.historyBuffer[1:]
|
||||
self.historyLines -= 1
|
||||
|
||||
|
||||
def clearHistory(self):
|
||||
"""Clear the history buffer"""
|
||||
self.historyBuffer = [];
|
||||
self.historyLines = 0;
|
||||
self.historyBuffer = []
|
||||
self.historyLines = 0
|
||||
|
||||
|
||||
def getHistory(self):
|
||||
"""Returns a string containing the entire history buffer"""
|
||||
output = "";
|
||||
output = ""
|
||||
|
||||
for line in self.historyBuffer:
|
||||
output += line + "\n";
|
||||
output += line + "\n"
|
||||
|
||||
return output;
|
||||
return output
|
||||
|
||||
|
||||
def setTimeout(self, timeout):
|
||||
"""Sets the timeout used to determine if a remote command
|
||||
has blocked"""
|
||||
self.TIMEOUT = timeout;
|
||||
self.TIMEOUT = timeout
|
||||
|
||||
|
||||
def setPrompt(self, prompt):
|
||||
"""Sets the string key used to delimit the end of command
|
||||
output"""
|
||||
self.PROMPT = prompt;
|
||||
self.PROMPT = prompt
|
||||
|
||||
|
||||
def __chewall(self, fd):
|
||||
timeout = 0;
|
||||
bytes = 0;
|
||||
timeout = 0
|
||||
bytes = 0
|
||||
|
||||
while timeout < 3:
|
||||
i, o, e = select.select([fd], [], [], 1);
|
||||
i, o, e = select.select([fd], [], [], 1)
|
||||
if fd in i:
|
||||
try:
|
||||
foo = os.read(fd, 1)
|
||||
@@ -143,7 +143,7 @@ class XmConsole:
|
||||
if self.debugMe:
|
||||
print "Ignored %i bytes of miscellaneous console output" % bytes
|
||||
|
||||
return bytes;
|
||||
return bytes
|
||||
|
||||
|
||||
def __runCmd(self, command, saveHistory=True):
|
||||
@@ -152,15 +152,15 @@ class XmConsole:
|
||||
lines = 0
|
||||
bytes = 0
|
||||
|
||||
self.__chewall(self.consoleFd);
|
||||
self.__chewall(self.consoleFd)
|
||||
|
||||
if verbose:
|
||||
print "[%s] Sending `%s'" % (self.domain, command)
|
||||
|
||||
os.write(self.consoleFd, "%s\n" % command);
|
||||
os.write(self.consoleFd, "%s\n" % command)
|
||||
|
||||
while 1==1:
|
||||
i, o, e = select.select([self.consoleFd], [], [], self.TIMEOUT);
|
||||
i, o, e = select.select([self.consoleFd], [], [], self.TIMEOUT)
|
||||
|
||||
if self.consoleFd in i:
|
||||
try:
|
||||
@@ -182,59 +182,59 @@ class XmConsole:
|
||||
if lines > 0:
|
||||
output += line + "\n"
|
||||
if saveHistory:
|
||||
self.__addToHistory(line);
|
||||
self.__addToHistory(line)
|
||||
elif self.historySaveCmds and saveHistory:
|
||||
self.__addToHistory("*" + line);
|
||||
lines += 1;
|
||||
line = "";
|
||||
self.__addToHistory("*" + line)
|
||||
lines += 1
|
||||
line = ""
|
||||
elif str == "\r":
|
||||
pass # ignore \r's
|
||||
else:
|
||||
line += str;
|
||||
line += str
|
||||
|
||||
if line == self.PROMPT:
|
||||
break;
|
||||
break
|
||||
|
||||
return output;
|
||||
return output
|
||||
|
||||
|
||||
def runCmd(self, command):
|
||||
"""Runs a command on the remote terminal and returns the output
|
||||
as well as the return code. For example:
|
||||
|
||||
ret = c.runCmd("ls");
|
||||
print ret["output"];
|
||||
sys.exit(run["return"]);
|
||||
ret = c.runCmd("ls")
|
||||
print ret["output"]
|
||||
sys.exit(run["return"])
|
||||
|
||||
"""
|
||||
|
||||
# Allow exceptions to bubble up
|
||||
realOutput = self.__runCmd(command);
|
||||
retOutput = self.__runCmd("echo $?", saveHistory=False);
|
||||
realOutput = self.__runCmd(command)
|
||||
retOutput = self.__runCmd("echo $?", saveHistory=False)
|
||||
|
||||
try:
|
||||
retCode = int(retOutput);
|
||||
retCode = int(retOutput)
|
||||
except:
|
||||
retCode = 255;
|
||||
retCode = 255
|
||||
return {
|
||||
"output": realOutput,
|
||||
"return": retCode,
|
||||
};
|
||||
}
|
||||
|
||||
def sendInput(self, input):
|
||||
"""Sends input to the remote terminal, but doesn't check
|
||||
for a return code"""
|
||||
realOutput = self.__runCmd(input);
|
||||
realOutput = self.__runCmd(input)
|
||||
return {
|
||||
"output": realOutput,
|
||||
"return": 0,
|
||||
};
|
||||
}
|
||||
|
||||
def closeConsole(self):
|
||||
"""Closes the console connection and ensures that the console
|
||||
process is killed"""
|
||||
os.close(self.consoleFd);
|
||||
os.kill(self.consolePid, 2);
|
||||
os.close(self.consoleFd)
|
||||
os.kill(self.consolePid, 2)
|
||||
|
||||
|
||||
def setLimit(self, limit):
|
||||
@@ -254,23 +254,23 @@ if __name__ == "__main__":
|
||||
code as the domU command.
|
||||
"""
|
||||
|
||||
verbose = True;
|
||||
verbose = True
|
||||
|
||||
try:
|
||||
t = XmConsole(sys.argv[1]);
|
||||
t = XmConsole(sys.argv[1])
|
||||
except ConsoleError, e:
|
||||
print "Failed to attach to console (%s)" % str(e)
|
||||
sys.exit(255)
|
||||
|
||||
try:
|
||||
run = t.runCmd(sys.argv[2]);
|
||||
run = t.runCmd(sys.argv[2])
|
||||
except ConsoleError, e:
|
||||
print "Console failed (%)" % str(e)
|
||||
sys.exit(255)
|
||||
|
||||
t.closeConsole();
|
||||
t.closeConsole()
|
||||
|
||||
print run["output"],;
|
||||
sys.exit(run["return"]);
|
||||
print run["output"],
|
||||
sys.exit(run["return"])
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
XM_TEST_VERSION = "0.4.0"
|
||||
@@ -0,0 +1,25 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Dan Smith <danms@us.ibm.com> - 16-Sep-2005
|
||||
#
|
||||
# This script takes all the .report files in the current
|
||||
# directory and generates a summary table, showing the
|
||||
# number of PASS, FAIL, XPASS, and XFAIL tests in each
|
||||
# report
|
||||
|
||||
|
||||
echo " Platform | PASS | FAIL | XPASS | XFAIL |"
|
||||
echo "---------------------+------+------+-------+-------+"
|
||||
|
||||
for r in *.report; do
|
||||
|
||||
mach=$(basename $r .report)
|
||||
pass=$(cat $r | grep ' PASS' | cut -d : -f 2 | sed 's/ *//')
|
||||
fail=$(cat $r | grep ' FAIL' | cut -d : -f 2 | sed 's/ *//')
|
||||
xpas=$(cat $r | grep ' XPASS' | cut -d : -f 2 | sed 's/ *//')
|
||||
xfal=$(cat $r | grep ' XFAIL' | cut -d : -f 2 | sed 's/ *//')
|
||||
|
||||
printf "%20s | %4s | %4s | %5s | %5s |\n" "$mach" "$pass" \
|
||||
"$fail" "$xpas" "$xfal"
|
||||
|
||||
done
|
||||
Regular → Executable
+230
-186
@@ -1,215 +1,259 @@
|
||||
#!/bin/sh
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 [opts] <logfile>"
|
||||
echo " Where opts are:"
|
||||
echo " -d : do not submit a report for this run"
|
||||
echo " -b : do not ask any questions (batch mode)"
|
||||
echo " -e <email> : set email address for report"
|
||||
}
|
||||
##
|
||||
## Test driver script
|
||||
##
|
||||
|
||||
#
|
||||
# Defaults
|
||||
#
|
||||
MAXFAIL=10
|
||||
report=yes
|
||||
batch=no
|
||||
usage() {
|
||||
echo "Usage: $0 [opts] <report>"
|
||||
echo " Where report is a name that will be used for report files"
|
||||
echo ""
|
||||
echo " Where opts are:"
|
||||
echo " -d : do not submit a report for this run"
|
||||
echo " -b : do not ask any questions (batch mode)"
|
||||
echo " -q : run a quick test set"
|
||||
echo " -e <email> : set email address for report"
|
||||
echo " -s <report> : just submit report <report>"
|
||||
}
|
||||
|
||||
#
|
||||
# Resolve options
|
||||
#
|
||||
while [ $# -gt 0 ]
|
||||
do
|
||||
case "$1" in
|
||||
-d)
|
||||
echo "(Skipping report submission)"
|
||||
report=no
|
||||
;;
|
||||
-b)
|
||||
echo "(Batch mode)"
|
||||
batch=yes
|
||||
;;
|
||||
-e)
|
||||
shift
|
||||
echo $1 > contact_info
|
||||
echo "(Email set to $1)"
|
||||
;;
|
||||
*)
|
||||
LOGFILE=$1
|
||||
break
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
# Just submit the report
|
||||
submit_report() {
|
||||
|
||||
#
|
||||
# Usage
|
||||
#
|
||||
if [ -z $LOGFILE ]; then
|
||||
usage
|
||||
reportfile=$1
|
||||
|
||||
./lib/XmTestReport/Report.py $reportfile
|
||||
}
|
||||
|
||||
# Generate XML result report from output file
|
||||
make_result_report() {
|
||||
output=$1
|
||||
reportfile=$2
|
||||
if ! ./lib/XmTestReport/ResultReport.py $output > $reportfile; then
|
||||
echo "Unable to generate clean ResultReport"
|
||||
echo "Take a look at $report"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#
|
||||
# Output files
|
||||
#
|
||||
OSREPORTTEMP=${LOGFILE}.os.xml
|
||||
PROGREPORTTEMP=${LOGFILE}.prog.xml
|
||||
RESULTREPORTTEMP=${LOGFILE}.result.xml
|
||||
OUTPUT=${LOGFILE}.output
|
||||
SUMMARY=${LOGFILE}.summary
|
||||
PASSFAIL=${LOGFILE}.passfail
|
||||
REPORT=${LOGFILE}.report
|
||||
FAILURES=${LOGFILE}.failures
|
||||
|
||||
#
|
||||
# Make sure we're root
|
||||
#
|
||||
uid=$(id -u)
|
||||
if [ $uid != 0 ]; then
|
||||
echo "ERROR: I must be run as root!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#
|
||||
# See if the ramdisk has been built
|
||||
#
|
||||
rdsize=$(stat -c %s ramdisk/initrd.img 2>/dev/null)
|
||||
if [ -z "$rdsize" ] || [ $rdsize -le 16384 ]; then
|
||||
echo "Cannot find a valid ramdisk. You need to run \"make\" or"
|
||||
echo "copy in a previously-built ramdisk to the ramdisk/ directory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#
|
||||
# See if xend is running
|
||||
#
|
||||
if ! xm list >/dev/null 2>&1; then
|
||||
echo "'xm list' failed: is xend running?"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#
|
||||
# Make sure permissions are correct
|
||||
#
|
||||
chmod a+x lib/XmTestReport/*
|
||||
chmod a+x mkreport mergereport
|
||||
|
||||
#
|
||||
# Get contact info if needed
|
||||
#
|
||||
if [ ! -f contact_info ]; then
|
||||
if [ "$batch" = "yes" ]; then
|
||||
echo "Unable to read contact_info!"
|
||||
echo "Please run me once interactively before using batch mode!"
|
||||
exit 1
|
||||
else
|
||||
echo "Please provide your email address so that we can "
|
||||
echo "contact you if we need further information concerning"
|
||||
echo "your results. Any information provided will be"
|
||||
echo "kept private. If you wish to remain anonymous, please"
|
||||
echo "hit [ENTER] now."
|
||||
|
||||
while ! echo "$EMAIL" | grep -q '@'; do
|
||||
echo
|
||||
echo -n "Your email address: "
|
||||
read EMAIL
|
||||
if [ -z $EMAIL ]; then
|
||||
EMAIL="anonymous@somewhere.com"
|
||||
fi
|
||||
done
|
||||
echo $EMAIL > contact_info
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# Collect environment information for XML report
|
||||
#
|
||||
if ! ./lib/XmTestReport/OSReport.py > $OSREPORTTEMP; then
|
||||
echo "Unable to generate clean OSReport"
|
||||
echo "Take a look at $OSREPORTTEMP"
|
||||
exit 1
|
||||
fi
|
||||
if ! ./lib/XmTestReport/ProgReport.py > $PROGREPORTTEMP; then
|
||||
echo "Unable to generate clean ProgReport"
|
||||
echo "Take a look at $PROGREPORTTEMP"
|
||||
exit 1
|
||||
fi
|
||||
make_environment_report() {
|
||||
os=$1
|
||||
prog=$2
|
||||
if ! ./lib/XmTestReport/OSReport.py > $os; then
|
||||
echo "Unable to generate clean OSReport"
|
||||
echo "Take a look at $os"
|
||||
exit 1
|
||||
fi
|
||||
if ! ./lib/XmTestReport/ProgReport.py > $prog; then
|
||||
echo "Unable to generate clean ProgReport"
|
||||
echo "Take a look at $prog"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Check conditions needed to actually run the tests
|
||||
runnable_tests() {
|
||||
# Make sure we're root
|
||||
uid=$(id -u)
|
||||
if [ $uid != 0 ]; then
|
||||
echo "ERROR: I must be run as root!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# See if the ramdisk has been built
|
||||
rdsize=$(stat -c %s ramdisk/initrd.img 2>/dev/null)
|
||||
if [ -z "$rdsize" ] || [ $rdsize -le 16384 ]; then
|
||||
echo "Cannot find a valid ramdisk. You need to run \"make\" or"
|
||||
echo "copy in a previously-built ramdisk to the ramdisk/ directory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# See if xend is running
|
||||
if ! xm list >/dev/null 2>&1; then
|
||||
echo "'xm list' failed: is xend running?"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
# Get contact info if needed
|
||||
get_contact_info() {
|
||||
|
||||
if [ ! -f contact_info ]; then
|
||||
if [ "$batch" = "yes" ]; then
|
||||
echo "Unable to read contact_info!"
|
||||
echo "Please run me once interactively before using batch mode!"
|
||||
exit 1
|
||||
else
|
||||
echo "Please provide your email address so that we can "
|
||||
echo "contact you if we need further information concerning"
|
||||
echo "your results. Any information provided will be"
|
||||
echo "kept private. If you wish to remain anonymous, please"
|
||||
echo "hit [ENTER] now."
|
||||
|
||||
while ! echo "$EMAIL" | grep -q '@'; do
|
||||
echo
|
||||
echo -n "Your email address: "
|
||||
read EMAIL
|
||||
if [ -z $EMAIL ]; then
|
||||
EMAIL="anonymous@somewhere.com"
|
||||
fi
|
||||
done
|
||||
echo $EMAIL > contact_info
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# Run the tests
|
||||
#
|
||||
export TEST_VERBOSE=1
|
||||
echo Running tests...
|
||||
make -k check > $OUTPUT 2>&1
|
||||
run_tests() {
|
||||
output=$1
|
||||
echo Running tests...
|
||||
TEST_VERBOSE=1 make -k check > $output 2>&1
|
||||
}
|
||||
|
||||
run_tests_quick() {
|
||||
|
||||
output=$1
|
||||
|
||||
create_tests="01_create_basic_pos.test 07_create_mem64_pos.test 10_create_fastdestroy.test 14_create_blockroot_pos.test"
|
||||
unpause_tests="01_unpause_basic_pos.test"
|
||||
memset_tests="01_memset_basic_pos.test 03_memset_random_pos.test"
|
||||
help_tests="06_help_allcmds.test"
|
||||
testgroups="create unpause memset help"
|
||||
|
||||
echo "*** Quick test" > $output
|
||||
for group in $testgroups; do
|
||||
eval $(echo list=\$${group}_tests)
|
||||
echo "*** Running tests [$list] from $group"
|
||||
(cd tests/$group && TEST_VERBOSE=1 make -k check TESTS="$list") >> $output 2>&1
|
||||
done
|
||||
|
||||
}
|
||||
|
||||
#
|
||||
# Generate some plain-text reports
|
||||
#
|
||||
echo "Making PASS/FAIL report ($PASSFAIL)..."
|
||||
cat $OUTPUT | egrep '(REASON|PASS|FAIL|XPASS|XFAIL|SKIP)' | perl -pe 's/^(PASS|FAIL|XPASS|XFAIL)(.+)$/$1$2\n/' > $PASSFAIL
|
||||
|
||||
echo "Making FAIL report ($FAILURES)..."
|
||||
cat $PASSFAIL | egrep '(REASON|FAIL)' > $FAILURES
|
||||
|
||||
NUMPASS=`grep -c PASS $OUTPUT`
|
||||
NUMFAIL=`grep -c FAIL $OUTPUT`
|
||||
NUMXPASS=`grep -c XPASS $OUTPUT`
|
||||
NUMXFAIL=`grep -c XFAIL $OUTPUT`
|
||||
cat > $SUMMARY << EOF
|
||||
make_text_reports() {
|
||||
passfail=$1
|
||||
failures=$2
|
||||
output=$3
|
||||
reportfile=$4
|
||||
summary=summary.tmp
|
||||
echo "Making PASS/FAIL report ($passfail)..."
|
||||
cat $OUTPUT | egrep '(REASON|PASS|FAIL|XPASS|XFAIL|SKIP)' | perl -pe 's/^(PASS|FAIL|XPASS|XFAIL)(.+)$/$1$2\n/' > $passfail
|
||||
|
||||
echo "Making FAIL report ($failures)..."
|
||||
cat $passfail | egrep '(REASON|FAIL)' > $failures
|
||||
|
||||
NUMPASS=`grep -c PASS $output`
|
||||
NUMFAIL=`grep -c FAIL $output`
|
||||
NUMXPASS=`grep -c XPASS $output`
|
||||
NUMXFAIL=`grep -c XFAIL $output`
|
||||
cat > $summary << EOF
|
||||
Xm-test execution summary:
|
||||
PASS: $NUMPASS
|
||||
FAIL: $NUMFAIL
|
||||
XPASS: $NUMXPASS
|
||||
XFAIL: $NUMXFAIL
|
||||
EOF
|
||||
|
||||
cat $summary > $reportfile
|
||||
|
||||
echo -e '\n\nDetails:\n' >> $reportfile
|
||||
|
||||
./mkreport $passfail >> $reportfile
|
||||
|
||||
cat $SUMMARY > $REPORT
|
||||
rm $summary
|
||||
}
|
||||
|
||||
echo -e '\n\nDetails:\n' >> $REPORT
|
||||
|
||||
./mkreport $PASSFAIL >> $REPORT
|
||||
############
|
||||
### Main ###
|
||||
############
|
||||
|
||||
#
|
||||
# Check to see if it's worth reporting these results
|
||||
#
|
||||
#if [ "$batch" = "no" ] &&
|
||||
# [ "$report" = "yes" ] &&
|
||||
# [ $NUMFAIL -gt $MAXFAIL ]; then
|
||||
# echo "NOTE: $NUMFAIL tests failed, which may be erroneous. It may"
|
||||
# echo "be a good idea to review the report before sending. If you"
|
||||
# echo "choose not to submit the report, it will be saved for your review"
|
||||
# echo "and later submission."
|
||||
# echo
|
||||
# echo -n "Submit anyway? [y/n] "
|
||||
# read ANSWER
|
||||
# if [ "$ANSWER" = "n" ]; then
|
||||
# report=no
|
||||
# fi
|
||||
#fi
|
||||
# Defaults
|
||||
MAXFAIL=10
|
||||
report=yes
|
||||
batch=no
|
||||
run=yes
|
||||
|
||||
#
|
||||
# Generate the XML result report
|
||||
#
|
||||
if ! ./lib/XmTestReport/ResultReport.py $OUTPUT > $RESULTREPORTTEMP; then
|
||||
echo "Unable to generate clean ResultReport"
|
||||
echo "Take a look at $RESULTREPORTTEMP"
|
||||
exit 1
|
||||
# Resolve options
|
||||
while [ $# -gt 0 ]
|
||||
do
|
||||
case "$1" in
|
||||
-d)
|
||||
echo "(Skipping report submission)"
|
||||
report=no
|
||||
;;
|
||||
-b)
|
||||
echo "(Batch mode)"
|
||||
batch=yes
|
||||
;;
|
||||
-e)
|
||||
shift
|
||||
echo $1 > contact_info
|
||||
echo "(Email set to $1)"
|
||||
;;
|
||||
-q)
|
||||
run=quick
|
||||
;;
|
||||
-s)
|
||||
run=no
|
||||
;;
|
||||
*)
|
||||
REPORT=$1
|
||||
break
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# Usage
|
||||
if [ -z $REPORT ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#
|
||||
# Maybe submit report and save the combined XML file
|
||||
#
|
||||
if [ "$report" = "yes" ]; then
|
||||
echo "Sending report..."
|
||||
./lib/XmTestReport/Report.py -D $OSREPORTTEMP $PROGREPORTTEMP \
|
||||
$RESULTREPORTTEMP > $1.xml
|
||||
echo "Report also saved in $1.xml"
|
||||
else
|
||||
echo "Saving report to $1.xml..."
|
||||
./lib/XmTestReport/Report.py -d $OSREPORTTEMP $PROGREPORTTEMP \
|
||||
$RESULTREPORTTEMP > $1.xml
|
||||
# Output files
|
||||
OSREPORTTEMP=${REPORT}.os.xml
|
||||
PROGREPORTTEMP=${REPORT}.prog.xml
|
||||
RESULTREPORTTEMP=${REPORT}.result.xml
|
||||
XMLREPORT=${REPORT}.xml
|
||||
OUTPUT=${REPORT}.output
|
||||
SUMMARY=${REPORT}.summary
|
||||
PASSFAIL=${REPORT}.passfail
|
||||
TXTREPORT=${REPORT}.report
|
||||
FAILURES=${REPORT}.failures
|
||||
|
||||
# Make sure permissions are correct
|
||||
chmod a+x lib/XmTestReport/*
|
||||
chmod a+x mkreport mergereport
|
||||
|
||||
if [ ! -f contact_info ]; then
|
||||
if [ "$batch" = "yes" ]; then
|
||||
echo "Unable to read contact_info"
|
||||
echo "You must run me interactively once!"
|
||||
exit 1
|
||||
else
|
||||
get_contact_info
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$run" != "no" ]; then
|
||||
runnable_tests
|
||||
make_environment_report $OSREPORTTEMP $PROGREPORTTEMP
|
||||
if [ "$run" = "yes" ]; then
|
||||
run_tests $OUTPUT
|
||||
else
|
||||
run_tests_quick $OUTPUT
|
||||
fi
|
||||
make_text_reports $PASSFAIL $FAILURES $OUTPUT $TXTREPORT
|
||||
make_result_report $OUTPUT $RESULTREPORTTEMP
|
||||
cat $OSREPORTTEMP $PROGREPORTTEMP $RESULTREPORTTEMP > $XMLREPORT
|
||||
rm $OSREPORTTEMP $PROGREPORTTEMP $RESULTREPORTTEMP
|
||||
fi
|
||||
|
||||
if [ "$report" = "yes" ] && [ "$run" = "yes" ]; then
|
||||
if [ ! -f "$XMLREPORT" ]; then
|
||||
echo "No such file: $XMLREPORT"
|
||||
exit 1
|
||||
fi
|
||||
submit_report $XMLREPORT
|
||||
fi
|
||||
+3
-1
@@ -36,7 +36,9 @@ except ConsoleError, e:
|
||||
saveLog(console.getHistory())
|
||||
FAIL(str(e))
|
||||
|
||||
os.system("mkfs.ext2 -F /dev/ram1")
|
||||
s, o = traceCommand("mke2fs -q -F /dev/ram1")
|
||||
if s != 0:
|
||||
FAIL("mke2fs returned %i != 0" % s)
|
||||
|
||||
for i in range(10):
|
||||
status, output = traceCommand("xm block-attach %s phy:ram1 hda1 w" % domain.getName())
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
-- BEGIN XmTest Log @Fri Oct 28 13:00:55 PDT 2005
|
||||
*input
|
||||
|
||||
|
||||
BusyBox v1.01 (2005.10.27-17:34+0000) Built-in shell (ash)
|
||||
Enter 'help' for a list of built-in commands.
|
||||
|
||||
-sh: can't access tty; job control turned off
|
||||
*ls
|
||||
CVS etc linuxrc opt sbin var
|
||||
bin home lost+found proc tmp
|
||||
dev lib mnt root usr
|
||||
|
||||
-- END XmTest Log
|
||||
@@ -5,13 +5,20 @@
|
||||
|
||||
from XmTestLib import *
|
||||
|
||||
domain = XmTestDomain()
|
||||
import re
|
||||
|
||||
domain = XmTestDomain(extraOpts={"nics":2})
|
||||
|
||||
domain.configAddDisk("phy:/dev/ram0", "hda1", "w")
|
||||
domain.configAddDisk("phy:/dev/ram1", "hdb2", "w")
|
||||
|
||||
s, o = traceCommand("mkfs /dev/ram0")
|
||||
s, o = traceCommand("mke2fs -q /dev/ram0")
|
||||
if s != 0:
|
||||
FAIL("Unable to mkfs /dev/ram0 in dom0")
|
||||
FAIL("Unable to mke2fs /dev/ram0 in dom0")
|
||||
|
||||
s, o = traceCommand("mke2fs -q /dev/ram1")
|
||||
if s != 0:
|
||||
FAIL("Unable to mke2fs /dev/ram1 in dom0")
|
||||
|
||||
try:
|
||||
domain.start()
|
||||
@@ -22,13 +29,38 @@ try:
|
||||
console = XmConsole(domain.getName())
|
||||
console.sendInput("foo")
|
||||
|
||||
run = console.runCmd("mount /dev/hda1 /mnt")
|
||||
run = console.runCmd("mkdir /mnt/a /mnt/b")
|
||||
if run["return"] != 0:
|
||||
FAIL("Unable to mkdir /mnt/a /mnt/b")
|
||||
|
||||
run = console.runCmd("mount /dev/hda1 /mnt/a")
|
||||
if run["return"] != 0:
|
||||
FAIL("Unable to mount /dev/hda1")
|
||||
|
||||
run = console.runCmd("echo bar > /mnt/foo")
|
||||
run = console.runCmd("mount /dev/hdb2 /mnt/b")
|
||||
if run["return"] != 0:
|
||||
FAIL("Unable to write to block device!")
|
||||
FAIL("Unable to mount /dev/hdb2")
|
||||
|
||||
run = console.runCmd("echo hda1 > /mnt/a/foo")
|
||||
if run["return"] != 0:
|
||||
FAIL("Unable to write to block device hda1!")
|
||||
|
||||
run = console.runCmd("echo hdb2 > /mnt/b/foo")
|
||||
if run["return"] != 0:
|
||||
FAIL("Unable to write to block device hdb2!")
|
||||
|
||||
run = console.runCmd("ifconfig eth0 169.254.0.1 netmask 255.255.255.0")
|
||||
if run["return"] != 0:
|
||||
FAIL("Unable to configure DomU's eth0")
|
||||
|
||||
run = console.runCmd("ifconfig eth1 169.254.1.1 netmask 255.255.255.0")
|
||||
if run["return"] != 0:
|
||||
FAIL("Unable to configure DomU's eth1")
|
||||
|
||||
run = console.runCmd("ifconfig lo 127.0.0.1")
|
||||
if run["return"] != 0:
|
||||
FAIL("Unable to configure DomU's lo")
|
||||
|
||||
|
||||
except ConsoleError, e:
|
||||
FAIL(str(e))
|
||||
@@ -63,9 +95,31 @@ try:
|
||||
if run["return"] != 0:
|
||||
FAIL("ls failed on restored domain")
|
||||
|
||||
run = console.runCmd("cat /mnt/foo | grep bar")
|
||||
run = console.runCmd("cat /mnt/a/foo")
|
||||
if run["return"] != 0:
|
||||
FAIL("Unable to read from block device")
|
||||
FAIL("Unable to read from block device hda1")
|
||||
if not re.search("hda1", run["output"]):
|
||||
FAIL("Failed to read correct data from hda1")
|
||||
|
||||
run = console.runCmd("cat /mnt/b/foo")
|
||||
if run["return"] != 0:
|
||||
FAIL("Unable to read from block device hdb2")
|
||||
if not re.search("hdb2", run["output"]):
|
||||
FAIL("Failed to read correct data from hdb2")
|
||||
|
||||
run = console.runCmd("ifconfig")
|
||||
if not re.search("eth0", run["output"]):
|
||||
FAIL("DomU's eth0 disappeared")
|
||||
if not re.search("169.254.0.1", run["output"]):
|
||||
FAIL("DomU's eth0 lost its IP")
|
||||
if not re.search("eth1", run["output"]):
|
||||
FAIL("DomU's eth1 disappeared")
|
||||
if not re.search("169.254.1.1", run["output"]):
|
||||
FAIL("DomU's eth1 lost its IP")
|
||||
if not re.search("Loopback", run["output"]):
|
||||
FAIL("DomU's lo disappeared")
|
||||
if not re.search("127.0.0.1", run["output"]):
|
||||
FAIL("DomU's lo lost its IP")
|
||||
|
||||
except ConsoleError, e:
|
||||
FAIL(str(e))
|
||||
|
||||
@@ -158,6 +158,14 @@ static unsigned long vmx_vioapic_read(struct vcpu *v,
|
||||
return result;
|
||||
}
|
||||
|
||||
static void vmx_vioapic_update_imr(struct vmx_vioapic *s, int index)
|
||||
{
|
||||
if (s->redirtbl[index].RedirForm.mask)
|
||||
set_bit(index, &s->imr);
|
||||
else
|
||||
clear_bit(index, &s->imr);
|
||||
}
|
||||
|
||||
static void vmx_vioapic_write_indirect(struct vmx_vioapic *s,
|
||||
unsigned long addr,
|
||||
unsigned long length,
|
||||
@@ -200,6 +208,7 @@ static void vmx_vioapic_write_indirect(struct vmx_vioapic *s,
|
||||
redir_content = ((redir_content >> 32) << 32) |
|
||||
(val & 0xffffffff);
|
||||
s->redirtbl[redir_index].value = redir_content;
|
||||
vmx_vioapic_update_imr(s, redir_index);
|
||||
} else {
|
||||
printk("vmx_vioapic_write_indirect "
|
||||
"error register %x\n", s->ioregsel);
|
||||
@@ -264,8 +273,10 @@ static void vmx_vioapic_reset(vmx_vioapic_t *s)
|
||||
|
||||
memset(s, 0, sizeof(vmx_vioapic_t));
|
||||
|
||||
for (i = 0; i < IOAPIC_NUM_PINS; i++)
|
||||
for (i = 0; i < IOAPIC_NUM_PINS; i++) {
|
||||
s->redirtbl[i].RedirForm.mask = 0x1;
|
||||
vmx_vioapic_update_imr(s, i);
|
||||
}
|
||||
}
|
||||
|
||||
static void ioapic_update_config(vmx_vioapic_t *s,
|
||||
@@ -422,7 +433,13 @@ static void ioapic_deliver(vmx_vioapic_t *s, int irqno)
|
||||
|
||||
target = apic_round_robin(
|
||||
s->domain, dest_mode, vector, deliver_bitmask);
|
||||
ioapic_inj_irq(s, target, vector, trig_mode, delivery_mode);
|
||||
if (target)
|
||||
ioapic_inj_irq(s, target, vector, trig_mode, delivery_mode);
|
||||
else{
|
||||
VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic deliver "
|
||||
"null round robin mask %x vector %x delivery_mode %x\n",
|
||||
deliver_bitmask, vector, deliver_bitmask);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -457,7 +474,7 @@ static int ioapic_get_highest_irq(vmx_vioapic_t *s)
|
||||
|
||||
ASSERT(s);
|
||||
|
||||
irqs = s->irr & ~s->isr;
|
||||
irqs = s->irr & ~s->isr & ~s->imr;
|
||||
return __fls(irqs);
|
||||
}
|
||||
|
||||
@@ -471,7 +488,7 @@ static void service_ioapic(vmx_vioapic_t *s)
|
||||
VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "service_ioapic "
|
||||
"highest irqno %x\n", irqno);
|
||||
|
||||
if (!s->redirtbl[irqno].RedirForm.mask) {
|
||||
if (!test_bit(irqno, &s->imr)) {
|
||||
ioapic_deliver(s, irqno);
|
||||
}
|
||||
|
||||
@@ -490,7 +507,7 @@ void vmx_vioapic_do_irqs(struct domain *d, uint16_t irqs)
|
||||
if (!vmx_apic_support(d))
|
||||
return;
|
||||
|
||||
s->irr |= irqs;
|
||||
s->irr |= irqs & ~s->imr;
|
||||
service_ioapic(s);
|
||||
}
|
||||
|
||||
@@ -584,7 +601,9 @@ int vmx_vioapic_add_lapic(struct vlapic *vlapic, struct vcpu *v)
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
|
||||
s->lapic_info[s->lapic_count ++] = vlapic;
|
||||
/* update count later for race condition on interrupt */
|
||||
s->lapic_info[s->lapic_count] = vlapic;
|
||||
s->lapic_count ++;
|
||||
|
||||
return s->lapic_count;
|
||||
}
|
||||
|
||||
@@ -407,6 +407,7 @@ int arch_set_info_guest(
|
||||
/* VMX uses the initially provided page tables as the P2M map. */
|
||||
if ( !pagetable_get_paddr(d->arch.phys_table) )
|
||||
d->arch.phys_table = v->arch.guest_table;
|
||||
v->arch.guest_table = mk_pagetable(0);
|
||||
|
||||
/* Initialize monitor page table */
|
||||
v->arch.monitor_table = mk_pagetable(0);
|
||||
@@ -646,7 +647,7 @@ long do_switch_to_user(void)
|
||||
|
||||
regs->rip = stu.rip;
|
||||
regs->cs = stu.cs | 3; /* force guest privilege */
|
||||
regs->rflags = stu.rflags;
|
||||
regs->rflags = (stu.rflags & ~(EF_IOPL|EF_VM)) | EF_IE;
|
||||
regs->rsp = stu.rsp;
|
||||
regs->ss = stu.ss | 3; /* force guest privilege */
|
||||
|
||||
|
||||
@@ -430,6 +430,10 @@ void __init __start_xen(multiboot_info_t *mbi)
|
||||
/* Sanity check for unwanted bloat of dom0_op_t structure. */
|
||||
BUG_ON(sizeof(((dom0_op_t *)0)->u) != sizeof(((dom0_op_t *)0)->u.pad));
|
||||
|
||||
BUG_ON(sizeof(start_info_t) > PAGE_SIZE);
|
||||
BUG_ON(sizeof(shared_info_t) > PAGE_SIZE);
|
||||
BUG_ON(sizeof(vcpu_info_t) != (sizeof(unsigned long) * 4));
|
||||
|
||||
init_frametable();
|
||||
|
||||
end_boot_allocator();
|
||||
|
||||
+16
-19
@@ -997,7 +997,8 @@ int __shadow_mode_enable(struct domain *d, unsigned int mode)
|
||||
if ( new_modes & SHM_log_dirty )
|
||||
{
|
||||
ASSERT( !d->arch.shadow_dirty_bitmap );
|
||||
d->arch.shadow_dirty_bitmap_size = (d->max_pages + 63) & ~63;
|
||||
d->arch.shadow_dirty_bitmap_size =
|
||||
(d->shared_info->arch.max_pfn + 63) & ~63;
|
||||
d->arch.shadow_dirty_bitmap =
|
||||
xmalloc_array(unsigned long, d->arch.shadow_dirty_bitmap_size /
|
||||
(8 * sizeof(unsigned long)));
|
||||
@@ -1287,34 +1288,28 @@ static int shadow_mode_table_op(
|
||||
d->arch.shadow_dirty_net_count = 0;
|
||||
d->arch.shadow_dirty_block_count = 0;
|
||||
|
||||
if ( (d->max_pages > sc->pages) ||
|
||||
(sc->dirty_bitmap == NULL) ||
|
||||
if ( (sc->dirty_bitmap == NULL) ||
|
||||
(d->arch.shadow_dirty_bitmap == NULL) )
|
||||
{
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
sc->pages = d->max_pages;
|
||||
|
||||
if(sc->pages > d->arch.shadow_dirty_bitmap_size)
|
||||
sc->pages = d->arch.shadow_dirty_bitmap_size;
|
||||
|
||||
#define chunk (8*1024) /* Transfer and clear in 1kB chunks for L1 cache. */
|
||||
for ( i = 0; i < d->max_pages; i += chunk )
|
||||
for ( i = 0; i < sc->pages; i += chunk )
|
||||
{
|
||||
int bytes = ((((d->max_pages - i) > chunk) ?
|
||||
chunk : (d->max_pages - i)) + 7) / 8;
|
||||
int bytes = ((((sc->pages - i) > chunk) ?
|
||||
chunk : (sc->pages - i)) + 7) / 8;
|
||||
|
||||
if (copy_to_user(
|
||||
sc->dirty_bitmap + (i/(8*sizeof(unsigned long))),
|
||||
d->arch.shadow_dirty_bitmap +(i/(8*sizeof(unsigned long))),
|
||||
bytes))
|
||||
{
|
||||
// copy_to_user can fail when copying to guest app memory.
|
||||
// app should zero buffer after mallocing, and pin it
|
||||
rc = -EINVAL;
|
||||
memset(
|
||||
d->arch.shadow_dirty_bitmap +
|
||||
(i/(8*sizeof(unsigned long))),
|
||||
0, (d->max_pages/8) - (i/(8*sizeof(unsigned long))));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1331,17 +1326,19 @@ static int shadow_mode_table_op(
|
||||
sc->stats.dirty_net_count = d->arch.shadow_dirty_net_count;
|
||||
sc->stats.dirty_block_count = d->arch.shadow_dirty_block_count;
|
||||
|
||||
if ( (d->max_pages > sc->pages) ||
|
||||
(sc->dirty_bitmap == NULL) ||
|
||||
|
||||
if ( (sc->dirty_bitmap == NULL) ||
|
||||
(d->arch.shadow_dirty_bitmap == NULL) )
|
||||
{
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
sc->pages = d->max_pages;
|
||||
if (copy_to_user(
|
||||
sc->dirty_bitmap, d->arch.shadow_dirty_bitmap, (d->max_pages+7)/8))
|
||||
if(sc->pages > d->arch.shadow_dirty_bitmap_size)
|
||||
sc->pages = d->arch.shadow_dirty_bitmap_size;
|
||||
|
||||
if (copy_to_user(sc->dirty_bitmap,
|
||||
d->arch.shadow_dirty_bitmap, (sc->pages+7)/8))
|
||||
{
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
|
||||
@@ -1009,7 +1009,8 @@ int __shadow_mode_enable(struct domain *d, unsigned int mode)
|
||||
if ( new_modes & SHM_log_dirty )
|
||||
{
|
||||
ASSERT( !d->arch.shadow_dirty_bitmap );
|
||||
d->arch.shadow_dirty_bitmap_size = (d->max_pages + 63) & ~63;
|
||||
d->arch.shadow_dirty_bitmap_size =
|
||||
(d->shared_info->arch.max_pfn + 63) & ~63;
|
||||
d->arch.shadow_dirty_bitmap =
|
||||
xmalloc_array(unsigned long, d->arch.shadow_dirty_bitmap_size /
|
||||
(8 * sizeof(unsigned long)));
|
||||
@@ -1163,34 +1164,29 @@ static int shadow_mode_table_op(
|
||||
d->arch.shadow_dirty_net_count = 0;
|
||||
d->arch.shadow_dirty_block_count = 0;
|
||||
|
||||
if ( (d->max_pages > sc->pages) ||
|
||||
(sc->dirty_bitmap == NULL) ||
|
||||
|
||||
if ( (sc->dirty_bitmap == NULL) ||
|
||||
(d->arch.shadow_dirty_bitmap == NULL) )
|
||||
{
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
sc->pages = d->max_pages;
|
||||
|
||||
if(sc->pages > d->arch.shadow_dirty_bitmap_size)
|
||||
sc->pages = d->arch.shadow_dirty_bitmap_size;
|
||||
|
||||
#define chunk (8*1024) /* Transfer and clear in 1kB chunks for L1 cache. */
|
||||
for ( i = 0; i < d->max_pages; i += chunk )
|
||||
for ( i = 0; i < sc->pages; i += chunk )
|
||||
{
|
||||
int bytes = ((((d->max_pages - i) > chunk) ?
|
||||
chunk : (d->max_pages - i)) + 7) / 8;
|
||||
int bytes = ((((sc->pages - i) > chunk) ?
|
||||
chunk : (sc->pages - i)) + 7) / 8;
|
||||
|
||||
if (copy_to_user(
|
||||
sc->dirty_bitmap + (i/(8*sizeof(unsigned long))),
|
||||
d->arch.shadow_dirty_bitmap +(i/(8*sizeof(unsigned long))),
|
||||
bytes))
|
||||
{
|
||||
// copy_to_user can fail when copying to guest app memory.
|
||||
// app should zero buffer after mallocing, and pin it
|
||||
rc = -EINVAL;
|
||||
memset(
|
||||
d->arch.shadow_dirty_bitmap +
|
||||
(i/(8*sizeof(unsigned long))),
|
||||
0, (d->max_pages/8) - (i/(8*sizeof(unsigned long))));
|
||||
break;
|
||||
}
|
||||
memset(
|
||||
@@ -1206,17 +1202,18 @@ static int shadow_mode_table_op(
|
||||
sc->stats.dirty_net_count = d->arch.shadow_dirty_net_count;
|
||||
sc->stats.dirty_block_count = d->arch.shadow_dirty_block_count;
|
||||
|
||||
if ( (d->max_pages > sc->pages) ||
|
||||
(sc->dirty_bitmap == NULL) ||
|
||||
if ( (sc->dirty_bitmap == NULL) ||
|
||||
(d->arch.shadow_dirty_bitmap == NULL) )
|
||||
{
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
sc->pages = d->max_pages;
|
||||
if (copy_to_user(
|
||||
sc->dirty_bitmap, d->arch.shadow_dirty_bitmap, (d->max_pages+7)/8))
|
||||
if(sc->pages > d->arch.shadow_dirty_bitmap_size)
|
||||
sc->pages = d->arch.shadow_dirty_bitmap_size;
|
||||
|
||||
if (copy_to_user(sc->dirty_bitmap,
|
||||
d->arch.shadow_dirty_bitmap, (sc->pages+7)/8))
|
||||
{
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
|
||||
@@ -412,16 +412,16 @@ void propagate_page_fault(unsigned long addr, u16 error_code)
|
||||
struct vcpu *v = current;
|
||||
struct trap_bounce *tb = &v->arch.trap_bounce;
|
||||
|
||||
v->arch.guest_context.ctrlreg[2] = addr;
|
||||
v->vcpu_info->arch.cr2 = addr;
|
||||
|
||||
ti = &v->arch.guest_context.trap_ctxt[TRAP_page_fault];
|
||||
tb->flags = TBF_EXCEPTION | TBF_EXCEPTION_ERRCODE | TBF_EXCEPTION_CR2;
|
||||
tb->cr2 = addr;
|
||||
tb->flags = TBF_EXCEPTION | TBF_EXCEPTION_ERRCODE;
|
||||
tb->error_code = error_code;
|
||||
tb->cs = ti->cs;
|
||||
tb->eip = ti->address;
|
||||
if ( TI_GET_IF(ti) )
|
||||
tb->flags |= TBF_INTERRUPT;
|
||||
|
||||
v->arch.guest_context.ctrlreg[2] = addr;
|
||||
}
|
||||
|
||||
static int handle_perdomain_mapping_fault(
|
||||
@@ -931,6 +931,7 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
|
||||
|
||||
case 2: /* Write CR2 */
|
||||
v->arch.guest_context.ctrlreg[2] = *reg;
|
||||
v->vcpu_info->arch.cr2 = *reg;
|
||||
break;
|
||||
|
||||
case 3: /* Write CR3 */
|
||||
|
||||
+47
-5
@@ -459,14 +459,56 @@ static void vmx_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
|
||||
}
|
||||
break;
|
||||
|
||||
case INSTR_MOVZ:
|
||||
case INSTR_MOVZX:
|
||||
if (dst & REGISTER) {
|
||||
index = operand_index(dst);
|
||||
switch (size) {
|
||||
case BYTE: p->u.data = p->u.data & 0xFFULL; break;
|
||||
case WORD: p->u.data = p->u.data & 0xFFFFULL; break;
|
||||
case LONG: p->u.data = p->u.data & 0xFFFFFFFFULL; break;
|
||||
case BYTE:
|
||||
p->u.data &= 0xFFULL;
|
||||
break;
|
||||
|
||||
case WORD:
|
||||
p->u.data &= 0xFFFFULL;
|
||||
break;
|
||||
|
||||
case LONG:
|
||||
p->u.data &= 0xFFFFFFFFULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
printk("Impossible source operand size of movzx instr: %d\n", size);
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
index = operand_index(dst);
|
||||
set_reg_value(operand_size(dst), index, 0, regs, p->u.data);
|
||||
}
|
||||
break;
|
||||
|
||||
case INSTR_MOVSX:
|
||||
if (dst & REGISTER) {
|
||||
switch (size) {
|
||||
case BYTE:
|
||||
p->u.data &= 0xFFULL;
|
||||
if ( p->u.data & 0x80ULL )
|
||||
p->u.data |= 0xFFFFFFFFFFFFFF00ULL;
|
||||
break;
|
||||
|
||||
case WORD:
|
||||
p->u.data &= 0xFFFFULL;
|
||||
if ( p->u.data & 0x8000ULL )
|
||||
p->u.data |= 0xFFFFFFFFFFFF0000ULL;
|
||||
break;
|
||||
|
||||
case LONG:
|
||||
p->u.data &= 0xFFFFFFFFULL;
|
||||
if ( p->u.data & 0x80000000ULL )
|
||||
p->u.data |= 0xFFFFFFFF00000000ULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
printk("Impossible source operand size of movsx instr: %d\n", size);
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
index = operand_index(dst);
|
||||
set_reg_value(operand_size(dst), index, 0, regs, p->u.data);
|
||||
}
|
||||
break;
|
||||
|
||||
+29
-14
@@ -581,25 +581,39 @@ static int vmx_decode(int vm86, unsigned char *opcode, struct instruction *instr
|
||||
}
|
||||
|
||||
switch (*++opcode) {
|
||||
case 0xB6: /* movz m8, r16/r32 */
|
||||
instr->instr = INSTR_MOVZ;
|
||||
case 0xB6: /* movzx m8, r16/r32/r64 */
|
||||
instr->instr = INSTR_MOVZX;
|
||||
GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
|
||||
index = get_index(opcode + 1, rex);
|
||||
instr->operand[0] = mk_operand(BYTE, 0, 0, MEMORY);
|
||||
instr->operand[1] = mk_operand(instr->op_size, index, 0, REGISTER);
|
||||
return DECODE_success;
|
||||
|
||||
case 0xB7: /* movz m16/m32, r32/r64 */
|
||||
instr->instr = INSTR_MOVZ;
|
||||
case 0xB7: /* movzx m16/m32, r32/r64 */
|
||||
instr->instr = INSTR_MOVZX;
|
||||
GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
|
||||
index = get_index(opcode + 1, rex);
|
||||
if (rex & 0x8) {
|
||||
instr->op_size = LONG;
|
||||
instr->operand[1] = mk_operand(QUAD, index, 0, REGISTER);
|
||||
} else {
|
||||
instr->op_size = WORD;
|
||||
instr->operand[1] = mk_operand(LONG, index, 0, REGISTER);
|
||||
}
|
||||
instr->operand[0] = mk_operand(instr->op_size, 0, 0, MEMORY);
|
||||
if (rex & 0x8)
|
||||
instr->operand[0] = mk_operand(LONG, 0, 0, MEMORY);
|
||||
else
|
||||
instr->operand[0] = mk_operand(WORD, 0, 0, MEMORY);
|
||||
instr->operand[1] = mk_operand(instr->op_size, index, 0, REGISTER);
|
||||
return DECODE_success;
|
||||
|
||||
case 0xBE: /* movsx m8, r16/r32/r64 */
|
||||
instr->instr = INSTR_MOVSX;
|
||||
GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
|
||||
index = get_index(opcode + 1, rex);
|
||||
instr->operand[0] = mk_operand(BYTE, 0, 0, MEMORY);
|
||||
instr->operand[1] = mk_operand(instr->op_size, index, 0, REGISTER);
|
||||
return DECODE_success;
|
||||
|
||||
case 0xBF: /* movsx m16, r32/r64 */
|
||||
instr->instr = INSTR_MOVSX;
|
||||
GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
|
||||
index = get_index(opcode + 1, rex);
|
||||
instr->operand[0] = mk_operand(WORD, 0, 0, MEMORY);
|
||||
instr->operand[1] = mk_operand(instr->op_size, index, 0, REGISTER);
|
||||
return DECODE_success;
|
||||
|
||||
case 0xA3: /* bt r32, m32 */
|
||||
@@ -702,7 +716,7 @@ static void mmio_operands(int type, unsigned long gpa, struct instruction *inst,
|
||||
send_mmio_req(type, gpa, 1, inst->op_size, value, IOREQ_WRITE, 0);
|
||||
} else if (inst->operand[0] & MEMORY) { /* dest is register */
|
||||
/* send the request and wait for the value */
|
||||
if (inst->instr == INSTR_MOVZ)
|
||||
if ( (inst->instr == INSTR_MOVZX) || (inst->instr == INSTR_MOVSX) )
|
||||
send_mmio_req(type, gpa, 1, size_reg, 0, IOREQ_READ, 0);
|
||||
else
|
||||
send_mmio_req(type, gpa, 1, inst->op_size, 0, IOREQ_READ, 0);
|
||||
@@ -827,7 +841,8 @@ void handle_mmio(unsigned long va, unsigned long gpa)
|
||||
break;
|
||||
}
|
||||
|
||||
case INSTR_MOVZ:
|
||||
case INSTR_MOVZX:
|
||||
case INSTR_MOVSX:
|
||||
mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mmio_opp, regs);
|
||||
break;
|
||||
|
||||
|
||||
+43
-31
@@ -119,22 +119,35 @@ uint32_t vlapic_update_ppr(struct vlapic *vlapic)
|
||||
}
|
||||
|
||||
/* This only for fixed delivery mode */
|
||||
int vlapic_match_dest(struct vlapic *target, struct vlapic *source,
|
||||
int short_hand, int dest, int dest_mode,
|
||||
int delivery_mode)
|
||||
static int vlapic_match_dest(struct vcpu *v, struct vlapic *source,
|
||||
int short_hand, int dest, int dest_mode,
|
||||
int delivery_mode)
|
||||
{
|
||||
int result = 0;
|
||||
struct vlapic *target = VLAPIC(v);
|
||||
|
||||
VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_match_dest: "
|
||||
"target %p source %p dest %x dest_mode %x short_hand %x "
|
||||
"delivery_mode %x",
|
||||
target, source, dest, dest_mode, short_hand, delivery_mode);
|
||||
|
||||
if ( unlikely(!target) &&
|
||||
( (delivery_mode != VLAPIC_DELIV_MODE_INIT) &&
|
||||
(delivery_mode != VLAPIC_DELIV_MODE_STARTUP) &&
|
||||
(delivery_mode != VLAPIC_DELIV_MODE_NMI) )) {
|
||||
VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_match_dest "
|
||||
"uninitialized target v %p delivery_mode %x dest %x\n",
|
||||
v, delivery_mode, dest);
|
||||
return result;
|
||||
}
|
||||
|
||||
switch (short_hand) {
|
||||
case VLAPIC_NO_SHORTHAND:
|
||||
if (!dest_mode) { /* Physical */
|
||||
result = (target->id == dest);
|
||||
result = ((target ? target->id : v->vcpu_id ) == dest);
|
||||
} else { /* Logical */
|
||||
if (!target)
|
||||
break;
|
||||
if (((target->dest_format >> 28) & 0xf) == 0xf) { /* Flat mode */
|
||||
result = (target->logical_dest >> 24) & dest;
|
||||
} else {
|
||||
@@ -176,17 +189,18 @@ int vlapic_match_dest(struct vlapic *target, struct vlapic *source,
|
||||
* Add a pending IRQ into lapic.
|
||||
* Return 1 if successfully added and 0 if discarded.
|
||||
*/
|
||||
int vlapic_accept_irq(struct vlapic *vlapic, int delivery_mode,
|
||||
int vector, int level, int trig_mode)
|
||||
static int vlapic_accept_irq(struct vcpu *v, int delivery_mode,
|
||||
int vector, int level, int trig_mode)
|
||||
{
|
||||
int result = 1;
|
||||
int result = 0;
|
||||
struct vlapic *vlapic = VLAPIC(v);
|
||||
|
||||
switch (delivery_mode) {
|
||||
case VLAPIC_DELIV_MODE_FIXED:
|
||||
case VLAPIC_DELIV_MODE_LPRI:
|
||||
/* FIXME add logic for vcpu on reset */
|
||||
if (!vlapic->vcpu || !vlapic_enabled(vlapic))
|
||||
return 0;
|
||||
if (unlikely(!vlapic || !vlapic_enabled(vlapic)))
|
||||
return result;
|
||||
|
||||
if (test_and_set_bit(vector, &vlapic->irr[0])) {
|
||||
printk("<vlapic_accept_irq>"
|
||||
@@ -199,6 +213,7 @@ int vlapic_accept_irq(struct vlapic *vlapic, int delivery_mode,
|
||||
}
|
||||
}
|
||||
evtchn_set_pending(vlapic->vcpu, iopacket_port(vlapic->domain));
|
||||
result = 1;
|
||||
break;
|
||||
|
||||
case VLAPIC_DELIV_MODE_RESERVED:
|
||||
@@ -269,15 +284,12 @@ struct vlapic* apic_round_robin(struct domain *d,
|
||||
|
||||
old = next = d->arch.vmx_platform.round_info[vector];
|
||||
|
||||
next++;
|
||||
if (next == MAX_VIRT_CPUS || !d->vcpu[next])
|
||||
next = 0;
|
||||
|
||||
do {
|
||||
/* the vcpu array is arranged according to vcpu_id */
|
||||
if (test_bit(next, &bitmap)) {
|
||||
target = d->vcpu[next]->arch.arch_vmx.vlapic;
|
||||
if (!vlapic_enabled(target)) {
|
||||
|
||||
if (!target || !vlapic_enabled(target)) {
|
||||
printk("warning: targe round robin local apic disabled\n");
|
||||
/* XXX should we domain crash?? Or should we return NULL */
|
||||
}
|
||||
@@ -285,7 +297,9 @@ struct vlapic* apic_round_robin(struct domain *d,
|
||||
}
|
||||
|
||||
next ++;
|
||||
if (next == MAX_VIRT_CPUS || !d->vcpu[next])
|
||||
if (!d->vcpu[next] ||
|
||||
!test_bit(_VCPUF_initialised, &d->vcpu[next]->vcpu_flags) ||
|
||||
next == MAX_VIRT_CPUS)
|
||||
next = 0;
|
||||
}while(next != old);
|
||||
|
||||
@@ -319,7 +333,7 @@ int vlapic_check_vector(struct vlapic *vlapic,
|
||||
{
|
||||
if ((dm == VLAPIC_DELIV_MODE_FIXED) && (vector < 16)) {
|
||||
vlapic->err_status |= 0x40;
|
||||
vlapic_accept_irq(vlapic, VLAPIC_DELIV_MODE_FIXED,
|
||||
vlapic_accept_irq(vlapic->vcpu, VLAPIC_DELIV_MODE_FIXED,
|
||||
vlapic_lvt_vector(vlapic, VLAPIC_LVT_ERROR), 0, 0);
|
||||
printk("<vlapic_check_vector>: check fail\n");
|
||||
return 0;
|
||||
@@ -340,7 +354,6 @@ void vlapic_ipi(struct vlapic *vlapic)
|
||||
|
||||
struct vlapic *target;
|
||||
struct vcpu *v = NULL;
|
||||
int result = 0;
|
||||
uint32_t lpr_map;
|
||||
|
||||
VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_ipi: "
|
||||
@@ -352,32 +365,27 @@ void vlapic_ipi(struct vlapic *vlapic)
|
||||
delivery_mode, vector);
|
||||
|
||||
for_each_vcpu ( vlapic->domain, v ) {
|
||||
target = VLAPIC(v);
|
||||
if (vlapic_match_dest(target, vlapic, short_hand,
|
||||
if (vlapic_match_dest(v, vlapic, short_hand,
|
||||
dest, dest_mode, delivery_mode)) {
|
||||
if (delivery_mode == VLAPIC_DELIV_MODE_LPRI) {
|
||||
set_bit(v->vcpu_id, &lpr_map);
|
||||
}else
|
||||
result = vlapic_accept_irq(target, delivery_mode,
|
||||
vector, level, trig_mode);
|
||||
} else
|
||||
vlapic_accept_irq(v, delivery_mode,
|
||||
vector, level, trig_mode);
|
||||
}
|
||||
}
|
||||
|
||||
if (delivery_mode == VLAPIC_DELIV_MODE_LPRI) {
|
||||
extern struct vlapic*
|
||||
apic_round_robin(struct domain *d,
|
||||
uint8_t dest_mode, uint8_t vector, uint32_t bitmap);
|
||||
|
||||
v = vlapic->vcpu;
|
||||
target = apic_round_robin(v->domain, dest_mode, vector, lpr_map);
|
||||
|
||||
if (target)
|
||||
vlapic_accept_irq(target, delivery_mode,
|
||||
vector, level, trig_mode);
|
||||
vlapic_accept_irq(target->vcpu, delivery_mode,
|
||||
vector, level, trig_mode);
|
||||
}
|
||||
}
|
||||
|
||||
void vlapic_begin_timer(struct vlapic *vlapic)
|
||||
static void vlapic_begin_timer(struct vlapic *vlapic)
|
||||
{
|
||||
s_time_t cur = NOW(), offset;
|
||||
|
||||
@@ -559,7 +567,9 @@ static unsigned long vlapic_read(struct vcpu *v, unsigned long address,
|
||||
|
||||
if ( len != 4) {
|
||||
/* some bugs on kernel cause read this with byte*/
|
||||
printk("Local APIC read with len = %lx, should be 4 instead\n", len);
|
||||
VMX_DBG_LOG(DBG_LEVEL_VLAPIC,
|
||||
"Local APIC read with len = %lx, should be 4 instead\n",
|
||||
len);
|
||||
}
|
||||
|
||||
alignment = offset & 0x3;
|
||||
@@ -737,12 +747,13 @@ static void vlapic_write(struct vcpu *v, unsigned long address,
|
||||
vlapic->timer_current = val;
|
||||
vlapic->timer_current_update = NOW();
|
||||
|
||||
vlapic_begin_timer(vlapic);
|
||||
|
||||
VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "timer_init %x timer_current %x"
|
||||
"timer_current_update %08x%08x",
|
||||
vlapic->timer_initial, vlapic->timer_current,
|
||||
(uint32_t)(vlapic->timer_current_update >> 32),
|
||||
(uint32_t)vlapic->timer_current_update);
|
||||
vlapic_begin_timer(vlapic);
|
||||
break;
|
||||
|
||||
case APIC_TDCR:
|
||||
@@ -827,6 +838,7 @@ void vlapic_timer_fn(void *data)
|
||||
}
|
||||
else
|
||||
vlapic->intr_pending_count[vlapic_lvt_vector(vlapic, VLAPIC_LVT_TIMER)]++;
|
||||
evtchn_set_pending(vlapic->vcpu, iopacket_port(vlapic->domain));
|
||||
}
|
||||
|
||||
vlapic->timer_current_update = NOW();
|
||||
|
||||
@@ -332,7 +332,7 @@ static void vmx_do_launch(struct vcpu *v)
|
||||
error |= __vmwrite(GUEST_TR_BASE, 0);
|
||||
error |= __vmwrite(GUEST_TR_LIMIT, 0xff);
|
||||
|
||||
__vmwrite(GUEST_CR3, pagetable_get_paddr(v->arch.guest_table));
|
||||
__vmwrite(GUEST_CR3, pagetable_get_paddr(v->domain->arch.phys_table));
|
||||
__vmwrite(HOST_CR3, pagetable_get_paddr(v->arch.monitor_table));
|
||||
__vmwrite(HOST_RSP, (unsigned long)get_stack_bottom());
|
||||
|
||||
|
||||
@@ -75,7 +75,6 @@ void __dummy__(void)
|
||||
BLANK();
|
||||
|
||||
OFFSET(TRAPBOUNCE_error_code, struct trap_bounce, error_code);
|
||||
OFFSET(TRAPBOUNCE_cr2, struct trap_bounce, cr2);
|
||||
OFFSET(TRAPBOUNCE_flags, struct trap_bounce, flags);
|
||||
OFFSET(TRAPBOUNCE_cs, struct trap_bounce, cs);
|
||||
OFFSET(TRAPBOUNCE_eip, struct trap_bounce, eip);
|
||||
|
||||
+14
-15
@@ -156,7 +156,7 @@ ENTRY(vmx_asm_vmexit_handler)
|
||||
* By this time, all the setups in the VMCS must be complete.
|
||||
*/
|
||||
.if \launch
|
||||
/* VMLUANCH */
|
||||
/* VMLAUNCH */
|
||||
.byte 0x0f,0x01,0xc2
|
||||
pushf
|
||||
call vm_launch_fail
|
||||
@@ -394,37 +394,37 @@ FLT14: movl %eax,%gs:(%esi)
|
||||
shll $16,%eax # Bits 16-23: saved_upcall_mask
|
||||
movw UREGS_cs+4(%esp),%ax # Bits 0-15: CS
|
||||
FLT15: movl %eax,%gs:4(%esi)
|
||||
test $0x00FF0000,%eax # Bits 16-23: saved_upcall_mask
|
||||
setz %ch # %ch == !saved_upcall_mask
|
||||
movl UREGS_eflags+4(%esp),%eax
|
||||
andl $~X86_EFLAGS_IF,%eax
|
||||
shlb $1,%ch # Bit 9 (EFLAGS.IF)
|
||||
orb %ch,%ah # Fold EFLAGS.IF into %eax
|
||||
FLT16: movl %eax,%gs:8(%esi)
|
||||
test $TBF_EXCEPTION_ERRCODE,%cl
|
||||
jz 1f
|
||||
subl $4,%esi # push error_code onto guest frame
|
||||
movl TRAPBOUNCE_error_code(%edx),%eax
|
||||
FLT17: movl %eax,%gs:(%esi)
|
||||
testb $TBF_EXCEPTION_CR2,%cl
|
||||
jz 2f
|
||||
subl $4,%esi # push %cr2 onto guest frame
|
||||
movl TRAPBOUNCE_cr2(%edx),%eax
|
||||
FLT18: movl %eax,%gs:(%esi)
|
||||
1: testb $TBF_FAILSAFE,%cl
|
||||
jz 2f
|
||||
subl $16,%esi # add DS/ES/FS/GS to failsafe stack frame
|
||||
testl $X86_EFLAGS_VM,UREGS_eflags+4(%esp)
|
||||
jz nvm86_2
|
||||
xorl %eax,%eax # VM86: we write zero selector values
|
||||
FLT19: movl %eax,%gs:(%esi)
|
||||
FLT20: movl %eax,%gs:4(%esi)
|
||||
FLT21: movl %eax,%gs:8(%esi)
|
||||
FLT22: movl %eax,%gs:12(%esi)
|
||||
FLT18: movl %eax,%gs:(%esi)
|
||||
FLT19: movl %eax,%gs:4(%esi)
|
||||
FLT20: movl %eax,%gs:8(%esi)
|
||||
FLT21: movl %eax,%gs:12(%esi)
|
||||
jmp 2f
|
||||
nvm86_2:movl UREGS_ds+4(%esp),%eax # non-VM86: write real selector values
|
||||
FLT23: movl %eax,%gs:(%esi)
|
||||
FLT22: movl %eax,%gs:(%esi)
|
||||
movl UREGS_es+4(%esp),%eax
|
||||
FLT24: movl %eax,%gs:4(%esi)
|
||||
FLT23: movl %eax,%gs:4(%esi)
|
||||
movl UREGS_fs+4(%esp),%eax
|
||||
FLT25: movl %eax,%gs:8(%esi)
|
||||
FLT24: movl %eax,%gs:8(%esi)
|
||||
movl UREGS_gs+4(%esp),%eax
|
||||
FLT26: movl %eax,%gs:12(%esi)
|
||||
FLT25: movl %eax,%gs:12(%esi)
|
||||
2: testl $X86_EFLAGS_VM,UREGS_eflags+4(%esp)
|
||||
jz nvm86_3
|
||||
xorl %eax,%eax /* zero DS-GS, just as a real CPU would */
|
||||
@@ -456,7 +456,6 @@ nvm86_3:/* Rewrite our stack frame and return to ring 1. */
|
||||
.long FLT20,domain_crash_synchronous , FLT21,domain_crash_synchronous
|
||||
.long FLT22,domain_crash_synchronous , FLT23,domain_crash_synchronous
|
||||
.long FLT24,domain_crash_synchronous , FLT25,domain_crash_synchronous
|
||||
.long FLT26,domain_crash_synchronous
|
||||
.previous
|
||||
|
||||
ALIGN
|
||||
|
||||
@@ -75,7 +75,6 @@ void __dummy__(void)
|
||||
BLANK();
|
||||
|
||||
OFFSET(TRAPBOUNCE_error_code, struct trap_bounce, error_code);
|
||||
OFFSET(TRAPBOUNCE_cr2, struct trap_bounce, cr2);
|
||||
OFFSET(TRAPBOUNCE_flags, struct trap_bounce, flags);
|
||||
OFFSET(TRAPBOUNCE_cs, struct trap_bounce, cs);
|
||||
OFFSET(TRAPBOUNCE_eip, struct trap_bounce, eip);
|
||||
|
||||
+15
-15
@@ -352,8 +352,6 @@ create_bounce_frame:
|
||||
FLT2: movq %rax,32(%rsi) # SS
|
||||
movq UREGS_rsp+8(%rsp),%rax
|
||||
FLT3: movq %rax,24(%rsi) # RSP
|
||||
movq UREGS_eflags+8(%rsp),%rax
|
||||
FLT4: movq %rax,16(%rsi) # RFLAGS
|
||||
movq VCPU_vcpu_info(%rbx),%rax
|
||||
pushq VCPUINFO_upcall_mask(%rax)
|
||||
testb $TBF_INTERRUPT,%cl
|
||||
@@ -362,7 +360,15 @@ FLT4: movq %rax,16(%rsi) # RFLAGS
|
||||
popq %rax
|
||||
shlq $32,%rax # Bits 32-39: saved_upcall_mask
|
||||
movw UREGS_cs+8(%rsp),%ax # Bits 0-15: CS
|
||||
FLT5: movq %rax,8(%rsi) # CS/saved_upcall_mask
|
||||
FLT4: movq %rax,8(%rsi) # CS / saved_upcall_mask
|
||||
shrq $32,%rax
|
||||
testb $0xFF,%al # Bits 0-7: saved_upcall_mask
|
||||
setz %ch # %ch == !saved_upcall_mask
|
||||
movq UREGS_eflags+8(%rsp),%rax
|
||||
andq $~X86_EFLAGS_IF,%rax
|
||||
shlb $1,%ch # Bit 9 (EFLAGS.IF)
|
||||
orb %ch,%ah # Fold EFLAGS.IF into %eax
|
||||
FLT5: movq %rax,16(%rsi) # RFLAGS
|
||||
movq UREGS_rip+8(%rsp),%rax
|
||||
FLT6: movq %rax,(%rsi) # RIP
|
||||
testb $TBF_EXCEPTION_ERRCODE,%cl
|
||||
@@ -370,27 +376,22 @@ FLT6: movq %rax,(%rsi) # RIP
|
||||
subq $8,%rsi
|
||||
movl TRAPBOUNCE_error_code(%rdx),%eax
|
||||
FLT7: movq %rax,(%rsi) # ERROR CODE
|
||||
testb $TBF_EXCEPTION_CR2,%cl
|
||||
jz 2f
|
||||
subq $8,%rsi
|
||||
movq TRAPBOUNCE_cr2(%rdx),%rax
|
||||
FLT8: movq %rax,(%rsi) # CR2
|
||||
1: testb $TBF_FAILSAFE,%cl
|
||||
jz 2f
|
||||
subq $32,%rsi
|
||||
movl %gs,%eax
|
||||
FLT9: movq %rax,24(%rsi) # GS
|
||||
FLT8: movq %rax,24(%rsi) # GS
|
||||
movl %fs,%eax
|
||||
FLT10: movq %rax,16(%rsi) # FS
|
||||
FLT9: movq %rax,16(%rsi) # FS
|
||||
movl %es,%eax
|
||||
FLT11: movq %rax,8(%rsi) # ES
|
||||
FLT10: movq %rax,8(%rsi) # ES
|
||||
movl %ds,%eax
|
||||
FLT12: movq %rax,(%rsi) # DS
|
||||
FLT11: movq %rax,(%rsi) # DS
|
||||
2: subq $16,%rsi
|
||||
movq UREGS_r11+8(%rsp),%rax
|
||||
FLT13: movq %rax,8(%rsi) # R11
|
||||
FLT12: movq %rax,8(%rsi) # R11
|
||||
movq UREGS_rcx+8(%rsp),%rax
|
||||
FLT14: movq %rax,(%rsi) # RCX
|
||||
FLT13: movq %rax,(%rsi) # RCX
|
||||
/* Rewrite our stack frame and return to guest-OS mode. */
|
||||
/* IA32 Ref. Vol. 3: TF, VM, RF and NT flags are cleared on trap. */
|
||||
movl $TRAP_syscall,UREGS_entry_vector+8(%rsp)
|
||||
@@ -411,7 +412,6 @@ FLT14: movq %rax,(%rsi) # RCX
|
||||
.quad FLT8,domain_crash_synchronous , FLT9,domain_crash_synchronous
|
||||
.quad FLT10,domain_crash_synchronous , FLT11,domain_crash_synchronous
|
||||
.quad FLT12,domain_crash_synchronous , FLT13,domain_crash_synchronous
|
||||
.quad FLT14,domain_crash_synchronous
|
||||
.previous
|
||||
|
||||
ALIGN
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
struct trap_bounce {
|
||||
unsigned long error_code;
|
||||
unsigned long cr2;
|
||||
unsigned short flags; /* TBF_ */
|
||||
unsigned short cs;
|
||||
unsigned long eip;
|
||||
|
||||
@@ -121,7 +121,6 @@
|
||||
/* 'trap_bounce' flags values */
|
||||
#define TBF_EXCEPTION 1
|
||||
#define TBF_EXCEPTION_ERRCODE 2
|
||||
#define TBF_EXCEPTION_CR2 4
|
||||
#define TBF_INTERRUPT 8
|
||||
#define TBF_FAILSAFE 16
|
||||
|
||||
|
||||
@@ -55,17 +55,18 @@
|
||||
#define REPNZ 0x2
|
||||
#define OVERLAP 0x4
|
||||
|
||||
#define INSTR_PIO 1
|
||||
#define INSTR_OR 2
|
||||
#define INSTR_AND 3
|
||||
#define INSTR_XOR 4
|
||||
#define INSTR_CMP 5
|
||||
#define INSTR_MOV 6
|
||||
#define INSTR_MOVS 7
|
||||
#define INSTR_MOVZ 8
|
||||
#define INSTR_STOS 9
|
||||
#define INSTR_TEST 10
|
||||
#define INSTR_BT 11
|
||||
#define INSTR_PIO 1
|
||||
#define INSTR_OR 2
|
||||
#define INSTR_AND 3
|
||||
#define INSTR_XOR 4
|
||||
#define INSTR_CMP 5
|
||||
#define INSTR_MOV 6
|
||||
#define INSTR_MOVS 7
|
||||
#define INSTR_MOVZX 8
|
||||
#define INSTR_MOVSX 9
|
||||
#define INSTR_STOS 10
|
||||
#define INSTR_TEST 11
|
||||
#define INSTR_BT 12
|
||||
|
||||
struct instruction {
|
||||
__s8 instr; /* instruction type */
|
||||
|
||||
@@ -92,9 +92,10 @@ typedef union RedirStatus
|
||||
#define MAX_LAPIC_NUM 32
|
||||
|
||||
typedef struct vmx_vioapic {
|
||||
uint32_t ioregsel;
|
||||
uint32_t irr;
|
||||
uint32_t isr; /* This is used for level trigger */
|
||||
uint32_t imr;
|
||||
uint32_t ioregsel;
|
||||
uint32_t flags;
|
||||
uint32_t lapic_count;
|
||||
uint32_t id;
|
||||
|
||||
@@ -271,12 +271,10 @@ typedef struct {
|
||||
|
||||
typedef mapped_regs_t vpd_t;
|
||||
|
||||
#define __ARCH_HAS_VCPU_INFO
|
||||
|
||||
typedef struct {
|
||||
unsigned int flags;
|
||||
unsigned long start_info_pfn;
|
||||
} arch_shared_info_t; // DON'T PACK
|
||||
} arch_shared_info_t;
|
||||
|
||||
typedef struct vcpu_guest_context {
|
||||
#define VGCF_FPU_VALID (1<<0)
|
||||
|
||||
@@ -90,7 +90,7 @@ typedef struct cpu_user_regs {
|
||||
uint16_t cs;
|
||||
uint8_t saved_upcall_mask;
|
||||
uint8_t _pad0;
|
||||
uint32_t eflags;
|
||||
uint32_t eflags; /* eflags.IF == !saved_upcall_mask */
|
||||
uint32_t esp;
|
||||
uint16_t ss, _pad1;
|
||||
uint16_t es, _pad2;
|
||||
@@ -132,6 +132,11 @@ typedef struct arch_shared_info {
|
||||
unsigned long pfn_to_mfn_frame_list_list;
|
||||
} arch_shared_info_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned long cr2;
|
||||
unsigned long pad; /* sizeof(vcpu_info_t) == 16 */
|
||||
} arch_vcpu_info_t;
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -154,7 +154,7 @@ typedef struct cpu_user_regs {
|
||||
uint16_t cs, _pad0[1];
|
||||
uint8_t saved_upcall_mask;
|
||||
uint8_t _pad1[3];
|
||||
__DECL_REG(flags);
|
||||
__DECL_REG(flags); /* rflags.IF == !saved_upcall_mask */
|
||||
__DECL_REG(sp);
|
||||
uint16_t ss, _pad2[3];
|
||||
uint16_t es, _pad3[3];
|
||||
@@ -201,6 +201,11 @@ typedef struct arch_shared_info {
|
||||
unsigned long pfn_to_mfn_frame_list_list;
|
||||
} arch_shared_info_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned long cr2;
|
||||
unsigned long pad; /* sizeof(vcpu_info_t) == 32 */
|
||||
} arch_vcpu_info_t;
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* This makes sure that old versions of dom0 tools will stop working in a
|
||||
* well-defined way (rather than crashing the machine, for instance).
|
||||
*/
|
||||
#define DOM0_INTERFACE_VERSION 0xAAAA1011
|
||||
#define DOM0_INTERFACE_VERSION 0xAAAA1012
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
|
||||
@@ -299,9 +299,7 @@ typedef struct vcpu_info {
|
||||
uint8_t evtchn_upcall_pending;
|
||||
uint8_t evtchn_upcall_mask;
|
||||
unsigned long evtchn_pending_sel;
|
||||
#ifdef __ARCH_HAS_VCPU_INFO
|
||||
arch_vcpu_info_t arch;
|
||||
#endif
|
||||
} vcpu_info_t;
|
||||
|
||||
typedef struct vcpu_time_info {
|
||||
|
||||