merge with xen-unstable.hg

This commit is contained in:
awilliam@xenbuild.aw committed 2006-07-05 20:11:37 -06:00
commit 989c3fcf11
126 files changed
+6044 -1130

No files matched your search

+1
View File
@@ -130,6 +130,7 @@ distclean:
rm -rf dist patches/tmp
for i in $(ALLKERNELS) ; do $(MAKE) $$i-delete ; done
for i in $(ALLSPARSETREES) ; do $(MAKE) $$i-mrproper ; done
rm -rf patches/*/.makedep
# Linux name for GNU distclean
.PHONY: mrproper
+2 -5
View File
@@ -59,10 +59,6 @@ ifneq ($(PATCHDIRS),)
$(patsubst patches/%,patches/%/.makedep,$(PATCHDIRS)): patches/%/.makedep:
@echo 'ref-$*/.valid-ref: $$(wildcard patches/$*/*.patch)' >$@
.PHONY: clean
clean::
rm -f patches/*/.makedep
ref-%/.valid-ref: pristine-%/.valid-pristine
set -e
rm -rf $(@D)
@@ -111,7 +107,8 @@ linux-2.6-xen.patch: ref-linux-$(LINUX_VER)/.valid-ref
rm -rf tmp-$@
%-mrproper:
rm -rf pristine-$(*)* ref-$(*)* $*.tar.bz2
$(MAKE) -f buildconfigs/mk.$*-xen mrpropper
rm -rf pristine-$(*)* ref-$(*)*
rm -rf $*-xen.patch
.PHONY: config-update-pae
+1
View File
@@ -1902,6 +1902,7 @@ CONFIG_HANGCHECK_TIMER=m
# TPM devices
#
CONFIG_TCG_TPM=m
CONFIG_TCG_TIS=m
CONFIG_TCG_NSC=m
CONFIG_TCG_ATMEL=m
CONFIG_TCG_INFINEON=m
+1
View File
@@ -1765,6 +1765,7 @@ CONFIG_HANGCHECK_TIMER=m
# TPM devices
#
CONFIG_TCG_TPM=m
CONFIG_TCG_TIS=m
CONFIG_TCG_NSC=m
CONFIG_TCG_ATMEL=m
CONFIG_TCG_INFINEON=m
+7 -1
View File
@@ -47,8 +47,14 @@ config: $(LINUX_DIR)/include/linux/autoconf.h
.PHONY: clean
clean::
$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) clean
[ ! -d $(LINUX_DIR) ] || \
$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) clean
.PHONY: delete
delete:
rm -rf tmp-linux-$(LINUX_VER) $(LINUX_DIR)
.PHONY: mrpropper
mrpropper:
rm -f linux-$(LINUX_VER).tar.bz2
+85 -8
View File
@@ -875,14 +875,43 @@ defined in the I<policy>. Unless specified, the default I<policy> is
the currently enforced access control policy. The default for I<type>
is 'dom'. The labels are arranged in alphabetical order.
=item B<addlabel> I<configfile> I<label> [I<policy>]
=item B<addlabel> I<label> dom I<configfile> [I<policy>]
=item B<addlabel> I<label> res I<resource> [I<policy>]
Adds the security label with name I<label> to a domain
I<configfile>. Unless specified, the default I<policy> is the
I<configfile> (dom) or to the global resource label file for the
given I<resource> (res). Unless specified, the default I<policy> is the
currently enforced access control policy. This subcommand also
verifies that the I<policy> definition supports the specified I<label>
name.
=item B<rmlabel> dom I<configfile>
=item B<rmlabel> res I<resource>
Works the same as the I<addlabel> command (above), except that this
command will remove the label from the domain I<configfile> (dom) or
the global resource label file (res).
=item B<getlabel> dom I<configfile>
=item B<getlabel> res I<resource>
Shows the label for the given I<configfile> or I<resource>
=item B<resources>
Lists all resources in the global resource label file. Each resource
is listed with its associated label and policy name.
=item B<dry-run> I<configfile>
Determines if the specified I<configfile> describes a domain with a valid
security configuration for type enforcement. The test shows the policy
decision made for each resource label against the domain label as well as
the overall decision.
B<CONFIGURING SECURITY>
=over 4
@@ -960,17 +989,18 @@ B<ATTACHING A SECURITY LABEL TO A DOMAIN>
=over 4
This subcommand attaches a security label to a domain configuration
file, here a HomeBanking label. The example policy ensures that this
domain does not share information with other non-hombanking user
domains (i.e., domains labeled as dom_Fun or dom_Boinc) and that it
will not run simultaneously with domains labeled as dom_Fun.
The I<addlabel> subcommand can attach a security label to a domain
configuration file, here a HomeBanking label. The example policy
ensures that this domain does not share information with other
non-hombanking user domains (i.e., domains labeled as dom_Fun or
dom_Boinc) and that it will not run simultaneously with domains
labeled as dom_Fun.
We assume that the specified myconfig.xm configuration file actually
instantiates a domain that runs workloads related to home-banking,
probably just a browser environment for online-banking.
xm addlabel myconfig.xm dom_HomeBanking
xm addlabel dom_HomeBanking dom myconfig.xm
The very simple configuration file might now look as printed
below. The I<addlabel> subcommand added the B<access_control> entry at
@@ -997,6 +1027,38 @@ permitted".
=back
B<ATTACHING A SECURITY LABEL TO A RESOURCE>
=over 4
The I<addlabel> subcommand can also be used to attach a security
label to a resource. Following the home banking example from above,
we can label a disk resource (e.g., a physical partition or a file)
to make it accessible to the home banking domain. The example policy
provides a resource label, res_LogicalDiskPartition1(hda1), that is
compatible with the HomeBanking domain label.
xm addlabel "res_LogicalDiskPartition1(hda1)" res phy:hda6
After labeling this disk resource, it can be attached to the domain
by adding a line to the domain configuration file. The line below
attaches this disk to the domain at boot time.
disk = [ 'phy:hda6,sda2,w' ]
Alternatively, the resource can be attached after booting the domain
by using the I<block-attach> subcommand.
xm block-attach homebanking phy:hda6 sda2 w
Note that labeled resources cannot be used when security is turned
off. Any attempt to use labeled resources with security turned off
will result in a failure with a corresponding error message. The
solution is to enable security or, if security is no longer desired,
to remove the resource label using the I<rmlabel> subcommand.
=back
B<STARTING AND LISTING LABELED DOMAINS>
=over 4
@@ -1011,6 +1073,21 @@ B<STARTING AND LISTING LABELED DOMAINS>
=back
B<LISTING LABELED RESOURCES>
=over 4
xm resources
phy:hda6
policy: example.chwall_ste.client_v1
label: res_LogicalDiskPartition1(hda1)
file:/xen/disk_image/disk.img
policy: example.chwall_ste.client_v1
label: res_LogicalDiskPartition2(hda2)
=back
B<POLICY REPRESENTATIONS>
=over 4
+33 -13
View File
@@ -1,5 +1,5 @@
Copyright: IBM Corporation (C), Intel Corporation
17 August 2005
29 June 2006
Authors: Stefan Berger <stefanb@us.ibm.com> (IBM),
Employees of Intel Corp
@@ -9,24 +9,34 @@ instance and doing a short test to verify success. It is assumed
that the user is fairly familiar with compiling and installing XEN
and Linux on a machine.
Production Prerequisites: An x86-based machine machine with an ATMEL or
National Semiconductor (NSC) TPM on the motherboard.
Production Prerequisites: An x86-based machine machine with a
Linux-supported TPM on the motherboard (NSC, Atmel, Infineon, TPM V1.2).
Development Prerequisites: An emulator for TESTING ONLY is provided
Compiling XEN tree:
-------------------
Compiling the XEN tree:
-----------------------
Compile the XEN tree as usual after the following lines set in the
linux-2.6.??-xen/.config file:
CONFIG_XEN_TPMDEV_BACKEND=y
CONFIG_XEN_TPMDEV_BACKEND=m
CONFIG_TCG_TPM=y
CONFIG_TCG_TPM=m
CONFIG_TCG_TIS=m (supported after 2.6.17-rc4)
CONFIG_TCG_NSC=m
CONFIG_TCG_ATMEL=m
CONFIG_TCG_INFINEON=m
CONFIG_TCG_XEN=m
<possible other TPM drivers supported by Linux>
If the frontend driver needs to be compiled into the user domain
kernel, then the following two lines should be changed.
CONFIG_TCG_TPM=y
CONFIG_TCG_XEN=y
You must also enable the virtual TPM to be built:
In Config.mk in the Xen root directory set the line
@@ -63,7 +73,7 @@ an example of how a user domain can be configured to have a TPM
available. It works similar to making a network interface
available to a domain.
kernel = "/boot/vmlinuz-2.6.12-xenU"
kernel = "/boot/vmlinuz-2.6.x"
ramdisk = "/xen/initrd_domU/U1_ramdisk.img"
memory = 32
name = "TPMUserDomain0"
@@ -92,7 +102,7 @@ leave out the 'vtpm' line in the configuration file.
Running the TPM:
----------------
To run the vTPM, dev device /dev/vtpm must be available.
To run the vTPM, the device /dev/vtpm must be available.
Verify that 'ls -l /dev/vtpm' shows the following output:
crw------- 1 root root 10, 225 Aug 11 06:58 /dev/vtpm
@@ -101,16 +111,26 @@ If it is not available, run the following command as 'root'.
mknod /dev/vtpm c 10 225
Make sure that the vTPM is running in domain 0. To do this run the
following
following:
modprobe tpmbk
/usr/bin/vtpm_managerd
Start a user domain using the 'xm create' command. Once you are in the
shell of the user domain, you should be able to do the following:
shell of the user domain, you should be able to do the following as
user 'root':
> cd /sys/devices/vtpm
Insert the TPM frontend into the kernel if it has been compiled as a
kernel module.
> modprobe tpm_xenu
Check the status of the TPM
> cd /sys/devices/xen/vtpm-0
> ls
cancel caps pcrs pubek
[...] cancel caps pcrs pubek [...]
> cat pcrs
PCR-00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
PCR-01: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+477 -21
View File
@@ -2203,6 +2203,33 @@ ne2000 & Enable ne2000, default = 0 (disabled; use pcnet)\\
serial & Enable redirection of VMX serial output to pty device\\
\end{tabular}
\begin{tabular}{lp{10cm}}
usb & Enable USB support without defining a specific USB device.
This option defaults to 0 (disabled) unless the option usbdevice is
specified in which case this option then defaults to 1 (enabled).\\
usbdevice & Enable USB support and also enable support for the given
device. Devices that can be specified are {\small {\tt mouse}} (a PS/2 style
mouse), {\small {\tt tablet}} (an absolute pointing device) and
{\small {\tt host:id1:id2}} (a physical USB device on the host machine whose
ids are {\small {\tt id1}} and {\small {\tt id2}}). The advantage
of {\small {\tt tablet}} is that Windows guests will automatically recognize
and support this device so specifying the config line
{\small
\begin{verbatim}
usbdevice='tablet'
\end{verbatim}
}
will create a mouse that works transparently with Windows guests under VNC.
Linux doesn't recognize the USB tablet yet so Linux guests under VNC will
still need the Summagraphics emulation.
Details about mouse emulation are provided in section \textbf{A.4.3}.\\
localtime & Set the real time clock to local time [default=0, that is, set to UTC].\\
enable-audio & Enable audio support. This is under development.\\
@@ -2317,29 +2344,458 @@ Simply follow the usual method of creating the guest, using the -f parameter and
In the default configuration, VNC is on and SDL is off. Therefore VNC windows will open when VMX guests are created. If you want to use SDL to create VMX guests, set {\small {\tt sdl=1}} in your VMX configuration file. You can also turn off VNC by setting {\small {\tt vnc=0}}.
\subsection{Use mouse in VNC window}
The default PS/2 mouse will not work properly in VMX by a VNC window. Summagraphics mouse emulation does work in this environment. A Summagraphics mouse can be enabled by reconfiguring 2 services:
\subsection{Mouse issues, especially under VNC}
Mouse handling when using VNC is a little problematic.
The problem is that the VNC viewer provides a virtual pointer which is
located at an absolute location in the VNC window and only absolute
coordinates are provided.
The VMX device model converts these absolute mouse coordinates
into the relative motion deltas that are expected by the PS/2
mouse driver running in the guest.
Unfortunately,
it is impossible to keep these generated mouse deltas
accurate enough for the guest cursor to exactly match
the VNC pointer.
This can lead to situations where the guest's cursor
is in the center of the screen and there's no way to
move that cursor to the left
(it can happen that the VNC pointer is at the left
edge of the screen and,
therefore,
there are no longer any left mouse deltas that
can be provided by the device model emulation code.)
{\small {\tt 1. General Purpose Mouse (GPM). The GPM daemon is configured in different ways in different Linux distributions. On a Redhat distribution, this is accomplished by changing the file `/etc/sysconfig/mouse' to have the following:\\
MOUSETYPE="summa"\\
XMOUSETYPE="SUMMA"\\
DEVICE=/dev/ttyS0\\
\\
2. X11. For all Linux distributions, change the Mouse0 stanza in `/etc/X11/xorg.conf' to:\\
Section "InputDevice"\\
Identifier "Mouse0"\\
Driver "summa"\\
Option "Device" "/dev/ttyS0"\\
Option "InputFashion" "Tablet"\\
Option "Mode" "Absolute"\\
Option "Name" "EasyPen"\\
Option "Compatible" "True"\\
Option "Protocol" "Auto"\\
Option "SendCoreEvents" "on"\\
Option "Vendor" "GENIUS"\\
EndSection}}
To deal with these mouse issues there are 4 different
mouse emulations available from the VMX device model:
If the Summagraphics mouse isn't the default mouse, you can manually kill 'gpm' and restart it with the command "gpm -m /dev/ttyS0 -t summa". Note that Summagraphics mouse makes no sense in an SDL window and is therefore not available in this environment.
\begin{description}
\item[PS/2 mouse over the PS/2 port.]
This is the default mouse
that works perfectly well under SDL.
Under VNC the guest cursor will get
out of sync with the VNC pointer.
When this happens you can re-synchronize
the guest cursor to the VNC pointer by
holding down the
\textbf{left-ctl}
and
\textbf{left-alt}
keys together.
While these keys are down VNC pointer motions
will not be reported to the guest so
that the VNC pointer can be moved
to a place where it is possible
to move the guest cursor again.
\item[Summagraphics mouse over the serial port.]
The device model also provides emulation
for a Summagraphics tablet,
an absolute pointer device.
This emulation is provided over the second
serial port,
\textbf{/dev/ttyS1}
for Linux guests and
\textbf{COM2}
for Windows guests.
Unfortunately,
neither Linux nor Windows provides
default support for the Summagraphics
tablet so the guest will have to be
manually configured for this mouse.
\textbf{Linux configuration.}
First,
configure the GPM service to use the Summagraphics tablet.
This can vary between distributions but,
typically,
all that needs to be done is modify the file
\path{/etc/sysconfig/mouse} to contain the lines:
{\small
\begin{verbatim}
MOUSETYPE="summa"
XMOUSETYPE="SUMMA"
DEVICE=/dev/ttyS1
\end{verbatim}
}
and then restart the GPM daemon.
Next,
modify the X11 config
\path{/etc/X11/xorg.conf}
to support the Summgraphics tablet by replacing
the input device stanza with the following:
{\small
\begin{verbatim}
Section "InputDevice"
Identifier "Mouse0"
Driver "summa"
Option "Device" "/dev/ttyS1"
Option "InputFashion" "Tablet"
Option "Mode" "Absolute"
Option "Name" "EasyPen"
Option "Compatible" "True"
Option "Protocol" "Auto"
Option "SendCoreEvents" "on"
Option "Vendor" "GENIUS"
EndSection
\end{verbatim}
}
Restart X and the X cursor should now properly
track the VNC pointer.
\textbf{Windows configuration.}
Get the file
\path{http://www.cad-plan.de/files/download/tw2k.exe}
and execute that file on the guest,
answering the questions as follows:
\begin{enumerate}
\item When the program asks for \textbf{model},
scroll down and selese \textbf{SummaSketch (MM Compatible)}.
\item When the program asks for \textbf{COM Port} specify \textbf{com2}.
\item When the programs asks for a \textbf{Cursor Type} specify
\textbf{4 button cursor/puck}.
\item The guest system will then reboot and,
when it comes back up,
the guest cursor will now properly track
the VNC pointer.
\end{enumerate}
\item[PS/2 mouse over USB port.]
This is just the same PS/2 emulation except it is
provided over a USB port.
This emulation is enabled by the configuration flag:
{\small
\begin{verbatim}
usbdevice='mouse'
\end{verbatim}
}
\item[USB tablet over USB port.]
The USB tablet is an absolute pointing device
that has the advantage that it is automatically
supported under Windows guests,
although Linux guests still require some
manual configuration.
This mouse emulation is enabled by the
configuration flag:
{\small
\begin{verbatim}
usbdevice='tablet'
\end{verbatim}
}
\textbf{Linux configuration.}
Unfortunately,
there is no GPM support for the
USB tablet at this point in time.
If you intend to use a GPM pointing
device under VNC you should
configure the guest for Summagraphics
emulation.
Support for X11 is available by following
the instructions at\\
\verb+http://stz-softwaretechnik.com/~ke/touchscreen/evtouch.html+\\
with one minor change.
The
\path{xorg.conf}
given in those instructions
uses the wrong values for the X \& Y minimums and maximums,
use the following config stanza instead:
{\small
\begin{verbatim}
Section "InputDevice"
Identifier "Tablet"
Driver "evtouch"
Option "Device" "/dev/input/event2"
Option "DeviceName" "touchscreen"
Option "MinX" "0"
Option "MinY" "0"
Option "MaxX" "32256"
Option "MaxY" "32256"
Option "ReportingMode" "Raw"
Option "Emulate3Buttons"
Option "Emulate3Timeout" "50"
Option "SendCoreEvents" "On"
EndSection
\end{verbatim}
}
\textbf{Windows configuration.}
Just enabling the USB tablet in the
guest's configuration file is sufficient,
Windows will automatically recognize and
configure device drivers for this
pointing device.
\end{description}
\subsection{USB Support}
There is support for an emulated USB mouse,
an emulated USB tablet
and physical low speed USB devices
(support for high speed USB 2.0 devices is
still under development).
\begin{description}
\item[USB PS/2 style mouse.]
Details on the USB mouse emulation are
given in sections
\textbf{A.2}
and
\textbf{A.4.3}.
Enabling USB PS/2 style mouse emulation
is just a matter of adding the line
{\small
\begin{verbatim}
usbdevice='mouse'
\end{verbatim}
}
to the configuration file.
\item[USB tablet.]
Details on the USB tablet emulation are
given in sections
\textbf{A.2}
and
\textbf{A.4.3}.
Enabling USB tablet emulation
is just a matter of adding the line
{\small
\begin{verbatim}
usbdevice='tablet'
\end{verbatim}
}
to the configuration file.
\item[USB physical devices.]
Access to a physical (low speed) USB device
is enabled by adding a line of the form
{\small
\begin{verbatim}
usbdevice='host:vid:pid'
\end{verbatim}
}
into the the configuration file.\footnote{
There is an alternate
way of specifying a USB device that
uses the syntax
\textbf{host:bus.addr}
but this syntax suffers from
a major problem that makes
it effectively useless.
The problem is that the
\textbf{addr}
portion of this address
changes every time the USB device
is plugged into the system.
For this reason this addressing
scheme is not recommended and
will not be documented further.
}
\textbf{vid}
and
\textbf{pid}
are a
product id and
vendor id
that uniquely identify
the USB device.
These ids can be identified
in two ways:
\begin{enumerate}
\item Through the control window.
As described in section
\textbf{A.4.6}
the control window
is activated by pressing
\textbf{ctl-alt-2}
in the guest VGA window.
As long as USB support is
enabled in the guest by including
the config file line
{\small
\begin{verbatim}
usb=1
\end{verbatim}
}
then executing the command
{\small
\begin{verbatim}
info usbhost
\end{verbatim}
}
in the control window
will display a list of all
usb devices and their ids.
For example,
this output:
{\small
\begin{verbatim}
Device 1.3, speed 1.5 Mb/s
Class 00: USB device 04b3:310b
\end{verbatim}
}
was created from a USB mouse with
vendor id
\textbf{04b3}
and product id
\textbf{310b}.
This device could be made available
to the VMX guest by including the
config file entry
{\small
\begin{verbatim}
usbdevice='host:04be:310b'
\end{verbatim}
}
It is also possible to
enable access to a USB
device dynamically through
the control window.
The control window command
{\small
\begin{verbatim}
usb_add host:vid:pid
\end{verbatim}
}
will also allow access to a
USB device with vendor id
\textbf{vid}
and product id
\textbf{pid}.
\item Through the
\path{/proc} file system.
The contents of the pseudo file
\path{/proc/bus/usb/devices}
can also be used to identify
vendor and product ids.
Looking at this file,
the line starting with
\textbf{P:}
has a field
\textbf{Vendor}
giving the vendor id and
another field
\textbf{ProdID}
giving the product id.
The contents of
\path{/proc/bus/usb/devices}
for the example mouse is as
follows:
{\small
\begin{verbatim}
T: Bus=01 Lev=01 Prnt=01 Port=01 Cnt=02 Dev#= 3 Spd=1.5 MxCh= 0
D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=04b3 ProdID=310b Rev= 1.60
C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr=100mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=(none)
E: Ad=81(I) Atr=03(Int.) MxPS= 4 Ivl=10ms
\end{verbatim}
}
Note that the
\textbf{P:}
line correctly identifies the
vendor id and product id
for this mouse as
\textbf{04b3:310b}.
\end{enumerate}
There is one other issue to
be aware of when accessing a
physical USB device from the guest.
The Dom0 kernel must not have
a device driver loaded for
the device that the guest wishes
to access.
This means that the Dom0
kernel must not have that
device driver compiled into
the kernel or,
if using modules,
that driver module must
not be loaded.
Note that this is the device
specific USB driver that must
not be loaded,
either the
\textbf{UHCI}
or
\textbf{OHCI}
USB controller driver must
still be loaded.
Going back to the USB mouse
as an example,
if \textbf{lsmod}
gives the output:
{\small
\begin{verbatim}
Module Size Used by
usbmouse 4128 0
usbhid 28996 0
uhci_hcd 35409 0
\end{verbatim}
}
then the USB mouse is being
used by the Dom0 kernel and is
not available to the guest.
Executing the command
\textbf{rmmod usbhid}\footnote{
Turns out the
\textbf{usbhid}
driver is the significant
one for the USB mouse,
the presence or absence of
the module
\textbf{usbmouse}
has no effect on whether or
not the guest can see a USB mouse.}
will remove the USB mouse
driver from the Dom0 kernel
and the mouse will now be
accessible by the VMX guest.
Be aware the the Linux USB
hotplug system will reload
the drivers if a USB device
is removed and plugged back
in.
This means that just unloading
the driver module might not
be sufficient if the USB device
is removed and added back.
A more reliable technique is
to first
\textbf{rmmod}
the driver and then rename the
driver file in the
\path{/lib/modules}
directory,
just to make sure it doesn't get
reloaded.
\end{description}
\subsection{Destroy VMX guests}
VMX guests can be destroyed in the same way as can paravirtualized guests. We recommend that you type the command
+3 -2
View File
@@ -53,7 +53,7 @@ int xencons_ring_send(const char *data, unsigned len)
static void handle_input(int port, struct pt_regs *regs)
static void handle_input(int port, struct pt_regs *regs, void *ign)
{
struct xencons_interface *intf = xencons_interface();
XENCONS_RING_IDX cons, prod;
@@ -83,7 +83,8 @@ int xencons_ring_init(void)
if (!start_info.console_evtchn)
return 0;
err = bind_evtchn(start_info.console_evtchn, handle_input);
err = bind_evtchn(start_info.console_evtchn, handle_input,
NULL);
if (err <= 0) {
printk("XEN console request chn bind failed %i\n", err);
return err;
+54 -30
View File
@@ -22,9 +22,18 @@
#include <events.h>
#include <lib.h>
#define NR_EVS 1024
/* this represents a event handler. Chaining or sharing is not allowed */
typedef struct _ev_action_t {
void (*handler)(int, struct pt_regs *, void *);
void *data;
u32 count;
} ev_action_t;
static ev_action_t ev_actions[NR_EVS];
void default_handler(int port, struct pt_regs *regs);
void default_handler(int port, struct pt_regs *regs, void *data);
/*
@@ -35,42 +44,33 @@ int do_event(u32 port, struct pt_regs *regs)
ev_action_t *action;
if (port >= NR_EVS) {
printk("Port number too large: %d\n", port);
goto out;
goto out;
}
action = &ev_actions[port];
action->count++;
if (!action->handler)
{
printk("Spurious event on port %d\n", port);
goto out;
}
if (action->status & EVS_DISABLED)
{
printk("Event on port %d disabled\n", port);
goto out;
}
/* call the handler */
action->handler(port, regs);
action->handler(port, regs, action->data);
out:
clear_evtchn(port);
return 1;
}
int bind_evtchn( u32 port, void (*handler)(int, struct pt_regs *) )
int bind_evtchn( u32 port, void (*handler)(int, struct pt_regs *, void *),
void *data )
{
if(ev_actions[port].handler != default_handler)
printk("WARN: Handler for port %d already registered, replacing\n",
port);
ev_actions[port].data = data;
wmb();
ev_actions[port].handler = handler;
ev_actions[port].status &= ~EVS_DISABLED;
/* Finally unmask the port */
unmask_evtchn(port);
@@ -82,13 +82,14 @@ void unbind_evtchn( u32 port )
if (ev_actions[port].handler == default_handler)
printk("WARN: No handler for port %d when unbinding\n", port);
ev_actions[port].handler = default_handler;
ev_actions[port].status |= EVS_DISABLED;
wmb();
ev_actions[port].data = NULL;
}
int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *) )
int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *, void *data),
void *data)
{
evtchn_op_t op;
int ret = 0;
/* Try to bind the virq to a port */
op.cmd = EVTCHNOP_bind_virq;
@@ -97,13 +98,11 @@ int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *) )
if ( HYPERVISOR_event_channel_op(&op) != 0 )
{
ret = 1;
printk("Failed to bind virtual IRQ %d\n", virq);
goto out;
return 1;
}
bind_evtchn(op.u.bind_virq.port, handler);
out:
return ret;
bind_evtchn(op.u.bind_virq.port, handler, data);
return 0;
}
void unbind_virq( u32 port )
@@ -137,13 +136,38 @@ void init_events(void)
#endif
/* inintialise event handler */
for ( i = 0; i < NR_EVS; i++ )
{
ev_actions[i].status = EVS_DISABLED;
{
ev_actions[i].handler = default_handler;
mask_evtchn(i);
}
}
void default_handler(int port, struct pt_regs *regs) {
void default_handler(int port, struct pt_regs *regs, void *ignore)
{
printk("[Port %d] - event received\n", port);
}
/* Unfortunate confusion of terminology: the port is unbound as far
as Xen is concerned, but we automatically bind a handler to it
from inside mini-os. */
int evtchn_alloc_unbound(void (*handler)(int, struct pt_regs *regs,
void *data),
void *data)
{
u32 port;
evtchn_op_t op;
int err;
op.cmd = EVTCHNOP_alloc_unbound;
op.u.alloc_unbound.dom = DOMID_SELF;
op.u.alloc_unbound.remote_dom = 0;
err = HYPERVISOR_event_channel_op(&op);
if (err) {
printk("Failed to alloc unbound evtchn: %d.\n", err);
return -1;
}
port = op.u.alloc_unbound.port;
bind_evtchn(port, handler, data);
return port;
}
+158
View File
@@ -0,0 +1,158 @@
/*
****************************************************************************
* (C) 2006 - Cambridge University
****************************************************************************
*
* File: gnttab.c
* Author: Steven Smith (sos22@cam.ac.uk)
* Changes: Grzegorz Milos (gm281@cam.ac.uk)
*
* Date: July 2006
*
* Environment: Xen Minimal OS
* Description: Simple grant tables implementation. About as stupid as it's
* possible to be and still work.
*
****************************************************************************
*/
#include <os.h>
#include <mm.h>
#include <gnttab.h>
#define NR_RESERVED_ENTRIES 8
#define NR_GRANT_FRAMES 4
#define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t))
#define GNTTAB_LIST_END (NR_GRANT_ENTRIES + 1)
static grant_entry_t *gnttab_table;
static grant_ref_t gnttab_list[NR_GRANT_ENTRIES];
static grant_ref_t gnttab_free_head;
static grant_ref_t
get_free_entries(int count)
{
grant_ref_t ref;
grant_ref_t head;
ref = head = gnttab_free_head;
while (count-- > 1)
head = gnttab_list[head];
gnttab_free_head = gnttab_list[head];
gnttab_list[head] = GNTTAB_LIST_END;
return ref;
}
static void
put_free_entry(grant_ref_t gref)
{
gnttab_list[gref] = gnttab_free_head;
gnttab_free_head = gref;
}
grant_ref_t
gnttab_grant_access(domid_t domid, unsigned long frame, int readonly)
{
grant_ref_t ref;
ref = get_free_entries(1);
gnttab_table[ref].frame = frame;
gnttab_table[ref].domid = domid;
wmb();
readonly *= GTF_readonly;
gnttab_table[ref].flags = GTF_permit_access | readonly;
return ref;
}
grant_ref_t
gnttab_grant_transfer(domid_t domid, unsigned long pfn)
{
grant_ref_t ref;
ref = get_free_entries(1);
gnttab_table[ref].frame = pfn;
gnttab_table[ref].domid = domid;
wmb();
gnttab_table[ref].flags = GTF_accept_transfer;
return ref;
}
int
gnttab_end_access(grant_ref_t ref)
{
u16 flags, nflags;
nflags = gnttab_table[ref].flags;
do {
if ((flags = nflags) & (GTF_reading|GTF_writing)) {
printk("WARNING: g.e. still in use!\n");
return 0;
}
} while ((nflags = synch_cmpxchg(&gnttab_table[ref].flags, flags, 0)) !=
flags);
put_free_entry(ref);
return 1;
}
unsigned long
gnttab_end_transfer(grant_ref_t ref)
{
unsigned long frame;
u16 flags;
while (!((flags = gnttab_table[ref].flags) & GTF_transfer_committed)) {
if (synch_cmpxchg(&gnttab_table[ref].flags, flags, 0) == flags) {
printk("Release unused transfer grant.\n");
put_free_entry(ref);
return 0;
}
}
/* If a transfer is in progress then wait until it is completed. */
while (!(flags & GTF_transfer_completed)) {
flags = gnttab_table[ref].flags;
}
/* Read the frame number /after/ reading completion status. */
rmb();
frame = gnttab_table[ref].frame;
put_free_entry(ref);
return frame;
}
grant_ref_t
gnttab_alloc_and_grant(void **map)
{
unsigned long mfn;
grant_ref_t gref;
*map = (void *)alloc_page();
mfn = virt_to_mfn(*map);
gref = gnttab_grant_access(0, mfn, 0);
return gref;
}
void
init_gnttab(void)
{
struct gnttab_setup_table setup;
unsigned long frames[NR_GRANT_FRAMES];
int i;
for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++)
gnttab_list[i] = i + 1;
gnttab_free_head = NR_RESERVED_ENTRIES;
setup.dom = DOMID_SELF;
setup.nr_frames = NR_GRANT_FRAMES;
set_xen_guest_handle(setup.frame_list, frames);
HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1);
gnttab_table = map_frames(frames, NR_GRANT_FRAMES);
printk("gnttab_table mapped at %p.\n", gnttab_table);
}
+7 -17
View File
@@ -22,28 +22,18 @@
#include<traps.h>
#include <xen/event_channel.h>
#define NR_EVS 1024
/* ev handler status */
#define EVS_INPROGRESS 1 /* Event handler active - do not enter! */
#define EVS_DISABLED 2 /* Event disabled - do not enter! */
#define EVS_PENDING 4 /* Event pending - replay on enable */
#define EVS_REPLAY 8 /* Event has been replayed but not acked yet */
/* this represents a event handler. Chaining or sharing is not allowed */
typedef struct _ev_action_t {
void (*handler)(int, struct pt_regs *);
unsigned int status; /* IRQ status */
u32 count;
} ev_action_t;
/* prototypes */
int do_event(u32 port, struct pt_regs *regs);
int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *) );
int bind_evtchn( u32 virq, void (*handler)(int, struct pt_regs *) );
int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *, void *data),
void *data);
int bind_evtchn( u32 virq, void (*handler)(int, struct pt_regs *, void *data),
void *data );
void unbind_evtchn( u32 port );
void init_events(void);
void unbind_virq( u32 port );
int evtchn_alloc_unbound(void (*handler)(int, struct pt_regs *regs,
void *data),
void *data);
static inline int notify_remote_via_evtchn(int port)
{
+14
View File
@@ -0,0 +1,14 @@
#ifndef __GNTTAB_H__
#define __GNTTAB_H__
#include <xen/grant_table.h>
void init_gnttab(void);
grant_ref_t gnttab_alloc_and_grant(void **map);
grant_ref_t gnttab_grant_access(domid_t domid, unsigned long frame,
int readonly);
grant_ref_t gnttab_grant_transfer(domid_t domid, unsigned long pfn);
unsigned long gnttab_end_transfer(grant_ref_t gref);
int gnttab_end_access(grant_ref_t ref);
#endif /* !__GNTTAB_H__ */
+13
View File
@@ -89,6 +89,7 @@ size_t strlen(const char *s);
char *strchr(const char *s, int c);
char *strstr(const char *s1, const char *s2);
char * strcat(char * dest, const char * src);
char *strdup(const char *s);
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
@@ -98,6 +99,18 @@ struct kvec {
size_t iov_len;
};
#define ASSERT(x) \
do { \
if (!(x)) { \
printk("ASSERTION FAILED: %s at %s:%d.\n", \
# x , \
__FILE__, \
__LINE__); \
BUG(); \
} \
} while(0)
/* Consistency check as much as possible. */
void sanity_check(void);
#endif /* _LIB_H_ */
+6 -2
View File
@@ -196,9 +196,11 @@ static __inline__ paddr_t machine_to_phys(maddr_t machine)
#define to_virt(x) ((void *)((unsigned long)(x)+VIRT_START))
#define virt_to_pfn(_virt) (PFN_DOWN(to_phys(_virt)))
#define virt_to_mfn(_virt) (pfn_to_mfn(virt_to_pfn(_virt)))
#define mach_to_virt(_mach) (to_virt(machine_to_phys(_mach)))
#define virt_to_mach(_virt) (phys_to_machine(to_phys(_virt)))
#define mfn_to_virt(_mfn) (to_virt(mfn_to_pfn(_mfn) << PAGE_SHIFT))
#define pfn_to_virt(_pfn) (to_virt(_pfn << PAGE_SHIFT))
#define pfn_to_virt(_pfn) (to_virt((_pfn) << PAGE_SHIFT))
/* Pagetable walking. */
#define pte_to_mfn(_pte) (((_pte) & (PADDR_MASK&PAGE_MASK)) >> L1_PAGETABLE_SHIFT)
@@ -206,7 +208,7 @@ static __inline__ paddr_t machine_to_phys(maddr_t machine)
void init_mm(void);
unsigned long alloc_pages(int order);
#define alloc_page() alloc_pages(0);
#define alloc_page() alloc_pages(0)
void free_pages(void *pointer, int order);
static __inline__ int get_order(unsigned long size)
@@ -219,4 +221,6 @@ static __inline__ int get_order(unsigned long size)
}
void *map_frames(unsigned long *f, unsigned long n);
#endif /* _MM_H_ */
+55
View File
@@ -445,7 +445,62 @@ static __inline__ unsigned long __ffs(unsigned long word)
/********************* common i386 and x86_64 ****************************/
struct __synch_xchg_dummy { unsigned long a[100]; };
#define __synch_xg(x) ((struct __synch_xchg_dummy *)(x))
#define synch_cmpxchg(ptr, old, new) \
((__typeof__(*(ptr)))__synch_cmpxchg((ptr),\
(unsigned long)(old), \
(unsigned long)(new), \
sizeof(*(ptr))))
static inline unsigned long __synch_cmpxchg(volatile void *ptr,
unsigned long old,
unsigned long new, int size)
{
unsigned long prev;
switch (size) {
case 1:
__asm__ __volatile__("lock; cmpxchgb %b1,%2"
: "=a"(prev)
: "q"(new), "m"(*__synch_xg(ptr)),
"0"(old)
: "memory");
return prev;
case 2:
__asm__ __volatile__("lock; cmpxchgw %w1,%2"
: "=a"(prev)
: "r"(new), "m"(*__synch_xg(ptr)),
"0"(old)
: "memory");
return prev;
#ifdef __x86_64__
case 4:
__asm__ __volatile__("lock; cmpxchgl %k1,%2"
: "=a"(prev)
: "r"(new), "m"(*__synch_xg(ptr)),
"0"(old)
: "memory");
return prev;
case 8:
__asm__ __volatile__("lock; cmpxchgq %1,%2"
: "=a"(prev)
: "r"(new), "m"(*__synch_xg(ptr)),
"0"(old)
: "memory");
return prev;
#else
case 4:
__asm__ __volatile__("lock; cmpxchgl %1,%2"
: "=a"(prev)
: "r"(new), "m"(*__synch_xg(ptr)),
"0"(old)
: "memory");
return prev;
#endif
}
return old;
}
static __inline__ void synch_set_bit(int nr, volatile void * addr)
+23 -6
View File
@@ -1,34 +1,51 @@
#ifndef XENBUS_H__
#define XENBUS_H__
typedef unsigned long xenbus_transaction_t;
#define XBT_NIL ((xenbus_transaction_t)0)
/* Initialize the XenBus system. */
void init_xenbus(void);
/* Read the value associated with a path. Returns a malloc'd error
string on failure and sets *value to NULL. On success, *value is
set to a malloc'd copy of the value. */
char *xenbus_read(const char *path, char **value);
char *xenbus_read(xenbus_transaction_t xbt, const char *path, char **value);
/* Associates a value with a path. Returns a malloc'd error string on
failure. */
char *xenbus_write(const char *path, const char *value);
char *xenbus_write(xenbus_transaction_t xbt, const char *path, const char *value);
/* Removes the value associated with a path. Returns a malloc'd error
string on failure. */
char *xenbus_rm(const char *path);
char *xenbus_rm(xenbus_transaction_t xbt, const char *path);
/* List the contents of a directory. Returns a malloc'd error string
on failure and sets *contents to NULL. On success, *contents is
set to a malloc'd array of pointers to malloc'd strings. The array
is NULL terminated. May block. */
char *xenbus_ls(const char *prefix, char ***contents);
char *xenbus_ls(xenbus_transaction_t xbt, const char *prefix, char ***contents);
/* Reads permissions associated with a path. Returns a malloc'd error
string on failure and sets *value to NULL. On success, *value is
set to a malloc'd copy of the value. */
char *xenbus_get_perms(const char *path, char **value);
char *xenbus_get_perms(xenbus_transaction_t xbt, const char *path, char **value);
/* Sets the permissions associated with a path. Returns a malloc'd
error string on failure. */
char *xenbus_set_perms(const char *path, domid_t dom, char perm);
char *xenbus_set_perms(xenbus_transaction_t xbt, const char *path, domid_t dom, char perm);
/* Start a xenbus transaction. Returns the transaction in xbt on
success or a malloc'd error string otherwise. */
char *xenbus_transaction_start(xenbus_transaction_t *xbt);
/* End a xenbus transaction. Returns a malloc'd error string if it
fails. abort says whether the transaction should be aborted.
Returns 1 in *retry iff the transaction should be retried. */
char *xenbus_transaction_end(xenbus_transaction_t, int abort,
int *retry);
/* Read path and parse it as an integer. Returns -1 on error. */
int xenbus_read_integer(char *path);
#endif /* XENBUS_H__ */
+7 -2
View File
@@ -35,6 +35,7 @@
#include <lib.h>
#include <sched.h>
#include <xenbus.h>
#include <gnttab.h>
#include <xen/features.h>
#include <xen/version.h>
@@ -104,7 +105,8 @@ void test_xenbus(void);
void xenbus_tester(void *p)
{
test_xenbus();
printk("Xenbus tests disabled, because of a Xend bug.\n");
/* test_xenbus(); */
}
/* This should be overridden by the application we are linked against. */
@@ -176,7 +178,10 @@ void start_kernel(start_info_t *si)
/* Init the console driver. */
init_console();
/* Init grant tables */
init_gnttab();
/* Init scheduler. */
init_sched();
+10
View File
@@ -23,6 +23,7 @@
#include <os.h>
#include <types.h>
#include <lib.h>
#include <xmalloc.h>
int memcmp(const void * cs,const void * ct,size_t count)
{
@@ -156,4 +157,13 @@ char * strstr(const char * s1,const char * s2)
return NULL;
}
char *strdup(const char *x)
{
int l = strlen(x);
char *res = malloc(l + 1);
if (!res) return NULL;
memcpy(res, x, l + 1);
return res;
}
#endif
+122 -1
View File
@@ -343,7 +343,7 @@ void free_pages(void *pointer, int order)
break;
/* Merge with successor */
freed_ct = (chunk_tail_t *)((char *)to_merge_ch + mask);
freed_ct = (chunk_tail_t *)((char *)to_merge_ch + mask) - 1;
}
/* We are commited to merging, unlink the chunk */
@@ -612,6 +612,107 @@ void mem_test(unsigned long *start_add, unsigned long *end_add)
}
static pgentry_t *demand_map_pgt;
static void *demand_map_area_start;
static void init_demand_mapping_area(unsigned long max_pfn)
{
unsigned long mfn;
pgentry_t *tab;
unsigned long start_addr;
unsigned long pt_pfn;
unsigned offset;
/* Round up to four megs. + 1024 rather than + 1023 since we want
to be sure we don't end up in the same place we started. */
max_pfn = (max_pfn + L1_PAGETABLE_ENTRIES) & ~(L1_PAGETABLE_ENTRIES - 1);
if (max_pfn == 0 ||
(unsigned long)pfn_to_virt(max_pfn + L1_PAGETABLE_ENTRIES) >=
HYPERVISOR_VIRT_START) {
printk("Too much memory; no room for demand map hole.\n");
do_exit();
}
demand_map_area_start = pfn_to_virt(max_pfn);
printk("Demand map pfns start at %lx (%p).\n", max_pfn,
demand_map_area_start);
start_addr = (unsigned long)demand_map_area_start;
tab = (pgentry_t *)start_info.pt_base;
mfn = virt_to_mfn(start_info.pt_base);
pt_pfn = virt_to_pfn(alloc_page());
#if defined(__x86_64__)
offset = l4_table_offset(start_addr);
if (!(tab[offset] & _PAGE_PRESENT)) {
new_pt_frame(&pt_pfn, mfn, offset, L3_FRAME);
pt_pfn = virt_to_pfn(alloc_page());
}
ASSERT(tab[offset] & _PAGE_PRESENT);
mfn = pte_to_mfn(tab[offset]);
tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT);
#endif
#if defined(__x86_64__) || defined(CONFIG_X86_PAE)
offset = l3_table_offset(start_addr);
if (!(tab[offset] & _PAGE_PRESENT)) {
new_pt_frame(&pt_pfn, mfn, offset, L2_FRAME);
pt_pfn = virt_to_pfn(alloc_page());
}
ASSERT(tab[offset] & _PAGE_PRESENT);
mfn = pte_to_mfn(tab[offset]);
tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT);
#endif
offset = l2_table_offset(start_addr);
if (tab[offset] & _PAGE_PRESENT) {
printk("Demand map area already has a page table covering it?\n");
BUG();
}
demand_map_pgt = pfn_to_virt(pt_pfn);
new_pt_frame(&pt_pfn, mfn, offset, L1_FRAME);
ASSERT(tab[offset] & _PAGE_PRESENT);
}
void *map_frames(unsigned long *f, unsigned long n)
{
unsigned long x;
unsigned long y = 0;
mmu_update_t mmu_updates[16];
int rc;
if (n > 16) {
printk("Tried to map too many (%ld) frames at once.\n", n);
return NULL;
}
/* Find a run of n contiguous frames */
for (x = 0; x <= 1024 - n; x += y + 1) {
for (y = 0; y < n; y++)
if (demand_map_pgt[y] & _PAGE_PRESENT)
break;
if (y == n)
break;
}
if (y != n) {
printk("Failed to map %ld frames!\n", n);
return NULL;
}
/* Found it at x. Map it in. */
for (y = 0; y < n; y++) {
mmu_updates[y].ptr = virt_to_mach(&demand_map_pgt[x + y]);
mmu_updates[y].val = (f[y] << PAGE_SHIFT) | L1_PROT;
}
rc = HYPERVISOR_mmu_update(mmu_updates, n, NULL, DOMID_SELF);
if (rc < 0) {
printk("Map %ld failed: %d.\n", n, rc);
return NULL;
} else {
return (void *)(unsigned long)((unsigned long)demand_map_area_start +
x * PAGE_SIZE);
}
}
void init_mm(void)
{
@@ -643,4 +744,24 @@ void init_mm(void)
(u_long)to_virt(PFN_PHYS(max_pfn)), PFN_PHYS(max_pfn));
init_page_allocator(PFN_PHYS(start_pfn), PFN_PHYS(max_pfn));
printk("MM: done\n");
init_demand_mapping_area(max_pfn);
printk("Initialised demand area.\n");
}
void sanity_check(void)
{
int x;
chunk_head_t *head;
for (x = 0; x < FREELIST_SIZE; x++) {
for (head = free_head[x]; !FREELIST_EMPTY(head); head = head->next) {
ASSERT(!allocated_in_map(virt_to_pfn(head)));
if (head->next)
ASSERT(head->next->pprev == &head->next);
}
if (free_head[x]) {
ASSERT(free_head[x]->pprev == &free_head[x]);
}
}
}
+2 -2
View File
@@ -215,7 +215,7 @@ void block_domain(u32 millisecs)
/*
* Just a dummy
*/
static void timer_handler(int ev, struct pt_regs *regs)
static void timer_handler(int ev, struct pt_regs *regs, void *ign)
{
static int i;
@@ -233,5 +233,5 @@ static void timer_handler(int ev, struct pt_regs *regs)
void init_time(void)
{
printk("Initialising timer interface\n");
bind_virq(VIRQ_TIMER, &timer_handler);
bind_virq(VIRQ_TIMER, &timer_handler, NULL);
}
+83 -23
View File
@@ -112,7 +112,7 @@ static void xenbus_thread_func(void *ign)
}
}
static void xenbus_evtchn_handler(int port, struct pt_regs *regs)
static void xenbus_evtchn_handler(int port, struct pt_regs *regs, void *ign)
{
wake_up(&xb_waitq);
}
@@ -174,7 +174,8 @@ void init_xenbus(void)
create_thread("xenstore", xenbus_thread_func, NULL);
DEBUG("buf at %p.\n", xenstore_buf);
err = bind_evtchn(start_info.store_evtchn,
xenbus_evtchn_handler);
xenbus_evtchn_handler,
NULL);
DEBUG("xenbus on irq %d\n", err);
}
@@ -187,8 +188,8 @@ struct write_req {
by xenbus as if sent atomically. The header is added
automatically, using type %type, req_id %req_id, and trans_id
%trans_id. */
static void xb_write(int type, int req_id, int trans_id,
const struct write_req *req, int nr_reqs)
static void xb_write(int type, int req_id, xenbus_transaction_t trans_id,
const struct write_req *req, int nr_reqs)
{
XENSTORE_RING_IDX prod;
int r;
@@ -266,9 +267,9 @@ static void xb_write(int type, int req_id, int trans_id,
freed by the caller. */
static struct xsd_sockmsg *
xenbus_msg_reply(int type,
int trans,
struct write_req *io,
int nr_reqs)
xenbus_transaction_t trans,
struct write_req *io,
int nr_reqs)
{
int id;
DEFINE_WAIT(w);
@@ -322,14 +323,14 @@ static void xenbus_debug_msg(const char *msg)
/* List the contents of a directory. Returns a malloc()ed array of
pointers to malloc()ed strings. The array is NULL terminated. May
block. */
char *xenbus_ls(const char *pre, char ***contents)
char *xenbus_ls(xenbus_transaction_t xbt, const char *pre, char ***contents)
{
struct xsd_sockmsg *reply, *repmsg;
struct write_req req[] = { { pre, strlen(pre)+1 } };
int nr_elems, x, i;
char **res;
repmsg = xenbus_msg_reply(XS_DIRECTORY, 0, req, ARRAY_SIZE(req));
repmsg = xenbus_msg_reply(XS_DIRECTORY, xbt, req, ARRAY_SIZE(req));
char *msg = errmsg(repmsg);
if (msg) {
*contents = NULL;
@@ -351,12 +352,12 @@ char *xenbus_ls(const char *pre, char ***contents)
return NULL;
}
char *xenbus_read(const char *path, char **value)
char *xenbus_read(xenbus_transaction_t xbt, const char *path, char **value)
{
struct write_req req[] = { {path, strlen(path) + 1} };
struct xsd_sockmsg *rep;
char *res;
rep = xenbus_msg_reply(XS_READ, 0, req, ARRAY_SIZE(req));
rep = xenbus_msg_reply(XS_READ, xbt, req, ARRAY_SIZE(req));
char *msg = errmsg(rep);
if (msg) {
*value = NULL;
@@ -370,14 +371,14 @@ char *xenbus_read(const char *path, char **value)
return NULL;
}
char *xenbus_write(const char *path, const char *value)
char *xenbus_write(xenbus_transaction_t xbt, const char *path, const char *value)
{
struct write_req req[] = {
{path, strlen(path) + 1},
{value, strlen(value) + 1},
};
struct xsd_sockmsg *rep;
rep = xenbus_msg_reply(XS_WRITE, 0, req, ARRAY_SIZE(req));
rep = xenbus_msg_reply(XS_WRITE, xbt, req, ARRAY_SIZE(req));
char *msg = errmsg(rep);
if (msg)
return msg;
@@ -385,11 +386,11 @@ char *xenbus_write(const char *path, const char *value)
return NULL;
}
char *xenbus_rm(const char *path)
char *xenbus_rm(xenbus_transaction_t xbt, const char *path)
{
struct write_req req[] = { {path, strlen(path) + 1} };
struct xsd_sockmsg *rep;
rep = xenbus_msg_reply(XS_RM, 0, req, ARRAY_SIZE(req));
rep = xenbus_msg_reply(XS_RM, xbt, req, ARRAY_SIZE(req));
char *msg = errmsg(rep);
if (msg)
return msg;
@@ -397,12 +398,12 @@ char *xenbus_rm(const char *path)
return NULL;
}
char *xenbus_get_perms(const char *path, char **value)
char *xenbus_get_perms(xenbus_transaction_t xbt, const char *path, char **value)
{
struct write_req req[] = { {path, strlen(path) + 1} };
struct xsd_sockmsg *rep;
char *res;
rep = xenbus_msg_reply(XS_GET_PERMS, 0, req, ARRAY_SIZE(req));
rep = xenbus_msg_reply(XS_GET_PERMS, xbt, req, ARRAY_SIZE(req));
char *msg = errmsg(rep);
if (msg) {
*value = NULL;
@@ -417,7 +418,7 @@ char *xenbus_get_perms(const char *path, char **value)
}
#define PERM_MAX_SIZE 32
char *xenbus_set_perms(const char *path, domid_t dom, char perm)
char *xenbus_set_perms(xenbus_transaction_t xbt, const char *path, domid_t dom, char perm)
{
char value[PERM_MAX_SIZE];
snprintf(value, PERM_MAX_SIZE, "%c%hu", perm, dom);
@@ -426,7 +427,7 @@ char *xenbus_set_perms(const char *path, domid_t dom, char perm)
{value, strlen(value) + 1},
};
struct xsd_sockmsg *rep;
rep = xenbus_msg_reply(XS_SET_PERMS, 0, req, ARRAY_SIZE(req));
rep = xenbus_msg_reply(XS_SET_PERMS, xbt, req, ARRAY_SIZE(req));
char *msg = errmsg(rep);
if (msg)
return msg;
@@ -434,13 +435,72 @@ char *xenbus_set_perms(const char *path, domid_t dom, char perm)
return NULL;
}
char *xenbus_transaction_start(xenbus_transaction_t *xbt)
{
/* xenstored becomes angry if you send a length 0 message, so just
shove a nul terminator on the end */
struct write_req req = { "", 1};
struct xsd_sockmsg *rep;
char *err;
rep = xenbus_msg_reply(XS_TRANSACTION_START, 0, &req, 1);
err = errmsg(rep);
if (err)
return err;
sscanf((char *)(rep + 1), "%u", xbt);
free(rep);
return NULL;
}
char *
xenbus_transaction_end(xenbus_transaction_t t, int abort, int *retry)
{
struct xsd_sockmsg *rep;
struct write_req req;
char *err;
*retry = 0;
req.data = abort ? "F" : "T";
req.len = 2;
rep = xenbus_msg_reply(XS_TRANSACTION_END, t, &req, 1);
err = errmsg(rep);
if (err) {
if (!strcmp(err, "EAGAIN")) {
*retry = 1;
free(err);
return NULL;
} else {
return err;
}
}
free(rep);
return NULL;
}
int xenbus_read_integer(char *path)
{
char *res, *buf;
int t;
res = xenbus_read(XBT_NIL, path, &buf);
if (res) {
printk("Failed to read %s.\n", path);
free(res);
return -1;
}
sscanf(buf, "%d", &t);
free(buf);
return t;
}
static void do_ls_test(const char *pre)
{
char **dirs;
int x;
DEBUG("ls %s...\n", pre);
char *msg = xenbus_ls(pre, &dirs);
char *msg = xenbus_ls(XBT_NIL, pre, &dirs);
if (msg) {
DEBUG("Error in xenbus ls: %s\n", msg);
free(msg);
@@ -458,7 +518,7 @@ static void do_read_test(const char *path)
{
char *res;
DEBUG("Read %s...\n", path);
char *msg = xenbus_read(path, &res);
char *msg = xenbus_read(XBT_NIL, path, &res);
if (msg) {
DEBUG("Error in xenbus read: %s\n", msg);
free(msg);
@@ -471,7 +531,7 @@ static void do_read_test(const char *path)
static void do_write_test(const char *path, const char *val)
{
DEBUG("Write %s to %s...\n", val, path);
char *msg = xenbus_write(path, val);
char *msg = xenbus_write(XBT_NIL, path, val);
if (msg) {
DEBUG("Result %s\n", msg);
free(msg);
@@ -483,7 +543,7 @@ static void do_write_test(const char *path, const char *val)
static void do_rm_test(const char *path)
{
DEBUG("rm %s...\n", path);
char *msg = xenbus_rm(path);
char *msg = xenbus_rm(XBT_NIL, path);
if (msg) {
DEBUG("Result %s\n", msg);
free(msg);
@@ -442,6 +442,7 @@ void flush_tlb_mm(struct mm_struct * mm)
{ xen_tlb_flush_mask(&mm->cpu_vm_mask); }
void flush_tlb_page(struct vm_area_struct *vma, unsigned long va)
{ xen_invlpg_mask(&vma->vm_mm->cpu_vm_mask, va); }
EXPORT_SYMBOL(flush_tlb_page);
void flush_tlb_all(void)
{ xen_tlb_flush_all(); }
@@ -989,12 +989,11 @@ static void stop_hz_timer(void)
smp_mb();
/* Leave ourselves in 'tick mode' if rcu or softirq pending. */
if (rcu_needs_cpu(cpu) || local_softirq_pending()) {
/* Leave ourselves in 'tick mode' if rcu or softirq or timer pending. */
if (rcu_needs_cpu(cpu) || local_softirq_pending() ||
(j = next_timer_interrupt(), time_before_eq(j, jiffies))) {
cpu_clear(cpu, nohz_cpu_mask);
j = jiffies + 1;
} else {
j = next_timer_interrupt();
}
BUG_ON(HYPERVISOR_set_timer_op(jiffies_to_st(j)) != 0);
@@ -60,7 +60,7 @@ void *kmap_atomic_pte(struct page *page, enum km_type type)
void kunmap_atomic(void *kvaddr, enum km_type type)
{
#ifdef CONFIG_DEBUG_HIGHMEM
#if defined(CONFIG_DEBUG_HIGHMEM) || defined(CONFIG_XEN)
unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
@@ -69,7 +69,9 @@ void kunmap_atomic(void *kvaddr, enum km_type type)
preempt_check_resched();
return;
}
#endif
#if defined(CONFIG_DEBUG_HIGHMEM)
if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx))
BUG();
@@ -79,6 +81,14 @@ void kunmap_atomic(void *kvaddr, enum km_type type)
*/
pte_clear(&init_mm, vaddr, kmap_pte-idx);
__flush_tlb_one(vaddr);
#elif defined(CONFIG_XEN)
/*
* We must ensure there are no dangling pagetable references when
* returning memory to Xen (decrease_reservation).
* XXX TODO: We could make this faster by only zapping when
* kmap_flush_unused is called but that is trickier and more invasive.
*/
pte_clear(&init_mm, vaddr, kmap_pte-idx);
#endif
dec_preempt_count();
+7 -22
View File
@@ -271,10 +271,6 @@ static unsigned long discontig_frames[1<<MAX_CONTIG_ORDER];
int xen_create_contiguous_region(
unsigned long vstart, unsigned int order, unsigned int address_bits)
{
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
unsigned long *in_frames = discontig_frames, out_frame;
unsigned long frame, i, flags;
long rc;
@@ -301,7 +297,7 @@ int xen_create_contiguous_region(
if (xen_feature(XENFEAT_auto_translated_physmap))
return 0;
if (order > MAX_CONTIG_ORDER)
if (unlikely(order > MAX_CONTIG_ORDER))
return -ENOMEM;
set_xen_guest_handle(exchange.in.extent_start, in_frames);
@@ -313,11 +309,7 @@ int xen_create_contiguous_region(
/* 1. Zap current PTEs, remembering MFNs. */
for (i = 0; i < (1UL<<order); i++) {
pgd = pgd_offset_k(vstart + (i*PAGE_SIZE));
pud = pud_offset(pgd, (vstart + (i*PAGE_SIZE)));
pmd = pmd_offset(pud, (vstart + (i*PAGE_SIZE)));
pte = pte_offset_kernel(pmd, (vstart + (i*PAGE_SIZE)));
in_frames[i] = pte_mfn(*pte);
in_frames[i] = pfn_to_mfn((__pa(vstart) >> PAGE_SHIFT) + i);
if (HYPERVISOR_update_va_mapping(vstart + (i*PAGE_SIZE),
__pte_ma(0), 0))
BUG();
@@ -372,10 +364,6 @@ int xen_create_contiguous_region(
void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order)
{
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
unsigned long *out_frames = discontig_frames, in_frame;
unsigned long frame, i, flags;
long rc;
@@ -397,7 +385,7 @@ void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order)
!test_bit(__pa(vstart) >> PAGE_SHIFT, contiguous_bitmap))
return;
if (order > MAX_CONTIG_ORDER)
if (unlikely(order > MAX_CONTIG_ORDER))
return;
set_xen_guest_handle(exchange.in.extent_start, &in_frame);
@@ -410,16 +398,13 @@ void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order)
contiguous_bitmap_clear(__pa(vstart) >> PAGE_SHIFT, 1UL << order);
/* 1. Find start MFN of contiguous extent. */
pgd = pgd_offset_k(vstart);
pud = pud_offset(pgd, vstart);
pmd = pmd_offset(pud, vstart);
pte = pte_offset_kernel(pmd, vstart);
in_frame = pte_mfn(*pte);
in_frame = pfn_to_mfn(__pa(vstart) >> PAGE_SHIFT);
/* 2. Zap current PTEs. */
for (i = 0; i < (1UL<<order); i++) {
if (HYPERVISOR_update_va_mapping(vstart + (i*PAGE_SIZE),
__pte_ma(0), 0));
__pte_ma(0), 0))
BUG();
set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i,
INVALID_P2M_ENTRY);
out_frames[i] = (__pa(vstart) >> PAGE_SHIFT) + i;
@@ -430,7 +415,7 @@ void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order)
success = (exchange.nr_exchanged == 1);
BUG_ON(!success && ((exchange.nr_exchanged != 0) || (rc == 0)));
BUG_ON(success && (rc != 0));
if (rc == -ENOSYS) {
if (unlikely(rc == -ENOSYS)) {
/* Compatibility when XENMEM_exchange is unsupported. */
if (HYPERVISOR_memory_op(XENMEM_decrease_reservation,
&exchange.in) != 1)
+11 -2
View File
@@ -20,9 +20,18 @@ config TCG_TPM
Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI
and CONFIG_PNPACPI.
config TCG_TIS
tristate "TPM Interface Specification 1.2 Interface"
depends on TCG_TPM
---help---
If you have a TPM security chip that is compliant with the
TCG TIS 1.2 TPM specification say Yes and it will be accessible
from within Linux. To compile this driver as a module, choose
M here; the module will be called tpm_tis.
config TCG_NSC
tristate "National Semiconductor TPM Interface"
depends on TCG_TPM && !XEN_UNPRIVILEGED_GUEST
depends on TCG_TPM && PNPACPI
---help---
If you have a TPM security chip from National Semicondutor
say Yes and it will be accessible from within Linux. To
@@ -31,7 +40,7 @@ config TCG_NSC
config TCG_ATMEL
tristate "Atmel TPM Interface"
depends on TCG_TPM && !XEN_UNPRIVILEGED_GUEST
depends on TCG_TPM
---help---
If you have a TPM security chip from Atmel say Yes and it
will be accessible from within Linux. To compile this driver
@@ -5,6 +5,7 @@ obj-$(CONFIG_TCG_TPM) += tpm.o
ifdef CONFIG_ACPI
obj-$(CONFIG_TCG_TPM) += tpm_bios.o
endif
obj-$(CONFIG_TCG_TIS) += tpm_tis.o
obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
File diff suppressed because it is too large. Load diff
+66 -8
View File
@@ -24,6 +24,14 @@
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#ifdef CONFIG_XEN
enum tpm_bufsize {
TPM_MIN_BUFFERSIZE = 2048,
TPM_MAX_BUFFERSIZE = 64 * 1024,
};
#endif
enum tpm_timeout {
TPM_TIMEOUT = 5, /* msecs */
@@ -41,19 +49,33 @@ extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr,
char *);
extern ssize_t tpm_show_caps(struct device *, struct device_attribute *attr,
char *);
extern ssize_t tpm_show_caps_1_2(struct device *, struct device_attribute *attr,
char *);
extern ssize_t tpm_store_cancel(struct device *, struct device_attribute *attr,
const char *, size_t);
extern ssize_t tpm_show_enabled(struct device *, struct device_attribute *attr,
char *);
extern ssize_t tpm_show_active(struct device *, struct device_attribute *attr,
char *);
extern ssize_t tpm_show_owned(struct device *, struct device_attribute *attr,
char *);
extern ssize_t tpm_show_temp_deactivated(struct device *,
struct device_attribute *attr, char *);
struct tpm_chip;
struct tpm_vendor_specific {
u8 req_complete_mask;
u8 req_complete_val;
u8 req_canceled;
const u8 req_complete_mask;
const u8 req_complete_val;
const u8 req_canceled;
#ifdef CONFIG_XEN
u32 buffersize;
#endif
void __iomem *iobase; /* ioremapped address */
unsigned long base; /* TPM base address */
int irq;
int region_size;
int have_region;
@@ -63,6 +85,13 @@ struct tpm_vendor_specific {
u8 (*status) (struct tpm_chip *);
struct miscdevice miscdev;
struct attribute_group *attr_group;
struct list_head list;
int locality;
unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */
unsigned long duration[3]; /* jiffies */
wait_queue_head_t read_queue;
wait_queue_head_t int_queue;
};
struct tpm_chip {
@@ -75,20 +104,27 @@ struct tpm_chip {
/* Data passed to and from the tpm via the read/write calls */
u8 *data_buffer;
atomic_t data_pending;
#ifdef CONFIG_XEN
atomic_t data_position;
#endif
struct semaphore buffer_mutex;
struct timer_list user_read_timer; /* user needs to claim result */
struct work_struct work;
struct semaphore tpm_mutex; /* tpm is processing */
struct tpm_vendor_specific *vendor;
struct tpm_vendor_specific vendor;
struct dentry **bios_dir;
struct list_head list;
#ifdef CONFIG_XEN
void *priv;
#endif
};
#define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor)
static inline int tpm_read_index(int base, int index)
{
outb(index, base);
@@ -101,13 +137,35 @@ static inline void tpm_write_index(int base, int index, int value)
outb(value & 0xFF, base+1);
}
#ifdef CONFIG_XEN
static inline u32 get_chip_buffersize(struct tpm_chip *chip)
{
return chip->vendor->buffersize;
u32 size = chip->vendor.buffersize;
if (size > TPM_MAX_BUFFERSIZE) {
return TPM_MAX_BUFFERSIZE;
} else if (size < TPM_MIN_BUFFERSIZE) {
return TPM_MIN_BUFFERSIZE;
}
return size;
}
extern int tpm_register_hardware(struct device *,
struct tpm_vendor_specific *);
static inline void *chip_get_private(const struct tpm_chip *chip)
{
return chip->priv;
}
static inline void chip_set_private(struct tpm_chip *chip, void *priv)
{
chip->priv = priv;
}
#endif
extern void tpm_get_timeouts(struct tpm_chip *);
extern void tpm_gen_interrupt(struct tpm_chip *);
extern void tpm_continue_selftest(struct tpm_chip *);
extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32);
extern struct tpm_chip* tpm_register_hardware(struct device *,
const struct tpm_vendor_specific *);
extern int tpm_open(struct inode *, struct file *);
extern int tpm_release(struct inode *, struct file *);
extern ssize_t tpm_write(struct file *, const char __user *, size_t,
@@ -121,7 +179,7 @@ extern int tpm_pm_resume(struct device *);
extern struct dentry ** tpm_bios_log_setup(char *);
extern void tpm_bios_log_teardown(struct dentry **);
#else
static inline struct dentry* tpm_bios_log_setup(char *name)
static inline struct dentry ** tpm_bios_log_setup(char *name)
{
return NULL;
}
@@ -29,8 +29,6 @@ enum {
STATUS_READY = 0x04
};
#define MIN(x,y) ((x) < (y)) ? (x) : (y)
struct transmission {
struct list_head next;
@@ -49,26 +47,6 @@ enum {
TRANSMISSION_FLAG_WAS_QUEUED = 0x1
};
struct vtpm_state {
struct transmission *current_request;
spinlock_t req_list_lock;
wait_queue_head_t req_wait_queue;
struct list_head queued_requests;
struct transmission *current_response;
spinlock_t resp_list_lock;
wait_queue_head_t resp_wait_queue; // processes waiting for responses
struct transmission *req_cancelled; // if a cancellation was encounterd
u8 vd_status;
u8 flags;
unsigned long disconnect_time;
struct tpm_virtual_device *tpmvd;
};
enum {
DATAEX_FLAG_QUEUED_ONLY = 0x1
@@ -76,7 +54,6 @@ enum {
/* local variables */
static struct vtpm_state *vtpms;
/* local function prototypes */
static int _vtpm_send_queued(struct tpm_chip *chip);
@@ -160,11 +137,16 @@ static inline void transmission_free(struct transmission *t)
/*
* Lower layer uses this function to make a response available.
*/
int vtpm_vd_recv(const unsigned char *buffer, size_t count, const void *ptr)
int vtpm_vd_recv(const struct tpm_chip *chip,
const unsigned char *buffer, size_t count,
void *ptr)
{
unsigned long flags;
int ret_size = 0;
struct transmission *t;
struct vtpm_state *vtpms;
vtpms = (struct vtpm_state *)chip_get_private(chip);
/*
* The list with requests must contain one request
@@ -173,26 +155,11 @@ int vtpm_vd_recv(const unsigned char *buffer, size_t count, const void *ptr)
*/
spin_lock_irqsave(&vtpms->resp_list_lock, flags);
if (vtpms->current_request != ptr) {
printk("WARNING: The request pointer is different than the "
"pointer the shared memory driver returned to me. "
"%p != %p\n",
vtpms->current_request, ptr);
}
/*
* If the request has been cancelled, just quit here
*/
if (vtpms->req_cancelled == (struct transmission *)ptr) {
if (vtpms->current_request == vtpms->req_cancelled) {
vtpms->current_request = NULL;
}
transmission_free(vtpms->req_cancelled);
vtpms->req_cancelled = NULL;
spin_unlock_irqrestore(&vtpms->resp_list_lock, flags);
return 0;
}
if (NULL != (t = vtpms->current_request)) {
if ((t = vtpms->current_request)) {
transmission_free(t);
vtpms->current_request = NULL;
}
@@ -217,8 +184,12 @@ int vtpm_vd_recv(const unsigned char *buffer, size_t count, const void *ptr)
/*
* Lower layer indicates its status (connected/disconnected)
*/
void vtpm_vd_status(u8 vd_status)
void vtpm_vd_status(const struct tpm_chip *chip, u8 vd_status)
{
struct vtpm_state *vtpms;
vtpms = (struct vtpm_state *)chip_get_private(chip);
vtpms->vd_status = vd_status;
if ((vtpms->vd_status & TPM_VD_STATUS_CONNECTED) == 0) {
vtpms->disconnect_time = jiffies;
@@ -233,6 +204,9 @@ static int vtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
{
int rc = 0;
unsigned long flags;
struct vtpm_state *vtpms;
vtpms = (struct vtpm_state *)chip_get_private(chip);
/*
* Check if the previous operation only queued the command
@@ -251,7 +225,7 @@ static int vtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
* Return a response of up to 30 '0's.
*/
count = MIN(count, 30);
count = min_t(size_t, count, 30);
memset(buf, 0x0, count);
return count;
}
@@ -270,7 +244,7 @@ static int vtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
if (vtpms->current_response) {
struct transmission *t = vtpms->current_response;
vtpms->current_response = NULL;
rc = MIN(count, t->response_len);
rc = min(count, t->response_len);
memcpy(buf, t->response, rc);
transmission_free(t);
}
@@ -284,6 +258,9 @@ static int vtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
int rc = 0;
unsigned long flags;
struct transmission *t = transmission_alloc();
struct vtpm_state *vtpms;
vtpms = (struct vtpm_state *)chip_get_private(chip);
if (!t)
return -ENOMEM;
@@ -327,8 +304,7 @@ static int vtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
vtpms->current_request = t;
rc = vtpm_vd_send(chip,
vtpms->tpmvd->tpm_private,
rc = vtpm_vd_send(vtpms->tpm_private,
buf,
count,
t);
@@ -373,6 +349,8 @@ static int _vtpm_send_queued(struct tpm_chip *chip)
int error = 0;
long flags;
unsigned char buffer[1];
struct vtpm_state *vtpms;
vtpms = (struct vtpm_state *)chip_get_private(chip);
spin_lock_irqsave(&vtpms->req_list_lock, flags);
@@ -387,8 +365,7 @@ static int _vtpm_send_queued(struct tpm_chip *chip)
vtpms->current_request = qt;
spin_unlock_irqrestore(&vtpms->req_list_lock, flags);
rc = vtpm_vd_send(chip,
vtpms->tpmvd->tpm_private,
rc = vtpm_vd_send(vtpms->tpm_private,
qt->request,
qt->request_len,
qt);
@@ -427,9 +404,21 @@ static int _vtpm_send_queued(struct tpm_chip *chip)
static void vtpm_cancel(struct tpm_chip *chip)
{
unsigned long flags;
struct vtpm_state *vtpms = (struct vtpm_state *)chip_get_private(chip);
spin_lock_irqsave(&vtpms->resp_list_lock,flags);
vtpms->req_cancelled = vtpms->current_request;
if (!vtpms->current_response && vtpms->current_request) {
spin_unlock_irqrestore(&vtpms->resp_list_lock, flags);
interruptible_sleep_on(&vtpms->resp_wait_queue);
spin_lock_irqsave(&vtpms->resp_list_lock,flags);
}
if (vtpms->current_response) {
struct transmission *t = vtpms->current_response;
vtpms->current_response = NULL;
transmission_free(t);
}
spin_unlock_irqrestore(&vtpms->resp_list_lock,flags);
}
@@ -438,6 +427,9 @@ static u8 vtpm_status(struct tpm_chip *chip)
{
u8 rc = 0;
unsigned long flags;
struct vtpm_state *vtpms;
vtpms = (struct vtpm_state *)chip_get_private(chip);
spin_lock_irqsave(&vtpms->resp_list_lock, flags);
/*
@@ -449,7 +441,10 @@ static u8 vtpm_status(struct tpm_chip *chip)
if (vtpms->current_response ||
0 != (vtpms->flags & DATAEX_FLAG_QUEUED_ONLY)) {
rc = STATUS_DATA_AVAIL;
} else if (!vtpms->current_response && !vtpms->current_request) {
rc = STATUS_READY;
}
spin_unlock_irqrestore(&vtpms->resp_list_lock, flags);
return rc;
}
@@ -465,12 +460,21 @@ static struct file_operations vtpm_ops = {
static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated,
NULL);
static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
static DEVICE_ATTR(cancel, S_IWUSR |S_IWGRP, NULL, tpm_store_cancel);
static struct attribute *vtpm_attrs[] = {
&dev_attr_pubek.attr,
&dev_attr_pcrs.attr,
&dev_attr_enabled.attr,
&dev_attr_active.attr,
&dev_attr_owned.attr,
&dev_attr_temp_deactivated.attr,
&dev_attr_caps.attr,
&dev_attr_cancel.attr,
NULL,
@@ -478,6 +482,8 @@ static struct attribute *vtpm_attrs[] = {
static struct attribute_group vtpm_attr_grp = { .attrs = vtpm_attrs };
#define TPM_LONG_TIMEOUT (10 * 60 * HZ)
static struct tpm_vendor_specific tpm_vtpm = {
.recv = vtpm_recv,
.send = vtpm_send,
@@ -486,61 +492,56 @@ static struct tpm_vendor_specific tpm_vtpm = {
.req_complete_mask = STATUS_BUSY | STATUS_DATA_AVAIL,
.req_complete_val = STATUS_DATA_AVAIL,
.req_canceled = STATUS_READY,
.base = 0,
.attr_group = &vtpm_attr_grp,
.miscdev = {
.fops = &vtpm_ops,
},
.duration = {
TPM_LONG_TIMEOUT,
TPM_LONG_TIMEOUT,
TPM_LONG_TIMEOUT,
},
};
static struct platform_device *pdev;
int __init init_vtpm(struct tpm_virtual_device *tvd)
struct tpm_chip *init_vtpm(struct device *dev,
struct tpm_virtual_device *tvd,
struct tpm_private *tp)
{
int rc;
/* vtpms is global - only allow one user */
if (vtpms)
return -EBUSY;
long rc;
struct tpm_chip *chip;
struct vtpm_state *vtpms;
vtpms = kzalloc(sizeof(struct vtpm_state), GFP_KERNEL);
if (!vtpms)
return -ENOMEM;
return ERR_PTR(-ENOMEM);
vtpm_state_init(vtpms);
vtpms->tpmvd = tvd;
pdev = platform_device_register_simple("tpm_vtpm", -1, NULL, 0);
if (IS_ERR(pdev)) {
rc = PTR_ERR(pdev);
goto err_free_mem;
}
vtpms->tpm_private = tp;
if (tvd)
tpm_vtpm.buffersize = tvd->max_tx_size;
if ((rc = tpm_register_hardware(&pdev->dev, &tpm_vtpm)) < 0) {
goto err_unreg_pdev;
chip = tpm_register_hardware(dev, &tpm_vtpm);
if (!chip) {
rc = -ENODEV;
goto err_free_mem;
}
return 0;
chip_set_private(chip, vtpms);
return chip;
err_unreg_pdev:
platform_device_unregister(pdev);
err_free_mem:
kfree(vtpms);
vtpms = NULL;
return rc;
return ERR_PTR(rc);
}
void __exit cleanup_vtpm(void)
void cleanup_vtpm(struct device *dev)
{
struct tpm_chip *chip = dev_get_drvdata(&pdev->dev);
if (chip) {
tpm_remove_hardware(chip->dev);
platform_device_unregister(pdev);
}
struct tpm_chip *chip = dev_get_drvdata(dev);
struct vtpm_state *vtpms = (struct vtpm_state*)chip_get_private(chip);
tpm_remove_hardware(dev);
kfree(vtpms);
vtpms = NULL;
}
@@ -12,6 +12,26 @@ struct tpm_virtual_device {
* for allocation of buffers.
*/
unsigned int max_tx_size;
};
struct vtpm_state {
struct transmission *current_request;
spinlock_t req_list_lock;
wait_queue_head_t req_wait_queue;
struct list_head queued_requests;
struct transmission *current_response;
spinlock_t resp_list_lock;
wait_queue_head_t resp_wait_queue; // processes waiting for responses
u8 vd_status;
u8 flags;
unsigned long disconnect_time;
struct tpm_virtual_device *tpmvd;
/*
* The following is a private structure of the underlying
* driver. It is passed as parameter in the send function.
@@ -19,20 +39,30 @@ struct tpm_virtual_device {
struct tpm_private *tpm_private;
};
enum vdev_status {
TPM_VD_STATUS_DISCONNECTED = 0x0,
TPM_VD_STATUS_CONNECTED = 0x1
};
/* this function is called from tpm_vtpm.c */
int vtpm_vd_send(struct tpm_chip *tc,
struct tpm_private * tp,
int vtpm_vd_send(struct tpm_private * tp,
const u8 * buf, size_t count, void *ptr);
/* these functions are offered by tpm_vtpm.c */
int __init init_vtpm(struct tpm_virtual_device *);
void __exit cleanup_vtpm(void);
int vtpm_vd_recv(const unsigned char *buffer, size_t count, const void *ptr);
void vtpm_vd_status(u8 status);
struct tpm_chip *init_vtpm(struct device *,
struct tpm_virtual_device *,
struct tpm_private *);
void cleanup_vtpm(struct device *);
int vtpm_vd_recv(const struct tpm_chip* chip,
const unsigned char *buffer, size_t count, void *ptr);
void vtpm_vd_status(const struct tpm_chip *, u8 status);
static inline struct tpm_private *tpm_private_from_dev(struct device *dev)
{
struct tpm_chip *chip = dev_get_drvdata(dev);
struct vtpm_state *vtpms = chip_get_private(chip);
return vtpms->tpm_private;
}
#endif
+28 -26
View File
@@ -34,6 +34,7 @@
*/
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/mutex.h>
#include <asm/uaccess.h>
@@ -41,12 +42,15 @@
#include <xen/interface/grant_table.h>
#include <xen/interface/io/tpmif.h>
#include <xen/xenbus.h>
#include "tpm.h"
#include "tpm_vtpm.h"
#undef DEBUG
/* local structures */
struct tpm_private {
struct tpm_chip *chip;
tpmif_tx_interface_t *tx;
atomic_t refcnt;
unsigned int evtchn;
@@ -60,6 +64,7 @@ struct tpm_private {
atomic_t tx_busy;
void *tx_remember;
domid_t backend_id;
wait_queue_head_t wait_q;
@@ -95,6 +100,7 @@ static int tpm_xmit(struct tpm_private *tp,
const u8 * buf, size_t count, int userbuffer,
void *remember);
static void destroy_tpmring(struct tpm_private *tp);
void __exit tpmif_exit(void);
#define DPRINTK(fmt, args...) \
pr_debug("xen_tpm_fr (%s:%d) " fmt, __FUNCTION__, __LINE__, ##args)
@@ -199,8 +205,7 @@ static DEFINE_MUTEX(suspend_lock);
/*
* Send data via this module by calling this function
*/
int vtpm_vd_send(struct tpm_chip *chip,
struct tpm_private *tp,
int vtpm_vd_send(struct tpm_private *tp,
const u8 * buf, size_t count, void *ptr)
{
int sent;
@@ -331,7 +336,7 @@ out:
static void backend_changed(struct xenbus_device *dev,
enum xenbus_state backend_state)
{
struct tpm_private *tp = dev->dev.driver_data;
struct tpm_private *tp = tpm_private_from_dev(&dev->dev);
DPRINTK("\n");
switch (backend_state) {
@@ -358,6 +363,9 @@ static void backend_changed(struct xenbus_device *dev,
}
}
struct tpm_virtual_device tvd = {
.max_tx_size = PAGE_SIZE * TPMIF_TX_RING_SIZE,
};
static int tpmfront_probe(struct xenbus_device *dev,
const struct xenbus_device_id *id)
@@ -369,6 +377,12 @@ static int tpmfront_probe(struct xenbus_device *dev,
if (!tp)
return -ENOMEM;
tp->chip = init_vtpm(&dev->dev, &tvd, tp);
if (IS_ERR(tp->chip)) {
return PTR_ERR(tp->chip);
}
err = xenbus_scanf(XBT_NIL, dev->nodename,
"handle", "%i", &handle);
if (XENBUS_EXIST_ERR(err))
@@ -380,12 +394,10 @@ static int tpmfront_probe(struct xenbus_device *dev,
}
tp->dev = dev;
dev->dev.driver_data = tp;
err = talk_to_backend(dev, tp);
if (err) {
tpm_private_put();
dev->dev.driver_data = NULL;
return err;
}
return 0;
@@ -394,16 +406,16 @@ static int tpmfront_probe(struct xenbus_device *dev,
static int tpmfront_remove(struct xenbus_device *dev)
{
struct tpm_private *tp = (struct tpm_private *)dev->dev.driver_data;
struct tpm_private *tp = tpm_private_from_dev(&dev->dev);
destroy_tpmring(tp);
cleanup_vtpm(&dev->dev);
return 0;
}
static int tpmfront_suspend(struct xenbus_device *dev)
{
struct tpm_private *tp = (struct tpm_private *)dev->dev.driver_data;
struct tpm_private *tp = tpm_private_from_dev(&dev->dev);
u32 ctr;
/* lock, so no app can send */
mutex_lock(&suspend_lock);
tp->is_suspended = 1;
@@ -431,7 +443,7 @@ static int tpmfront_suspend(struct xenbus_device *dev)
static int tpmfront_resume(struct xenbus_device *dev)
{
struct tpm_private *tp = (struct tpm_private *)dev->dev.driver_data;
struct tpm_private *tp = tpm_private_from_dev(&dev->dev);
destroy_tpmring(tp);
return talk_to_backend(dev, tp);
}
@@ -548,7 +560,7 @@ static void tpmif_rx_action(unsigned long priv)
offset += tocopy;
}
vtpm_vd_recv(buffer, received, tp->tx_remember);
vtpm_vd_recv(tp->chip, buffer, received, tp->tx_remember);
kfree(buffer);
exit:
@@ -638,6 +650,7 @@ static int tpm_xmit(struct tpm_private *tp,
atomic_set(&tp->tx_busy, 1);
tp->tx_remember = remember;
mb();
DPRINTK("Notifying backend via event channel %d\n",
@@ -657,9 +670,9 @@ static void tpmif_notify_upperlayer(struct tpm_private *tp)
* to the BE.
*/
if (tp->is_connected) {
vtpm_vd_status(TPM_VD_STATUS_CONNECTED);
vtpm_vd_status(tp->chip, TPM_VD_STATUS_CONNECTED);
} else {
vtpm_vd_status(TPM_VD_STATUS_DISCONNECTED);
vtpm_vd_status(tp->chip, TPM_VD_STATUS_DISCONNECTED);
}
}
@@ -699,13 +712,10 @@ static void tpmif_set_connected_state(struct tpm_private *tp, u8 is_connected)
* =================================================================
*/
struct tpm_virtual_device tvd = {
.max_tx_size = PAGE_SIZE * TPMIF_TX_RING_SIZE,
};
static int __init tpmif_init(void)
{
int rc;
long rc = 0;
struct tpm_private *tp;
if ((xen_start_info->flags & SIF_INITDOMAIN)) {
@@ -718,11 +728,6 @@ static int __init tpmif_init(void)
goto failexit;
}
tvd.tpm_private = tp;
rc = init_vtpm(&tvd);
if (rc)
goto init_vtpm_failed;
IPRINTK("Initialising the vTPM driver.\n");
if ( gnttab_alloc_grant_references ( TPMIF_TX_RING_SIZE,
&gref_head ) < 0) {
@@ -734,19 +739,16 @@ static int __init tpmif_init(void)
return 0;
gnttab_alloc_failed:
cleanup_vtpm();
init_vtpm_failed:
tpm_private_put();
failexit:
return rc;
return (int)rc;
}
static void __exit tpmif_exit(void)
void __exit tpmif_exit(void)
{
exit_tpm_xenbus();
cleanup_vtpm();
tpm_private_put();
gnttab_free_grant_references(gref_head);
}
@@ -75,6 +75,9 @@ DEFINE_SPINLOCK(balloon_lock);
static unsigned long current_pages;
static unsigned long target_pages;
/* We increase/decrease in batches which fit in a page */
static unsigned long frame_list[PAGE_SIZE / sizeof(unsigned long)];
/* VM /proc information for memory */
extern unsigned long totalram_pages;
@@ -96,6 +99,11 @@ static void balloon_process(void *unused);
static DECLARE_WORK(balloon_worker, balloon_process, NULL);
static struct timer_list balloon_timer;
/* When ballooning out (allocating memory to return to Xen) we don't really
want the kernel to try too hard since that can trigger the oom killer. */
#define GFP_BALLOON \
(GFP_HIGHUSER | __GFP_NOWARN | __GFP_NORETRY | __GFP_NOMEMALLOC)
#define PAGE_TO_LIST(p) (&(p)->lru)
#define LIST_TO_PAGE(l) list_entry((l), struct page, lru)
#define UNLIST_PAGE(p) \
@@ -172,7 +180,7 @@ static unsigned long current_target(void)
static int increase_reservation(unsigned long nr_pages)
{
unsigned long *frame_list, frame, pfn, i, flags;
unsigned long pfn, i, flags;
struct page *page;
long rc;
struct xen_memory_reservation reservation = {
@@ -181,15 +189,8 @@ static int increase_reservation(unsigned long nr_pages)
.domid = DOMID_SELF
};
if (nr_pages > (PAGE_SIZE / sizeof(unsigned long)))
nr_pages = PAGE_SIZE / sizeof(unsigned long);
frame_list = (unsigned long *)__get_free_page(GFP_KERNEL);
if (frame_list == NULL) {
frame_list = &frame;
if (nr_pages > 1)
nr_pages = 1;
}
if (nr_pages > ARRAY_SIZE(frame_list))
nr_pages = ARRAY_SIZE(frame_list);
balloon_lock(flags);
@@ -253,15 +254,12 @@ static int increase_reservation(unsigned long nr_pages)
out:
balloon_unlock(flags);
if (frame_list != &frame)
free_page((unsigned long)frame_list);
return 0;
}
static int decrease_reservation(unsigned long nr_pages)
{
unsigned long *frame_list, frame, pfn, i, flags;
unsigned long pfn, i, flags;
struct page *page;
void *v;
int need_sleep = 0;
@@ -272,18 +270,11 @@ static int decrease_reservation(unsigned long nr_pages)
.domid = DOMID_SELF
};
if (nr_pages > (PAGE_SIZE / sizeof(unsigned long)))
nr_pages = PAGE_SIZE / sizeof(unsigned long);
frame_list = (unsigned long *)__get_free_page(GFP_KERNEL);
if (frame_list == NULL) {
frame_list = &frame;
if (nr_pages > 1)
nr_pages = 1;
}
if (nr_pages > ARRAY_SIZE(frame_list))
nr_pages = ARRAY_SIZE(frame_list);
for (i = 0; i < nr_pages; i++) {
if ((page = alloc_page(GFP_HIGHUSER)) == NULL) {
if ((page = alloc_page(GFP_BALLOON)) == NULL) {
nr_pages = i;
need_sleep = 1;
break;
@@ -331,9 +322,6 @@ static int decrease_reservation(unsigned long nr_pages)
balloon_unlock(flags);
if (frame_list != &frame)
free_page((unsigned long)frame_list);
return need_sleep;
}
@@ -76,8 +76,6 @@ static void update_blkif_status(blkif_t *blkif)
* sysfs interface for VBD I/O requests
*/
#ifdef CONFIG_SYSFS
#define VBD_SHOW(name, format, args...) \
static ssize_t show_##name(struct device *_dev, \
struct device_attribute *attr, \
@@ -106,57 +104,40 @@ static struct attribute_group vbdstat_group = {
.attrs = vbdstat_attrs,
};
VBD_SHOW(physical_device, "%x:%x\n", be->major, be->minor);
VBD_SHOW(mode, "%s\n", be->mode);
int xenvbd_sysfs_addif(struct xenbus_device *dev)
{
int error = 0;
int error;
error = sysfs_create_group(&dev->dev.kobj,
&vbdstat_group);
error = device_create_file(&dev->dev, &dev_attr_physical_device);
if (error)
goto fail1;
error = device_create_file(&dev->dev, &dev_attr_mode);
if (error)
goto fail;
goto fail2;
error = sysfs_create_group(&dev->dev.kobj, &vbdstat_group);
if (error)
goto fail3;
return 0;
fail:
sysfs_remove_group(&dev->dev.kobj,
&vbdstat_group);
fail3: sysfs_remove_group(&dev->dev.kobj, &vbdstat_group);
fail2: device_remove_file(&dev->dev, &dev_attr_mode);
fail1: device_remove_file(&dev->dev, &dev_attr_physical_device);
return error;
}
void xenvbd_sysfs_delif(struct xenbus_device *dev)
{
sysfs_remove_group(&dev->dev.kobj,
&vbdstat_group);
sysfs_remove_group(&dev->dev.kobj, &vbdstat_group);
device_remove_file(&dev->dev, &dev_attr_mode);
device_remove_file(&dev->dev, &dev_attr_physical_device);
}
#else
#define xenvbd_sysfs_addif(dev) (0)
#define xenvbd_sysfs_delif(dev) ((void)0)
#endif /* CONFIG_SYSFS */
static ssize_t show_physical_device(struct device *_dev,
struct device_attribute *attr, char *buf)
{
struct xenbus_device *dev = to_xenbus_device(_dev);
struct backend_info *be = dev->dev.driver_data;
return sprintf(buf, "%x:%x\n", be->major, be->minor);
}
DEVICE_ATTR(physical_device, S_IRUSR | S_IRGRP | S_IROTH,
show_physical_device, NULL);
static ssize_t show_mode(struct device *_dev, struct device_attribute *attr,
char *buf)
{
struct xenbus_device *dev = to_xenbus_device(_dev);
struct backend_info *be = dev->dev.driver_data;
return sprintf(buf, "%s\n", be->mode);
}
DEVICE_ATTR(mode, S_IRUSR | S_IRGRP | S_IROTH, show_mode, NULL);
static int blkback_remove(struct xenbus_device *dev)
{
struct backend_info *be = dev->dev.driver_data;
@@ -176,9 +157,8 @@ static int blkback_remove(struct xenbus_device *dev)
be->blkif = NULL;
}
device_remove_file(&dev->dev, &dev_attr_physical_device);
device_remove_file(&dev->dev, &dev_attr_mode);
xenvbd_sysfs_delif(dev);
if (be->major || be->minor)
xenvbd_sysfs_delif(dev);
kfree(be);
dev->dev.driver_data = NULL;
@@ -293,15 +273,18 @@ static void backend_changed(struct xenbus_watch *watch,
err = vbd_create(be->blkif, handle, major, minor,
(NULL == strchr(be->mode, 'w')));
if (err) {
be->major = 0;
be->minor = 0;
be->major = be->minor = 0;
xenbus_dev_fatal(dev, err, "creating vbd structure");
return;
}
device_create_file(&dev->dev, &dev_attr_physical_device);
device_create_file(&dev->dev, &dev_attr_mode);
xenvbd_sysfs_addif(dev);
err = xenvbd_sysfs_addif(dev);
if (err) {
vbd_free(&be->blkif->vbd);
be->major = be->minor = 0;
xenbus_dev_fatal(dev, err, "creating sysfs entries");
return;
}
/* We're potentially connected now */
update_blkif_status(be->blkif);
@@ -267,7 +267,8 @@ void xencons_force_flush(void)
/******************** User-space console driver (/dev/console) ************/
#define DRV(_d) (_d)
#define TTY_INDEX(_tty) ((_tty)->index)
#define DUMMY_TTY(_tty) ((xc_mode != XC_SERIAL) && \
((_tty)->index != (xc_num - 1)))
static struct termios *xencons_termios[MAX_NR_CONSOLES];
static struct termios *xencons_termios_locked[MAX_NR_CONSOLES];
@@ -391,7 +392,7 @@ static void xencons_send_xchar(struct tty_struct *tty, char ch)
{
unsigned long flags;
if (TTY_INDEX(tty) != 0)
if (DUMMY_TTY(tty))
return;
spin_lock_irqsave(&xencons_lock, flags);
@@ -402,7 +403,7 @@ static void xencons_send_xchar(struct tty_struct *tty, char ch)
static void xencons_throttle(struct tty_struct *tty)
{
if (TTY_INDEX(tty) != 0)
if (DUMMY_TTY(tty))
return;
if (I_IXOFF(tty))
@@ -411,7 +412,7 @@ static void xencons_throttle(struct tty_struct *tty)
static void xencons_unthrottle(struct tty_struct *tty)
{
if (TTY_INDEX(tty) != 0)
if (DUMMY_TTY(tty))
return;
if (I_IXOFF(tty)) {
@@ -426,7 +427,7 @@ static void xencons_flush_buffer(struct tty_struct *tty)
{
unsigned long flags;
if (TTY_INDEX(tty) != 0)
if (DUMMY_TTY(tty))
return;
spin_lock_irqsave(&xencons_lock, flags);
@@ -451,7 +452,7 @@ static int xencons_write(
int i;
unsigned long flags;
if (TTY_INDEX(tty) != 0)
if (DUMMY_TTY(tty))
return count;
spin_lock_irqsave(&xencons_lock, flags);
@@ -472,7 +473,7 @@ static void xencons_put_char(struct tty_struct *tty, u_char ch)
{
unsigned long flags;
if (TTY_INDEX(tty) != 0)
if (DUMMY_TTY(tty))
return;
spin_lock_irqsave(&xencons_lock, flags);
@@ -484,7 +485,7 @@ static void xencons_flush_chars(struct tty_struct *tty)
{
unsigned long flags;
if (TTY_INDEX(tty) != 0)
if (DUMMY_TTY(tty))
return;
spin_lock_irqsave(&xencons_lock, flags);
@@ -496,7 +497,7 @@ static void xencons_wait_until_sent(struct tty_struct *tty, int timeout)
{
unsigned long orig_jiffies = jiffies;
if (TTY_INDEX(tty) != 0)
if (DUMMY_TTY(tty))
return;
while (DRV(tty->driver)->chars_in_buffer(tty)) {
@@ -515,7 +516,7 @@ static int xencons_open(struct tty_struct *tty, struct file *filp)
{
unsigned long flags;
if (TTY_INDEX(tty) != 0)
if (DUMMY_TTY(tty))
return 0;
spin_lock_irqsave(&xencons_lock, flags);
@@ -532,7 +533,7 @@ static void xencons_close(struct tty_struct *tty, struct file *filp)
{
unsigned long flags;
if (TTY_INDEX(tty) != 0)
if (DUMMY_TTY(tty))
return;
if (tty->count == 1) {
@@ -588,8 +589,7 @@ static int __init xencons_init(void)
DRV(xencons_driver)->init_termios = tty_std_termios;
DRV(xencons_driver)->flags =
TTY_DRIVER_REAL_RAW |
TTY_DRIVER_RESET_TERMIOS |
TTY_DRIVER_NO_DEVFS;
TTY_DRIVER_RESET_TERMIOS;
DRV(xencons_driver)->termios = xencons_termios;
DRV(xencons_driver)->termios_locked = xencons_termios_locked;
@@ -599,8 +599,8 @@ static int __init xencons_init(void)
DRV(xencons_driver)->name_base = 0 + xc_num;
} else {
DRV(xencons_driver)->name = "tty";
DRV(xencons_driver)->minor_start = xc_num;
DRV(xencons_driver)->name_base = xc_num;
DRV(xencons_driver)->minor_start = 1;
DRV(xencons_driver)->name_base = 1;
}
tty_set_operations(xencons_driver, &xencons_ops);
@@ -615,8 +615,6 @@ static int __init xencons_init(void)
return rc;
}
tty_register_device(xencons_driver, 0, NULL);
if (xen_start_info->flags & SIF_INITDOMAIN) {
xencons_priv_irq = bind_virq_to_irqhandler(
VIRQ_CONSOLE,
@@ -629,8 +627,7 @@ static int __init xencons_init(void)
}
printk("Xen virtual console successfully installed as %s%d\n",
DRV(xencons_driver)->name,
DRV(xencons_driver)->name_base );
DRV(xencons_driver)->name, xc_num);
return 0;
}
@@ -219,7 +219,10 @@ asmlinkage void evtchn_do_upcall(struct pt_regs *regs)
vcpu_info->evtchn_upcall_pending = 0;
/* NB. No need for a barrier here -- XCHG is a barrier on x86. */
#ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */
/* Clear master pending flag /before/ clearing selector flag. */
rmb();
#endif
l1 = xchg(&vcpu_info->evtchn_pending_sel, 0);
while (l1 != 0) {
l1i = __ffs(l1);
@@ -169,7 +169,7 @@ int gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly)
printk(KERN_ALERT "WARNING: g.e. still in use!\n");
return 0;
}
} while ((nflags = synch_cmpxchg(&shared[ref].flags, flags, 0)) !=
} while ((nflags = synch_cmpxchg_subword(&shared[ref].flags, flags, 0)) !=
flags);
return 1;
@@ -224,7 +224,7 @@ unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref)
* reference and return failure (== 0).
*/
while (!((flags = shared[ref].flags) & GTF_transfer_committed)) {
if (synch_cmpxchg(&shared[ref].flags, flags, 0) == flags)
if (synch_cmpxchg_subword(&shared[ref].flags, flags, 0) == flags)
return 0;
cpu_relax();
}
@@ -8,12 +8,14 @@
*/
#include <linux/config.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <asm/hypervisor.h>
#include <xen/features.h>
#include <xen/hypervisor_sysfs.h>
#include <xen/xenbus.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mike D. Day <ncmike@us.ibm.com>");
@@ -97,6 +99,37 @@ static void xen_sysfs_version_destroy(void)
sysfs_remove_group(&hypervisor_subsys.kset.kobj, &version_group);
}
/* UUID */
static ssize_t uuid_show(struct hyp_sysfs_attr *attr, char *buffer)
{
char *vm, *val;
int ret;
vm = xenbus_read(XBT_NIL, "vm", "", NULL);
if (IS_ERR(vm))
return PTR_ERR(vm);
val = xenbus_read(XBT_NIL, vm, "uuid", NULL);
kfree(vm);
if (IS_ERR(val))
return PTR_ERR(val);
ret = sprintf(buffer, "%s\n", val);
kfree(val);
return ret;
}
HYPERVISOR_ATTR_RO(uuid);
static int __init xen_sysfs_uuid_init(void)
{
return sysfs_create_file(&hypervisor_subsys.kset.kobj, &uuid_attr.attr);
}
static void xen_sysfs_uuid_destroy(void)
{
sysfs_remove_file(&hypervisor_subsys.kset.kobj, &uuid_attr.attr);
}
/* xen compilation attributes */
static ssize_t compiler_show(struct hyp_sysfs_attr *attr, char *buffer)
@@ -314,10 +347,15 @@ static int __init hyper_sysfs_init(void)
ret = xen_compilation_init();
if (ret)
goto comp_out;
ret = xen_sysfs_uuid_init();
if (ret)
goto uuid_out;
ret = xen_properties_init();
if (!ret)
goto out;
xen_sysfs_uuid_destroy();
uuid_out:
xen_compilation_destroy();
comp_out:
xen_sysfs_version_destroy();
@@ -331,6 +369,7 @@ static void hyper_sysfs_exit(void)
{
xen_properties_destroy();
xen_compilation_destroy();
xen_sysfs_uuid_destroy();
xen_sysfs_version_destroy();
xen_sysfs_type_destroy();
@@ -496,9 +496,9 @@ static void netbk_tx_err(netif_t *netif, netif_tx_request_t *txp, RING_IDX end)
do {
make_tx_response(netif, txp, NETIF_RSP_ERROR);
if (++cons >= end)
if (cons >= end)
break;
txp = RING_GET_REQUEST(&netif->tx, cons);
txp = RING_GET_REQUEST(&netif->tx, cons++);
} while (1);
netif->tx.req_cons = cons;
netif_schedule_work(netif);
@@ -663,6 +663,57 @@ static void netbk_fill_frags(struct sk_buff *skb)
}
}
int netbk_get_extras(netif_t *netif, struct netif_extra_info *extras,
int work_to_do)
{
struct netif_extra_info *extra;
RING_IDX cons = netif->tx.req_cons;
do {
if (unlikely(work_to_do-- <= 0)) {
DPRINTK("Missing extra info\n");
return -EBADR;
}
extra = (struct netif_extra_info *)
RING_GET_REQUEST(&netif->tx, cons);
if (unlikely(!extra->type ||
extra->type >= XEN_NETIF_EXTRA_TYPE_MAX)) {
netif->tx.req_cons = ++cons;
DPRINTK("Invalid extra type: %d\n", extra->type);
return -EINVAL;
}
memcpy(&extras[extra->type - 1], extra, sizeof(*extra));
netif->tx.req_cons = ++cons;
} while (extra->flags & XEN_NETIF_EXTRA_FLAG_MORE);
return work_to_do;
}
static int netbk_set_skb_gso(struct sk_buff *skb, struct netif_extra_info *gso)
{
if (!gso->u.gso.size) {
DPRINTK("GSO size must not be zero.\n");
return -EINVAL;
}
/* Currently only TCPv4 S.O. is supported. */
if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) {
DPRINTK("Bad GSO type %d.\n", gso->u.gso.type);
return -EINVAL;
}
skb_shinfo(skb)->gso_size = gso->u.gso.size;
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
/* Header must be checked, and gso_segs computed. */
skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
skb_shinfo(skb)->gso_segs = 0;
return 0;
}
/* Called after netfront has transmitted */
static void net_tx_action(unsigned long unused)
{
@@ -670,7 +721,7 @@ static void net_tx_action(unsigned long unused)
struct sk_buff *skb;
netif_t *netif;
netif_tx_request_t txreq;
struct netif_tx_extra txtra;
struct netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX - 1];
u16 pending_idx;
RING_IDX i;
gnttab_map_grant_ref_t *mop;
@@ -732,16 +783,15 @@ static void net_tx_action(unsigned long unused)
work_to_do--;
netif->tx.req_cons = ++i;
memset(extras, 0, sizeof(extras));
if (txreq.flags & NETTXF_extra_info) {
if (work_to_do-- <= 0) {
DPRINTK("Missing extra info\n");
work_to_do = netbk_get_extras(netif, extras,
work_to_do);
i = netif->tx.req_cons;
if (unlikely(work_to_do < 0)) {
netbk_tx_err(netif, &txreq, i);
continue;
}
memcpy(&txtra, RING_GET_REQUEST(&netif->tx, i),
sizeof(txtra));
netif->tx.req_cons = ++i;
}
ret = netbk_count_requests(netif, &txreq, work_to_do);
@@ -751,7 +801,7 @@ static void net_tx_action(unsigned long unused)
}
i += ret;
if (unlikely(ret > MAX_SKB_FRAGS + 1)) {
if (unlikely(ret > MAX_SKB_FRAGS)) {
DPRINTK("Too many frags\n");
netbk_tx_err(netif, &txreq, i);
continue;
@@ -788,10 +838,15 @@ static void net_tx_action(unsigned long unused)
/* Packets passed to netif_rx() must have some headroom. */
skb_reserve(skb, 16);
if (txreq.flags & NETTXF_gso) {
skb_shinfo(skb)->gso_size = txtra.u.gso.size;
skb_shinfo(skb)->gso_segs = txtra.u.gso.segs;
skb_shinfo(skb)->gso_type = txtra.u.gso.type;
if (extras[XEN_NETIF_EXTRA_TYPE_GSO - 1].type) {
struct netif_extra_info *gso;
gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1];
if (netbk_set_skb_gso(skb, gso)) {
kfree_skb(skb);
netbk_tx_err(netif, &txreq, i);
continue;
}
}
gnttab_set_map_op(mop, MMAP_VADDR(pending_idx),
@@ -101,11 +101,14 @@ static int netback_probe(struct xenbus_device *dev,
goto abort_transaction;
}
err = xenbus_printf(xbt, dev->nodename, "feature-tso", "%d", 1);
#if 0 /* KAF: After the protocol is finalised. */
err = xenbus_printf(xbt, dev->nodename, "feature-gso-tcpv4",
"%d", 1);
if (err) {
message = "writing feature-tso";
message = "writing feature-gso-tcpv4";
goto abort_transaction;
}
#endif
err = xenbus_transaction_end(xbt, 0);
} while (err == -EAGAIN);
@@ -463,7 +463,7 @@ static int network_open(struct net_device *dev)
static inline int netfront_tx_slot_available(struct netfront_info *np)
{
return RING_FREE_REQUESTS(&np->tx) >= MAX_SKB_FRAGS + 1;
return RING_FREE_REQUESTS(&np->tx) >= MAX_SKB_FRAGS + 2;
}
static inline void network_maybe_wake_tx(struct net_device *dev)
@@ -491,7 +491,13 @@ static void network_tx_buf_gc(struct net_device *dev)
rmb(); /* Ensure we see responses up to 'rp'. */
for (cons = np->tx.rsp_cons; cons != prod; cons++) {
id = RING_GET_RESPONSE(&np->tx, cons)->id;
struct netif_tx_response *txrsp;
txrsp = RING_GET_RESPONSE(&np->tx, cons);
if (txrsp->status == NETIF_RSP_NULL)
continue;
id = txrsp->id;
skb = np->tx_skbs[id];
if (unlikely(gnttab_query_foreign_access(
np->grant_tx_ref[id]) != 0)) {
@@ -719,6 +725,7 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
unsigned short id;
struct netfront_info *np = netdev_priv(dev);
struct netif_tx_request *tx;
struct netif_extra_info *extra;
char *data = skb->data;
RING_IDX i;
grant_ref_t ref;
@@ -739,7 +746,8 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
spin_lock_irq(&np->tx_lock);
if (unlikely(!netif_carrier_ok(dev) ||
(frags > 1 && !xennet_can_sg(dev)))) {
(frags > 1 && !xennet_can_sg(dev)) ||
netif_needs_gso(dev, skb))) {
spin_unlock_irq(&np->tx_lock);
goto drop;
}
@@ -762,11 +770,30 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
tx->size = len;
tx->flags = 0;
extra = NULL;
if (skb->ip_summed == CHECKSUM_HW) /* local packet? */
tx->flags |= NETTXF_csum_blank | NETTXF_data_validated;
if (skb->proto_data_valid) /* remote but checksummed? */
tx->flags |= NETTXF_data_validated;
if (skb_shinfo(skb)->gso_size) {
struct netif_extra_info *gso = (struct netif_extra_info *)
RING_GET_REQUEST(&np->tx, ++i);
if (extra)
extra->flags |= XEN_NETIF_EXTRA_FLAG_MORE;
else
tx->flags |= NETTXF_extra_info;
gso->u.gso.size = skb_shinfo(skb)->gso_size;
gso->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
gso->type = XEN_NETIF_EXTRA_TYPE_GSO;
gso->flags = 0;
extra = gso;
}
np->tx.req_prod_pvt = i + 1;
xennet_make_frags(skb, dev, tx);
@@ -1065,9 +1092,33 @@ static int xennet_set_sg(struct net_device *dev, u32 data)
return ethtool_op_set_sg(dev, data);
}
static int xennet_set_tso(struct net_device *dev, u32 data)
{
if (data) {
struct netfront_info *np = netdev_priv(dev);
int val;
if (xenbus_scanf(XBT_NIL, np->xbdev->otherend,
"feature-gso-tcpv4", "%d", &val) < 0)
val = 0;
#if 0 /* KAF: After the protocol is finalised. */
if (!val)
#endif
return -ENOSYS;
}
return ethtool_op_set_tso(dev, data);
}
static void xennet_set_features(struct net_device *dev)
{
xennet_set_sg(dev, 1);
/* Turn off all GSO bits except ROBUST. */
dev->features &= (1 << NETIF_F_GSO_SHIFT) - 1;
dev->features |= NETIF_F_GSO_ROBUST;
xennet_set_sg(dev, 0);
if (!xennet_set_sg(dev, 1))
xennet_set_tso(dev, 1);
}
static void network_connect(struct net_device *dev)
@@ -1148,6 +1199,8 @@ static struct ethtool_ops network_ethtool_ops =
.set_tx_csum = ethtool_op_set_tx_csum,
.get_sg = ethtool_op_get_sg,
.set_sg = xennet_set_sg,
.get_tso = ethtool_op_get_tso,
.set_tso = xennet_set_tso,
};
#ifdef CONFIG_SYSFS
@@ -886,29 +886,6 @@ void unregister_xenstore_notifier(struct notifier_block *nb)
EXPORT_SYMBOL_GPL(unregister_xenstore_notifier);
static int all_devices_ready_(struct device *dev, void *data)
{
struct xenbus_device *xendev = to_xenbus_device(dev);
int *result = data;
if (xendev->state != XenbusStateConnected) {
*result = 0;
return 1;
}
return 0;
}
static int all_devices_ready(void)
{
int ready = 1;
bus_for_each_dev(&xenbus_frontend.bus, NULL, &ready,
all_devices_ready_);
return ready;
}
void xenbus_probe(void *unused)
{
BUG_ON((xenstored_ready <= 0));
@@ -1060,6 +1037,43 @@ static int __init xenbus_probe_init(void)
postcore_initcall(xenbus_probe_init);
static int is_disconnected_device(struct device *dev, void *data)
{
struct xenbus_device *xendev = to_xenbus_device(dev);
/*
* A device with no driver will never connect. We care only about
* devices which should currently be in the process of connecting.
*/
if (!dev->driver)
return 0;
return (xendev->state != XenbusStateConnected);
}
static int exists_disconnected_device(void)
{
return bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL,
is_disconnected_device);
}
static int print_device_status(struct device *dev, void *data)
{
struct xenbus_device *xendev = to_xenbus_device(dev);
if (!dev->driver) {
/* Information only: is this too noisy? */
printk(KERN_INFO "XENBUS: Device with no driver: %s\n",
xendev->nodename);
} else if (xendev->state != XenbusStateConnected) {
printk(KERN_WARNING "XENBUS: Timeout connecting "
"to device: %s (state %d)\n",
xendev->nodename, xendev->state);
}
return 0;
}
/*
* On a 10 second timeout, wait for all devices currently configured. We need
* to do this to guarantee that the filesystems and / or network devices
@@ -1081,13 +1095,12 @@ static int __init wait_for_devices(void)
if (!is_running_on_xen())
return -ENODEV;
while (time_before(jiffies, timeout)) {
if (all_devices_ready())
return 0;
while (time_before(jiffies, timeout) && exists_disconnected_device())
schedule_timeout_interruptible(HZ/10);
}
printk(KERN_WARNING "XENBUS: Timeout connecting to devices!\n");
bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL,
print_device_status);
return 0;
}
@@ -138,4 +138,6 @@ static __inline__ int synch_var_test_bit(int nr, volatile void * addr)
synch_const_test_bit((nr),(addr)) : \
synch_var_test_bit((nr),(addr)))
#define synch_cmpxchg_subword synch_cmpxchg
#endif /* __XEN_SYNCH_BITOPS_H__ */
@@ -58,4 +58,6 @@ static __inline__ int synch_var_test_bit(int nr, volatile void * addr)
synch_const_test_bit((nr),(addr)) : \
synch_var_test_bit((nr),(addr)))
#define synch_cmpxchg_subword synch_cmpxchg
#endif /* __XEN_SYNCH_BITOPS_H__ */
@@ -0,0 +1,26 @@
diff -pruN ../pristine-linux-2.6.16.13/kernel/timer.c ./kernel/timer.c
--- ../pristine-linux-2.6.16.13/kernel/timer.c 2006-05-02 22:38:44.000000000 +0100
+++ ./kernel/timer.c 2006-06-29 14:34:12.788957720 +0100
@@ -555,6 +555,22 @@ found:
}
spin_unlock(&base->t_base.lock);
+ /*
+ * It can happen that other CPUs service timer IRQs and increment
+ * jiffies, but we have not yet got a local timer tick to process
+ * the timer wheels. In that case, the expiry time can be before
+ * jiffies, but since the high-resolution timer here is relative to
+ * jiffies, the default expression when high-resolution timers are
+ * not active,
+ *
+ * time_before(MAX_JIFFY_OFFSET + jiffies, expires)
+ *
+ * would falsely evaluate to true. If that is the case, just
+ * return jiffies so that we can immediately fire the local timer
+ */
+ if (time_before(expires, jiffies))
+ return jiffies;
+
if (time_before(hr_expires, expires))
return hr_expires;
+12 -6
View File
@@ -2225,7 +2225,7 @@ index d64e2ec..7494823 100644
err = ipcomp_compress(x, skb);
iph = skb->nh.iph;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 00aa80e..84130c9 100644
index 00aa80e..30c81a8 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -257,6 +257,7 @@ #include <linux/smp_lock.h>
@@ -2281,7 +2281,7 @@ index 00aa80e..84130c9 100644
from += copy;
copied += copy;
@@ -2026,6 +2021,71 @@ int tcp_getsockopt(struct sock *sk, int
@@ -2026,6 +2021,77 @@ int tcp_getsockopt(struct sock *sk, int
}
@@ -2306,13 +2306,19 @@ index 00aa80e..84130c9 100644
+ if (!pskb_may_pull(skb, thlen))
+ goto out;
+
+ segs = NULL;
+ if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST))
+ goto out;
+
+ oldlen = (u16)~skb->len;
+ __skb_pull(skb, thlen);
+
+ if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
+ /* Packet is from an untrusted source, reset gso_segs. */
+ int mss = skb_shinfo(skb)->gso_size;
+
+ skb_shinfo(skb)->gso_segs = (skb->len + mss - 1) / mss;
+
+ segs = NULL;
+ goto out;
+ }
+
+ segs = skb_segment(skb, features);
+ if (IS_ERR(segs))
+ goto out;
File diff suppressed because it is too large. Load diff
@@ -123,6 +123,21 @@ diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.c ./drivers/o
}
}
}
diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.h ./drivers/oprofile/buffer_sync.h
--- ../pristine-linux-2.6.16.13/drivers/oprofile/buffer_sync.h 2006-05-03 05:38:44.000000000 +0800
+++ ./drivers/oprofile/buffer_sync.h 2006-06-27 12:12:09.000000000 +0800
@@ -9,6 +9,11 @@
#ifndef OPROFILE_BUFFER_SYNC_H
#define OPROFILE_BUFFER_SYNC_H
+
+#define NO_DOMAIN_SWITCH -1
+#define DOMAIN_SWITCH_START_EVENT1 0
+#define DOMAIN_SWITCH_START_EVENT2 1
+#define DOMAIN_SWITCH_STOP_EVENT1 2
/* add the necessary profiling hooks */
int sync_start(void);
diff -pru ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.c ./drivers/oprofile/cpu_buffer.c
--- ../pristine-linux-2.6.16.13/drivers/oprofile/cpu_buffer.c 2006-05-03 05:38:44.000000000 +0800
+++ ./drivers/oprofile/cpu_buffer.c 2006-06-19 22:43:53.000000000 +0800
+1 -1
View File
@@ -26,7 +26,7 @@ XEN_SCRIPTS += network-route vif-route
XEN_SCRIPTS += network-nat vif-nat
XEN_SCRIPTS += block
XEN_SCRIPTS += block-enbd block-nbd
XEN_SCRIPTS += vtpm vtpm-delete
XEN_SCRIPTS += vtpm vtpm-delete vtpm-addtodb
XEN_SCRIPTS += xen-hotplug-cleanup
XEN_SCRIPTS += external-device-migrate
XEN_SCRIPT_DATA = xen-script-common.sh locking.sh logging.sh
+10
View File
@@ -0,0 +1,10 @@
#!/bin/sh
# This script must be called with the following parameters to have
# an entry added to the TPM-to-domain associations table in /etc/xen/vtpm.db
# vtpm-addtodb <dom name> <instance number>
dir=$(dirname "$0")
. "$dir/vtpm-common.sh"
vtpmdb_add_instance $1 $2
+3 -10
View File
@@ -347,16 +347,9 @@ function isLocalAddress() {
# 2nd: name of the domain to migrate
# 3rd: the migration step to perform
function vtpm_migration_step() {
local instance res
instance=$(vtpmdb_find_instance $2)
if [ "$instance" == "" ]; then
echo "Error: Translation of domain name ($2) to instance failed. Check /etc/xen/vtpm.db"
log err "Error during translation of domain name"
else
res=$(isLocalAddress $1)
if [ "$res" == "0" ]; then
vtpm_migrate $1 $2 $3
fi
local res=$(isLocalAddress $1)
if [ "$res" == "0" ]; then
vtpm_migrate $1 $2 $3
fi
}
+3 -3
View File
@@ -45,9 +45,9 @@ LDFLAGS = -m32 -nostdlib -Wl,-N -Wl,-Ttext -Wl,$(LOADADDR)
.PHONY: all
all: hvmloader
hvmloader: roms.h hvmloader.c acpi_madt.c
$(CC) $(CFLAGS) -c hvmloader.c acpi_madt.c
$(CC) $(LDFLAGS) -o hvmloader.tmp hvmloader.o acpi_madt.o
hvmloader: roms.h hvmloader.c acpi_madt.c mp_tables.c
$(CC) $(CFLAGS) -c hvmloader.c acpi_madt.c mp_tables.c
$(CC) $(LDFLAGS) -o hvmloader.tmp hvmloader.o acpi_madt.o mp_tables.o
$(OBJCOPY) hvmloader.tmp hvmloader
rm -f hvmloader.tmp
+1 -1
View File
@@ -51,7 +51,7 @@ static int validate_hvm_info(struct hvm_info_table *t)
}
/* xc_vmx_builder wrote hvm info at 0x9F800. Return it. */
static struct hvm_info_table *
struct hvm_info_table *
get_hvm_info_table(void)
{
struct hvm_info_table *t;
+8
View File
@@ -23,6 +23,7 @@
*/
#include "roms.h"
#include "../acpi/acpi2_0.h" /* for ACPI_PHYSICAL_ADDRESS */
#include <xen/hvm/hvm_info_table.h>
/* memory map */
#define VGABIOS_PHYSICAL_ADDRESS 0x000C0000
@@ -71,6 +72,8 @@ asm(
extern int get_acpi_enabled(void);
extern int acpi_madt_update(unsigned char* acpi_start);
extern void create_mp_tables(void);
struct hvm_info_table *get_hvm_info_table(void);
static inline void
outw(unsigned short addr, unsigned short val)
@@ -162,10 +165,15 @@ check_amd(void)
int
main(void)
{
struct hvm_info_table *t = get_hvm_info_table();
puts("HVM Loader\n");
puts("Loading ROMBIOS ...\n");
memcpy((void *)ROMBIOS_PHYSICAL_ADDRESS, rombios, sizeof(rombios));
if (t->apic_enabled)
create_mp_tables();
if (cirrus_check()) {
puts("Loading Cirrus VGABIOS ...\n");
memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
+426
View File
@@ -0,0 +1,426 @@
/*
* mp_tables.c: Dynamically writes MP table info into the ROMBIOS.
*
* In order to work with various VCPU counts, this code reads the VCPU count
* for the HVM partition and creates the correct MP tables for the VCPU count
* and places the information into a predetermined location set aside in the
* ROMBIOS during build time.
*
* Please note that many of the values, such as the CPU's
* family/model/stepping, are hard-coded based upon the values that were used
* in the ROMBIOS and may need to be modified or calculated dynamically to
* correspond with what an HVM guest's CPUID returns.
*
* Travis Betak, travis.betak@amd.com
* Copyright (c) 2006, AMD.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA.
*/
/* FIXME find a header that already has types defined!!! */
typedef unsigned char uint8_t;
typedef signed char int8_t;
typedef unsigned short uint16_t;
typedef signed short int16_t;
typedef unsigned int uint32_t;
typedef signed int int32_t;
#ifdef __i386__
typedef unsigned long long uint64_t;
typedef signed long long int64_t;
#else
typedef unsigned long uint64_t;
typedef signed long int64_t;
#endif
#define ROMBIOS_SEG 0xF000
#define ROMBIOS_BEGIN 0x000F0000
#define ROMBIOS_SIZE 0x00010000
#define ROMBIOS_MAXOFFSET 0x0000FFFF
#define ROMBIOS_END (ROMBIOS_BEGIN + ROMBIOS_SIZE)
/* number of non-processor MP table entries */
#define NR_NONPROC_ENTRIES 18
#define ENTRY_TYPE_PROCESSOR 0
#define ENTRY_TYPE_BUS 1
#define ENTRY_TYPE_IOAPIC 2
#define ENTRY_TYPE_IO_INTR 3
#define ENTRY_TYPE_LOCAL_INTR 4
#define CPU_FLAG_ENABLED 0x01
#define CPU_FLAG_BSP 0x02
/* TODO change this to correspond with what the guest's see's from CPUID */
#define CPU_SIG_FAMILY 0x06
#define CPU_SIG_MODEL 0x00
#define CPU_SIG_STEPPING 0x00
#define CPU_SIGNATURE ((CPU_SIG_FAMILY << 8) \
| (CPU_SIG_MODEL << 4) \
| (CPU_SIG_STEPPING))
#define CPU_FEATURE_FPU (1U << 0)
#define CPU_FEATURE_MCE (1U << 7)
#define CPU_FEATURE_CX8 (1U << 8)
#define CPU_FEATURE_APIC (1U << 9)
#define CPU_FEATURES (CPU_FEATURE_FPU | CPU_FEATURE_APIC)
#define BUS_TYPE_LENGTH 6
#define BUS_TYPE_STR_ISA "ISA "
#define LAPIC_BASE_ADDR 0xFEE00000
#define IOAPIC_VERSION 0x11
#define IOAPIC_BASE_ADDR 0xFEC00000
#define IOAPIC_FLAG_ENABLED (1U << 0)
#define INTR_TYPE_INT 0
#define INTR_TYPE_NMI 1
#define INTR_TYPE_SMI 2
#define INTR_TYPE_EXTINT 3
#define INTR_FLAGS 0
#define INTR_MAX_NR 16
extern int puts(const char *); /* for printing */
extern int get_vcpu_nr(void); /* for the guest's VCPU count */
/*
* The following structures are defined in the MuliProcessor Specifiation v1.4
*/
/* MP Floating Pointer Structure */
struct mp_floating_pointer_struct {
uint8_t signature[4];
uint32_t mp_table;
uint8_t length;
uint8_t revision;
uint8_t checksum;
uint8_t feature[5];
};
/* MP Configuration Table */
struct mp_config_table {
uint8_t signature[4];
uint16_t length;
uint8_t revision;
uint8_t checksum;
uint8_t oem_id[8];
uint8_t vendor_id[12];
uint32_t oem_table;
uint16_t oem_table_sz;
uint16_t nr_entries;
uint32_t lapic;
uint16_t extended_length;
uint8_t extended_checksum;
uint8_t reserved;
};
/* MP Processor Entry */
struct mp_proc_entry {
uint8_t type;
uint8_t lapic_id;
uint8_t lapic_version;
uint8_t cpu_flags;
uint32_t cpu_signature;
uint32_t feature_flags;
uint8_t reserved[8];
};
/* MP Bus Entry */
struct mp_bus_entry {
uint8_t type;
uint8_t bus_id;
uint8_t bus_type_str[6];
};
/* MP IOAPIC Entry */
struct mp_ioapic_entry {
uint8_t type;
uint8_t ioapic_id;
uint8_t ioapic_version;
uint8_t ioapic_flags;
uint32_t ioapic_addr;
};
/* MP IO Interrupt Entry */
struct mp_io_intr_entry {
uint8_t type;
uint8_t intr_type;
uint16_t io_intr_flags;
uint8_t src_bus_id;
uint8_t src_bus_irq;
uint8_t dst_ioapic_id;
uint8_t dst_ioapic_intin;
};
/* MP Local Interrupt Entry */
struct mp_local_intr_entry {
uint8_t type;
uint8_t intr_type;
uint16_t local_intr_flags;
uint8_t src_bus_id;
uint8_t src_bus_irq;
uint8_t dst_lapic_id;
uint8_t dst_lapic_lintin;
};
/*
* fill_mp_config_table - fills in the information for the MP config table
*
* When calculating the length and nr_entries fields, keep in mind that there
* are always 18 non-processor entries and N processor entries
*
* N vcpu entries
* 1 bus entry
* 1 IOAPIC entry
* + 16 IO intr. entries
* ----------------------
* 18 + N total entries
*/
void fill_mp_config_table(struct mp_config_table *mpct)
{
int vcpu_nr;
vcpu_nr = get_vcpu_nr();
/* fill in the MP configuration table signature, "PCMP" */
mpct->signature[0] = 'P';
mpct->signature[1] = 'C';
mpct->signature[2] = 'M';
mpct->signature[3] = 'P';
mpct->length = sizeof(struct mp_config_table)
+ vcpu_nr * sizeof(struct mp_proc_entry)
+ sizeof(struct mp_ioapic_entry)
+ sizeof(struct mp_bus_entry)
+ 16 * sizeof(struct mp_local_intr_entry);
mpct->revision = 4;
/*
* We'll fill in the checksum later after all of the
* entries have been created
*/
mpct->checksum = 0;
/* fill in the OEM ID string, "_HVMCPU_" */
mpct->oem_id[0] = '_'; mpct->oem_id[3] = 'M'; mpct->oem_id[6] = 'U';
mpct->oem_id[1] = 'H'; mpct->oem_id[4] = 'C'; mpct->oem_id[7] = '_';
mpct->oem_id[2] = 'V'; mpct->oem_id[5] = 'P';
/* fill in the Vendor ID string, "XEN " */
mpct->vendor_id[0] = 'X'; mpct->vendor_id[6] = ' ';
mpct->vendor_id[1] = 'E'; mpct->vendor_id[7] = ' ';
mpct->vendor_id[2] = 'N'; mpct->vendor_id[8] = ' ';
mpct->vendor_id[3] = ' '; mpct->vendor_id[9] = ' ';
mpct->vendor_id[4] = ' '; mpct->vendor_id[10] = ' ';
mpct->vendor_id[5] = ' '; mpct->vendor_id[11] = ' ';
mpct->oem_table = 0;
mpct->oem_table_sz = 0;
mpct->nr_entries = vcpu_nr + NR_NONPROC_ENTRIES;
mpct->lapic = LAPIC_BASE_ADDR;
mpct->extended_length = 0;
mpct->extended_checksum = 0;
}
/* calculates the checksum for the MP configuration table */
void fill_mp_config_table_checksum(struct mp_config_table *mpct)
{
int i;
uint8_t checksum;
checksum = 0;
for (i = 0; i < mpct->length; ++i)
checksum += ((uint8_t *)(mpct))[i];
mpct->checksum = -checksum;
}
/* fills in an MP processor entry for VCPU 'vcpu_id' */
void fill_mp_proc_entry(struct mp_proc_entry *mppe, int vcpu_id)
{
mppe->type = ENTRY_TYPE_PROCESSOR;
mppe->lapic_id = vcpu_id;
mppe->lapic_version = 0x11;
mppe->cpu_flags = CPU_FLAG_ENABLED;
if (vcpu_id == 0)
mppe->cpu_flags |= CPU_FLAG_BSP;
mppe->cpu_signature = CPU_SIGNATURE;
mppe->feature_flags = CPU_FEATURES;
}
/* fills in an MP bus entry of type 'type' and bus ID 'bus_id' */
void fill_mp_bus_entry(struct mp_bus_entry *mpbe, int bus_id, const char *type)
{
int i;
mpbe->type = ENTRY_TYPE_BUS;
mpbe->bus_id = bus_id;
for (i = 0; i < BUS_TYPE_LENGTH; ++i)
mpbe->bus_type_str[i] = type[i]; /* FIXME length check? */
}
/* fills in an MP IOAPIC entry for IOAPIC 'ioapic_id' */
void fill_mp_ioapic_entry(struct mp_ioapic_entry *mpie, int ioapic_id)
{
mpie->type = ENTRY_TYPE_IOAPIC;
mpie->ioapic_id = ioapic_id;
mpie->ioapic_version = IOAPIC_VERSION;
mpie->ioapic_flags = IOAPIC_FLAG_ENABLED;
mpie->ioapic_addr = IOAPIC_BASE_ADDR;
}
/* fills in an IO interrupt entry for IOAPIC 'ioapic_id' */
void fill_mp_io_intr_entry(struct mp_io_intr_entry *mpiie,
int src_bus_irq, int ioapic_id, int dst_ioapic_intin)
{
mpiie->type = ENTRY_TYPE_IO_INTR;
mpiie->intr_type = INTR_TYPE_INT;
mpiie->io_intr_flags = INTR_FLAGS;
mpiie->src_bus_id = 0;
mpiie->src_bus_irq = src_bus_irq;
mpiie->dst_ioapic_id = ioapic_id;
mpiie->dst_ioapic_intin = dst_ioapic_intin;
}
/* fill in the mp floating processor structure */
void fill_mpfps(struct mp_floating_pointer_struct *mpfps, uint32_t mpct)
{
int i;
uint8_t checksum;
mpfps->signature[0] = '_';
mpfps->signature[1] = 'M';
mpfps->signature[2] = 'P';
mpfps->signature[3] = '_';
mpfps->mp_table = mpct;
mpfps->length = 1;
mpfps->revision = 4;
mpfps->checksum = 0;
for (i = 0; i < 5; ++i)
mpfps->feature[i] = 0;
/* compute the checksum for our new table */
checksum = 0;
for (i = 0; i < sizeof(struct mp_floating_pointer_struct); ++i)
checksum += ((uint8_t *)(mpfps))[i];
mpfps->checksum = -checksum;
}
/*
* find_mp_table_start - searchs through BIOS memory for '___HVMMP' signature
*
* The '___HVMMP' signature is created by the ROMBIOS and designates a chunk
* of space inside the ROMBIOS that is safe for us to write our MP table info
*/
void* get_mp_table_start(void)
{
char *bios_mem;
for (bios_mem = (char *)ROMBIOS_BEGIN;
bios_mem != (char *)ROMBIOS_END;
++bios_mem)
if (bios_mem[0] == '_' && bios_mem[1] == '_' &&
bios_mem[2] == '_' && bios_mem[3] == 'H' &&
bios_mem[4] == 'V' && bios_mem[5] == 'M' &&
bios_mem[6] == 'M' && bios_mem[7] == 'P')
return bios_mem;
return (void *)-1;
}
/* recalculate the new ROMBIOS checksum after adding MP tables */
void reset_bios_checksum(void)
{
uint32_t i;
uint8_t checksum;
checksum = 0;
for (i = 0; i < ROMBIOS_MAXOFFSET; ++i)
checksum += ((uint8_t *)(ROMBIOS_BEGIN))[i];
*((uint8_t *)(ROMBIOS_BEGIN + ROMBIOS_MAXOFFSET)) = -checksum;
}
/* create_mp_tables - creates MP tables for the guest based upon config data */
void create_mp_tables(void)
{
void *mp_table_base;
char *p;
struct mp_config_table *mp_config_table;
int vcpu_nr;
int i;
vcpu_nr = get_vcpu_nr();
puts("Creating MP tables ...\n");
/* find the 'safe' place in ROMBIOS for the MP tables */
mp_table_base = get_mp_table_start();
if (mp_table_base == (void *)-1) {
puts("Couldn't find start point for MP tables\n");
return;
}
p = mp_table_base;
fill_mp_config_table((struct mp_config_table *)p);
/* save the location of the MP config table for a little later*/
mp_config_table = (struct mp_config_table *)p;
p += sizeof(struct mp_config_table);
for (i = 0; i < vcpu_nr; ++i) {
fill_mp_proc_entry((struct mp_proc_entry *)p, i);
p += sizeof(struct mp_proc_entry);
}
fill_mp_bus_entry((struct mp_bus_entry *)p, 0, BUS_TYPE_STR_ISA);
p += sizeof(struct mp_bus_entry);
fill_mp_ioapic_entry((struct mp_ioapic_entry *)p, vcpu_nr);
p += sizeof(struct mp_ioapic_entry);
for (i = 0; i < INTR_MAX_NR; ++i) {
fill_mp_io_intr_entry((struct mp_io_intr_entry *)p,
i, vcpu_nr, i);
p += sizeof(struct mp_io_intr_entry);
}
/* find the next 16-byte boundary to place the mp floating pointer */
while ((unsigned long)p & 0xF)
++p;
fill_mpfps((struct mp_floating_pointer_struct *)p,
(uint32_t)mp_table_base);
/* calculate the MP configuration table's checksum */
fill_mp_config_table_checksum(mp_config_table);
/* finally, recalculate the ROMBIOS checksum */
reset_bios_checksum();
}
+1 -35
View File
@@ -1,13 +1,9 @@
BIOS_BUILDS = BIOS-bochs-latest
#BIOS_BUILDS += BIOS-bochs-2-processors
#BIOS_BUILDS += BIOS-bochs-4-processors
#BIOS_BUILDS += BIOS-bochs-8-processors
.PHONY: all
all: bios
.PHONY: bios
bios: biossums ${BIOS_BUILDS}
bios: biossums BIOS-bochs-latest
.PHONY: clean
clean:
@@ -26,36 +22,6 @@ BIOS-bochs-latest: rombios.c biossums
./biossums BIOS-bochs-latest
rm -f _rombios_.s
BIOS-bochs-2-processors: rombios.c biossums
gcc -DBX_SMP_PROCESSORS=2 -E -P $< > _rombios2_.c
bcc -o rombios2.s -C-c -D__i86__ -0 -S _rombios2_.c
sed -e 's/^\.text//' -e 's/^\.data//' rombios2.s > _rombios2_.s
as86 _rombios2_.s -b tmp2.bin -u- -w- -g -0 -j -O -l rombios2.txt
-perl makesym.perl < rombios2.txt > rombios2.sym
mv tmp2.bin BIOS-bochs-2-processors
./biossums BIOS-bochs-2-processors
rm -f _rombios2_.s
BIOS-bochs-4-processors: rombios.c biossums
gcc -DBX_SMP_PROCESSORS=4 -E -P $< > _rombios4_.c
bcc -o rombios4.s -C-c -D__i86__ -0 -S _rombios4_.c
sed -e 's/^\.text//' -e 's/^\.data//' rombios4.s > _rombios4_.s
as86 _rombios4_.s -b tmp4.bin -u- -w- -g -0 -j -O -l rombios4.txt
-perl makesym.perl < rombios4.txt > rombios4.sym
mv tmp4.bin BIOS-bochs-4-processors
./biossums BIOS-bochs-4-processors
rm -f _rombios4_.s
BIOS-bochs-8-processors: rombios.c biossums
gcc -DBX_SMP_PROCESSORS=8 -E -P $< > _rombios8_.c
bcc -o rombios8.s -C-c -D__i86__ -0 -S _rombios8_.c
sed -e 's/^\.text//' -e 's/^\.data//' rombios8.s > _rombios8_.s
as86 _rombios8_.s -b tmp8.bin -u- -w- -g -0 -j -O -l rombios8.txt
-perl makesym.perl < rombios8.txt > rombios8.sym
mv tmp8.bin BIOS-bochs-8-processors
./biossums BIOS-bochs-8-processors
rm -f _rombios8_.s
biossums: biossums.c
gcc -o biossums biossums.c
+30
View File
@@ -10514,6 +10514,34 @@ static Bit8u vgafont8[128*8]=
0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00,
};
#ifdef HVMASSIST
//
// MP Tables
// just carve out some blank space for HVMLOADER to write the MP tables to
//
// NOTE: There should be enough space for a 32 processor entry MP table
//
ASM_START
.org 0xcc00
db 0x5F, 0x5F, 0x5F, 0x48, 0x56, 0x4D, 0x4D, 0x50 ;; ___HVMMP
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 64 bytes
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 128 bytes
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 192 bytes
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 256 bytes
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 320 bytes
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 384 bytes
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 448 bytes
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 512 bytes
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 576 bytes
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 640 bytes
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 704 bytes
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 768 bytes
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 832 bytes
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;; 896 bytes
ASM_END
#else // !HVMASSIST
ASM_START
.org 0xcc00
// bcc-generated data will be placed here
@@ -10835,3 +10863,5 @@ db 0,0,0,0 ;; MP feature bytes 2-5.
#endif
ASM_END
#endif // HVMASSIST
+1 -1
View File
@@ -476,6 +476,6 @@ void pci_piix4_acpi_init(PCIBus *bus)
pci_register_io_region((PCIDevice *)d, 4, 0x10,
PCI_ADDRESS_SPACE_IO, acpi_map);
pmtimer_state = pmtimer_init();
/*pmtimer_state = pmtimer_init();*/
acpi_reset (d);
}
+5 -4
View File
@@ -4,6 +4,7 @@
#define ELFSIZE 32
#include <stddef.h>
#include <inttypes.h>
#include "xg_private.h"
#include "xc_elf.h"
#include <stdlib.h>
@@ -188,7 +189,7 @@ static int setup_guest(int xc_handle,
unsigned char e820_map_nr;
struct domain_setup_info dsi;
unsigned long long v_end;
uint64_t v_end;
unsigned long shared_page_frame = 0;
shared_iopage_t *sp;
@@ -208,11 +209,11 @@ static int setup_guest(int xc_handle,
v_end = (unsigned long long)memsize << 20;
IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n"
" Loaded HVM loader: %08lx->%08lx\n"
" TOTAL: %08lx->%016llx\n",
" Loaded HVM loader: %016"PRIx64"->%016"PRIx64"\n"
" TOTAL: %016"PRIx64"->%016"PRIx64"\n",
dsi.v_kernstart, dsi.v_kernend,
dsi.v_start, v_end);
IPRINTF(" ENTRY ADDRESS: %08lx\n", dsi.v_kernentry);
IPRINTF(" ENTRY ADDRESS: %016"PRIx64"\n", dsi.v_kernentry);
if ( (v_end - dsi.v_start) > ((unsigned long long)nr_pages << PAGE_SHIFT) )
{
+10 -10
View File
@@ -13,6 +13,9 @@
#include <inttypes.h>
#include <zlib.h>
/* Handy for printing out '0' prepended values at native pointer size */
#define _p(a) ((void *) ((ulong)a))
#if defined(__i386__)
#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
@@ -519,8 +522,6 @@ static int setup_guest(int xc_handle,
goto error_out;
}
#define _p(a) ((void *) (a))
IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n"
" Loaded kernel: %p->%p\n"
" Init. ramdisk: %p->%p\n"
@@ -795,9 +796,9 @@ static int setup_guest(int xc_handle,
goto error_out;
}
#define NR(_l,_h,_s) \
(((((_h) + ((1UL<<(_s))-1)) & ~((1UL<<(_s))-1)) - \
((_l) & ~((1UL<<(_s))-1))) >> (_s))
#define NR(_l,_h,_s) \
(((((unsigned long)(_h) + ((1UL<<(_s))-1)) & ~((1UL<<(_s))-1)) - \
((unsigned long)(_l) & ~((1UL<<(_s))-1))) >> (_s))
#if defined(__i386__)
if ( dsi.pae_kernel != PAEKERN_no )
{
@@ -826,8 +827,6 @@ static int setup_guest(int xc_handle,
#endif
}
#define _p(a) ((void *) (a))
IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n");
IPRINTF(" Loaded kernel: %p->%p\n", _p(dsi.v_kernstart),
_p(dsi.v_kernend));
@@ -848,8 +847,8 @@ static int setup_guest(int xc_handle,
if ( ((v_end - dsi.v_start)>>PAGE_SHIFT) > nr_pages )
{
PERROR("Initial guest OS requires too much space\n"
"(%luMB is greater than %luMB limit)\n",
(v_end-dsi.v_start)>>20, nr_pages>>(20-PAGE_SHIFT));
"(%pMB is greater than %luMB limit)\n",
_p((v_end-dsi.v_start)>>20), nr_pages>>(20-PAGE_SHIFT));
goto error_out;
}
@@ -1083,7 +1082,8 @@ static int setup_guest(int xc_handle,
if ( hypercall_pfn >= nr_pages )
goto error_out;
op.u.hypercall_init.domain = (domid_t)dom;
op.u.hypercall_init.mfn = page_array[hypercall_pfn];
op.u.hypercall_init.gmfn = shadow_mode_enabled ?
hypercall_pfn : page_array[hypercall_pfn];
op.cmd = DOM0_HYPERCALL_INIT;
if ( xc_dom0_op(xc_handle, &op) )
goto error_out;
+12 -7
View File
@@ -415,11 +415,11 @@ static int suspend_and_state(int (*suspend)(int), int xc_handle, int io_fd,
** which entries do not require canonicalization (in particular, those
** entries which map the virtual address reserved for the hypervisor).
*/
void canonicalize_pagetable(unsigned long type, unsigned long pfn,
const void *spage, void *dpage)
int canonicalize_pagetable(unsigned long type, unsigned long pfn,
const void *spage, void *dpage)
{
int i, pte_last, xen_start, xen_end;
int i, pte_last, xen_start, xen_end, race = 0;
uint64_t pte;
/*
@@ -481,7 +481,8 @@ void canonicalize_pagetable(unsigned long type, unsigned long pfn,
is quite feasible under live migration */
DPRINTF("PT Race: [%08lx,%d] pte=%llx, mfn=%08lx\n",
type, i, (unsigned long long)pte, mfn);
pfn = 0; /* zap it - we'll retransmit this page later */
pfn = 0; /* zap it - we'll retransmit this page later */
race = 1; /* inform the caller of race; fatal if !live */
} else
pfn = mfn_to_pfn(mfn);
@@ -496,7 +497,7 @@ void canonicalize_pagetable(unsigned long type, unsigned long pfn,
}
return;
return race;
}
@@ -567,7 +568,7 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
int rc = 1, i, j, last_iter, iter = 0;
int live = (flags & XCFLAGS_LIVE);
int debug = (flags & XCFLAGS_DEBUG);
int sent_last_iter, skip_this_iter;
int race = 0, sent_last_iter, skip_this_iter;
/* The new domain's shared-info frame number. */
unsigned long shared_info_frame;
@@ -1000,7 +1001,11 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
if (pagetype >= L1TAB && pagetype <= L4TAB) {
/* We have a pagetable page: need to rewrite it. */
canonicalize_pagetable(pagetype, pfn, spage, page);
race =
canonicalize_pagetable(pagetype, pfn, spage, page);
if(race && !live)
goto out;
if (ratewrite(io_fd, page, PAGE_SIZE) != PAGE_SIZE) {
ERR("Error when writing to state file (4)");
+18 -11
View File
@@ -68,7 +68,7 @@ static int parseelfimage(const char *image,
Elf_Ehdr *ehdr = (Elf_Ehdr *)image;
Elf_Phdr *phdr;
Elf_Shdr *shdr;
unsigned long kernstart = ~0UL, kernend=0UL, vaddr, virt_base, elf_pa_off;
Elf_Addr kernstart = ~0, kernend = 0, vaddr, virt_base, elf_pa_off;
const char *shstrtab;
char *guestinfo=NULL, *p;
int h, virt_base_defined, elf_pa_off_defined;
@@ -162,15 +162,19 @@ static int parseelfimage(const char *image,
/* Initial guess for virt_base is 0 if it is not explicitly defined. */
p = strstr(guestinfo, "VIRT_BASE=");
virt_base_defined = (p != NULL);
virt_base = virt_base_defined ? strtoul(p+10, &p, 0) : 0;
virt_base = virt_base_defined ? strtoull(p+10, &p, 0) : 0;
/* Initial guess for elf_pa_off is virt_base if not explicitly defined. */
p = strstr(guestinfo, "ELF_PADDR_OFFSET=");
elf_pa_off_defined = (p != NULL);
elf_pa_off = elf_pa_off_defined ? strtoul(p+17, &p, 0) : virt_base;
elf_pa_off = elf_pa_off_defined ? strtoull(p+17, &p, 0) : virt_base;
if ( elf_pa_off_defined && !virt_base_defined )
goto bad_image;
{
ERROR("Neither ELF_PADDR_OFFSET nor VIRT_BASE found in __xen_guest"
" section.");
return -EINVAL;
}
for ( h = 0; h < ehdr->e_phnum; h++ )
{
@@ -179,7 +183,11 @@ static int parseelfimage(const char *image,
continue;
vaddr = phdr->p_paddr - elf_pa_off + virt_base;
if ( (vaddr + phdr->p_memsz) < vaddr )
goto bad_image;
{
ERROR("ELF program header %d is too large.", h);
return -EINVAL;
}
if ( vaddr < kernstart )
kernstart = vaddr;
if ( (vaddr + phdr->p_memsz) > kernend )
@@ -196,13 +204,16 @@ static int parseelfimage(const char *image,
dsi->v_kernentry = ehdr->e_entry;
if ( (p = strstr(guestinfo, "VIRT_ENTRY=")) != NULL )
dsi->v_kernentry = strtoul(p+11, &p, 0);
dsi->v_kernentry = strtoull(p+11, &p, 0);
if ( (kernstart > kernend) ||
(dsi->v_kernentry < kernstart) ||
(dsi->v_kernentry > kernend) ||
(dsi->v_start > kernstart) )
goto bad_image;
{
ERROR("ELF start or entries are out of bounds.");
return -EINVAL;
}
if ( (p = strstr(guestinfo, "BSD_SYMTAB")) != NULL )
dsi->load_symtab = 1;
@@ -214,10 +225,6 @@ static int parseelfimage(const char *image,
loadelfsymtab(image, 0, 0, NULL, dsi);
return 0;
bad_image:
ERROR("Malformed ELF image.");
return -EINVAL;
}
static int
+1 -1
View File
@@ -26,7 +26,7 @@ unsigned int get_pfn_type(int xc_handle,
{
DECLARE_DOM0_OP;
op.cmd = DOM0_GETPAGEFRAMEINFO;
op.u.getpageframeinfo.mfn = mfn;
op.u.getpageframeinfo.gmfn = mfn;
op.u.getpageframeinfo.domain = (domid_t)dom;
if ( do_dom0_op(xc_handle, &op) < 0 )
{
+6 -6
View File
@@ -132,13 +132,13 @@ typedef unsigned long l4_pgentry_t;
struct domain_setup_info
{
unsigned long v_start;
unsigned long v_end;
unsigned long v_kernstart;
unsigned long v_kernend;
unsigned long v_kernentry;
uint64_t v_start;
uint64_t v_end;
uint64_t v_kernstart;
uint64_t v_kernend;
uint64_t v_kernentry;
unsigned long elf_paddr_offset;
uint64_t elf_paddr_offset;
#define PAEKERN_no 0
#define PAEKERN_yes 1
+1 -1
View File
@@ -43,7 +43,7 @@ MAX_BYTES = 1 << 20 # 1MB
BACKUP_COUNT = 5
STDERR_FORMAT = "[%(name)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s"
LOGFILE_FORMAT = "[%(asctime)s %(name)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s"
LOGFILE_FORMAT = "[%(asctime)s %(name)s %(process)d] %(levelname)s (%(module)s:%(lineno)d) %(message)s"
DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
-2
View File
@@ -22,8 +22,6 @@ import sys
import traceback
import tempfile
import os, stat
import re
import commands
import shutil
import string
from xen.util.security import ACMError, err
-3
View File
@@ -21,11 +21,8 @@
"""
import os
import os.path
import string
import sys
import socket
import commands
import time
import re
import xmlrpclib
-4
View File
@@ -19,10 +19,6 @@
"""
import sys
import traceback
import os
import commands
import shutil
import string
from xen.util.security import ACMError, err, dump_policy
-3
View File
@@ -20,9 +20,6 @@
"""
import sys
import traceback
import os
import commands
import shutil
import string
from xen.util.security import ACMError, err, list_labels, active_policy
from xen.util.security import vm_label_re, res_label_re, all_label_re
-4
View File
@@ -20,10 +20,6 @@
"""
import sys
import traceback
import os
import commands
import shutil
import string
from xen.util.security import ACMError, err, load_policy
+1 -1
View File
@@ -556,7 +556,7 @@ def xm_vcpu_list(args):
def xm_reboot(args):
arg_check(args, "reboot", 1, 4)
arg_check(args, "reboot", 1, 3)
from xen.xm import shutdown
shutdown.main(["shutdown", "-R"] + args)
-4
View File
@@ -19,10 +19,6 @@
"""
import sys
import traceback
import os
import commands
import shutil
import string
from xen.util.security import ACMError, err, make_policy
+2 -3
View File
@@ -17,8 +17,6 @@
"""Domain shutdown.
"""
import string
import sys
import time
from xen.xend.XendClient import server
@@ -92,7 +90,8 @@ def main_all(opts, args):
shutdown(opts, None, mode, opts.vals.wait)
def main_dom(opts, args):
if len(args) < 1: opts.err('Missing domain')
if len(args) == 0: opts.err('No domain parameter given')
if len(args) > 1: opts.err('No multiple domain parameters allowed')
dom = args[0]
mode = shutdown_mode(opts)
shutdown(opts, [ dom ], mode, opts.vals.wait)
+19 -7
View File
@@ -36,6 +36,7 @@ import sys
# constants
NSAMPLES = 100
NDOMAINS = 32
IDLE_DOMAIN = 31 # idle domain's ID
# the struct strings for qos_info
ST_DOM_INFO = "6Q4i32s"
@@ -253,6 +254,14 @@ def display(scr, row, col, str, attr=0):
sys.exit(1)
# diplay domain id
def display_domain_id(scr, row, col, dom):
if dom == IDLE_DOMAIN:
display(scr, row, col-1, "Idle")
else:
display(scr, row, col, "%d" % dom)
# the live monitoring code
def show_livestats(cpu):
ncpu = 1 # number of cpu's on this platform
@@ -361,7 +370,7 @@ def show_livestats(cpu):
# display gotten
row += 1
col = 2
display(stdscr, row, col, "%d" % dom)
display_domain_id(stdscr, row, col, dom)
col += 4
display(stdscr, row, col, "%s" % time_scale(h2[dom][0][0]))
col += 12
@@ -386,7 +395,7 @@ def show_livestats(cpu):
if options.allocated:
row += 1
col = 2
display(stdscr, row, col, "%d" % dom)
display_domain_id(stdscr, row, col, dom)
col += 28
display(stdscr, row, col, "%s/ex" % time_scale(h2[dom][1]))
col += 42
@@ -398,7 +407,7 @@ def show_livestats(cpu):
if options.blocked:
row += 1
col = 2
display(stdscr, row, col, "%d" % dom)
display_domain_id(stdscr, row, col, dom)
col += 4
display(stdscr, row, col, "%s" % time_scale(h2[dom][2][0]))
col += 12
@@ -418,7 +427,7 @@ def show_livestats(cpu):
if options.waited:
row += 1
col = 2
display(stdscr, row, col, "%d" % dom)
display_domain_id(stdscr, row, col, dom)
col += 4
display(stdscr, row, col, "%s" % time_scale(h2[dom][3][0]))
col += 12
@@ -438,7 +447,7 @@ def show_livestats(cpu):
if options.excount:
row += 1
col = 2
display(stdscr, row, col, "%d" % dom)
display_domain_id(stdscr, row, col, dom)
col += 28
display(stdscr, row, col, "%d/s" % h2[dom][4])
@@ -451,7 +460,7 @@ def show_livestats(cpu):
if options.iocount:
row += 1
col = 2
display(stdscr, row, col, "%d" % dom)
display_domain_id(stdscr, row, col, dom)
col += 4
display(stdscr, row, col, "%d/s" % h2[dom][5][0])
col += 24
@@ -558,7 +567,10 @@ def writelog():
curr = last = time.time()
outfiles = {}
for dom in range(0, NDOMAINS):
outfiles[dom] = Delayed("%s-dom%d.log" % (options.prefix, dom), 'w')
if dom == IDLE_DOMAIN:
outfiles[dom] = Delayed("%s-idle.log" % options.prefix, 'w')
else:
outfiles[dom] = Delayed("%s-dom%d.log" % (options.prefix, dom), 'w')
outfiles[dom].delayed_write("# passed cpu dom cpu(tot) cpu(%) cpu/ex allocated/ex blocked(tot) blocked(%) blocked/io waited(tot) waited(%) waited/ex ex/s io(tot) io/ex\n")
while options.duration == 0 or interval < (options.duration * 1000):
+173 -1
View File
@@ -20,6 +20,11 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <linux/compiler.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <xs.h>
#include "xenstat.h"
@@ -36,6 +41,7 @@ struct xenstat_handle {
struct xs_handle *xshandle; /* xenstore handle */
int page_size;
FILE *procnetdev;
DIR *sysfsvbd;
char xen_version[VERSION_SIZE]; /* xen version running on this node */
};
@@ -62,6 +68,8 @@ struct xenstat_domain {
unsigned int ssid;
unsigned int num_networks;
xenstat_network *networks; /* Array of length num_networks */
unsigned int num_vbds;
xenstat_vbd *vbds;
};
struct xenstat_vcpu {
@@ -83,6 +91,15 @@ struct xenstat_network {
unsigned long long tdrop;
};
struct xenstat_vbd {
unsigned int dev;
unsigned long long oo_reqs;
unsigned long long rd_reqs;
unsigned long long wr_reqs;
};
#define SYSFS_VBD_PATH "/sys/devices/xen-backend/"
/*
* Data-collection types
*/
@@ -108,12 +125,15 @@ typedef struct xenstat_collector {
static int xenstat_collect_vcpus(xenstat_node * node);
static int xenstat_collect_networks(xenstat_node * node);
static int xenstat_collect_xen_version(xenstat_node * node);
static int xenstat_collect_vbds(xenstat_node * node);
static void xenstat_free_vcpus(xenstat_node * node);
static void xenstat_free_networks(xenstat_node * node);
static void xenstat_free_xen_version(xenstat_node * node);
static void xenstat_free_vbds(xenstat_node * node);
static void xenstat_uninit_vcpus(xenstat_handle * handle);
static void xenstat_uninit_networks(xenstat_handle * handle);
static void xenstat_uninit_xen_version(xenstat_handle * handle);
static void xenstat_uninit_vbds(xenstat_handle * handle);
static char *xenstat_get_domain_name(xenstat_handle * handle, unsigned int domain_id);
static xenstat_collector collectors[] = {
@@ -122,7 +142,9 @@ static xenstat_collector collectors[] = {
{ XENSTAT_NETWORK, xenstat_collect_networks,
xenstat_free_networks, xenstat_uninit_networks },
{ XENSTAT_XEN_VERSION, xenstat_collect_xen_version,
xenstat_free_xen_version, xenstat_uninit_xen_version }
xenstat_free_xen_version, xenstat_uninit_xen_version },
{ XENSTAT_VBD, xenstat_collect_vbds,
xenstat_free_vbds, xenstat_uninit_vbds }
};
#define NUM_COLLECTORS (sizeof(collectors)/sizeof(xenstat_collector))
@@ -259,6 +281,8 @@ xenstat_node *xenstat_get_node(xenstat_handle * handle, unsigned int flags)
domain->ssid = domaininfo[i].ssidref;
domain->num_networks = 0;
domain->networks = NULL;
domain->num_vbds = 0;
domain->vbds = NULL;
domain++;
}
@@ -451,6 +475,21 @@ xenstat_network *xenstat_domain_network(xenstat_domain * domain,
return NULL;
}
/* Get the number of VBDs for a given domain */
unsigned int xenstat_domain_num_vbds(xenstat_domain * domain)
{
return domain->num_vbds;
}
/* Get the VBD handle to obtain VBD stats */
xenstat_vbd *xenstat_domain_vbd(xenstat_domain * domain,
unsigned int vbd)
{
if (domain->vbds && 0 <= vbd && vbd < domain->num_vbds)
return &(domain->vbds[vbd]);
return NULL;
}
/*
* VCPU functions
*/
@@ -710,6 +749,139 @@ static void xenstat_uninit_xen_version(xenstat_handle * handle)
{
}
/*
* VBD functions
*/
static int read_attributes_vbd(const char *vbd_directory, const char *what, char *ret, int cap)
{
static char file_name[80];
int fd, num_read;
sprintf(file_name, "%s/%s/%s", SYSFS_VBD_PATH, vbd_directory, what);
fd = open(file_name, O_RDONLY, 0);
if (fd==-1) return -1;
num_read = read(fd, ret, cap - 1);
close(fd);
if (num_read<=0) return -1;
ret[num_read] = '\0';
return num_read;
}
/* Collect information about VBDs */
static int xenstat_collect_vbds(xenstat_node * node)
{
struct dirent *dp;
if (node->handle->sysfsvbd == NULL) {
node->handle->sysfsvbd = opendir(SYSFS_VBD_PATH);
if (node->handle->sysfsvbd == NULL) {
perror("Error opening " SYSFS_VBD_PATH);
return 0;
}
}
rewinddir(node->handle->sysfsvbd);
for(dp = readdir(node->handle->sysfsvbd); dp != NULL ;
dp = readdir(node->handle->sysfsvbd)) {
xenstat_domain *domain;
xenstat_vbd vbd;
unsigned int domid;
int ret;
char buf[256];
ret = sscanf(dp->d_name, "vbd-%u-%u", &domid, &vbd.dev);
if (ret != 2) {
continue;
}
printf("%s is VBD.\n",dp->d_name);
domain = xenstat_node_domain(node, domid);
if (domain == NULL) {
fprintf(stderr,
"Found interface vbd-%u-%u but domain %u"
" does not exist.\n",
domid, vbd.dev, domid);
continue;
}
if((read_attributes_vbd(dp->d_name, "statistics/oo_req", buf, 256)<=0)
|| ((ret = sscanf(buf, "%llu", &vbd.oo_reqs)) != 1))
{
continue;
}
if((read_attributes_vbd(dp->d_name, "statistics/rd_req", buf, 256)<=0)
|| ((ret = sscanf(buf, "%llu", &vbd.rd_reqs)) != 1))
{
continue;
}
if((read_attributes_vbd(dp->d_name, "statistics/wr_req", buf, 256)<=0)
|| ((ret = sscanf(buf, "%llu", &vbd.wr_reqs)) != 1))
{
continue;
}
if (domain->vbds == NULL) {
domain->num_vbds = 1;
domain->vbds = malloc(sizeof(xenstat_vbd));
} else {
domain->num_vbds++;
domain->vbds = realloc(domain->vbds,
domain->num_vbds *
sizeof(xenstat_vbd));
}
if (domain->vbds == NULL)
return 0;
domain->vbds[domain->num_vbds - 1] = vbd;
}
return 1;
}
/* Free VBD information */
static void xenstat_free_vbds(xenstat_node * node)
{
unsigned int i;
for (i = 0; i < node->num_domains; i++)
free(node->domains[i].vbds);
}
/* Free VBD information in handle */
static void xenstat_uninit_vbds(xenstat_handle * handle)
{
if (handle->sysfsvbd)
closedir(handle->sysfsvbd);
}
/* Get the major number of VBD device */
unsigned int xenstat_vbd_dev(xenstat_vbd * vbd)
{
return vbd->dev;
}
/* Get the number of OO(Out of) requests */
unsigned long long xenstat_vbd_oo_reqs(xenstat_vbd * vbd)
{
return vbd->oo_reqs;
}
/* Get the number of READ requests */
unsigned long long xenstat_vbd_rd_reqs(xenstat_vbd * vbd)
{
return vbd->rd_reqs;
}
/* Get the number of WRITE requests */
unsigned long long xenstat_vbd_wr_reqs(xenstat_vbd * vbd)
{
return vbd->wr_reqs;
}
static char *xenstat_get_domain_name(xenstat_handle *handle, unsigned int domain_id)
{
char path[80];
+21 -1
View File
@@ -23,6 +23,7 @@ typedef struct xenstat_domain xenstat_domain;
typedef struct xenstat_node xenstat_node;
typedef struct xenstat_vcpu xenstat_vcpu;
typedef struct xenstat_network xenstat_network;
typedef struct xenstat_vbd xenstat_vbd;
/* Initialize the xenstat library. Returns a handle to be used with
* subsequent calls to the xenstat library, or NULL if an error occurs. */
@@ -35,7 +36,8 @@ void xenstat_uninit(xenstat_handle * handle);
#define XENSTAT_VCPU 0x1
#define XENSTAT_NETWORK 0x2
#define XENSTAT_XEN_VERSION 0x4
#define XENSTAT_ALL (XENSTAT_VCPU|XENSTAT_NETWORK|XENSTAT_XEN_VERSION)
#define XENSTAT_VBD 0x8
#define XENSTAT_ALL (XENSTAT_VCPU|XENSTAT_NETWORK|XENSTAT_XEN_VERSION|XENSTAT_VBD)
/* Get all available information about a node */
xenstat_node *xenstat_get_node(xenstat_handle * handle, unsigned int flags);
@@ -117,6 +119,13 @@ unsigned int xenstat_domain_num_networks(xenstat_domain *);
xenstat_network *xenstat_domain_network(xenstat_domain * domain,
unsigned int network);
/* Get the number of VBDs for a given domain */
unsigned int xenstat_domain_num_vbds(xenstat_domain *);
/* Get the VBD handle to obtain VBD stats */
xenstat_vbd *xenstat_domain_vbd(xenstat_domain * domain,
unsigned int vbd);
/*
* VCPU functions - extract information from a xenstat_vcpu
*/
@@ -156,3 +165,14 @@ unsigned long long xenstat_network_terrs(xenstat_network * network);
/* Get the number of transmit drops for this network */
unsigned long long xenstat_network_tdrop(xenstat_network * network);
/*
* VBD functions - extract information from a xen_vbd
*/
/* Get the device number for Virtual Block Device */
unsigned int xenstat_vbd_dev(xenstat_vbd * vbd);
/* Get the number of OO/RD/WR requests for vbd */
unsigned long long xenstat_vbd_oo_reqs(xenstat_vbd * vbd);
unsigned long long xenstat_vbd_rd_reqs(xenstat_vbd * vbd);
unsigned long long xenstat_vbd_wr_reqs(xenstat_vbd * vbd);
+151 -1
View File
@@ -27,6 +27,7 @@
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <linux/kdev_t.h>
#include <xenstat.h>
@@ -65,6 +66,7 @@ static int handle_key(int);
static int compare(unsigned long long, unsigned long long);
static int compare_domains(xenstat_domain **, xenstat_domain **);
static unsigned long long tot_net_bytes( xenstat_domain *, int);
static unsigned long long tot_vbd_reqs( xenstat_domain *, int);
/* Field functions */
static int compare_state(xenstat_domain *domain1, xenstat_domain *domain2);
@@ -91,6 +93,15 @@ static int compare_ssid(xenstat_domain *domain1, xenstat_domain *domain2);
static void print_ssid(xenstat_domain *domain);
static int compare_name(xenstat_domain *domain1, xenstat_domain *domain2);
static void print_name(xenstat_domain *domain);
static int compare_vbds(xenstat_domain *domain1, xenstat_domain *domain2);
static void print_vbds(xenstat_domain *domain);
static int compare_vbd_oo(xenstat_domain *domain1, xenstat_domain *domain2);
static void print_vbd_oo(xenstat_domain *domain);
static int compare_vbd_rd(xenstat_domain *domain1, xenstat_domain *domain2);
static void print_vbd_rd(xenstat_domain *domain);
static int compare_vbd_wr(xenstat_domain *domain1, xenstat_domain *domain2);
static void print_vbd_wr(xenstat_domain *domain);
/* Section printing functions */
static void do_summary(void);
@@ -99,6 +110,7 @@ static void do_bottom_line(void);
static void do_domain(xenstat_domain *);
static void do_vcpu(xenstat_domain *);
static void do_network(xenstat_domain *);
static void do_vbd(xenstat_domain *);
static void top(void);
/* Field types */
@@ -116,6 +128,10 @@ typedef enum field_id {
FIELD_NETS,
FIELD_NET_TX,
FIELD_NET_RX,
FIELD_VBDS,
FIELD_VBD_OO,
FIELD_VBD_RD,
FIELD_VBD_WR,
FIELD_SSID
} field_id;
@@ -140,6 +156,10 @@ field fields[] = {
{ FIELD_NETS, "NETS", 4, compare_nets, print_nets },
{ FIELD_NET_TX, "NETTX(k)", 8, compare_net_tx, print_net_tx },
{ FIELD_NET_RX, "NETRX(k)", 8, compare_net_rx, print_net_rx },
{ FIELD_VBDS, "VBDS", 4, compare_vbds, print_vbds },
{ FIELD_VBD_OO, "VBD_OO", 8, compare_vbd_oo, print_vbd_oo },
{ FIELD_VBD_RD, "VBD_RD", 8, compare_vbd_rd, print_vbd_rd },
{ FIELD_VBD_WR, "VBD_WR", 8, compare_vbd_wr, print_vbd_wr },
{ FIELD_SSID, "SSID", 4, compare_ssid, print_ssid }
};
@@ -158,6 +178,7 @@ unsigned int loop = 1;
unsigned int iterations = 0;
int show_vcpus = 0;
int show_networks = 0;
int show_vbds = 0;
int repeat_header = 0;
#define PROMPT_VAL_LEN 80
char *prompt = NULL;
@@ -180,6 +201,7 @@ static void usage(const char *program)
"-V, --version output version information and exit\n"
"-d, --delay=SECONDS seconds between updates (default 3)\n"
"-n, --networks output vif network data\n"
"-b, --vbds output vbd block device data\n"
"-r, --repeat-header repeat table header before each domain\n"
"-v, --vcpus output vcpu data\n"
"-b, --batch output in batch mode, no user input accepted\n"
@@ -290,6 +312,9 @@ static int handle_key(int ch)
case 'n': case 'N':
show_networks ^= 1;
break;
case 'b': case 'B':
show_vbds ^= 1;
break;
case 'r': case 'R':
repeat_header ^= 1;
break;
@@ -585,6 +610,96 @@ static unsigned long long tot_net_bytes(xenstat_domain *domain, int rx_flag)
return total;
}
/* Compares number of virtual block devices of two domains,
returning -1,0,1 for * <,=,> */
static int compare_vbds(xenstat_domain *domain1, xenstat_domain *domain2)
{
return -compare(xenstat_domain_num_vbds(domain1),
xenstat_domain_num_vbds(domain2));
}
/* Prints number of virtual block devices statistic */
static void print_vbds(xenstat_domain *domain)
{
print("%4u", xenstat_domain_num_vbds(domain));
}
/* Compares number of total VBD OO requests of two domains,
returning -1,0,1 * for <,=,> */
static int compare_vbd_oo(xenstat_domain *domain1, xenstat_domain *domain2)
{
return -compare(tot_vbd_reqs(domain1, FIELD_VBD_OO),
tot_vbd_reqs(domain2, FIELD_VBD_OO));
}
/* Prints number of total VBD OO requests statistic */
static void print_vbd_oo(xenstat_domain *domain)
{
print("%8llu", tot_vbd_reqs(domain, FIELD_VBD_OO));
}
/* Compares number of total VBD READ requests of two domains,
returning -1,0,1 * for <,=,> */
static int compare_vbd_rd(xenstat_domain *domain1, xenstat_domain *domain2)
{
return -compare(tot_vbd_reqs(domain1, FIELD_VBD_RD),
tot_vbd_reqs(domain2, FIELD_VBD_RD));
}
/* Prints number of total VBD READ requests statistic */
static void print_vbd_rd(xenstat_domain *domain)
{
print("%8llu", tot_vbd_reqs(domain, FIELD_VBD_RD));
}
/* Compares number of total VBD WRITE requests of two domains,
returning -1,0,1 * for <,=,> */
static int compare_vbd_wr(xenstat_domain *domain1, xenstat_domain *domain2)
{
return -compare(tot_vbd_reqs(domain1,FIELD_VBD_WR),
tot_vbd_reqs(domain2,FIELD_VBD_WR));
}
/* Prints number of total VBD WRITE requests statistic */
static void print_vbd_wr(xenstat_domain *domain)
{
print("%8llu", tot_vbd_reqs(domain,FIELD_VBD_WR));
}
/* Gets number of total VBD requests statistic,
* if flag is FIELD_VBD_OO, then OO requests,
* if flag is FIELD_VBD_RD, then READ requests and
* if flag is FIELD_VBD_WR, then WRITE requests.
*/
static unsigned long long tot_vbd_reqs(xenstat_domain *domain, int flag)
{
int i = 0;
xenstat_vbd *vbd;
unsigned num_vbds = 0;
unsigned long long total = 0;
num_vbds = xenstat_domain_num_vbds(domain);
for ( i=0 ; i < num_vbds ; i++) {
vbd = xenstat_domain_vbd(domain,i);
switch(flag) {
case FIELD_VBD_OO:
total += xenstat_vbd_oo_reqs(vbd);
break;
case FIELD_VBD_RD:
total += xenstat_vbd_rd_reqs(vbd);
break;
case FIELD_VBD_WR:
total += xenstat_vbd_wr_reqs(vbd);
break;
default:
break;
}
}
return total;
}
/* Compares security id (ssid) of two domains, returning -1,0,1 for <,=,> */
static int compare_ssid(xenstat_domain *domain1, xenstat_domain *domain2)
{
@@ -680,6 +795,13 @@ void do_bottom_line(void)
addch(A_REVERSE | 'N');
attr_addstr(show_networks ? COLOR_PAIR(1) : 0, "etworks");
addstr(" ");
/* VBDs */
attr_addstr(show_vbds ? COLOR_PAIR(1) : 0, "v");
addch(A_REVERSE | 'B');
attr_addstr(show_vbds ? COLOR_PAIR(1) : 0, "ds");
addstr(" ");
/* vcpus */
addch(A_REVERSE | 'V');
@@ -769,6 +891,28 @@ void do_network(xenstat_domain *domain)
}
}
/* Output all VBD information */
void do_vbd(xenstat_domain *domain)
{
int i = 0;
xenstat_vbd *vbd;
unsigned num_vbds = 0;
num_vbds = xenstat_domain_num_vbds(domain);
for (i=0 ; i< num_vbds; i++) {
vbd = xenstat_domain_vbd(domain,i);
print("VBD %4u [%2x:%2x] OO: %8llu RD: %8llu WR: %8llu\n",
xenstat_vbd_dev(vbd),
MAJOR(xenstat_vbd_dev(vbd)), MINOR(xenstat_vbd_dev(vbd)),
xenstat_vbd_oo_reqs(vbd),
xenstat_vbd_rd_reqs(vbd),
xenstat_vbd_wr_reqs(vbd));
}
}
static void top(void)
{
xenstat_domain **domains;
@@ -812,6 +956,8 @@ static void top(void)
do_vcpu(domains[i]);
if (show_networks)
do_network(domains[i]);
if (show_vbds)
do_vbd(domains[i]);
}
if(!batch)
@@ -827,6 +973,7 @@ int main(int argc, char **argv)
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
{ "networks", no_argument, NULL, 'n' },
{ "vbds", no_argument, NULL, 'x' },
{ "repeat-header", no_argument, NULL, 'r' },
{ "vcpus", no_argument, NULL, 'v' },
{ "delay", required_argument, NULL, 'd' },
@@ -834,7 +981,7 @@ int main(int argc, char **argv)
{ "iterations", required_argument, NULL, 'i' },
{ 0, 0, 0, 0 },
};
const char *sopts = "hVbnvd:bi:";
const char *sopts = "hVnxrvd:bi:";
if (atexit(cleanup) != 0)
fail("Failed to install cleanup handler.\n");
@@ -852,6 +999,9 @@ int main(int argc, char **argv)
case 'n':
show_networks = 1;
break;
case 'x':
show_vbds = 1;
break;
case 'r':
repeat_header = 1;
break;
+5 -6
View File
@@ -14,16 +14,15 @@ import os.path
config = {"vtpm":"instance=1,backend=0"}
domain = XmTestDomain(extraConfig=config)
domName = domain.getName()
try:
console = domain.start()
except DomainError, e:
if verbose:
print e.extra
vtpm_cleanup(domain.getName())
FAIL("Unable to create domain")
domName = domain.getName()
vtpm_cleanup(domName)
FAIL("Unable to create domain (%s)" % domName)
try:
console.sendInput("input")
@@ -33,11 +32,11 @@ except ConsoleError, e:
FAIL(str(e))
try:
run = console.runCmd("cat /sys/devices/platform/tpm_vtpm/pcrs")
run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs")
except ConsoleError, e:
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL(str(e))
FAIL("No result from dumping the PCRs")
if re.search("No such file",run["output"]):
vtpm_cleanup(domName)
+50 -44
View File
@@ -15,6 +15,7 @@ import os.path
config = {"vtpm":"instance=1,backend=0"}
domain = XmTestDomain(extraConfig=config)
domName = domain.getName()
consoleHistory = ""
try:
@@ -22,10 +23,8 @@ try:
except DomainError, e:
if verbose:
print e.extra
vtpm_cleanup(domain.getName())
FAIL("Unable to create domain")
domName = domain.getName()
vtpm_cleanup(domName)
FAIL("Unable to create domain (%s)" % domName)
try:
console.sendInput("input")
@@ -35,11 +34,11 @@ except ConsoleError, e:
FAIL(str(e))
try:
run = console.runCmd("cat /sys/devices/platform/tpm_vtpm/pcrs")
run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs")
except ConsoleError, e:
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL(str(e))
FAIL("No result from dumping the PCRs")
if re.search("No such file",run["output"]):
vtpm_cleanup(domName)
@@ -48,50 +47,59 @@ if re.search("No such file",run["output"]):
consoleHistory = console.getHistory()
domain.closeConsole()
try:
status, ouptut = traceCommand("xm save %s %s.save" %
(domName, domName),
timeout=30)
loop = 0
while loop < 3:
try:
status, ouptut = traceCommand("xm save %s %s.save" %
(domName, domName),
timeout=30)
except TimeoutError, e:
saveLog(consoleHistory)
vtpm_cleanup(domName)
FAIL(str(e))
except TimeoutError, e:
saveLog(consoleHistory)
vtpm_cleanup(domName)
FAIL(str(e))
if status != 0:
saveLog(consoleHistory)
vtpm_cleanup(domName)
FAIL("xm save did not succeed")
if status != 0:
saveLog(consoleHistory)
vtpm_cleanup(domName)
FAIL("xm save did not succeed")
try:
status, ouptut = traceCommand("xm restore %s.save" %
(domName),
timeout=30)
except TimeoutError, e:
os.remove("%s.save" % domName)
saveLog(consoleHistory)
vtpm_cleanup(domName)
FAIL(str(e))
try:
status, ouptut = traceCommand("xm restore %s.save" %
(domName),
timeout=30)
except TimeoutError, e:
os.remove("%s.save" % domName)
saveLog(consoleHistory)
vtpm_cleanup(domName)
FAIL(str(e))
os.remove("%s.save" % domName)
if status != 0:
saveLog(consoleHistory)
vtpm_cleanup(domName)
FAIL("xm restore did not succeed")
if status != 0:
saveLog(consoleHistory)
vtpm_cleanup(domName)
FAIL("xm restore did not succeed")
try:
console = domain.getConsole()
except ConsoleError, e:
vtpm_cleanup(domName)
FAIL(str(e))
try:
console = domain.getConsole()
except ConsoleError, e:
vtpm_cleanup(domName)
FAIL(str(e))
try:
run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs")
except ConsoleError, e:
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL(str(e))
try:
run = console.runCmd("cat /sys/devices/platform/tpm_vtpm/pcrs")
except ConsoleError, e:
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL(str(e))
if not re.search("PCR-00:",run["output"]):
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side")
loop += 1
domain.closeConsole()
@@ -99,5 +107,3 @@ domain.stop()
vtpm_cleanup(domName)
if not re.search("PCR-00:",run["output"]):
FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side")
+13 -11
View File
@@ -16,6 +16,7 @@ import os.path
config = {"vtpm":"instance=1,backend=0"}
domain = XmTestDomain(extraConfig=config)
domName = domain.getName()
consoleHistory = ""
try:
@@ -23,10 +24,8 @@ try:
except DomainError, e:
if verbose:
print e.extra
vtpm_cleanup(domain.getName())
FAIL("Unable to create domain")
domName = domain.getName()
vtpm_cleanup(domName)
FAIL("Unable to create domain (%s)" % domName)
try:
console.sendInput("input")
@@ -36,11 +35,11 @@ except ConsoleError, e:
FAIL(str(e))
try:
run = console.runCmd("cat /sys/devices/platform/tpm_vtpm/pcrs")
run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs")
except ConsoleError, e:
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL(str(e))
FAIL("No result from dumping the PCRs")
if re.search("No such file",run["output"]):
vtpm_cleanup(domName)
@@ -83,11 +82,17 @@ while loop < 3:
FAIL(str(e))
try:
run = console.runCmd("cat /sys/devices/platform/tpm_vtpm/pcrs")
run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs")
except ConsoleError, e:
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL(str(e))
FAIL("No result from dumping the PCRs")
if not re.search("PCR-00:",run["output"]):
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side")
loop += 1
domain.closeConsole()
@@ -95,6 +100,3 @@ domain.closeConsole()
domain.stop()
vtpm_cleanup(domName)
if not re.search("PCR-00:",run["output"]):
FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side")
+13 -11
View File
@@ -16,6 +16,7 @@ import os.path
config = {"vtpm":"instance=1,backend=0"}
domain = XmTestDomain(extraConfig=config)
domName = domain.getName()
consoleHistory = ""
try:
@@ -23,10 +24,8 @@ try:
except DomainError, e:
if verbose:
print e.extra
vtpm_cleanup(domain.getName())
FAIL("Unable to create domain")
domName = domain.getName()
vtpm_cleanup(domName)
FAIL("Unable to create domain (%s)" % domName)
try:
console.sendInput("input")
@@ -36,11 +35,11 @@ except ConsoleError, e:
FAIL(str(e))
try:
run = console.runCmd("cat /sys/devices/platform/tpm_vtpm/pcrs")
run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs")
except ConsoleError, e:
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL(str(e))
FAIL("No result from dumping the PCRs")
if re.search("No such file",run["output"]):
vtpm_cleanup(domName)
@@ -83,11 +82,17 @@ while loop < 3:
FAIL(str(e))
try:
run = console.runCmd("cat /sys/devices/platform/tpm_vtpm/pcrs")
run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs")
except ConsoleError, e:
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL(str(e))
FAIL("No result from dumping the PCRs")
if not re.search("PCR-00:",run["output"]):
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side")
loop += 1
domain.closeConsole()
@@ -95,6 +100,3 @@ domain.closeConsole()
domain.stop()
vtpm_cleanup(domName)
if not re.search("PCR-00:",run["output"]):
FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side")
@@ -0,0 +1,139 @@
#!/usr/bin/python
# Copyright (C) International Business Machines Corp., 2006
# Author: Stefan Berger <stefanb@us.ibm.com>
# Positive Test: create domain with virtual TPM attached at build time,
# extend a pcr
# check list of pcrs; suspend and resume the domain and
# check list of pcrs again and validate extended pcr
from XmTestLib import *
from vtpm_utils import *
import commands
import os
import os.path
config = {"vtpm":"instance=1,backend=0"}
domain = XmTestDomain(extraConfig=config)
domName = domain.getName()
consoleHistory = ""
try:
console = domain.start()
except DomainError, e:
if verbose:
print e.extra
vtpm_cleanup(domName)
FAIL("Unable to create domain (%s)" % domName)
try:
console.sendInput("input")
except ConsoleError, e:
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL(str(e))
try:
run = console.runCmd("mknod /dev/tpm0 c 10 224")
except ConsoleError, e:
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL("Error while creating /dev/tpm0")
try:
run = console.runCmd("echo -ne \"\\x00\\xc1\\x00\\x00\\x00\\x22\\x00\\x00\\x00\\x14\\x00\\x00\\x00\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\0xf\\x10\\x11\\x12\\x13\\x14\" > /dev/tpm0")
except ConsoleError, e:
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL("Error while extending PCR 0")
try:
run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs")
except ConsoleError, e:
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL("No result from dumping the PCRs")
if re.search("No such file",run["output"]):
vtpm_cleanup(domName)
FAIL("TPM frontend support not compiled into (domU?) kernel")
if not re.search("PCR-00:",run["output"]):
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side: \n%s" % run["output"])
if not re.search("PCR-00: 1E A7 BD",run["output"]):
saveLog(console.getHistory())
FAIL("Extend did not lead to expected result (1E A7 BD ...): \n%s" % run["output"])
consoleHistory = console.getHistory()
domain.closeConsole()
loop = 0
while loop < 3:
try:
status, ouptut = traceCommand("xm save %s %s.save" %
(domName, domName),
timeout=30)
except TimeoutError, e:
saveLog(consoleHistory)
vtpm_cleanup(domName)
FAIL(str(e))
if status != 0:
saveLog(consoleHistory)
vtpm_cleanup(domName)
FAIL("xm save did not succeed")
try:
status, ouptut = traceCommand("xm restore %s.save" %
(domName),
timeout=30)
except TimeoutError, e:
os.remove("%s.save" % domName)
saveLog(consoleHistory)
vtpm_cleanup(domName)
FAIL(str(e))
os.remove("%s.save" % domName)
if status != 0:
saveLog(consoleHistory)
vtpm_cleanup(domName)
FAIL("xm restore did not succeed")
try:
console = domain.getConsole()
except ConsoleError, e:
vtpm_cleanup(domName)
FAIL(str(e))
try:
run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs")
except ConsoleError, e:
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL(str(e))
if not re.search("PCR-00:",run["output"]):
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side")
if not re.search("PCR-00: 1E A7 BD",run["output"]):
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL("Virtual TPM lost PCR 0 value: \n%s" % run["output"])
loop += 1
domain.closeConsole()
domain.stop()
vtpm_cleanup(domName)
@@ -0,0 +1,132 @@
#!/usr/bin/python
# Copyright (C) International Business Machines Corp., 2006
# Author: Stefan Berger <stefanb@us.ibm.com>
# Positive Test: create domain with virtual TPM attached at build time,
# extend a pcr
# check list of pcrs; locally migrate the domain and
# check list of pcrs again and validate extended pcr
# This test does local live migration.
from XmTestLib import *
from vtpm_utils import *
import commands
import os
import os.path
config = {"vtpm":"instance=1,backend=0"}
domain = XmTestDomain(extraConfig=config)
domName = domain.getName()
consoleHistory = ""
try:
console = domain.start()
except DomainError, e:
if verbose:
print e.extra
vtpm_cleanup(domName)
FAIL("Unable to create domain (%s)" % domName)
try:
console.sendInput("input")
except ConsoleError, e:
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL(str(e))
try:
run = console.runCmd("mknod /dev/tpm0 c 10 224")
except ConsoleError, e:
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL("Error while creating /dev/tpm0")
try:
run = console.runCmd("echo -ne \"\\x00\\xc1\\x00\\x00\\x00\\x22\\x00\\x00\\x00\\x14\\x00\\x00\\x00\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\0xf\\x10\\x11\\x12\\x13\\x14\" > /dev/tpm0")
except ConsoleError, e:
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL("Error while extending PCR 0")
try:
run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs")
except ConsoleError, e:
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL("No result from dumping the PCRs")
if re.search("No such file",run["output"]):
vtpm_cleanup(domName)
FAIL("TPM frontend support not compiled into (domU?) kernel")
if not re.search("PCR-00:",run["output"]):
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side: \n%s" % run["output"])
if not re.search("PCR-00: 1E A7 BD",run["output"]):
saveLog(console.getHistory())
FAIL("Extend did not lead to expected result (1E A7 BD ...): \n%s" % run["output"])
consoleHistory = console.getHistory()
domain.closeConsole()
old_domid = domid(domName)
loop = 0
while loop < 3:
try:
status, ouptut = traceCommand("xm migrate -l %s localhost" %
domName,
timeout=90)
except TimeoutError, e:
saveLog(consoleHistory)
vtpm_cleanup(domName)
FAIL(str(e))
if status != 0:
saveLog(consoleHistory)
vtpm_cleanup(domName)
FAIL("xm migrate did not succeed. External device migration activated?")
domName = domain.getName()
new_domid = domid(domName)
if (old_domid == new_domid):
vtpm_cleanup(domName)
FAIL("xm migrate failed, domain id is still %s (loop=%d)" %
(old_domid,loop))
try:
console = domain.getConsole()
except ConsoleError, e:
vtpm_cleanup(domName)
FAIL(str(e))
try:
run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs")
except ConsoleError, e:
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL("No result from dumping the PCRs")
if not re.search("PCR-00:",run["output"]):
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side")
if not re.search("PCR-00: 1E A7 BD",run["output"]):
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL("Virtual TPM lost PCR 0 value: \n%s" % run["output"])
loop += 1
domain.closeConsole()
domain.stop()
vtpm_cleanup(domName)
@@ -0,0 +1,132 @@
#!/usr/bin/python
# Copyright (C) International Business Machines Corp., 2006
# Author: Stefan Berger <stefanb@us.ibm.com>
# Positive Test: create domain with virtual TPM attached at build time,
# extend a pcr
# check list of pcrs; locally migrate the domain and
# check list of pcrs again and validate extended pcr
# This test does local (non-live) migration.
from XmTestLib import *
from vtpm_utils import *
import commands
import os
import os.path
config = {"vtpm":"instance=1,backend=0"}
domain = XmTestDomain(extraConfig=config)
domName = domain.getName()
consoleHistory = ""
try:
console = domain.start()
except DomainError, e:
if verbose:
print e.extra
vtpm_cleanup(domName)
FAIL("Unable to create domain (%s)" % domName)
try:
console.sendInput("input")
except ConsoleError, e:
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL(str(e))
try:
run = console.runCmd("mknod /dev/tpm0 c 10 224")
except ConsoleError, e:
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL("Error while creating /dev/tpm0")
try:
run = console.runCmd("echo -ne \"\\x00\\xc1\\x00\\x00\\x00\\x22\\x00\\x00\\x00\\x14\\x00\\x00\\x00\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\0xf\\x10\\x11\\x12\\x13\\x14\" > /dev/tpm0")
except ConsoleError, e:
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL("Error while extending PCR 0")
try:
run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs")
except ConsoleError, e:
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL("No result from dumping the PCRs")
if re.search("No such file",run["output"]):
vtpm_cleanup(domName)
FAIL("TPM frontend support not compiled into (domU?) kernel")
if not re.search("PCR-00:",run["output"]):
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side: \n%s" % run["output"])
if not re.search("PCR-00: 1E A7 BD",run["output"]):
saveLog(console.getHistory())
FAIL("Extend did not lead to expected result (1E A7 BD ...): \n%s" % run["output"])
consoleHistory = console.getHistory()
domain.closeConsole()
old_domid = domid(domName)
loop = 0
while loop < 3:
try:
status, ouptut = traceCommand("xm migrate %s localhost" %
domName,
timeout=90)
except TimeoutError, e:
saveLog(consoleHistory)
vtpm_cleanup(domName)
FAIL(str(e))
if status != 0:
saveLog(consoleHistory)
vtpm_cleanup(domName)
FAIL("xm migrate did not succeed. External device migration activated?")
domName = domain.getName()
new_domid = domid(domName)
if (old_domid == new_domid):
vtpm_cleanup(domName)
FAIL("xm migrate failed, domain id is still %s (loop=%d)" %
(old_domid,loop))
try:
console = domain.getConsole()
except ConsoleError, e:
vtpm_cleanup(domName)
FAIL(str(e))
try:
run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs")
except ConsoleError, e:
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL("No result from dumping the PCRs")
if not re.search("PCR-00:",run["output"]):
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL("Virtual TPM is not working correctly on /dev/vtpm on backend side")
if not re.search("PCR-00: 1E A7 BD",run["output"]):
saveLog(console.getHistory())
vtpm_cleanup(domName)
FAIL("Virtual TPM lost PCR 0 value: \n%s" % run["output"])
loop += 1
domain.closeConsole()
domain.stop()
vtpm_cleanup(domName)
+4 -1
View File
@@ -4,7 +4,10 @@ TESTS = 01_vtpm-list_pos.test \
02_vtpm-cat_pcrs.test \
03_vtpm-susp_res.test \
04_vtpm-loc_migr.test \
05_vtpm-loc_migr.test
05_vtpm-loc_migr.test \
06_vtpm-susp_res_pcrs.test \
07_vtpm-mig_pcrs.test \
08_vtpm-mig_pcrs.test
XFAIL_TESTS =
+1 -1
View File
@@ -16,4 +16,4 @@ if output == "":
FAIL("virtual TPM manager must be started to run this test")
def vtpm_cleanup(domName):
traceCommand("/etc/xen/scripts/vtpm-delete %s" % domName)
traceCommand("/etc/xen/scripts/vtpm-delete %s" % domName)
+1 -1
View File
@@ -36,7 +36,7 @@ long arch_do_dom0_op(dom0_op_t *op, XEN_GUEST_HANDLE(dom0_op_t) u_dom0_op)
case DOM0_GETPAGEFRAMEINFO:
{
struct page_info *page;
unsigned long mfn = op->u.getpageframeinfo.mfn;
unsigned long mfn = op->u.getpageframeinfo.gmfn;
domid_t dom = op->u.getpageframeinfo.domain;
struct domain *d;
+5 -5
View File
@@ -425,8 +425,9 @@ void start_kernel(void)
scheduler_init();
idle_vcpu[0] = (struct vcpu*) ia64_r13;
idle_domain = domain_create(IDLE_DOMAIN_ID, 0);
BUG_ON(idle_domain == NULL);
idle_domain = domain_create(IDLE_DOMAIN_ID);
if ( (idle_domain == NULL) || (alloc_vcpu(idle_domain, 0, 0) == NULL) )
BUG();
late_setup_arch(&cmdline);
alloc_dom_xen_and_dom_io();
@@ -503,9 +504,8 @@ printk("num_online_cpus=%d, max_cpus=%d\n",num_online_cpus(),max_cpus);
}
/* Create initial domain 0. */
dom0 = domain_create(0, 0);
if ( dom0 == NULL )
dom0 = domain_create(0);
if ( (dom0 == NULL) || (alloc_vcpu(dom0, 0, 0) == NULL) )
panic("Error creating domain 0\n");
set_bit(_DOMF_privileged, &dom0->domain_flags);
+7 -5
View File
@@ -207,7 +207,7 @@ long arch_do_dom0_op(struct dom0_op *op, XEN_GUEST_HANDLE(dom0_op_t) u_dom0_op)
case DOM0_GETPAGEFRAMEINFO:
{
struct page_info *page;
unsigned long mfn = op->u.getpageframeinfo.mfn;
unsigned long mfn = op->u.getpageframeinfo.gmfn;
domid_t dom = op->u.getpageframeinfo.domain;
struct domain *d;
@@ -407,15 +407,17 @@ long arch_do_dom0_op(struct dom0_op *op, XEN_GUEST_HANDLE(dom0_op_t) u_dom0_op)
case DOM0_HYPERCALL_INIT:
{
struct domain *d;
unsigned long mfn = op->u.hypercall_init.mfn;
struct domain *d = find_domain_by_id(op->u.hypercall_init.domain);
unsigned long gmfn = op->u.hypercall_init.gmfn;
unsigned long mfn;
void *hypercall_page;
ret = -ESRCH;
if ( unlikely((d = find_domain_by_id(
op->u.hypercall_init.domain)) == NULL) )
if ( unlikely(d == NULL) )
break;
mfn = gmfn_to_mfn(d, gmfn);
ret = -EACCES;
if ( !mfn_valid(mfn) ||
!get_page_and_type(mfn_to_page(mfn), d, PGT_writable_page) )
+2 -7
View File
@@ -67,16 +67,11 @@ static void default_idle(void)
void idle_loop(void)
{
int cpu = smp_processor_id();
for ( ; ; )
{
page_scrub_schedule_work();
default_idle();
if ( softirq_pending(cpu) )
do_softirq();
do_softirq();
}
}
@@ -956,7 +951,7 @@ void domain_relinquish_resources(struct domain *d)
}
}
if ( hvm_guest(d->vcpu[0]) )
if ( d->vcpu[0] && hvm_guest(d->vcpu[0]) )
hvm_relinquish_guest_resources(d);
shadow_mode_disable(d);
+45 -44
View File
@@ -962,8 +962,8 @@ static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
!vlapic_global_enabled((VLAPIC(v))) )
{
/* Since the apic is disabled, avoid any confusion
about SMP cpus being available */
clear_bit(X86_FEATURE_APIC, &edx);
about SMP cpus being available */
clear_bit(X86_FEATURE_APIC, &edx);
}
#if CONFIG_PAGING_LEVELS < 3
@@ -974,52 +974,51 @@ static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
if ( v->domain->arch.ops->guest_paging_levels == PAGING_L2 )
{
if ( !v->domain->arch.hvm_domain.pae_enabled )
{
clear_bit(X86_FEATURE_PAE, &edx);
}
clear_bit(X86_FEATURE_PAE, &edx);
clear_bit(X86_FEATURE_PSE, &edx);
clear_bit(X86_FEATURE_PSE36, &edx);
}
#endif
#endif
/* Clear out reserved bits. */
ecx &= ~SVM_VCPU_CPUID_L1_ECX_RESERVED;
edx &= ~SVM_VCPU_CPUID_L1_EDX_RESERVED;
clear_bit(X86_FEATURE_MWAIT & 31, &ecx);
/* Guest should only see one logical processor.
* See details on page 23 of AMD CPUID Specification.
*/
clear_bit(X86_FEATURE_HT, &edx); /* clear the hyperthread bit */
ebx &= 0xFF00FFFF; /* clear the logical processor count when HTT=0 */
ebx |= 0x00010000; /* set to 1 just for precaution */
/* Guest should only see one logical processor.
* See details on page 23 of AMD CPUID Specification.
*/
clear_bit(X86_FEATURE_HT, &edx); /* clear the hyperthread bit */
ebx &= 0xFF00FFFF; /* clear the logical processor count when HTT=0 */
ebx |= 0x00010000; /* set to 1 just for precaution */
/* Disable machine check architecture */
clear_bit(X86_FEATURE_MCA, &edx);
clear_bit(X86_FEATURE_MCE, &edx);
/* Disable machine check architecture */
clear_bit(X86_FEATURE_MCA, &edx);
clear_bit(X86_FEATURE_MCE, &edx);
}
else if ( ( input > 0x00000005 ) && ( input < 0x80000000 ) )
else if ( (input > 0x00000005) && (input < 0x80000000) )
{
eax = ebx = ecx = edx = 0x0;
if ( !cpuid_hypervisor_leaves(input, &eax, &ebx, &ecx, &edx) )
eax = ebx = ecx = edx = 0;
}
else if ( input == 0x80000001 )
{
/* We duplicate some CPUID_00000001 code because many bits of
CPUID_80000001_EDX overlaps with CPUID_00000001_EDX. */
/* We duplicate some CPUID_00000001 code because many bits of
CPUID_80000001_EDX overlaps with CPUID_00000001_EDX. */
if ( !hvm_apic_support(v->domain) ||
!vlapic_global_enabled((VLAPIC(v))) )
!vlapic_global_enabled((VLAPIC(v))) )
{
/* Since the apic is disabled, avoid any confusion
about SMP cpus being available */
clear_bit(X86_FEATURE_APIC, &edx);
about SMP cpus being available */
clear_bit(X86_FEATURE_APIC, &edx);
}
/* Clear the Cmp_Legacy bit
* This bit is supposed to be zero when HTT = 0.
* See details on page 23 of AMD CPUID Specification.
*/
clear_bit(X86_FEATURE_CMP_LEGACY & 31, &ecx);
/* Clear the Cmp_Legacy bit
* This bit is supposed to be zero when HTT = 0.
* See details on page 23 of AMD CPUID Specification.
*/
clear_bit(X86_FEATURE_CMP_LEGACY & 31, &ecx);
#ifdef __i386__
/* Mask feature for Intel ia32e or AMD long mode. */
@@ -1030,7 +1029,7 @@ static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
#endif
#if CONFIG_PAGING_LEVELS < 3
clear_bit(X86_FEATURE_NX & 31, &edx);
clear_bit(X86_FEATURE_NX & 31, &edx);
clear_bit(X86_FEATURE_PAE, &edx);
clear_bit(X86_FEATURE_PSE, &edx);
clear_bit(X86_FEATURE_PSE36, &edx);
@@ -1039,29 +1038,29 @@ static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
{
if ( !v->domain->arch.hvm_domain.pae_enabled )
{
clear_bit(X86_FEATURE_NX & 31, &edx);
clear_bit(X86_FEATURE_PAE, &edx);
clear_bit(X86_FEATURE_NX & 31, &edx);
clear_bit(X86_FEATURE_PAE, &edx);
}
clear_bit(X86_FEATURE_PSE, &edx);
clear_bit(X86_FEATURE_PSE36, &edx);
}
#endif
#endif
/* Make SVM feature invisible to the guest. */
clear_bit(X86_FEATURE_SVME & 31, &ecx);
/* So far, we do not support 3DNow for the guest. */
clear_bit(X86_FEATURE_3DNOW & 31, &edx);
clear_bit(X86_FEATURE_3DNOWEXT & 31, &edx);
/* So far, we do not support 3DNow for the guest. */
clear_bit(X86_FEATURE_3DNOW & 31, &edx);
clear_bit(X86_FEATURE_3DNOWEXT & 31, &edx);
}
else if ( ( input == 0x80000007 ) || ( input == 0x8000000A ) )
{
/* Mask out features of power management and SVM extension. */
eax = ebx = ecx = edx = 0;
/* Mask out features of power management and SVM extension. */
eax = ebx = ecx = edx = 0;
}
else if ( input == 0x80000008 )
{
ecx &= 0xFFFFFF00; /* Make sure Number of CPU core is 1 when HTT=0 */
ecx &= 0xFFFFFF00; /* Make sure Number of CPU core is 1 when HTT=0 */
}
regs->eax = (unsigned long)eax;
@@ -1214,8 +1213,9 @@ static void svm_dr_access (struct vcpu *v, unsigned int reg, unsigned int type,
}
static void svm_get_prefix_info(struct vmcb_struct *vmcb,
unsigned int dir, segment_selector_t **seg, unsigned int *asize)
static void svm_get_prefix_info(
struct vmcb_struct *vmcb,
unsigned int dir, segment_selector_t **seg, unsigned int *asize)
{
unsigned char inst[MAX_INST_LEN];
int i;
@@ -1287,9 +1287,10 @@ static void svm_get_prefix_info(struct vmcb_struct *vmcb,
/* Get the address of INS/OUTS instruction */
static inline int svm_get_io_address(struct vcpu *v,
struct cpu_user_regs *regs, unsigned int dir,
unsigned long *count, unsigned long *addr)
static inline int svm_get_io_address(
struct vcpu *v,
struct cpu_user_regs *regs, unsigned int dir,
unsigned long *count, unsigned long *addr)
{
unsigned long reg;
unsigned int asize = 0;
@@ -2697,9 +2698,9 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs regs)
if (exit_reason == -1)
{
svm_dump_vmcb(__func__, vmcb);
printk("%s: exit_reason == -1 - Did someone clobber the VMCB\n",
__func__);
BUG();
domain_crash_synchronous();
}
+85 -81
View File
@@ -36,38 +36,57 @@
#include <xen/kernel.h>
#include <asm/shadow.h>
#include <xen/keyhandler.h>
#if CONFIG_PAGING_LEVELS >= 3
#include <asm/shadow_64.h>
#endif
int vmcs_size;
static int vmcs_size;
static int vmcs_order;
static u32 vmcs_revision_id;
struct vmcs_struct *vmx_alloc_vmcs(void)
void vmx_init_vmcs_config(void)
{
struct vmcs_struct *vmcs;
u32 vmx_msr_low, vmx_msr_high;
rdmsr(MSR_IA32_VMX_BASIC_MSR, vmx_msr_low, vmx_msr_high);
vmcs_size = vmx_msr_high & 0x1fff;
vmcs = alloc_xenheap_pages(get_order_from_bytes(vmcs_size));
memset((char *)vmcs, 0, vmcs_size); /* don't remove this */
if ( vmcs_size )
return;
rdmsr(MSR_IA32_VMX_BASIC_MSR, vmx_msr_low, vmx_msr_high);
vmcs_revision_id = vmx_msr_low;
vmcs_size = vmx_msr_high & 0x1fff;
vmcs_order = get_order_from_bytes(vmcs_size);
}
static struct vmcs_struct *vmx_alloc_vmcs(void)
{
struct vmcs_struct *vmcs;
if ( (vmcs = alloc_xenheap_pages(vmcs_order)) == NULL )
{
DPRINTK("Failed to allocate VMCS.\n");
return NULL;
}
memset(vmcs, 0, vmcs_size); /* don't remove this */
vmcs->vmcs_revision_id = vmcs_revision_id;
vmcs->vmcs_revision_id = vmx_msr_low;
return vmcs;
}
static void free_vmcs(struct vmcs_struct *vmcs)
static void vmx_free_vmcs(struct vmcs_struct *vmcs)
{
int order;
order = get_order_from_bytes(vmcs_size);
free_xenheap_pages(vmcs, order);
free_xenheap_pages(vmcs, vmcs_order);
}
static void __vmx_clear_vmcs(void *info)
{
struct vcpu *v = info;
__vmpclear(virt_to_maddr(v->arch.hvm_vmx.vmcs));
v->arch.hvm_vmx.active_cpu = -1;
v->arch.hvm_vmx.launched = 0;
}
@@ -127,11 +146,19 @@ void vmx_vmcs_exit(struct vcpu *v)
vcpu_unpause(v);
}
struct vmcs_struct *vmx_alloc_host_vmcs(void)
{
return vmx_alloc_vmcs();
}
void vmx_free_host_vmcs(struct vmcs_struct *vmcs)
{
vmx_free_vmcs(vmcs);
}
static inline int construct_vmcs_controls(struct arch_vmx_struct *arch_vmx)
{
int error = 0;
void *io_bitmap_a;
void *io_bitmap_b;
error |= __vmwrite(PIN_BASED_VM_EXEC_CONTROL,
MONITOR_PIN_BASED_EXEC_CONTROLS);
@@ -140,19 +167,8 @@ static inline int construct_vmcs_controls(struct arch_vmx_struct *arch_vmx)
error |= __vmwrite(VM_ENTRY_CONTROLS, MONITOR_VM_ENTRY_CONTROLS);
/* need to use 0x1000 instead of PAGE_SIZE */
io_bitmap_a = (void*) alloc_xenheap_pages(get_order_from_bytes(0x1000));
io_bitmap_b = (void*) alloc_xenheap_pages(get_order_from_bytes(0x1000));
memset(io_bitmap_a, 0xff, 0x1000);
/* don't bother debug port access */
clear_bit(PC_DEBUG_PORT, io_bitmap_a);
memset(io_bitmap_b, 0xff, 0x1000);
error |= __vmwrite(IO_BITMAP_A, (u64) virt_to_maddr(io_bitmap_a));
error |= __vmwrite(IO_BITMAP_B, (u64) virt_to_maddr(io_bitmap_b));
arch_vmx->io_bitmap_a = io_bitmap_a;
arch_vmx->io_bitmap_b = io_bitmap_b;
error |= __vmwrite(IO_BITMAP_A, (u64)virt_to_maddr(arch_vmx->io_bitmap_a));
error |= __vmwrite(IO_BITMAP_B, (u64)virt_to_maddr(arch_vmx->io_bitmap_b));
return error;
}
@@ -428,84 +444,71 @@ static inline int construct_vmcs_host(void)
}
/*
* Need to extend to support full virtualization.
* the working VMCS pointer has been set properly
* just before entering this function.
*/
static int construct_vmcs(struct vcpu *v,
cpu_user_regs_t *regs)
{
struct arch_vmx_struct *arch_vmx = &v->arch.hvm_vmx;
int error;
long rc;
memset(arch_vmx, 0, sizeof(struct arch_vmx_struct));
spin_lock_init(&arch_vmx->vmcs_lock);
arch_vmx->active_cpu = -1;
/*
* Create a new VMCS
*/
if (!(arch_vmx->vmcs = vmx_alloc_vmcs())) {
printk("Failed to create a new VMCS\n");
return -ENOMEM;
}
vmx_clear_vmcs(v);
vmx_load_vmcs(v);
if ((error = construct_vmcs_controls(arch_vmx))) {
printk("construct_vmcs: construct_vmcs_controls failed\n");
rc = -EINVAL;
goto err_out;
if ( (error = construct_vmcs_controls(arch_vmx)) ) {
printk("construct_vmcs: construct_vmcs_controls failed.\n");
return error;
}
/* host selectors */
if ((error = construct_vmcs_host())) {
printk("construct_vmcs: construct_vmcs_host failed\n");
rc = -EINVAL;
goto err_out;
if ( (error = construct_vmcs_host()) ) {
printk("construct_vmcs: construct_vmcs_host failed.\n");
return error;
}
/* guest selectors */
if ((error = construct_init_vmcs_guest(regs))) {
printk("construct_vmcs: construct_vmcs_guest failed\n");
rc = -EINVAL;
goto err_out;
if ( (error = construct_init_vmcs_guest(regs)) ) {
printk("construct_vmcs: construct_vmcs_guest failed.\n");
return error;
}
if ((error |= __vmwrite(EXCEPTION_BITMAP,
MONITOR_DEFAULT_EXCEPTION_BITMAP))) {
printk("construct_vmcs: setting Exception bitmap failed\n");
rc = -EINVAL;
goto err_out;
if ( (error = __vmwrite(EXCEPTION_BITMAP,
MONITOR_DEFAULT_EXCEPTION_BITMAP)) ) {
printk("construct_vmcs: setting exception bitmap failed.\n");
return error;
}
if (regs->eflags & EF_TF)
__vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
if ( regs->eflags & EF_TF )
error = __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
else
__vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
error = __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
return error;
}
int vmx_create_vmcs(struct vcpu *v)
{
if ( (v->arch.hvm_vmx.vmcs = vmx_alloc_vmcs()) == NULL )
return -ENOMEM;
__vmx_clear_vmcs(v);
return 0;
err_out:
vmx_destroy_vmcs(v);
return rc;
}
void vmx_destroy_vmcs(struct vcpu *v)
{
struct arch_vmx_struct *arch_vmx = &v->arch.hvm_vmx;
if ( arch_vmx->vmcs == NULL )
return;
vmx_clear_vmcs(v);
free_vmcs(arch_vmx->vmcs);
arch_vmx->vmcs = NULL;
free_xenheap_pages(arch_vmx->io_bitmap_a, IO_BITMAP_ORDER);
free_xenheap_pages(arch_vmx->io_bitmap_b, IO_BITMAP_ORDER);
free_xenheap_pages(arch_vmx->io_bitmap_a, get_order_from_bytes(0x1000));
arch_vmx->io_bitmap_a = NULL;
free_xenheap_pages(arch_vmx->io_bitmap_b, get_order_from_bytes(0x1000));
arch_vmx->io_bitmap_b = NULL;
vmx_free_vmcs(arch_vmx->vmcs);
arch_vmx->vmcs = NULL;
}
void vm_launch_fail(unsigned long eflags)
@@ -544,19 +547,20 @@ void arch_vmx_do_resume(struct vcpu *v)
void arch_vmx_do_launch(struct vcpu *v)
{
int error;
cpu_user_regs_t *regs = &current->arch.guest_context.user_regs;
error = construct_vmcs(v, regs);
if ( error < 0 )
vmx_load_vmcs(v);
if ( construct_vmcs(v, regs) < 0 )
{
if (v->vcpu_id == 0) {
printk("Failed to construct a new VMCS for BSP.\n");
if ( v->vcpu_id == 0 ) {
printk("Failed to construct VMCS for BSP.\n");
} else {
printk("Failed to construct a new VMCS for AP %d\n", v->vcpu_id);
printk("Failed to construct VMCS for AP %d.\n", v->vcpu_id);
}
domain_crash_synchronous();
}
vmx_do_launch(v);
reset_stack_and_jump(vmx_asm_do_vmentry);
}
+111 -53
View File
@@ -54,34 +54,73 @@ static unsigned long trace_values[NR_CPUS][5];
static void vmx_ctxt_switch_from(struct vcpu *v);
static void vmx_ctxt_switch_to(struct vcpu *v);
void vmx_final_setup_guest(struct vcpu *v)
static int vmx_initialize_guest_resources(struct vcpu *v)
{
struct domain *d = v->domain;
struct vcpu *vc;
void *io_bitmap_a, *io_bitmap_b;
int rc;
v->arch.schedule_tail = arch_vmx_do_launch;
v->arch.ctxt_switch_from = vmx_ctxt_switch_from;
v->arch.ctxt_switch_to = vmx_ctxt_switch_to;
if ( v->vcpu_id == 0 )
if ( v->vcpu_id != 0 )
return 1;
for_each_vcpu ( d, vc )
{
struct domain *d = v->domain;
struct vcpu *vc;
/* Initialize monitor page table */
for_each_vcpu(d, vc)
vc->arch.monitor_table = pagetable_null();
vc->arch.monitor_table = pagetable_null();
/*
* Required to do this once per domain
* XXX todo: add a seperate function to do these.
*/
memset(&d->shared_info->evtchn_mask[0], 0xff,
sizeof(d->shared_info->evtchn_mask));
memset(&vc->arch.hvm_vmx, 0, sizeof(struct arch_vmx_struct));
/* Put the domain in shadow mode even though we're going to be using
* the shared 1:1 page table initially. It shouldn't hurt */
shadow_mode_enable(d,
SHM_enable|SHM_refcounts|
SHM_translate|SHM_external|SHM_wr_pt_pte);
if ( (rc = vmx_create_vmcs(vc)) != 0 )
{
DPRINTK("Failed to create VMCS for vcpu %d: err=%d.\n",
vc->vcpu_id, rc);
return 0;
}
spin_lock_init(&vc->arch.hvm_vmx.vmcs_lock);
if ( (io_bitmap_a = alloc_xenheap_pages(IO_BITMAP_ORDER)) == NULL )
{
DPRINTK("Failed to allocate io bitmap b for vcpu %d.\n",
vc->vcpu_id);
return 0;
}
if ( (io_bitmap_b = alloc_xenheap_pages(IO_BITMAP_ORDER)) == NULL )
{
DPRINTK("Failed to allocate io bitmap b for vcpu %d.\n",
vc->vcpu_id);
return 0;
}
memset(io_bitmap_a, 0xff, 0x1000);
memset(io_bitmap_b, 0xff, 0x1000);
/* don't bother debug port access */
clear_bit(PC_DEBUG_PORT, io_bitmap_a);
vc->arch.hvm_vmx.io_bitmap_a = io_bitmap_a;
vc->arch.hvm_vmx.io_bitmap_b = io_bitmap_b;
}
/*
* Required to do this once per domain XXX todo: add a seperate function
* to do these.
*/
memset(&d->shared_info->evtchn_mask[0], 0xff,
sizeof(d->shared_info->evtchn_mask));
/* Put the domain in shadow mode even though we're going to be using
* the shared 1:1 page table initially. It shouldn't hurt */
shadow_mode_enable(
d, SHM_enable|SHM_refcounts|SHM_translate|SHM_external|SHM_wr_pt_pte);
return 1;
}
static void vmx_relinquish_guest_resources(struct domain *d)
@@ -90,9 +129,9 @@ static void vmx_relinquish_guest_resources(struct domain *d)
for_each_vcpu ( d, v )
{
vmx_destroy_vmcs(v);
if ( !test_bit(_VCPUF_initialised, &v->vcpu_flags) )
continue;
vmx_destroy_vmcs(v);
free_monitor_pagetable(v);
kill_timer(&v->arch.hvm_vmx.hlt_timer);
if ( hvm_apic_support(v->domain) && (VLAPIC(v) != NULL) )
@@ -444,12 +483,6 @@ void stop_vmx(void)
__vmxoff();
}
int vmx_initialize_guest_resources(struct vcpu *v)
{
vmx_final_setup_guest(v);
return 1;
}
void vmx_migrate_timers(struct vcpu *v)
{
struct periodic_time *pt = &(v->domain->arch.hvm_domain.pl_time.periodic_tm);
@@ -638,58 +671,61 @@ static int check_vmx_controls(u32 ctrls, u32 msr)
int start_vmx(void)
{
struct vmcs_struct *vmcs;
u32 ecx;
u32 eax, edx;
u64 phys_vmcs; /* debugging */
struct vmcs_struct *vmcs;
/*
* Xen does not fill x86_capability words except 0.
*/
ecx = cpuid_ecx(1);
boot_cpu_data.x86_capability[4] = ecx;
boot_cpu_data.x86_capability[4] = cpuid_ecx(1);
if (!(test_bit(X86_FEATURE_VMXE, &boot_cpu_data.x86_capability)))
return 0;
rdmsr(IA32_FEATURE_CONTROL_MSR, eax, edx);
if (eax & IA32_FEATURE_CONTROL_MSR_LOCK) {
if ((eax & IA32_FEATURE_CONTROL_MSR_ENABLE_VMXON) == 0x0) {
if ( eax & IA32_FEATURE_CONTROL_MSR_LOCK )
{
if ( (eax & IA32_FEATURE_CONTROL_MSR_ENABLE_VMXON) == 0x0 )
{
printk("VMX disabled by Feature Control MSR.\n");
return 0;
}
}
else {
else
{
wrmsr(IA32_FEATURE_CONTROL_MSR,
IA32_FEATURE_CONTROL_MSR_LOCK |
IA32_FEATURE_CONTROL_MSR_ENABLE_VMXON, 0);
}
if (!check_vmx_controls(MONITOR_PIN_BASED_EXEC_CONTROLS,
MSR_IA32_VMX_PINBASED_CTLS_MSR))
if ( !check_vmx_controls(MONITOR_PIN_BASED_EXEC_CONTROLS,
MSR_IA32_VMX_PINBASED_CTLS_MSR) )
return 0;
if (!check_vmx_controls(MONITOR_CPU_BASED_EXEC_CONTROLS,
MSR_IA32_VMX_PROCBASED_CTLS_MSR))
if ( !check_vmx_controls(MONITOR_CPU_BASED_EXEC_CONTROLS,
MSR_IA32_VMX_PROCBASED_CTLS_MSR) )
return 0;
if (!check_vmx_controls(MONITOR_VM_EXIT_CONTROLS,
MSR_IA32_VMX_EXIT_CTLS_MSR))
if ( !check_vmx_controls(MONITOR_VM_EXIT_CONTROLS,
MSR_IA32_VMX_EXIT_CTLS_MSR) )
return 0;
if (!check_vmx_controls(MONITOR_VM_ENTRY_CONTROLS,
MSR_IA32_VMX_ENTRY_CTLS_MSR))
if ( !check_vmx_controls(MONITOR_VM_ENTRY_CONTROLS,
MSR_IA32_VMX_ENTRY_CTLS_MSR) )
return 0;
set_in_cr4(X86_CR4_VMXE); /* Enable VMXE */
set_in_cr4(X86_CR4_VMXE);
if (!(vmcs = vmx_alloc_vmcs())) {
printk("Failed to allocate VMCS\n");
vmx_init_vmcs_config();
if ( (vmcs = vmx_alloc_host_vmcs()) == NULL )
{
printk("Failed to allocate host VMCS\n");
return 0;
}
phys_vmcs = (u64) virt_to_maddr(vmcs);
if (__vmxon(phys_vmcs)) {
if ( __vmxon(virt_to_maddr(vmcs)) )
{
printk("VMXON failed\n");
vmx_free_host_vmcs(vmcs);
return 0;
}
@@ -832,7 +868,7 @@ static void vmx_vmexit_do_cpuid(struct cpu_user_regs *regs)
cpuid_count(input, count, &eax, &ebx, &ecx, &edx);
eax &= NUM_CORES_RESET_MASK;
}
else
else if ( !cpuid_hypervisor_leaves(input, &eax, &ebx, &ecx, &edx) )
{
cpuid(input, &eax, &ebx, &ecx, &edx);
@@ -857,10 +893,14 @@ static void vmx_vmexit_do_cpuid(struct cpu_user_regs *regs)
#else
if ( v->domain->arch.ops->guest_paging_levels == PAGING_L2 )
{
if ( !v->domain->arch.hvm_domain.pae_enabled )
if ( v->domain->arch.hvm_domain.pae_enabled )
clear_bit(X86_FEATURE_PSE36, &edx);
else
{
clear_bit(X86_FEATURE_PAE, &edx);
clear_bit(X86_FEATURE_PSE, &edx);
clear_bit(X86_FEATURE_PSE36, &edx);
clear_bit(X86_FEATURE_PSE, &edx);
clear_bit(X86_FEATURE_PSE36, &edx);
}
}
#endif
@@ -2053,8 +2093,26 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs regs)
if ( unlikely(exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) )
{
printk("Failed vm entry (reason 0x%x)\n", exit_reason);
printk("*********** VMCS Area **************\n");
unsigned int failed_vmentry_reason = exit_reason & 0xFFFF;
__vmread(EXIT_QUALIFICATION, &exit_qualification);
printk("Failed vm entry (exit reason 0x%x) ", exit_reason);
switch ( failed_vmentry_reason ) {
case EXIT_REASON_INVALID_GUEST_STATE:
printk("caused by invalid guest state (%ld).\n", exit_qualification);
break;
case EXIT_REASON_MSR_LOADING:
printk("caused by MSR entry %ld loading.\n", exit_qualification);
break;
case EXIT_REASON_MACHINE_CHECK:
printk("caused by machine check.\n");
break;
default:
printk("reason not known yet!");
break;
}
printk("************* VMCS Area **************\n");
vmcs_dump_vcpu();
printk("**************************************\n");
domain_crash_synchronous();
+6 -5
View File
@@ -439,8 +439,9 @@ void __init __start_xen(multiboot_info_t *mbi)
scheduler_init();
idle_domain = domain_create(IDLE_DOMAIN_ID, 0);
BUG_ON(idle_domain == NULL);
idle_domain = domain_create(IDLE_DOMAIN_ID);
if ( (idle_domain == NULL) || (alloc_vcpu(idle_domain, 0, 0) == NULL) )
BUG();
set_current(idle_domain->vcpu[0]);
this_cpu(curr_vcpu) = idle_domain->vcpu[0];
@@ -537,8 +538,8 @@ void __init __start_xen(multiboot_info_t *mbi)
acm_init(&initrdidx, mbi, initial_images_start);
/* Create initial domain 0. */
dom0 = domain_create(0, 0);
if ( dom0 == NULL )
dom0 = domain_create(0);
if ( (dom0 == NULL) || (alloc_vcpu(dom0, 0, 0) == NULL) )
panic("Error creating domain 0\n");
set_bit(_DOMF_privileged, &dom0->domain_flags);
@@ -624,7 +625,7 @@ void arch_get_xen_caps(xen_capabilities_info_t info)
if ( hvm_enabled )
{
p += sprintf(p, "hvm-%d.%d-x86_32 ", XEN_VERSION, XEN_SUBVERSION);
//p += sprintf(p, "hvm-%d.%d-x86_32p ", XEN_VERSION, XEN_SUBVERSION);
p += sprintf(p, "hvm-%d.%d-x86_32p ", XEN_VERSION, XEN_SUBVERSION);
}
#elif defined(CONFIG_X86_64)
+9 -3
View File
@@ -1726,6 +1726,7 @@ static int resync_all(struct domain *d, u32 stype)
{
guest_l1_pgentry_t tmp_gl1e = guest_l1e_empty();
validate_pte_change(d, tmp_gl1e, sl1e_p);
unshadow_l1 = 1;
continue;
}
#endif
@@ -3676,20 +3677,19 @@ static inline int l2e_rw_fault(
put_page_from_l1e(old_sl1e, d);
}
l1_p[gpfn - start_gpfn] = sl1e;
if (rw) {
/* shadow_mark_va_out_of_sync() need modificatin for 2M pages*/
if ( mfn_is_page_table(mfn) )
shadow_mark_va_out_of_sync_2mp(v, gpfn, mfn,
l2e_get_paddr(sl2e) | (sizeof(l1_pgentry_t) * (gpfn - start_gpfn)));
}
l1_p[gpfn - start_gpfn] = sl1e;
}
unmap_domain_page(l1_p);
*gl2e_p = gl2e;
return 1;
}
/*
@@ -3724,7 +3724,13 @@ static inline int guest_page_fault(
}
if ( guest_l2e_get_flags(*gpl2e) & _PAGE_PSE )
{
printk("None-PAE HVM guests can NOT use PSE, "
"because we don't support 4MBytes PSE pages.\n");
printk("remove pae=1 from your config file.\n");
domain_crash_synchronous();
return 0;
}
__guest_get_l1e(v, va, gpl1e);
+1 -2
View File
@@ -1197,8 +1197,7 @@ int __devinit __cpu_up(unsigned int cpu)
cpu_set(cpu, smp_commenced_mask);
while (!cpu_isset(cpu, cpu_online_map)) {
mb();
if (softirq_pending(0))
do_softirq();
process_pending_timers();
}
return 0;
}
+30 -3
View File
@@ -426,10 +426,32 @@ DO_ERROR_NOCODE(16, "fpu error", coprocessor_error)
DO_ERROR(17, "alignment check", alignment_check)
DO_ERROR_NOCODE(19, "simd error", simd_coprocessor_error)
int cpuid_hypervisor_leaves(
uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
{
if ( (idx < 0x40000000) || (idx > 0x40000000) )
return 0;
switch ( idx - 0x40000000 )
{
case 0:
*eax = 0x40000000;
*ebx = 0x006e6558; /* "Xen\0" */
*ecx = *edx = 0;
break;
default:
BUG();
}
return 1;
}
static int emulate_forced_invalid_op(struct cpu_user_regs *regs)
{
char signature[5], instr[2];
unsigned long a, b, c, d, eip;
uint32_t a, b, c, d;
unsigned long eip;
a = regs->eax;
b = regs->ebx;
@@ -466,6 +488,10 @@ static int emulate_forced_invalid_op(struct cpu_user_regs *regs)
if ( !IS_PRIV(current->domain) )
clear_bit(X86_FEATURE_MTRR, &d);
}
else
{
(void)cpuid_hypervisor_leaves(regs->eax, &a, &b, &c, &d);
}
regs->eax = a;
regs->ebx = b;
@@ -1397,13 +1423,14 @@ static void nmi_softirq(void)
static void nmi_dom0_report(unsigned int reason_idx)
{
struct domain *d;
struct vcpu *v;
if ( (d = dom0) == NULL )
if ( ((d = dom0) == NULL) || ((v = d->vcpu[0]) == NULL) )
return;
set_bit(reason_idx, &d->shared_info->arch.nmi_reason);
if ( test_and_set_bit(_VCPUF_nmi_pending, &d->vcpu[0]->vcpu_flags) )
if ( test_and_set_bit(_VCPUF_nmi_pending, &v->vcpu_flags) )
raise_softirq(NMI_SOFTIRQ); /* not safe to wake up a vcpu here */
}
+1 -1
View File
@@ -118,7 +118,7 @@ static uint8_t opcode_table[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xC0 - 0xC7 */
ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImmByte|ModRM, 0, 0,
0, 0, ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImm|ModRM,
0, 0, ByteOp|DstMem|SrcImm|ModRM|Mov, DstMem|SrcImm|ModRM|Mov,
/* 0xC8 - 0xCF */
0, 0, 0, 0, 0, 0, 0, 0,
/* 0xD0 - 0xD7 */
+52 -48
View File
@@ -90,6 +90,44 @@ static void getdomaininfo(struct domain *d, dom0_getdomaininfo_t *info)
memcpy(info->handle, d->handle, sizeof(xen_domain_handle_t));
}
static unsigned int default_vcpu0_location(void)
{
struct domain *d;
struct vcpu *v;
unsigned int i, cpu, cnt[NR_CPUS] = { 0 };
cpumask_t cpu_exclude_map;
/* Do an initial CPU placement. Pick the least-populated CPU. */
read_lock(&domlist_lock);
for_each_domain ( d )
for_each_vcpu ( d, v )
if ( !test_bit(_VCPUF_down, &v->vcpu_flags) )
cnt[v->processor]++;
read_unlock(&domlist_lock);
/*
* If we're on a HT system, we only auto-allocate to a non-primary HT. We
* favour high numbered CPUs in the event of a tie.
*/
cpu = first_cpu(cpu_sibling_map[0]);
if ( cpus_weight(cpu_sibling_map[0]) > 1 )
cpu = next_cpu(cpu, cpu_sibling_map[0]);
cpu_exclude_map = cpu_sibling_map[0];
for_each_online_cpu ( i )
{
if ( cpu_isset(i, cpu_exclude_map) )
continue;
if ( (i == first_cpu(cpu_sibling_map[i])) &&
(cpus_weight(cpu_sibling_map[i]) > 1) )
continue;
cpus_or(cpu_exclude_map, cpu_exclude_map, cpu_sibling_map[i]);
if ( cnt[i] <= cnt[cpu] )
cpu = i;
}
return cpu;
}
long do_dom0_op(XEN_GUEST_HANDLE(dom0_op_t) u_dom0_op)
{
long ret = 0;
@@ -150,7 +188,7 @@ long do_dom0_op(XEN_GUEST_HANDLE(dom0_op_t) u_dom0_op)
if ( d != NULL )
{
ret = -EINVAL;
if ( (d != current->domain) &&
if ( (d != current->domain) && (d->vcpu[0] != NULL) &&
test_bit(_VCPUF_initialised, &d->vcpu[0]->vcpu_flags) )
{
domain_unpause_by_systemcontroller(d);
@@ -164,11 +202,7 @@ long do_dom0_op(XEN_GUEST_HANDLE(dom0_op_t) u_dom0_op)
case DOM0_CREATEDOMAIN:
{
struct domain *d;
unsigned int pro;
domid_t dom;
struct vcpu *v;
unsigned int i, cnt[NR_CPUS] = { 0 };
cpumask_t cpu_exclude_map;
static domid_t rover = 0;
/*
@@ -202,36 +236,8 @@ long do_dom0_op(XEN_GUEST_HANDLE(dom0_op_t) u_dom0_op)
rover = dom;
}
/* Do an initial CPU placement. Pick the least-populated CPU. */
read_lock(&domlist_lock);
for_each_domain ( d )
for_each_vcpu ( d, v )
if ( !test_bit(_VCPUF_down, &v->vcpu_flags) )
cnt[v->processor]++;
read_unlock(&domlist_lock);
/*
* If we're on a HT system, we only auto-allocate to a non-primary HT.
* We favour high numbered CPUs in the event of a tie.
*/
pro = first_cpu(cpu_sibling_map[0]);
if ( cpus_weight(cpu_sibling_map[0]) > 1 )
pro = next_cpu(pro, cpu_sibling_map[0]);
cpu_exclude_map = cpu_sibling_map[0];
for_each_online_cpu ( i )
{
if ( cpu_isset(i, cpu_exclude_map) )
continue;
if ( (i == first_cpu(cpu_sibling_map[i])) &&
(cpus_weight(cpu_sibling_map[i]) > 1) )
continue;
cpus_or(cpu_exclude_map, cpu_exclude_map, cpu_sibling_map[i]);
if ( cnt[i] <= cnt[pro] )
pro = i;
}
ret = -ENOMEM;
if ( (d = domain_create(dom, pro)) == NULL )
if ( (d = domain_create(dom)) == NULL )
break;
memcpy(d->handle, op->u.createdomain.handle,
@@ -258,14 +264,8 @@ long do_dom0_op(XEN_GUEST_HANDLE(dom0_op_t) u_dom0_op)
if ( (d = find_domain_by_id(op->u.max_vcpus.domain)) == NULL )
break;
/*
* Can only create new VCPUs while the domain is not fully constructed
* (and hence not runnable). Xen needs auditing for races before
* removing this check.
*/
ret = -EINVAL;
if ( test_bit(_VCPUF_initialised, &d->vcpu[0]->vcpu_flags) )
goto maxvcpu_out;
/* Needed, for example, to ensure writable p.t. state is synced. */
domain_pause(d);
/* We cannot reduce maximum VCPUs. */
ret = -EINVAL;
@@ -275,17 +275,21 @@ long do_dom0_op(XEN_GUEST_HANDLE(dom0_op_t) u_dom0_op)
ret = -ENOMEM;
for ( i = 0; i < max; i++ )
{
if ( d->vcpu[i] == NULL )
{
cpu = (d->vcpu[i-1]->processor + 1) % num_online_cpus();
if ( alloc_vcpu(d, i, cpu) == NULL )
goto maxvcpu_out;
}
if ( d->vcpu[i] != NULL )
continue;
cpu = (i == 0) ?
default_vcpu0_location() :
(d->vcpu[i-1]->processor + 1) % num_online_cpus();
if ( alloc_vcpu(d, i, cpu) == NULL )
goto maxvcpu_out;
}
ret = 0;
maxvcpu_out:
domain_unpause(d);
put_domain(d);
}
break;
Loaded 100 of 126 files, more files were not shown because too many files have changed in this diff. Show more
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.