Merge with xen-unstable-ia64.hg

This commit is contained in:
kaf24@firebug.cl.cam.ac.uk committed 2005-11-11 10:47:43 +01:00
commit 5aa99be215
67 files changed
+1177 -855

No files matched your search

+56 -52
View File
@@ -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 .
+69 -95
View File
@@ -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.
+39 -40
View File
@@ -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.
+85
View File
@@ -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}
+12 -9
View File
@@ -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 },
+16 -12
View File
@@ -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;
+20 -22
View File
@@ -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.
+10 -1
View File
@@ -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
+2 -2
View File
@@ -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
+1 -1
View File
@@ -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
View File
@@ -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;
+1
View File
@@ -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
+9 -5
View File
@@ -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;
}
+3 -2
View File
@@ -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
View File
@@ -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"
+11
View File
@@ -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")
+3
View File
@@ -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)
+8 -7
View File
@@ -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)
+2
View File
@@ -0,0 +1,2 @@
+54 -25
View File
@@ -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);
+64 -64
View File
@@ -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"])
-3
View File
@@ -1,3 +0,0 @@
#!/usr/bin/python
XM_TEST_VERSION = "0.4.0"
+25
View File
@@ -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
View File
@@ -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
@@ -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())
-14
View File
@@ -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))
+25 -6
View File
@@ -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;
}
+2 -1
View File
@@ -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 */
+4
View File
@@ -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
View File
@@ -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;
+16 -19
View File
@@ -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;
+5 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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();
+1 -1
View File
@@ -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());
-1
View File
@@ -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
View File
@@ -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
-1
View File
@@ -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
View File
@@ -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
-1
View File
@@ -8,7 +8,6 @@
struct trap_bounce {
unsigned long error_code;
unsigned long cr2;
unsigned short flags; /* TBF_ */
unsigned short cs;
unsigned long eip;
-1
View File
@@ -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
+12 -11
View File
@@ -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 */
+2 -1
View File
@@ -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;
+1 -3
View File
@@ -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)
+6 -1
View File
@@ -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
+6 -1
View File
@@ -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
+1 -1
View File
@@ -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
/************************************************************************/
-2
View File
@@ -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 {
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.