# HG changeset patch
# User awilliam@xxxxxxxxxxxx
# Date 1173715628 21600
# Node ID cb2575cec95c9960c30133725943a0da81daa2f5
# Parent d1853a39e063ea82f8900fa91208258492845f6a
# Parent 8a01644306ee024eb49a195a50662d04021aefa1
merge with xen-unstable.hg
---
xen/arch/x86/mm/shadow/page-guest32.h | 100 -
buildconfigs/linux-defconfig_xen0_ia64 | 2
buildconfigs/linux-defconfig_xen0_x86_32 | 2
buildconfigs/linux-defconfig_xen0_x86_64 | 2
buildconfigs/linux-defconfig_xenU_ia64 | 2
buildconfigs/linux-defconfig_xenU_x86_32 | 2
buildconfigs/linux-defconfig_xenU_x86_64 | 2
buildconfigs/linux-defconfig_xen_ia64 | 2
buildconfigs/linux-defconfig_xen_x86_32 | 2
buildconfigs/linux-defconfig_xen_x86_64 | 2
docs/man/xm.pod.1 | 2
docs/misc/dump-core-format.txt | 8
docs/xen-api/coversheet.tex | 2
docs/xen-api/presentation.tex | 16
docs/xen-api/vm-lifecycle.tex | 16
docs/xen-api/wire-protocol.tex | 50
docs/xen-api/xenapi-datamodel.tex | 744
++++------
docs/xen-api/xenapi.tex | 3
linux-2.6-xen-sparse/arch/i386/kernel/cpu/mtrr/main-xen.c | 24
linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c | 4
linux-2.6-xen-sparse/arch/i386/kernel/ioport-xen.c | 2
linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c | 6
linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c | 6
linux-2.6-xen-sparse/arch/i386/kernel/quirks-xen.c | 6
linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c | 39
linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c | 4
linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c | 2
linux-2.6-xen-sparse/arch/ia64/xen/xcom_hcall.c | 2
linux-2.6-xen-sparse/arch/ia64/xen/xcom_mini.c | 2
linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c | 24
linux-2.6-xen-sparse/arch/x86_64/kernel/ioport-xen.c | 2
linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c | 8
linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c | 2
linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.h | 13
linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c | 28
linux-2.6-xen-sparse/drivers/xen/Kconfig | 9
linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c | 1
linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c | 13
linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.c | 6
linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.h | 2
linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c | 12
linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c | 1
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h | 10
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h | 2
linux-2.6-xen-sparse/include/asm-ia64/hypercall.h | 6
linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h | 2
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h | 10
patches/linux-2.6.18/softlockup-no-idle-hz.patch | 1
tools/ioemu/hw/ide.c | 176 ++
tools/ioemu/target-i386-dm/helper2.c | 21
tools/ioemu/vl.h | 1
tools/libxc/xc_core_ia64.c | 24
tools/libxc/xc_dom_x86.c | 30
tools/libxc/xc_hvm_restore.c | 73
tools/libxc/xc_hvm_save.c | 149 +-
tools/libxc/xc_misc.c | 19
tools/libxc/xc_private.c | 2
tools/libxc/xc_ptrace_core.c | 1
tools/libxc/xenctrl.h | 8
tools/libxc/xenguest.h | 3
tools/libxc/xg_private.c | 5
tools/libxen/include/xen_crashdump.h | 23
tools/libxen/include/xen_vbd.h | 16
tools/libxen/include/xen_vdi.h | 7
tools/libxen/include/xen_vif.h | 16
tools/libxen/include/xen_vm.h | 133 -
tools/libxen/src/xen_common.c | 21
tools/libxen/src/xen_crashdump.c | 47
tools/libxen/src/xen_vbd.c | 28
tools/libxen/src/xen_vdi.c | 16
tools/libxen/src/xen_vif.c | 28
tools/libxen/src/xen_vm.c | 244 +--
tools/libxen/test/test_bindings.c | 2
tools/python/xen/lowlevel/xc/xc.c | 26
tools/python/xen/xend/XendAPI.py | 163 --
tools/python/xen/xend/XendCheckpoint.py | 7
tools/python/xen/xend/XendConfig.py | 276 +--
tools/python/xen/xend/XendDomain.py | 2
tools/python/xen/xend/XendDomainInfo.py | 78 -
tools/python/xen/xend/XendError.py | 7
tools/python/xen/xend/XendNode.py | 9
tools/python/xen/xend/image.py | 59
tools/python/xen/xend/server/XMLRPCServer.py | 2
tools/python/xen/xm/XenAPI.py | 2
tools/python/xen/xm/main.py | 21
tools/python/xen/xm/messages/en/xen-xm.po | 5
tools/xm-test/tests/vtpm/09_vtpm-xapi.py | 9
xen/arch/ia64/xen/xensetup.c | 2
xen/arch/powerpc/domain.c | 2
xen/arch/powerpc/setup.c | 3
xen/arch/x86/apic.c | 14
xen/arch/x86/domain.c | 9
xen/arch/x86/domctl.c | 10
xen/arch/x86/hvm/hvm.c | 64
xen/arch/x86/hvm/rtc.c | 17
xen/arch/x86/hvm/svm/svm.c | 220 ++
xen/arch/x86/hvm/svm/vmcb.c | 15
xen/arch/x86/mm/Makefile | 1
xen/arch/x86/mm/hap/Makefile | 2
xen/arch/x86/mm/hap/hap.c | 708
+++++++++
xen/arch/x86/mm/hap/private.h | 112 +
xen/arch/x86/mm/hap/support.c | 334 ++++
xen/arch/x86/mm/page-guest32.h | 100 +
xen/arch/x86/mm/paging.c | 34
xen/arch/x86/mm/shadow/common.c | 17
xen/arch/x86/mm/shadow/types.h | 2
xen/arch/x86/setup.c | 8
xen/common/compat/domain.c | 4
xen/common/domain.c | 74
xen/common/event_channel.c | 3
xen/common/keyhandler.c | 34
xen/common/page_alloc.c | 138 -
xen/common/sched_credit.c | 40
xen/common/schedule.c | 139 +
xen/common/sysctl.c | 15
xen/common/xmalloc.c | 6
xen/drivers/char/console.c | 2
xen/include/asm-x86/domain.h | 16
xen/include/asm-x86/hap.h | 122 +
xen/include/asm-x86/hvm/svm/vmcb.h | 1
xen/include/asm-x86/hvm/vpt.h | 1
xen/include/asm-x86/paging.h | 2
xen/include/public/hvm/hvm_op.h | 8
xen/include/public/sysctl.h | 13
xen/include/public/vcpu.h | 42
xen/include/public/xen.h | 1
xen/include/xen/mm.h | 5
xen/include/xen/sched-if.h | 2
xen/include/xen/sched.h | 8
xen/include/xen/timer.h | 4
130 files changed, 3527 insertions(+), 1794 deletions(-)
diff -r d1853a39e063 -r cb2575cec95c buildconfigs/linux-defconfig_xen0_ia64
--- a/buildconfigs/linux-defconfig_xen0_ia64 Mon Mar 12 09:43:48 2007 -0600
+++ b/buildconfigs/linux-defconfig_xen0_ia64 Mon Mar 12 10:07:08 2007 -0600
@@ -1619,7 +1619,7 @@ CONFIG_XEN_BALLOON=y
CONFIG_XEN_BALLOON=y
CONFIG_XEN_REBOOT=y
# CONFIG_XEN_SMPBOOT is not set
-CONFIG_XEN_INTERFACE_VERSION=0x00030203
+CONFIG_XEN_INTERFACE_VERSION=0x00030205
#
# XEN
diff -r d1853a39e063 -r cb2575cec95c buildconfigs/linux-defconfig_xen0_x86_32
--- a/buildconfigs/linux-defconfig_xen0_x86_32 Mon Mar 12 09:43:48 2007 -0600
+++ b/buildconfigs/linux-defconfig_xen0_x86_32 Mon Mar 12 10:07:08 2007 -0600
@@ -1384,7 +1384,7 @@ CONFIG_CRYPTO_CRC32C=m
#
# CONFIG_CRYPTO_DEV_PADLOCK is not set
CONFIG_XEN=y
-CONFIG_XEN_INTERFACE_VERSION=0x00030203
+CONFIG_XEN_INTERFACE_VERSION=0x00030205
#
# XEN
diff -r d1853a39e063 -r cb2575cec95c buildconfigs/linux-defconfig_xen0_x86_64
--- a/buildconfigs/linux-defconfig_xen0_x86_64 Mon Mar 12 09:43:48 2007 -0600
+++ b/buildconfigs/linux-defconfig_xen0_x86_64 Mon Mar 12 10:07:08 2007 -0600
@@ -1334,7 +1334,7 @@ CONFIG_CRYPTO_CRC32C=m
# Hardware crypto devices
#
CONFIG_XEN=y
-CONFIG_XEN_INTERFACE_VERSION=0x00030203
+CONFIG_XEN_INTERFACE_VERSION=0x00030205
#
# XEN
diff -r d1853a39e063 -r cb2575cec95c buildconfigs/linux-defconfig_xenU_ia64
--- a/buildconfigs/linux-defconfig_xenU_ia64 Mon Mar 12 09:43:48 2007 -0600
+++ b/buildconfigs/linux-defconfig_xenU_ia64 Mon Mar 12 10:07:08 2007 -0600
@@ -1471,7 +1471,7 @@ CONFIG_XEN_BALLOON=y
CONFIG_XEN_BALLOON=y
CONFIG_XEN_REBOOT=y
# CONFIG_XEN_SMPBOOT is not set
-CONFIG_XEN_INTERFACE_VERSION=0x00030203
+CONFIG_XEN_INTERFACE_VERSION=0x00030205
#
# XEN
diff -r d1853a39e063 -r cb2575cec95c buildconfigs/linux-defconfig_xenU_x86_32
--- a/buildconfigs/linux-defconfig_xenU_x86_32 Mon Mar 12 09:43:48 2007 -0600
+++ b/buildconfigs/linux-defconfig_xenU_x86_32 Mon Mar 12 10:07:08 2007 -0600
@@ -904,7 +904,7 @@ CONFIG_CRYPTO_CRC32C=m
#
# CONFIG_CRYPTO_DEV_PADLOCK is not set
CONFIG_XEN=y
-CONFIG_XEN_INTERFACE_VERSION=0x00030203
+CONFIG_XEN_INTERFACE_VERSION=0x00030205
#
# XEN
diff -r d1853a39e063 -r cb2575cec95c buildconfigs/linux-defconfig_xenU_x86_64
--- a/buildconfigs/linux-defconfig_xenU_x86_64 Mon Mar 12 09:43:48 2007 -0600
+++ b/buildconfigs/linux-defconfig_xenU_x86_64 Mon Mar 12 10:07:08 2007 -0600
@@ -1200,7 +1200,7 @@ CONFIG_CRYPTO_CRC32C=m
# Hardware crypto devices
#
CONFIG_XEN=y
-CONFIG_XEN_INTERFACE_VERSION=0x00030203
+CONFIG_XEN_INTERFACE_VERSION=0x00030205
#
# XEN
diff -r d1853a39e063 -r cb2575cec95c buildconfigs/linux-defconfig_xen_ia64
--- a/buildconfigs/linux-defconfig_xen_ia64 Mon Mar 12 09:43:48 2007 -0600
+++ b/buildconfigs/linux-defconfig_xen_ia64 Mon Mar 12 10:07:08 2007 -0600
@@ -1619,7 +1619,7 @@ CONFIG_XEN_BALLOON=y
CONFIG_XEN_BALLOON=y
CONFIG_XEN_REBOOT=y
# CONFIG_XEN_SMPBOOT is not set
-CONFIG_XEN_INTERFACE_VERSION=0x00030203
+CONFIG_XEN_INTERFACE_VERSION=0x00030205
#
# XEN
diff -r d1853a39e063 -r cb2575cec95c buildconfigs/linux-defconfig_xen_x86_32
--- a/buildconfigs/linux-defconfig_xen_x86_32 Mon Mar 12 09:43:48 2007 -0600
+++ b/buildconfigs/linux-defconfig_xen_x86_32 Mon Mar 12 10:07:08 2007 -0600
@@ -3242,7 +3242,7 @@ CONFIG_CRYPTO_TEST=m
#
# CONFIG_CRYPTO_DEV_PADLOCK is not set
CONFIG_XEN=y
-CONFIG_XEN_INTERFACE_VERSION=0x00030203
+CONFIG_XEN_INTERFACE_VERSION=0x00030205
#
# XEN
diff -r d1853a39e063 -r cb2575cec95c buildconfigs/linux-defconfig_xen_x86_64
--- a/buildconfigs/linux-defconfig_xen_x86_64 Mon Mar 12 09:43:48 2007 -0600
+++ b/buildconfigs/linux-defconfig_xen_x86_64 Mon Mar 12 10:07:08 2007 -0600
@@ -3072,7 +3072,7 @@ CONFIG_CRYPTO_TEST=m
# Hardware crypto devices
#
CONFIG_XEN=y
-CONFIG_XEN_INTERFACE_VERSION=0x00030203
+CONFIG_XEN_INTERFACE_VERSION=0x00030205
#
# XEN
diff -r d1853a39e063 -r cb2575cec95c docs/man/xm.pod.1
--- a/docs/man/xm.pod.1 Mon Mar 12 09:43:48 2007 -0600
+++ b/docs/man/xm.pod.1 Mon Mar 12 10:07:08 2007 -0600
@@ -619,7 +619,7 @@ devices, or by device id, such as 0x1400
=item I<mode>
The access mode for the device from the guest domain. Supported modes
-are I<rw> (read/write) or I<ro> (read-only).
+are I<w> (read/write) or I<r> (read-only).
=item I<bedomain-id>
diff -r d1853a39e063 -r cb2575cec95c docs/misc/dump-core-format.txt
--- a/docs/misc/dump-core-format.txt Mon Mar 12 09:43:48 2007 -0600
+++ b/docs/misc/dump-core-format.txt Mon Mar 12 10:07:08 2007 -0600
@@ -80,8 +80,7 @@ Currently the following sections are def
gmfn: machine physical frame number
The size of arrays is stored in xch_nr_pages member of header
note descriptor in .note.Xen note section.
- There is no rule about the order. Analysis tools must no rely
- on its order.
+ The entryies are stored in pfn-ascending order.
This section must exist when the domain is non auto
translated physmap mode. Currently x86 paravirtualized domain.
@@ -94,8 +93,7 @@ Currently the following sections are def
in .xen_pages section.
The size of arrays is stored in xch_nr_pages member of header
note descriptor in .note.Xen note section.
- There is no rule about the order. Analysis tools must no rely
- on its order.
+ The entries are stored in ascending order.
This section must exist when the domain is auto translated
physmap mode. Currently x86 full virtualized domain and
ia64 domain.
@@ -226,6 +224,8 @@ Currently only (major, minor) = (0, 1) i
[When the format is changed, it would be described here.]
(0, 1) update
+- .xen_p2m, .xen_pfn section
+ Arrays must be in pfn ascending order for efficient looking up.
- EI_CLASS member of elf header was changed to ELFCLASS64 independent of
architecture. This is mainly for x86_32pae.
The format version isn't bumped because analysis tools can distinguish it.
diff -r d1853a39e063 -r cb2575cec95c docs/xen-api/coversheet.tex
--- a/docs/xen-api/coversheet.tex Mon Mar 12 09:43:48 2007 -0600
+++ b/docs/xen-api/coversheet.tex Mon Mar 12 10:07:08 2007 -0600
@@ -47,4 +47,4 @@ Date: \datestring{}
\legalnotice{}
\newpage
-\pagestyle{plain}
\ No newline at end of file
+\pagestyle{fancy}
\ No newline at end of file
diff -r d1853a39e063 -r cb2575cec95c docs/xen-api/presentation.tex
--- a/docs/xen-api/presentation.tex Mon Mar 12 09:43:48 2007 -0600
+++ b/docs/xen-api/presentation.tex Mon Mar 12 10:07:08 2007 -0600
@@ -57,14 +57,14 @@ type $t_1$ to values of type $t_2$.
\end{itemize}
Note that there are a number of cases where {\em Ref}s are {\em doubly
-linked\/}---e.g.\ a VM has a field called {\tt groups} of type
-$(\mathit{VMGroup}~\mathit{Ref})~\mathit{Set}$; this field lists
-the VMGroups that a particular VM is part of. Similarly, the VMGroups
-class has a field called {\tt VMs} of type $(\mathit{VM}~{\mathit
-Ref})~\mathit{Set}$ that contains the VMs that are part of a particular
-VMGroup. These two fields are {\em bound together\/}, in the sense that
-adding a new VMGroup to a VM causes the VMs field of the corresponding
-VMGroup object to be updated automatically.
+linked\/}---e.g.\ a VM has a field called {\tt VIFs} of type
+$(\mathit{VIF}~\mathit{Ref})~\mathit{Set}$; this field lists
+the network interfaces attached to a particular VM. Similarly, the VIF
+class has a field called {\tt VM} of type $(\mathit{VM}~{\mathit
+Ref})$ which references the VM to which the interface is connected.
+These two fields are {\em bound together\/}, in the sense that
+creating a new VIF causes the {\tt VIFs} field of the corresponding
+VM object to be updated automatically.
The API reference explicitly lists the fields that are
bound together in this way. It also contains a diagram that shows
diff -r d1853a39e063 -r cb2575cec95c docs/xen-api/vm-lifecycle.tex
--- a/docs/xen-api/vm-lifecycle.tex Mon Mar 12 09:43:48 2007 -0600
+++ b/docs/xen-api/vm-lifecycle.tex Mon Mar 12 10:07:08 2007 -0600
@@ -22,3 +22,19 @@
Figure~\ref{fig-vm-lifecycle} shows the states that a VM can be in
and the API calls that can be used to move the VM between these states.
+
+\section{VM boot parameters}
+
+The VM class contains a number of fields that control the way in which the VM
is booted.
+With reference to the fields defined in the VM class (see later in this
document),
+this section outlines the boot options available and the mechanisms provided
for controlling them.
+
+VM booting is controlled by setting one of the two mutually exclusive groups:
``PV'', and ``HVM''. If HVM.boot\_policy is the empty string, then paravirtual
domain building and booting will be used; otherwise the VM will be loaded as an
HVM domain, and booted using an emulated BIOS.
+
+When paravirtual booting is in use, the PV/bootloader field indicates the
bootloader to use. It may be ``pygrub'', in which case the platform's default
installation of pygrub will be used, or a full path within the control domain
to some other bootloader. The other fields, PV/kernel, PV/ramdisk, PV/args and
PV/bootloader\_args will be passed to the bootloader unmodified, and
interpretation of those fields is then specific to the bootloader itself,
including the possibility that the bootloader will ignore some or all of those
given values. Finally the paths of all bootable disks are added to the
bootloader commandline (a disk is bootable if its VBD has the bootable flag
set). There may be zero, one or many bootable disks; the bootloader decides
which disk (if any) to boot from.
+
+If the bootloader is pygrub, then the menu.lst is parsed if present in the
guest's filesystem, otherwise the specified kernel and ramdisk are used, or an
autodetected kernel is used if nothing is specified and autodetection is
possible. PV/args is appended to the kernel command line, no matter which
mechanism is used for finding the kernel.
+
+If PV/bootloader is empty but PV/kernel is specified, then the kernel and
ramdisk values will be treated as paths within the control domain. If both
PV/bootloader and PV/kernel are empty, then the behaviour is as if
PV/bootloader was specified as ``pygrub''.
+
+When using HVM booting, HVM/boot\_policy and HVM/boot\_params specify the boot
handling. Only one policy is currently defined: ``BIOS order''. In this case,
HVM/boot\_params should contain one key-value pair ``order'' = ``N'' where N is
the string that will be passed to QEMU.
\ No newline at end of file
diff -r d1853a39e063 -r cb2575cec95c docs/xen-api/wire-protocol.tex
--- a/docs/xen-api/wire-protocol.tex Mon Mar 12 09:43:48 2007 -0600
+++ b/docs/xen-api/wire-protocol.tex Mon Mar 12 10:07:08 2007 -0600
@@ -30,8 +30,13 @@ These types are mapped onto XML-RPC type
\item Floats, Bools, DateTimes and Strings map directly to the XML-RPC {\tt
double}, {\tt boolean}, {\tt dateTime.iso8601}, and {\tt string} elements.
- \item all our ``{\tt ref\_}'' types (e.g.\ {\tt ref\_vm} in the above
- example) map to XML-RPC's {\tt String} type. The string itself is the OSF
+ \item all ``{\tt ref\_}'' types are opaque references, encoded as the
+ XML-RPC's {\tt String} type. Users of the API should not make assumptions
+ about the concrete form of these strings and should not expect them to
+ remain valid after the client's session with the server has terminated.
+
+ \item fields named ``{\tt uuid}'' of type ``{\tt String}'' are mapped to
+ the XML-RPC {\tt String} type. The string itself is the OSF
DCE UUID presentation format (as output by {\tt uuidgen}, etc).
\item ints are all assumed to be 64-bit in our API and are encoded as a
@@ -82,6 +87,32 @@ These types are mapped onto XML-RPC type
\item our {\tt Void} type is transmitted as an empty string.
+\end{itemize}
+
+\subsection{Note on References vs UUIDs}
+
+References are opaque types --- encoded as XML-RPC strings on the wire ---
understood
+only by the particular server which generated them. Servers are free to choose
+any concrete representation they find convenient; clients should not make any
+assumptions or attempt to parse the string contents. References are not
guaranteed
+to be permanent identifiers for objects; clients should not assume that
references
+generated during one session are valid for any future session. References do
not
+allow objects to be compared for equality. Two references to the same object
are
+not guaranteed to be textually identical.
+
+UUIDs are intended to be permanent names for objects. They are
+guaranteed to be in the OSF DCE UUID presentation format (as output by {\tt
uuidgen}.
+Clients may store UUIDs on disk and use them to lookup objects in subsequent
sessions
+with the server. Clients may also test equality on objects by comparing UUID
strings.
+
+The API provides mechanisms
+for translating between UUIDs and opaque references. Each class that contains
a UUID
+field provides:
+\begin{itemize}
+\item A ``{\tt get\_by\_uuid}'' method that takes a UUID, $u$, and returns an
opaque reference
+to the server-side object that has UUID=$u$;
+\item A {\tt get\_uuid} function (a regular ``field getter'' RPC) that takes
an opaque reference,
+$r$, and returns the UUID of the server-side object that is referenced by $r$.
\end{itemize}
\subsection{Return Values/Status Codes}
@@ -138,7 +169,7 @@ may look like this:
\subsection{Transport Layer}
-We ought to support at least
+The following transport layers are currently supported:
\begin{itemize}
\item HTTP/S for remote administration
\item HTTP over Unix domain sockets for local administration
@@ -247,13 +278,12 @@ call takes the session token as the only
\begin{verbatim}
>>> all_vms = host.get_resident_VMs(session)['Value']
>>> all_vms
-['b7b92d9e-d442-4710-92a5-ab039fd7d89b',
'23e1e837-abbf-4675-b077-d4007989b0cc',
- '2045dbc0-0734-4eea-9cb2-b8218c6b5bf2',
'3202ae18-a046-4c32-9fda-e32e9631866e']
-\end{verbatim}
-
-The VM references here are UUIDs, though they may not be that simple in the
-future, and you should treat them as opaque strings. Once a reference to a VM
-has been acquired a lifecycle operation may be invoked:
+['OpaqueRef:1', 'OpaqueRef:2', 'OpaqueRef:3', 'OpaqueRef:4' ]
+\end{verbatim}
+
+The VM references here have the form {\tt OpaqueRef:X}, though they may not be
+that simple in the future, and you should treat them as opaque strings.
+Once a reference to a VM has been acquired a lifecycle operation may be
invoked:
\begin{verbatim}
>>> xen.VM.start(session, all_vms[3], False)
diff -r d1853a39e063 -r cb2575cec95c docs/xen-api/xenapi-datamodel.tex
--- a/docs/xen-api/xenapi-datamodel.tex Mon Mar 12 09:43:48 2007 -0600
+++ b/docs/xen-api/xenapi-datamodel.tex Mon Mar 12 10:07:08 2007 -0600
@@ -231,7 +231,7 @@ Quals & Field & Type & Description \\
$\mathit{RO}_\mathit{run}$ & {\tt last\_active} & int & Timestamp for last
time session was active \\
\hline
\end{longtable}
-\subsection{Additional RPCs associated with class: session}
+\subsection{RPCs associated with class: session}
\subsubsection{RPC name:~login\_with\_password}
{\bf Overview:}
@@ -505,7 +505,7 @@ Quals & Field & Type & Description \\
$\mathit{RO}_\mathit{run}$ & {\tt allowed\_operations} &
(task\_allowed\_operations) Set & Operations allowed on this task \\
\hline
\end{longtable}
-\subsection{Additional RPCs associated with class: task}
+\subsection{RPCs associated with class: task}
\subsubsection{RPC name:~cancel}
{\bf Overview:}
@@ -1022,40 +1022,7 @@ references to objects with match names
\hline
\multicolumn{1}{|l}{Name} & \multicolumn{3}{l|}{\bf VM} \\
\multicolumn{1}{|l}{Description} & \multicolumn{3}{l|}{\parbox{11cm}{\em A
-virtual machine (or 'guest').
-
-VM booting is controlled by setting one of the two mutually exclusive
-groups: "PV", and "HVM". If HVM.boot\_policy is the empty string, then
-paravirtual domain building and booting will be used; otherwise the VM will
-be loaded as an HVM domain, and booted using an emulated BIOS.
-
-When paravirtual booting is in use, the PV/bootloader field indicates the
-bootloader to use. It may be "pygrub", in which case the platform's
-default installation of pygrub will be used, or a full path within the
-control domain to some other bootloader. The other fields, PV/kernel,
-PV/ramdisk, PV/args and PV/bootloader\_args will be passed to the
-bootloader unmodified, and interpretation of those fields is then specific
-to the bootloader itself, including the possibility that the bootloader
-will ignore some or all of those given values. Finally the paths of all
-bootable disks are added to the bootloader commandline (a disk is bootable
-if its VBD has the bootable flag set). There may be zero, one or many
-bootable disks; the bootloader decides which disk (if any) to boot from.
-
-If the bootloader is pygrub, then the menu.lst is parsed if present in the
-guest's filesystem, otherwise the specified kernel and ramdisk are used, or
-an autodetected kernel is used if nothing is specified and autodetection is
-possible. PV/args is appended to the kernel command line, no matter which
-mechanism is used for finding the kernel.
-
-If PV/bootloader is empty but PV/kernel is specified, then the kernel and
-ramdisk values will be treated as paths within the control domain. If both
-PV/bootloader and PV/kernel are empty, then the behaviour is as if
-PV/bootloader was specified as "pygrub".
-
-When using HVM booting, HVM/boot\_policy and HVM/boot\_params specify the
-boot handling. Only one policy is currently defined: "BIOS order". In
-this case, HVM/boot\_params should contain one key-value pair "order" = "N"
-where N is the string that will be passed to QEMU.}} \\
+virtual machine (or 'guest').}} \\
\hline
Quals & Field & Type & Description \\
\hline
@@ -1091,12 +1058,8 @@ Quals & Field & Type & Description \\
$\mathit{RW}$ & {\tt PV/bootloader\_args} & string & miscellaneous arguments
for the bootloader \\
$\mathit{RW}$ & {\tt HVM/boot\_policy} & string & HVM boot policy \\
$\mathit{RW}$ & {\tt HVM/boot\_params} & (string $\rightarrow$ string) Map &
HVM boot params \\
-$\mathit{RW}$ & {\tt platform/std\_VGA} & bool & emulate standard VGA instead
of cirrus logic \\
-$\mathit{RW}$ & {\tt platform/serial} & string & redirect serial port to pty
\\
-$\mathit{RW}$ & {\tt platform/localtime} & bool & set RTC to local time \\
-$\mathit{RW}$ & {\tt platform/clock\_offset} & bool & timeshift applied to
guest's clock \\
-$\mathit{RW}$ & {\tt platform/enable\_audio} & bool & emulate audio \\
-$\mathit{RO}_\mathit{ins}$ & {\tt PCI\_bus} & string & PCI bus path for
pass-through devices \\
+$\mathit{RW}$ & {\tt platform} & (string $\rightarrow$ string) Map &
platform-specific configuration \\
+$\mathit{RW}$ & {\tt PCI\_bus} & string & PCI bus path for pass-through
devices \\
$\mathit{RW}$ & {\tt other\_config} & (string $\rightarrow$ string) Map &
additional configuration \\
$\mathit{RO}_\mathit{run}$ & {\tt domid} & int & domain ID (if available, -1
otherwise) \\
$\mathit{RO}_\mathit{run}$ & {\tt is\_control\_domain} & bool & true if this
is a control domain (domain 0 or a driver domain) \\
@@ -1104,7 +1067,7 @@ Quals & Field & Type & Description \\
$\mathit{RO}_\mathit{run}$ & {\tt guest\_metrics} & VM\_guest\_metrics ref &
metrics associated with the running guest \\
\hline
\end{longtable}
-\subsection{Additional RPCs associated with class: VM}
+\subsection{RPCs associated with class: VM}
\subsubsection{RPC name:~clone}
{\bf Overview:}
@@ -1178,7 +1141,8 @@ void
\vspace{0.3cm}
-\noindent{\bf Possible Error Codes:} {\tt VM\_BAD\_POWER\_STATE}
+\noindent{\bf Possible Error Codes:} {\tt VM\_BAD\_POWER\_STATE}, {\tt
+VM\_HVM\_REQUIRED}
\vspace{0.6cm}
\subsubsection{RPC name:~pause}
@@ -1362,8 +1326,10 @@ void
\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
+
+\noindent{\bf Possible Error Codes:} {\tt VM\_BAD\_POWER\_STATE}
+
+\vspace{0.6cm}
\subsubsection{RPC name:~hard\_reboot}
{\bf Overview:}
@@ -3438,13 +3404,13 @@ void
\vspace{0.3cm}
\vspace{0.3cm}
\vspace{0.3cm}
-\subsubsection{RPC name:~get\_platform\_std\_VGA}
-
-{\bf Overview:}
-Get the platform/std\_VGA field of the given VM.
-
- \noindent {\bf Signature:}
-\begin{verbatim} bool get_platform_std_VGA (session_id s, VM ref
self)\end{verbatim}
+\subsubsection{RPC name:~get\_platform}
+
+{\bf Overview:}
+Get the platform field of the given VM.
+
+ \noindent {\bf Signature:}
+\begin{verbatim} ((string -> string) Map) get_platform (session_id s, VM ref
self)\end{verbatim}
\noindent{\bf Arguments:}
@@ -3462,21 +3428,21 @@ Get the platform/std\_VGA field of the g
\noindent {\bf Return Type:}
{\tt
-bool
-}
-
-
-value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~set\_platform\_std\_VGA}
-
-{\bf Overview:}
-Set the platform/std\_VGA field of the given VM.
-
- \noindent {\bf Signature:}
-\begin{verbatim} void set_platform_std_VGA (session_id s, VM ref self, bool
value)\end{verbatim}
+(string $\rightarrow$ string) Map
+}
+
+
+value of the field
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~set\_platform}
+
+{\bf Overview:}
+Set the platform field of the given VM.
+
+ \noindent {\bf Signature:}
+\begin{verbatim} void set_platform (session_id s, VM ref self, (string ->
string) Map value)\end{verbatim}
\noindent{\bf Arguments:}
@@ -3488,7 +3454,7 @@ Set the platform/std\_VGA field of the g
{\bf type} & {\bf name} & {\bf description} \\ \hline
{\tt VM ref } & self & reference to the object \\ \hline
-{\tt bool } & value & New value to set \\ \hline
+{\tt (string $\rightarrow$ string) Map } & value & New value to set \\ \hline
\end{tabular}
@@ -3504,13 +3470,13 @@ void
\vspace{0.3cm}
\vspace{0.3cm}
\vspace{0.3cm}
-\subsubsection{RPC name:~get\_platform\_serial}
-
-{\bf Overview:}
-Get the platform/serial field of the given VM.
-
- \noindent {\bf Signature:}
-\begin{verbatim} string get_platform_serial (session_id s, VM ref
self)\end{verbatim}
+\subsubsection{RPC name:~add\_to\_platform}
+
+{\bf Overview:}
+Add the given key-value pair to the platform field of the given VM.
+
+ \noindent {\bf Signature:}
+\begin{verbatim} void add_to_platform (session_id s, VM ref self, string key,
string value)\end{verbatim}
\noindent{\bf Arguments:}
@@ -3522,6 +3488,77 @@ Get the platform/serial field of the giv
{\bf type} & {\bf name} & {\bf description} \\ \hline
{\tt VM ref } & self & reference to the object \\ \hline
+{\tt string } & key & Key to add \\ \hline
+
+{\tt string } & value & Value to add \\ \hline
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:}
+{\tt
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~remove\_from\_platform}
+
+{\bf Overview:}
+Remove the given key and its corresponding value from the platform field of
+the given VM. If the key is not in that Map, then do nothing.
+
+ \noindent {\bf Signature:}
+\begin{verbatim} void remove_from_platform (session_id s, VM ref self, string
key)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VM ref } & self & reference to the object \\ \hline
+
+{\tt string } & key & Key to remove \\ \hline
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:}
+{\tt
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~get\_PCI\_bus}
+
+{\bf Overview:}
+Get the PCI\_bus field of the given VM.
+
+ \noindent {\bf Signature:}
+\begin{verbatim} string get_PCI_bus (session_id s, VM ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VM ref } & self & reference to the object \\ \hline
+
\end{tabular}
\vspace{0.3cm}
@@ -3536,13 +3573,13 @@ value of the field
\vspace{0.3cm}
\vspace{0.3cm}
\vspace{0.3cm}
-\subsubsection{RPC name:~set\_platform\_serial}
-
-{\bf Overview:}
-Set the platform/serial field of the given VM.
-
- \noindent {\bf Signature:}
-\begin{verbatim} void set_platform_serial (session_id s, VM ref self, string
value)\end{verbatim}
+\subsubsection{RPC name:~set\_PCI\_bus}
+
+{\bf Overview:}
+Set the PCI\_bus field of the given VM.
+
+ \noindent {\bf Signature:}
+\begin{verbatim} void set_PCI_bus (session_id s, VM ref self, string
value)\end{verbatim}
\noindent{\bf Arguments:}
@@ -3567,236 +3604,6 @@ void
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~get\_platform\_localtime}
-
-{\bf Overview:}
-Get the platform/localtime field of the given VM.
-
- \noindent {\bf Signature:}
-\begin{verbatim} bool get_platform_localtime (session_id s, VM ref
self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
-
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VM ref } & self & reference to the object \\ \hline
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:}
-{\tt
-bool
-}
-
-
-value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~set\_platform\_localtime}
-
-{\bf Overview:}
-Set the platform/localtime field of the given VM.
-
- \noindent {\bf Signature:}
-\begin{verbatim} void set_platform_localtime (session_id s, VM ref self, bool
value)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
-
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VM ref } & self & reference to the object \\ \hline
-
-{\tt bool } & value & New value to set \\ \hline
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:}
-{\tt
-void
-}
-
-
-
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~get\_platform\_clock\_offset}
-
-{\bf Overview:}
-Get the platform/clock\_offset field of the given VM.
-
- \noindent {\bf Signature:}
-\begin{verbatim} bool get_platform_clock_offset (session_id s, VM ref
self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
-
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VM ref } & self & reference to the object \\ \hline
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:}
-{\tt
-bool
-}
-
-
-value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~set\_platform\_clock\_offset}
-
-{\bf Overview:}
-Set the platform/clock\_offset field of the given VM.
-
- \noindent {\bf Signature:}
-\begin{verbatim} void set_platform_clock_offset (session_id s, VM ref self,
bool value)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
-
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VM ref } & self & reference to the object \\ \hline
-
-{\tt bool } & value & New value to set \\ \hline
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:}
-{\tt
-void
-}
-
-
-
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~get\_platform\_enable\_audio}
-
-{\bf Overview:}
-Get the platform/enable\_audio field of the given VM.
-
- \noindent {\bf Signature:}
-\begin{verbatim} bool get_platform_enable_audio (session_id s, VM ref
self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
-
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VM ref } & self & reference to the object \\ \hline
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:}
-{\tt
-bool
-}
-
-
-value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~set\_platform\_enable\_audio}
-
-{\bf Overview:}
-Set the platform/enable\_audio field of the given VM.
-
- \noindent {\bf Signature:}
-\begin{verbatim} void set_platform_enable_audio (session_id s, VM ref self,
bool value)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
-
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VM ref } & self & reference to the object \\ \hline
-
-{\tt bool } & value & New value to set \\ \hline
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:}
-{\tt
-void
-}
-
-
-
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~get\_PCI\_bus}
-
-{\bf Overview:}
-Get the PCI\_bus field of the given VM.
-
- \noindent {\bf Signature:}
-\begin{verbatim} string get_PCI_bus (session_id s, VM ref self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
-
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VM ref } & self & reference to the object \\ \hline
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:}
-{\tt
-string
-}
-
-
-value of the field
\vspace{0.3cm}
\vspace{0.3cm}
\vspace{0.3cm}
@@ -4245,7 +4052,7 @@ Quals & Field & Type & Description \\
$\mathit{RO}_\mathit{run}$ & {\tt VCPUs/utilisation} & (int $\rightarrow$
float) Map & Utilisation for all of guest's current VCPUs \\
\hline
\end{longtable}
-\subsection{Additional RPCs associated with class: VM\_metrics}
+\subsection{RPCs associated with class: VM\_metrics}
\subsubsection{RPC name:~get\_all}
{\bf Overview:}
@@ -4481,7 +4288,7 @@ Quals & Field & Type & Description \\
$\mathit{RO}_\mathit{run}$ & {\tt other} & (string $\rightarrow$ string) Map
& anything else \\
\hline
\end{longtable}
-\subsection{Additional RPCs associated with class: VM\_guest\_metrics}
+\subsection{RPCs associated with class: VM\_guest\_metrics}
\subsubsection{RPC name:~get\_all}
{\bf Overview:}
@@ -4825,7 +4632,7 @@ Quals & Field & Type & Description \\
$\mathit{RO}_\mathit{ins}$ & {\tt metrics} & host\_metrics ref & metrics
associated with this host. \\
\hline
\end{longtable}
-\subsection{Additional RPCs associated with class: host}
+\subsection{RPCs associated with class: host}
\subsubsection{RPC name:~disable}
{\bf Overview:}
@@ -6078,7 +5885,7 @@ Quals & Field & Type & Description \\
$\mathit{RO}_\mathit{run}$ & {\tt memory/free} & int & Host's free memory
(bytes) \\
\hline
\end{longtable}
-\subsection{Additional RPCs associated with class: host\_metrics}
+\subsection{RPCs associated with class: host\_metrics}
\subsubsection{RPC name:~get\_all}
{\bf Overview:}
@@ -6283,7 +6090,7 @@ Quals & Field & Type & Description \\
$\mathit{RO}_\mathit{run}$ & {\tt utilisation} & float & the current CPU
utilisation \\
\hline
\end{longtable}
-\subsection{Additional RPCs associated with class: host\_cpu}
+\subsection{RPCs associated with class: host\_cpu}
\subsubsection{RPC name:~get\_all}
{\bf Overview:}
@@ -6677,7 +6484,7 @@ Quals & Field & Type & Description \\
$\mathit{RO}_\mathit{run}$ & {\tt PIFs} & (PIF ref) Set & list of connected
pifs \\
\hline
\end{longtable}
-\subsection{Additional RPCs associated with class: network}
+\subsection{RPCs associated with class: network}
\subsubsection{RPC name:~get\_all}
{\bf Overview:}
@@ -7115,7 +6922,72 @@ Quals & Field & Type & Description \\
$\mathit{RO}_\mathit{run}$ & {\tt metrics} & VIF\_metrics ref & metrics
associated with this VIF. \\
\hline
\end{longtable}
-\subsection{Additional RPCs associated with class: VIF}
+\subsection{RPCs associated with class: VIF}
+\subsubsection{RPC name:~plug}
+
+{\bf Overview:}
+Hotplug the specified VIF, dynamically attaching it to the running VM.
+
+ \noindent {\bf Signature:}
+\begin{verbatim} void plug (session_id s, VIF ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VIF ref } & self & The VIF to hotplug \\ \hline
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:}
+{\tt
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~unplug}
+
+{\bf Overview:}
+Hot-unplug the specified VIF, dynamically unattaching it from the running
+VM.
+
+ \noindent {\bf Signature:}
+\begin{verbatim} void unplug (session_id s, VIF ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VIF ref } & self & The VIF to hot-unplug \\ \hline
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:}
+{\tt
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
\subsubsection{RPC name:~get\_all}
{\bf Overview:}
@@ -7942,7 +7814,7 @@ Quals & Field & Type & Description \\
$\mathit{RO}_\mathit{run}$ & {\tt io/write\_kbs} & float & Write bandwidth
(KiB/s) \\
\hline
\end{longtable}
-\subsection{Additional RPCs associated with class: VIF\_metrics}
+\subsection{RPCs associated with class: VIF\_metrics}
\subsubsection{RPC name:~get\_all}
{\bf Overview:}
@@ -8148,7 +8020,7 @@ Quals & Field & Type & Description \\
$\mathit{RO}_\mathit{ins}$ & {\tt metrics} & PIF\_metrics ref & metrics
associated with this PIF. \\
\hline
\end{longtable}
-\subsection{Additional RPCs associated with class: PIF}
+\subsection{RPCs associated with class: PIF}
\subsubsection{RPC name:~create\_VLAN}
{\bf Overview:}
@@ -8719,7 +8591,7 @@ Quals & Field & Type & Description \\
$\mathit{RO}_\mathit{run}$ & {\tt io/write\_kbs} & float & Write bandwidth
(KiB/s) \\
\hline
\end{longtable}
-\subsection{Additional RPCs associated with class: PIF\_metrics}
+\subsection{RPCs associated with class: PIF\_metrics}
\subsubsection{RPC name:~get\_all}
{\bf Overview:}
@@ -8926,7 +8798,7 @@ Quals & Field & Type & Description \\
$\mathit{RO}_\mathit{ins}$ & {\tt location} & string & a string that uniquely
determines the location of the storage repository; the format of this string
depends on the repository's type \\
\hline
\end{longtable}
-\subsection{Additional RPCs associated with class: SR}
+\subsection{RPCs associated with class: SR}
\subsubsection{RPC name:~clone}
{\bf Overview:}
@@ -9549,7 +9421,7 @@ Quals & Field & Type & Description \\
$\mathit{RO}_\mathit{run}$ & {\tt uuid} & string & unique identifier/object
reference \\
$\mathit{RW}$ & {\tt name/label} & string & a human-readable name \\
$\mathit{RW}$ & {\tt name/description} & string & a notes field containg
human-readable description \\
-$\mathit{RW}$ & {\tt SR} & SR ref & storage repository in which the VDI
resides \\
+$\mathit{RO}_\mathit{ins}$ & {\tt SR} & SR ref & storage repository in which
the VDI resides \\
$\mathit{RO}_\mathit{run}$ & {\tt VBDs} & (VBD ref) Set & list of vbds that
refer to this disk \\
$\mathit{RO}_\mathit{run}$ & {\tt crash\_dumps} & (crashdump ref) Set & list
of crash dumps that refer to this disk \\
$\mathit{RW}$ & {\tt virtual\_size} & int & size of disk as presented to the
guest (in bytes). Note that, depending on storage backend type, requested size
may not be respected exactly \\
@@ -9560,7 +9432,7 @@ Quals & Field & Type & Description \\
$\mathit{RW}$ & {\tt read\_only} & bool & true if this disk may ONLY be
mounted read-only \\
\hline
\end{longtable}
-\subsection{Additional RPCs associated with class: VDI}
+\subsection{RPCs associated with class: VDI}
\subsubsection{RPC name:~snapshot}
{\bf Overview:}
@@ -9842,40 +9714,6 @@ SR ref
value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~set\_SR}
-
-{\bf Overview:}
-Set the SR field of the given VDI.
-
- \noindent {\bf Signature:}
-\begin{verbatim} void set_SR (session_id s, VDI ref self, SR ref
value)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
-
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt VDI ref } & self & reference to the object \\ \hline
-
-{\tt SR ref } & value & New value to set \\ \hline
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:}
-{\tt
-void
-}
-
-
-
\vspace{0.3cm}
\vspace{0.3cm}
\vspace{0.3cm}
@@ -10426,7 +10264,7 @@ Quals & Field & Type & Description \\
$\mathit{RO}_\mathit{run}$ & {\tt metrics} & VBD\_metrics ref & metrics
associated with this VBD \\
\hline
\end{longtable}
-\subsection{Additional RPCs associated with class: VBD}
+\subsection{RPCs associated with class: VBD}
\subsubsection{RPC name:~media\_change}
{\bf Overview:}
@@ -10447,6 +10285,71 @@ devices, detach the VBD and attach a new
{\tt VBD ref } & vbd & The vbd representing the CDROM-like device \\ \hline
{\tt VDI ref } & vdi & The new VDI to 'insert' \\ \hline
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:}
+{\tt
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~plug}
+
+{\bf Overview:}
+Hotplug the specified VBD, dynamically attaching it to the running VM.
+
+ \noindent {\bf Signature:}
+\begin{verbatim} void plug (session_id s, VBD ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD ref } & self & The VBD to hotplug \\ \hline
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:}
+{\tt
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
+\subsubsection{RPC name:~unplug}
+
+{\bf Overview:}
+Hot-unplug the specified VBD, dynamically unattaching it from the running
+VM.
+
+ \noindent {\bf Signature:}
+\begin{verbatim} void unplug (session_id s, VBD ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt VBD ref } & self & The VBD to hot-unplug \\ \hline
\end{tabular}
@@ -11354,7 +11257,7 @@ Quals & Field & Type & Description \\
$\mathit{RO}_\mathit{run}$ & {\tt io/write\_kbs} & float & Write bandwidth
(KiB/s) \\
\hline
\end{longtable}
-\subsection{Additional RPCs associated with class: VBD\_metrics}
+\subsection{RPCs associated with class: VBD\_metrics}
\subsubsection{RPC name:~get\_all}
{\bf Overview:}
@@ -11556,7 +11459,7 @@ Quals & Field & Type & Description \\
$\mathit{RO}_\mathit{run}$ & {\tt currently\_attached} & bool & is the SR
currently attached on this host? \\
\hline
\end{longtable}
-\subsection{Additional RPCs associated with class: PBD}
+\subsection{RPCs associated with class: PBD}
\subsubsection{RPC name:~get\_all}
{\bf Overview:}
@@ -11884,7 +11787,39 @@ Quals & Field & Type & Description \\
$\mathit{RO}_\mathit{ins}$ & {\tt VDI} & VDI ref & the virtual disk \\
\hline
\end{longtable}
-\subsection{Additional RPCs associated with class: crashdump}
+\subsection{RPCs associated with class: crashdump}
+\subsubsection{RPC name:~destroy}
+
+{\bf Overview:}
+Destroy the specified crashdump.
+
+ \noindent {\bf Signature:}
+\begin{verbatim} void destroy (session_id s, crashdump ref self)\end{verbatim}
+
+
+\noindent{\bf Arguments:}
+
+
+\vspace{0.3cm}
+\begin{tabular}{|c|c|p{7cm}|}
+ \hline
+{\bf type} & {\bf name} & {\bf description} \\ \hline
+{\tt crashdump ref } & self & The crashdump to destroy \\ \hline
+
+\end{tabular}
+
+\vspace{0.3cm}
+
+ \noindent {\bf Return Type:}
+{\tt
+void
+}
+
+
+
+\vspace{0.3cm}
+\vspace{0.3cm}
+\vspace{0.3cm}
\subsubsection{RPC name:~get\_all}
{\bf Overview:}
@@ -11999,70 +11934,6 @@ VDI ref
value of the field
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~create}
-
-{\bf Overview:}
-Create a new crashdump instance, and return its handle.
-
- \noindent {\bf Signature:}
-\begin{verbatim} (crashdump ref) create (session_id s, crashdump record
args)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
-
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt crashdump record } & args & All constructor arguments \\ \hline
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:}
-{\tt
-crashdump ref
-}
-
-
-reference to the newly created object
-\vspace{0.3cm}
-\vspace{0.3cm}
-\vspace{0.3cm}
-\subsubsection{RPC name:~destroy}
-
-{\bf Overview:}
-Destroy the specified crashdump instance.
-
- \noindent {\bf Signature:}
-\begin{verbatim} void destroy (session_id s, crashdump ref self)\end{verbatim}
-
-
-\noindent{\bf Arguments:}
-
-
-\vspace{0.3cm}
-\begin{tabular}{|c|c|p{7cm}|}
- \hline
-{\bf type} & {\bf name} & {\bf description} \\ \hline
-{\tt crashdump ref } & self & reference to the object \\ \hline
-
-\end{tabular}
-
-\vspace{0.3cm}
-
- \noindent {\bf Return Type:}
-{\tt
-void
-}
-
-
-
\vspace{0.3cm}
\vspace{0.3cm}
\vspace{0.3cm}
@@ -12148,7 +12019,7 @@ Quals & Field & Type & Description \\
$\mathit{RO}_\mathit{ins}$ & {\tt backend} & VM ref & the domain where the
backend is located \\
\hline
\end{longtable}
-\subsection{Additional RPCs associated with class: VTPM}
+\subsection{RPCs associated with class: VTPM}
\subsubsection{RPC name:~get\_uuid}
{\bf Overview:}
@@ -12393,7 +12264,7 @@ Quals & Field & Type & Description \\
$\mathit{RW}$ & {\tt other\_config} & (string $\rightarrow$ string) Map &
additional configuration \\
\hline
\end{longtable}
-\subsection{Additional RPCs associated with class: console}
+\subsection{RPCs associated with class: console}
\subsubsection{RPC name:~get\_all}
{\bf Overview:}
@@ -12828,7 +12699,7 @@ Quals & Field & Type & Description \\
$\mathit{RW}$ & {\tt fullname} & string & full name \\
\hline
\end{longtable}
-\subsection{Additional RPCs associated with class: user}
+\subsection{RPCs associated with class: user}
\subsubsection{RPC name:~get\_uuid}
{\bf Overview:}
@@ -13093,7 +12964,7 @@ all fields from the object
\section{Class: debug}
\subsection{Fields for class: debug}
{\bf Class debug has no fields.}
-\subsection{Additional RPCs associated with class: debug}
+\subsection{RPCs associated with class: debug}
\subsubsection{RPC name:~get\_all}
{\bf Overview:}
@@ -13467,6 +13338,15 @@ expected and actual VM state at the time
\begin{verbatim}VM_BAD_POWER_STATE(vm, expected, actual)\end{verbatim}
\begin{center}\rule{10em}{0.1pt}\end{center}
+\subsubsection{VM\_HVM\_REQUIRED}
+
+HVM is required for this operation
+
+\vspace{0.3cm}
+{\bf Signature:}
+\begin{verbatim}VM_HVM_REQUIRED(vm)\end{verbatim}
+\begin{center}\rule{10em}{0.1pt}\end{center}
+
\newpage
diff -r d1853a39e063 -r cb2575cec95c docs/xen-api/xenapi.tex
--- a/docs/xen-api/xenapi.tex Mon Mar 12 09:43:48 2007 -0600
+++ b/docs/xen-api/xenapi.tex Mon Mar 12 10:07:08 2007 -0600
@@ -16,6 +16,7 @@
\usepackage{a4wide}
\usepackage{graphics}
\usepackage{longtable}
+\usepackage{fancyhdr}
\setlength\topskip{0cm}
\setlength\topmargin{0cm}
@@ -35,7 +36,7 @@
\chapter{Introduction}
-This document contains a proposal for a Xen Management API---an interface for
+This document contains a description of the Xen Management API---an interface
for
remotely configuring and controlling virtualised guests running on a
Xen-enabled host.
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/arch/i386/kernel/cpu/mtrr/main-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/cpu/mtrr/main-xen.c Mon Mar 12
09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/cpu/mtrr/main-xen.c Mon Mar 12
10:07:08 2007 -0600
@@ -14,11 +14,11 @@ void generic_get_mtrr(unsigned int reg,
void generic_get_mtrr(unsigned int reg, unsigned long *base,
unsigned int *size, mtrr_type * type)
{
- dom0_op_t op;
+ struct xen_platform_op op;
- op.cmd = DOM0_READ_MEMTYPE;
+ op.cmd = XENPF_read_memtype;
op.u.read_memtype.reg = reg;
- (void)HYPERVISOR_dom0_op(&op);
+ (void)HYPERVISOR_platform_op(&op);
*size = op.u.read_memtype.nr_mfns;
*base = op.u.read_memtype.mfn;
@@ -36,12 +36,12 @@ unsigned int *usage_table;
static void __init set_num_var_ranges(void)
{
- dom0_op_t op;
+ struct xen_platform_op op;
for (num_var_ranges = 0; ; num_var_ranges++) {
- op.cmd = DOM0_READ_MEMTYPE;
+ op.cmd = XENPF_read_memtype;
op.u.read_memtype.reg = num_var_ranges;
- if (HYPERVISOR_dom0_op(&op) != 0)
+ if (HYPERVISOR_platform_op(&op) != 0)
break;
}
}
@@ -64,15 +64,15 @@ int mtrr_add_page(unsigned long base, un
unsigned int type, char increment)
{
int error;
- dom0_op_t op;
+ struct xen_platform_op op;
mutex_lock(&mtrr_mutex);
- op.cmd = DOM0_ADD_MEMTYPE;
+ op.cmd = XENPF_add_memtype;
op.u.add_memtype.mfn = base;
op.u.add_memtype.nr_mfns = size;
op.u.add_memtype.type = type;
- error = HYPERVISOR_dom0_op(&op);
+ error = HYPERVISOR_platform_op(&op);
if (error) {
mutex_unlock(&mtrr_mutex);
BUG_ON(error > 0);
@@ -117,7 +117,7 @@ int mtrr_del_page(int reg, unsigned long
unsigned long lbase;
unsigned int lsize;
int error = -EINVAL;
- dom0_op_t op;
+ struct xen_platform_op op;
mutex_lock(&mtrr_mutex);
@@ -141,10 +141,10 @@ int mtrr_del_page(int reg, unsigned long
goto out;
}
if (--usage_table[reg] < 1) {
- op.cmd = DOM0_DEL_MEMTYPE;
+ op.cmd = XENPF_del_memtype;
op.u.del_memtype.handle = 0;
op.u.del_memtype.reg = reg;
- error = HYPERVISOR_dom0_op(&op);
+ error = HYPERVISOR_platform_op(&op);
if (error) {
BUG_ON(error > 0);
goto out;
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c Mon Mar 12
09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c Mon Mar 12
10:07:08 2007 -0600
@@ -2510,10 +2510,10 @@ static int __init io_apic_bug_finalize(v
if(sis_apic_bug == -1)
sis_apic_bug = 0;
if (is_initial_xendomain()) {
- dom0_op_t op = { .cmd = DOM0_PLATFORM_QUIRK };
+ struct xen_platform_op op = { .cmd = XENPF_platform_quirk };
op.u.platform_quirk.quirk_id = sis_apic_bug ?
QUIRK_IOAPIC_BAD_REGSEL : QUIRK_IOAPIC_GOOD_REGSEL;
- HYPERVISOR_dom0_op(&op);
+ HYPERVISOR_platform_op(&op);
}
return 0;
}
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/arch/i386/kernel/ioport-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/ioport-xen.c Mon Mar 12
09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/ioport-xen.c Mon Mar 12
10:07:08 2007 -0600
@@ -81,7 +81,7 @@ asmlinkage long sys_ioperm(unsigned long
t->io_bitmap_ptr = bitmap;
set_thread_flag(TIF_IO_BITMAP);
- set_iobitmap.bitmap = (char *)bitmap;
+ set_xen_guest_handle(set_iobitmap.bitmap, (char *)bitmap);
set_iobitmap.nr_ports = IO_BITMAP_BITS;
HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap, &set_iobitmap);
}
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c Mon Mar 12
09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c Mon Mar 12
10:07:08 2007 -0600
@@ -71,12 +71,12 @@ static int do_microcode_update (const vo
return -ENOMEM;
if (copy_from_user(kbuf, ubuf, len) == 0) {
- dom0_op_t op;
+ struct xen_platform_op op;
- op.cmd = DOM0_MICROCODE;
+ op.cmd = XENPF_microcode_update;
set_xen_guest_handle(op.u.microcode.data, kbuf);
op.u.microcode.length = len;
- err = HYPERVISOR_dom0_op(&op);
+ err = HYPERVISOR_platform_op(&op);
} else
err = -EFAULT;
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c Mon Mar 12
09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/process-xen.c Mon Mar 12
10:07:08 2007 -0600
@@ -307,7 +307,8 @@ void exit_thread(void)
if (unlikely(test_thread_flag(TIF_IO_BITMAP))) {
struct task_struct *tsk = current;
struct thread_struct *t = &tsk->thread;
- struct physdev_set_iobitmap set_iobitmap = { 0 };
+ struct physdev_set_iobitmap set_iobitmap;
+ memset(&set_iobitmap, 0, sizeof(set_iobitmap));
HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap, &set_iobitmap);
kfree(t->io_bitmap_ptr);
t->io_bitmap_ptr = NULL;
@@ -606,7 +607,8 @@ struct task_struct fastcall * __switch_t
}
if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) {
- iobmp_op.bitmap = (char *)next->io_bitmap_ptr;
+ set_xen_guest_handle(iobmp_op.bitmap,
+ (char *)next->io_bitmap_ptr);
iobmp_op.nr_ports = next->io_bitmap_ptr ? IO_BITMAP_BITS : 0;
mcl->op = __HYPERVISOR_physdev_op;
mcl->args[0] = PHYSDEVOP_set_iobitmap;
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/arch/i386/kernel/quirks-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/quirks-xen.c Mon Mar 12
09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/quirks-xen.c Mon Mar 12
10:07:08 2007 -0600
@@ -30,11 +30,11 @@ static void __devinit quirk_intel_irqbal
raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word);
if (!(word & (1 << 13))) {
- dom0_op_t op;
+ struct xen_platform_op op;
printk(KERN_INFO "Disabling irq balancing and affinity\n");
- op.cmd = DOM0_PLATFORM_QUIRK;
+ op.cmd = XENPF_platform_quirk;
op.u.platform_quirk.quirk_id = QUIRK_NOIRQBALANCING;
- (void)HYPERVISOR_dom0_op(&op);
+ (void)HYPERVISOR_platform_op(&op);
}
/* put back the original value for config space*/
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c Mon Mar 12 09:43:48
2007 -0600
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c Mon Mar 12 10:07:08
2007 -0600
@@ -435,7 +435,7 @@ int do_settimeofday(struct timespec *tv)
s64 nsec;
unsigned int cpu;
struct shadow_time_info *shadow;
- dom0_op_t op;
+ struct xen_platform_op op;
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
return -EINVAL;
@@ -460,11 +460,11 @@ int do_settimeofday(struct timespec *tv)
__normalize_time(&sec, &nsec);
if (is_initial_xendomain() && !independent_wallclock) {
- op.cmd = DOM0_SETTIME;
+ op.cmd = XENPF_settime;
op.u.settime.secs = sec;
op.u.settime.nsecs = nsec;
op.u.settime.system_time = shadow->system_timestamp;
- HYPERVISOR_dom0_op(&op);
+ HYPERVISOR_platform_op(&op);
update_wallclock();
} else if (independent_wallclock) {
nsec -= shadow->system_timestamp;
@@ -488,7 +488,7 @@ static void sync_xen_wallclock(unsigned
{
time_t sec;
s64 nsec;
- dom0_op_t op;
+ struct xen_platform_op op;
if (!ntp_synced() || independent_wallclock || !is_initial_xendomain())
return;
@@ -499,11 +499,11 @@ static void sync_xen_wallclock(unsigned
nsec = xtime.tv_nsec + ((jiffies - wall_jiffies) * (u64)NS_PER_TICK);
__normalize_time(&sec, &nsec);
- op.cmd = DOM0_SETTIME;
+ op.cmd = XENPF_settime;
op.u.settime.secs = sec;
op.u.settime.nsecs = nsec;
op.u.settime.system_time = processed_system_time;
- HYPERVISOR_dom0_op(&op);
+ HYPERVISOR_platform_op(&op);
update_wallclock();
@@ -907,6 +907,10 @@ static void setup_cpu0_timer_irq(void)
BUG_ON(per_cpu(timer_irq, 0) < 0);
}
+static struct vcpu_set_periodic_timer xen_set_periodic_tick = {
+ .period_ns = NS_PER_TICK
+};
+
void __init time_init(void)
{
#ifdef CONFIG_HPET_TIMER
@@ -919,6 +923,10 @@ void __init time_init(void)
return;
}
#endif
+
+ HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, 0,
+ &xen_set_periodic_tick);
+
get_time_values_from_xen(0);
processed_system_time = per_cpu(shadow_time, 0).system_timestamp;
@@ -976,8 +984,10 @@ EXPORT_SYMBOL(jiffies_to_st);
*/
static void stop_hz_timer(void)
{
+ struct vcpu_set_singleshot_timer singleshot;
unsigned int cpu = smp_processor_id();
unsigned long j;
+ int rc;
cpu_set(cpu, nohz_cpu_mask);
@@ -997,8 +1007,16 @@ static void stop_hz_timer(void)
j = jiffies + 1;
}
- if (HYPERVISOR_set_timer_op(jiffies_to_st(j)) != 0)
- BUG();
+ singleshot.timeout_abs_ns = jiffies_to_st(j);
+ singleshot.flags = 0;
+ rc = HYPERVISOR_vcpu_op(VCPUOP_set_singleshot_timer, cpu, &singleshot);
+#ifdef XEN_COMPAT_030004
+ if (rc) {
+ BUG_ON(rc != -ENOSYS);
+ rc = HYPERVISOR_set_timer_op(singleshot.timeout_abs_ns);
+ }
+#endif
+ BUG_ON(rc);
}
static void start_hz_timer(void)
@@ -1030,6 +1048,8 @@ void time_resume(void)
init_cpu_khz();
for_each_online_cpu(cpu) {
+ HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, cpu,
+ &xen_set_periodic_tick);
get_time_values_from_xen(cpu);
per_cpu(processed_system_time, cpu) =
per_cpu(shadow_time, 0).system_timestamp;
@@ -1049,6 +1069,9 @@ int local_setup_timer(unsigned int cpu)
int seq, irq;
BUG_ON(cpu == 0);
+
+ HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, cpu,
+ &xen_set_periodic_tick);
do {
seq = read_seqbegin(&xtime_lock);
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c
--- a/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c Mon Mar 12 09:43:48
2007 -0600
+++ b/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c Mon Mar 12 10:07:08
2007 -0600
@@ -146,7 +146,7 @@ void xen_tlb_flush_mask(cpumask_t *mask)
if ( cpus_empty(*mask) )
return;
op.cmd = MMUEXT_TLB_FLUSH_MULTI;
- op.arg2.vcpumask = mask->bits;
+ set_xen_guest_handle(op.arg2.vcpumask, mask->bits);
BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
}
@@ -165,7 +165,7 @@ void xen_invlpg_mask(cpumask_t *mask, un
return;
op.cmd = MMUEXT_INVLPG_MULTI;
op.arg1.linear_addr = ptr & PAGE_MASK;
- op.arg2.vcpumask = mask->bits;
+ set_xen_guest_handle(op.arg2.vcpumask, mask->bits);
BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
}
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c Mon Mar 12 09:43:48
2007 -0600
+++ b/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c Mon Mar 12 10:07:08
2007 -0600
@@ -600,7 +600,7 @@ static void pgd_walk(pgd_t *pgd_base, pg
int g, u, m, rc;
if (xen_feature(XENFEAT_auto_translated_physmap))
- return 0;
+ return;
for (g = 0; g < USER_PTRS_PER_PGD; g++, pgd++) {
if (pgd_none(*pgd))
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/arch/ia64/xen/xcom_hcall.c
--- a/linux-2.6-xen-sparse/arch/ia64/xen/xcom_hcall.c Mon Mar 12 09:43:48
2007 -0600
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/xcom_hcall.c Mon Mar 12 10:07:08
2007 -0600
@@ -21,7 +21,7 @@
#include <linux/gfp.h>
#include <linux/module.h>
#include <xen/interface/xen.h>
-#include <xen/interface/dom0_ops.h>
+#include <xen/interface/platform.h>
#include <xen/interface/memory.h>
#include <xen/interface/xencomm.h>
#include <xen/interface/version.h>
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/arch/ia64/xen/xcom_mini.c
--- a/linux-2.6-xen-sparse/arch/ia64/xen/xcom_mini.c Mon Mar 12 09:43:48
2007 -0600
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/xcom_mini.c Mon Mar 12 10:07:08
2007 -0600
@@ -20,7 +20,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <xen/interface/xen.h>
-#include <xen/interface/dom0_ops.h>
+#include <xen/interface/platform.h>
#include <xen/interface/memory.h>
#include <xen/interface/xencomm.h>
#include <xen/interface/version.h>
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c
--- a/linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c Mon Mar 12 09:43:48
2007 -0600
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/xcom_privcmd.c Mon Mar 12 10:07:08
2007 -0600
@@ -22,7 +22,7 @@
#include <linux/gfp.h>
#include <linux/module.h>
#include <xen/interface/xen.h>
-#include <xen/interface/dom0_ops.h>
+#include <xen/interface/platform.h>
#define __XEN__
#include <xen/interface/domctl.h>
#include <xen/interface/sysctl.h>
@@ -40,25 +40,25 @@
#define ROUND_DIV(v,s) (((v) + (s) - 1) / (s))
static int
-xencomm_privcmd_dom0_op(privcmd_hypercall_t *hypercall)
-{
- dom0_op_t kern_op;
- dom0_op_t __user *user_op = (dom0_op_t __user *)hypercall->arg[0];
+xencomm_privcmd_platform_op(privcmd_hypercall_t *hypercall)
+{
+ struct xen_platform_op kern_op;
+ struct xen_platform_op __user *user_op = (struct xen_platform_op __user
*)hypercall->arg[0];
struct xencomm_handle *op_desc;
struct xencomm_handle *desc = NULL;
int ret = 0;
- if (copy_from_user(&kern_op, user_op, sizeof(dom0_op_t)))
+ if (copy_from_user(&kern_op, user_op, sizeof(struct xen_platform_op)))
return -EFAULT;
- if (kern_op.interface_version != DOM0_INTERFACE_VERSION)
+ if (kern_op.interface_version != XENPF_INTERFACE_VERSION)
return -EACCES;
op_desc = xencomm_create_inline(&kern_op);
switch (kern_op.cmd) {
default:
- printk("%s: unknown dom0 cmd %d\n", __func__, kern_op.cmd);
+ printk("%s: unknown platform cmd %d\n", __func__, kern_op.cmd);
return -ENOSYS;
}
@@ -67,10 +67,10 @@ xencomm_privcmd_dom0_op(privcmd_hypercal
return ret;
}
- ret = xencomm_arch_hypercall_dom0_op(op_desc);
+ ret = xencomm_arch_hypercall_platform_op(op_desc);
/* FIXME: should we restore the handle? */
- if (copy_to_user(user_op, &kern_op, sizeof(dom0_op_t)))
+ if (copy_to_user(user_op, &kern_op, sizeof(struct xen_platform_op)))
ret = -EFAULT;
if (desc)
@@ -638,8 +638,8 @@ privcmd_hypercall(privcmd_hypercall_t *h
privcmd_hypercall(privcmd_hypercall_t *hypercall)
{
switch (hypercall->op) {
- case __HYPERVISOR_dom0_op:
- return xencomm_privcmd_dom0_op(hypercall);
+ case __HYPERVISOR_platform_op:
+ return xencomm_privcmd_platform_op(hypercall);
case __HYPERVISOR_domctl:
return xencomm_privcmd_domctl(hypercall);
case __HYPERVISOR_sysctl:
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/arch/x86_64/kernel/ioport-xen.c
--- a/linux-2.6-xen-sparse/arch/x86_64/kernel/ioport-xen.c Mon Mar 12
09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/ioport-xen.c Mon Mar 12
10:07:08 2007 -0600
@@ -59,7 +59,7 @@ asmlinkage long sys_ioperm(unsigned long
memset(bitmap, 0xff, IO_BITMAP_BYTES);
t->io_bitmap_ptr = bitmap;
- set_iobitmap.bitmap = (char *)bitmap;
+ set_xen_guest_handle(set_iobitmap.bitmap, (char *)bitmap);
set_iobitmap.nr_ports = IO_BITMAP_BITS;
HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap, &set_iobitmap);
}
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c
--- a/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c Mon Mar 12
09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/process-xen.c Mon Mar 12
10:07:08 2007 -0600
@@ -50,7 +50,7 @@
#include <asm/pda.h>
#include <asm/prctl.h>
#include <asm/kdebug.h>
-#include <xen/interface/dom0_ops.h>
+#include <xen/interface/platform.h>
#include <xen/interface/physdev.h>
#include <xen/interface/vcpu.h>
#include <asm/desc.h>
@@ -304,7 +304,8 @@ void exit_thread(void)
struct tss_struct *tss = &per_cpu(init_tss, get_cpu());
#endif
#ifdef CONFIG_XEN
- struct physdev_set_iobitmap iobmp_op = { 0 };
+ struct physdev_set_iobitmap iobmp_op;
+ memset(&iobmp_op, 0, sizeof(iobmp_op));
#endif
kfree(t->io_bitmap_ptr);
@@ -540,7 +541,8 @@ __switch_to(struct task_struct *prev_p,
}
if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) {
- iobmp_op.bitmap = (char *)next->io_bitmap_ptr;
+ set_xen_guest_handle(iobmp_op.bitmap,
+ (char *)next->io_bitmap_ptr);
iobmp_op.nr_ports = next->io_bitmap_ptr ? IO_BITMAP_BITS : 0;
mcl->op = __HYPERVISOR_physdev_op;
mcl->args[0] = PHYSDEVOP_set_iobitmap;
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c
--- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c Mon Mar 12 09:43:48
2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.c Mon Mar 12 10:07:08
2007 -0600
@@ -504,7 +504,6 @@ static struct tpm_vendor_specific tpm_vt
};
struct tpm_chip *init_vtpm(struct device *dev,
- struct tpm_virtual_device *tvd,
struct tpm_private *tp)
{
long rc;
@@ -516,7 +515,6 @@ struct tpm_chip *init_vtpm(struct device
return ERR_PTR(-ENOMEM);
vtpm_state_init(vtpms);
- vtpms->tpmvd = tvd;
vtpms->tpm_private = tp;
chip = tpm_register_hardware(dev, &tpm_vtpm);
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.h
--- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.h Mon Mar 12 09:43:48
2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_vtpm.h Mon Mar 12 10:07:08
2007 -0600
@@ -3,16 +3,6 @@
struct tpm_chip;
struct tpm_private;
-
-struct tpm_virtual_device {
- /*
- * This field indicates the maximum size the driver can
- * transfer in one chunk. It is filled in by the front-end
- * driver and should be propagated to the generic tpm driver
- * for allocation of buffers.
- */
- unsigned int max_tx_size;
-};
struct vtpm_state {
struct transmission *current_request;
@@ -30,8 +20,6 @@ struct vtpm_state {
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.
@@ -51,7 +39,6 @@ int vtpm_vd_send(struct tpm_private * tp
/* these functions are offered by tpm_vtpm.c */
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,
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c
--- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c Mon Mar 12 09:43:48
2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c Mon Mar 12 10:07:08
2007 -0600
@@ -369,10 +369,6 @@ static void backend_changed(struct xenbu
}
}
-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)
{
@@ -383,7 +379,7 @@ static int tpmfront_probe(struct xenbus_
if (!tp)
return -ENOMEM;
- tp->chip = init_vtpm(&dev->dev, &tvd, tp);
+ tp->chip = init_vtpm(&dev->dev, tp);
if (IS_ERR(tp->chip))
return PTR_ERR(tp->chip);
@@ -500,11 +496,6 @@ static void __init init_tpm_xenbus(void)
xenbus_register_frontend(&tpmfront);
}
-static void __exit exit_tpm_xenbus(void)
-{
- xenbus_unregister_driver(&tpmfront);
-}
-
static int tpmif_allocate_tx_buffers(struct tpm_private *tp)
{
unsigned int i;
@@ -530,13 +521,11 @@ static void tpmif_rx_action(unsigned lon
static void tpmif_rx_action(unsigned long priv)
{
struct tpm_private *tp = (struct tpm_private *)priv;
-
int i = 0;
unsigned int received;
unsigned int offset = 0;
u8 *buffer;
- tpmif_tx_request_t *tx;
- tx = &tp->tx->ring[i].req;
+ tpmif_tx_request_t *tx = &tp->tx->ring[i].req;
atomic_set(&tp->tx_busy, 0);
wake_up_interruptible(&tp->wait_q);
@@ -545,7 +534,7 @@ static void tpmif_rx_action(unsigned lon
buffer = kmalloc(received, GFP_ATOMIC);
if (!buffer)
- goto exit;
+ return;
for (i = 0; i < TPMIF_TX_RING_SIZE && offset < received; i++) {
struct tx_buffer *txb = tp->tx_buffers[i];
@@ -566,10 +555,6 @@ static void tpmif_rx_action(unsigned lon
vtpm_vd_recv(tp->chip, buffer, received, tp->tx_remember);
kfree(buffer);
-
-exit:
-
- return;
}
@@ -730,13 +715,6 @@ static int __init tpmif_init(void)
}
-void __exit tpmif_exit(void)
-{
- exit_tpm_xenbus();
- tpm_private_put();
- gnttab_free_grant_references(gref_head);
-}
-
module_init(tpmif_init);
MODULE_LICENSE("Dual BSD/GPL");
diff -r d1853a39e063 -r cb2575cec95c linux-2.6-xen-sparse/drivers/xen/Kconfig
--- a/linux-2.6-xen-sparse/drivers/xen/Kconfig Mon Mar 12 09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/Kconfig Mon Mar 12 10:07:08 2007 -0600
@@ -13,7 +13,7 @@ if XEN
if XEN
config XEN_INTERFACE_VERSION
hex
- default 0x00030203
+ default 0x00030205
menu "XEN"
@@ -227,6 +227,9 @@ choice
config XEN_COMPAT_030002_AND_LATER
bool "3.0.2 and later"
+ config XEN_COMPAT_030004_AND_LATER
+ bool "3.0.4 and later"
+
config XEN_COMPAT_LATEST_ONLY
bool "no compatibility code"
@@ -236,6 +239,10 @@ config XEN_COMPAT_030002
bool
default XEN_COMPAT_030002_AND_LATER
+config XEN_COMPAT_030004
+ bool
+ default XEN_COMPAT_030002_AND_LATER || XEN_COMPAT_030004_AND_LATER
+
endmenu
config HAVE_IRQ_IGNORE_UNHANDLED
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c
--- a/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c Mon Mar 12
09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c Mon Mar 12
10:07:08 2007 -0600
@@ -11,7 +11,6 @@
#include <asm/mmu_context.h>
#include <xen/evtchn.h>
#include <asm/hypervisor.h>
-#include <xen/interface/dom0_ops.h>
#include <xen/xenbus.h>
#include <linux/cpu.h>
#include <linux/kthread.h>
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c
--- a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c Mon Mar 12
09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space.c Mon Mar 12
10:07:08 2007 -0600
@@ -349,16 +349,12 @@ void pciback_config_free_dev(struct pci_
int pciback_config_add_field_offset(struct pci_dev *dev,
struct config_field *field,
- unsigned int offset)
+ unsigned int base_offset)
{
int err = 0;
struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
struct config_field_entry *cfg_entry;
void *tmp;
-
- /* silently ignore duplicate fields */
- if (pciback_field_is_dup(dev, field->offset))
- goto out;
cfg_entry = kmalloc(sizeof(*cfg_entry), GFP_KERNEL);
if (!cfg_entry) {
@@ -368,7 +364,12 @@ int pciback_config_add_field_offset(stru
cfg_entry->data = NULL;
cfg_entry->field = field;
- cfg_entry->base_offset = offset;
+ cfg_entry->base_offset = base_offset;
+
+ /* silently ignore duplicate fields */
+ err = pciback_field_is_dup(dev,OFFSET(cfg_entry));
+ if (err)
+ goto out;
if (field->init) {
tmp = field->init(dev, OFFSET(cfg_entry));
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.c
--- a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.c Mon Mar
12 09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.c Mon Mar
12 10:07:08 2007 -0600
@@ -32,16 +32,14 @@ static inline void register_quirk(struct
list_add_tail(&quirk->quirks_list, &pciback_quirks);
}
-int pciback_field_is_dup(struct pci_dev *dev, int reg)
+int pciback_field_is_dup(struct pci_dev *dev, unsigned int reg)
{
int ret = 0;
struct pciback_dev_data *dev_data = pci_get_drvdata(dev);
- struct config_field *field;
struct config_field_entry *cfg_entry;
list_for_each_entry(cfg_entry, &dev_data->config_fields, list) {
- field = cfg_entry->field;
- if (field->offset == reg) {
+ if ( OFFSET(cfg_entry) == reg) {
ret = 1;
break;
}
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.h
--- a/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.h Mon Mar
12 09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/conf_space_quirks.h Mon Mar
12 10:07:08 2007 -0600
@@ -30,6 +30,6 @@ void pciback_config_field_free(struct co
int pciback_config_quirk_release(struct pci_dev *dev);
-int pciback_field_is_dup(struct pci_dev *dev, int reg);
+int pciback_field_is_dup(struct pci_dev *dev, unsigned int reg);
#endif
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c
--- a/linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c Mon Mar 12
09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/pciback/pci_stub.c Mon Mar 12
10:07:08 2007 -0600
@@ -589,10 +589,6 @@ static int pcistub_reg_add(int domain, i
}
dev = psdev->dev;
- /* check for duplicate field */
- if (pciback_field_is_dup(dev, reg))
- goto out;
-
field = kzalloc(sizeof(*field), GFP_ATOMIC);
if (!field) {
err = -ENOMEM;
@@ -728,10 +724,10 @@ static ssize_t pcistub_quirk_show(struct
if (count >= PAGE_SIZE)
goto out;
- count += scnprintf(buf + count, PAGE_SIZE -
- count, "\t\t%08x:%01x:%08x\n",
- field->offset, field->size,
- field->mask);
+ count += scnprintf(buf + count, PAGE_SIZE - count,
+ "\t\t%08x:%01x:%08x\n",
+ cfg_entry->base_offset +
field->offset,
+ field->size, field->mask);
}
}
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c
--- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Mon Mar 12
09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Mon Mar 12
10:07:08 2007 -0600
@@ -28,7 +28,6 @@
#include <asm/hypervisor.h>
#include <xen/public/privcmd.h>
#include <xen/interface/xen.h>
-#include <xen/interface/dom0_ops.h>
#include <xen/xen_proc.h>
static struct proc_dir_entry *privcmd_intf;
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h Mon Mar
12 09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypercall.h Mon Mar
12 10:07:08 2007 -0600
@@ -201,11 +201,11 @@ HYPERVISOR_set_timer_op(
}
static inline int
-HYPERVISOR_dom0_op(
- dom0_op_t *dom0_op)
-{
- dom0_op->interface_version = DOM0_INTERFACE_VERSION;
- return _hypercall1(int, dom0_op, dom0_op);
+HYPERVISOR_platform_op(
+ struct xen_platform_op *platform_op)
+{
+ platform_op->interface_version = XENPF_INTERFACE_VERSION;
+ return _hypercall1(int, platform_op, platform_op);
}
static inline int
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h Mon Mar
12 09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h Mon Mar
12 10:07:08 2007 -0600
@@ -38,7 +38,7 @@
#include <linux/version.h>
#include <linux/errno.h>
#include <xen/interface/xen.h>
-#include <xen/interface/dom0_ops.h>
+#include <xen/interface/platform.h>
#include <xen/interface/event_channel.h>
#include <xen/interface/physdev.h>
#include <xen/interface/sched.h>
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/include/asm-ia64/hypercall.h
--- a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Mon Mar 12 09:43:48
2007 -0600
+++ b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Mon Mar 12 10:07:08
2007 -0600
@@ -120,9 +120,9 @@ HYPERVISOR_set_timer_op(u64 timeout)
}
static inline int
-xencomm_arch_hypercall_dom0_op(struct xencomm_handle *op)
-{
- return _hypercall1(int, dom0_op, op);
+xencomm_arch_hypercall_platform_op(struct xencomm_handle *op)
+{
+ return _hypercall1(int, platform_op, op);
}
static inline int
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h
--- a/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h Mon Mar 12
09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h Mon Mar 12
10:07:08 2007 -0600
@@ -51,7 +51,7 @@ extern int running_on_xen;
#include <linux/version.h>
#include <linux/errno.h>
#include <xen/interface/xen.h>
-#include <xen/interface/dom0_ops.h>
+#include <xen/interface/platform.h>
#include <xen/interface/event_channel.h>
#include <xen/interface/physdev.h>
#include <xen/interface/sched.h>
diff -r d1853a39e063 -r cb2575cec95c
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h
--- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h Mon Mar
12 09:43:48 2007 -0600
+++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/hypercall.h Mon Mar
12 10:07:08 2007 -0600
@@ -204,11 +204,11 @@ HYPERVISOR_set_timer_op(
}
static inline int
-HYPERVISOR_dom0_op(
- dom0_op_t *dom0_op)
-{
- dom0_op->interface_version = DOM0_INTERFACE_VERSION;
- return _hypercall1(int, dom0_op, dom0_op);
+HYPERVISOR_platform_op(
+ struct xen_platform_op *platform_op)
+{
+ platform_op->interface_version = XENPF_INTERFACE_VERSION;
+ return _hypercall1(int, platform_op, platform_op);
}
static inline int
diff -r d1853a39e063 -r cb2575cec95c
patches/linux-2.6.18/softlockup-no-idle-hz.patch
--- a/patches/linux-2.6.18/softlockup-no-idle-hz.patch Mon Mar 12 09:43:48
2007 -0600
+++ b/patches/linux-2.6.18/softlockup-no-idle-hz.patch Mon Mar 12 10:07:08
2007 -0600
@@ -34,7 +34,7 @@ diff -pruN ../orig-linux-2.6.18/kernel/s
+ !per_cpu(watchdog_task, this_cpu))
+ return MAX_JIFFY_OFFSET;
+
-+ return min_t(long, 0, touch_timestamp + HZ - jiffies);
++ return max_t(long, 0, touch_timestamp + HZ - jiffies);
+}
+
/*
diff -r d1853a39e063 -r cb2575cec95c tools/ioemu/hw/ide.c
--- a/tools/ioemu/hw/ide.c Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/ioemu/hw/ide.c Mon Mar 12 10:07:08 2007 -0600
@@ -396,17 +396,41 @@ typedef struct PCIIDEState {
#ifdef DMA_MULTI_THREAD
+static pthread_t ide_dma_thread;
static int file_pipes[2];
static void ide_dma_loop(BMDMAState *bm);
static void dma_thread_loop(BMDMAState *bm);
+extern int suspend_requested;
static void *dma_thread_func(void* opaque)
{
BMDMAState* req;
-
- while (read(file_pipes[0], &req, sizeof(req))) {
- dma_thread_loop(req);
+ fd_set fds;
+ int rv, nfds = file_pipes[0] + 1;
+ struct timeval tm;
+
+ while (1) {
+
+ /* Wait at most a second for the pipe to become readable */
+ FD_ZERO(&fds);
+ FD_SET(file_pipes[0], &fds);
+ tm.tv_sec = 1;
+ tm.tv_usec = 0;
+ rv = select(nfds, &fds, NULL, NULL, &tm);
+
+ if (rv != 0) {
+ if (read(file_pipes[0], &req, sizeof(req)) == 0)
+ return NULL;
+ dma_thread_loop(req);
+ } else {
+ if (suspend_requested) {
+ /* Need to tidy up the DMA thread so that we don't end up
+ * finishing operations after the domain's ioreqs are
+ * drained and its state saved */
+ return NULL;
+ }
+ }
}
return NULL;
@@ -414,23 +438,40 @@ static void *dma_thread_func(void* opaqu
static void dma_create_thread(void)
{
- pthread_t tid;
int rt;
+ pthread_attr_t a;
if (pipe(file_pipes) != 0) {
fprintf(stderr, "create pipe failed\n");
exit(1);
}
- if ((rt = pthread_create(&tid, NULL, dma_thread_func, NULL))) {
+ if ((rt = pthread_attr_init(&a))
+ || (rt = pthread_attr_setdetachstate(&a, PTHREAD_CREATE_JOINABLE))) {
+ fprintf(stderr, "Oops, dma thread attr setup failed, errno=%d\n", rt);
+ exit(1);
+ }
+
+ if ((rt = pthread_create(&ide_dma_thread, &a, dma_thread_func, NULL))) {
fprintf(stderr, "Oops, dma thread creation failed, errno=%d\n", rt);
exit(1);
}
-
- if ((rt = pthread_detach(tid))) {
- fprintf(stderr, "Oops, dma thread detachment failed, errno=%d\n", rt);
- exit(1);
- }
+}
+
+void ide_stop_dma_thread(void)
+{
+ int rc;
+ /* Make sure the IDE DMA thread is stopped */
+ if ( (rc = pthread_join(ide_dma_thread, NULL)) != 0 )
+ {
+ fprintf(stderr, "Oops, error collecting IDE DMA thread (%s)\n",
+ strerror(rc));
+ }
+}
+
+#else
+void ide_stop_dma_thread(void)
+{
}
#endif /* DMA_MULTI_THREAD */
@@ -2602,6 +2643,120 @@ void pci_cmd646_ide_init(PCIBus *bus, Bl
#endif /* DMA_MULTI_THREAD */
}
+static void pci_ide_save(QEMUFile* f, void *opaque)
+{
+ PCIIDEState *d = opaque;
+ int i;
+
+ for(i = 0; i < 2; i++) {
+ BMDMAState *bm = &d->bmdma[i];
+ qemu_put_8s(f, &bm->cmd);
+ qemu_put_8s(f, &bm->status);
+ qemu_put_be32s(f, &bm->addr);
+ /* XXX: if a transfer is pending, we do not save it yet */
+ }
+
+ /* per IDE interface data */
+ for(i = 0; i < 2; i++) {
+ IDEState *s = &d->ide_if[i * 2];
+ uint8_t drive1_selected;
+ qemu_put_8s(f, &s->cmd);
+ drive1_selected = (s->cur_drive != s);
+ qemu_put_8s(f, &drive1_selected);
+ }
+
+ /* per IDE drive data */
+ for(i = 0; i < 4; i++) {
+ IDEState *s = &d->ide_if[i];
+ qemu_put_be32s(f, &s->mult_sectors);
+ qemu_put_be32s(f, &s->identify_set);
+ if (s->identify_set) {
+ qemu_put_buffer(f, (const uint8_t *)s->identify_data, 512);
+ }
+ qemu_put_8s(f, &s->write_cache);
+ qemu_put_8s(f, &s->feature);
+ qemu_put_8s(f, &s->error);
+ qemu_put_be32s(f, &s->nsector);
+ qemu_put_8s(f, &s->sector);
+ qemu_put_8s(f, &s->lcyl);
+ qemu_put_8s(f, &s->hcyl);
+ qemu_put_8s(f, &s->hob_feature);
+ qemu_put_8s(f, &s->hob_nsector);
+ qemu_put_8s(f, &s->hob_sector);
+ qemu_put_8s(f, &s->hob_lcyl);
+ qemu_put_8s(f, &s->hob_hcyl);
+ qemu_put_8s(f, &s->select);
+ qemu_put_8s(f, &s->status);
+ qemu_put_8s(f, &s->lba48);
+
+ qemu_put_8s(f, &s->sense_key);
+ qemu_put_8s(f, &s->asc);
+ /* XXX: if a transfer is pending, we do not save it yet */
+ }
+}
+
+static int pci_ide_load(QEMUFile* f, void *opaque, int version_id)
+{
+ PCIIDEState *d = opaque;
+ int ret, i;
+
+ if (version_id != 1)
+ return -EINVAL;
+
+ for(i = 0; i < 2; i++) {
+ BMDMAState *bm = &d->bmdma[i];
+ qemu_get_8s(f, &bm->cmd);
+ qemu_get_8s(f, &bm->status);
+ qemu_get_be32s(f, &bm->addr);
+ /* XXX: if a transfer is pending, we do not save it yet */
+ }
+
+ /* per IDE interface data */
+ for(i = 0; i < 2; i++) {
+ IDEState *s = &d->ide_if[i * 2];
+ uint8_t drive1_selected;
+ qemu_get_8s(f, &s->cmd);
+ qemu_get_8s(f, &drive1_selected);
+ s->cur_drive = &d->ide_if[i * 2 + (drive1_selected != 0)];
+ }
+
+ /* per IDE drive data */
+ for(i = 0; i < 4; i++) {
+ IDEState *s = &d->ide_if[i];
+ qemu_get_be32s(f, &s->mult_sectors);
+ qemu_get_be32s(f, &s->identify_set);
+ if (s->identify_set) {
+ qemu_get_buffer(f, (uint8_t *)s->identify_data, 512);
+ }
+ qemu_get_8s(f, &s->write_cache);
+ qemu_get_8s(f, &s->feature);
+ qemu_get_8s(f, &s->error);
+ qemu_get_be32s(f, &s->nsector);
+ qemu_get_8s(f, &s->sector);
+ qemu_get_8s(f, &s->lcyl);
+ qemu_get_8s(f, &s->hcyl);
+ qemu_get_8s(f, &s->hob_feature);
+ qemu_get_8s(f, &s->hob_nsector);
+ qemu_get_8s(f, &s->hob_sector);
+ qemu_get_8s(f, &s->hob_lcyl);
+ qemu_get_8s(f, &s->hob_hcyl);
+ qemu_get_8s(f, &s->select);
+ qemu_get_8s(f, &s->status);
+ qemu_get_8s(f, &s->lba48);
+
+ qemu_get_8s(f, &s->sense_key);
+ qemu_get_8s(f, &s->asc);
+ /* XXX: if a transfer is pending, we do not save it yet */
+ if (s->status & (DRQ_STAT|BUSY_STAT)) {
+ /* Tell the guest that its transfer has gone away */
+ ide_abort_command(s);
+ ide_set_irq(s);
+ }
+ }
+ return 0;
+}
+
+
/* hd_table must contain 4 block drivers */
/* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */
void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn)
@@ -2643,6 +2798,7 @@ void pci_piix3_ide_init(PCIBus *bus, Blo
buffered_pio_init();
register_savevm("ide_pci", 0, 1, generic_pci_save, generic_pci_load, d);
+ register_savevm("ide", 0, 1, pci_ide_save, pci_ide_load, d);
#ifdef DMA_MULTI_THREAD
dma_create_thread();
diff -r d1853a39e063 -r cb2575cec95c tools/ioemu/target-i386-dm/helper2.c
--- a/tools/ioemu/target-i386-dm/helper2.c Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/ioemu/target-i386-dm/helper2.c Mon Mar 12 10:07:08 2007 -0600
@@ -577,7 +577,28 @@ int main_loop(void)
destroy_hvm_domain();
else {
char qemu_file[20];
+ ioreq_t *req;
+ int rc;
+
sprintf(qemu_file, "/tmp/xen.qemu-dm.%d", domid);
+ xc_domain_pause(xc_handle, domid);
+
+ /* Pull all outstanding ioreqs through the system */
+ handle_buffered_io(env);
+ main_loop_wait(1); /* For the select() on events */
+
+ /* Stop the IDE thread */
+ ide_stop_dma_thread();
+
+ /* Make sure that all outstanding IO responses are handled too */
+ if ( xc_hvm_drain_io(xc_handle, domid) != 0 )
+ {
+ fprintf(stderr, "error clearing ioreq rings (%s)\n",
+ strerror(errno));
+ return -1;
+ }
+
+ /* Save the device state */
if (qemu_savevm(qemu_file) < 0)
fprintf(stderr, "qemu save fail.\n");
}
diff -r d1853a39e063 -r cb2575cec95c tools/ioemu/vl.h
--- a/tools/ioemu/vl.h Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/ioemu/vl.h Mon Mar 12 10:07:08 2007 -0600
@@ -843,6 +843,7 @@ void pci_piix3_ide_init(PCIBus *bus, Blo
void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn);
int pmac_ide_init (BlockDriverState **hd_table,
SetIRQFunc *set_irq, void *irq_opaque, int irq);
+void ide_stop_dma_thread(void);
/* cdrom.c */
int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track);
diff -r d1853a39e063 -r cb2575cec95c tools/libxc/xc_core_ia64.c
--- a/tools/libxc/xc_core_ia64.c Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxc/xc_core_ia64.c Mon Mar 12 10:07:08 2007 -0600
@@ -22,6 +22,28 @@
#include "xc_core.h"
#include "xc_efi.h"
#include "xc_dom.h"
+#include <inttypes.h>
+
+static int
+xc_memory_map_cmp(const void *lhs__, const void *rhs__)
+{
+ const struct xc_core_memory_map *lhs =
+ (const struct xc_core_memory_map *)lhs__;
+ const struct xc_core_memory_map *rhs =
+ (const struct xc_core_memory_map *)rhs__;
+
+ if (lhs->addr < rhs->addr)
+ return -1;
+ if (lhs->addr > rhs->addr)
+ return 1;
+
+ /* memory map overlap isn't allowed. complain */
+ DPRINTF("duplicated addresses are detected "
+ "(0x%" PRIx64 ", 0x%" PRIx64 "), "
+ "(0x%" PRIx64 ", 0x%" PRIx64 ")\n",
+ lhs->addr, lhs->size, rhs->addr, rhs->size);
+ return 0;
+}
int
xc_core_arch_auto_translated_physmap(const xc_dominfo_t *info)
@@ -111,6 +133,7 @@ memory_map_get_old_hvm(int xc_handle, xc
}
*mapp = map;
*nr_entries = i;
+ qsort(map, *nr_entries, sizeof(map[0]), &xc_memory_map_cmp);
return 0;
out:
@@ -196,6 +219,7 @@ xc_core_arch_memory_map_get(int xc_handl
ret = 0;
out:
munmap(memmap_info, PAGE_SIZE);
+ qsort(map, *nr_entries, sizeof(map[0]), &xc_memory_map_cmp);
return ret;
old:
diff -r d1853a39e063 -r cb2575cec95c tools/libxc/xc_dom_x86.c
--- a/tools/libxc/xc_dom_x86.c Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxc/xc_dom_x86.c Mon Mar 12 10:07:08 2007 -0600
@@ -433,23 +433,11 @@ static int vcpu_x86_32(struct xc_dom_ima
{
vcpu_guest_context_x86_32_t *ctxt = ptr;
xen_pfn_t cr3_pfn;
- int i;
xc_dom_printf("%s: called\n", __FUNCTION__);
/* clear everything */
memset(ctxt, 0, sizeof(*ctxt));
-
- /* Virtual IDT is empty at start-of-day. */
- for ( i = 0; i < 256; i++ )
- {
- ctxt->trap_ctxt[i].vector = i;
- ctxt->trap_ctxt[i].cs = FLAT_KERNEL_CS_X86_32;
- }
-
- /* No callback handlers. */
- ctxt->event_callback_cs = FLAT_KERNEL_CS_X86_32;
- ctxt->failsafe_callback_cs = FLAT_KERNEL_CS_X86_32;
ctxt->user_regs.ds = FLAT_KERNEL_DS_X86_32;
ctxt->user_regs.es = FLAT_KERNEL_DS_X86_32;
@@ -464,9 +452,8 @@ static int vcpu_x86_32(struct xc_dom_ima
dom->parms.virt_base + (dom->start_info_pfn) * PAGE_SIZE_X86;
ctxt->user_regs.eflags = 1 << 9; /* Interrupt Enable */
- ctxt->kernel_ss = FLAT_KERNEL_SS_X86_32;
- ctxt->kernel_sp =
- dom->parms.virt_base + (dom->bootstack_pfn + 1) * PAGE_SIZE_X86;
+ ctxt->kernel_ss = ctxt->user_regs.ss;
+ ctxt->kernel_sp = ctxt->user_regs.esp;
ctxt->flags = VGCF_in_kernel_X86_32;
if ( dom->parms.pae == 2 /* extended_cr3 */ ||
@@ -485,19 +472,11 @@ static int vcpu_x86_64(struct xc_dom_ima
{
vcpu_guest_context_x86_64_t *ctxt = ptr;
xen_pfn_t cr3_pfn;
- int i;
xc_dom_printf("%s: called\n", __FUNCTION__);
/* clear everything */
memset(ctxt, 0, sizeof(*ctxt));
-
- /* Virtual IDT is empty at start-of-day. */
- for ( i = 0; i < 256; i++ )
- {
- ctxt->trap_ctxt[i].vector = i;
- ctxt->trap_ctxt[i].cs = FLAT_KERNEL_CS_X86_64;
- }
ctxt->user_regs.ds = FLAT_KERNEL_DS_X86_64;
ctxt->user_regs.es = FLAT_KERNEL_DS_X86_64;
@@ -512,9 +491,8 @@ static int vcpu_x86_64(struct xc_dom_ima
dom->parms.virt_base + (dom->start_info_pfn) * PAGE_SIZE_X86;
ctxt->user_regs.rflags = 1 << 9; /* Interrupt Enable */
- ctxt->kernel_ss = FLAT_KERNEL_SS_X86_64;
- ctxt->kernel_sp =
- dom->parms.virt_base + (dom->bootstack_pfn + 1) * PAGE_SIZE_X86;
+ ctxt->kernel_ss = ctxt->user_regs.ss;
+ ctxt->kernel_sp = ctxt->user_regs.esp;
ctxt->flags = VGCF_in_kernel_X86_64;
cr3_pfn = xc_dom_p2m_guest(dom, dom->pgtables_seg.pfn);
diff -r d1853a39e063 -r cb2575cec95c tools/libxc/xc_hvm_restore.c
--- a/tools/libxc/xc_hvm_restore.c Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxc/xc_hvm_restore.c Mon Mar 12 10:07:08 2007 -0600
@@ -101,6 +101,9 @@ int xc_hvm_restore(int xc_handle, int io
/* Number of pages of memory the guest has. *Not* the same as max_pfn. */
unsigned long nr_pages;
+ /* The size of an array big enough to contain all guest pfns */
+ unsigned long pfn_array_size = max_pfn + 1;
+
/* hvm guest mem size (Mb) */
memsize = (unsigned long long)*store_mfn;
v_end = memsize << 20;
@@ -127,7 +130,7 @@ int xc_hvm_restore(int xc_handle, int io
}
- pfns = malloc(max_pfn * sizeof(xen_pfn_t));
+ pfns = malloc(pfn_array_size * sizeof(xen_pfn_t));
if (pfns == NULL) {
ERROR("memory alloc failed");
errno = ENOMEM;
@@ -139,11 +142,11 @@ int xc_hvm_restore(int xc_handle, int io
goto out;
}
- for ( i = 0; i < max_pfn; i++ )
+ for ( i = 0; i < pfn_array_size; i++ )
pfns[i] = i;
- for ( i = HVM_BELOW_4G_RAM_END >> PAGE_SHIFT; i < max_pfn; i++ )
+ for ( i = HVM_BELOW_4G_RAM_END >> PAGE_SHIFT; i < pfn_array_size; i++ )
pfns[i] += HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT;
- arch_max_pfn = pfns[max_pfn - 1];/* used later */
+ arch_max_pfn = pfns[max_pfn];/* used later */
/* Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000. */
rc = xc_domain_memory_populate_physmap(
@@ -281,6 +284,14 @@ int xc_hvm_restore(int xc_handle, int io
else
shared_page_nr = (v_end >> PAGE_SHIFT) - 1;
+ /* Paranoia: clean pages. */
+ if ( xc_clear_domain_page(xc_handle, dom, shared_page_nr) ||
+ xc_clear_domain_page(xc_handle, dom, shared_page_nr-1) ||
+ xc_clear_domain_page(xc_handle, dom, shared_page_nr-2) ) {
+ ERROR("error clearing comms frames!\n");
+ goto out;
+ }
+
xc_set_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, shared_page_nr-1);
xc_set_hvm_param(xc_handle, dom, HVM_PARAM_BUFIOREQ_PFN, shared_page_nr-2);
xc_set_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN, shared_page_nr);
@@ -288,6 +299,33 @@ int xc_hvm_restore(int xc_handle, int io
/* caculate the store_mfn , wrong val cause hang when introduceDomain */
*store_mfn = (v_end >> PAGE_SHIFT) - 2;
DPRINTF("hvm restore:calculate new store_mfn=0x%lx,v_end=0x%llx..\n",
*store_mfn, v_end);
+
+ if (!read_exact(io_fd, &nr_vcpus, sizeof(uint32_t))) {
+ ERROR("error read nr vcpu !\n");
+ goto out;
+ }
+ DPRINTF("hvm restore:get nr_vcpus=%d.\n", nr_vcpus);
+
+ for (i =0; i < nr_vcpus; i++) {
+ if (!read_exact(io_fd, &rec_len, sizeof(uint32_t))) {
+ ERROR("error read vcpu context size!\n");
+ goto out;
+ }
+ if (rec_len != sizeof(ctxt)) {
+ ERROR("vcpu context size dismatch!\n");
+ goto out;
+ }
+
+ if (!read_exact(io_fd, &(ctxt), sizeof(ctxt))) {
+ ERROR("error read vcpu context.\n");
+ goto out;
+ }
+
+ if ( (rc = xc_vcpu_setcontext(xc_handle, dom, i, &ctxt)) ) {
+ ERROR("Could not set vcpu context, rc=%d", rc);
+ goto out;
+ }
+ }
/* restore hvm context including pic/pit/shpage */
if (!read_exact(io_fd, &rec_len, sizeof(uint32_t))) {
@@ -310,33 +348,6 @@ int xc_hvm_restore(int xc_handle, int io
if (( rc = xc_domain_hvm_setcontext(xc_handle, dom, hvm_buf, rec_len))) {
ERROR("error set hvm buffer!\n");
goto out;
- }
-
- if (!read_exact(io_fd, &nr_vcpus, sizeof(uint32_t))) {
- ERROR("error read nr vcpu !\n");
- goto out;
- }
- DPRINTF("hvm restore:get nr_vcpus=%d.\n", nr_vcpus);
-
- for (i =0; i < nr_vcpus; i++) {
- if (!read_exact(io_fd, &rec_len, sizeof(uint32_t))) {
- ERROR("error read vcpu context size!\n");
- goto out;
- }
- if (rec_len != sizeof(ctxt)) {
- ERROR("vcpu context size dismatch!\n");
- goto out;
- }
-
- if (!read_exact(io_fd, &(ctxt), sizeof(ctxt))) {
- ERROR("error read vcpu context.\n");
- goto out;
- }
-
- if ( (rc = xc_vcpu_setcontext(xc_handle, dom, i, &ctxt)) ) {
- ERROR("Could not set vcpu context, rc=%d", rc);
- goto out;
- }
}
/* Shared-info pfn */
diff -r d1853a39e063 -r cb2575cec95c tools/libxc/xc_hvm_save.c
--- a/tools/libxc/xc_hvm_save.c Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxc/xc_hvm_save.c Mon Mar 12 10:07:08 2007 -0600
@@ -27,11 +27,13 @@
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
-#include <xen/hvm/e820.h>
#include "xc_private.h"
#include "xg_private.h"
#include "xg_save_restore.h"
+
+#include <xen/hvm/e820.h>
+#include <xen/hvm/params.h>
/*
** Default values for important tuning parameters. Can override by passing
@@ -49,11 +51,25 @@ static unsigned long max_mfn;
/* virtual starting address of the hypervisor */
static unsigned long hvirt_start;
-/* #levels of page tables used by the currrent guest */
+/* #levels of page tables used by the current guest */
static unsigned int pt_levels;
-/* total number of pages used by the current guest */
-static unsigned long max_pfn;
+int xc_hvm_drain_io(int handle, domid_t dom)
+{
+ DECLARE_HYPERCALL;
+ xen_hvm_drain_io_t arg;
+ int rc;
+
+ hypercall.op = __HYPERVISOR_hvm_op;
+ hypercall.arg[0] = HVMOP_drain_io;
+ hypercall.arg[1] = (unsigned long)&arg;
+ arg.domid = dom;
+ if ( lock_pages(&arg, sizeof(arg)) != 0 )
+ return -1;
+ rc = do_xen_hypercall(handle, &hypercall);
+ unlock_pages(&arg, sizeof(arg));
+ return rc;
+}
/*
** During (live) save/migrate, we maintain a number of bitmaps to track
@@ -61,7 +77,7 @@ static unsigned long max_pfn;
*/
#define BITS_PER_LONG (sizeof(unsigned long) * 8)
-#define BITMAP_SIZE ((max_pfn + BITS_PER_LONG - 1) / 8)
+#define BITMAP_SIZE ((pfn_array_size + BITS_PER_LONG - 1) / 8)
#define BITMAP_ENTRY(_nr,_bmap) \
((unsigned long *)(_bmap))[(_nr)/BITS_PER_LONG]
@@ -183,7 +199,7 @@ static int print_stats(int xc_handle, ui
return 0;
}
-static int analysis_phase(int xc_handle, uint32_t domid, int max_pfn,
+static int analysis_phase(int xc_handle, uint32_t domid, int pfn_array_size,
unsigned long *arr, int runs)
{
long long start, now;
@@ -196,7 +212,7 @@ static int analysis_phase(int xc_handle,
int i;
xc_shadow_control(xc_handle, domid, XEN_DOMCTL_SHADOW_OP_CLEAN,
- arr, max_pfn, NULL, 0, NULL);
+ arr, pfn_array_size, NULL, 0, NULL);
DPRINTF("#Flush\n");
for ( i = 0; i < 40; i++ ) {
usleep(50000);
@@ -236,7 +252,7 @@ static int suspend_and_state(int (*suspe
if (info->shutdown && info->shutdown_reason == SHUTDOWN_suspend)
- return 0; // success
+ return 0; // success
if (info->paused) {
// try unpausing domain, wait, and retest
@@ -268,10 +284,20 @@ int xc_hvm_save(int xc_handle, int io_fd
int rc = 1, i, j, last_iter, iter = 0;
int live = (flags & XCFLAGS_LIVE);
int debug = (flags & XCFLAGS_DEBUG);
+ int stdvga = (flags & XCFLAGS_STDVGA);
int sent_last_iter, skip_this_iter;
+
+ /* The highest guest-physical frame number used by the current guest */
+ unsigned long max_pfn;
+
+ /* The size of an array big enough to contain all guest pfns */
+ unsigned long pfn_array_size;
/* The new domain's shared-info frame number. */
unsigned long shared_info_frame;
+
+ /* Other magic frames: ioreqs and xenstore comms */
+ unsigned long ioreq_pfn, bufioreq_pfn, store_pfn;
/* A copy of the CPU context of the guest. */
vcpu_guest_context_t ctxt;
@@ -291,7 +317,7 @@ int xc_hvm_save(int xc_handle, int io_fd
uint32_t rec_size, nr_vcpus;
- /* power of 2 order of max_pfn */
+ /* power of 2 order of pfn_array_size */
int order_nr;
/* bitmap of pages:
@@ -350,6 +376,15 @@ int xc_hvm_save(int xc_handle, int io_fd
if(!(live_shinfo = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
PROT_READ, shared_info_frame))) {
ERROR("HVM:Couldn't map live_shinfo");
+ goto out;
+ }
+
+ if ( xc_get_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, &store_pfn)
+ || xc_get_hvm_param(xc_handle, dom, HVM_PARAM_IOREQ_PFN, &ioreq_pfn)
+ || xc_get_hvm_param(xc_handle, dom,
+ HVM_PARAM_BUFIOREQ_PFN, &bufioreq_pfn) )
+ {
+ ERROR("HVM: Could not read magic PFN parameters");
goto out;
}
@@ -368,6 +403,7 @@ int xc_hvm_save(int xc_handle, int io_fd
}
last_iter = 0;
+
DPRINTF("hvm domain live migration debug start: logdirty enable.\n");
} else {
/* This is a non-live suspend. Issue the call back to get the
@@ -388,20 +424,28 @@ int xc_hvm_save(int xc_handle, int io_fd
/* Calculate the highest PFN of "normal" memory:
* HVM memory is sequential except for the VGA and MMIO holes. */
- max_pfn = info.nr_pages;
+ max_pfn = info.nr_pages - 1;
+ /* If the domain has a Cirrus framebuffer and we haven't already
+ * suspended qemu-dm, it will have 8MB of framebuffer memory
+ * still allocated, which we don't want to copy: qemu will save it
+ * for us later */
+ if ( live && !stdvga )
+ max_pfn -= 0x800;
/* Skip the VGA hole from 0xa0000 to 0xc0000 */
- max_pfn += 0x20;
+ max_pfn += 0x20;
/* Skip the MMIO hole: 256MB just below 4GB */
if ( max_pfn >= (HVM_BELOW_4G_MMIO_START >> PAGE_SHIFT) )
max_pfn += (HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT);
- skip_this_iter = 0;/*XXX*/
+ /* Size of any array that covers 0 ... max_pfn */
+ pfn_array_size = max_pfn + 1;
+
/* pretend we sent all the pages last iteration */
- sent_last_iter = max_pfn;
-
- /* calculate the power of 2 order of max_pfn, e.g.
+ sent_last_iter = pfn_array_size;
+
+ /* calculate the power of 2 order of pfn_array_size, e.g.
15->4 16->4 17->5 */
- for (i = max_pfn-1, order_nr = 0; i ; i >>= 1, order_nr++)
+ for (i = pfn_array_size-1, order_nr = 0; i ; i >>= 1, order_nr++)
continue;
/* Setup to_send / to_fix and to_skip bitmaps */
@@ -435,7 +479,7 @@ int xc_hvm_save(int xc_handle, int io_fd
return 1;
}
- analysis_phase(xc_handle, dom, max_pfn, to_skip, 0);
+ analysis_phase(xc_handle, dom, pfn_array_size, to_skip, 0);
/* We want zeroed memory so use calloc rather than malloc. */
@@ -465,9 +509,17 @@ int xc_hvm_save(int xc_handle, int io_fd
DPRINTF("Saving HVM domain memory pages: iter %d 0%%", iter);
- while( N < max_pfn ){
-
- unsigned int this_pc = (N * 100) / max_pfn;
+ if (last_iter && (max_pfn != live_shinfo->arch.max_pfn)) {
+ DPRINTF("calculated max_pfn as %#lx, shinfo says %#lx\n",
+ max_pfn, live_shinfo->arch.max_pfn);
+ ERROR("Max pfn doesn't match shared info");
+ goto out;
+ }
+
+ while( N < pfn_array_size ){
+
+ unsigned int this_pc = (N * 100) / pfn_array_size;
+ int rc;
if ((this_pc - prev_pc) >= 5) {
DPRINTF("\b\b\b\b%3d%%", this_pc);
@@ -476,9 +528,9 @@ int xc_hvm_save(int xc_handle, int io_fd
/* slightly wasteful to peek the whole array evey time,
but this is fast enough for the moment. */
- if (!last_iter && xc_shadow_control(
- xc_handle, dom, XEN_DOMCTL_SHADOW_OP_PEEK,
- to_skip, max_pfn, NULL, 0, NULL) != max_pfn) {
+ if (!last_iter && (rc = xc_shadow_control(
+ xc_handle, dom, XEN_DOMCTL_SHADOW_OP_PEEK, to_skip,
+ pfn_array_size, NULL, 0, NULL)) != pfn_array_size) {
ERROR("Error peeking HVM shadow bitmap");
goto out;
}
@@ -486,11 +538,11 @@ int xc_hvm_save(int xc_handle, int io_fd
/* load pfn_batch[] with the mfn of all the pages we're doing in
this batch. */
- for (batch = 0; batch < MAX_BATCH_SIZE && N < max_pfn ; N++) {
-
- int n = permute(N, max_pfn, order_nr);
-
- if (debug) {
+ for (batch = 0; batch < MAX_BATCH_SIZE && N < pfn_array_size; N++){
+
+ int n = permute(N, pfn_array_size, order_nr);
+
+ if (0&&debug) {
DPRINTF("%d pfn= %08lx %d \n",
iter, (unsigned long)n, test_bit(n, to_send));
}
@@ -505,7 +557,10 @@ int xc_hvm_save(int xc_handle, int io_fd
/* Skip PFNs that aren't really there */
if ((n >= 0xa0 && n < 0xc0) /* VGA hole */
|| (n >= (HVM_BELOW_4G_MMIO_START >> PAGE_SHIFT)
- && n < (1ULL << 32) >> PAGE_SHIFT)) /* 4G MMIO hole */
+ && n < (1ULL << 32) >> PAGE_SHIFT) /* 4G MMIO hole */
+ || n == store_pfn
+ || n == ioreq_pfn
+ || n == bufioreq_pfn)
continue;
/*
@@ -570,7 +625,7 @@ int xc_hvm_save(int xc_handle, int io_fd
print_stats( xc_handle, dom, sent_this_iter, &stats, 1);
DPRINTF("Total pages sent= %ld (%.2fx)\n",
- total_sent, ((float)total_sent)/max_pfn );
+ total_sent, ((float)total_sent)/pfn_array_size );
}
if (last_iter && debug){
@@ -597,7 +652,7 @@ int xc_hvm_save(int xc_handle, int io_fd
((sent_this_iter > sent_last_iter) && RATE_IS_MAX()) ||
(iter >= max_iters) ||
(sent_this_iter+skip_this_iter < 50) ||
- (total_sent > max_pfn*max_factor) ) {
+ (total_sent > pfn_array_size*max_factor) ) {
DPRINTF("Start last iteration for HVM domain\n");
last_iter = 1;
@@ -616,7 +671,8 @@ int xc_hvm_save(int xc_handle, int io_fd
if (xc_shadow_control(xc_handle, dom,
XEN_DOMCTL_SHADOW_OP_CLEAN, to_send,
- max_pfn, NULL, 0, &stats) != max_pfn) {
+ pfn_array_size, NULL,
+ 0, &stats) != pfn_array_size) {
ERROR("Error flushing shadow PT");
goto out;
}
@@ -640,20 +696,6 @@ int xc_hvm_save(int xc_handle, int io_fd
goto out;
}
- if ( (rec_size = xc_domain_hvm_getcontext(xc_handle, dom, hvm_buf,
- hvm_buf_size)) == -1) {
- ERROR("HVM:Could not get hvm buffer");
- goto out;
- }
-
- if (!write_exact(io_fd, &rec_size, sizeof(uint32_t))) {
- ERROR("error write hvm buffer size");
- goto out;
- }
-
- if ( !write_exact(io_fd, hvm_buf, rec_size) ) {
- ERROR("write HVM info failed!\n");
- }
/* save vcpu/vmcs context */
if (!write_exact(io_fd, &nr_vcpus, sizeof(uint32_t))) {
@@ -682,6 +724,21 @@ int xc_hvm_save(int xc_handle, int io_fd
}
}
+ if ( (rec_size = xc_domain_hvm_getcontext(xc_handle, dom, hvm_buf,
+ hvm_buf_size)) == -1) {
+ ERROR("HVM:Could not get hvm buffer");
+ goto out;
+ }
+
+ if (!write_exact(io_fd, &rec_size, sizeof(uint32_t))) {
+ ERROR("error write hvm buffer size");
+ goto out;
+ }
+
+ if ( !write_exact(io_fd, hvm_buf, rec_size) ) {
+ ERROR("write HVM info failed!\n");
+ }
+
/* Shared-info pfn */
if (!write_exact(io_fd, &(shared_info_frame), sizeof(uint32_t)) ) {
ERROR("write shared-info pfn failed!\n");
diff -r d1853a39e063 -r cb2575cec95c tools/libxc/xc_misc.c
--- a/tools/libxc/xc_misc.c Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxc/xc_misc.c Mon Mar 12 10:07:08 2007 -0600
@@ -29,6 +29,25 @@ int xc_readconsolering(int xc_handle,
*pnr_chars = sysctl.u.readconsole.count;
unlock_pages(buffer, nr_chars);
+
+ return ret;
+}
+
+int xc_send_debug_keys(int xc_handle, char *keys)
+{
+ int ret, len = strlen(keys);
+ DECLARE_SYSCTL;
+
+ sysctl.cmd = XEN_SYSCTL_debug_keys;
+ set_xen_guest_handle(sysctl.u.debug_keys.keys, keys);
+ sysctl.u.debug_keys.nr_keys = len;
+
+ if ( (ret = lock_pages(keys, len)) != 0 )
+ return ret;
+
+ ret = do_sysctl(xc_handle, &sysctl);
+
+ unlock_pages(keys, len);
return ret;
}
diff -r d1853a39e063 -r cb2575cec95c tools/libxc/xc_private.c
--- a/tools/libxc/xc_private.c Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxc/xc_private.c Mon Mar 12 10:07:08 2007 -0600
@@ -23,7 +23,7 @@ void xc_default_error_handler(const xc_e
fprintf(stderr, "ERROR %s: %s\n", desc, err->message);
}
-const xc_error const *xc_get_last_error(void)
+const xc_error *xc_get_last_error(void)
{
return &last_error;
}
diff -r d1853a39e063 -r cb2575cec95c tools/libxc/xc_ptrace_core.c
--- a/tools/libxc/xc_ptrace_core.c Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxc/xc_ptrace_core.c Mon Mar 12 10:07:08 2007 -0600
@@ -390,7 +390,6 @@ map_gmfn_to_offset_elf(unsigned long gmf
{
/*
* linear search
- * There is no gurantee that those tables are sorted.
*/
unsigned long i;
if (current_is_auto_translated_physmap) {
diff -r d1853a39e063 -r cb2575cec95c tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxc/xenctrl.h Mon Mar 12 10:07:08 2007 -0600
@@ -467,6 +467,8 @@ int xc_readconsolering(int xc_handle,
unsigned int *pnr_chars,
int clear);
+int xc_send_debug_keys(int xc_handle, char *keys);
+
typedef xen_sysctl_physinfo_t xc_physinfo_t;
int xc_physinfo(int xc_handle,
xc_physinfo_t *info);
@@ -770,19 +772,19 @@ typedef struct {
* data pointed to are only valid until the next call to
* libxc.
*/
-const xc_error const *xc_get_last_error(void);
+const xc_error *xc_get_last_error(void);
/*
* Clear the last error
*/
void xc_clear_last_error(void);
-typedef void (*xc_error_handler)(const xc_error const* err);
+typedef void (*xc_error_handler)(const xc_error * const err);
/*
* The default error handler which prints to stderr
*/
-void xc_default_error_handler(const xc_error const* err);
+void xc_default_error_handler(const xc_error * const err);
/*
* Convert an error code into a text description
diff -r d1853a39e063 -r cb2575cec95c tools/libxc/xenguest.h
--- a/tools/libxc/xenguest.h Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxc/xenguest.h Mon Mar 12 10:07:08 2007 -0600
@@ -12,6 +12,7 @@
#define XCFLAGS_LIVE 1
#define XCFLAGS_DEBUG 2
#define XCFLAGS_HVM 4
+#define XCFLAGS_STDVGA 8
/**
@@ -155,6 +156,8 @@ int xc_get_hvm_param(
int xc_get_hvm_param(
int handle, domid_t dom, int param, unsigned long *value);
+int xc_hvm_drain_io(int handle, domid_t dom);
+
/* PowerPC specific. */
int xc_prose_build(int xc_handle,
uint32_t domid,
diff -r d1853a39e063 -r cb2575cec95c tools/libxc/xg_private.c
--- a/tools/libxc/xg_private.c Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxc/xg_private.c Mon Mar 12 10:07:08 2007 -0600
@@ -225,6 +225,11 @@ __attribute__((weak)) int xc_get_hvm_par
__attribute__((weak)) int xc_set_hvm_param(
int handle, domid_t dom, int param, unsigned long value)
+{
+ return -ENOSYS;
+}
+
+__attribute__((weak)) int xc_hvm_drain_io(int handle, domid_t dom)
{
return -ENOSYS;
}
diff -r d1853a39e063 -r cb2575cec95c tools/libxen/include/xen_crashdump.h
--- a/tools/libxen/include/xen_crashdump.h Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxen/include/xen_crashdump.h Mon Mar 12 10:07:08 2007 -0600
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, XenSource Inc.
+ * Copyright (c) 2006-2007, XenSource Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -162,20 +162,6 @@ xen_crashdump_get_by_uuid(xen_session *s
/**
- * Create a new crashdump instance, and return its handle.
- */
-extern bool
-xen_crashdump_create(xen_session *session, xen_crashdump *result,
xen_crashdump_record *record);
-
-
-/**
- * Destroy the specified crashdump instance.
- */
-extern bool
-xen_crashdump_destroy(xen_session *session, xen_crashdump crashdump);
-
-
-/**
* Get the uuid field of the given crashdump.
*/
extern bool
@@ -197,6 +183,13 @@ xen_crashdump_get_vdi(xen_session *sessi
/**
+ * Destroy the specified crashdump
+ */
+extern bool
+xen_crashdump_destroy(xen_session *session, xen_crashdump self);
+
+
+/**
* Return a list of all the crashdumps known to the system.
*/
extern bool
diff -r d1853a39e063 -r cb2575cec95c tools/libxen/include/xen_vbd.h
--- a/tools/libxen/include/xen_vbd.h Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxen/include/xen_vbd.h Mon Mar 12 10:07:08 2007 -0600
@@ -358,6 +358,22 @@ xen_vbd_media_change(xen_session *sessio
/**
+ * Hotplug the specified VBD, dynamically attaching it to the running
+ * VM
+ */
+extern bool
+xen_vbd_plug(xen_session *session, xen_vbd self);
+
+
+/**
+ * Hot-unplug the specified VBD, dynamically unattaching it from the
+ * running VM
+ */
+extern bool
+xen_vbd_unplug(xen_session *session, xen_vbd self);
+
+
+/**
* Return a list of all the VBDs known to the system.
*/
extern bool
diff -r d1853a39e063 -r cb2575cec95c tools/libxen/include/xen_vdi.h
--- a/tools/libxen/include/xen_vdi.h Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxen/include/xen_vdi.h Mon Mar 12 10:07:08 2007 -0600
@@ -293,13 +293,6 @@ xen_vdi_set_name_description(xen_session
/**
- * Set the SR field of the given VDI.
- */
-extern bool
-xen_vdi_set_sr(xen_session *session, xen_vdi vdi, xen_sr sr);
-
-
-/**
* Set the virtual_size field of the given VDI.
*/
extern bool
diff -r d1853a39e063 -r cb2575cec95c tools/libxen/include/xen_vif.h
--- a/tools/libxen/include/xen_vif.h Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxen/include/xen_vif.h Mon Mar 12 10:07:08 2007 -0600
@@ -332,6 +332,22 @@ xen_vif_remove_from_qos_algorithm_params
/**
+ * Hotplug the specified VIF, dynamically attaching it to the running
+ * VM
+ */
+extern bool
+xen_vif_plug(xen_session *session, xen_vif self);
+
+
+/**
+ * Hot-unplug the specified VIF, dynamically unattaching it from the
+ * running VM
+ */
+extern bool
+xen_vif_unplug(xen_session *session, xen_vif self);
+
+
+/**
* Return a list of all the VIFs known to the system.
*/
extern bool
diff -r d1853a39e063 -r cb2575cec95c tools/libxen/include/xen_vm.h
--- a/tools/libxen/include/xen_vm.h Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxen/include/xen_vm.h Mon Mar 12 10:07:08 2007 -0600
@@ -40,39 +40,6 @@
* The VM class.
*
* A virtual machine (or 'guest').
- *
- * VM booting is controlled by setting one of the two mutually exclusive
- * groups: "PV", and "HVM". If HVM.boot_policy is the empty string, then
- * paravirtual domain building and booting will be used; otherwise the VM will
- * be loaded as an HVM domain, and booted using an emulated BIOS.
- *
- * When paravirtual booting is in use, the PV/bootloader field indicates the
- * bootloader to use. It may be "pygrub", in which case the platform's
- * default installation of pygrub will be used, or a full path within the
- * control domain to some other bootloader. The other fields, PV/kernel,
- * PV/ramdisk, PV/args and PV/bootloader_args will be passed to the bootloader
- * unmodified, and interpretation of those fields is then specific to the
- * bootloader itself, including the possibility that the bootloader will
- * ignore some or all of those given values. Finally the paths of all bootable
- * disks are added to the bootloader commandline (a disk is bootable if its
- * VBD has the bootable flag set). There may be zero, one or many bootable
- * disks; the bootloader decides which disk (if any) to boot from.
- *
- * If the bootloader is pygrub, then the menu.lst is parsed if present in the
- * guest's filesystem, otherwise the specified kernel and ramdisk are used, or
- * an autodetected kernel is used if nothing is specified and autodetection is
- * possible. PV/args is appended to the kernel command line, no matter which
- * mechanism is used for finding the kernel.
- *
- * If PV/bootloader is empty but PV/kernel is specified, then the kernel and
- * ramdisk values will be treated as paths within the control domain. If both
- * PV/bootloader and PV/kernel are empty, then the behaviour is as if
- * PV/bootloader was specified as "pygrub".
- *
- * When using HVM booting, HVM/boot_policy and HVM/boot_params specify the
- * boot handling. Only one policy is currently defined: "BIOS order". In
- * this case, HVM/boot_params should contain one key-value pair "order" = "N"
- * where N is the string that will be passed to QEMU..
*/
@@ -139,11 +106,7 @@ typedef struct xen_vm_record
char *pv_bootloader_args;
char *hvm_boot_policy;
xen_string_string_map *hvm_boot_params;
- bool platform_std_vga;
- char *platform_serial;
- bool platform_localtime;
- bool platform_clock_offset;
- bool platform_enable_audio;
+ xen_string_string_map *platform;
char *pci_bus;
xen_string_string_map *other_config;
int64_t domid;
@@ -493,38 +456,10 @@ xen_vm_get_hvm_boot_params(xen_session *
/**
- * Get the platform/std_VGA field of the given VM.
- */
-extern bool
-xen_vm_get_platform_std_vga(xen_session *session, bool *result, xen_vm vm);
-
-
-/**
- * Get the platform/serial field of the given VM.
- */
-extern bool
-xen_vm_get_platform_serial(xen_session *session, char **result, xen_vm vm);
-
-
-/**
- * Get the platform/localtime field of the given VM.
- */
-extern bool
-xen_vm_get_platform_localtime(xen_session *session, bool *result, xen_vm vm);
-
-
-/**
- * Get the platform/clock_offset field of the given VM.
- */
-extern bool
-xen_vm_get_platform_clock_offset(xen_session *session, bool *result, xen_vm
vm);
-
-
-/**
- * Get the platform/enable_audio field of the given VM.
- */
-extern bool
-xen_vm_get_platform_enable_audio(xen_session *session, bool *result, xen_vm
vm);
+ * Get the platform field of the given VM.
+ */
+extern bool
+xen_vm_get_platform(xen_session *session, xen_string_string_map **result,
xen_vm vm);
/**
@@ -765,38 +700,32 @@ xen_vm_remove_from_hvm_boot_params(xen_s
/**
- * Set the platform/std_VGA field of the given VM.
- */
-extern bool
-xen_vm_set_platform_std_vga(xen_session *session, xen_vm vm, bool std_vga);
-
-
-/**
- * Set the platform/serial field of the given VM.
- */
-extern bool
-xen_vm_set_platform_serial(xen_session *session, xen_vm vm, char *serial);
-
-
-/**
- * Set the platform/localtime field of the given VM.
- */
-extern bool
-xen_vm_set_platform_localtime(xen_session *session, xen_vm vm, bool localtime);
-
-
-/**
- * Set the platform/clock_offset field of the given VM.
- */
-extern bool
-xen_vm_set_platform_clock_offset(xen_session *session, xen_vm vm, bool
clock_offset);
-
-
-/**
- * Set the platform/enable_audio field of the given VM.
- */
-extern bool
-xen_vm_set_platform_enable_audio(xen_session *session, xen_vm vm, bool
enable_audio);
+ * Set the platform field of the given VM.
+ */
+extern bool
+xen_vm_set_platform(xen_session *session, xen_vm vm, xen_string_string_map
*platform);
+
+
+/**
+ * Add the given key-value pair to the platform field of the given VM.
+ */
+extern bool
+xen_vm_add_to_platform(xen_session *session, xen_vm vm, char *key, char
*value);
+
+
+/**
+ * Remove the given key and its corresponding value from the platform
+ * field of the given VM. If the key is not in that Map, then do nothing.
+ */
+extern bool
+xen_vm_remove_from_platform(xen_session *session, xen_vm vm, char *key);
+
+
+/**
+ * Set the PCI_bus field of the given VM.
+ */
+extern bool
+xen_vm_set_pci_bus(xen_session *session, xen_vm vm, char *pci_bus);
/**
diff -r d1853a39e063 -r cb2575cec95c tools/libxen/src/xen_common.c
--- a/tools/libxen/src/xen_common.c Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxen/src/xen_common.c Mon Mar 12 10:07:08 2007 -0600
@@ -110,7 +110,7 @@ static size_t size_of_member(const abstr
static size_t size_of_member(const abstract_type *);
static const char *
-get_val_as_string(const struct abstract_type *, void *, char *);
+get_val_as_string(const struct abstract_type *, void *, char *, size_t);
void
@@ -666,8 +666,7 @@ static void parse_into(xen_session *s, x
{
if (!is_container_node(value_node, "value") ||
value_node->children->type != XML_ELEMENT_NODE ||
- 0 != strcmp((char *)value_node->children->name, "struct") ||
- value_node->children->children == NULL)
+ 0 != strcmp((char *)value_node->children->name, "struct"))
{
server_error(s,
"Expected Map from the server, but didn't get it");
@@ -890,6 +889,9 @@ static size_t size_of_member(const abstr
case REF:
return sizeof(arbitrary_record_opt *);
+ case STRUCT:
+ return type->struct_size;
+
default:
assert(false);
}
@@ -1183,7 +1185,8 @@ add_struct_value(const struct abstract_t
case INT:
case ENUM:
{
- const char *val_as_string = get_val_as_string(type, value, buf);
+ const char *val_as_string =
+ get_val_as_string(type, value, buf, sizeof(buf));
adder(node, key, "string", val_as_string);
}
break;
@@ -1215,7 +1218,8 @@ add_struct_value(const struct abstract_t
for (size_t i = 0; i < set_val->size; i++)
{
- void *member_value = set_val->contents + (i * member_size);
+ void *member_value = (char *)set_val->contents +
+ (i * member_size);
add_struct_value(member_type, member_value,
add_unnamed_value, NULL, data_node);
}
@@ -1254,7 +1258,7 @@ add_struct_value(const struct abstract_t
void *r_value = contents + (i * member_size) + r_offset;
const char *l_value_as_string =
- get_val_as_string(l_type, l_value, buf);
+ get_val_as_string(l_type, l_value, buf, sizeof(buf));
add_struct_value(r_type, r_value, add_struct_member,
l_value_as_string, struct_node);
@@ -1270,7 +1274,8 @@ add_struct_value(const struct abstract_t
static const char *
-get_val_as_string(const struct abstract_type *type, void *value, char *buf)
+get_val_as_string(const struct abstract_type *type, void *value, char *buf,
+ size_t bufsize)
{
switch (type->typename)
{
@@ -1304,7 +1309,7 @@ get_val_as_string(const struct abstract_
case INT:
{
int64_t val = *(int64_t *)value;
- snprintf(buf, sizeof(buf), "%"PRId64, val);
+ snprintf(buf, bufsize, "%"PRId64, val);
return buf;
}
break;
diff -r d1853a39e063 -r cb2575cec95c tools/libxen/src/xen_crashdump.c
--- a/tools/libxen/src/xen_crashdump.c Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxen/src/xen_crashdump.c Mon Mar 12 10:07:08 2007 -0600
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, XenSource Inc.
+ * Copyright (c) 2006-2007, XenSource Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -115,37 +115,6 @@ xen_crashdump_get_by_uuid(xen_session *s
bool
-xen_crashdump_create(xen_session *session, xen_crashdump *result,
xen_crashdump_record *record)
-{
- abstract_value param_values[] =
- {
- { .type = &xen_crashdump_record_abstract_type_,
- .u.struct_val = record }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("crashdump.create");
- return session->ok;
-}
-
-
-bool
-xen_crashdump_destroy(xen_session *session, xen_crashdump crashdump)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = crashdump }
- };
-
- xen_call_(session, "crashdump.destroy", param_values, 1, NULL, NULL);
- return session->ok;
-}
-
-
-bool
xen_crashdump_get_vm(xen_session *session, xen_vm *result, xen_crashdump
crashdump)
{
abstract_value param_values[] =
@@ -180,6 +149,20 @@ xen_crashdump_get_vdi(xen_session *sessi
bool
+xen_crashdump_destroy(xen_session *session, xen_crashdump self)
+{
+ abstract_value param_values[] =
+ {
+ { .type = &abstract_type_string,
+ .u.string_val = self }
+ };
+
+ xen_call_(session, "crashdump.destroy", param_values, 1, NULL, NULL);
+ return session->ok;
+}
+
+
+bool
xen_crashdump_get_all(xen_session *session, struct xen_crashdump_set **result)
{
diff -r d1853a39e063 -r cb2575cec95c tools/libxen/src/xen_vbd.c
--- a/tools/libxen/src/xen_vbd.c Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxen/src/xen_vbd.c Mon Mar 12 10:07:08 2007 -0600
@@ -552,6 +552,34 @@ xen_vbd_media_change(xen_session *sessio
bool
+xen_vbd_plug(xen_session *session, xen_vbd self)
+{
+ abstract_value param_values[] =
+ {
+ { .type = &abstract_type_string,
+ .u.string_val = self }
+ };
+
+ xen_call_(session, "VBD.plug", param_values, 1, NULL, NULL);
+ return session->ok;
+}
+
+
+bool
+xen_vbd_unplug(xen_session *session, xen_vbd self)
+{
+ abstract_value param_values[] =
+ {
+ { .type = &abstract_type_string,
+ .u.string_val = self }
+ };
+
+ xen_call_(session, "VBD.unplug", param_values, 1, NULL, NULL);
+ return session->ok;
+}
+
+
+bool
xen_vbd_get_all(xen_session *session, struct xen_vbd_set **result)
{
diff -r d1853a39e063 -r cb2575cec95c tools/libxen/src/xen_vdi.c
--- a/tools/libxen/src/xen_vdi.c Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxen/src/xen_vdi.c Mon Mar 12 10:07:08 2007 -0600
@@ -410,22 +410,6 @@ xen_vdi_set_name_description(xen_session
bool
-xen_vdi_set_sr(xen_session *session, xen_vdi vdi, xen_sr sr)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vdi },
- { .type = &abstract_type_string,
- .u.string_val = sr }
- };
-
- xen_call_(session, "VDI.set_SR", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
xen_vdi_set_virtual_size(xen_session *session, xen_vdi vdi, int64_t
virtual_size)
{
abstract_value param_values[] =
diff -r d1853a39e063 -r cb2575cec95c tools/libxen/src/xen_vif.c
--- a/tools/libxen/src/xen_vif.c Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxen/src/xen_vif.c Mon Mar 12 10:07:08 2007 -0600
@@ -500,6 +500,34 @@ xen_vif_remove_from_qos_algorithm_params
bool
+xen_vif_plug(xen_session *session, xen_vif self)
+{
+ abstract_value param_values[] =
+ {
+ { .type = &abstract_type_string,
+ .u.string_val = self }
+ };
+
+ xen_call_(session, "VIF.plug", param_values, 1, NULL, NULL);
+ return session->ok;
+}
+
+
+bool
+xen_vif_unplug(xen_session *session, xen_vif self)
+{
+ abstract_value param_values[] =
+ {
+ { .type = &abstract_type_string,
+ .u.string_val = self }
+ };
+
+ xen_call_(session, "VIF.unplug", param_values, 1, NULL, NULL);
+ return session->ok;
+}
+
+
+bool
xen_vif_get_all(xen_session *session, struct xen_vif_set **result)
{
diff -r d1853a39e063 -r cb2575cec95c tools/libxen/src/xen_vm.c
--- a/tools/libxen/src/xen_vm.c Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxen/src/xen_vm.c Mon Mar 12 10:07:08 2007 -0600
@@ -145,21 +145,9 @@ static const struct_member xen_vm_record
{ .key = "HVM_boot_params",
.type = &abstract_type_string_string_map,
.offset = offsetof(xen_vm_record, hvm_boot_params) },
- { .key = "platform_std_VGA",
- .type = &abstract_type_bool,
- .offset = offsetof(xen_vm_record, platform_std_vga) },
- { .key = "platform_serial",
- .type = &abstract_type_string,
- .offset = offsetof(xen_vm_record, platform_serial) },
- { .key = "platform_localtime",
- .type = &abstract_type_bool,
- .offset = offsetof(xen_vm_record, platform_localtime) },
- { .key = "platform_clock_offset",
- .type = &abstract_type_bool,
- .offset = offsetof(xen_vm_record, platform_clock_offset) },
- { .key = "platform_enable_audio",
- .type = &abstract_type_bool,
- .offset = offsetof(xen_vm_record, platform_enable_audio) },
+ { .key = "platform",
+ .type = &abstract_type_string_string_map,
+ .offset = offsetof(xen_vm_record, platform) },
{ .key = "PCI_bus",
.type = &abstract_type_string,
.offset = offsetof(xen_vm_record, pci_bus) },
@@ -217,7 +205,7 @@ xen_vm_record_free(xen_vm_record *record
free(record->pv_bootloader_args);
free(record->hvm_boot_policy);
xen_string_string_map_free(record->hvm_boot_params);
- free(record->platform_serial);
+ xen_string_string_map_free(record->platform);
free(record->pci_bus);
xen_string_string_map_free(record->other_config);
xen_vm_metrics_record_opt_free(record->metrics);
@@ -825,82 +813,18 @@ xen_vm_get_hvm_boot_params(xen_session *
bool
-xen_vm_get_platform_std_vga(xen_session *session, bool *result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_bool;
-
- XEN_CALL_("VM.get_platform_std_VGA");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_platform_serial(xen_session *session, char **result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_string;
-
- *result = NULL;
- XEN_CALL_("VM.get_platform_serial");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_platform_localtime(xen_session *session, bool *result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_bool;
-
- XEN_CALL_("VM.get_platform_localtime");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_platform_clock_offset(xen_session *session, bool *result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_bool;
-
- XEN_CALL_("VM.get_platform_clock_offset");
- return session->ok;
-}
-
-
-bool
-xen_vm_get_platform_enable_audio(xen_session *session, bool *result, xen_vm vm)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm }
- };
-
- abstract_type result_type = abstract_type_bool;
-
- XEN_CALL_("VM.get_platform_enable_audio");
+xen_vm_get_platform(xen_session *session, xen_string_string_map **result,
xen_vm vm)
+{
+ abstract_value param_values[] =
+ {
+ { .type = &abstract_type_string,
+ .u.string_val = vm }
+ };
+
+ abstract_type result_type = abstract_type_string_string_map;
+
+ *result = NULL;
+ XEN_CALL_("VM.get_platform");
return session->ok;
}
@@ -1442,81 +1366,67 @@ xen_vm_remove_from_hvm_boot_params(xen_s
bool
-xen_vm_set_platform_std_vga(xen_session *session, xen_vm vm, bool std_vga)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_bool,
- .u.bool_val = std_vga }
- };
-
- xen_call_(session, "VM.set_platform_std_VGA", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_platform_serial(xen_session *session, xen_vm vm, char *serial)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_string,
- .u.string_val = serial }
- };
-
- xen_call_(session, "VM.set_platform_serial", param_values, 2, NULL, NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_platform_localtime(xen_session *session, xen_vm vm, bool localtime)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_bool,
- .u.bool_val = localtime }
- };
-
- xen_call_(session, "VM.set_platform_localtime", param_values, 2, NULL,
NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_platform_clock_offset(xen_session *session, xen_vm vm, bool
clock_offset)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_bool,
- .u.bool_val = clock_offset }
- };
-
- xen_call_(session, "VM.set_platform_clock_offset", param_values, 2, NULL,
NULL);
- return session->ok;
-}
-
-
-bool
-xen_vm_set_platform_enable_audio(xen_session *session, xen_vm vm, bool
enable_audio)
-{
- abstract_value param_values[] =
- {
- { .type = &abstract_type_string,
- .u.string_val = vm },
- { .type = &abstract_type_bool,
- .u.bool_val = enable_audio }
- };
-
- xen_call_(session, "VM.set_platform_enable_audio", param_values, 2, NULL,
NULL);
+xen_vm_set_platform(xen_session *session, xen_vm vm, xen_string_string_map
*platform)
+{
+ abstract_value param_values[] =
+ {
+ { .type = &abstract_type_string,
+ .u.string_val = vm },
+ { .type = &abstract_type_string_string_map,
+ .u.set_val = (arbitrary_set *)platform }
+ };
+
+ xen_call_(session, "VM.set_platform", param_values, 2, NULL, NULL);
+ return session->ok;
+}
+
+
+bool
+xen_vm_add_to_platform(xen_session *session, xen_vm vm, char *key, char *value)
+{
+ abstract_value param_values[] =
+ {
+ { .type = &abstract_type_string,
+ .u.string_val = vm },
+ { .type = &abstract_type_string,
+ .u.string_val = key },
+ { .type = &abstract_type_string,
+ .u.string_val = value }
+ };
+
+ xen_call_(session, "VM.add_to_platform", param_values, 3, NULL, NULL);
+ return session->ok;
+}
+
+
+bool
+xen_vm_remove_from_platform(xen_session *session, xen_vm vm, char *key)
+{
+ abstract_value param_values[] =
+ {
+ { .type = &abstract_type_string,
+ .u.string_val = vm },
+ { .type = &abstract_type_string,
+ .u.string_val = key }
+ };
+
+ xen_call_(session, "VM.remove_from_platform", param_values, 2, NULL, NULL);
+ return session->ok;
+}
+
+
+bool
+xen_vm_set_pci_bus(xen_session *session, xen_vm vm, char *pci_bus)
+{
+ abstract_value param_values[] =
+ {
+ { .type = &abstract_type_string,
+ .u.string_val = vm },
+ { .type = &abstract_type_string,
+ .u.string_val = pci_bus }
+ };
+
+ xen_call_(session, "VM.set_PCI_bus", param_values, 2, NULL, NULL);
return session->ok;
}
diff -r d1853a39e063 -r cb2575cec95c tools/libxen/test/test_bindings.c
--- a/tools/libxen/test/test_bindings.c Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/libxen/test/test_bindings.c Mon Mar 12 10:07:08 2007 -0600
@@ -375,6 +375,8 @@ static xen_vm create_new_vm(xen_session
.memory_static_min = 128,
.vcpus_policy = "credit",
.vcpus_params = vcpus_params,
+ .vcpus_max = 4,
+ .vcpus_at_startup = 2,
.actions_after_shutdown = XEN_ON_NORMAL_EXIT_DESTROY,
.actions_after_reboot = XEN_ON_NORMAL_EXIT_RESTART,
.actions_after_crash = XEN_ON_CRASH_BEHAVIOUR_PRESERVE,
diff -r d1853a39e063 -r cb2575cec95c tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/python/xen/lowlevel/xc/xc.c Mon Mar 12 10:07:08 2007 -0600
@@ -47,7 +47,7 @@ static PyObject *pyxc_error_to_exception
static PyObject *pyxc_error_to_exception(void)
{
PyObject *pyerr;
- const xc_error const *err = xc_get_last_error();
+ const xc_error *err = xc_get_last_error();
const char *desc = xc_error_code_to_desc(err->code);
if (err->code == XC_ERROR_NONE)
@@ -1007,6 +1007,24 @@ static PyObject *pyxc_domain_send_trigge
return zero;
}
+static PyObject *pyxc_send_debug_keys(XcObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ char *keys;
+
+ static char *kwd_list[] = { "keys", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "s", kwd_list, &keys) )
+ return NULL;
+
+ if ( xc_send_debug_keys(self->xc_handle, keys) != 0 )
+ return pyxc_error_to_exception();
+
+ Py_INCREF(zero);
+ return zero;
+}
+
static PyObject *dom_op(XcObject *self, PyObject *args,
int (*fn)(int, uint32_t))
{
@@ -1419,6 +1437,12 @@ static PyMethodDef pyxc_methods[] = {
" trigger [int]: Trigger type number.\n"
" vcpu [int]: VCPU to be sent trigger.\n"
"Returns: [int] 0 on success; -1 on error.\n" },
+
+ { "send_debug_keys",
+ (PyCFunction)pyxc_send_debug_keys,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "Inject debug keys into Xen.\n"
+ " keys [str]: String of keys to inject.\n" },
#ifdef __powerpc__
{ "arch_alloc_real_mode_area",
diff -r d1853a39e063 -r cb2575cec95c tools/python/xen/xend/XendAPI.py
--- a/tools/python/xen/xend/XendAPI.py Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/python/xen/xend/XendAPI.py Mon Mar 12 10:07:08 2007 -0600
@@ -676,8 +676,9 @@ class XendAPI(object):
return xen_api_success_void()
def host_remove_from_other_config(self, session, host_ref, key):
node = XendNode.instance()
- del node.other_config[key]
- node.save()
+ if key in node.other_config:
+ del node.other_config[key]
+ node.save()
return xen_api_success_void()
def host_get_API_version_major(self, _, ref):
return xen_api_success(XEN_API_VERSION_MAJOR)
@@ -998,7 +999,6 @@ class XendAPI(object):
'VIFs',
'VBDs',
'VTPMs',
- 'PCI_bus',
'tools_version',
'domid',
'is_control_domain',
@@ -1024,12 +1024,8 @@ class XendAPI(object):
'PV_bootloader_args',
'HVM_boot_policy',
'HVM_boot_params',
- 'platform_std_VGA',
- 'platform_serial',
- 'platform_localtime',
- 'platform_clock_offset',
- 'platform_enable_audio',
- 'platform_keymap',
+ 'platform',
+ 'PCI_bus',
'other_config']
VM_methods = [('clone', 'VM'),
@@ -1042,6 +1038,10 @@ class XendAPI(object):
('hard_reboot', None),
('suspend', None),
('resume', None),
+ ('add_to_HVM_boot_params', None),
+ ('remove_from_HVM_boot_params', None),
+ ('add_to_platform', None),
+ ('remove_from_platform', None),
('add_to_other_config', None),
('remove_from_other_config', None)]
@@ -1071,13 +1071,7 @@ class XendAPI(object):
'PV_bootloader_args',
'HVM_boot_policy',
'HVM_boot_params',
- 'platform_std_VGA',
- 'platform_serial',
- 'platform_localtime',
- 'platform_clock_offset',
- 'platform_enable_audio',
- 'platform_keymap',
- 'grub_cmdline',
+ 'platform',
'PCI_bus',
'other_config']
@@ -1089,7 +1083,10 @@ class XendAPI(object):
xd = XendDomain.instance()
dominfo = xd.get_vm_by_uuid(vm_ref)
dominfo.info[name] = value
- xd.managed_config_save(dominfo)
+ return self._VM_save(dominfo)
+
+ def _VM_save(self, dominfo):
+ XendDomain.instance().managed_config_save(dominfo)
return xen_api_success_void()
# attributes (ro)
@@ -1136,10 +1133,6 @@ class XendAPI(object):
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
return xen_api_success(dom.get_consoles())
- def VM_get_PCI_bus(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return dom.get_pci_bus()
-
def VM_get_tools_version(self, session, vm_ref):
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
return dom.get_tools_version()
@@ -1214,29 +1207,16 @@ class XendAPI(object):
def VM_get_HVM_boot_params(self, session, vm_ref):
return self.VM_get('HVM_boot_params', session, vm_ref)
- def VM_get_platform_std_VGA(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success(dom.get_platform_std_vga())
-
- def VM_get_platform_serial(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success(dom.get_platform_serial())
-
- def VM_get_platform_localtime(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success(dom.get_platform_localtime())
-
- def VM_get_platform_clock_offset(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success(dom.get_platform_clock_offset())
-
- def VM_get_platform_enable_audio(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success(dom.get_platform_enable_audio())
-
- def VM_get_platform_keymap(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success(dom.get_platform_keymap())
+ def VM_get_platform(self, session, vm_ref):
+ dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
+ return xen_api_success(dom.get_platform())
+
+ def VM_get_PCI_bus(self, session, vm_ref):
+ dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
+ return dom.get_pci_bus()
+
+ def VM_set_PCI_bus(self, session, vm_ref, val):
+ return self.VM_set('PCI_bus', session, vm_ref, val)
def VM_get_other_config(self, session, vm_ref):
return self.VM_get('other_config', session, vm_ref)
@@ -1253,7 +1233,7 @@ class XendAPI(object):
def VM_set_name_label(self, session, vm_ref, label):
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
dom.setName(label)
- return xen_api_success_void()
+ return self._VM_save(dom)
def VM_set_name_description(self, session, vm_ref, desc):
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
@@ -1284,12 +1264,12 @@ class XendAPI(object):
return xen_api_todo()
def VM_set_actions_after_shutdown(self, session, vm_ref, action):
- if action not in XEN_API_ON_NORMAL_EXIST:
+ if action not in XEN_API_ON_NORMAL_EXIT:
return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
return self.VM_set('actions_after_shutdown', session, vm_ref, action)
def VM_set_actions_after_reboot(self, session, vm_ref, action):
- if action not in XEN_API_ON_NORMAL_EXIST:
+ if action not in XEN_API_ON_NORMAL_EXIT:
return xen_api_error(['VM_ON_NORMAL_EXIT_INVALID', vm_ref])
return self.VM_set('actions_after_reboot', session, vm_ref, action)
@@ -1319,14 +1299,16 @@ class XendAPI(object):
if 'HVM_boot_params' not in dom.info:
dom.info['HVM_boot_params'] = {}
dom.info['HVM_boot_params'][key] = value
- return xen_api_success_void()
+ return self._VM_save(dom)
def VM_remove_from_HVM_boot_params(self, session, vm_ref, key):
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
if 'HVM_boot_params' in dom.info \
and key in dom.info['HVM_boot_params']:
del dom.info['HVM_boot_params'][key]
- return xen_api_success_void()
+ return self._VM_save(dom)
+ else:
+ return xen_api_success_void()
def VM_set_PV_bootloader(self, session, vm_ref, value):
return self.VM_set('PV_bootloader', session, vm_ref, value)
@@ -1343,40 +1325,42 @@ class XendAPI(object):
def VM_set_PV_bootloader_args(self, session, vm_ref, value):
return self.VM_set('PV_bootloader_args', session, vm_ref, value)
- def VM_set_platform_std_VGA(self, session, vm_ref, value):
- return self.VM_set('platform_std_vga', session, vm_ref, value)
-
- def VM_set_platform_serial(self, session, vm_ref, value):
- return self.VM_set('platform_serial', session, vm_ref, value)
-
- def VM_set_platform_keymap(self, session, vm_ref, value):
- return self.VM_set('platform_keymap', session, vm_ref, value)
-
- def VM_set_platform_localtime(self, session, vm_ref, value):
- return self.VM_set('platform_localtime', session, vm_ref, value)
-
- def VM_set_platform_clock_offset(self, session, vm_ref, value):
- return self.VM_set('platform_clock_offset', session, vm_ref, value)
-
- def VM_set_platform_enable_audio(self, session, vm_ref, value):
- return self.VM_set('platform_enable_audio', session, vm_ref, value)
-
+ def VM_set_platform(self, session, vm_ref, value):
+ return self.VM_set('platform', session, vm_ref, value)
+
+ def VM_add_to_platform(self, session, vm_ref, key, value):
+ dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
+ plat = dom.get_platform()
+ plat[key] = value
+ return self.VM_set_platform(session, vm_ref, plat)
+
+ def VM_remove_from_platform(self, session, vm_ref, key):
+ dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
+ plat = dom.get_platform()
+ if key in plat:
+ del plat[key]
+ return self.VM_set_platform(session, vm_ref, plat)
+ else:
+ return xen_api_success_void()
+
def VM_set_other_config(self, session, vm_ref, value):
- return self.VM_set('otherconfig', session, vm_ref, value)
+ return self.VM_set('other_config', session, vm_ref, value)
def VM_add_to_other_config(self, session, vm_ref, key, value):
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- if dom and 'otherconfig' in dom.info:
- dom.info['otherconfig'][key] = value
- return xen_api_success_void()
+ if dom and 'other_config' in dom.info:
+ dom.info['other_config'][key] = value
+ return self._VM_save(dom)
def VM_remove_from_other_config(self, session, vm_ref, key):
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- if dom and 'otherconfig' in dom.info \
- and key in dom.info['otherconfig']:
- del dom.info['otherconfig'][key]
- return xen_api_success_void()
-
+ if dom and 'other_config' in dom.info \
+ and key in dom.info['other_config']:
+ del dom.info['other_config'][key]
+ return self._VM_save(dom)
+ else:
+ return xen_api_success_void()
+
# class methods
def VM_get_all(self, session):
refs = [d.get_uuid() for d in XendDomain.instance().list('all')]
@@ -1437,12 +1421,7 @@ class XendAPI(object):
'PV_bootloader_args': xeninfo.info.get('PV_bootloader_args'),
'HVM_boot_policy': xeninfo.info.get('HVM_boot_policy'),
'HVM_boot_params': xeninfo.info.get('HVM_boot_params'),
- 'platform_std_VGA': xeninfo.get_platform_std_vga(),
- 'platform_serial': xeninfo.get_platform_serial(),
- 'platform_localtime': xeninfo.get_platform_localtime(),
- 'platform_clock_offset': xeninfo.get_platform_clock_offset(),
- 'platform_enable_audio': xeninfo.get_platform_enable_audio(),
- 'platform_keymap': xeninfo.get_platform_keymap(),
+ 'platform': xeninfo.get_platform(),
'PCI_bus': xeninfo.get_pci_bus(),
'tools_version': xeninfo.get_tools_version(),
'other_config': xeninfo.info.get('other_config', {}),
@@ -1486,10 +1465,13 @@ class XendAPI(object):
start_paused = start_paused)
def VM_start(self, session, vm_ref, start_paused):
- return XendTask.log_progress(0, 100, do_vm_func,
- "domain_start", vm_ref,
- start_paused = start_paused)
-
+ try:
+ return XendTask.log_progress(0, 100, do_vm_func,
+ "domain_start", vm_ref,
+ start_paused = start_paused)
+ except HVMRequired, exn:
+ return xen_api_error(['VM_HVM_REQUIRED', vm_ref])
+
def VM_suspend(self, session, vm_ref):
return XendTask.log_progress(0, 100, do_vm_func,
"domain_suspend", vm_ref)
@@ -1754,13 +1736,13 @@ class XendAPI(object):
# Xen API: Class VDI
# ----------------------------------------------------------------
- VDI_attr_ro = ['VBDs',
+ VDI_attr_ro = ['SR',
+ 'VBDs',
'physical_utilisation',
'sector_size',
'type']
VDI_attr_rw = ['name_label',
'name_description',
- 'SR',
'virtual_size',
'sharable',
'read_only']
@@ -1811,9 +1793,6 @@ class XendAPI(object):
def VDI_set_name_description(self, session, vdi_ref, value):
self._get_VDI(vdi_ref).name_description = value
return xen_api_success_void()
-
- def VDI_set_SR(self, session, vdi_ref, value):
- return xen_api_error(XEND_ERROR_UNSUPPORTED)
def VDI_set_virtual_size(self, session, vdi_ref, value):
return xen_api_error(XEND_ERROR_UNSUPPORTED)
@@ -1929,7 +1908,7 @@ class XendAPI(object):
XendDomain.POWER_STATE_NAMES[dom.state]])
from xen.xend.server import tpmif
tpmif.destroy_vtpmstate(dom.getName())
- return xen_api_success(True)
+ return xen_api_success_void()
else:
return xen_api_error(['HANDLE_INVALID', 'VM', vtpm_struct['VM']])
diff -r d1853a39e063 -r cb2575cec95c tools/python/xen/xend/XendCheckpoint.py
--- a/tools/python/xen/xend/XendCheckpoint.py Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/python/xen/xend/XendCheckpoint.py Mon Mar 12 10:07:08 2007 -0600
@@ -74,9 +74,13 @@ def save(fd, dominfo, network, live, dst
image_cfg = dominfo.info.get('image', {})
hvm = image_cfg.has_key('hvm')
+ stdvga = 0
if hvm:
log.info("save hvm domain")
+ if image_cfg['hvm']['devices']['stdvga'] == 1:
+ stdvga = 1
+
# xc_save takes three customization parameters: maxit, max_f, and
# flags the last controls whether or not save is 'live', while the
# first two further customize behaviour when 'live' save is
@@ -84,7 +88,8 @@ def save(fd, dominfo, network, live, dst
# libxenguest; see the comments and/or code in xc_linux_save() for
# more information.
cmd = [xen.util.auxbin.pathTo(XC_SAVE), str(fd),
- str(dominfo.getDomid()), "0", "0", str(int(live) | (int(hvm) <<
2)) ]
+ str(dominfo.getDomid()), "0", "0",
+ str(int(live) | (int(hvm) << 2) | (int(stdvga) << 3)) ]
log.debug("[xc_save]: %s", string.join(cmd))
def saveInputHandler(line, tochild):
diff -r d1853a39e063 -r cb2575cec95c tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/python/xen/xend/XendConfig.py Mon Mar 12 10:07:08 2007 -0600
@@ -12,7 +12,7 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#============================================================================
-# Copyright (C) 2006 XenSource Ltd
+# Copyright (C) 2006-2007 XenSource Ltd
#============================================================================
import logging
@@ -111,22 +111,18 @@ XENAPI_CFG_TO_LEGACY_CFG = {
'actions_after_shutdown': 'on_poweroff',
'actions_after_reboot': 'on_reboot',
'actions_after_crash': 'on_crash',
- 'platform_localtime': 'localtime',
'PV_bootloader': 'bootloader',
'PV_bootloader_args': 'bootloader_args',
}
LEGACY_CFG_TO_XENAPI_CFG = reverse_dict(XENAPI_CFG_TO_LEGACY_CFG)
-# Mapping from XendConfig configuration keys to the old
-# legacy configuration keys that are found in the 'image'
-# SXP object.
-XENAPI_HVM_CFG = {
- 'platform_std_vga': 'stdvga',
- 'platform_serial' : 'serial',
- 'platform_localtime': 'localtime',
- 'platform_keymap' : 'keymap'
-}
+# Platform configuration keys.
+XENAPI_PLATFORM_CFG = [ 'acpi', 'apic', 'device_model', 'display', 'fda',
+ 'fdb', 'keymap', 'isa', 'localtime', 'nographic',
+ 'pae', 'serial', 'sdl', 'soundhw','stdvga', 'usb',
+ 'usbdevice', 'vnc', 'vncconsole', 'vncdisplay',
+ 'vnclisten', 'vncpasswd', 'vncunused', 'xauthority']
# List of XendConfig configuration keys that have no direct equivalent
# in the old world.
@@ -151,7 +147,6 @@ XENAPI_CFG_TYPES = {
'actions_after_shutdown': str,
'actions_after_reboot': str,
'actions_after_crash': str,
- 'tpm_backend': int,
'PV_bootloader': str,
'PV_kernel': str,
'PV_ramdisk': str,
@@ -159,15 +154,10 @@ XENAPI_CFG_TYPES = {
'PV_bootloader_args': str,
'HVM_boot_policy': str,
'HVM_boot_params': dict,
- 'platform_std_vga': bool0,
- 'platform_serial': str,
- 'platform_localtime': bool0,
- 'platform_clock_offset': bool0,
- 'platform_enable_audio': bool0,
- 'platform_keymap': str,
- 'pci_bus': str,
+ 'PCI_bus': str,
+ 'platform': dict,
'tools_version': dict,
- 'otherconfig': dict,
+ 'other_config': dict,
}
# List of legacy configuration keys that have no equivalent in the
@@ -237,44 +227,7 @@ LEGACY_XENSTORE_VM_PARAMS = [
'on_xend_stop',
]
-LEGACY_IMAGE_CFG = [
- ('root', str),
- ('ip', str),
- ('nographic', int),
- ('vnc', int),
- ('sdl', int),
- ('vncdisplay', int),
- ('vncunused', int),
- ('vncpasswd', str),
- ('vnclisten', str),
-]
-
-LEGACY_IMAGE_HVM_CFG = [
- ('device_model', str),
- ('display', str),
- ('xauthority', str),
- ('vncconsole', int),
- ('pae', int),
- ('apic', int),
-]
-
-LEGACY_IMAGE_HVM_DEVICES_CFG = [
- ('acpi', int),
- ('boot', str),
- ('fda', str),
- ('fdb', str),
- ('isa', int),
- ('keymap', str),
- ('localtime', int),
- ('serial', str),
- ('stdvga', int),
- ('soundhw', str),
- ('usb', int),
- ('usbdevice', str),
- ('vcpus', int),
-]
-
-LEGACY_DM = '/usr/lib/xen/bin/qemu-dm'
+DEFAULT_DM = '/usr/lib/xen/bin/qemu-dm'
##
## Config Choices
@@ -316,7 +269,6 @@ class XendConfig(dict):
self._sxp_to_xapi_unsupported(sxp_obj)
elif xapi:
self.update_with_xenapi_config(xapi)
- self._add_xapi_unsupported(xapi)
elif dominfo:
# output from xc.domain_getinfo
self._dominfo_to_xapi(dominfo)
@@ -363,7 +315,6 @@ class XendConfig(dict):
'memory_dynamic_max': 0,
'memory_actual': 0,
'devices': {},
- 'image': {},
'security': None,
'on_xend_start': 'ignore',
'on_xend_stop': 'ignore',
@@ -377,6 +328,7 @@ class XendConfig(dict):
'vbd_refs': [],
'vtpm_refs': [],
'other_config': {},
+ 'platform': {}
}
return defaults
@@ -417,12 +369,23 @@ class XendConfig(dict):
if 'name_label' not in self:
self['name_label'] = 'Domain-' + self['uuid']
+ def _platform_sanity_check(self):
+ if self.is_hvm():
+ if 'device_model' not in self['platform']:
+ self['platform']['device_model'] = DEFAULT_DM
+
+ # Compatibility hack, can go away soon.
+ if 'soundhw' not in self['platform'] and \
+ self['platform'].get('enable_audio'):
+ self['platform']['soundhw'] = 'sb16'
+
def validate(self):
self._uuid_sanity_check()
self._name_sanity_check()
self._memory_sanity_check()
self._actions_sanity_check()
self._vcpus_sanity_check()
+ self._platform_sanity_check()
def _dominfo_to_xapi(self, dominfo):
self['domid'] = dominfo['domid']
@@ -497,6 +460,18 @@ class XendConfig(dict):
except (TypeError, ValueError), e:
log.warn("Unable to parse key %s: %s: %s" %
(key, str(val), e))
+
+ if 'platform' not in cfg:
+ cfg['platform'] = {}
+ localtime = sxp.child_value(sxp_cfg, 'localtime')
+ if localtime is not None:
+ cfg['platform']['localtime'] = localtime
+
+ # Compatibility hack -- can go soon.
+ for key in XENAPI_PLATFORM_CFG:
+ val = sxp.child_value(sxp_cfg, "platform_" + key, None)
+ if val is not None:
+ self['platform'][key] = val
# Compatibility hack -- can go soon.
boot_order = sxp.child_value(sxp_cfg, 'HVM_boot')
@@ -652,10 +627,9 @@ class XendConfig(dict):
self.update_with_image_sxp(image_sxp)
# Convert Legacy HVM parameters to Xen API configuration
- self['platform_std_vga'] = bool0(cfg.get('stdvga', 0))
- self['platform_serial'] = str(cfg.get('serial', ''))
- self['platform_localtime'] = bool0(cfg.get('localtime', 0))
- self['platform_enable_audio'] = bool0(cfg.get('soundhw', 0))
+ for key in XENAPI_PLATFORM_CFG:
+ if key in cfg:
+ self['platform'][key] = cfg[key]
# make sure a sane maximum is set
if self['memory_static_max'] <= 0:
@@ -672,7 +646,7 @@ class XendConfig(dict):
self['vtpm_refs'] = cfg.get('vtpm_refs', [])
# coalesce hvm vnc frame buffer with vfb config
- if self['image']['type'] == 'hvm' and self['image'].get('vnc', 0):
+ if self.is_hvm() and self['platform'].get('vnc', 0):
# add vfb device if it isn't there already
has_rfb = False
for console_uuid in self['console_refs']:
@@ -685,11 +659,11 @@ class XendConfig(dict):
if not has_rfb:
dev_config = ['vfb']
- # copy VNC related params from image config to vfb dev conf
+ # copy VNC related params from platform config to vfb dev conf
for key in ['vncpasswd', 'vncunused', 'vncdisplay',
'vnclisten']:
- if key in self['image']:
- dev_config.append([key, self['image'][key]])
+ if key in self['platform']:
+ dev_config.append([key, self['platform'][key]])
self.device_add('vfb', cfg_sxp = dev_config)
@@ -706,39 +680,19 @@ class XendConfig(dict):
# the image (as well as HVM images)
image_sxp = sxp.child_value(sxp_cfg, 'image', [])
if image_sxp:
- image = {}
- image['type'] = sxp.name(image_sxp)
- for arg, conv in LEGACY_IMAGE_CFG:
- val = sxp.child_value(image_sxp, arg, None)
- if val != None:
- image[arg] = conv(val)
-
- image_hvm = {}
- for arg, conv in LEGACY_IMAGE_HVM_CFG:
- val = sxp.child_value(image_sxp, arg, None)
- if val != None:
- image_hvm[arg] = conv(val)
-
- image_hvm_devices = {}
- for arg, conv in LEGACY_IMAGE_HVM_DEVICES_CFG:
- val = sxp.child_value(image_sxp, arg, None)
- if val != None:
- image_hvm_devices[arg] = conv(val)
-
- if image_hvm or image_hvm_devices:
- image['hvm'] = image_hvm
- image['hvm']['devices'] = image_hvm_devices
-
+ image_type = sxp.name(image_sxp)
+ if image_type != 'hvm' and image_type != 'linux':
+ self['platform']['image_type'] = image_type
+
+ for key in XENAPI_PLATFORM_CFG:
+ val = sxp.child_value(image_sxp, key, None)
+ if val is not None:
+ self['platform'][key] = val
+
notes = sxp.children(image_sxp, 'notes')
if notes:
- image['notes'] = self.notes_from_sxp(notes[0])
-
- self['image'] = image
-
- for apikey, imgkey in XENAPI_HVM_CFG.items():
- val = sxp.child_value(image_sxp, imgkey, None)
- if val != None:
- self[apikey] = val
+ self['notes'] = self.notes_from_sxp(notes[0])
+
self._hvm_boot_params_from_sxp(image_sxp)
# extract backend value
@@ -774,33 +728,6 @@ class XendConfig(dict):
_set_cfg_if_exists('up_time')
_set_cfg_if_exists('status') # TODO, deprecated
- def _add_xapi_unsupported(self, xapi_dict):
- """Updates the configuration object with entries that are not
- officially supported by the Xen API but is required for
- the rest of Xend to function.
- """
-
- # populate image
- if 'image' in xapi_dict:
- self['image'].update(xapi_dict['image'])
- else:
- hvm = self['HVM_boot_policy'] != ''
- self['image']['type'] = hvm and 'hvm' or 'linux'
- if hvm:
- self['image']['hvm'] = {'devices': {}}
- for xapi, cfgapi in XENAPI_HVM_CFG.items():
- if xapi in self:
- self['image']['hvm']['devices'][cfgapi] = self[xapi]
-
- # currently unsupported options
- self['image']['hvm']['device_model'] = LEGACY_DM
- self['image']['vnc'] = 0
- self['image']['hvm']['pae'] = 1
-
- if self['platform_enable_audio']:
- self['image']['hvm']['devices']['soundhw'] = 'sb16'
-
-
def _get_old_state_string(self):
"""Returns the old xm state string.
@rtype: string
@@ -890,9 +817,7 @@ class XendConfig(dict):
if self.has_key(legacy) and self[legacy] not in (None, []):
sxpr.append([legacy, self[legacy]])
- if 'image' in self and self['image']:
- sxpr.append(['image', self.image_sxpr()])
-
+ sxpr.append(['image', self.image_sxpr()])
sxpr.append(['status', domain.state])
sxpr.append(['memory_dynamic_min', self.get('memory_dynamic_min')])
sxpr.append(['memory_dynamic_max', self.get('memory_dynamic_max')])
@@ -1339,7 +1264,7 @@ class XendConfig(dict):
def image_sxpr(self):
"""Returns a backwards compatible image SXP expression that is
used in xenstore's /vm/<uuid>/image value and xm list."""
- image = [self['image'].get('type', 'linux')]
+ image = [self.image_type()]
if self.has_key('PV_kernel'):
image.append(['kernel', self['PV_kernel']])
if self.has_key('PV_ramdisk') and self['PV_ramdisk']:
@@ -1347,28 +1272,12 @@ class XendConfig(dict):
if self.has_key('PV_args') and self['PV_args']:
image.append(['args', self['PV_args']])
- for arg, conv in LEGACY_IMAGE_CFG:
- if self['image'].has_key(arg):
- image.append([arg, self['image'][arg]])
-
- if 'hvm' in self['image']:
- for arg, conv in LEGACY_IMAGE_HVM_CFG:
- if self['image']['hvm'].get(arg):
- image.append([arg, conv(self['image']['hvm'][arg])])
-
- if 'hvm' in self['image'] and 'devices' in self['image']['hvm']:
- for arg, conv in LEGACY_IMAGE_HVM_DEVICES_CFG:
- val = self['image']['hvm']['devices'].get(arg)
- if val != None:
- try:
- if conv: val = conv(val)
- except (ValueError, TypeError):
- if type(val) == bool: val = int(val)
-
- image.append([arg, val])
-
- if 'notes' in self['image']:
- image.append(self.notes_sxp(self['image']['notes']))
+ for key in XENAPI_PLATFORM_CFG:
+ if key in self['platform']:
+ image.append([key, self['platform'][key]])
+
+ if 'notes' in self:
+ image.append(self.notes_sxp(self['notes']))
return image
@@ -1399,57 +1308,24 @@ class XendConfig(dict):
self['PV_ramdisk'] = sxp.child_value(image_sxp, 'ramdisk','')
self['PV_args'] = kernel_args
- # Store image SXP in python dictionary format
- image = {}
- image['type'] = sxp.name(image_sxp)
- for arg, conv in LEGACY_IMAGE_CFG:
- val = sxp.child_value(image_sxp, arg, None)
- if val != None:
- image[arg] = conv(val)
-
- image_hvm = {}
- for arg, conv in LEGACY_IMAGE_HVM_CFG:
- val = sxp.child_value(image_sxp, arg, None)
- if val != None:
- image_hvm[arg] = conv(val)
-
- image_hvm_devices = {}
- for arg, conv in LEGACY_IMAGE_HVM_DEVICES_CFG:
- val = sxp.child_value(image_sxp, arg, None)
- if val != None:
- try:
- image_hvm_devices[arg] = conv(val)
- except (ValueError, TypeError):
- image_hvm_devices[arg] = val
-
-
- if image_hvm or image_hvm_devices:
- image['hvm'] = image_hvm
- image['hvm']['devices'] = image_hvm_devices
+ for key in XENAPI_PLATFORM_CFG:
+ val = sxp.child_value(image_sxp, key, None)
+ if val is not None:
+ self['platform'][key] = val
notes = sxp.children(image_sxp, 'notes')
if notes:
- image['notes'] = self.notes_from_sxp(notes[0])
-
- self['image'] = image
-
- for apikey, imgkey in XENAPI_HVM_CFG.items():
- val = sxp.child_value(image_sxp, imgkey, None)
- if val != None:
- type_conv = XENAPI_CFG_TYPES[apikey]
- if callable(type_conv):
- self[apikey] = type_conv(val)
- else:
- self[apikey] = val
+ self['notes'] = self.notes_from_sxp(notes[0])
+
self._hvm_boot_params_from_sxp(image_sxp)
def set_notes(self, notes):
'Add parsed elfnotes to image'
- self['image']['notes'] = notes
+ self['notes'] = notes
def get_notes(self):
try:
- return self['image']['notes'] or {}
+ return self['notes'] or {}
except KeyError:
return {}
@@ -1471,11 +1347,9 @@ class XendConfig(dict):
self['HVM_boot_policy'] = 'BIOS order'
self['HVM_boot_params'] = { 'order' : boot }
-
-#
-# debugging
-#
-
-if __name__ == "__main__":
- pass
-
+ def is_hvm(self):
+ return self['HVM_boot_policy'] != ''
+
+ def image_type(self):
+ stored_type = self['platform'].get('image_type')
+ return stored_type or (self.is_hvm() and 'hvm' or 'linux')
diff -r d1853a39e063 -r cb2575cec95c tools/python/xen/xend/XendDomain.py
--- a/tools/python/xen/xend/XendDomain.py Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/python/xen/xend/XendDomain.py Mon Mar 12 10:07:08 2007 -0600
@@ -495,7 +495,7 @@ class XendDomain:
self._refresh(refresh_shutdown = False)
dom = self.domain_lookup_nr(domid)
if not dom:
- raise XendInvalidDomain("No domain named '%s'." % str(domid))
+ raise XendInvalidDomain(str(domid))
return dom
finally:
self.domains_lock.release()
diff -r d1853a39e063 -r cb2575cec95c tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/python/xen/xend/XendDomainInfo.py Mon Mar 12 10:07:08 2007 -0600
@@ -13,7 +13,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#============================================================================
# Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx>
-# Copyright (C) 2005, 2006 XenSource Ltd
+# Copyright (C) 2005-2007 XenSource Ltd
#============================================================================
"""Representation of a single domain.
@@ -176,14 +176,8 @@ def recreate(info, priv):
vm._storeVmDetails()
vm._storeDomDetails()
- if vm.info['image']: # Only dom0 should be without an image entry when
- # recreating, but we cope with missing ones
- # elsewhere just in case.
- vm.image = image.create(vm,
- vm.info,
- vm.info['image'],
- vm.info['devices'])
- vm.image.recreate()
+ vm.image = image.create(vm, vm.info)
+ vm.image.recreate()
vm._registerWatches()
vm.refreshShutdown(xeninfo)
@@ -448,9 +442,7 @@ class XendDomainInfo:
self.storeDom("control/shutdown", reason)
## shutdown hypercall for hvm domain desides xenstore write
- image_cfg = self.info.get('image', {})
- hvm = image_cfg.has_key('hvm')
- if hvm:
+ if self.info.is_hvm():
for code in DOMAIN_SHUTDOWN_REASONS.keys():
if DOMAIN_SHUTDOWN_REASONS[code] == reason:
break
@@ -781,7 +773,6 @@ class XendDomainInfo:
'name': self.info['name_label'],
'console/limit': str(xoptions.get_console_limit() * 1024),
'memory/target': str(self.info['memory_static_min'] * 1024),
- 'control/platform-feature-multiprocessor-suspend': str(1)
}
def f(n, v):
@@ -795,6 +786,9 @@ class XendDomainInfo:
f('console/ring-ref', self.console_mfn)
f('store/port', self.store_port)
f('store/ring-ref', self.store_mfn)
+
+ if arch.type == "x86":
+ f('control/platform-feature-multiprocessor-suspend', True)
# elfnotes
for n, v in self.info.get_notes().iteritems():
@@ -1387,9 +1381,7 @@ class XendDomainInfo:
self.shutdownStartTime = None
- image_cfg = self.info.get('image', {})
- hvm = image_cfg.has_key('hvm')
-
+ hvm = self.info.is_hvm()
if hvm:
info = xc.xeninfo()
if 'hvm' not in info['xen_caps']:
@@ -1436,14 +1428,8 @@ class XendDomainInfo:
self._configureBootloader()
- if not self._infoIsSet('image'):
- raise VmError('Missing image in configuration')
-
try:
- self.image = image.create(self,
- self.info,
- self.info['image'],
- self.info['devices'])
+ self.image = image.create(self, self.info)
localtime = self.info.get('platform_localtime', False)
if localtime:
@@ -1503,9 +1489,15 @@ class XendDomainInfo:
self.info['start_time'] = time.time()
self._stateSet(DOM_STATE_RUNNING)
- except (RuntimeError, VmError), exn:
+ except VmError, exn:
log.exception("XendDomainInfo.initDomain: exception occurred")
- self.image.cleanupBootloading()
+ if self.image:
+ self.image.cleanupBootloading()
+ raise exn
+ except RuntimeError, exn:
+ log.exception("XendDomainInfo.initDomain: exception occurred")
+ if self.image:
+ self.image.cleanupBootloading()
raise VmError(str(exn))
@@ -1572,13 +1564,8 @@ class XendDomainInfo:
self.console_mfn = console_mfn
self._introduceDomain()
- image_cfg = self.info.get('image', {})
- hvm = image_cfg.has_key('hvm')
- if hvm:
- self.image = image.create(self,
- self.info,
- self.info['image'],
- self.info['devices'])
+ if self.info.is_hvm():
+ self.image = image.create(self, self.info)
if self.image:
self.image.createDeviceModel(True)
self.image.register_shutdown_watch()
@@ -1740,11 +1727,7 @@ class XendDomainInfo:
if boot:
# HVM booting.
- self.info['image']['type'] = 'hvm'
- if not 'devices' in self.info['image']:
- self.info['image']['devices'] = {}
- self.info['image']['devices']['boot'] = \
- self.info['HVM_boot_params'].get('order', 'dc')
+ pass
elif not blexec and kernel:
# Boot from dom0. Nothing left to do -- the kernel and ramdisk
# will be picked up by image.py.
@@ -1908,10 +1891,9 @@ class XendDomainInfo:
if self._infoIsSet(info_key):
to_store[key] = str(self.info[info_key])
- if self.info.get('image'):
- image_sxpr = self.info.image_sxpr()
- if image_sxpr:
- to_store['image'] = sxp.to_string(image_sxpr)
+ image_sxpr = self.info.image_sxpr()
+ if image_sxpr:
+ to_store['image'] = sxp.to_string(image_sxpr)
if self._infoIsSet('security'):
secinfo = self.info['security']
@@ -2072,18 +2054,8 @@ class XendDomainInfo:
return retval
def get_power_state(self):
return XEN_API_VM_POWER_STATE[self.state]
- def get_platform_std_vga(self):
- return self.info.get('platform_std_vga', False)
- def get_platform_serial(self):
- return self.info.get('platform_serial', '')
- def get_platform_localtime(self):
- return self.info.get('platform_localtime', False)
- def get_platform_clock_offset(self):
- return self.info.get('platform_clock_offset', False)
- def get_platform_enable_audio(self):
- return self.info.get('platform_enable_audio', False)
- def get_platform_keymap(self):
- return self.info.get('platform_keymap', '')
+ def get_platform(self):
+ return self.info.get('platform', {})
def get_pci_bus(self):
return self.info.get('pci_bus', '')
def get_tools_version(self):
diff -r d1853a39e063 -r cb2575cec95c tools/python/xen/xend/XendError.py
--- a/tools/python/xen/xend/XendError.py Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/python/xen/xend/XendError.py Mon Mar 12 10:07:08 2007 -0600
@@ -13,6 +13,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#============================================================================
# Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx>
+# Copyright (c) 2006, 2007 XenSource Inc.
#============================================================================
from xmlrpclib import Fault
@@ -55,6 +56,12 @@ class VmError(XendError):
"""Vm construction error."""
pass
+class HVMRequired(VmError):
+ def __init__(self):
+ XendError.__init__(self,
+ 'HVM guest support is unavailable: is VT/AMD-V '
+ 'supported by your CPU and enabled in your BIOS?')
+
XEND_ERROR_AUTHENTICATION_FAILED = ('ELUSER', 'Authentication Failed')
XEND_ERROR_SESSION_INVALID = ('EPERMDENIED', 'Session Invalid')
diff -r d1853a39e063 -r cb2575cec95c tools/python/xen/xend/XendNode.py
--- a/tools/python/xen/xend/XendNode.py Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/python/xen/xend/XendNode.py Mon Mar 12 10:07:08 2007 -0600
@@ -95,15 +95,12 @@ class XendNode:
self.cpus[u] = {'uuid': u, 'number': i }
for u in self.cpus.keys():
- log.error(self.cpus[u])
number = self.cpus[u]['number']
# We can run off the end of the cpuinfo list if domain0 does not
# have #vcpus == #pcpus. In that case we just replicate one that's
# in the hash table.
if not cpuinfo.has_key(number):
number = cpuinfo.keys()[0]
- log.error(number)
- log.error(cpuinfo)
if arch.type == "x86":
self.cpus[u].update(
{ 'host' : self.uuid,
@@ -453,6 +450,12 @@ class XendNode:
return pif.network
raise Exception('Bridge %s is not connected to a network' % bridge)
+ #
+ # Debug keys.
+ #
+
+ def send_debug_keys(self, keys):
+ return self.xc.send_debug_keys(keys)
#
# Getting host information.
diff -r d1853a39e063 -r cb2575cec95c tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/python/xen/xend/image.py Mon Mar 12 10:07:08 2007 -0600
@@ -13,7 +13,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#============================================================================
# Copyright (C) 2005 Mike Wray <mike.wray@xxxxxx>
-# Copyright (C) 2005 XenSource Ltd
+# Copyright (C) 2005-2007 XenSource Ltd
#============================================================================
@@ -24,7 +24,7 @@ import signal
import xen.lowlevel.xc
from xen.xend.XendConstants import REVERSE_DOMAIN_SHUTDOWN_REASONS
-from xen.xend.XendError import VmError, XendError
+from xen.xend.XendError import VmError, XendError, HVMRequired
from xen.xend.XendLogging import log
from xen.xend.XendOptions import instance as xenopts
from xen.xend.server.netif import randomMAC
@@ -36,13 +36,12 @@ MAX_GUEST_CMDLINE = 1024
MAX_GUEST_CMDLINE = 1024
-def create(vm, vmConfig, imageConfig, deviceConfig):
+def create(vm, vmConfig):
"""Create an image handler for a vm.
@return ImageHandler instance
"""
- return findImageHandlerClass(imageConfig)(vm, vmConfig, imageConfig,
- deviceConfig)
+ return findImageHandlerClass(vmConfig)(vm, vmConfig)
class ImageHandler:
@@ -65,7 +64,7 @@ class ImageHandler:
ostype = None
- def __init__(self, vm, vmConfig, imageConfig, deviceConfig):
+ def __init__(self, vm, vmConfig):
self.vm = vm
self.bootloader = False
@@ -73,9 +72,9 @@ class ImageHandler:
self.ramdisk = None
self.cmdline = None
- self.configure(vmConfig, imageConfig, deviceConfig)
-
- def configure(self, vmConfig, imageConfig, _):
+ self.configure(vmConfig)
+
+ def configure(self, vmConfig):
"""Config actions common to all unix-like domains."""
if '_temp_using_bootloader' in vmConfig:
self.bootloader = True
@@ -262,30 +261,29 @@ class HVMImageHandler(ImageHandler):
ostype = "hvm"
- def __init__(self, vm, vmConfig, imageConfig, deviceConfig):
- ImageHandler.__init__(self, vm, vmConfig, imageConfig, deviceConfig)
+ def __init__(self, vm, vmConfig):
+ ImageHandler.__init__(self, vm, vmConfig)
self.shutdownWatch = None
self.rebootFeatureWatch = None
- def configure(self, vmConfig, imageConfig, deviceConfig):
- ImageHandler.configure(self, vmConfig, imageConfig, deviceConfig)
+ def configure(self, vmConfig):
+ ImageHandler.configure(self, vmConfig)
if not self.kernel:
self.kernel = '/usr/lib/xen/boot/hvmloader'
info = xc.xeninfo()
if 'hvm' not in info['xen_caps']:
- raise VmError("HVM guest support is unavailable: is VT/AMD-V "
- "supported by your CPU and enabled in your BIOS?")
+ raise HVMRequired()
self.dmargs = self.parseDeviceModelArgs(vmConfig)
- self.device_model = imageConfig['hvm'].get('device_model')
+ self.device_model = vmConfig['platform'].get('device_model')
if not self.device_model:
raise VmError("hvm: missing device model")
- self.display = imageConfig['hvm'].get('display')
- self.xauthority = imageConfig['hvm'].get('xauthority')
- self.vncconsole = imageConfig['hvm'].get('vncconsole')
+ self.display = vmConfig['platform'].get('display')
+ self.xauthority = vmConfig['platform'].get('xauthority')
+ self.vncconsole = vmConfig['platform'].get('vncconsole')
self.vm.storeVm(("image/dmargs", " ".join(self.dmargs)),
("image/device-model", self.device_model),
@@ -293,9 +291,9 @@ class HVMImageHandler(ImageHandler):
self.pid = None
- self.pae = imageConfig['hvm'].get('pae', 0)
- self.apic = imageConfig['hvm'].get('apic', 0)
- self.acpi = imageConfig['hvm']['devices'].get('acpi', 0)
+ self.pae = int(vmConfig['platform'].get('pae', 0))
+ self.apic = int(vmConfig['platform'].get('apic', 0))
+ self.acpi = int(vmConfig['platform'].get('acpi', 0))
def buildDomain(self):
@@ -331,11 +329,10 @@ class HVMImageHandler(ImageHandler):
'localtime', 'serial', 'stdvga', 'isa',
'acpi', 'usb', 'usbdevice', 'keymap' ]
- hvmDeviceConfig = vmConfig['image']['hvm']['devices']
ret = ['-vcpus', str(self.vm.getVCpuCount())]
for a in dmargs:
- v = hvmDeviceConfig.get(a)
+ v = vmConfig['platform'].get(a)
# python doesn't allow '-' in variable names
if a == 'stdvga': a = 'std-vga'
@@ -395,14 +392,14 @@ class HVMImageHandler(ImageHandler):
# Find RFB console device, and if it exists, make QEMU enable
# the VNC console.
#
- if vmConfig['image'].get('nographic'):
+ if vmConfig['platform'].get('nographic'):
# skip vnc init if nographic is set
ret.append('-nographic')
return ret
vnc_config = {}
- has_vnc = int(vmConfig['image'].get('vnc', 0)) != 0
- has_sdl = int(vmConfig['image'].get('sdl', 0)) != 0
+ has_vnc = int(vmConfig['platform'].get('vnc', 0)) != 0
+ has_sdl = int(vmConfig['platform'].get('sdl', 0)) != 0
for dev_uuid in vmConfig['console_refs']:
dev_type, dev_info = vmConfig['devices'][dev_uuid]
if dev_type == 'vfb':
@@ -414,8 +411,8 @@ class HVMImageHandler(ImageHandler):
if not vnc_config:
for key in ('vncunused', 'vnclisten', 'vncdisplay',
'vncpasswd'):
- if key in vmConfig['image']:
- vnc_config[key] = vmConfig['image'][key]
+ if key in vmConfig['platform']:
+ vnc_config[key] = vmConfig['platform'][key]
if not vnc_config.get('vncunused', 0) and \
vnc_config.get('vncdisplay', 0):
@@ -634,9 +631,7 @@ def findImageHandlerClass(image):
@param image config
@return ImageHandler subclass or None
"""
- image_type = image['type']
- if image_type is None:
- raise VmError('missing image type')
+ image_type = image.image_type()
try:
return _handlers[arch.type][image_type]
except KeyError:
diff -r d1853a39e063 -r cb2575cec95c
tools/python/xen/xend/server/XMLRPCServer.py
--- a/tools/python/xen/xend/server/XMLRPCServer.py Mon Mar 12 09:43:48
2007 -0600
+++ b/tools/python/xen/xend/server/XMLRPCServer.py Mon Mar 12 10:07:08
2007 -0600
@@ -157,7 +157,7 @@ class XMLRPCServer:
self.server.register_function(fn, "xend.domain.%s" %
name[7:])
# Functions in XendNode and XendDmesg
- for type, lst, n in [(XendNode, ['info'], 'node'),
+ for type, lst, n in [(XendNode, ['info', 'send_debug_keys'], 'node'),
(XendDmesg, ['info', 'clear'], 'node.dmesg')]:
inst = type.instance()
for name in lst:
diff -r d1853a39e063 -r cb2575cec95c tools/python/xen/xm/XenAPI.py
--- a/tools/python/xen/xm/XenAPI.py Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/python/xen/xm/XenAPI.py Mon Mar 12 10:07:08 2007 -0600
@@ -155,7 +155,7 @@ class Session(xen.util.xmlrpclib2.Server
def _parse_result(result):
if type(result) != dict or 'Status' not in result:
- raise xmlrpclib.Fault(500, 'Missing Status in response from server')
+ raise xmlrpclib.Fault(500, 'Missing Status in response from server' +
result)
if result['Status'] == 'Success':
if 'Value' in result:
return result['Value']
diff -r d1853a39e063 -r cb2575cec95c tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/python/xen/xm/main.py Mon Mar 12 10:07:08 2007 -0600
@@ -25,6 +25,7 @@ import cmd
import cmd
import os
import pprint
+import readline
import shlex
import sys
import re
@@ -133,6 +134,7 @@ SUBCOMMAND_HELP = {
'sched-credit': ('[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]]',
'Get/set credit scheduler parameters.'),
'sysrq' : ('<Domain> <letter>', 'Send a sysrq to a domain.'),
+ 'debug-keys' : ('<Keys>', 'Send debug keys to Xen.'),
'trigger' : ('<Domain> <nmi|reset|init> [<VCPU>]',
'Send a trigger to a domain.'),
'vcpu-list' : ('[<Domain>]',
@@ -260,7 +262,6 @@ common_commands = [
"shutdown",
"start",
"suspend",
- "trigger",
"top",
"unpause",
"uptime",
@@ -300,6 +301,7 @@ domain_commands = [
]
host_commands = [
+ "debug-keys",
"dmesg",
"info",
"log",
@@ -557,6 +559,10 @@ class Shell(cmd.Cmd):
for f in res:
setattr(Shell, 'do_' + f, self.default)
+ def preloop(self):
+ cmd.Cmd.preloop(self)
+ readline.set_completer_delims(' ')
+
def default(self, line):
words = shlex.split(line)
if len(words) > 0 and words[0] == 'xm':
@@ -576,9 +582,9 @@ class Shell(cmd.Cmd):
return False
def completedefault(self, text, line, begidx, endidx):
- cmd = line.split(' ')[0]
- clas, func = cmd.split('.')
- if begidx != len(cmd) + 1 or \
+ words = shlex.split(line[:begidx])
+ clas, func = words[0].split('.')
+ if len(words) > 1 or \
func.startswith('get_by_') or \
func == 'get_all':
return []
@@ -1394,6 +1400,10 @@ def xm_trigger(args):
vcpu = int(args[2])
server.xend.domain.send_trigger(dom, trigger, vcpu)
+
+def xm_debug_keys(args):
+ arg_check(args, "debug-keys", 1)
+ server.xend.node.send_debug_keys(str(args[0]))
def xm_top(args):
arg_check(args, "top", 0)
@@ -1738,6 +1748,7 @@ commands = {
"pause": xm_pause,
"unpause": xm_unpause,
# host commands
+ "debug-keys": xm_debug_keys,
"dmesg": xm_dmesg,
"info": xm_info,
"log": xm_log,
@@ -1881,7 +1892,7 @@ def _run_cmd(cmd, cmd_name, args):
err("Domain '%s' does not exist." % ex.faultString)
else:
err(ex.faultString)
- _usage(cmd_name)
+ _usage(cmd_name)
except xmlrpclib.ProtocolError, ex:
if ex.errcode == -1:
print >>sys.stderr, (
diff -r d1853a39e063 -r cb2575cec95c tools/python/xen/xm/messages/en/xen-xm.po
--- a/tools/python/xen/xm/messages/en/xen-xm.po Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/python/xen/xm/messages/en/xen-xm.po Mon Mar 12 10:07:08 2007 -0600
@@ -19,7 +19,7 @@ msgid ""
msgid ""
msgstr ""
"Project-Id-Version: Xen-xm 3.0\n"
-"PO-Revision-Date: 2007-02-20 15:22+0000\n"
+"PO-Revision-Date: 2007-03-10 23:17+0000\n"
"Last-Translator: Ewan Mellor <ewan@xxxxxxxxxxxxx>\n"
"Language-Team: xen-devel <xen-devel@xxxxxxxxxxxxxxxxxxx>\n"
"MIME-Version: 1.0\n"
@@ -61,3 +61,6 @@ msgstr "The VLAN tag you gave (%(1)s) is
msgid "VM_BAD_POWER_STATE"
msgstr "The VM must be %(2)s to perform the requested operation (it is
currently %(3)s)."
+
+msgid "VM_HVM_REQUIRED"
+msgstr "HVM guest support is unavailable: is VT/AMD-V supported by your CPU
and enabled in your BIOS?"
diff -r d1853a39e063 -r cb2575cec95c tools/xm-test/tests/vtpm/09_vtpm-xapi.py
--- a/tools/xm-test/tests/vtpm/09_vtpm-xapi.py Mon Mar 12 09:43:48 2007 -0600
+++ b/tools/xm-test/tests/vtpm/09_vtpm-xapi.py Mon Mar 12 10:07:08 2007 -0600
@@ -113,7 +113,7 @@ if not re.search("PCR-00:",run["output"]
FAIL("1. Virtual TPM is not working correctly on /dev/vtpm on backend
side: \n%s" % run["output"])
try:
- rc = session.xenapi.VTPM.destroy(vtpm_uuid)
+ session.xenapi.VTPM.destroy(vtpm_uuid)
#Should never get here
FAIL("Could destroy vTPM while VM is running")
except:
@@ -124,7 +124,7 @@ if rc:
FAIL("Could not suspend VM")
try:
- rc = session.xenapi.VTPM.destroy(vtpm_uuid)
+ session.xenapi.VTPM.destroy(vtpm_uuid)
#May not throw an exception in 'suspend' state
except:
pass
@@ -150,8 +150,9 @@ if not re.search("PCR-00:",run["output"]
domain.stop()
-rc = session.xenapi.VTPM.destroy(vtpm_uuid)
-if not rc:
+try:
+ session.xenapi.VTPM.destroy(vtpm_uuid)
+except:
FAIL("Could NOT destroy vTPM while domain is halted.")
domain.destroy()
diff -r d1853a39e063 -r cb2575cec95c xen/arch/ia64/xen/xensetup.c
--- a/xen/arch/ia64/xen/xensetup.c Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/ia64/xen/xensetup.c Mon Mar 12 10:07:08 2007 -0600
@@ -543,8 +543,6 @@ printk("num_online_cpus=%d, max_cpus=%d\
domain0_ready = 1;
- schedulers_start();
-
domain_unpause_by_systemcontroller(dom0);
startup_cpu_idle_loop();
diff -r d1853a39e063 -r cb2575cec95c xen/arch/powerpc/domain.c
--- a/xen/arch/powerpc/domain.c Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/powerpc/domain.c Mon Mar 12 10:07:08 2007 -0600
@@ -142,6 +142,8 @@ void free_vcpu_struct(struct vcpu *v)
int vcpu_initialise(struct vcpu *v)
{
+ /* Guests by default have a 100Hz ticker. */
+ v->periodic_period = MILLISECS(10);
return 0;
}
diff -r d1853a39e063 -r cb2575cec95c xen/arch/powerpc/setup.c
--- a/xen/arch/powerpc/setup.c Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/powerpc/setup.c Mon Mar 12 10:07:08 2007 -0600
@@ -365,9 +365,6 @@ static void __init __start_xen(multiboot
kick_secondary_cpus(max_cpus);
}
- /* Secondary processors must be online before we call this. */
- schedulers_start();
-
/* This cannot be called before secondary cpus are marked online. */
percpu_free_unused_areas();
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/apic.c
--- a/xen/arch/x86/apic.c Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/x86/apic.c Mon Mar 12 10:07:08 2007 -0600
@@ -1023,6 +1023,13 @@ int reprogram_timer(s_time_t timeout)
u64 apic_tmict;
/*
+ * If we don't have local APIC then we just poll the timer list off the
+ * PIT interrupt.
+ */
+ if ( !cpu_has_apic )
+ return 1;
+
+ /*
* We use this value because we don't trust zero (we think it may just
* cause an immediate interrupt). At least this is guaranteed to hold it
* off for ages (esp. since the clock ticks on bus clock, not cpu clock!).
@@ -1043,13 +1050,6 @@ int reprogram_timer(s_time_t timeout)
(u32)now, (u32)(timeout>>32),(u32)timeout);
return 0;
}
-
- /*
- * If we don't have local APIC then we just poll the timer list off the
- * PIT interrupt. Cheesy but good enough to work on eg. VMware :-)
- */
- if ( !cpu_has_apic )
- return 1;
/* conversion to bus units */
apic_tmict = (((u64)bus_scale) * expire)>>18;
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/x86/domain.c Mon Mar 12 10:07:08 2007 -0600
@@ -350,6 +350,9 @@ int vcpu_initialise(struct vcpu *v)
}
else
{
+ /* PV guests by default have a 100Hz ticker. */
+ v->periodic_period = MILLISECS(10);
+
/* PV guests get an emulated PIT too for video BIOSes to use. */
if ( !is_idle_domain(d) && (v->vcpu_id == 0) )
pit_init(v, cpu_khz);
@@ -457,8 +460,10 @@ int arch_domain_create(struct domain *d)
fail:
free_xenheap_page(d->shared_info);
#ifdef __x86_64__
- free_domheap_page(virt_to_page(d->arch.mm_perdomain_l2));
- free_domheap_page(virt_to_page(d->arch.mm_perdomain_l3));
+ if ( d->arch.mm_perdomain_l2 )
+ free_domheap_page(virt_to_page(d->arch.mm_perdomain_l2));
+ if ( d->arch.mm_perdomain_l3 )
+ free_domheap_page(virt_to_page(d->arch.mm_perdomain_l3));
#endif
free_xenheap_pages(d->arch.mm_perdomain_pt, pdpt_order);
return rc;
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/domctl.c
--- a/xen/arch/x86/domctl.c Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/x86/domctl.c Mon Mar 12 10:07:08 2007 -0600
@@ -145,6 +145,12 @@ long arch_do_domctl(
}
arr32 = alloc_xenheap_page();
+ if ( !arr32 )
+ {
+ ret = -ENOMEM;
+ put_domain(d);
+ break;
+ }
ret = 0;
for ( n = 0; n < num; )
@@ -157,7 +163,7 @@ long arch_do_domctl(
domctl->u.getpageframeinfo2.array,
n, k) )
{
- ret = -EINVAL;
+ ret = -EFAULT;
break;
}
@@ -201,7 +207,7 @@ long arch_do_domctl(
if ( copy_to_guest_offset(domctl->u.getpageframeinfo2.array,
n, arr32, k) )
{
- ret = -EINVAL;
+ ret = -EFAULT;
break;
}
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/x86/hvm/hvm.c Mon Mar 12 10:07:08 2007 -0600
@@ -146,6 +146,48 @@ void hvm_do_resume(struct vcpu *v)
}
}
+/* Called from the tools when saving a domain to make sure the io
+ * request-response ring is entirely empty. */
+static int hvmop_drain_io(
+ XEN_GUEST_HANDLE(xen_hvm_drain_io_t) uop)
+{
+ struct xen_hvm_drain_io op;
+ struct domain *d;
+ struct vcpu *v;
+ ioreq_t *p;
+ int rc;
+
+ if ( copy_from_guest(&op, uop, 1) )
+ return -EFAULT;
+
+ if ( !IS_PRIV(current->domain) )
+ return -EPERM;
+
+ d = rcu_lock_domain_by_id(op.domid);
+ if ( d == NULL )
+ return -ESRCH;
+
+ rc = -EINVAL;
+ /* Can't do this to yourself, or to a domain without an ioreq ring */
+ if ( d == current->domain || !is_hvm_domain(d) || get_sp(d) == NULL )
+ goto out;
+
+ rc = 0;
+
+ domain_pause(d); /* It's not safe to do this to running vcpus */
+ for_each_vcpu(d, v)
+ {
+ p = &get_vio(v->domain, v->vcpu_id)->vp_ioreq;
+ if ( p->state == STATE_IORESP_READY )
+ hvm_io_assist(v);
+ }
+ domain_unpause(d);
+
+ out:
+ rcu_unlock_domain(d);
+ return rc;
+}
+
int hvm_domain_initialise(struct domain *d)
{
int rc;
@@ -161,7 +203,8 @@ int hvm_domain_initialise(struct domain
spin_lock_init(&d->arch.hvm_domain.buffered_io_lock);
spin_lock_init(&d->arch.hvm_domain.irq_lock);
- rc = paging_enable(d, PG_SH_enable|PG_refcounts|PG_translate|PG_external);
+ /* paging support will be determined inside paging.c */
+ rc = paging_enable(d, PG_refcounts|PG_translate|PG_external);
if ( rc != 0 )
return rc;
@@ -379,7 +422,7 @@ void hvm_triple_fault(void)
*/
static int __hvm_copy(void *buf, paddr_t addr, int size, int dir, int virt)
{
- unsigned long mfn;
+ unsigned long gfn, mfn;
char *p;
int count, todo;
@@ -389,9 +432,11 @@ static int __hvm_copy(void *buf, paddr_t
count = min_t(int, PAGE_SIZE - (addr & ~PAGE_MASK), todo);
if ( virt )
- mfn = get_mfn_from_gpfn(paging_gva_to_gfn(current, addr));
+ gfn = paging_gva_to_gfn(current, addr);
else
- mfn = get_mfn_from_gpfn(addr >> PAGE_SHIFT);
+ gfn = addr >> PAGE_SHIFT;
+
+ mfn = get_mfn_from_gpfn(gfn);
if ( mfn == INVALID_MFN )
return todo;
@@ -399,14 +444,15 @@ static int __hvm_copy(void *buf, paddr_t
p = (char *)map_domain_page(mfn) + (addr & ~PAGE_MASK);
if ( dir )
+ {
memcpy(p, buf, count); /* dir == TRUE: *to* guest */
+ mark_dirty(current->domain, mfn);
+ }
else
memcpy(buf, p, count); /* dir == FALSE: *from guest */
unmap_domain_page(p);
- mark_dirty(current->domain, mfn);
-
addr += count;
buf += count;
todo -= count;
@@ -912,6 +958,12 @@ long do_hvm_op(unsigned long op, XEN_GUE
guest_handle_cast(arg, xen_hvm_set_pci_link_route_t));
break;
+ case HVMOP_drain_io:
+ rc = hvmop_drain_io(
+ guest_handle_cast(arg, xen_hvm_drain_io_t));
+ break;
+
+
default:
{
gdprintk(XENLOG_WARNING, "Bad HVM op %ld.\n", op);
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/hvm/rtc.c
--- a/xen/arch/x86/hvm/rtc.c Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/x86/hvm/rtc.c Mon Mar 12 10:07:08 2007 -0600
@@ -174,6 +174,11 @@ static void rtc_copy_date(RTCState *s)
{
const struct tm *tm = &s->current_tm;
+ if (s->time_offset_seconds != s->pt.vcpu->domain->time_offset_seconds) {
+ s->current_tm = gmtime(get_localtime(s->pt.vcpu->domain));
+ s->time_offset_seconds = s->pt.vcpu->domain->time_offset_seconds;
+ }
+
s->hw.cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec);
s->hw.cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min);
if ( s->hw.cmos_data[RTC_REG_B] & RTC_24H )
@@ -211,9 +216,15 @@ static int get_days_in_month(int month,
}
/* update 'tm' to the next second */
-static void rtc_next_second(struct tm *tm)
-{
+static void rtc_next_second(RTCState *s)
+{
+ struct tm *tm = &s->current_tm;
int days_in_month;
+
+ if (s->time_offset_seconds != s->pt.vcpu->domain->time_offset_seconds) {
+ s->current_tm = gmtime(get_localtime(s->pt.vcpu->domain));
+ s->time_offset_seconds = s->pt.vcpu->domain->time_offset_seconds;
+ }
tm->tm_sec++;
if ((unsigned)tm->tm_sec >= 60) {
@@ -258,7 +269,7 @@ static void rtc_update_second(void *opaq
}
else
{
- rtc_next_second(&s->current_tm);
+ rtc_next_second(s);
if ( !(s->hw.cmos_data[RTC_REG_B] & RTC_SET) )
s->hw.cmos_data[RTC_REG_A] |= RTC_UIP;
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/x86/hvm/svm/svm.c Mon Mar 12 10:07:08 2007 -0600
@@ -49,6 +49,7 @@
#include <public/sched.h>
#include <asm/hvm/vpt.h>
#include <asm/hvm/trace.h>
+#include <asm/hap.h>
#define SVM_EXTRA_DEBUG
@@ -76,6 +77,10 @@ static void *root_vmcb[NR_CPUS] __read_m
/* physical address of above for host VMSAVE/VMLOAD */
u64 root_vmcb_pa[NR_CPUS] __read_mostly;
+/* hardware assisted paging bits */
+extern int opt_hap_enabled;
+extern int hap_capable_system;
+
static inline void svm_inject_exception(struct vcpu *v, int trap,
int ev, int error_code)
{
@@ -102,22 +107,10 @@ static void stop_svm(void)
static void stop_svm(void)
{
u32 eax, edx;
- int cpu = smp_processor_id();
-
/* We turn off the EFER_SVME bit. */
rdmsr(MSR_EFER, eax, edx);
eax &= ~EFER_SVME;
wrmsr(MSR_EFER, eax, edx);
-
- /* release the HSA */
- free_host_save_area(hsa[cpu]);
- hsa[cpu] = NULL;
- wrmsr(MSR_K8_VM_HSAVE_PA, 0, 0 );
-
- /* free up the root vmcb */
- free_vmcb(root_vmcb[cpu]);
- root_vmcb[cpu] = NULL;
- root_vmcb_pa[cpu] = 0;
}
static void svm_store_cpu_guest_regs(
@@ -240,7 +233,9 @@ static inline int long_mode_do_msr_write
/*
* Check for EFER.LME transitions from 0->1 or 1->0. Do the
* sanity checks and then make sure that both EFER.LME and
- * EFER.LMA are cleared.
+ * EFER.LMA are cleared. (EFER.LME can't be set in the vmcb
+ * until the guest also sets CR0.PG, since even if the guest has
+ * paging "disabled", the vmcb's CR0 always has PG set.)
*/
if ( (msr_content & EFER_LME) && !svm_lme_is_set(v) )
{
@@ -269,10 +264,12 @@ static inline int long_mode_do_msr_write
vmcb->efer &= ~(EFER_LME | EFER_LMA);
}
+
#endif /* __x86_64__ */
/* update the guest EFER's shadow with the intended value */
v->arch.hvm_svm.cpu_shadow_efer = msr_content;
+
break;
#ifdef __x86_64__
@@ -902,6 +899,10 @@ static void arch_svm_do_launch(struct vc
{
svm_do_launch(v);
+ if ( paging_mode_hap(v->domain) ) {
+ v->arch.hvm_svm.vmcb->h_cr3 =
pagetable_get_paddr(v->domain->arch.phys_table);
+ }
+
if ( v->vcpu_id != 0 )
{
cpu_user_regs_t *regs = ¤t->arch.guest_context.user_regs;
@@ -1008,6 +1009,21 @@ static struct hvm_function_table svm_fun
.event_injection_faulted = svm_event_injection_faulted
};
+void svm_npt_detect(void)
+{
+ u32 eax, ebx, ecx, edx;
+
+ /* check CPUID for nested paging support */
+ cpuid(0x8000000A, &eax, &ebx, &ecx, &edx);
+ if ( edx & 0x01 ) { /* nested paging */
+ hap_capable_system = 1;
+ }
+ else if ( opt_hap_enabled ) {
+ printk(" nested paging is not supported by this CPU.\n");
+ hap_capable_system = 0; /* no nested paging, we disable flag. */
+ }
+}
+
int start_svm(void)
{
u32 eax, ecx, edx;
@@ -1030,13 +1046,16 @@ int start_svm(void)
return 0;
}
- if (!(hsa[cpu] = alloc_host_save_area()))
- return 0;
+ if (!hsa[cpu])
+ if (!(hsa[cpu] = alloc_host_save_area()))
+ return 0;
rdmsr(MSR_EFER, eax, edx);
eax |= EFER_SVME;
wrmsr(MSR_EFER, eax, edx);
printk("AMD SVM Extension is enabled for cpu %d.\n", cpu );
+
+ svm_npt_detect();
/* Initialize the HSA for this core */
phys_hsa = (u64) virt_to_maddr(hsa[cpu]);
@@ -1044,8 +1063,9 @@ int start_svm(void)
phys_hsa_hi = (u32) (phys_hsa >> 32);
wrmsr(MSR_K8_VM_HSAVE_PA, phys_hsa_lo, phys_hsa_hi);
- if (!(root_vmcb[cpu] = alloc_vmcb()))
- return 0;
+ if (!root_vmcb[cpu])
+ if (!(root_vmcb[cpu] = alloc_vmcb()))
+ return 0;
root_vmcb_pa[cpu] = virt_to_maddr(root_vmcb[cpu]);
if (cpu == 0)
@@ -1073,6 +1093,18 @@ void arch_svm_do_resume(struct vcpu *v)
reset_stack_and_jump( svm_asm_do_resume );
}
}
+
+static int svm_do_nested_pgfault(paddr_t gpa, struct cpu_user_regs *regs)
+{
+ if (mmio_space(gpa)) {
+ handle_mmio(gpa);
+ return 1;
+ }
+
+ /* We should not reach here. Otherwise, P2M table is not correct.*/
+ return 0;
+}
+
static int svm_do_page_fault(unsigned long va, struct cpu_user_regs *regs)
{
@@ -1700,6 +1732,52 @@ static void svm_io_instruction(struct vc
}
}
+static int npt_set_cr0(unsigned long value)
+{
+ struct vcpu *v = current;
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+
+ ASSERT(vmcb);
+
+ /* ET is reserved and should be always be 1*/
+ value |= X86_CR0_ET;
+
+ /* Check whether the guest is about to turn on long mode.
+ * If it is, set EFER.LME and EFER.LMA. Update the shadow EFER.LMA
+ * bit too, so svm_long_mode_enabled() will work.
+ */
+ if ( (value & X86_CR0_PG) && svm_lme_is_set(v) &&
+ (vmcb->cr4 & X86_CR4_PAE) && (vmcb->cr0 & X86_CR0_PE) )
+ {
+ v->arch.hvm_svm.cpu_shadow_efer |= EFER_LMA;
+ vmcb->efer |= EFER_LMA | EFER_LME;
+ }
+
+ /* Whenever CR0.PG is cleared under long mode, LMA will be cleared
+ * immediatly. We emulate this process for svm_long_mode_enabled().
+ */
+ if ( (value & (X86_CR0_PE | X86_CR0_PG)) == X86_CR0_PE )
+ {
+ if ( svm_long_mode_enabled(v) )
+ {
+ v->arch.hvm_svm.cpu_shadow_efer &= ~EFER_LMA;
+ }
+ }
+
+ vmcb->cr0 = value | X86_CR0_WP;
+ v->arch.hvm_svm.cpu_shadow_cr0 = value;
+
+ /* TS cleared? Then initialise FPU now. */
+ if ( !(value & X86_CR0_TS) ) {
+ setup_fpu(v);
+ vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM;
+ }
+
+ paging_update_paging_modes(v);
+
+ return 1;
+}
+
static int svm_set_cr0(unsigned long value)
{
struct vcpu *v = current;
@@ -1795,6 +1873,85 @@ static int svm_set_cr0(unsigned long val
}
return 1;
+}
+
+//
+// nested paging functions
+//
+
+static int npt_mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
+{
+ unsigned long value;
+ struct vcpu *v = current;
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+ struct vlapic *vlapic = vcpu_vlapic(v);
+
+ ASSERT(vmcb);
+
+ value = get_reg(gpreg, regs, vmcb);
+
+ switch (cr) {
+ case 0:
+ return npt_set_cr0(value);
+
+ case 3:
+ vmcb->cr3 = value;
+ v->arch.hvm_svm.cpu_cr3 = value;
+ break;
+
+ case 4: /* CR4 */
+ vmcb->cr4 = value;
+ v->arch.hvm_svm.cpu_shadow_cr4 = value;
+ paging_update_paging_modes(v);
+ break;
+
+ case 8:
+ vlapic_set_reg(vlapic, APIC_TASKPRI, ((value & 0x0F) << 4));
+ vmcb->vintr.fields.tpr = value & 0x0F;
+ break;
+
+ default:
+ gdprintk(XENLOG_ERR, "invalid cr: %d\n", cr);
+ domain_crash(v->domain);
+ return 0;
+ }
+
+ return 1;
+}
+
+static void npt_mov_from_cr(int cr, int gp, struct cpu_user_regs *regs)
+{
+ unsigned long value = 0;
+ struct vcpu *v = current;
+ struct vmcb_struct *vmcb;
+ struct vlapic *vlapic = vcpu_vlapic(v);
+
+ vmcb = v->arch.hvm_svm.vmcb;
+ ASSERT(vmcb);
+
+ switch(cr) {
+ case 0:
+ value = (unsigned long) v->arch.hvm_svm.cpu_shadow_cr0;
+ break;
+ case 2:
+ value = vmcb->cr2;
+ break;
+ case 3:
+ value = (unsigned long) v->arch.hvm_svm.cpu_cr3;
+ break;
+ case 4:
+ value = (unsigned long) v->arch.hvm_svm.cpu_shadow_cr4;
+ break;
+ case 8:
+ value = (unsigned long)vlapic_get_reg(vlapic, APIC_TASKPRI);
+ value = (value & 0xF0) >> 4;
+ break;
+ default:
+ domain_crash(v->domain);
+ return;
+ }
+
+ set_reg(gp, value, regs, vmcb);
}
/*
@@ -2043,12 +2200,18 @@ static int svm_cr_access(struct vcpu *v,
{
case INSTR_MOV2CR:
gpreg = decode_src_reg(prefix, buffer[index+2]);
- result = mov_to_cr(gpreg, cr, regs);
+ if ( paging_mode_hap(v->domain) )
+ result = npt_mov_to_cr(gpreg, cr, regs);
+ else
+ result = mov_to_cr(gpreg, cr, regs);
break;
case INSTR_MOVCR2:
gpreg = decode_src_reg(prefix, buffer[index+2]);
- mov_from_cr(cr, gpreg, regs);
+ if ( paging_mode_hap(v->domain) )
+ npt_mov_from_cr(cr, gpreg, regs);
+ else
+ mov_from_cr(cr, gpreg, regs);
break;
case INSTR_CLTS:
@@ -2075,7 +2238,10 @@ static int svm_cr_access(struct vcpu *v,
if (svm_dbg_on)
printk("CR0-LMSW CR0 - New value=%lx\n", value);
- result = svm_set_cr0(value);
+ if ( paging_mode_hap(v->domain) )
+ result = npt_set_cr0(value);
+ else
+ result = svm_set_cr0(value);
break;
case INSTR_SMSW:
@@ -2358,6 +2524,11 @@ static int svm_do_vmmcall_reset_to_realm
vmcb->cr4 = SVM_CR4_HOST_MASK;
v->arch.hvm_svm.cpu_shadow_cr4 = 0;
+
+ if ( paging_mode_hap(v->domain) ) {
+ vmcb->cr0 = v->arch.hvm_svm.cpu_shadow_cr0;
+ vmcb->cr4 = v->arch.hvm_svm.cpu_shadow_cr4;
+ }
/* This will jump to ROMBIOS */
vmcb->rip = 0xFFF0;
@@ -3042,6 +3213,15 @@ asmlinkage void svm_vmexit_handler(struc
hvm_triple_fault();
break;
+ case VMEXIT_NPF:
+ {
+ regs->error_code = vmcb->exitinfo1;
+ if ( !svm_do_nested_pgfault(vmcb->exitinfo2, regs) ) {
+ domain_crash(v->domain);
+ }
+ break;
+ }
+
default:
exit_and_crash:
gdprintk(XENLOG_ERR, "unexpected VMEXIT: exit reason = 0x%x, "
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/hvm/svm/vmcb.c
--- a/xen/arch/x86/hvm/svm/vmcb.c Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/x86/hvm/svm/vmcb.c Mon Mar 12 10:07:08 2007 -0600
@@ -79,11 +79,6 @@ struct host_save_area *alloc_host_save_a
return hsa;
}
-void free_host_save_area(struct host_save_area *hsa)
-{
- free_xenheap_page(hsa);
-}
-
static int construct_vmcb(struct vcpu *v)
{
struct arch_svm_struct *arch_svm = &v->arch.hvm_svm;
@@ -200,6 +195,13 @@ static int construct_vmcb(struct vcpu *v
vmcb->cr3 = v->arch.hvm_vcpu.hw_cr3;
arch_svm->vmcb->exception_intercepts = MONITOR_DEFAULT_EXCEPTION_BITMAP;
+
+ if ( paging_mode_hap(v->domain) ) {
+ vmcb->cr0 = arch_svm->cpu_shadow_cr0;
+ vmcb->np_enable = 1; /* enable nested paging */
+ vmcb->g_pat = 0x0007040600070406ULL; /* guest PAT */
+ vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_PG;
+ }
return 0;
}
@@ -310,7 +312,8 @@ void svm_dump_vmcb(const char *from, str
printk("KernGSBase = 0x%016llx PAT = 0x%016llx \n",
(unsigned long long) vmcb->kerngsbase,
(unsigned long long) vmcb->g_pat);
-
+ printk("H_CR3 = 0x%016llx\n", (unsigned long long)vmcb->h_cr3);
+
/* print out all the selectors */
svm_dump_sel("CS", &vmcb->cs);
svm_dump_sel("DS", &vmcb->ds);
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/mm/Makefile
--- a/xen/arch/x86/mm/Makefile Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/x86/mm/Makefile Mon Mar 12 10:07:08 2007 -0600
@@ -1,4 +1,5 @@ subdir-y += shadow
subdir-y += shadow
+subdir-y += hap
obj-y += paging.o
obj-y += p2m.o
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/mm/hap/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/mm/hap/Makefile Mon Mar 12 10:07:08 2007 -0600
@@ -0,0 +1,2 @@
+obj-y += hap.o
+obj-y += support.o
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/mm/hap/hap.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/mm/hap/hap.c Mon Mar 12 10:07:08 2007 -0600
@@ -0,0 +1,708 @@
+/******************************************************************************
+ * arch/x86/mm/hap/hap.c
+ *
+ * hardware assisted paging
+ * Copyright (c) 2007 Advanced Micro Devices (Wei Huang)
+ * Parts of this code are Copyright (c) 2007 by XenSource Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/mm.h>
+#include <xen/trace.h>
+#include <xen/sched.h>
+#include <xen/perfc.h>
+#include <xen/irq.h>
+#include <xen/domain_page.h>
+#include <xen/guest_access.h>
+#include <xen/keyhandler.h>
+#include <asm/event.h>
+#include <asm/page.h>
+#include <asm/current.h>
+#include <asm/flushtlb.h>
+#include <asm/shared.h>
+#include <asm/hap.h>
+#include <asm/paging.h>
+#include <asm/domain.h>
+
+#include "private.h"
+
+/* Override macros from asm/page.h to make them work with mfn_t */
+#undef mfn_to_page
+#define mfn_to_page(_m) (frame_table + mfn_x(_m))
+#undef mfn_valid
+#define mfn_valid(_mfn) (mfn_x(_mfn) < max_page)
+#undef page_to_mfn
+#define page_to_mfn(_pg) (_mfn((_pg) - frame_table))
+
+/************************************************/
+/* HAP SUPPORT FUNCTIONS */
+/************************************************/
+mfn_t hap_alloc(struct domain *d, unsigned long backpointer)
+{
+ struct page_info *sp = NULL;
+ void *p;
+
+ ASSERT(hap_locked_by_me(d));
+
+ sp = list_entry(d->arch.paging.hap.freelists.next, struct page_info, list);
+ list_del(&sp->list);
+ d->arch.paging.hap.free_pages -= 1;
+
+ /* Now safe to clear the page for reuse */
+ p = hap_map_domain_page(page_to_mfn(sp));
+ ASSERT(p != NULL);
+ clear_page(p);
+ hap_unmap_domain_page(p);
+
+ return page_to_mfn(sp);
+}
+
+void hap_free(struct domain *d, mfn_t smfn)
+{
+ struct page_info *sp = mfn_to_page(smfn);
+
+ ASSERT(hap_locked_by_me(d));
+
+ d->arch.paging.hap.free_pages += 1;
+ list_add_tail(&sp->list, &d->arch.paging.hap.freelists);
+}
+
+static int hap_alloc_p2m_pages(struct domain *d)
+{
+ struct page_info *pg;
+
+ ASSERT(hap_locked_by_me(d));
+
+ pg = mfn_to_page(hap_alloc(d, 0));
+ d->arch.paging.hap.p2m_pages += 1;
+ d->arch.paging.hap.total_pages -= 1;
+
+ page_set_owner(pg, d);
+ pg->count_info = 1;
+ list_add_tail(&pg->list, &d->arch.paging.hap.p2m_freelist);
+
+ return 1;
+}
+
+struct page_info * hap_alloc_p2m_page(struct domain *d)
+{
+ struct list_head *entry;
+ struct page_info *pg;
+ mfn_t mfn;
+ void *p;
+
+ hap_lock(d);
+
+ if ( list_empty(&d->arch.paging.hap.p2m_freelist) &&
+ !hap_alloc_p2m_pages(d) ) {
+ hap_unlock(d);
+ return NULL;
+ }
+ entry = d->arch.paging.hap.p2m_freelist.next;
+ list_del(entry);
+
+ hap_unlock(d);
+
+ pg = list_entry(entry, struct page_info, list);
+ mfn = page_to_mfn(pg);
+ p = hap_map_domain_page(mfn);
+ clear_page(p);
+ hap_unmap_domain_page(p);
+
+ return pg;
+}
+
+void hap_free_p2m_page(struct domain *d, struct page_info *pg)
+{
+ ASSERT(page_get_owner(pg) == d);
+ /* Should have just the one ref we gave it in alloc_p2m_page() */
+ if ( (pg->count_info & PGC_count_mask) != 1 ) {
+ HAP_ERROR("Odd p2m page count c=%#x t=%"PRtype_info"\n",
+ pg->count_info, pg->u.inuse.type_info);
+ }
+ /* Free should not decrement domain's total allocation, since
+ * these pages were allocated without an owner. */
+ page_set_owner(pg, NULL);
+ free_domheap_pages(pg, 0);
+ d->arch.paging.hap.p2m_pages--;
+}
+
+/* Return the size of the pool, rounded up to the nearest MB */
+static unsigned int
+hap_get_allocation(struct domain *d)
+{
+ unsigned int pg = d->arch.paging.hap.total_pages;
+
+ HERE_I_AM;
+ return ((pg >> (20 - PAGE_SHIFT))
+ + ((pg & ((1 << (20 - PAGE_SHIFT)) - 1)) ? 1 : 0));
+}
+
+/* Set the pool of pages to the required number of pages.
+ * Returns 0 for success, non-zero for failure. */
+static unsigned int
+hap_set_allocation(struct domain *d, unsigned int pages, int *preempted)
+{
+ struct page_info *sp;
+
+ ASSERT(hap_locked_by_me(d));
+
+ while ( d->arch.paging.hap.total_pages != pages ) {
+ if ( d->arch.paging.hap.total_pages < pages ) {
+ /* Need to allocate more memory from domheap */
+ sp = alloc_domheap_pages(NULL, 0, 0);
+ if ( sp == NULL ) {
+ HAP_PRINTK("failed to allocate hap pages.\n");
+ return -ENOMEM;
+ }
+ d->arch.paging.hap.free_pages += 1;
+ d->arch.paging.hap.total_pages += 1;
+ list_add_tail(&sp->list, &d->arch.paging.hap.freelists);
+ }
+ else if ( d->arch.paging.hap.total_pages > pages ) {
+ /* Need to return memory to domheap */
+ ASSERT(!list_empty(&d->arch.paging.hap.freelists));
+ sp = list_entry(d->arch.paging.hap.freelists.next,
+ struct page_info, list);
+ list_del(&sp->list);
+ d->arch.paging.hap.free_pages -= 1;
+ d->arch.paging.hap.total_pages -= 1;
+ free_domheap_pages(sp, 0);
+ }
+
+ /* Check to see if we need to yield and try again */
+ if ( preempted && hypercall_preempt_check() ) {
+ *preempted = 1;
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+#if CONFIG_PAGING_LEVELS == 4
+void hap_install_xen_entries_in_l4(struct vcpu *v, mfn_t gl4mfn, mfn_t sl4mfn)
+{
+ struct domain *d = v->domain;
+ l4_pgentry_t *sl4e;
+
+ sl4e = hap_map_domain_page(sl4mfn);
+ ASSERT(sl4e != NULL);
+
+ /* Copy the common Xen mappings from the idle domain */
+ memcpy(&sl4e[ROOT_PAGETABLE_FIRST_XEN_SLOT],
+ &idle_pg_table[ROOT_PAGETABLE_FIRST_XEN_SLOT],
+ ROOT_PAGETABLE_XEN_SLOTS * sizeof(l4_pgentry_t));
+
+ /* Install the per-domain mappings for this domain */
+ sl4e[l4_table_offset(PERDOMAIN_VIRT_START)] =
+ l4e_from_pfn(mfn_x(page_to_mfn(virt_to_page(d->arch.mm_perdomain_l3))),
+ __PAGE_HYPERVISOR);
+
+ sl4e[l4_table_offset(LINEAR_PT_VIRT_START)] =
+ l4e_from_pfn(mfn_x(gl4mfn), __PAGE_HYPERVISOR);
+
+ /* install domain-specific P2M table */
+ sl4e[l4_table_offset(RO_MPT_VIRT_START)] =
+ l4e_from_pfn(mfn_x(pagetable_get_mfn(d->arch.phys_table)),
+ __PAGE_HYPERVISOR);
+
+ hap_unmap_domain_page(sl4e);
+}
+#endif /* CONFIG_PAGING_LEVELS == 4 */
+
+#if CONFIG_PAGING_LEVELS == 3
+void hap_install_xen_entries_in_l2h(struct vcpu *v, mfn_t sl2hmfn)
+{
+ struct domain *d = v->domain;
+ l2_pgentry_t *sl2e;
+
+ int i;
+
+ sl2e = hap_map_domain_page(sl2hmfn);
+ ASSERT(sl2e != NULL);
+
+ /* Copy the common Xen mappings from the idle domain */
+ memcpy(&sl2e[L2_PAGETABLE_FIRST_XEN_SLOT & (L2_PAGETABLE_ENTRIES-1)],
+ &idle_pg_table_l2[L2_PAGETABLE_FIRST_XEN_SLOT],
+ L2_PAGETABLE_XEN_SLOTS * sizeof(l2_pgentry_t));
+
+ /* Install the per-domain mappings for this domain */
+ for ( i = 0; i < PDPT_L2_ENTRIES; i++ )
+ sl2e[l2_table_offset(PERDOMAIN_VIRT_START) + i] =
+ l2e_from_pfn(
+
mfn_x(page_to_mfn(virt_to_page(d->arch.mm_perdomain_pt) + i)),
+ __PAGE_HYPERVISOR);
+
+ for ( i = 0; i < HAP_L3_PAGETABLE_ENTRIES; i++ )
+ sl2e[l2_table_offset(LINEAR_PT_VIRT_START) + i] =
+ l2e_empty();
+
+ if ( paging_mode_translate(d) )
+ {
+ /* Install the domain-specific p2m table */
+ l3_pgentry_t *p2m;
+ ASSERT(pagetable_get_pfn(d->arch.phys_table) != 0);
+ p2m = hap_map_domain_page(pagetable_get_mfn(d->arch.phys_table));
+ for ( i = 0; i < MACHPHYS_MBYTES>>1; i++ )
+ {
+ sl2e[l2_table_offset(RO_MPT_VIRT_START) + i] =
+ (l3e_get_flags(p2m[i]) & _PAGE_PRESENT)
+ ? l2e_from_pfn(mfn_x(_mfn(l3e_get_pfn(p2m[i]))),
+ __PAGE_HYPERVISOR)
+ : l2e_empty();
+ }
+ hap_unmap_domain_page(p2m);
+ }
+
+ hap_unmap_domain_page(sl2e);
+}
+#endif
+
+#if CONFIG_PAGING_LEVELS == 2
+void hap_install_xen_entries_in_l2(struct vcpu *v, mfn_t gl2mfn, mfn_t sl2mfn)
+{
+ struct domain *d = v->domain;
+ l2_pgentry_t *sl2e;
+ int i;
+
+ sl2e = hap_map_domain_page(sl2mfn);
+ ASSERT(sl2e != NULL);
+
+ /* Copy the common Xen mappings from the idle domain */
+ memcpy(&sl2e[L2_PAGETABLE_FIRST_XEN_SLOT],
+ &idle_pg_table[L2_PAGETABLE_FIRST_XEN_SLOT],
+ L2_PAGETABLE_XEN_SLOTS * sizeof(l2_pgentry_t));
+
+ /* Install the per-domain mappings for this domain */
+ for ( i = 0; i < PDPT_L2_ENTRIES; i++ )
+ sl2e[l2_table_offset(PERDOMAIN_VIRT_START) + i] =
+ l2e_from_pfn(
+ mfn_x(page_to_mfn(virt_to_page(d->arch.mm_perdomain_pt) + i)),
+ __PAGE_HYPERVISOR);
+
+
+ sl2e[l2_table_offset(LINEAR_PT_VIRT_START)] =
+ l2e_from_pfn(mfn_x(gl2mfn), __PAGE_HYPERVISOR);
+
+ /* install domain-specific P2M table */
+ sl2e[l2_table_offset(RO_MPT_VIRT_START)] =
+ l2e_from_pfn(mfn_x(pagetable_get_mfn(d->arch.phys_table)),
+ __PAGE_HYPERVISOR);
+
+ hap_unmap_domain_page(sl2e);
+}
+#endif
+
+mfn_t hap_make_monitor_table(struct vcpu *v)
+{
+ struct domain *d = v->domain;
+
+ ASSERT(pagetable_get_pfn(v->arch.monitor_table) == 0);
+
+#if CONFIG_PAGING_LEVELS == 4
+ {
+ mfn_t m4mfn;
+ m4mfn = hap_alloc(d, 0);
+ hap_install_xen_entries_in_l4(v, m4mfn, m4mfn);
+ return m4mfn;
+ }
+#elif CONFIG_PAGING_LEVELS == 3
+ {
+ mfn_t m3mfn, m2mfn;
+ l3_pgentry_t *l3e;
+ l2_pgentry_t *l2e;
+ int i;
+
+ m3mfn = hap_alloc(d, 0);
+
+ /* Install a monitor l2 table in slot 3 of the l3 table.
+ * This is used for all Xen entries, including linear maps
+ */
+ m2mfn = hap_alloc(d, 0);
+ l3e = hap_map_domain_page(m3mfn);
+ l3e[3] = l3e_from_pfn(mfn_x(m2mfn), _PAGE_PRESENT);
+ hap_install_xen_entries_in_l2h(v, m2mfn);
+ /* Install the monitor's own linear map */
+ l2e = hap_map_domain_page(m2mfn);
+ for ( i = 0; i < L3_PAGETABLE_ENTRIES; i++ )
+ l2e[l2_table_offset(LINEAR_PT_VIRT_START) + i] =
+ (l3e_get_flags(l3e[i]) & _PAGE_PRESENT)
+ ? l2e_from_pfn(l3e_get_pfn(l3e[i]), __PAGE_HYPERVISOR)
+ : l2e_empty();
+ hap_unmap_domain_page(l2e);
+ hap_unmap_domain_page(l3e);
+
+ HAP_PRINTK("new monitor table: %#lx\n", mfn_x(m3mfn));
+ return m3mfn;
+ }
+#else
+ {
+ mfn_t m2mfn;
+
+ m2mfn = hap_alloc(d, 0);
+ hap_install_xen_entries_in_l2(v, m2mfn, m2mfn);
+
+ return m2mfn;
+ }
+#endif
+}
+
+void hap_destroy_monitor_table(struct vcpu* v, mfn_t mmfn)
+{
+ struct domain *d = v->domain;
+
+#if CONFIG_PAGING_LEVELS == 4
+ /* Need to destroy the l3 monitor page in slot 0 too */
+ {
+ mfn_t m3mfn;
+ l4_pgentry_t *l4e = hap_map_domain_page(mmfn);
+ ASSERT(l4e_get_flags(l4e[0]) & _PAGE_PRESENT);
+ m3mfn = _mfn(l4e_get_pfn(l4e[0]));
+ hap_free(d, m3mfn);
+ hap_unmap_domain_page(l4e);
+ }
+#elif CONFIG_PAGING_LEVELS == 3
+ /* Need to destroy the l2 monitor page in slot 4 too */
+ {
+ l3_pgentry_t *l3e = hap_map_domain_page(mmfn);
+ ASSERT(l3e_get_flags(l3e[3]) & _PAGE_PRESENT);
+ hap_free(d, _mfn(l3e_get_pfn(l3e[3])));
+ hap_unmap_domain_page(l3e);
+ }
+#endif
+
+ /* Put the memory back in the pool */
+ hap_free(d, mmfn);
+}
+
+/************************************************/
+/* HAP DOMAIN LEVEL FUNCTIONS */
+/************************************************/
+void hap_domain_init(struct domain *d)
+{
+ hap_lock_init(d);
+ INIT_LIST_HEAD(&d->arch.paging.hap.freelists);
+ INIT_LIST_HEAD(&d->arch.paging.hap.p2m_freelist);
+}
+
+/* return 0 for success, -errno for failure */
+int hap_enable(struct domain *d, u32 mode)
+{
+ unsigned int old_pages;
+ int rv = 0;
+
+ HERE_I_AM;
+
+ domain_pause(d);
+ /* error check */
+ if ( (d == current->domain) ) {
+ rv = -EINVAL;
+ goto out;
+ }
+
+ old_pages = d->arch.paging.hap.total_pages;
+ if ( old_pages == 0 ) {
+ unsigned int r;
+ hap_lock(d);
+ r = hap_set_allocation(d, 256, NULL);
+ hap_unlock(d);
+ if ( r != 0 ) {
+ hap_set_allocation(d, 0, NULL);
+ rv = -ENOMEM;
+ goto out;
+ }
+ }
+
+ /* allocate P2m table */
+ if ( mode & PG_translate ) {
+ rv = p2m_alloc_table(d, hap_alloc_p2m_page, hap_free_p2m_page);
+ if ( rv != 0 )
+ goto out;
+ }
+
+ d->arch.paging.mode = mode | PG_SH_enable;
+
+ out:
+ domain_unpause(d);
+ return rv;
+}
+
+void hap_final_teardown(struct domain *d)
+{
+ HERE_I_AM;
+
+ if ( d->arch.paging.hap.total_pages != 0 )
+ hap_teardown(d);
+
+ p2m_teardown(d);
+}
+
+void hap_teardown(struct domain *d)
+{
+ struct vcpu *v;
+ mfn_t mfn;
+ HERE_I_AM;
+
+ ASSERT(test_bit(_DOMF_dying, &d->domain_flags));
+ ASSERT(d != current->domain);
+
+ if ( !hap_locked_by_me(d) )
+ hap_lock(d); /* Keep various asserts happy */
+
+ if ( paging_mode_enabled(d) ) {
+ /* release the monitor table held by each vcpu */
+ for_each_vcpu(d, v) {
+ if ( v->arch.paging.mode && paging_mode_external(d) ) {
+ mfn = pagetable_get_mfn(v->arch.monitor_table);
+ if ( mfn_valid(mfn) && (mfn_x(mfn) != 0) )
+ hap_destroy_monitor_table(v, mfn);
+ v->arch.monitor_table = pagetable_null();
+ }
+ }
+ }
+
+ if ( d->arch.paging.hap.total_pages != 0 ) {
+ HAP_PRINTK("teardown of domain %u starts."
+ " pages total = %u, free = %u, p2m=%u\n",
+ d->domain_id,
+ d->arch.paging.hap.total_pages,
+ d->arch.paging.hap.free_pages,
+ d->arch.paging.hap.p2m_pages);
+ hap_set_allocation(d, 0, NULL);
+ HAP_PRINTK("teardown done."
+ " pages total = %u, free = %u, p2m=%u\n",
+ d->arch.paging.hap.total_pages,
+ d->arch.paging.hap.free_pages,
+ d->arch.paging.hap.p2m_pages);
+ ASSERT(d->arch.paging.hap.total_pages == 0);
+ }
+
+ d->arch.paging.mode &= ~PG_log_dirty;
+
+ hap_unlock(d);
+}
+
+int hap_domctl(struct domain *d, xen_domctl_shadow_op_t *sc,
+ XEN_GUEST_HANDLE(void) u_domctl)
+{
+ int rc, preempted = 0;
+
+ HERE_I_AM;
+
+ if ( unlikely(d == current->domain) ) {
+ gdprintk(XENLOG_INFO, "Don't try to do a hap op on yourself!\n");
+ return -EINVAL;
+ }
+
+ switch ( sc->op ) {
+ case XEN_DOMCTL_SHADOW_OP_OFF:
+ case XEN_DOMCTL_SHADOW_OP_ENABLE_TEST:
+ case XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY:
+ case XEN_DOMCTL_SHADOW_OP_ENABLE_TRANSLATE:
+ case XEN_DOMCTL_SHADOW_OP_CLEAN:
+ case XEN_DOMCTL_SHADOW_OP_PEEK:
+ case XEN_DOMCTL_SHADOW_OP_ENABLE:
+ HAP_ERROR("Bad hap domctl op %u\n", sc->op);
+ domain_crash(d);
+ return -EINVAL;
+ case XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION:
+ hap_lock(d);
+ rc = hap_set_allocation(d, sc->mb << (20 - PAGE_SHIFT), &preempted);
+ hap_unlock(d);
+ if ( preempted )
+ /* Not finished. Set up to re-run the call. */
+ rc = hypercall_create_continuation(__HYPERVISOR_domctl, "h",
+ u_domctl);
+ else
+ /* Finished. Return the new allocation */
+ sc->mb = hap_get_allocation(d);
+ return rc;
+ case XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION:
+ sc->mb = hap_get_allocation(d);
+ return 0;
+ default:
+ HAP_ERROR("Bad hap domctl op %u\n", sc->op);
+ return -EINVAL;
+ }
+}
+
+void hap_vcpu_init(struct vcpu *v)
+{
+ v->arch.paging.mode = &hap_paging_real_mode;
+}
+/************************************************/
+/* HAP PAGING MODE FUNCTIONS */
+/************************************************/
+/* In theory, hap should not intercept guest page fault. This function can
+ * be recycled to handle host/nested page fault, if needed.
+ */
+int hap_page_fault(struct vcpu *v, unsigned long va,
+ struct cpu_user_regs *regs)
+{
+ HERE_I_AM;
+ domain_crash(v->domain);
+ return 0;
+}
+
+/* called when guest issues a invlpg request.
+ * Return 1 if need to issue page invalidation on CPU; Return 0 if does not
+ * need to do so.
+ */
+int hap_invlpg(struct vcpu *v, unsigned long va)
+{
+ HERE_I_AM;
+ return 0;
+}
+
+void hap_update_cr3(struct vcpu *v, int do_locking)
+{
+ struct domain *d = v->domain;
+ mfn_t gmfn;
+
+ HERE_I_AM;
+ /* Don't do anything on an uninitialised vcpu */
+ if ( !is_hvm_domain(d) && !test_bit(_VCPUF_initialised, &v->vcpu_flags) ) {
+ ASSERT(v->arch.cr3 == 0);
+ return;
+ }
+
+ if ( do_locking )
+ hap_lock(v->domain);
+
+ ASSERT(hap_locked_by_me(v->domain));
+ ASSERT(v->arch.paging.mode);
+
+ gmfn = pagetable_get_mfn(v->arch.guest_table);
+
+ make_cr3(v, pagetable_get_pfn(v->arch.monitor_table));
+
+ hvm_update_guest_cr3(v, pagetable_get_paddr(v->arch.monitor_table));
+
+ HAP_PRINTK("d=%u v=%u guest_table=%05lx, monitor_table = %05lx\n",
+ d->domain_id, v->vcpu_id,
+ (unsigned long)pagetable_get_pfn(v->arch.guest_table),
+ (unsigned long)pagetable_get_pfn(v->arch.monitor_table));
+
+ flush_tlb_mask(d->domain_dirty_cpumask);
+
+ if ( do_locking )
+ hap_unlock(v->domain);
+}
+
+void hap_update_paging_modes(struct vcpu *v)
+{
+ struct domain *d;
+
+ HERE_I_AM;
+
+ d = v->domain;
+ hap_lock(d);
+
+ /* update guest paging mode. Note that we rely on hvm functions to detect
+ * guest's paging mode. So, make sure the shadow registers (CR0, CR4, EFER)
+ * reflect guest's status correctly.
+ */
+ if ( hvm_paging_enabled(v) ) {
+ if ( hvm_long_mode_enabled(v) )
+ v->arch.paging.mode = &hap_paging_long_mode;
+ else if ( hvm_pae_enabled(v) )
+ v->arch.paging.mode = &hap_paging_pae_mode;
+ else
+ v->arch.paging.mode = &hap_paging_protected_mode;
+ }
+ else {
+ v->arch.paging.mode = &hap_paging_real_mode;
+ }
+
+ v->arch.paging.translate_enabled = !!hvm_paging_enabled(v);
+
+ /* use p2m map */
+ v->arch.guest_table =
+ pagetable_from_pfn(pagetable_get_pfn(d->arch.phys_table));
+
+ if ( pagetable_is_null(v->arch.monitor_table) ) {
+ mfn_t mmfn = hap_make_monitor_table(v);
+ v->arch.monitor_table = pagetable_from_mfn(mmfn);
+ make_cr3(v, mfn_x(mmfn));
+ }
+
+ flush_tlb_mask(d->domain_dirty_cpumask);
+ hap_unlock(d);
+}
+
+void
+hap_write_p2m_entry(struct vcpu *v, unsigned long gfn, l1_pgentry_t *p,
+ l1_pgentry_t new, unsigned int level)
+{
+ hap_lock(v->domain);
+ safe_write_pte(p, new);
+ hap_unlock(v->domain);
+}
+
+/* Entry points into this mode of the hap code. */
+struct paging_mode hap_paging_real_mode = {
+ .page_fault = hap_page_fault,
+ .invlpg = hap_invlpg,
+ .gva_to_gfn = hap_gva_to_gfn_real_mode,
+ .update_cr3 = hap_update_cr3,
+ .update_paging_modes = hap_update_paging_modes,
+ .write_p2m_entry = hap_write_p2m_entry,
+ .guest_levels = 1
+};
+
+struct paging_mode hap_paging_protected_mode = {
+ .page_fault = hap_page_fault,
+ .invlpg = hap_invlpg,
+ .gva_to_gfn = hap_gva_to_gfn_protected_mode,
+ .update_cr3 = hap_update_cr3,
+ .update_paging_modes = hap_update_paging_modes,
+ .write_p2m_entry = hap_write_p2m_entry,
+ .guest_levels = 2
+};
+
+struct paging_mode hap_paging_pae_mode = {
+ .page_fault = hap_page_fault,
+ .invlpg = hap_invlpg,
+ .gva_to_gfn = hap_gva_to_gfn_pae_mode,
+ .update_cr3 = hap_update_cr3,
+ .update_paging_modes = hap_update_paging_modes,
+ .write_p2m_entry = hap_write_p2m_entry,
+ .guest_levels = 3
+};
+
+struct paging_mode hap_paging_long_mode = {
+ .page_fault = hap_page_fault,
+ .invlpg = hap_invlpg,
+ .gva_to_gfn = hap_gva_to_gfn_long_mode,
+ .update_cr3 = hap_update_cr3,
+ .update_paging_modes = hap_update_paging_modes,
+ .write_p2m_entry = hap_write_p2m_entry,
+ .guest_levels = 4
+};
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
+
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/mm/hap/private.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/mm/hap/private.h Mon Mar 12 10:07:08 2007 -0600
@@ -0,0 +1,112 @@
+/*
+ * arch/x86/mm/hap/private.h
+ *
+ * Copyright (c) 2007, AMD Corporation (Wei Huang)
+ *
+ * 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.
+ *
+ */
+#ifndef __HAP_PRIVATE_H__
+#define __HAP_PRIVATE_H__
+
+#include <asm/flushtlb.h>
+#include <asm/hvm/support.h>
+
+/********************************************/
+/* GUEST TRANSLATION FUNCS */
+/********************************************/
+unsigned long hap_gva_to_gfn_real_mode(struct vcpu *v, unsigned long gva);
+unsigned long hap_gva_to_gfn_protected_mode(struct vcpu *v, unsigned long gva);
+unsigned long hap_gva_to_gfn_pae_mode(struct vcpu *v, unsigned long gva);
+unsigned long hap_gva_to_gfn_long_mode(struct vcpu *v, unsigned long gva);
+/********************************************/
+/* MISC DEFINITIONS */
+/********************************************/
+
+/* PT_SHIFT describes the amount by which a virtual address is shifted right
+ * to right justify the portion to be used for indexing into a page
+ * table, given the guest memory model (i.e. number of levels) and the level
+ * of the page table being accessed. The idea is from Virtual Iron's code.
+ */
+static const int PT_SHIFT[][5] =
+ { /* ------ level ------ nr_levels */
+ /* 1 2 3 4 */
+ { 0, 0, 0, 0, 0}, /* 0 not used */
+ { 0, 0, 0, 0, 0}, /* 1 not used */
+ { 0, 12, 22, 0, 0}, /* 2 */
+ { 0, 12, 21, 30, 0}, /* 3 */
+ { 0, 12, 21, 30, 39} /* 4 */
+ };
+
+/* PT_ENTRIES describes the number of entries in a page table, given the
+ * memory model (i.e. number of levels) and the level of the page table
+ * being considered. This idea from Virtual Iron's shadow code*/
+static const int PT_ENTRIES[][5] =
+ { /* ------ level ------ nr_levels */
+ /* 1 2 3 4 */
+ { 0, 0, 0, 0, 0}, /* 0 not used */
+ { 0, 0, 0, 0, 0}, /* 1 not used */
+ { 0, 1024, 1024, 0, 0}, /* 2 */
+ { 0, 512, 512, 4, 0}, /* 3 */
+ { 0, 512, 512, 512, 512} /* 4 */
+ };
+
+/********************************************/
+/* PAGING DEFINITION FOR GUEST */
+/********************************************/
+#define PHYSICAL_PAGE_4K_SIZE (1UL << 12)
+#define PHYSICAL_PAGE_2M_SIZE (1UL << 21)
+#define PHYSICAL_PAGE_4M_SIZE (1UL << 22)
+#define PHYSICAL_PAGE_4K_MASK ( ~(PHYSICAL_PAGE_4K_SIZE - 1) )
+#define PHYSICAL_PAGE_2M_MASK ( ~(PHYSICAL_PAGE_2M_SIZE - 1) )
+#define PHYSICAL_PAGE_4M_MASK ( ~(PHYSICAL_PAGE_4M_SIZE - 1) )
+
+/* long mode physical address mask */
+#define PHYSICAL_ADDR_BITS_LM 52
+#define PHYSICAL_ADDR_MASK_LM ((1UL << PHYSICAL_ADDR_BITS_LM)-1)
+#define PHYSICAL_ADDR_2M_MASK_LM (PHYSICAL_PAGE_2M_MASK &
PHYSICAL_ADDR_MASK_LM)
+#define PHYSICAL_ADDR_4K_MASK_LM (PHYSICAL_PAGE_4K_MASK &
PHYSICAL_ADDR_MASK_LM)
+
+#define PAGE_NX_BIT (1ULL << 63)
+/************************************************/
+/* PAGETABLE RELATED VARIABLES */
+/************************************************/
+#if CONFIG_PAGING_LEVELS == 2
+#define HAP_L1_PAGETABLE_ENTRIES 1024
+#define HAP_L2_PAGETABLE_ENTRIES 1024
+#define HAP_L1_PAGETABLE_SHIFT 12
+#define HAP_L2_PAGETABLE_SHIFT 22
+#endif
+
+#if CONFIG_PAGING_LEVELS == 3
+#define HAP_L1_PAGETABLE_ENTRIES 512
+#define HAP_L2_PAGETABLE_ENTRIES 512
+#define HAP_L3_PAGETABLE_ENTRIES 4
+#define HAP_L1_PAGETABLE_SHIFT 12
+#define HAP_L2_PAGETABLE_SHIFT 21
+#define HAP_L3_PAGETABLE_SHIFT 30
+#endif
+
+#if CONFIG_PAGING_LEVELS == 4
+#define HAP_L1_PAGETABLE_ENTRIES 512
+#define HAP_L2_PAGETABLE_ENTRIES 512
+#define HAP_L3_PAGETABLE_ENTRIES 512
+#define HAP_L4_PAGETABLE_ENTRIES 512
+#define HAP_L1_PAGETABLE_SHIFT 12
+#define HAP_L2_PAGETABLE_SHIFT 21
+#define HAP_L3_PAGETABLE_SHIFT 30
+#define HAP_L4_PAGETABLE_SHIFT 39
+#endif
+
+#endif /* __SVM_NPT_H__ */
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/mm/hap/support.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/mm/hap/support.c Mon Mar 12 10:07:08 2007 -0600
@@ -0,0 +1,334 @@
+/*
+ * arch/x86/mm/hap/support.c
+ *
+ * guest page table walker
+ * Copyright (c) 2007, AMD Corporation (Wei Huang)
+ *
+ * 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.
+ *
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/mm.h>
+#include <xen/domain_page.h>
+#include <asm/page.h>
+#include <xen/event.h>
+#include <xen/sched.h>
+#include <asm/hvm/svm/vmcb.h>
+#include <asm/domain.h>
+#include <asm/shadow.h>
+#include <asm/hap.h>
+
+#include "private.h"
+#include "../page-guest32.h"
+
+/*******************************************/
+/* Platform Specific Functions */
+/*******************************************/
+
+/* Translate guest virtual address to guest physical address. Specifically
+ * for real mode guest.
+ */
+unsigned long hap_gva_to_gfn_real_mode(struct vcpu *v, unsigned long gva)
+{
+ HERE_I_AM;
+ return ((paddr_t)gva >> PAGE_SHIFT);
+}
+
+/* Translate guest virtual address to guest physical address. Specifically
+ * for protected guest.
+ */
+unsigned long hap_gva_to_gfn_protected_mode(struct vcpu *v, unsigned long gva)
+{
+ unsigned long gcr3 = hvm_get_guest_ctrl_reg(v, 3);
+ int mode = 2; /* two-level guest */
+ int lev, index;
+ paddr_t gpa = 0;
+ unsigned long gpfn, mfn;
+ int success = 1;
+ l2_pgentry_32_t *l2e; /* guest page entry size is 32-bit */
+ l1_pgentry_32_t *l1e;
+
+ HERE_I_AM;
+
+ gpfn = (gcr3 >> PAGE_SHIFT);
+ for ( lev = mode; lev >= 1; lev-- ) {
+ mfn = get_mfn_from_gpfn( gpfn );
+ if ( mfn == INVALID_MFN ) {
+ HAP_PRINTK("bad pfn=0x%lx from gva=0x%lx at lev%d\n", gpfn, gva,
+ lev);
+ success = 0;
+ break;
+ }
+ index = (gva >> PT_SHIFT[mode][lev]) & (PT_ENTRIES[mode][lev]-1);
+
+ if ( lev == 2 ) {
+ l2e = map_domain_page( mfn );
+ HAP_PRINTK("l2 page table entry is %ulx at index = %d\n",
+ l2e[index].l2, index);
+ if ( !(l2e_get_flags_32(l2e[index]) & _PAGE_PRESENT) ) {
+ HAP_PRINTK("Level 2 entry not present at index = %d\n", index);
+ success = 0;
+ }
+
+ if ( l2e_get_flags_32(l2e[index]) & _PAGE_PSE ) { /* handle PSE */
+ HAP_PRINTK("guest page table is PSE\n");
+ if ( l2e_get_intpte(l2e[index]) & 0x001FE000UL ) { /*[13:20] */
+ printk("guest physical memory size is too large!\n");
+ domain_crash(v->domain);
+ }
+ gpa = (l2e_get_intpte(l2e[index]) & PHYSICAL_PAGE_4M_MASK) +
+ (gva & ~PHYSICAL_PAGE_4M_MASK);
+ unmap_domain_page(l2e);
+ break; /* last level page table, return from here */
+ }
+ else {
+ gpfn = l2e_get_pfn( l2e[index] );
+ }
+ unmap_domain_page(l2e);
+ }
+
+ if ( lev == 1 ) {
+ l1e = map_domain_page( mfn );
+ HAP_PRINTK("l1 page table entry is %ulx at index = %d\n",
+ l1e[index].l1, index);
+ if ( !(l1e_get_flags_32(l1e[index]) & _PAGE_PRESENT) ) {
+ HAP_PRINTK("Level 1 entry not present at index = %d\n", index);
+ success = 0;
+ }
+ gpfn = l1e_get_pfn( l1e[index] );
+ gpa = (l1e_get_intpte(l1e[index]) & PHYSICAL_PAGE_4K_MASK) +
+ (gva & ~PHYSICAL_PAGE_4K_MASK);
+ unmap_domain_page(l1e);
+ }
+
+ if ( !success ) /* error happened, jump out */
+ break;
+ }
+
+ HAP_PRINTK("success = %d, gva = %lx, gpa = %lx\n", success, gva, gpa);
+
+ if ( !success ) /* error happened */
+ return INVALID_GFN;
+ else
+ return ((paddr_t)gpa >> PAGE_SHIFT);
+}
+
+
+
+/* Translate guest virtual address to guest physical address. Specifically
+ * for PAE mode guest.
+ */
+unsigned long hap_gva_to_gfn_pae_mode(struct vcpu *v, unsigned long gva)
+{
+#if CONFIG_PAGING_LEVELS >= 3
+ unsigned long gcr3 = hvm_get_guest_ctrl_reg(v, 3);
+ int mode = 3; /* three-level guest */
+ int lev, index;
+ paddr_t gpa = 0;
+ unsigned long gpfn, mfn;
+ int success = 1;
+ l1_pgentry_t *l1e;
+ l2_pgentry_t *l2e;
+ l3_pgentry_t *l3e;
+
+ HERE_I_AM;
+
+ gpfn = (gcr3 >> PAGE_SHIFT);
+ for ( lev = mode; lev >= 1; lev-- ) {
+ mfn = get_mfn_from_gpfn( gpfn );
+ if ( mfn == INVALID_MFN ) {
+ HAP_PRINTK("bad pfn=0x%lx from gva=0x%lx at lev%d\n", gpfn, gva,
+ lev);
+ success = 0;
+ break;
+ }
+ index = (gva >> PT_SHIFT[mode][lev]) & (PT_ENTRIES[mode][lev]-1);
+
+ if ( lev == 3 ) {
+ l3e = map_domain_page( mfn );
+ index += ( ((gcr3 >> 5 ) & 127 ) * 4 );
+ if ( !(l3e_get_flags(l3e[index]) & _PAGE_PRESENT) ) {
+ HAP_PRINTK("Level 3 entry not present at index = %d\n", index);
+ success = 0;
+ }
+ gpfn = l3e_get_pfn( l3e[index] );
+ unmap_domain_page(l3e);
+ }
+
+ if ( lev == 2 ) {
+ l2e = map_domain_page( mfn );
+ if ( !(l2e_get_flags(l2e[index]) & _PAGE_PRESENT) ) {
+ HAP_PRINTK("Level 2 entry not present at index = %d\n", index);
+ success = 0;
+ }
+
+ if ( l2e_get_flags(l2e[index]) & _PAGE_PSE ) { /* handle PSE */
+ HAP_PRINTK("guest page table is PSE\n");
+ gpa = (l2e_get_intpte(l2e[index]) & PHYSICAL_PAGE_2M_MASK) +
+ (gva & ~PHYSICAL_PAGE_2M_MASK);
+ unmap_domain_page(l2e);
+ break; /* last level page table, jump out from here */
+ }
+ else {
+ gpfn = l2e_get_pfn(l2e[index]);
+ }
+ unmap_domain_page(l2e);
+ }
+
+ if ( lev == 1 ) {
+ l1e = map_domain_page( mfn );
+ if ( !(l1e_get_flags(l1e[index]) & _PAGE_PRESENT) ) {
+ HAP_PRINTK("Level 1 entry not present at index = %d\n", index);
+ success = 0;
+ }
+ gpfn = l1e_get_pfn( l1e[index] );
+ gpa = (l1e_get_intpte(l1e[index]) & PHYSICAL_PAGE_4K_MASK) +
+ (gva & ~PHYSICAL_PAGE_4K_MASK);
+ unmap_domain_page(l1e);
+ }
+
+ if ( success != 1 ) /* error happened, jump out */
+ break;
+ }
+
+ gpa &= ~PAGE_NX_BIT; /* clear NX bit of guest physical address */
+ HAP_PRINTK("success = %d, gva = %lx, gpa = %lx\n", success, gva, gpa);
+
+ if ( !success )
+ return INVALID_GFN;
+ else
+ return ((paddr_t)gpa >> PAGE_SHIFT);
+#else
+ HERE_I_AM;
+ printk("guest paging level (3) is greater than host paging level!\n");
+ domain_crash(v->domain);
+ return INVALID_GFN;
+#endif
+}
+
+
+
+/* Translate guest virtual address to guest physical address. Specifically
+ * for long mode guest.
+ */
+unsigned long hap_gva_to_gfn_long_mode(struct vcpu *v, unsigned long gva)
+{
+#if CONFIG_PAGING_LEVELS == 4
+ unsigned long gcr3 = hvm_get_guest_ctrl_reg(v, 3);
+ int mode = 4; /* four-level guest */
+ int lev, index;
+ paddr_t gpa = 0;
+ unsigned long gpfn, mfn;
+ int success = 1;
+ l4_pgentry_t *l4e;
+ l3_pgentry_t *l3e;
+ l2_pgentry_t *l2e;
+ l1_pgentry_t *l1e;
+
+ HERE_I_AM;
+
+ gpfn = (gcr3 >> PAGE_SHIFT);
+ for ( lev = mode; lev >= 1; lev-- ) {
+ mfn = get_mfn_from_gpfn( gpfn );
+ if ( mfn == INVALID_MFN ) {
+ HAP_PRINTK("bad pfn=0x%lx from gva=0x%lx at lev%d\n", gpfn, gva,
+ lev);
+ success = 0;
+ break;
+ }
+ index = (gva >> PT_SHIFT[mode][lev]) & (PT_ENTRIES[mode][lev]-1);
+
+ if ( lev == 4 ) {
+ l4e = map_domain_page( mfn );
+ if ( !(l4e_get_flags(l4e[index]) & _PAGE_PRESENT) ) {
+ HAP_PRINTK("Level 4 entry not present at index = %d\n", index);
+ success = 0;
+ }
+ gpfn = l4e_get_pfn( l4e[index] );
+ unmap_domain_page(l4e);
+ }
+
+ if ( lev == 3 ) {
+ l3e = map_domain_page( mfn );
+ if ( !(l3e_get_flags(l3e[index]) & _PAGE_PRESENT) ) {
+ HAP_PRINTK("Level 3 entry not present at index = %d\n", index);
+ success = 0;
+ }
+ gpfn = l3e_get_pfn( l3e[index] );
+ unmap_domain_page(l3e);
+ }
+
+ if ( lev == 2 ) {
+ l2e = map_domain_page( mfn );
+ if ( !(l2e_get_flags(l2e[index]) & _PAGE_PRESENT) ) {
+ HAP_PRINTK("Level 2 entry not present at index = %d\n", index);
+ success = 0;
+ }
+
+ if ( l2e_get_flags(l2e[index]) & _PAGE_PSE ) { /* handle PSE */
+ HAP_PRINTK("guest page table is PSE\n");
+ gpa = (l2e_get_intpte(l2e[index]) & PHYSICAL_ADDR_2M_MASK_LM)
+ + (gva & ~PHYSICAL_PAGE_2M_MASK);
+ unmap_domain_page(l2e);
+ break; /* last level page table, jump out from here */
+ }
+ else {
+ gpfn = l2e_get_pfn(l2e[index]);
+ }
+ unmap_domain_page(l2e);
+ }
+
+ if ( lev == 1 ) {
+ l1e = map_domain_page( mfn );
+ if ( !(l1e_get_flags(l1e[index]) & _PAGE_PRESENT) ) {
+ HAP_PRINTK("Level 1 entry not present at index = %d\n", index);
+ success = 0;
+ }
+ gpfn = l1e_get_pfn( l1e[index] );
+ gpa = (l1e_get_intpte(l1e[index]) & PHYSICAL_ADDR_4K_MASK_LM) +
+ (gva & ~PHYSICAL_PAGE_4K_MASK);
+ unmap_domain_page(l1e);
+ }
+
+ if ( success != 1 ) /* error happened, jump out */
+ break;
+ }
+
+ gpa &= ~PAGE_NX_BIT; /* clear NX bit of guest physical address */
+ HAP_PRINTK("success = %d, gva = %lx, gpa = %lx\n", success, gva, gpa);
+
+ if ( !success )
+ return INVALID_GFN;
+ else
+ return ((paddr_t)gpa >> PAGE_SHIFT);
+#else
+ HERE_I_AM;
+ printk("guest paging level (4) is greater than host paging level!\n");
+ domain_crash(v->domain);
+ return INVALID_GFN;
+#endif
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/mm/page-guest32.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/mm/page-guest32.h Mon Mar 12 10:07:08 2007 -0600
@@ -0,0 +1,100 @@
+
+#ifndef __X86_PAGE_GUEST_H__
+#define __X86_PAGE_GUEST_H__
+
+#ifndef __ASSEMBLY__
+# include <asm/types.h>
+#endif
+
+#define PAGETABLE_ORDER_32 10
+#define L1_PAGETABLE_ENTRIES_32 (1<<PAGETABLE_ORDER_32)
+#define L2_PAGETABLE_ENTRIES_32 (1<<PAGETABLE_ORDER_32)
+#define ROOT_PAGETABLE_ENTRIES_32 L2_PAGETABLE_ENTRIES_32
+
+
+#define L1_PAGETABLE_SHIFT_32 12
+#define L2_PAGETABLE_SHIFT_32 22
+
+/* Extract flags into 12-bit integer, or turn 12-bit flags into a pte mask. */
+
+#ifndef __ASSEMBLY__
+
+typedef u32 intpte_32_t;
+
+typedef struct { intpte_32_t l1; } l1_pgentry_32_t;
+typedef struct { intpte_32_t l2; } l2_pgentry_32_t;
+typedef l2_pgentry_t root_pgentry_32_t;
+#endif
+
+#define get_pte_flags_32(x) ((u32)(x) & 0xFFF)
+#define put_pte_flags_32(x) ((intpte_32_t)(x))
+
+/* Get pte access flags (unsigned int). */
+#define l1e_get_flags_32(x) (get_pte_flags_32((x).l1))
+#define l2e_get_flags_32(x) (get_pte_flags_32((x).l2))
+
+#define l1e_get_paddr_32(x) \
+ ((paddr_t)(((x).l1 & (PADDR_MASK&PAGE_MASK))))
+#define l2e_get_paddr_32(x) \
+ ((paddr_t)(((x).l2 & (PADDR_MASK&PAGE_MASK))))
+
+/* Construct an empty pte. */
+#define l1e_empty_32() ((l1_pgentry_32_t) { 0 })
+#define l2e_empty_32() ((l2_pgentry_32_t) { 0 })
+
+/* Construct a pte from a pfn and access flags. */
+#define l1e_from_pfn_32(pfn, flags) \
+ ((l1_pgentry_32_t) { ((intpte_32_t)(pfn) << PAGE_SHIFT) |
put_pte_flags_32(flags) })
+#define l2e_from_pfn_32(pfn, flags) \
+ ((l2_pgentry_32_t) { ((intpte_32_t)(pfn) << PAGE_SHIFT) |
put_pte_flags_32(flags) })
+
+/* Construct a pte from a physical address and access flags. */
+#ifndef __ASSEMBLY__
+static inline l1_pgentry_32_t l1e_from_paddr_32(paddr_t pa, unsigned int flags)
+{
+ ASSERT((pa & ~(PADDR_MASK & PAGE_MASK)) == 0);
+ return (l1_pgentry_32_t) { pa | put_pte_flags_32(flags) };
+}
+static inline l2_pgentry_32_t l2e_from_paddr_32(paddr_t pa, unsigned int flags)
+{
+ ASSERT((pa & ~(PADDR_MASK & PAGE_MASK)) == 0);
+ return (l2_pgentry_32_t) { pa | put_pte_flags_32(flags) };
+}
+#endif /* !__ASSEMBLY__ */
+
+
+/* Construct a pte from a page pointer and access flags. */
+#define l1e_from_page_32(page, flags)
(l1e_from_pfn_32(page_to_mfn(page),(flags)))
+#define l2e_from_page_32(page, flags)
(l2e_from_pfn_32(page_to_mfn(page),(flags)))
+
+/* Add extra flags to an existing pte. */
+#define l1e_add_flags_32(x, flags) ((x).l1 |= put_pte_flags_32(flags))
+#define l2e_add_flags_32(x, flags) ((x).l2 |= put_pte_flags_32(flags))
+
+/* Remove flags from an existing pte. */
+#define l1e_remove_flags_32(x, flags) ((x).l1 &= ~put_pte_flags_32(flags))
+#define l2e_remove_flags_32(x, flags) ((x).l2 &= ~put_pte_flags_32(flags))
+
+/* Check if a pte's page mapping or significant access flags have changed. */
+#define l1e_has_changed_32(x,y,flags) \
+ ( !!(((x).l1 ^ (y).l1) & ((PADDR_MASK&PAGE_MASK)|put_pte_flags_32(flags)))
)
+#define l2e_has_changed_32(x,y,flags) \
+ ( !!(((x).l2 ^ (y).l2) & ((PADDR_MASK&PAGE_MASK)|put_pte_flags_32(flags)))
)
+
+/* Given a virtual address, get an entry offset into a page table. */
+#define l1_table_offset_32(a) \
+ (((a) >> L1_PAGETABLE_SHIFT_32) & (L1_PAGETABLE_ENTRIES_32 - 1))
+#define l2_table_offset_32(a) \
+ (((a) >> L2_PAGETABLE_SHIFT_32) & (L2_PAGETABLE_ENTRIES_32 - 1))
+
+#endif /* __X86_PAGE_GUEST_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/mm/paging.c
--- a/xen/arch/x86/mm/paging.c Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/x86/mm/paging.c Mon Mar 12 10:07:08 2007 -0600
@@ -24,10 +24,12 @@
#include <asm/paging.h>
#include <asm/shadow.h>
#include <asm/p2m.h>
+#include <asm/hap.h>
/* Xen command-line option to enable hardware-assisted paging */
int opt_hap_enabled = 0;
boolean_param("hap", opt_hap_enabled);
+int hap_capable_system = 0;
/* Printouts */
#define PAGING_PRINTK(_f, _a...) \
@@ -46,12 +48,18 @@ void paging_domain_init(struct domain *d
{
p2m_init(d);
shadow_domain_init(d);
+
+ if ( opt_hap_enabled && hap_capable_system && is_hvm_domain(d) )
+ hap_domain_init(d);
}
/* vcpu paging struct initialization goes here */
void paging_vcpu_init(struct vcpu *v)
{
- shadow_vcpu_init(v);
+ if ( opt_hap_enabled && hap_capable_system && is_hvm_vcpu(v) )
+ hap_vcpu_init(v);
+ else
+ shadow_vcpu_init(v);
}
@@ -59,32 +67,38 @@ int paging_domctl(struct domain *d, xen_
XEN_GUEST_HANDLE(void) u_domctl)
{
/* Here, dispatch domctl to the appropriate paging code */
- return shadow_domctl(d, sc, u_domctl);
+ if ( opt_hap_enabled && hap_capable_system && is_hvm_domain(d) )
+ return hap_domctl(d, sc, u_domctl);
+ else
+ return shadow_domctl(d, sc, u_domctl);
}
/* Call when destroying a domain */
void paging_teardown(struct domain *d)
{
- shadow_teardown(d);
- /* Call other modes' teardown code here */
+ if ( opt_hap_enabled && hap_capable_system && is_hvm_domain(d) )
+ hap_teardown(d);
+ else
+ shadow_teardown(d);
}
/* Call once all of the references to the domain have gone away */
void paging_final_teardown(struct domain *d)
{
- shadow_teardown(d);
- /* Call other modes' final teardown code here */
+ if ( opt_hap_enabled && hap_capable_system && is_hvm_domain(d) )
+ hap_final_teardown(d);
+ else
+ shadow_final_teardown(d);
}
/* Enable an arbitrary paging-assistance mode. Call once at domain
* creation. */
int paging_enable(struct domain *d, u32 mode)
{
- if ( mode & PG_SH_enable )
- return shadow_enable(d, mode);
+ if ( opt_hap_enabled && hap_capable_system && is_hvm_domain(d) )
+ return hap_enable(d, mode | PG_HAP_enable);
else
- /* No other modes supported yet */
- return -EINVAL;
+ return shadow_enable(d, mode | PG_SH_enable);
}
/* Print paging-assistance info to the console */
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/mm/shadow/common.c
--- a/xen/arch/x86/mm/shadow/common.c Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/x86/mm/shadow/common.c Mon Mar 12 10:07:08 2007 -0600
@@ -802,7 +802,7 @@ void shadow_prealloc(struct domain *d, u
v = current;
if ( v->domain != d )
v = d->vcpu[0];
- ASSERT(v != NULL);
+ ASSERT(v != NULL); /* Shouldn't have enabled shadows if we've no vcpus */
/* Stage one: walk the list of pinned pages, unpinning them */
perfc_incrc(shadow_prealloc_1);
@@ -861,7 +861,9 @@ static void shadow_blow_tables(struct do
struct vcpu *v = d->vcpu[0];
mfn_t smfn;
int i;
-
+
+ ASSERT(v != NULL);
+
/* Pass one: unpin all pinned pages */
list_for_each_backwards_safe(l,t, &d->arch.paging.shadow.pinned_shadows)
{
@@ -1129,6 +1131,7 @@ shadow_free_p2m_page(struct domain *d, s
SHADOW_ERROR("Odd p2m page count c=%#x t=%"PRtype_info"\n",
pg->count_info, pg->u.inuse.type_info);
}
+ pg->count_info = 0;
/* Free should not decrement domain's total allocation, since
* these pages were allocated without an owner. */
page_set_owner(pg, NULL);
@@ -1243,6 +1246,9 @@ static unsigned int sh_set_allocation(st
list_del(&sp->list);
d->arch.paging.shadow.free_pages -= 1<<SHADOW_MAX_ORDER;
d->arch.paging.shadow.total_pages -= 1<<SHADOW_MAX_ORDER;
+ for ( j = 0; j < 1<<SHADOW_MAX_ORDER; j++ )
+ /* Keep the page allocator happy */
+ ((struct page_info *)sp)[j].count_info = 0;
free_domheap_pages((struct page_info *)sp, SHADOW_MAX_ORDER);
}
@@ -2989,6 +2995,13 @@ int shadow_domctl(struct domain *d,
return 0;
}
+ if ( unlikely(d->vcpu[0] == NULL) )
+ {
+ SHADOW_ERROR("Shadow op on a domain (%u) with no vcpus\n",
+ d->domain_id);
+ return -EINVAL;
+ }
+
switch ( sc->op )
{
case XEN_DOMCTL_SHADOW_OP_OFF:
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/mm/shadow/page-guest32.h
--- a/xen/arch/x86/mm/shadow/page-guest32.h Mon Mar 12 09:43:48 2007 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-
-#ifndef __X86_PAGE_GUEST_H__
-#define __X86_PAGE_GUEST_H__
-
-#ifndef __ASSEMBLY__
-# include <asm/types.h>
-#endif
-
-#define PAGETABLE_ORDER_32 10
-#define L1_PAGETABLE_ENTRIES_32 (1<<PAGETABLE_ORDER_32)
-#define L2_PAGETABLE_ENTRIES_32 (1<<PAGETABLE_ORDER_32)
-#define ROOT_PAGETABLE_ENTRIES_32 L2_PAGETABLE_ENTRIES_32
-
-
-#define L1_PAGETABLE_SHIFT_32 12
-#define L2_PAGETABLE_SHIFT_32 22
-
-/* Extract flags into 12-bit integer, or turn 12-bit flags into a pte mask. */
-
-#ifndef __ASSEMBLY__
-
-typedef u32 intpte_32_t;
-
-typedef struct { intpte_32_t l1; } l1_pgentry_32_t;
-typedef struct { intpte_32_t l2; } l2_pgentry_32_t;
-typedef l2_pgentry_t root_pgentry_32_t;
-#endif
-
-#define get_pte_flags_32(x) ((u32)(x) & 0xFFF)
-#define put_pte_flags_32(x) ((intpte_32_t)(x))
-
-/* Get pte access flags (unsigned int). */
-#define l1e_get_flags_32(x) (get_pte_flags_32((x).l1))
-#define l2e_get_flags_32(x) (get_pte_flags_32((x).l2))
-
-#define l1e_get_paddr_32(x) \
- ((paddr_t)(((x).l1 & (PADDR_MASK&PAGE_MASK))))
-#define l2e_get_paddr_32(x) \
- ((paddr_t)(((x).l2 & (PADDR_MASK&PAGE_MASK))))
-
-/* Construct an empty pte. */
-#define l1e_empty_32() ((l1_pgentry_32_t) { 0 })
-#define l2e_empty_32() ((l2_pgentry_32_t) { 0 })
-
-/* Construct a pte from a pfn and access flags. */
-#define l1e_from_pfn_32(pfn, flags) \
- ((l1_pgentry_32_t) { ((intpte_32_t)(pfn) << PAGE_SHIFT) |
put_pte_flags_32(flags) })
-#define l2e_from_pfn_32(pfn, flags) \
- ((l2_pgentry_32_t) { ((intpte_32_t)(pfn) << PAGE_SHIFT) |
put_pte_flags_32(flags) })
-
-/* Construct a pte from a physical address and access flags. */
-#ifndef __ASSEMBLY__
-static inline l1_pgentry_32_t l1e_from_paddr_32(paddr_t pa, unsigned int flags)
-{
- ASSERT((pa & ~(PADDR_MASK & PAGE_MASK)) == 0);
- return (l1_pgentry_32_t) { pa | put_pte_flags_32(flags) };
-}
-static inline l2_pgentry_32_t l2e_from_paddr_32(paddr_t pa, unsigned int flags)
-{
- ASSERT((pa & ~(PADDR_MASK & PAGE_MASK)) == 0);
- return (l2_pgentry_32_t) { pa | put_pte_flags_32(flags) };
-}
-#endif /* !__ASSEMBLY__ */
-
-
-/* Construct a pte from a page pointer and access flags. */
-#define l1e_from_page_32(page, flags)
(l1e_from_pfn_32(page_to_mfn(page),(flags)))
-#define l2e_from_page_32(page, flags)
(l2e_from_pfn_32(page_to_mfn(page),(flags)))
-
-/* Add extra flags to an existing pte. */
-#define l1e_add_flags_32(x, flags) ((x).l1 |= put_pte_flags_32(flags))
-#define l2e_add_flags_32(x, flags) ((x).l2 |= put_pte_flags_32(flags))
-
-/* Remove flags from an existing pte. */
-#define l1e_remove_flags_32(x, flags) ((x).l1 &= ~put_pte_flags_32(flags))
-#define l2e_remove_flags_32(x, flags) ((x).l2 &= ~put_pte_flags_32(flags))
-
-/* Check if a pte's page mapping or significant access flags have changed. */
-#define l1e_has_changed_32(x,y,flags) \
- ( !!(((x).l1 ^ (y).l1) & ((PADDR_MASK&PAGE_MASK)|put_pte_flags_32(flags)))
)
-#define l2e_has_changed_32(x,y,flags) \
- ( !!(((x).l2 ^ (y).l2) & ((PADDR_MASK&PAGE_MASK)|put_pte_flags_32(flags)))
)
-
-/* Given a virtual address, get an entry offset into a page table. */
-#define l1_table_offset_32(a) \
- (((a) >> L1_PAGETABLE_SHIFT_32) & (L1_PAGETABLE_ENTRIES_32 - 1))
-#define l2_table_offset_32(a) \
- (((a) >> L2_PAGETABLE_SHIFT_32) & (L2_PAGETABLE_ENTRIES_32 - 1))
-
-#endif /* __X86_PAGE_GUEST_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/mm/shadow/types.h
--- a/xen/arch/x86/mm/shadow/types.h Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/x86/mm/shadow/types.h Mon Mar 12 10:07:08 2007 -0600
@@ -235,7 +235,7 @@ static inline shadow_l4e_t shadow_l4e_fr
#if GUEST_PAGING_LEVELS == 2
-#include "page-guest32.h"
+#include "../page-guest32.h"
#define GUEST_L1_PAGETABLE_ENTRIES 1024
#define GUEST_L2_PAGETABLE_ENTRIES 1024
diff -r d1853a39e063 -r cb2575cec95c xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/arch/x86/setup.c Mon Mar 12 10:07:08 2007 -0600
@@ -195,13 +195,13 @@ static void __init percpu_free_unused_ar
/* Find first unused CPU number. */
for ( i = 0; i < NR_CPUS; i++ )
- if ( !cpu_online(i) )
+ if ( !cpu_possible(i) )
break;
first_unused = i;
- /* Check that there are no holes in cpu_online_map. */
+ /* Check that there are no holes in cpu_possible_map. */
for ( ; i < NR_CPUS; i++ )
- BUG_ON(cpu_online(i));
+ BUG_ON(cpu_possible(i));
#ifndef MEMORY_GUARD
init_xenheap_pages(__pa(__per_cpu_start) + (first_unused << PERCPU_SHIFT),
@@ -717,8 +717,6 @@ void __init __start_xen(multiboot_info_t
do_initcalls();
- schedulers_start();
-
if ( opt_watchdog )
watchdog_enable();
diff -r d1853a39e063 -r cb2575cec95c xen/common/compat/domain.c
--- a/xen/common/compat/domain.c Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/common/compat/domain.c Mon Mar 12 10:07:08 2007 -0600
@@ -55,6 +55,10 @@ int compat_vcpu_op(int cmd, int vcpuid,
case VCPUOP_up:
case VCPUOP_down:
case VCPUOP_is_up:
+ case VCPUOP_set_periodic_timer:
+ case VCPUOP_stop_periodic_timer:
+ case VCPUOP_set_singleshot_timer:
+ case VCPUOP_stop_singleshot_timer:
rc = do_vcpu_op(cmd, vcpuid, arg);
break;
diff -r d1853a39e063 -r cb2575cec95c xen/common/domain.c
--- a/xen/common/domain.c Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/common/domain.c Mon Mar 12 10:07:08 2007 -0600
@@ -267,6 +267,9 @@ void domain_kill(struct domain *d)
domain_relinquish_resources(d);
put_domain(d);
+ /* Kick page scrubbing after domain_relinquish_resources(). */
+ page_scrub_kick();
+
send_guest_global_virq(dom0, VIRQ_DOM_EXC);
}
@@ -543,16 +546,12 @@ long do_vcpu_op(int cmd, int vcpuid, XEN
{
case VCPUOP_initialise:
if ( (ctxt = xmalloc(struct vcpu_guest_context)) == NULL )
- {
- rc = -ENOMEM;
- break;
- }
+ return -ENOMEM;
if ( copy_from_guest(ctxt, arg, 1) )
{
xfree(ctxt);
- rc = -EFAULT;
- break;
+ return -EFAULT;
}
LOCK_BIGLOCK(d);
@@ -566,9 +565,11 @@ long do_vcpu_op(int cmd, int vcpuid, XEN
case VCPUOP_up:
if ( !test_bit(_VCPUF_initialised, &v->vcpu_flags) )
- rc = -EINVAL;
- else if ( test_and_clear_bit(_VCPUF_down, &v->vcpu_flags) )
+ return -EINVAL;
+
+ if ( test_and_clear_bit(_VCPUF_down, &v->vcpu_flags) )
vcpu_wake(v);
+
break;
case VCPUOP_down:
@@ -586,6 +587,63 @@ long do_vcpu_op(int cmd, int vcpuid, XEN
vcpu_runstate_get(v, &runstate);
if ( copy_to_guest(arg, &runstate, 1) )
rc = -EFAULT;
+ break;
+ }
+
+ case VCPUOP_set_periodic_timer:
+ {
+ struct vcpu_set_periodic_timer set;
+
+ if ( copy_from_guest(&set, arg, 1) )
+ return -EFAULT;
+
+ if ( set.period_ns < MILLISECS(1) )
+ return -EINVAL;
+
+ v->periodic_period = set.period_ns;
+ vcpu_force_reschedule(v);
+
+ break;
+ }
+
+ case VCPUOP_stop_periodic_timer:
+ {
+ v->periodic_period = 0;
+ vcpu_force_reschedule(v);
+ break;
+ }
+
+ case VCPUOP_set_singleshot_timer:
+ {
+ struct vcpu_set_singleshot_timer set;
+
+ if ( v != current )
+ return -EINVAL;
+
+ if ( copy_from_guest(&set, arg, 1) )
+ return -EFAULT;
+
+ if ( (set.flags & VCPU_SSHOTTMR_future) &&
+ (set.timeout_abs_ns < NOW()) )
+ return -ETIME;
+
+ if ( v->singleshot_timer.cpu != smp_processor_id() )
+ {
+ stop_timer(&v->singleshot_timer);
+ v->singleshot_timer.cpu = smp_processor_id();
+ }
+
+ set_timer(&v->singleshot_timer, set.timeout_abs_ns);
+
+ break;
+ }
+
+ case VCPUOP_stop_singleshot_timer:
+ {
+ if ( v != current )
+ return -EINVAL;
+
+ stop_timer(&v->singleshot_timer);
break;
}
diff -r d1853a39e063 -r cb2575cec95c xen/common/event_channel.c
--- a/xen/common/event_channel.c Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/common/event_channel.c Mon Mar 12 10:07:08 2007 -0600
@@ -560,6 +560,9 @@ void send_guest_global_virq(struct domai
ASSERT(virq_is_global(virq));
+ if ( unlikely(d == NULL) )
+ return;
+
v = d->vcpu[0];
if ( unlikely(v == NULL) )
return;
diff -r d1853a39e063 -r cb2575cec95c xen/common/keyhandler.c
--- a/xen/common/keyhandler.c Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/common/keyhandler.c Mon Mar 12 10:07:08 2007 -0600
@@ -47,7 +47,7 @@ void handle_keypress(unsigned char key,
{
irq_keyhandler_t *h;
- if ( key_table[key].flags & KEYHANDLER_IRQ_CALLBACK )
+ if ( !in_irq() || (key_table[key].flags & KEYHANDLER_IRQ_CALLBACK) )
{
console_start_log_everything();
if ( (h = key_table[key].u.irq_handler) != NULL )
@@ -135,12 +135,25 @@ static void cpuset_print(char *set, int
*set++ = '\0';
}
+static void periodic_timer_print(char *str, int size, uint64_t period)
+{
+ if ( period == 0 )
+ {
+ strlcpy(str, "No periodic timer", size);
+ return;
+ }
+
+ snprintf(str, size,
+ "%u Hz periodic timer (period %u ms)",
+ 1000000000/(int)period, (int)period/1000000);
+}
+
static void dump_domains(unsigned char key)
{
struct domain *d;
struct vcpu *v;
s_time_t now = NOW();
- char cpuset[100];
+ char tmpstr[100];
printk("'%c' pressed -> dumping domain info (now=0x%X:%08X)\n", key,
(u32)(now>>32), (u32)now);
@@ -150,11 +163,11 @@ static void dump_domains(unsigned char k
for_each_domain ( d )
{
printk("General information for domain %u:\n", d->domain_id);
- cpuset_print(cpuset, sizeof(cpuset), d->domain_dirty_cpumask);
+ cpuset_print(tmpstr, sizeof(tmpstr), d->domain_dirty_cpumask);
printk(" flags=%lx refcnt=%d nr_pages=%d xenheap_pages=%d "
"dirty_cpus=%s\n",
d->domain_flags, atomic_read(&d->refcnt),
- d->tot_pages, d->xenheap_pages, cpuset);
+ d->tot_pages, d->xenheap_pages, tmpstr);
printk(" handle=%02x%02x%02x%02x-%02x%02x-%02x%02x-"
"%02x%02x-%02x%02x%02x%02x%02x%02x vm_assist=%08lx\n",
d->handle[ 0], d->handle[ 1], d->handle[ 2], d->handle[ 3],
@@ -179,18 +192,21 @@ static void dump_domains(unsigned char k
v->vcpu_flags,
vcpu_info(v, evtchn_upcall_pending),
vcpu_info(v, evtchn_upcall_mask));
- cpuset_print(cpuset, sizeof(cpuset), v->vcpu_dirty_cpumask);
- printk("dirty_cpus=%s ", cpuset);
- cpuset_print(cpuset, sizeof(cpuset), v->cpu_affinity);
- printk("cpu_affinity=%s\n", cpuset);
+ cpuset_print(tmpstr, sizeof(tmpstr), v->vcpu_dirty_cpumask);
+ printk("dirty_cpus=%s ", tmpstr);
+ cpuset_print(tmpstr, sizeof(tmpstr), v->cpu_affinity);
+ printk("cpu_affinity=%s\n", tmpstr);
arch_dump_vcpu_info(v);
+ periodic_timer_print(tmpstr, sizeof(tmpstr), v->periodic_period);
+ printk(" %s\n", tmpstr);
printk(" Notifying guest (virq %d, port %d, stat %d/%d/%d)\n",
VIRQ_DEBUG, v->virq_to_evtchn[VIRQ_DEBUG],
test_bit(v->virq_to_evtchn[VIRQ_DEBUG],
shared_info_addr(d, evtchn_pending)),
test_bit(v->virq_to_evtchn[VIRQ_DEBUG],
shared_info_addr(d, evtchn_mask)),
-
test_bit(v->virq_to_evtchn[VIRQ_DEBUG]/BITS_PER_GUEST_LONG(d),
+ test_bit(v->virq_to_evtchn[VIRQ_DEBUG] /
+ BITS_PER_GUEST_LONG(d),
vcpu_info_addr(v, evtchn_pending_sel)));
send_guest_vcpu_virq(v, VIRQ_DEBUG);
}
diff -r d1853a39e063 -r cb2575cec95c xen/common/page_alloc.c
--- a/xen/common/page_alloc.c Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/common/page_alloc.c Mon Mar 12 10:07:08 2007 -0600
@@ -49,7 +49,7 @@ string_param("badpage", opt_badpage);
* Bit width of the DMA heap.
*/
static unsigned int dma_bitsize = CONFIG_DMA_BITSIZE;
-static unsigned long max_dma_mfn = (1UL << (CONFIG_DMA_BITSIZE - PAGE_SHIFT))
- 1;
+static unsigned long max_dma_mfn = (1UL<<(CONFIG_DMA_BITSIZE-PAGE_SHIFT))-1;
static void parse_dma_bits(char *s)
{
unsigned int v = simple_strtol(s, NULL, 0);
@@ -345,6 +345,7 @@ static struct page_info *alloc_heap_page
unsigned int i, j, zone;
unsigned int node = cpu_to_node(cpu), num_nodes = num_online_nodes();
unsigned long request = 1UL << order;
+ cpumask_t extra_cpus_mask, mask;
struct page_info *pg;
ASSERT(node >= 0);
@@ -403,6 +404,29 @@ static struct page_info *alloc_heap_page
spin_unlock(&heap_lock);
+ cpus_clear(mask);
+
+ for ( i = 0; i < (1 << order); i++ )
+ {
+ /* Reference count must continuously be zero for free pages. */
+ BUG_ON(pg[i].count_info != 0);
+
+ /* Add in any extra CPUs that need flushing because of this page. */
+ cpus_andnot(extra_cpus_mask, pg[i].u.free.cpumask, mask);
+ tlbflush_filter(extra_cpus_mask, pg[i].tlbflush_timestamp);
+ cpus_or(mask, mask, extra_cpus_mask);
+
+ /* Initialise fields which have other uses for free pages. */
+ pg[i].u.inuse.type_info = 0;
+ page_set_owner(&pg[i], NULL);
+ }
+
+ if ( unlikely(!cpus_empty(mask)) )
+ {
+ perfc_incrc(need_flush_tlb_flush);
+ flush_tlb_mask(mask);
+ }
+
return pg;
}
@@ -411,12 +435,27 @@ static void free_heap_pages(
unsigned int zone, struct page_info *pg, unsigned int order)
{
unsigned long mask;
- unsigned int node = phys_to_nid(page_to_maddr(pg));
+ unsigned int i, node = phys_to_nid(page_to_maddr(pg));
+ struct domain *d;
ASSERT(zone < NR_ZONES);
ASSERT(order <= MAX_ORDER);
ASSERT(node >= 0);
ASSERT(node < num_online_nodes());
+
+ for ( i = 0; i < (1 << order); i++ )
+ {
+ BUG_ON(pg[i].count_info != 0);
+ if ( (d = page_get_owner(&pg[i])) != NULL )
+ {
+ pg[i].tlbflush_timestamp = tlbflush_current_time();
+ pg[i].u.free.cpumask = d->domain_dirty_cpumask;
+ }
+ else
+ {
+ cpus_clear(pg[i].u.free.cpumask);
+ }
+ }
spin_lock(&heap_lock);
@@ -554,7 +593,7 @@ void end_boot_allocator(void)
/*
* Scrub all unallocated pages in all heap zones. This function is more
* convoluted than appears necessary because we do not want to continuously
- * hold the lock or disable interrupts while scrubbing very large memory areas.
+ * hold the lock while scrubbing very large memory areas.
*/
void scrub_heap_pages(void)
{
@@ -575,7 +614,7 @@ void scrub_heap_pages(void)
if ( (mfn % ((100*1024*1024)/PAGE_SIZE)) == 0 )
printk(".");
- spin_lock_irq(&heap_lock);
+ spin_lock(&heap_lock);
/* Re-check page status with lock held. */
if ( !allocated_in_map(mfn) )
@@ -595,7 +634,7 @@ void scrub_heap_pages(void)
}
}
- spin_unlock_irq(&heap_lock);
+ spin_unlock(&heap_lock);
}
printk("done.\n");
@@ -609,8 +648,6 @@ void scrub_heap_pages(void)
void init_xenheap_pages(paddr_t ps, paddr_t pe)
{
- unsigned long flags;
-
ps = round_pgup(ps);
pe = round_pgdown(pe);
if ( pe <= ps )
@@ -625,33 +662,21 @@ void init_xenheap_pages(paddr_t ps, padd
if ( !IS_XEN_HEAP_FRAME(maddr_to_page(pe)) )
pe -= PAGE_SIZE;
- local_irq_save(flags);
init_heap_pages(MEMZONE_XEN, maddr_to_page(ps), (pe - ps) >> PAGE_SHIFT);
- local_irq_restore(flags);
}
void *alloc_xenheap_pages(unsigned int order)
{
- unsigned long flags;
struct page_info *pg;
- int i;
-
- local_irq_save(flags);
+
+ ASSERT(!in_irq());
+
pg = alloc_heap_pages(MEMZONE_XEN, MEMZONE_XEN, smp_processor_id(), order);
- local_irq_restore(flags);
-
if ( unlikely(pg == NULL) )
goto no_memory;
memguard_unguard_range(page_to_virt(pg), 1 << (order + PAGE_SHIFT));
-
- for ( i = 0; i < (1 << order); i++ )
- {
- pg[i].count_info = 0;
- pg[i].u.inuse._domain = 0;
- pg[i].u.inuse.type_info = 0;
- }
return page_to_virt(pg);
@@ -663,16 +688,14 @@ void *alloc_xenheap_pages(unsigned int o
void free_xenheap_pages(void *v, unsigned int order)
{
- unsigned long flags;
+ ASSERT(!in_irq());
if ( v == NULL )
return;
- memguard_guard_range(v, 1 << (order + PAGE_SHIFT));
-
- local_irq_save(flags);
+ memguard_guard_range(v, 1 << (order + PAGE_SHIFT));
+
free_heap_pages(MEMZONE_XEN, virt_to_page(v), order);
- local_irq_restore(flags);
}
@@ -762,8 +785,6 @@ struct page_info *__alloc_domheap_pages(
unsigned int memflags)
{
struct page_info *pg = NULL;
- cpumask_t mask;
- unsigned long i;
unsigned int bits = memflags >> _MEMF_bits, zone_hi = NR_ZONES - 1;
ASSERT(!in_irq());
@@ -792,38 +813,10 @@ struct page_info *__alloc_domheap_pages(
return NULL;
}
- if ( pg == NULL )
- if ( (pg = alloc_heap_pages(MEMZONE_XEN + 1,
- zone_hi,
- cpu, order)) == NULL )
- return NULL;
-
- mask = pg->u.free.cpumask;
- tlbflush_filter(mask, pg->tlbflush_timestamp);
-
- pg->count_info = 0;
- pg->u.inuse._domain = 0;
- pg->u.inuse.type_info = 0;
-
- for ( i = 1; i < (1 << order); i++ )
- {
- /* Add in any extra CPUs that need flushing because of this page. */
- cpumask_t extra_cpus_mask;
- cpus_andnot(extra_cpus_mask, pg[i].u.free.cpumask, mask);
- tlbflush_filter(extra_cpus_mask, pg[i].tlbflush_timestamp);
- cpus_or(mask, mask, extra_cpus_mask);
-
- pg[i].count_info = 0;
- pg[i].u.inuse._domain = 0;
- pg[i].u.inuse.type_info = 0;
- page_set_owner(&pg[i], NULL);
- }
-
- if ( unlikely(!cpus_empty(mask)) )
- {
- perfc_incrc(need_flush_tlb_flush);
- flush_tlb_mask(mask);
- }
+ if ( (pg == NULL) &&
+ ((pg = alloc_heap_pages(MEMZONE_XEN + 1, zone_hi,
+ cpu, order)) == NULL) )
+ return NULL;
if ( (d != NULL) && assign_pages(d, pg, order, memflags) )
{
@@ -867,10 +860,7 @@ void free_domheap_pages(struct page_info
for ( i = 0; i < (1 << order); i++ )
{
- shadow_drop_references(d, &pg[i]);
- ASSERT((pg[i].u.inuse.type_info & PGT_count_mask) == 0);
- pg[i].tlbflush_timestamp = tlbflush_current_time();
- pg[i].u.free.cpumask = d->domain_dirty_cpumask;
+ BUG_ON((pg[i].u.inuse.type_info & PGT_count_mask) != 0);
list_del(&pg[i].list);
}
@@ -892,6 +882,7 @@ void free_domheap_pages(struct page_info
*/
for ( i = 0; i < (1 << order); i++ )
{
+ page_set_owner(&pg[i], NULL);
spin_lock(&page_scrub_lock);
list_add(&pg[i].list, &page_scrub_list);
scrub_pages++;
@@ -902,8 +893,6 @@ void free_domheap_pages(struct page_info
else
{
/* Freeing anonymous domain-heap pages. */
- for ( i = 0; i < (1 << order); i++ )
- cpus_clear(pg[i].u.free.cpumask);
free_heap_pages(pfn_dom_zone_type(page_to_mfn(pg)), pg, order);
drop_dom_ref = 0;
}
@@ -981,6 +970,8 @@ __initcall(pagealloc_keyhandler_init);
* PAGE SCRUBBING
*/
+static DEFINE_PER_CPU(struct timer, page_scrub_timer);
+
static void page_scrub_softirq(void)
{
struct list_head *ent;
@@ -989,7 +980,7 @@ static void page_scrub_softirq(void)
int i;
s_time_t start = NOW();
- /* Aim to do 1ms of work (ten percent of a 10ms jiffy). */
+ /* Aim to do 1ms of work every 10ms. */
do {
spin_lock(&page_scrub_lock);
@@ -1025,6 +1016,13 @@ static void page_scrub_softirq(void)
free_heap_pages(pfn_dom_zone_type(page_to_mfn(pg)), pg, 0);
}
} while ( (NOW() - start) < MILLISECS(1) );
+
+ set_timer(&this_cpu(page_scrub_timer), NOW() + MILLISECS(10));
+}
+
+static void page_scrub_timer_fn(void *unused)
+{
+ page_scrub_schedule_work();
}
unsigned long avail_scrub_pages(void)
@@ -1060,6 +1058,10 @@ __initcall(register_heap_trigger);
static __init int page_scrub_init(void)
{
+ int cpu;
+ for_each_cpu ( cpu )
+ init_timer(&per_cpu(page_scrub_timer, cpu),
+ page_scrub_timer_fn, NULL, cpu);
open_softirq(PAGE_SCRUB_SOFTIRQ, page_scrub_softirq);
return 0;
}
diff -r d1853a39e063 -r cb2575cec95c xen/common/sched_credit.c
--- a/xen/common/sched_credit.c Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/common/sched_credit.c Mon Mar 12 10:07:08 2007 -0600
@@ -186,6 +186,8 @@ struct csched_pcpu {
struct csched_pcpu {
struct list_head runq;
uint32_t runq_sort_last;
+ struct timer ticker;
+ unsigned int tick;
};
/*
@@ -245,7 +247,7 @@ struct csched_private {
*/
static struct csched_private csched_priv;
-
+static void csched_tick(void *_cpu);
static inline int
__cycle_cpu(int cpu, const cpumask_t *mask)
@@ -362,12 +364,13 @@ csched_pcpu_init(int cpu)
if ( csched_priv.master >= csched_priv.ncpus )
csched_priv.master = cpu;
+ init_timer(&spc->ticker, csched_tick, (void *)(unsigned long)cpu, cpu);
INIT_LIST_HEAD(&spc->runq);
spc->runq_sort_last = csched_priv.runq_sort;
per_cpu(schedule_data, cpu).sched_priv = spc;
/* Start off idling... */
- BUG_ON( !is_idle_vcpu(per_cpu(schedule_data, cpu).curr) );
+ BUG_ON(!is_idle_vcpu(per_cpu(schedule_data, cpu).curr));
cpu_set(cpu, csched_priv.idlers);
spin_unlock_irqrestore(&csched_priv.lock, flags);
@@ -1013,8 +1016,13 @@ csched_acct(void)
}
static void
-csched_tick(unsigned int cpu)
-{
+csched_tick(void *_cpu)
+{
+ unsigned int cpu = (unsigned long)_cpu;
+ struct csched_pcpu *spc = CSCHED_PCPU(cpu);
+
+ spc->tick++;
+
/*
* Accounting for running VCPU
*/
@@ -1028,7 +1036,7 @@ csched_tick(unsigned int cpu)
* we could distribute or at the very least cycle the duty.
*/
if ( (csched_priv.master == cpu) &&
- (per_cpu(schedule_data, cpu).tick % CSCHED_TICKS_PER_ACCT) == 0 )
+ (spc->tick % CSCHED_TICKS_PER_ACCT) == 0 )
{
csched_acct();
}
@@ -1041,6 +1049,8 @@ csched_tick(unsigned int cpu)
* once per accounting period (currently 30 milliseconds).
*/
csched_runq_sort(cpu);
+
+ set_timer(&spc->ticker, NOW() + MILLISECS(CSCHED_MSECS_PER_TICK));
}
static struct csched_vcpu *
@@ -1248,8 +1258,7 @@ csched_dump_pcpu(int cpu)
spc = CSCHED_PCPU(cpu);
runq = &spc->runq;
- printk(" tick=%lu, sort=%d, sibling=0x%lx, core=0x%lx\n",
- per_cpu(schedule_data, cpu).tick,
+ printk(" sort=%d, sibling=0x%lx, core=0x%lx\n",
spc->runq_sort_last,
cpu_sibling_map[cpu].bits[0],
cpu_core_map[cpu].bits[0]);
@@ -1341,6 +1350,22 @@ csched_init(void)
CSCHED_STATS_RESET();
}
+/* Tickers cannot be kicked until SMP subsystem is alive. */
+static __init int csched_start_tickers(void)
+{
+ struct csched_pcpu *spc;
+ unsigned int cpu;
+
+ for_each_online_cpu ( cpu )
+ {
+ spc = CSCHED_PCPU(cpu);
+ set_timer(&spc->ticker, NOW() + MILLISECS(CSCHED_MSECS_PER_TICK));
+ }
+
+ return 0;
+}
+__initcall(csched_start_tickers);
+
struct scheduler sched_credit_def = {
.name = "SMP Credit Scheduler",
@@ -1359,7 +1384,6 @@ struct scheduler sched_credit_def = {
.adjust = csched_dom_cntl,
.pick_cpu = csched_cpu_pick,
- .tick = csched_tick,
.do_schedule = csched_schedule,
.dump_cpu_state = csched_dump_pcpu,
diff -r d1853a39e063 -r cb2575cec95c xen/common/schedule.c
--- a/xen/common/schedule.c Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/common/schedule.c Mon Mar 12 10:07:08 2007 -0600
@@ -45,8 +45,8 @@ boolean_param("dom0_vcpus_pin", opt_dom0
/* Various timer handlers. */
static void s_timer_fn(void *unused);
-static void t_timer_fn(void *unused);
-static void vcpu_timer_fn(void *data);
+static void vcpu_periodic_timer_fn(void *data);
+static void vcpu_singleshot_timer_fn(void *data);
static void poll_timer_fn(void *data);
/* This is global for now so that private implementations can reach it */
@@ -65,9 +65,6 @@ static struct scheduler ops;
#define SCHED_OP(fn, ...) \
(( ops.fn != NULL ) ? ops.fn( __VA_ARGS__ ) \
: (typeof(ops.fn(__VA_ARGS__)))0 )
-
-/* Per-CPU periodic timer sends an event to the currently-executing domain. */
-static DEFINE_PER_CPU(struct timer, t_timer);
static inline void vcpu_runstate_change(
struct vcpu *v, int new_state, s_time_t new_entry_time)
@@ -113,9 +110,13 @@ int sched_init_vcpu(struct vcpu *v, unsi
else
cpus_setall(v->cpu_affinity);
- /* Initialise the per-domain timers. */
- init_timer(&v->timer, vcpu_timer_fn, v, v->processor);
- init_timer(&v->poll_timer, poll_timer_fn, v, v->processor);
+ /* Initialise the per-vcpu timers. */
+ init_timer(&v->periodic_timer, vcpu_periodic_timer_fn,
+ v, v->processor);
+ init_timer(&v->singleshot_timer, vcpu_singleshot_timer_fn,
+ v, v->processor);
+ init_timer(&v->poll_timer, poll_timer_fn,
+ v, v->processor);
/* Idle VCPUs are scheduled immediately. */
if ( is_idle_domain(d) )
@@ -132,7 +133,8 @@ int sched_init_vcpu(struct vcpu *v, unsi
void sched_destroy_vcpu(struct vcpu *v)
{
- kill_timer(&v->timer);
+ kill_timer(&v->periodic_timer);
+ kill_timer(&v->singleshot_timer);
kill_timer(&v->poll_timer);
SCHED_OP(destroy_vcpu, v);
}
@@ -223,10 +225,29 @@ static void vcpu_migrate(struct vcpu *v)
vcpu_wake(v);
}
+/*
+ * Force a VCPU through a deschedule/reschedule path.
+ * For example, using this when setting the periodic timer period means that
+ * most periodic-timer state need only be touched from within the scheduler
+ * which can thus be done without need for synchronisation.
+ */
+void vcpu_force_reschedule(struct vcpu *v)
+{
+ vcpu_schedule_lock_irq(v);
+ if ( test_bit(_VCPUF_running, &v->vcpu_flags) )
+ set_bit(_VCPUF_migrating, &v->vcpu_flags);
+ vcpu_schedule_unlock_irq(v);
+
+ if ( test_bit(_VCPUF_migrating, &v->vcpu_flags) )
+ {
+ vcpu_sleep_nosync(v);
+ vcpu_migrate(v);
+ }
+}
+
int vcpu_set_affinity(struct vcpu *v, cpumask_t *affinity)
{
cpumask_t online_affinity;
- unsigned long flags;
if ( (v->domain->domain_id == 0) && opt_dom0_vcpus_pin )
return -EINVAL;
@@ -235,13 +256,13 @@ int vcpu_set_affinity(struct vcpu *v, cp
if ( cpus_empty(online_affinity) )
return -EINVAL;
- vcpu_schedule_lock_irqsave(v, flags);
+ vcpu_schedule_lock_irq(v);
v->cpu_affinity = *affinity;
if ( !cpu_isset(v->processor, v->cpu_affinity) )
set_bit(_VCPUF_migrating, &v->vcpu_flags);
- vcpu_schedule_unlock_irqrestore(v, flags);
+ vcpu_schedule_unlock_irq(v);
if ( test_bit(_VCPUF_migrating, &v->vcpu_flags) )
{
@@ -450,7 +471,7 @@ ret_t do_sched_op(int cmd, XEN_GUEST_HAN
#ifndef COMPAT
-/* Per-domain one-shot-timer hypercall. */
+/* Per-vcpu oneshot-timer hypercall. */
long do_set_timer_op(s_time_t timeout)
{
struct vcpu *v = current;
@@ -458,7 +479,7 @@ long do_set_timer_op(s_time_t timeout)
if ( timeout == 0 )
{
- stop_timer(&v->timer);
+ stop_timer(&v->singleshot_timer);
}
else if ( unlikely(timeout < 0) || /* overflow into 64th bit? */
unlikely((offset > 0) && ((uint32_t)(offset >> 50) != 0)) )
@@ -474,14 +495,20 @@ long do_set_timer_op(s_time_t timeout)
* timeout in this case can burn a lot of CPU. We therefore go for a
* reasonable middleground of triggering a timer event in 100ms.
*/
- gdprintk(XENLOG_INFO, "Warning: huge timeout set by domain %d (vcpu
%d):"
- " %"PRIx64"\n",
+ gdprintk(XENLOG_INFO, "Warning: huge timeout set by domain %d "
+ "(vcpu %d): %"PRIx64"\n",
v->domain->domain_id, v->vcpu_id, (uint64_t)timeout);
- set_timer(&v->timer, NOW() + MILLISECS(100));
+ set_timer(&v->singleshot_timer, NOW() + MILLISECS(100));
}
else
{
- set_timer(&v->timer, timeout);
+ if ( v->singleshot_timer.cpu != smp_processor_id() )
+ {
+ stop_timer(&v->singleshot_timer);
+ v->singleshot_timer.cpu = smp_processor_id();
+ }
+
+ set_timer(&v->singleshot_timer, timeout);
}
return 0;
@@ -540,6 +567,28 @@ long sched_adjust(struct domain *d, stru
return 0;
}
+static void vcpu_periodic_timer_work(struct vcpu *v)
+{
+ s_time_t now = NOW();
+ uint64_t periodic_next_event;
+
+ ASSERT(!active_timer(&v->periodic_timer));
+
+ if ( v->periodic_period == 0 )
+ return;
+
+ periodic_next_event = v->periodic_last_event + v->periodic_period;
+ if ( now > periodic_next_event )
+ {
+ send_timer_event(v);
+ v->periodic_last_event = now;
+ periodic_next_event = now + v->periodic_period;
+ }
+
+ v->periodic_timer.cpu = smp_processor_id();
+ set_timer(&v->periodic_timer, periodic_next_event);
+}
+
/*
* The main function
* - deschedule the current domain (scheduler independent).
@@ -606,14 +655,13 @@ static void schedule(void)
perfc_incrc(sched_ctx);
- prev->sleep_tick = sd->tick;
+ stop_timer(&prev->periodic_timer);
/* Ensure that the domain has an up-to-date time base. */
if ( !is_idle_vcpu(next) )
{
update_vcpu_system_time(next);
- if ( next->sleep_tick != sd->tick )
- send_timer_event(next);
+ vcpu_periodic_timer_work(next);
}
TRACE_4D(TRC_SCHED_SWITCH,
@@ -631,13 +679,6 @@ void context_saved(struct vcpu *prev)
vcpu_migrate(prev);
}
-/****************************************************************************
- * Timers: the scheduler utilises a number of timers
- * - s_timer: per CPU timer for preemption and scheduling decisions
- * - t_timer: per CPU periodic timer to send timer interrupt to current dom
- * - dom_timer: per domain timer to specifiy timeout values
- ****************************************************************************/
-
/* The scheduler timer: force a run through the scheduler */
static void s_timer_fn(void *unused)
{
@@ -645,28 +686,15 @@ static void s_timer_fn(void *unused)
perfc_incrc(sched_irq);
}
-/* Periodic tick timer: send timer event to current domain */
-static void t_timer_fn(void *unused)
-{
- struct vcpu *v = current;
-
- this_cpu(schedule_data).tick++;
-
- if ( !is_idle_vcpu(v) )
- {
- update_vcpu_system_time(v);
- send_timer_event(v);
- }
-
- page_scrub_schedule_work();
-
- SCHED_OP(tick, smp_processor_id());
-
- set_timer(&this_cpu(t_timer), NOW() + MILLISECS(10));
-}
-
-/* Per-VCPU timer function: sends a virtual timer interrupt. */
-static void vcpu_timer_fn(void *data)
+/* Per-VCPU periodic timer function: sends a virtual timer interrupt. */
+static void vcpu_periodic_timer_fn(void *data)
+{
+ struct vcpu *v = data;
+ vcpu_periodic_timer_work(v);
+}
+
+/* Per-VCPU single-shot timer function: sends a virtual timer interrupt. */
+static void vcpu_singleshot_timer_fn(void *data)
{
struct vcpu *v = data;
send_timer_event(v);
@@ -691,7 +719,6 @@ void __init scheduler_init(void)
{
spin_lock_init(&per_cpu(schedule_data, i).schedule_lock);
init_timer(&per_cpu(schedule_data, i).s_timer, s_timer_fn, NULL, i);
- init_timer(&per_cpu(t_timer, i), t_timer_fn, NULL, i);
}
for ( i = 0; schedulers[i] != NULL; i++ )
@@ -706,16 +733,6 @@ void __init scheduler_init(void)
printk("Using scheduler: %s (%s)\n", ops.name, ops.opt_name);
SCHED_OP(init);
-}
-
-/*
- * Start a scheduler for each CPU
- * This has to be done *after* the timers, e.g., APICs, have been initialised
- */
-void schedulers_start(void)
-{
- t_timer_fn(0);
- smp_call_function((void *)t_timer_fn, NULL, 1, 1);
}
void dump_runq(unsigned char key)
diff -r d1853a39e063 -r cb2575cec95c xen/common/sysctl.c
--- a/xen/common/sysctl.c Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/common/sysctl.c Mon Mar 12 10:07:08 2007 -0600
@@ -18,6 +18,7 @@
#include <xen/console.h>
#include <xen/iocap.h>
#include <xen/guest_access.h>
+#include <xen/keyhandler.h>
#include <asm/current.h>
#include <public/sysctl.h>
@@ -121,6 +122,20 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysc
break;
#endif
+ case XEN_SYSCTL_debug_keys:
+ {
+ char c;
+ uint32_t i;
+
+ for ( i = 0; i < op->u.debug_keys.nr_keys; i++ )
+ {
+ if ( copy_from_guest_offset(&c, op->u.debug_keys.keys, i, 1) )
+ return -EFAULT;
+ handle_keypress(c, guest_cpu_user_regs());
+ }
+ }
+ break;
+
default:
ret = arch_do_sysctl(op, u_sysctl);
break;
diff -r d1853a39e063 -r cb2575cec95c xen/common/xmalloc.c
--- a/xen/common/xmalloc.c Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/common/xmalloc.c Mon Mar 12 10:07:08 2007 -0600
@@ -33,6 +33,8 @@
#include <xen/timer.h>
#include <xen/cache.h>
#include <xen/prefetch.h>
+#include <xen/irq.h>
+#include <xen/smp.h>
/*
* XMALLOC_DEBUG:
@@ -175,6 +177,8 @@ void *_xmalloc(size_t size, size_t align
struct xmalloc_hdr *i;
unsigned long flags;
+ ASSERT(!in_irq());
+
/* We currently always return cacheline aligned. */
BUG_ON(align > SMP_CACHE_BYTES);
@@ -212,6 +216,8 @@ void xfree(void *p)
{
unsigned long flags;
struct xmalloc_hdr *i, *tmp, *hdr;
+
+ ASSERT(!in_irq());
if ( p == NULL )
return;
diff -r d1853a39e063 -r cb2575cec95c xen/drivers/char/console.c
--- a/xen/drivers/char/console.c Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/drivers/char/console.c Mon Mar 12 10:07:08 2007 -0600
@@ -399,6 +399,8 @@ static void __putstr(const char *str)
vga_putchar(c);
putchar_console_ring(c);
}
+
+ send_guest_global_virq(dom0, VIRQ_CON_RING);
}
static int printk_prefix_check(char *p, char **pp)
diff -r d1853a39e063 -r cb2575cec95c xen/include/asm-x86/domain.h
--- a/xen/include/asm-x86/domain.h Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/include/asm-x86/domain.h Mon Mar 12 10:07:08 2007 -0600
@@ -104,6 +104,21 @@ struct shadow_vcpu {
};
/************************************************/
+/* hardware assisted paging */
+/************************************************/
+struct hap_domain {
+ spinlock_t lock;
+ int locker;
+ const char *locker_function;
+
+ struct list_head freelists;
+ struct list_head p2m_freelist;
+ unsigned int total_pages; /* number of pages allocated */
+ unsigned int free_pages; /* number of pages on freelists */
+ unsigned int p2m_pages; /* number of pages allocates to p2m */
+};
+
+/************************************************/
/* p2m handling */
/************************************************/
@@ -135,6 +150,7 @@ struct paging_domain {
struct shadow_domain shadow;
/* Other paging assistance code will have structs here */
+ struct hap_domain hap;
};
struct paging_vcpu {
diff -r d1853a39e063 -r cb2575cec95c xen/include/asm-x86/hap.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/asm-x86/hap.h Mon Mar 12 10:07:08 2007 -0600
@@ -0,0 +1,122 @@
+/******************************************************************************
+ * include/asm-x86/hap.h
+ *
+ * hardware-assisted paging
+ * Copyright (c) 2007 Advanced Micro Devices (Wei Huang)
+ *
+ * Parts of this code are Copyright (c) 2006 by XenSource Inc.
+ * Parts of this code are Copyright (c) 2006 by Michael A Fetterman
+ * Parts based on earlier work by Michael A Fetterman, Ian Pratt et al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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
+ */
+
+#ifndef _XEN_HAP_H
+#define _XEN_HAP_H
+
+#define HERE_I_AM \
+ debugtrace_printk("HERE I AM: %s %s %d\n", __func__, __FILE__, __LINE__)
+#define HAP_PRINTK(_f, _a...) \
+ debugtrace_printk("hap: %s(): " _f, __func__, ##_a)
+#define HAP_ERROR(_f, _a...) \
+ printk("hap error: %s(): " _f, __func__, ##_a)
+
+/************************************************/
+/* hap domain page mapping */
+/************************************************/
+static inline void *
+hap_map_domain_page(mfn_t mfn)
+{
+ return map_domain_page(mfn_x(mfn));
+}
+
+static inline void
+hap_unmap_domain_page(void *p)
+{
+ unmap_domain_page(p);
+}
+
+static inline void *
+hap_map_domain_page_global(mfn_t mfn)
+{
+ return map_domain_page_global(mfn_x(mfn));
+}
+
+static inline void
+hap_unmap_domain_page_global(void *p)
+{
+ unmap_domain_page_global(p);
+}
+
+/************************************************/
+/* locking for hap code */
+/************************************************/
+#define hap_lock_init(_d) \
+ do { \
+ spin_lock_init(&(_d)->arch.paging.hap.lock); \
+ (_d)->arch.paging.hap.locker = -1; \
+ (_d)->arch.paging.hap.locker_function = "nobody"; \
+ } while (0)
+
+#define hap_locked_by_me(_d) \
+ (current->processor == (_d)->arch.paging.hap.locker)
+
+#define hap_lock(_d) \
+ do { \
+ if ( unlikely((_d)->arch.paging.hap.locker == current->processor) )\
+ { \
+ printk("Error: hap lock held by %s\n", \
+ (_d)->arch.paging.hap.locker_function); \
+ BUG(); \
+ } \
+ spin_lock(&(_d)->arch.paging.hap.lock); \
+ ASSERT((_d)->arch.paging.hap.locker == -1); \
+ (_d)->arch.paging.hap.locker = current->processor; \
+ (_d)->arch.paging.hap.locker_function = __func__; \
+ } while (0)
+
+#define hap_unlock(_d) \
+ do { \
+ ASSERT((_d)->arch.paging.hap.locker == current->processor); \
+ (_d)->arch.paging.hap.locker = -1; \
+ (_d)->arch.paging.hap.locker_function = "nobody"; \
+ spin_unlock(&(_d)->arch.paging.hap.lock); \
+ } while (0)
+
+/************************************************/
+/* hap domain level functions */
+/************************************************/
+void hap_domain_init(struct domain *d);
+int hap_domctl(struct domain *d, xen_domctl_shadow_op_t *sc,
+ XEN_GUEST_HANDLE(void) u_domctl);
+int hap_enable(struct domain *d, u32 mode);
+void hap_final_teardown(struct domain *d);
+void hap_teardown(struct domain *d);
+void hap_vcpu_init(struct vcpu *v);
+
+extern struct paging_mode hap_paging_real_mode;
+extern struct paging_mode hap_paging_protected_mode;
+extern struct paging_mode hap_paging_pae_mode;
+extern struct paging_mode hap_paging_long_mode;
+#endif /* XEN_HAP_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r d1853a39e063 -r cb2575cec95c xen/include/asm-x86/hvm/svm/vmcb.h
--- a/xen/include/asm-x86/hvm/svm/vmcb.h Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/include/asm-x86/hvm/svm/vmcb.h Mon Mar 12 10:07:08 2007 -0600
@@ -460,7 +460,6 @@ struct vmcb_struct *alloc_vmcb(void);
struct vmcb_struct *alloc_vmcb(void);
struct host_save_area *alloc_host_save_area(void);
void free_vmcb(struct vmcb_struct *vmcb);
-void free_host_save_area(struct host_save_area *hsa);
int svm_create_vmcb(struct vcpu *v);
void svm_destroy_vmcb(struct vcpu *v);
diff -r d1853a39e063 -r cb2575cec95c xen/include/asm-x86/hvm/vpt.h
--- a/xen/include/asm-x86/hvm/vpt.h Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/include/asm-x86/hvm/vpt.h Mon Mar 12 10:07:08 2007 -0600
@@ -92,6 +92,7 @@ typedef struct RTCState {
struct timer second_timer;
struct timer second_timer2;
struct periodic_time pt;
+ int32_t time_offset_seconds;
} RTCState;
#define FREQUENCE_PMTIMER 3579545 /* Timer should run at 3.579545 MHz */
diff -r d1853a39e063 -r cb2575cec95c xen/include/asm-x86/paging.h
--- a/xen/include/asm-x86/paging.h Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/include/asm-x86/paging.h Mon Mar 12 10:07:08 2007 -0600
@@ -273,7 +273,7 @@ static inline void paging_write_p2m_entr
struct vcpu *v = current;
if ( v->domain != d )
v = d->vcpu[0];
- if ( likely(paging_mode_enabled(d) && v->arch.paging.mode != NULL) )
+ if ( likely(v && paging_mode_enabled(d) && v->arch.paging.mode != NULL) )
{
return v->arch.paging.mode->write_p2m_entry(v, gfn, p, new, level);
}
diff -r d1853a39e063 -r cb2575cec95c xen/include/public/hvm/hvm_op.h
--- a/xen/include/public/hvm/hvm_op.h Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/include/public/hvm/hvm_op.h Mon Mar 12 10:07:08 2007 -0600
@@ -70,4 +70,12 @@ typedef struct xen_hvm_set_pci_link_rout
typedef struct xen_hvm_set_pci_link_route xen_hvm_set_pci_link_route_t;
DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_pci_link_route_t);
+/* Drain all outstanding qemu-dm IO responses from a domain's ioreq ring. */
+#define HVMOP_drain_io 5
+struct xen_hvm_drain_io {
+ domid_t domid;
+};
+typedef struct xen_hvm_drain_io xen_hvm_drain_io_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_drain_io_t);
+
#endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
diff -r d1853a39e063 -r cb2575cec95c xen/include/public/sysctl.h
--- a/xen/include/public/sysctl.h Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/include/public/sysctl.h Mon Mar 12 10:07:08 2007 -0600
@@ -140,6 +140,18 @@ typedef struct xen_sysctl_getdomaininfol
typedef struct xen_sysctl_getdomaininfolist xen_sysctl_getdomaininfolist_t;
DEFINE_XEN_GUEST_HANDLE(xen_sysctl_getdomaininfolist_t);
+/*
+ * Inject debug keys into Xen.
+ */
+#define XEN_SYSCTL_debug_keys 7
+struct xen_sysctl_debug_keys {
+ /* IN variables. */
+ XEN_GUEST_HANDLE_64(char) keys;
+ uint32_t nr_keys;
+};
+typedef struct xen_sysctl_debug_keys xen_sysctl_debug_keys_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_debug_keys_t);
+
struct xen_sysctl {
uint32_t cmd;
uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */
@@ -150,6 +162,7 @@ struct xen_sysctl {
struct xen_sysctl_sched_id sched_id;
struct xen_sysctl_perfc_op perfc_op;
struct xen_sysctl_getdomaininfolist getdomaininfolist;
+ struct xen_sysctl_debug_keys debug_keys;
uint8_t pad[128];
} u;
};
diff -r d1853a39e063 -r cb2575cec95c xen/include/public/vcpu.h
--- a/xen/include/public/vcpu.h Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/include/public/vcpu.h Mon Mar 12 10:07:08 2007 -0600
@@ -42,13 +42,13 @@
* @extra_arg == pointer to vcpu_guest_context structure containing initial
* state for the VCPU.
*/
-#define VCPUOP_initialise 0
+#define VCPUOP_initialise 0
/*
* Bring up a VCPU. This makes the VCPU runnable. This operation will fail
* if the VCPU has not been initialised (VCPUOP_initialise).
*/
-#define VCPUOP_up 1
+#define VCPUOP_up 1
/*
* Bring down a VCPU (i.e., make it non-runnable).
@@ -64,16 +64,16 @@
* practise to move a VCPU onto an 'idle' or default page table, LDT and
* GDT before bringing it down.
*/
-#define VCPUOP_down 2
+#define VCPUOP_down 2
/* Returns 1 if the given VCPU is up. */
-#define VCPUOP_is_up 3
+#define VCPUOP_is_up 3
/*
* Return information about the state and running time of a VCPU.
* @extra_arg == pointer to vcpu_runstate_info structure.
*/
-#define VCPUOP_get_runstate_info 4
+#define VCPUOP_get_runstate_info 4
struct vcpu_runstate_info {
/* VCPU's current state (RUNSTATE_*). */
int state;
@@ -128,6 +128,38 @@ struct vcpu_register_runstate_memory_are
} addr;
};
typedef struct vcpu_register_runstate_memory_area
vcpu_register_runstate_memory_area_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_register_runstate_memory_area_t);
+
+/*
+ * Set or stop a VCPU's periodic timer. Every VCPU has one periodic timer
+ * which can be set via these commands. Periods smaller than one millisecond
+ * may not be supported.
+ */
+#define VCPUOP_set_periodic_timer 6 /* arg == vcpu_set_periodic_timer_t */
+#define VCPUOP_stop_periodic_timer 7 /* arg == NULL */
+struct vcpu_set_periodic_timer {
+ uint64_t period_ns;
+};
+typedef struct vcpu_set_periodic_timer vcpu_set_periodic_timer_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_set_periodic_timer_t);
+
+/*
+ * Set or stop a VCPU's single-shot timer. Every VCPU has one single-shot
+ * timer which can be set via these commands.
+ */
+#define VCPUOP_set_singleshot_timer 8 /* arg == vcpu_set_singleshot_timer_t */
+#define VCPUOP_stop_singleshot_timer 9 /* arg == NULL */
+struct vcpu_set_singleshot_timer {
+ uint64_t timeout_abs_ns; /* Absolute system time value in nanoseconds. */
+ uint32_t flags; /* VCPU_SSHOTTMR_??? */
+};
+typedef struct vcpu_set_singleshot_timer vcpu_set_singleshot_timer_t;
+DEFINE_XEN_GUEST_HANDLE(vcpu_set_singleshot_timer_t);
+
+/* Flags to VCPUOP_set_singleshot_timer. */
+ /* Require the timeout to be in the future (return -ETIME if it's passed). */
+#define _VCPU_SSHOTTMR_future (0)
+#define VCPU_SSHOTTMR_future (1U << _VCPU_SSHOTTMR_future)
#endif /* __XEN_PUBLIC_VCPU_H__ */
diff -r d1853a39e063 -r cb2575cec95c xen/include/public/xen.h
--- a/xen/include/public/xen.h Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/include/public/xen.h Mon Mar 12 10:07:08 2007 -0600
@@ -131,6 +131,7 @@
#define VIRQ_TBUF 4 /* G. (DOM0) Trace buffer has records available. */
#define VIRQ_DEBUGGER 6 /* G. (DOM0) A domain has paused for debugging. */
#define VIRQ_XENOPROF 7 /* V. XenOprofile interrupt: new sample available */
+#define VIRQ_CON_RING 8 /* G. (DOM0) Bytes received on console */
/* Architecture-specific VIRQ definitions. */
#define VIRQ_ARCH_0 16
diff -r d1853a39e063 -r cb2575cec95c xen/include/xen/mm.h
--- a/xen/include/xen/mm.h Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/include/xen/mm.h Mon Mar 12 10:07:08 2007 -0600
@@ -92,6 +92,11 @@ extern struct list_head page_scrub_list;
if ( !list_empty(&page_scrub_list) ) \
raise_softirq(PAGE_SCRUB_SOFTIRQ); \
} while ( 0 )
+#define page_scrub_kick() \
+ do { \
+ if ( !list_empty(&page_scrub_list) ) \
+ cpumask_raise_softirq(cpu_online_map, PAGE_SCRUB_SOFTIRQ); \
+ } while ( 0 )
unsigned long avail_scrub_pages(void);
#include <asm/mm.h>
diff -r d1853a39e063 -r cb2575cec95c xen/include/xen/sched-if.h
--- a/xen/include/xen/sched-if.h Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/include/xen/sched-if.h Mon Mar 12 10:07:08 2007 -0600
@@ -16,7 +16,6 @@ struct schedule_data {
struct vcpu *idle; /* idle task for this cpu */
void *sched_priv;
struct timer s_timer; /* scheduling timer */
- unsigned long tick; /* current periodic 'tick' */
} __cacheline_aligned;
DECLARE_PER_CPU(struct schedule_data, schedule_data);
@@ -61,7 +60,6 @@ struct scheduler {
unsigned int sched_id; /* ID for this scheduler */
void (*init) (void);
- void (*tick) (unsigned int cpu);
int (*init_domain) (struct domain *);
void (*destroy_domain) (struct domain *);
diff -r d1853a39e063 -r cb2575cec95c xen/include/xen/sched.h
--- a/xen/include/xen/sched.h Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/include/xen/sched.h Mon Mar 12 10:07:08 2007 -0600
@@ -79,8 +79,10 @@ struct vcpu
struct vcpu *next_in_list;
- struct timer timer; /* one-shot timer for timeout values */
- unsigned long sleep_tick; /* tick at which this vcpu started sleep */
+ uint64_t periodic_period;
+ uint64_t periodic_last_event;
+ struct timer periodic_timer;
+ struct timer singleshot_timer;
struct timer poll_timer; /* timeout for SCHEDOP_poll */
@@ -332,7 +334,6 @@ void __domain_crash_synchronous(void) __
#define set_current_state(_s) do { current->state = (_s); } while (0)
void scheduler_init(void);
-void schedulers_start(void);
int sched_init_vcpu(struct vcpu *v, unsigned int processor);
void sched_destroy_vcpu(struct vcpu *v);
int sched_init_domain(struct domain *d);
@@ -497,6 +498,7 @@ void domain_unpause_by_systemcontroller(
void domain_unpause_by_systemcontroller(struct domain *d);
void cpu_init(void);
+void vcpu_force_reschedule(struct vcpu *v);
int vcpu_set_affinity(struct vcpu *v, cpumask_t *affinity);
void vcpu_runstate_get(struct vcpu *v, struct vcpu_runstate_info *runstate);
diff -r d1853a39e063 -r cb2575cec95c xen/include/xen/timer.h
--- a/xen/include/xen/timer.h Mon Mar 12 09:43:48 2007 -0600
+++ b/xen/include/xen/timer.h Mon Mar 12 10:07:08 2007 -0600
@@ -35,7 +35,7 @@ struct timer {
* The timer must *previously* have been initialised by init_timer(), or its
* structure initialised to all-zeroes.
*/
-static __inline__ int active_timer(struct timer *timer)
+static inline int active_timer(struct timer *timer)
{
return (timer->heap_offset != 0);
}
@@ -46,7 +46,7 @@ static __inline__ int active_timer(struc
* time (and multiple times) on an inactive timer. It must *never* execute
* concurrently with any other operation on the same timer.
*/
-static __inline__ void init_timer(
+static inline void init_timer(
struct timer *timer,
void (*function)(void *),
void *data,
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|