mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
merge with xen-unstable.hg
This commit is contained in:
commit
dc1c0a8170
112 files changed
+2701
-1456
No files matched your search
@@ -184,6 +184,7 @@
|
||||
^tools/xm-test/ramdisk/buildroot
|
||||
^xen/BLOG$
|
||||
^xen/TAGS$
|
||||
^xen/cscope\.*$
|
||||
^xen/arch/x86/asm-offsets\.s$
|
||||
^xen/arch/x86/boot/mkelf32$
|
||||
^xen/arch/x86/xen\.lds$
|
||||
|
||||
@@ -99,14 +99,14 @@ endif
|
||||
linux-2.6-xen.patch: ref-linux-$(LINUX_VER)/.valid-ref
|
||||
rm -rf tmp-$@
|
||||
cp -al $(<D) tmp-$@
|
||||
( cd linux-2.6-xen-sparse && ./mkbuildtree ../tmp-$@ )
|
||||
( cd linux-2.6-xen-sparse && bash ./mkbuildtree ../tmp-$@ )
|
||||
diff -Nurp $(patsubst ref%,pristine%,$(<D)) tmp-$@ > $@ || true
|
||||
rm -rf tmp-$@
|
||||
|
||||
%-xen.patch: ref-%/.valid-ref
|
||||
rm -rf tmp-$@
|
||||
cp -al $(<D) tmp-$@
|
||||
( cd $*-xen-sparse && ./mkbuildtree ../tmp-$@ )
|
||||
( cd $*-xen-sparse && bash ./mkbuildtree ../tmp-$@ )
|
||||
diff -Nurp $(patsubst ref%,pristine%,$(<D)) tmp-$@ > $@ || true
|
||||
rm -rf tmp-$@
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.16-rc3-xen0
|
||||
# Mon Feb 20 11:37:43 2006
|
||||
# Linux kernel version: 2.6.16-xen0
|
||||
# Thu Apr 13 14:58:29 2006
|
||||
#
|
||||
CONFIG_X86_64=y
|
||||
CONFIG_64BIT=y
|
||||
@@ -99,6 +99,8 @@ CONFIG_X86_PC=y
|
||||
# CONFIG_MPSC is not set
|
||||
CONFIG_GENERIC_CPU=y
|
||||
CONFIG_X86_64_XEN=y
|
||||
CONFIG_X86_NO_TSS=y
|
||||
CONFIG_X86_NO_IDT=y
|
||||
CONFIG_X86_L1_CACHE_BYTES=128
|
||||
CONFIG_X86_L1_CACHE_SHIFT=7
|
||||
CONFIG_X86_GOOD_APIC=y
|
||||
@@ -176,6 +178,19 @@ CONFIG_PCI_DIRECT=y
|
||||
CONFIG_XEN_PCIDEV_FRONTEND=y
|
||||
# CONFIG_XEN_PCIDEV_FE_DEBUG is not set
|
||||
# CONFIG_UNORDERED_IO is not set
|
||||
# CONFIG_PCIEPORTBUS is not set
|
||||
CONFIG_PCI_LEGACY_PROC=y
|
||||
# CONFIG_PCI_DEBUG is not set
|
||||
|
||||
#
|
||||
# PCCARD (PCMCIA/CardBus) support
|
||||
#
|
||||
# CONFIG_PCCARD is not set
|
||||
|
||||
#
|
||||
# PCI Hotplug Support
|
||||
#
|
||||
# CONFIG_HOTPLUG_PCI is not set
|
||||
|
||||
#
|
||||
# Executable file formats / Emulations
|
||||
@@ -1001,11 +1016,7 @@ CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y
|
||||
CONFIG_INFINIBAND_SRP=y
|
||||
|
||||
#
|
||||
# SN Devices
|
||||
#
|
||||
|
||||
#
|
||||
# EDAC - error detection and reporting (RAS)
|
||||
# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
|
||||
#
|
||||
# CONFIG_EDAC is not set
|
||||
|
||||
@@ -1239,7 +1250,7 @@ CONFIG_CRYPTO_CRC32C=m
|
||||
# Hardware crypto devices
|
||||
#
|
||||
CONFIG_XEN=y
|
||||
CONFIG_NO_IDLE_HZ=y
|
||||
CONFIG_XEN_INTERFACE_VERSION=0x00030101
|
||||
|
||||
#
|
||||
# XEN
|
||||
@@ -1266,6 +1277,7 @@ CONFIG_XEN_DISABLE_SERIAL=y
|
||||
CONFIG_XEN_SYSFS=y
|
||||
CONFIG_HAVE_ARCH_ALLOC_SKB=y
|
||||
CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
|
||||
CONFIG_NO_IDLE_HZ=y
|
||||
|
||||
#
|
||||
# Library routines
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.16-rc3-xen0
|
||||
# Thu Feb 16 22:56:02 2006
|
||||
# Linux kernel version: 2.6.16-xenU
|
||||
# Thu Apr 13 14:59:16 2006
|
||||
#
|
||||
CONFIG_X86_64=y
|
||||
CONFIG_64BIT=y
|
||||
@@ -103,6 +103,8 @@ CONFIG_X86_PC=y
|
||||
CONFIG_MPSC=y
|
||||
# CONFIG_GENERIC_CPU is not set
|
||||
CONFIG_X86_64_XEN=y
|
||||
CONFIG_X86_NO_TSS=y
|
||||
CONFIG_X86_NO_IDT=y
|
||||
CONFIG_X86_L1_CACHE_BYTES=128
|
||||
CONFIG_X86_L1_CACHE_SHIFT=7
|
||||
CONFIG_X86_GOOD_APIC=y
|
||||
@@ -146,6 +148,15 @@ CONFIG_GENERIC_PENDING_IRQ=y
|
||||
# CONFIG_PCI is not set
|
||||
# CONFIG_UNORDERED_IO is not set
|
||||
|
||||
#
|
||||
# PCCARD (PCMCIA/CardBus) support
|
||||
#
|
||||
# CONFIG_PCCARD is not set
|
||||
|
||||
#
|
||||
# PCI Hotplug Support
|
||||
#
|
||||
|
||||
#
|
||||
# Executable file formats / Emulations
|
||||
#
|
||||
@@ -844,11 +855,7 @@ CONFIG_DUMMY_CONSOLE=y
|
||||
#
|
||||
|
||||
#
|
||||
# SN Devices
|
||||
#
|
||||
|
||||
#
|
||||
# EDAC - error detection and reporting (RAS)
|
||||
# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
|
||||
#
|
||||
# CONFIG_EDAC is not set
|
||||
|
||||
@@ -1128,7 +1135,7 @@ CONFIG_CRYPTO_CRC32C=m
|
||||
# Hardware crypto devices
|
||||
#
|
||||
CONFIG_XEN=y
|
||||
CONFIG_NO_IDLE_HZ=y
|
||||
CONFIG_XEN_INTERFACE_VERSION=0x00030101
|
||||
|
||||
#
|
||||
# XEN
|
||||
@@ -1144,6 +1151,7 @@ CONFIG_XEN_DISABLE_SERIAL=y
|
||||
CONFIG_XEN_SYSFS=y
|
||||
CONFIG_HAVE_ARCH_ALLOC_SKB=y
|
||||
CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
|
||||
CONFIG_NO_IDLE_HZ=y
|
||||
|
||||
#
|
||||
# Library routines
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.16-xen
|
||||
# Mon Mar 27 09:43:44 2006
|
||||
# Thu Apr 13 15:01:04 2006
|
||||
#
|
||||
CONFIG_X86_64=y
|
||||
CONFIG_64BIT=y
|
||||
@@ -186,6 +186,41 @@ CONFIG_PCI_DIRECT=y
|
||||
CONFIG_XEN_PCIDEV_FRONTEND=y
|
||||
# CONFIG_XEN_PCIDEV_FE_DEBUG is not set
|
||||
# CONFIG_UNORDERED_IO is not set
|
||||
# CONFIG_PCIEPORTBUS is not set
|
||||
# CONFIG_PCI_LEGACY_PROC is not set
|
||||
# CONFIG_PCI_DEBUG is not set
|
||||
|
||||
#
|
||||
# PCCARD (PCMCIA/CardBus) support
|
||||
#
|
||||
CONFIG_PCCARD=m
|
||||
# CONFIG_PCMCIA_DEBUG is not set
|
||||
CONFIG_PCMCIA=m
|
||||
CONFIG_PCMCIA_LOAD_CIS=y
|
||||
CONFIG_PCMCIA_IOCTL=y
|
||||
CONFIG_CARDBUS=y
|
||||
|
||||
#
|
||||
# PC-card bridges
|
||||
#
|
||||
CONFIG_YENTA=m
|
||||
CONFIG_YENTA_O2=y
|
||||
CONFIG_YENTA_RICOH=y
|
||||
CONFIG_YENTA_TI=y
|
||||
CONFIG_YENTA_ENE_TUNE=y
|
||||
CONFIG_YENTA_TOSHIBA=y
|
||||
CONFIG_PD6729=m
|
||||
CONFIG_I82092=m
|
||||
CONFIG_PCCARD_NONSTATIC=m
|
||||
|
||||
#
|
||||
# PCI Hotplug Support
|
||||
#
|
||||
CONFIG_HOTPLUG_PCI=m
|
||||
# CONFIG_HOTPLUG_PCI_FAKE is not set
|
||||
# CONFIG_HOTPLUG_PCI_ACPI is not set
|
||||
# CONFIG_HOTPLUG_PCI_CPCI is not set
|
||||
# CONFIG_HOTPLUG_PCI_SHPC is not set
|
||||
|
||||
#
|
||||
# Executable file formats / Emulations
|
||||
@@ -625,6 +660,10 @@ CONFIG_BT_HCIUART_BCSP=y
|
||||
CONFIG_BT_HCIBCM203X=m
|
||||
CONFIG_BT_HCIBPA10X=m
|
||||
CONFIG_BT_HCIBFUSB=m
|
||||
# CONFIG_BT_HCIDTL1 is not set
|
||||
# CONFIG_BT_HCIBT3C is not set
|
||||
# CONFIG_BT_HCIBLUECARD is not set
|
||||
# CONFIG_BT_HCIBTUART is not set
|
||||
CONFIG_BT_HCIVHCI=m
|
||||
CONFIG_IEEE80211=m
|
||||
# CONFIG_IEEE80211_DEBUG is not set
|
||||
@@ -769,6 +808,7 @@ CONFIG_PARPORT=m
|
||||
CONFIG_PARPORT_PC=m
|
||||
# CONFIG_PARPORT_PC_FIFO is not set
|
||||
# CONFIG_PARPORT_PC_SUPERIO is not set
|
||||
# CONFIG_PARPORT_PC_PCMCIA is not set
|
||||
CONFIG_PARPORT_NOT_PC=y
|
||||
# CONFIG_PARPORT_GSC is not set
|
||||
CONFIG_PARPORT_1284=y
|
||||
@@ -851,6 +891,7 @@ CONFIG_BLK_DEV_IDE=y
|
||||
# CONFIG_BLK_DEV_HD_IDE is not set
|
||||
CONFIG_BLK_DEV_IDEDISK=y
|
||||
CONFIG_IDEDISK_MULTI_MODE=y
|
||||
# CONFIG_BLK_DEV_IDECS is not set
|
||||
CONFIG_BLK_DEV_IDECD=y
|
||||
# CONFIG_BLK_DEV_IDETAPE is not set
|
||||
CONFIG_BLK_DEV_IDEFLOPPY=y
|
||||
@@ -1011,6 +1052,13 @@ CONFIG_SCSI_DC395x=m
|
||||
CONFIG_SCSI_DC390T=m
|
||||
# CONFIG_SCSI_DEBUG is not set
|
||||
|
||||
#
|
||||
# PCMCIA SCSI adapter support
|
||||
#
|
||||
# CONFIG_PCMCIA_FDOMAIN is not set
|
||||
# CONFIG_PCMCIA_QLOGIC is not set
|
||||
# CONFIG_PCMCIA_SYM53C500 is not set
|
||||
|
||||
#
|
||||
# Multi-device support (RAID and LVM)
|
||||
#
|
||||
@@ -1141,6 +1189,7 @@ CONFIG_DE4X5=m
|
||||
CONFIG_WINBOND_840=m
|
||||
CONFIG_DM9102=m
|
||||
CONFIG_ULI526X=m
|
||||
# CONFIG_PCMCIA_XIRCOM is not set
|
||||
# CONFIG_HP100 is not set
|
||||
CONFIG_NET_PCI=y
|
||||
CONFIG_PCNET32=m
|
||||
@@ -1224,6 +1273,13 @@ CONFIG_NET_RADIO=y
|
||||
# Obsolete Wireless cards support (pre-802.11)
|
||||
#
|
||||
# CONFIG_STRIP is not set
|
||||
# CONFIG_PCMCIA_WAVELAN is not set
|
||||
# CONFIG_PCMCIA_NETWAVE is not set
|
||||
|
||||
#
|
||||
# Wireless 802.11 Frequency Hopping cards support
|
||||
#
|
||||
# CONFIG_PCMCIA_RAYCS is not set
|
||||
|
||||
#
|
||||
# Wireless 802.11b ISA/PCI cards support
|
||||
@@ -1242,6 +1298,15 @@ CONFIG_PCI_HERMES=m
|
||||
CONFIG_ATMEL=m
|
||||
CONFIG_PCI_ATMEL=m
|
||||
|
||||
#
|
||||
# Wireless 802.11b Pcmcia/Cardbus cards support
|
||||
#
|
||||
# CONFIG_PCMCIA_HERMES is not set
|
||||
# CONFIG_PCMCIA_SPECTRUM is not set
|
||||
# CONFIG_AIRO_CS is not set
|
||||
# CONFIG_PCMCIA_ATMEL is not set
|
||||
# CONFIG_PCMCIA_WL3501 is not set
|
||||
|
||||
#
|
||||
# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
|
||||
#
|
||||
@@ -1250,8 +1315,14 @@ CONFIG_HOSTAP=m
|
||||
# CONFIG_HOSTAP_FIRMWARE is not set
|
||||
CONFIG_HOSTAP_PLX=m
|
||||
CONFIG_HOSTAP_PCI=m
|
||||
# CONFIG_HOSTAP_CS is not set
|
||||
CONFIG_NET_WIRELESS=y
|
||||
|
||||
#
|
||||
# PCMCIA network device support
|
||||
#
|
||||
# CONFIG_NET_PCMCIA is not set
|
||||
|
||||
#
|
||||
# Wan interfaces
|
||||
#
|
||||
@@ -1376,6 +1447,10 @@ CONFIG_HISAX_ENTERNOW_PCI=y
|
||||
#
|
||||
# HiSax PCMCIA card service modules
|
||||
#
|
||||
# CONFIG_HISAX_SEDLBAUER_CS is not set
|
||||
# CONFIG_HISAX_ELSA_CS is not set
|
||||
# CONFIG_HISAX_AVM_A1_CS is not set
|
||||
# CONFIG_HISAX_TELES_CS is not set
|
||||
|
||||
#
|
||||
# HiSax sub driver modules
|
||||
@@ -1412,6 +1487,7 @@ CONFIG_CAPI_AVM=y
|
||||
CONFIG_ISDN_DRV_AVMB1_B1PCI=m
|
||||
CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y
|
||||
CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
|
||||
# CONFIG_ISDN_DRV_AVMB1_AVM_CS is not set
|
||||
CONFIG_ISDN_DRV_AVMB1_T1PCI=m
|
||||
CONFIG_ISDN_DRV_AVMB1_C4=m
|
||||
|
||||
@@ -1600,6 +1676,13 @@ CONFIG_DRM_RADEON=m
|
||||
CONFIG_DRM_MGA=m
|
||||
CONFIG_DRM_VIA=m
|
||||
CONFIG_DRM_SAVAGE=m
|
||||
|
||||
#
|
||||
# PCMCIA character devices
|
||||
#
|
||||
# CONFIG_SYNCLINK_CS is not set
|
||||
# CONFIG_CARDMAN_4000 is not set
|
||||
# CONFIG_CARDMAN_4040 is not set
|
||||
# CONFIG_MWAVE is not set
|
||||
# CONFIG_RAW_DRIVER is not set
|
||||
# CONFIG_HPET is not set
|
||||
@@ -2100,6 +2183,10 @@ CONFIG_SND_YMFPCI=m
|
||||
CONFIG_SND_USB_AUDIO=m
|
||||
CONFIG_SND_USB_USX2Y=m
|
||||
|
||||
#
|
||||
# PCMCIA devices
|
||||
#
|
||||
|
||||
#
|
||||
# Open Sound System
|
||||
#
|
||||
@@ -2134,6 +2221,7 @@ CONFIG_USB_OHCI_HCD=m
|
||||
CONFIG_USB_OHCI_LITTLE_ENDIAN=y
|
||||
CONFIG_USB_UHCI_HCD=m
|
||||
CONFIG_USB_SL811_HCD=m
|
||||
# CONFIG_USB_SL811_CS is not set
|
||||
|
||||
#
|
||||
# USB Device Class drivers
|
||||
@@ -2284,6 +2372,7 @@ CONFIG_USB_SERIAL_SAFE_PADDED=y
|
||||
CONFIG_USB_SERIAL_TI=m
|
||||
CONFIG_USB_SERIAL_CYBERJACK=m
|
||||
CONFIG_USB_SERIAL_XIRCOM=m
|
||||
# CONFIG_USB_SERIAL_OPTION is not set
|
||||
CONFIG_USB_SERIAL_OMNINET=m
|
||||
CONFIG_USB_EZUSB=y
|
||||
|
||||
@@ -2649,7 +2738,7 @@ CONFIG_CRYPTO_CRC32C=m
|
||||
# Hardware crypto devices
|
||||
#
|
||||
CONFIG_XEN=y
|
||||
CONFIG_NO_IDLE_HZ=y
|
||||
CONFIG_XEN_INTERFACE_VERSION=0x00030101
|
||||
|
||||
#
|
||||
# XEN
|
||||
@@ -2676,6 +2765,7 @@ CONFIG_XEN_DISABLE_SERIAL=y
|
||||
CONFIG_XEN_SYSFS=m
|
||||
CONFIG_HAVE_ARCH_ALLOC_SKB=y
|
||||
CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y
|
||||
CONFIG_NO_IDLE_HZ=y
|
||||
|
||||
#
|
||||
# Library routines
|
||||
|
||||
@@ -22,8 +22,8 @@ $(LINUX_DIR)/include/linux/autoconf.h: ref-linux-$(LINUX_VER)/.valid-ref
|
||||
rm -rf $(LINUX_DIR)
|
||||
cp -al $(<D) $(LINUX_DIR)
|
||||
# Apply arch-xen patches
|
||||
( cd linux-$(LINUX_SERIES)-xen-sparse ; \
|
||||
LINUX_ARCH=$(LINUX_ARCH) ./mkbuildtree ../$(LINUX_DIR) )
|
||||
( cd linux-$(LINUX_SERIES)-xen-sparse && \
|
||||
LINUX_ARCH=$(LINUX_ARCH) bash ./mkbuildtree ../$(LINUX_DIR) )
|
||||
# Re-use config from install dir if one exits else use default config
|
||||
CONFIG_VERSION=$$(sed -ne 's/^EXTRAVERSION = //p' $(LINUX_DIR)/Makefile); \
|
||||
[ -r $(DESTDIR)/boot/config-$(LINUX_VER)$$CONFIG_VERSION-$(EXTRAVERSION) ] && \
|
||||
|
||||
+65
-9
@@ -1232,8 +1232,15 @@ customized variants for your site's preferred configuration.
|
||||
\subsection{PCI}
|
||||
\label{ss:pcidd}
|
||||
|
||||
Individual PCI devices can be assigned to a given domain to allow that
|
||||
domain direct access to the PCI hardware. To use this functionality, ensure
|
||||
Individual PCI devices can be assigned to a given domain (a PCI driver domain)
|
||||
to allow that domain direct access to the PCI hardware.
|
||||
|
||||
While PCI Driver Domains can increase the stability and security of a system
|
||||
by addressing a number of security concerns, there are some security issues
|
||||
that remain that you can read about in Section~\ref{s:ddsecurity}.
|
||||
|
||||
\subsubsection{Compile-Time Setup}
|
||||
To use this functionality, ensure
|
||||
that the PCI Backend is compiled in to a privileged domain (e.g. domain 0)
|
||||
and that the domains which will be assigned PCI devices have the PCI Frontend
|
||||
compiled in. In XenLinux, the PCI Backend is available under the Xen
|
||||
@@ -1241,21 +1248,73 @@ configuration section while the PCI Frontend is under the
|
||||
architecture-specific "Bus Options" section. You may compile both the backend
|
||||
and the frontend into the same kernel; they will not affect each other.
|
||||
|
||||
\subsubsection{PCI Backend Configuration - Binding at Boot}
|
||||
The PCI devices you wish to assign to unprivileged domains must be "hidden"
|
||||
from your backend domain (usually domain 0) so that it does not load a driver
|
||||
for them. Use the \path{pciback.hide} kernel parameter which is specified on
|
||||
the kernel command-line and is configurable through GRUB (see
|
||||
Section~\ref{s:configure}). Note that devices are not really hidden from the
|
||||
backend domain. The PCI Backend ensures that no other device driver loads
|
||||
for those devices. PCI devices are identified by hexadecimal
|
||||
slot/funciton numbers (on Linux, use \path{lspci} to determine slot/funciton
|
||||
numbers of your devices) and can be specified with or without the PCI domain: \\
|
||||
backend domain. The PCI Backend appears to the Linux kernel as a regular PCI
|
||||
device driver. The PCI Backend ensures that no other device driver loads
|
||||
for the devices by binding itself as the device driver for those devices.
|
||||
PCI devices are identified by hexadecimal slot/funciton numbers (on Linux,
|
||||
use \path{lspci} to determine slot/funciton numbers of your devices) and
|
||||
can be specified with or without the PCI domain: \\
|
||||
\centerline{ {\tt ({\em bus}:{\em slot}.{\em func})} example {\tt (02:1d.3)}} \\
|
||||
\centerline{ {\tt ({\em domain}:{\em bus}:{\em slot}.{\em func})} example {\tt (0000:02:1d.3)}} \\
|
||||
|
||||
An example kernel command-line which hides two PCI devices might be: \\
|
||||
\centerline{ {\tt root=/dev/sda4 ro console=tty0 pciback.hide=(02:01.f)(0000:04:1d.0) } } \\
|
||||
|
||||
\subsubsection{PCI Backend Configuration - Late Binding}
|
||||
PCI devices can also be bound to the PCI Backend after boot through the manual
|
||||
binding/unbinding facilities provided by the Linux kernel in sysfs (allowing
|
||||
for a Xen user to give PCI devices to driver domains that were not specified
|
||||
on the kernel command-line). There are several attributes with the PCI
|
||||
Backend's sysfs directory (\path{/sys/bus/pci/drivers/pciback}) that can be
|
||||
used to bind/unbind devices:
|
||||
|
||||
\begin{description}
|
||||
\item[slots] lists all of the PCI slots that the PCI Backend will try to seize
|
||||
(or "hide" from Domain 0). A PCI slot must appear in this list before it can
|
||||
be bound to the PCI Backend through the \path{bind} attribute.
|
||||
\item[new\_slot] write the name of a slot here (in 0000:00:00.0 format) to
|
||||
have the PCI Backend seize the device in this slot.
|
||||
\item[remove\_slot] write the name of a slot here (same format as
|
||||
\path{new\_slot}) to have the PCI Backend no longer try to seize devices in
|
||||
this slot. Note that this does not unbind the driver from a device it has
|
||||
already seized.
|
||||
\item[bind] write the name of a slot here (in 0000:00:00.0 format) to have
|
||||
the Linux kernel attempt to bind the device in that slot to the PCI Backend
|
||||
driver.
|
||||
\item[unbind] write the name of a skit here (same format as \path{bind}) to have
|
||||
the Linux kernel unbind the device from the PCI Backend. DO NOT unbind a
|
||||
device while it is currently given to a PCI driver domain!
|
||||
\end{description}
|
||||
|
||||
Some examples:
|
||||
|
||||
Bind a device to the PCI Backend which is not bound to any other driver.
|
||||
\begin{verbatim}
|
||||
# # Add a new slot to the PCI Backend's list
|
||||
# echo -n 0000:01:04.d > /sys/bus/pci/drivers/pciback/new_slot
|
||||
# # Now that the backend is watching for the slot, bind to it
|
||||
# echo -n 0000:01:04.d > /sys/bus/pci/drivers/pciback/bind
|
||||
\end{verbatim}
|
||||
|
||||
Unbind a device from its driver and bind to the PCI Backend.
|
||||
\begin{verbatim}
|
||||
# # Unbind a PCI network card from its network driver
|
||||
# echo -n 0000:05:02.0 > /sys/bus/pci/drivers/3c905/unbind
|
||||
# # And now bind it to the PCI Backend
|
||||
# echo -n 0000:05:02.0 > /sys/bus/pci/drivers/pciback/new_slot
|
||||
# echo -n 0000:05:02.0 > /sys/bus/pci/drivers/pciback/bind
|
||||
\end{verbatim}
|
||||
|
||||
Note that the "-n" option in the example is important as it causes echo to not
|
||||
output a new-line.
|
||||
|
||||
\subsubsection{PCI Frontend Configuration}
|
||||
To configure a domU to receive a PCI device:
|
||||
|
||||
\begin{description}
|
||||
@@ -1282,9 +1341,6 @@ To configure a domU to receive a PCI device:
|
||||
}
|
||||
\end{description}
|
||||
|
||||
There are a number of security concerns associated with PCI Driver Domains
|
||||
that you can read about in Section~\ref{s:ddsecurity}.
|
||||
|
||||
%% There are two possible types of privileges: IO privileges and
|
||||
%% administration privileges.
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@ fastcall void do_fixup_4gb_segment(struct pt_regs *regs, long error_code)
|
||||
DP("");
|
||||
|
||||
for (i = 5; i > 0; i--) {
|
||||
touch_softlockup_watchdog();
|
||||
printk("Pausing... %d", i);
|
||||
mdelay(1000);
|
||||
printk("\b\b\b\b\b\b\b\b\b\b\b\b");
|
||||
|
||||
@@ -206,8 +206,8 @@ swiotlb_init(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* We use __copy_to_user to transfer to the host buffer because the buffer
|
||||
* may be mapped read-only (e.g, in blkback driver) but lower-level
|
||||
* We use __copy_to_user_inatomic to transfer to the host buffer because the
|
||||
* buffer may be mapped read-only (e.g, in blkback driver) but lower-level
|
||||
* drivers map the buffer for DMA_BIDIRECTIONAL access. This causes an
|
||||
* unnecessary copy from the aperture to the host buffer, and a page fault.
|
||||
*/
|
||||
@@ -225,7 +225,7 @@ __sync_single(struct phys_addr buffer, char *dma_addr, size_t size, int dir)
|
||||
dev = dma_addr + size - len;
|
||||
host = kmp + buffer.offset;
|
||||
if (dir == DMA_FROM_DEVICE) {
|
||||
if (__copy_to_user(host, dev, bytes))
|
||||
if (__copy_to_user_inatomic(host, dev, bytes))
|
||||
/* inaccessible */;
|
||||
} else
|
||||
memcpy(dev, host, bytes);
|
||||
@@ -238,7 +238,7 @@ __sync_single(struct phys_addr buffer, char *dma_addr, size_t size, int dir)
|
||||
char *host = (char *)phys_to_virt(
|
||||
page_to_pseudophys(buffer.page)) + buffer.offset;
|
||||
if (dir == DMA_FROM_DEVICE) {
|
||||
if (__copy_to_user(host, dma_addr, size))
|
||||
if (__copy_to_user_inatomic(host, dma_addr, size))
|
||||
/* inaccessible */;
|
||||
} else if (dir == DMA_TO_DEVICE)
|
||||
memcpy(dma_addr, host, size);
|
||||
|
||||
@@ -568,7 +568,6 @@ config UNORDERED_IO
|
||||
from i386. Requires that the driver writer used memory barriers
|
||||
properly.
|
||||
|
||||
if !X86_64_XEN
|
||||
source "drivers/pci/pcie/Kconfig"
|
||||
|
||||
source "drivers/pci/Kconfig"
|
||||
@@ -576,7 +575,6 @@ source "drivers/pci/Kconfig"
|
||||
source "drivers/pcmcia/Kconfig"
|
||||
|
||||
source "drivers/pci/hotplug/Kconfig"
|
||||
endif
|
||||
|
||||
endmenu
|
||||
|
||||
|
||||
@@ -186,9 +186,8 @@ static void fast_flush_area(pending_req_t *req)
|
||||
handle = pending_handle(req, i);
|
||||
if (handle == BLKBACK_INVALID_HANDLE)
|
||||
continue;
|
||||
unmap[invcount].host_addr = vaddr(req, i);
|
||||
unmap[invcount].dev_bus_addr = 0;
|
||||
unmap[invcount].handle = handle;
|
||||
gnttab_set_unmap_op(&unmap[i], vaddr(req, i), GNTMAP_host_map,
|
||||
handle);
|
||||
pending_handle(req, i) = BLKBACK_INVALID_HANDLE;
|
||||
invcount++;
|
||||
}
|
||||
@@ -384,6 +383,8 @@ static void dispatch_rw_block_io(blkif_t *blkif,
|
||||
pending_req->nr_pages = nseg;
|
||||
|
||||
for (i = 0; i < nseg; i++) {
|
||||
uint32_t flags;
|
||||
|
||||
seg[i].nsec = req->seg[i].last_sect -
|
||||
req->seg[i].first_sect + 1;
|
||||
|
||||
@@ -392,12 +393,11 @@ static void dispatch_rw_block_io(blkif_t *blkif,
|
||||
goto fail_response;
|
||||
preq.nr_sects += seg[i].nsec;
|
||||
|
||||
map[i].host_addr = vaddr(pending_req, i);
|
||||
map[i].dom = blkif->domid;
|
||||
map[i].ref = req->seg[i].gref;
|
||||
map[i].flags = GNTMAP_host_map;
|
||||
flags = GNTMAP_host_map;
|
||||
if ( operation == WRITE )
|
||||
map[i].flags |= GNTMAP_readonly;
|
||||
flags |= GNTMAP_readonly;
|
||||
gnttab_set_map_op(&map[i], vaddr(pending_req, i), flags,
|
||||
req->seg[i].gref, blkif->domid);
|
||||
}
|
||||
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, nseg);
|
||||
|
||||
@@ -58,10 +58,8 @@ static int map_frontend_page(blkif_t *blkif, unsigned long shared_page)
|
||||
struct gnttab_map_grant_ref op;
|
||||
int ret;
|
||||
|
||||
op.host_addr = (unsigned long)blkif->blk_ring_area->addr;
|
||||
op.flags = GNTMAP_host_map;
|
||||
op.ref = shared_page;
|
||||
op.dom = blkif->domid;
|
||||
gnttab_set_map_op(&op, (unsigned long)blkif->blk_ring_area->addr,
|
||||
GNTMAP_host_map, shared_page, blkif->domid);
|
||||
|
||||
lock_vm_area(blkif->blk_ring_area);
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
|
||||
@@ -90,9 +88,8 @@ static void unmap_frontend_page(blkif_t *blkif)
|
||||
struct gnttab_unmap_grant_ref op;
|
||||
int ret;
|
||||
|
||||
op.host_addr = (unsigned long)blkif->blk_ring_area->addr;
|
||||
op.handle = blkif->shmem_handle;
|
||||
op.dev_bus_addr = 0;
|
||||
gnttab_set_unmap_op(&op, (unsigned long)blkif->blk_ring_area->addr,
|
||||
GNTMAP_host_map, blkif->shmem_handle);
|
||||
|
||||
lock_vm_area(blkif->blk_ring_area);
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
|
||||
|
||||
@@ -418,9 +418,9 @@ static void fast_flush_area(int idx, int nr_pages)
|
||||
if (BLKTAP_INVALID_HANDLE(handle))
|
||||
continue;
|
||||
|
||||
unmap[op].host_addr = MMAP_VADDR(mmap_vstart, idx, i);
|
||||
unmap[op].dev_bus_addr = 0;
|
||||
unmap[op].handle = handle->kernel;
|
||||
gnttab_set_unmap_op(&unmap[op],
|
||||
MMAP_VADDR(mmap_vstart, idx, i),
|
||||
GNTMAP_host_map, handle->kernel);
|
||||
op++;
|
||||
|
||||
if (create_lookup_pte_addr(
|
||||
@@ -430,9 +430,10 @@ static void fast_flush_area(int idx, int nr_pages)
|
||||
DPRINTK("Couldn't get a pte addr!\n");
|
||||
return;
|
||||
}
|
||||
unmap[op].host_addr = ptep;
|
||||
unmap[op].dev_bus_addr = 0;
|
||||
unmap[op].handle = handle->user;
|
||||
gnttab_set_unmap_grnat_ref(&unmap[op], ptep,
|
||||
GNTMAP_host_map |
|
||||
GNTMAP_application_map |
|
||||
GNTMAP_contains_pte, handle->user);
|
||||
op++;
|
||||
|
||||
BLKTAP_INVALIDATE_HANDLE(handle);
|
||||
@@ -703,21 +704,21 @@ static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req)
|
||||
unsigned long uvaddr;
|
||||
unsigned long kvaddr;
|
||||
uint64_t ptep;
|
||||
uint32_t flags;
|
||||
|
||||
uvaddr = MMAP_VADDR(user_vstart, pending_idx, i);
|
||||
kvaddr = MMAP_VADDR(mmap_vstart, pending_idx, i);
|
||||
|
||||
/* Map the remote page to kernel. */
|
||||
map[op].host_addr = kvaddr;
|
||||
map[op].dom = blkif->domid;
|
||||
map[op].ref = req->seg[i].gref;
|
||||
map[op].flags = GNTMAP_host_map;
|
||||
flags = GNTMAP_host_map;
|
||||
/* This needs a bit more thought in terms of interposition:
|
||||
* If we want to be able to modify pages during write using
|
||||
* grant table mappings, the guest will either need to allow
|
||||
* it, or we'll need to incur a copy. Bit of an fbufs moment. ;) */
|
||||
if (req->operation == BLKIF_OP_WRITE)
|
||||
map[op].flags |= GNTMAP_readonly;
|
||||
flags |= GNTMAP_readonly;
|
||||
/* Map the remote page to kernel. */
|
||||
gnttab_set_map_op(&map[op], kvaddr, flags, req->seg[i].gref,
|
||||
blkif->domid);
|
||||
op++;
|
||||
|
||||
/* Now map it to user. */
|
||||
@@ -728,14 +729,13 @@ static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req)
|
||||
goto bad_descriptor;
|
||||
}
|
||||
|
||||
map[op].host_addr = ptep;
|
||||
map[op].dom = blkif->domid;
|
||||
map[op].ref = req->seg[i].gref;
|
||||
map[op].flags = GNTMAP_host_map | GNTMAP_application_map
|
||||
flags = GNTMAP_host_map | GNTMAP_application_map
|
||||
| GNTMAP_contains_pte;
|
||||
/* Above interposition comment applies here as well. */
|
||||
if (req->operation == BLKIF_OP_WRITE)
|
||||
map[op].flags |= GNTMAP_readonly;
|
||||
flags |= GNTMAP_readonly;
|
||||
gnttab_set_map_op(&map[op], ptep, flags, req->seg[i].gref,
|
||||
blkif->domid);
|
||||
op++;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,10 +33,8 @@ static int map_frontend_page(blkif_t *blkif, unsigned long shared_page)
|
||||
struct gnttab_map_grant_ref op;
|
||||
int ret;
|
||||
|
||||
op.host_addr = (unsigned long)blkif->blk_ring_area->addr;
|
||||
op.flags = GNTMAP_host_map;
|
||||
op.ref = shared_page;
|
||||
op.dom = blkif->domid;
|
||||
gnttab_set_map_op(&op, (unsigned long)blkif->blk_ring_area->addr,
|
||||
GNTMAP_host_map, shared_page, blkif->domid);
|
||||
|
||||
lock_vm_area(blkif->blk_ring_area);
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
|
||||
@@ -59,9 +57,8 @@ static void unmap_frontend_page(blkif_t *blkif)
|
||||
struct gnttab_unmap_grant_ref op;
|
||||
int ret;
|
||||
|
||||
op.host_addr = (unsigned long)blkif->blk_ring_area->addr;
|
||||
op.handle = blkif->shmem_handle;
|
||||
op.dev_bus_addr = 0;
|
||||
gnttab_set_unmap_op(&op, (unsigned long)blkif->blk_ring_area->addr,
|
||||
GNTMAP_host_map, blkif->shmem_handle);
|
||||
|
||||
lock_vm_area(blkif->blk_ring_area);
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
|
||||
|
||||
@@ -513,6 +513,8 @@ static void ack_dynirq(unsigned int irq)
|
||||
{
|
||||
int evtchn = evtchn_from_irq(irq);
|
||||
|
||||
move_native_irq(irq);
|
||||
|
||||
if (VALID_EVTCHN(evtchn)) {
|
||||
mask_evtchn(evtchn);
|
||||
clear_evtchn(evtchn);
|
||||
@@ -636,6 +638,8 @@ static void ack_pirq(unsigned int irq)
|
||||
{
|
||||
int evtchn = evtchn_from_irq(irq);
|
||||
|
||||
move_native_irq(irq);
|
||||
|
||||
if (VALID_EVTCHN(evtchn)) {
|
||||
mask_evtchn(evtchn);
|
||||
clear_evtchn(evtchn);
|
||||
|
||||
@@ -65,6 +65,7 @@ EXPORT_SYMBOL_GPL(gnttab_end_foreign_transfer);
|
||||
EXPORT_SYMBOL_GPL(gnttab_alloc_grant_references);
|
||||
EXPORT_SYMBOL_GPL(gnttab_free_grant_references);
|
||||
EXPORT_SYMBOL_GPL(gnttab_free_grant_reference);
|
||||
EXPORT_SYMBOL_GPL(gnttab_empty_grant_references);
|
||||
EXPORT_SYMBOL_GPL(gnttab_claim_grant_reference);
|
||||
EXPORT_SYMBOL_GPL(gnttab_release_grant_reference);
|
||||
EXPORT_SYMBOL_GPL(gnttab_request_free_callback);
|
||||
@@ -324,6 +325,12 @@ gnttab_alloc_grant_references(u16 count, grant_ref_t *head)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
gnttab_empty_grant_references(const grant_ref_t *private_head)
|
||||
{
|
||||
return (*private_head == GNTTAB_LIST_END);
|
||||
}
|
||||
|
||||
int
|
||||
gnttab_claim_grant_reference(grant_ref_t *private_head)
|
||||
{
|
||||
|
||||
@@ -150,10 +150,8 @@ static int map_frontend_pages(
|
||||
struct gnttab_map_grant_ref op;
|
||||
int ret;
|
||||
|
||||
op.host_addr = (unsigned long)netif->tx_comms_area->addr;
|
||||
op.flags = GNTMAP_host_map;
|
||||
op.ref = tx_ring_ref;
|
||||
op.dom = netif->domid;
|
||||
gnttab_set_map_op(&op, (unsigned long)netif->tx_comms_area->addr,
|
||||
GNTMAP_host_map, tx_ring_ref, netif->domid);
|
||||
|
||||
lock_vm_area(netif->tx_comms_area);
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
|
||||
@@ -168,10 +166,8 @@ static int map_frontend_pages(
|
||||
netif->tx_shmem_ref = tx_ring_ref;
|
||||
netif->tx_shmem_handle = op.handle;
|
||||
|
||||
op.host_addr = (unsigned long)netif->rx_comms_area->addr;
|
||||
op.flags = GNTMAP_host_map;
|
||||
op.ref = rx_ring_ref;
|
||||
op.dom = netif->domid;
|
||||
gnttab_set_map_op(&op, (unsigned long)netif->rx_comms_area->addr,
|
||||
GNTMAP_host_map, rx_ring_ref, netif->domid);
|
||||
|
||||
lock_vm_area(netif->rx_comms_area);
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
|
||||
@@ -194,18 +190,16 @@ static void unmap_frontend_pages(netif_t *netif)
|
||||
struct gnttab_unmap_grant_ref op;
|
||||
int ret;
|
||||
|
||||
op.host_addr = (unsigned long)netif->tx_comms_area->addr;
|
||||
op.handle = netif->tx_shmem_handle;
|
||||
op.dev_bus_addr = 0;
|
||||
gnttab_set_unmap_op(&op, (unsigned long)netif->tx_comms_area->addr,
|
||||
GNTMAP_host_map, netif->tx_shmem_handle);
|
||||
|
||||
lock_vm_area(netif->tx_comms_area);
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
|
||||
unlock_vm_area(netif->tx_comms_area);
|
||||
BUG_ON(ret);
|
||||
|
||||
op.host_addr = (unsigned long)netif->rx_comms_area->addr;
|
||||
op.handle = netif->rx_shmem_handle;
|
||||
op.dev_bus_addr = 0;
|
||||
gnttab_set_unmap_op(&op, (unsigned long)netif->rx_comms_area->addr,
|
||||
GNTMAP_host_map, netif->rx_shmem_handle);
|
||||
|
||||
lock_vm_area(netif->rx_comms_area);
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
|
||||
|
||||
@@ -453,9 +453,9 @@ inline static void net_tx_action_dealloc(void)
|
||||
gop = tx_unmap_ops;
|
||||
while (dc != dp) {
|
||||
pending_idx = dealloc_ring[MASK_PEND_IDX(dc++)];
|
||||
gop->host_addr = MMAP_VADDR(pending_idx);
|
||||
gop->dev_bus_addr = 0;
|
||||
gop->handle = grant_tx_handle[pending_idx];
|
||||
gnttab_set_unmap_op(gop, MMAP_VADDR(pending_idx),
|
||||
GNTMAP_host_map,
|
||||
grant_tx_handle[pending_idx]);
|
||||
gop++;
|
||||
}
|
||||
ret = HYPERVISOR_grant_table_op(
|
||||
@@ -579,10 +579,9 @@ static void net_tx_action(unsigned long unused)
|
||||
/* Packets passed to netif_rx() must have some headroom. */
|
||||
skb_reserve(skb, 16);
|
||||
|
||||
mop->host_addr = MMAP_VADDR(pending_idx);
|
||||
mop->dom = netif->domid;
|
||||
mop->ref = txreq.gref;
|
||||
mop->flags = GNTMAP_host_map | GNTMAP_readonly;
|
||||
gnttab_set_map_op(mop, MMAP_VADDR(pending_idx),
|
||||
GNTMAP_host_map | GNTMAP_readonly,
|
||||
txreq.gref, netif->domid);
|
||||
mop++;
|
||||
|
||||
memcpy(&pending_tx_info[pending_idx].req,
|
||||
|
||||
@@ -106,7 +106,7 @@ struct netfront_info
|
||||
/* Receive-ring batched refills. */
|
||||
#define RX_MIN_TARGET 8
|
||||
#define RX_DFL_MIN_TARGET 64
|
||||
#define RX_MAX_TARGET NET_RX_RING_SIZE
|
||||
#define RX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
|
||||
int rx_min_target, rx_max_target, rx_target;
|
||||
struct sk_buff_head rx_batch;
|
||||
|
||||
@@ -119,6 +119,7 @@ struct netfront_info
|
||||
struct sk_buff *tx_skbs[NET_TX_RING_SIZE+1];
|
||||
struct sk_buff *rx_skbs[NET_RX_RING_SIZE+1];
|
||||
|
||||
#define TX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
|
||||
grant_ref_t gref_tx_head;
|
||||
grant_ref_t grant_tx_ref[NET_TX_RING_SIZE + 1];
|
||||
grant_ref_t gref_rx_head;
|
||||
@@ -505,8 +506,9 @@ static void network_tx_buf_gc(struct net_device *dev)
|
||||
} while (prod != np->tx.sring->rsp_prod);
|
||||
|
||||
out:
|
||||
if (np->tx_full &&
|
||||
((np->tx.sring->req_prod - prod) < NET_TX_RING_SIZE)) {
|
||||
if ((np->tx_full) &&
|
||||
((np->tx.sring->req_prod - prod) < NET_TX_RING_SIZE) &&
|
||||
!gnttab_empty_grant_references(&np->gref_tx_head)) {
|
||||
np->tx_full = 0;
|
||||
if (np->user_state == UST_OPEN)
|
||||
netif_wake_queue(dev);
|
||||
@@ -705,7 +707,8 @@ static int network_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
|
||||
network_tx_buf_gc(dev);
|
||||
|
||||
if (RING_FULL(&np->tx)) {
|
||||
if (RING_FULL(&np->tx) ||
|
||||
gnttab_empty_grant_references(&np->gref_tx_head)) {
|
||||
np->tx_full = 1;
|
||||
netif_stop_queue(dev);
|
||||
}
|
||||
@@ -1140,14 +1143,14 @@ static int create_netdev(int handle, struct xenbus_device *dev,
|
||||
}
|
||||
|
||||
/* A grant for every tx ring slot */
|
||||
if (gnttab_alloc_grant_references(NET_TX_RING_SIZE,
|
||||
if (gnttab_alloc_grant_references(TX_MAX_TARGET,
|
||||
&np->gref_tx_head) < 0) {
|
||||
printk(KERN_ALERT "#### netfront can't alloc tx grant refs\n");
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
/* A grant for every rx ring slot */
|
||||
if (gnttab_alloc_grant_references(NET_RX_RING_SIZE,
|
||||
if (gnttab_alloc_grant_references(RX_MAX_TARGET,
|
||||
&np->gref_rx_head) < 0) {
|
||||
printk(KERN_ALERT "#### netfront can't alloc rx grant refs\n");
|
||||
gnttab_free_grant_references(np->gref_tx_head);
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include "common.h"
|
||||
#include <xen/balloon.h>
|
||||
#include <xen/gnttab.h>
|
||||
|
||||
static kmem_cache_t *tpmif_cachep;
|
||||
int num_frontends = 0;
|
||||
@@ -72,12 +73,10 @@ tpmif_t *tpmif_find(domid_t domid, long int instance)
|
||||
static int map_frontend_page(tpmif_t *tpmif, unsigned long shared_page)
|
||||
{
|
||||
int ret;
|
||||
struct gnttab_map_grant_ref op = {
|
||||
.host_addr = (unsigned long)tpmif->tx_area->addr,
|
||||
.flags = GNTMAP_host_map,
|
||||
.ref = shared_page,
|
||||
.dom = tpmif->domid,
|
||||
};
|
||||
struct gnttab_map_grant_ref op;
|
||||
|
||||
gnttab_set_map_op(&op, (unsigned long)tpmif->tx_area->addr,
|
||||
GNTMAP_host_map, shared_page, tpmif->domid);
|
||||
|
||||
lock_vm_area(tpmif->tx_area);
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
|
||||
@@ -100,9 +99,8 @@ static void unmap_frontend_page(tpmif_t *tpmif)
|
||||
struct gnttab_unmap_grant_ref op;
|
||||
int ret;
|
||||
|
||||
op.host_addr = (unsigned long)tpmif->tx_area->addr;
|
||||
op.handle = tpmif->shmem_handle;
|
||||
op.dev_bus_addr = 0;
|
||||
gnttab_set_unmap_op(&op, (unsigned long)tpmif->tx_area->addr,
|
||||
GNTMAP_host_map, tpmif->shmem_handle);
|
||||
|
||||
lock_vm_area(tpmif->tx_area);
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <asm/uaccess.h>
|
||||
#include <xen/xenbus.h>
|
||||
#include <xen/interface/grant_table.h>
|
||||
#include <xen/gnttab.h>
|
||||
|
||||
/* local data structures */
|
||||
struct data_exchange {
|
||||
@@ -278,10 +279,8 @@ int _packet_write(struct packet *pak,
|
||||
return 0;
|
||||
}
|
||||
|
||||
map_op.host_addr = MMAP_VADDR(tpmif, i);
|
||||
map_op.flags = GNTMAP_host_map;
|
||||
map_op.ref = tx->ref;
|
||||
map_op.dom = tpmif->domid;
|
||||
gnttab_set_map_op(&map_op, MMAP_VADDR(tpmif, i),
|
||||
GNTMAP_host_map, tx->ref, tpmif->domid);
|
||||
|
||||
if (unlikely(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
|
||||
&map_op, 1))) {
|
||||
@@ -308,9 +307,8 @@ int _packet_write(struct packet *pak,
|
||||
}
|
||||
tx->size = tocopy;
|
||||
|
||||
unmap_op.host_addr = MMAP_VADDR(tpmif, i);
|
||||
unmap_op.handle = handle;
|
||||
unmap_op.dev_bus_addr = 0;
|
||||
gnttab_set_unmap_op(&unmap_op, MMAP_VADDR(tpmif, i),
|
||||
GNTMAP_host_map, handle);
|
||||
|
||||
if (unlikely
|
||||
(HYPERVISOR_grant_table_op
|
||||
@@ -422,10 +420,8 @@ static int packet_read_shmem(struct packet *pak,
|
||||
|
||||
tx = &tpmif->tx->ring[i].req;
|
||||
|
||||
map_op.host_addr = MMAP_VADDR(tpmif, i);
|
||||
map_op.flags = GNTMAP_host_map;
|
||||
map_op.ref = tx->ref;
|
||||
map_op.dom = tpmif->domid;
|
||||
gnttab_set_map_op(&map_op, MMAP_VADDR(tpmif, i),
|
||||
GNTMAP_host_map, tx->ref, tpmif->domid);
|
||||
|
||||
if (unlikely(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref,
|
||||
&map_op, 1))) {
|
||||
@@ -461,9 +457,8 @@ static int packet_read_shmem(struct packet *pak,
|
||||
tpmif->domid, buffer[offset], buffer[offset + 1],
|
||||
buffer[offset + 2], buffer[offset + 3]);
|
||||
|
||||
unmap_op.host_addr = MMAP_VADDR(tpmif, i);
|
||||
unmap_op.handle = handle;
|
||||
unmap_op.dev_bus_addr = 0;
|
||||
gnttab_set_unmap_op(&unmap_op, MMAP_VADDR(tpmif, i),
|
||||
GNTMAP_host_map, handle);
|
||||
|
||||
if (unlikely
|
||||
(HYPERVISOR_grant_table_op
|
||||
|
||||
@@ -164,10 +164,10 @@ static void frontend_changed(struct xenbus_device *dev,
|
||||
|
||||
switch (frontend_state) {
|
||||
case XenbusStateInitialising:
|
||||
case XenbusStateConnected:
|
||||
case XenbusStateInitialised:
|
||||
break;
|
||||
|
||||
case XenbusStateInitialised:
|
||||
case XenbusStateConnected:
|
||||
err = connect_ring(be);
|
||||
if (err) {
|
||||
return;
|
||||
|
||||
@@ -334,12 +334,6 @@ again:
|
||||
goto abort_transaction;
|
||||
}
|
||||
|
||||
err = xenbus_printf(xbt, dev->nodename,
|
||||
"state", "%d", XenbusStateInitialised);
|
||||
if (err) {
|
||||
goto abort_transaction;
|
||||
}
|
||||
|
||||
err = xenbus_transaction_end(xbt, 0);
|
||||
if (err == -EAGAIN)
|
||||
goto again;
|
||||
@@ -347,6 +341,9 @@ again:
|
||||
xenbus_dev_fatal(dev, err, "completing transaction");
|
||||
goto destroy_tpmring;
|
||||
}
|
||||
|
||||
xenbus_switch_state(dev, XenbusStateConnected);
|
||||
|
||||
return 0;
|
||||
|
||||
abort_transaction:
|
||||
@@ -387,6 +384,7 @@ static void backend_changed(struct xenbus_device *dev,
|
||||
if (tp->is_suspended == 0) {
|
||||
device_unregister(&dev->dev);
|
||||
}
|
||||
xenbus_switch_state(dev, XenbusStateClosed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -439,6 +437,7 @@ static int tpmfront_suspend(struct xenbus_device *dev)
|
||||
|
||||
/* lock, so no app can send */
|
||||
mutex_lock(&suspend_lock);
|
||||
xenbus_switch_state(dev, XenbusStateClosed);
|
||||
tp->is_suspended = 1;
|
||||
|
||||
for (ctr = 0; atomic_read(&tp->tx_busy) && ctr <= 25; ctr++) {
|
||||
|
||||
@@ -37,11 +37,7 @@
|
||||
/* Based on Rusty Russell's skeleton driver's map_page */
|
||||
int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr)
|
||||
{
|
||||
struct gnttab_map_grant_ref op = {
|
||||
.flags = GNTMAP_host_map,
|
||||
.ref = gnt_ref,
|
||||
.dom = dev->otherend_id,
|
||||
};
|
||||
struct gnttab_map_grant_ref op;
|
||||
struct vm_struct *area;
|
||||
|
||||
*vaddr = NULL;
|
||||
@@ -50,8 +46,9 @@ int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr)
|
||||
if (!area)
|
||||
return -ENOMEM;
|
||||
|
||||
op.host_addr = (unsigned long)area->addr;
|
||||
|
||||
gnttab_set_map_op(&op, (unsigned long)area->addr, GNTMAP_host_map,
|
||||
gnt_ref, dev->otherend_id);
|
||||
|
||||
lock_vm_area(area);
|
||||
BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1));
|
||||
unlock_vm_area(area);
|
||||
@@ -76,13 +73,10 @@ EXPORT_SYMBOL_GPL(xenbus_map_ring_valloc);
|
||||
int xenbus_map_ring(struct xenbus_device *dev, int gnt_ref,
|
||||
grant_handle_t *handle, void *vaddr)
|
||||
{
|
||||
struct gnttab_map_grant_ref op = {
|
||||
.host_addr = (unsigned long)vaddr,
|
||||
.flags = GNTMAP_host_map,
|
||||
.ref = gnt_ref,
|
||||
.dom = dev->otherend_id,
|
||||
};
|
||||
|
||||
struct gnttab_map_grant_ref op;
|
||||
|
||||
gnttab_set_map_op(&op, (unsigned long)vaddr, GNTMAP_host_map,
|
||||
gnt_ref, dev->otherend_id);
|
||||
BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1));
|
||||
|
||||
if (op.status != GNTST_okay) {
|
||||
@@ -101,9 +95,7 @@ EXPORT_SYMBOL_GPL(xenbus_map_ring);
|
||||
int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr)
|
||||
{
|
||||
struct vm_struct *area;
|
||||
struct gnttab_unmap_grant_ref op = {
|
||||
.host_addr = (unsigned long)vaddr,
|
||||
};
|
||||
struct gnttab_unmap_grant_ref op;
|
||||
|
||||
/* It'd be nice if linux/vmalloc.h provided a find_vm_area(void *addr)
|
||||
* method so that we don't have to muck with vmalloc internals here.
|
||||
@@ -124,7 +116,8 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr)
|
||||
return GNTST_bad_virt_addr;
|
||||
}
|
||||
|
||||
op.handle = (grant_handle_t)area->phys_addr;
|
||||
gnttab_set_unmap_op(&op, (unsigned long)vaddr, GNTMAP_host_map,
|
||||
(grant_handle_t)area->phys_addr);
|
||||
|
||||
lock_vm_area(area);
|
||||
BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
|
||||
@@ -145,11 +138,10 @@ EXPORT_SYMBOL_GPL(xenbus_unmap_ring_vfree);
|
||||
int xenbus_unmap_ring(struct xenbus_device *dev,
|
||||
grant_handle_t handle, void *vaddr)
|
||||
{
|
||||
struct gnttab_unmap_grant_ref op = {
|
||||
.host_addr = (unsigned long)vaddr,
|
||||
.handle = handle,
|
||||
};
|
||||
struct gnttab_unmap_grant_ref op;
|
||||
|
||||
gnttab_set_unmap_op(&op, (unsigned long)vaddr, GNTMAP_host_map,
|
||||
handle);
|
||||
BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
|
||||
|
||||
if (op.status != GNTST_okay)
|
||||
|
||||
@@ -114,6 +114,7 @@ static ssize_t xenbus_dev_write(struct file *filp,
|
||||
{
|
||||
struct xenbus_dev_data *u = filp->private_data;
|
||||
struct xenbus_dev_transaction *trans = NULL;
|
||||
uint32_t msg_type;
|
||||
void *reply;
|
||||
|
||||
if ((len + u->len) > sizeof(u->u.buffer))
|
||||
@@ -126,7 +127,9 @@ static ssize_t xenbus_dev_write(struct file *filp,
|
||||
if (u->len < (sizeof(u->u.msg) + u->u.msg.len))
|
||||
return len;
|
||||
|
||||
switch (u->u.msg.type) {
|
||||
msg_type = u->u.msg.type;
|
||||
|
||||
switch (msg_type) {
|
||||
case XS_TRANSACTION_START:
|
||||
case XS_TRANSACTION_END:
|
||||
case XS_DIRECTORY:
|
||||
@@ -138,7 +141,7 @@ static ssize_t xenbus_dev_write(struct file *filp,
|
||||
case XS_MKDIR:
|
||||
case XS_RM:
|
||||
case XS_SET_PERMS:
|
||||
if (u->u.msg.type == XS_TRANSACTION_START) {
|
||||
if (msg_type == XS_TRANSACTION_START) {
|
||||
trans = kmalloc(sizeof(*trans), GFP_KERNEL);
|
||||
if (!trans)
|
||||
return -ENOMEM;
|
||||
@@ -150,10 +153,10 @@ static ssize_t xenbus_dev_write(struct file *filp,
|
||||
return PTR_ERR(reply);
|
||||
}
|
||||
|
||||
if (u->u.msg.type == XS_TRANSACTION_START) {
|
||||
if (msg_type == XS_TRANSACTION_START) {
|
||||
trans->handle = simple_strtoul(reply, NULL, 0);
|
||||
list_add(&trans->list, &u->transactions);
|
||||
} else if (u->u.msg.type == XS_TRANSACTION_END) {
|
||||
} else if (msg_type == XS_TRANSACTION_END) {
|
||||
list_for_each_entry(trans, &u->transactions, list)
|
||||
if (trans->handle == u->u.msg.tx_id)
|
||||
break;
|
||||
|
||||
@@ -825,6 +825,8 @@ static int resume_dev(struct device *dev, void *data)
|
||||
return err;
|
||||
}
|
||||
|
||||
xdev->state = XenbusStateInitialising;
|
||||
|
||||
if (drv->resume)
|
||||
err = drv->resume(xdev);
|
||||
if (err)
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <linux/config.h>
|
||||
#include <asm/hypervisor.h>
|
||||
#include <xen/interface/grant_table.h>
|
||||
#include <xen/features.h>
|
||||
|
||||
/* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */
|
||||
#ifdef __ia64__
|
||||
@@ -90,6 +91,8 @@ void gnttab_free_grant_reference(grant_ref_t ref);
|
||||
|
||||
void gnttab_free_grant_references(grant_ref_t head);
|
||||
|
||||
int gnttab_empty_grant_references(const grant_ref_t *pprivate_head);
|
||||
|
||||
int gnttab_claim_grant_reference(grant_ref_t *pprivate_head);
|
||||
|
||||
void gnttab_release_grant_reference(grant_ref_t *private_head,
|
||||
@@ -113,6 +116,37 @@ void gnttab_grant_foreign_transfer_ref(grant_ref_t, domid_t domid,
|
||||
int gnttab_suspend(void);
|
||||
int gnttab_resume(void);
|
||||
|
||||
static inline void
|
||||
gnttab_set_map_op(struct gnttab_map_grant_ref *map, unsigned long addr,
|
||||
uint32_t flags, grant_ref_t ref, domid_t domid)
|
||||
{
|
||||
if (flags & GNTMAP_contains_pte)
|
||||
map->host_addr = addr;
|
||||
else if (xen_feature(XENFEAT_auto_translated_physmap))
|
||||
map->host_addr = __pa(addr);
|
||||
else
|
||||
map->host_addr = addr;
|
||||
|
||||
map->flags = flags;
|
||||
map->ref = ref;
|
||||
map->dom = domid;
|
||||
}
|
||||
|
||||
static inline void
|
||||
gnttab_set_unmap_op(struct gnttab_unmap_grant_ref *unmap, unsigned long addr,
|
||||
uint32_t flags, grant_handle_t handle)
|
||||
{
|
||||
if (flags & GNTMAP_contains_pte)
|
||||
unmap->host_addr = addr;
|
||||
else if (xen_feature(XENFEAT_auto_translated_physmap))
|
||||
unmap->host_addr = __pa(addr);
|
||||
else
|
||||
unmap->host_addr = addr;
|
||||
|
||||
unmap->handle = handle;
|
||||
unmap->dev_bus_addr = 0;
|
||||
}
|
||||
|
||||
#endif /* __ASM_GNTTAB_H__ */
|
||||
|
||||
/*
|
||||
|
||||
@@ -90,8 +90,8 @@ abs_to_rel ${AD} ${AS}
|
||||
RS=$DESTPATH
|
||||
|
||||
# Arch-specific pre-processing
|
||||
if [ -x arch/${LINUX_ARCH}/xen-mkbuildtree-pre ]; then
|
||||
arch/${LINUX_ARCH}/xen-mkbuildtree-pre
|
||||
if [ -e arch/${LINUX_ARCH}/xen-mkbuildtree-pre ]; then
|
||||
bash arch/${LINUX_ARCH}/xen-mkbuildtree-pre
|
||||
fi
|
||||
|
||||
# Remove old copies of files and directories at the destination
|
||||
@@ -115,6 +115,6 @@ relative_lndir ../../../${RS}/../xen/include/public
|
||||
|
||||
# Arch-specific post-processing
|
||||
cd ${AD}
|
||||
if [ -x arch/${LINUX_ARCH}/xen-mkbuildtree-post ]; then
|
||||
arch/${LINUX_ARCH}/xen-mkbuildtree-post
|
||||
if [ -e arch/${LINUX_ARCH}/xen-mkbuildtree-post ]; then
|
||||
bash arch/${LINUX_ARCH}/xen-mkbuildtree-post
|
||||
fi
|
||||
@@ -1294,6 +1294,7 @@ int dev_queue_xmit(struct sk_buff *skb)
|
||||
if ((skb->h.raw + skb->csum + 2) > skb->tail)
|
||||
goto out_kfree_skb;
|
||||
skb->ip_summed = CHECKSUM_HW;
|
||||
skb->proto_csum_blank = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ rm -rf gdb-6.2.1 gdb-6.2.1-linux-i386-xen
|
||||
tar xjf gdb-6.2.1.tar.bz2
|
||||
|
||||
cd gdb-6.2.1-xen-sparse
|
||||
./mkbuildtree ../gdb-6.2.1
|
||||
bash ./mkbuildtree ../gdb-6.2.1
|
||||
|
||||
cd ..
|
||||
mkdir gdb-6.2.1-linux-i386-xen
|
||||
|
||||
@@ -127,3 +127,6 @@
|
||||
|
||||
# Whether to enable core-dumps when domains crash.
|
||||
#(enable-dump no)
|
||||
|
||||
# The tool used for initiating virtual TPM migration
|
||||
#(external-migration-tool '')
|
||||
@@ -21,7 +21,7 @@
|
||||
# External CFLAGS can do more harm than good.
|
||||
CFLAGS :=
|
||||
|
||||
XEN_TARGET_ARCH = x86_32
|
||||
override XEN_TARGET_ARCH = x86_32
|
||||
XEN_ROOT = ../../..
|
||||
include $(XEN_ROOT)/Config.mk
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
# External CFLAGS can do more harm than good.
|
||||
CFLAGS :=
|
||||
|
||||
XEN_TARGET_ARCH = x86_32
|
||||
override XEN_TARGET_ARCH = x86_32
|
||||
XEN_ROOT = ../../..
|
||||
include $(XEN_ROOT)/Config.mk
|
||||
|
||||
|
||||
+1
-1
@@ -138,7 +138,7 @@ int adlib_enabled = 1;
|
||||
int gus_enabled = 1;
|
||||
int pci_enabled = 1;
|
||||
int prep_enabled = 0;
|
||||
int rtc_utc = 0;
|
||||
int rtc_utc = 1;
|
||||
int cirrus_vga_enabled = 1;
|
||||
int vga_accelerate = 1;
|
||||
int graphic_width = 800;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/******************************************************************************
|
||||
* xc_bvtsched.c
|
||||
*
|
||||
*
|
||||
* API for manipulating parameters of the Borrowed Virtual Time scheduler.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2003, K A Fraser.
|
||||
*/
|
||||
|
||||
@@ -26,7 +26,7 @@ int xc_bvtsched_global_get(int xc_handle,
|
||||
{
|
||||
DECLARE_DOM0_OP;
|
||||
int ret;
|
||||
|
||||
|
||||
op.cmd = DOM0_SCHEDCTL;
|
||||
op.u.schedctl.sched_id = SCHED_BVT;
|
||||
op.u.schedctl.direction = SCHED_INFO_GET;
|
||||
@@ -71,7 +71,7 @@ int xc_bvtsched_domain_get(int xc_handle,
|
||||
long long *warpl,
|
||||
long long *warpu)
|
||||
{
|
||||
|
||||
|
||||
DECLARE_DOM0_OP;
|
||||
int ret;
|
||||
struct bvt_adjdom *adjptr = &op.u.adjustdom.u.bvt;
|
||||
|
||||
@@ -23,7 +23,7 @@ copy_from_domain_page(int xc_handle,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
xc_domain_dumpcore_via_callback(int xc_handle,
|
||||
uint32_t domid,
|
||||
void *args,
|
||||
@@ -45,13 +45,13 @@ xc_domain_dumpcore_via_callback(int xc_handle,
|
||||
PERROR("Could not allocate dump_mem");
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
|
||||
if ( xc_domain_getinfo(xc_handle, domid, 1, &info) != 1 )
|
||||
{
|
||||
PERROR("Could not get info for domain");
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
|
||||
if ( domid != info.domid )
|
||||
{
|
||||
PERROR("Domain %d does not exist", domid);
|
||||
@@ -61,10 +61,10 @@ xc_domain_dumpcore_via_callback(int xc_handle,
|
||||
for ( i = 0; i <= info.max_vcpu_id; i++ )
|
||||
if ( xc_vcpu_getcontext(xc_handle, domid, i, &ctxt[nr_vcpus]) == 0)
|
||||
nr_vcpus++;
|
||||
|
||||
|
||||
nr_pages = info.nr_pages;
|
||||
|
||||
header.xch_magic = XC_CORE_MAGIC;
|
||||
header.xch_magic = XC_CORE_MAGIC;
|
||||
header.xch_nr_vcpus = nr_vcpus;
|
||||
header.xch_nr_pages = nr_pages;
|
||||
header.xch_ctxt_offset = sizeof(struct xc_core_header);
|
||||
@@ -74,7 +74,7 @@ xc_domain_dumpcore_via_callback(int xc_handle,
|
||||
(sizeof(vcpu_guest_context_t) * nr_vcpus) +
|
||||
(nr_pages * sizeof(unsigned long)));
|
||||
header.xch_pages_offset = round_pgup(dummy_len);
|
||||
|
||||
|
||||
sts = dump_rtn(args, (char *)&header, sizeof(struct xc_core_header));
|
||||
if ( sts != 0 )
|
||||
goto error_out;
|
||||
@@ -150,7 +150,7 @@ static int local_file_dump(void *args, char *buffer, unsigned int length)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
xc_domain_dumpcore(int xc_handle,
|
||||
uint32_t domid,
|
||||
const char *corename)
|
||||
@@ -163,7 +163,7 @@ xc_domain_dumpcore(int xc_handle,
|
||||
PERROR("Could not open corefile %s: %s", corename, strerror(errno));
|
||||
return -errno;
|
||||
}
|
||||
|
||||
|
||||
sts = xc_domain_dumpcore_via_callback(
|
||||
xc_handle, domid, &da, &local_file_dump);
|
||||
|
||||
|
||||
+30
-30
@@ -1,8 +1,8 @@
|
||||
/******************************************************************************
|
||||
* xc_domain.c
|
||||
*
|
||||
*
|
||||
* API for manipulating and obtaining information on domains.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2003, K A Fraser.
|
||||
*/
|
||||
|
||||
@@ -26,17 +26,17 @@ int xc_domain_create(int xc_handle,
|
||||
|
||||
*pdomid = (uint16_t)op.u.createdomain.domain;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int xc_domain_pause(int xc_handle,
|
||||
int xc_domain_pause(int xc_handle,
|
||||
uint32_t domid)
|
||||
{
|
||||
DECLARE_DOM0_OP;
|
||||
op.cmd = DOM0_PAUSEDOMAIN;
|
||||
op.u.pausedomain.domain = (domid_t)domid;
|
||||
return do_dom0_op(xc_handle, &op);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int xc_domain_unpause(int xc_handle,
|
||||
@@ -46,7 +46,7 @@ int xc_domain_unpause(int xc_handle,
|
||||
op.cmd = DOM0_UNPAUSEDOMAIN;
|
||||
op.u.unpausedomain.domain = (domid_t)domid;
|
||||
return do_dom0_op(xc_handle, &op);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int xc_domain_destroy(int xc_handle,
|
||||
@@ -88,7 +88,7 @@ int xc_domain_shutdown(int xc_handle,
|
||||
|
||||
|
||||
int xc_vcpu_setaffinity(int xc_handle,
|
||||
uint32_t domid,
|
||||
uint32_t domid,
|
||||
int vcpu,
|
||||
cpumap_t cpumap)
|
||||
{
|
||||
@@ -109,7 +109,7 @@ int xc_domain_getinfo(int xc_handle,
|
||||
unsigned int nr_doms;
|
||||
uint32_t next_domid = first_domid;
|
||||
DECLARE_DOM0_OP;
|
||||
int rc = 0;
|
||||
int rc = 0;
|
||||
|
||||
memset(info, 0, max_doms*sizeof(xc_dominfo_t));
|
||||
|
||||
@@ -127,8 +127,8 @@ int xc_domain_getinfo(int xc_handle,
|
||||
info->blocked = !!(op.u.getdomaininfo.flags & DOMFLAGS_BLOCKED);
|
||||
info->running = !!(op.u.getdomaininfo.flags & DOMFLAGS_RUNNING);
|
||||
|
||||
info->shutdown_reason =
|
||||
(op.u.getdomaininfo.flags>>DOMFLAGS_SHUTDOWNSHIFT) &
|
||||
info->shutdown_reason =
|
||||
(op.u.getdomaininfo.flags>>DOMFLAGS_SHUTDOWNSHIFT) &
|
||||
DOMFLAGS_SHUTDOWNMASK;
|
||||
|
||||
if ( info->shutdown && (info->shutdown_reason == SHUTDOWN_crash) )
|
||||
@@ -152,7 +152,7 @@ int xc_domain_getinfo(int xc_handle,
|
||||
info++;
|
||||
}
|
||||
|
||||
if( !nr_doms ) return rc;
|
||||
if( !nr_doms ) return rc;
|
||||
|
||||
return nr_doms;
|
||||
}
|
||||
@@ -167,7 +167,7 @@ int xc_domain_getinfolist(int xc_handle,
|
||||
|
||||
if ( mlock(info, max_domains*sizeof(xc_domaininfo_t)) != 0 )
|
||||
return -1;
|
||||
|
||||
|
||||
op.cmd = DOM0_GETDOMAININFOLIST;
|
||||
op.u.getdomaininfolist.first_domain = first_domain;
|
||||
op.u.getdomaininfolist.max_domains = max_domains;
|
||||
@@ -177,10 +177,10 @@ int xc_domain_getinfolist(int xc_handle,
|
||||
ret = -1;
|
||||
else
|
||||
ret = op.u.getdomaininfolist.num_domains;
|
||||
|
||||
|
||||
if ( munlock(info, max_domains*sizeof(xc_domaininfo_t)) != 0 )
|
||||
ret = -1;
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ int xc_vcpu_getcontext(int xc_handle,
|
||||
|
||||
|
||||
int xc_shadow_control(int xc_handle,
|
||||
uint32_t domid,
|
||||
uint32_t domid,
|
||||
unsigned int sop,
|
||||
unsigned long *dirty_bitmap,
|
||||
unsigned long pages,
|
||||
@@ -238,11 +238,11 @@ int xc_domain_setcpuweight(int xc_handle,
|
||||
{
|
||||
int sched_id;
|
||||
int ret;
|
||||
|
||||
|
||||
/* Figure out which scheduler is currently used: */
|
||||
if ( (ret = xc_sched_id(xc_handle, &sched_id)) != 0 )
|
||||
return ret;
|
||||
|
||||
|
||||
switch ( sched_id )
|
||||
{
|
||||
case SCHED_BVT:
|
||||
@@ -253,20 +253,20 @@ int xc_domain_setcpuweight(int xc_handle,
|
||||
long long warpl;
|
||||
long long warpu;
|
||||
|
||||
/* Preserve all the scheduling parameters apart
|
||||
/* Preserve all the scheduling parameters apart
|
||||
of MCU advance. */
|
||||
if ( (ret = xc_bvtsched_domain_get(
|
||||
xc_handle, domid, &mcuadv,
|
||||
xc_handle, domid, &mcuadv,
|
||||
&warpback, &warpvalue, &warpl, &warpu)) != 0 )
|
||||
return ret;
|
||||
|
||||
|
||||
/* The MCU advance is inverse of the weight.
|
||||
Default value of the weight is 1, default mcuadv 10.
|
||||
The scaling factor is therefore 10. */
|
||||
if ( weight > 0 )
|
||||
mcuadv = 10 / weight;
|
||||
|
||||
ret = xc_bvtsched_domain_set(xc_handle, domid, mcuadv,
|
||||
|
||||
ret = xc_bvtsched_domain_set(xc_handle, domid, mcuadv,
|
||||
warpback, warpvalue, warpl, warpu);
|
||||
break;
|
||||
}
|
||||
@@ -276,7 +276,7 @@ int xc_domain_setcpuweight(int xc_handle,
|
||||
}
|
||||
|
||||
int xc_domain_setmaxmem(int xc_handle,
|
||||
uint32_t domid,
|
||||
uint32_t domid,
|
||||
unsigned int max_memkb)
|
||||
{
|
||||
DECLARE_DOM0_OP;
|
||||
@@ -287,7 +287,7 @@ int xc_domain_setmaxmem(int xc_handle,
|
||||
}
|
||||
|
||||
int xc_domain_memory_increase_reservation(int xc_handle,
|
||||
uint32_t domid,
|
||||
uint32_t domid,
|
||||
unsigned long nr_extents,
|
||||
unsigned int extent_order,
|
||||
unsigned int address_bits,
|
||||
@@ -297,7 +297,7 @@ int xc_domain_memory_increase_reservation(int xc_handle,
|
||||
struct xen_memory_reservation reservation = {
|
||||
.extent_start = extent_start, /* may be NULL */
|
||||
.nr_extents = nr_extents,
|
||||
.extent_order = extent_order,
|
||||
.extent_order = extent_order,
|
||||
.address_bits = address_bits,
|
||||
.domid = domid
|
||||
};
|
||||
@@ -319,16 +319,16 @@ int xc_domain_memory_increase_reservation(int xc_handle,
|
||||
}
|
||||
|
||||
int xc_domain_memory_decrease_reservation(int xc_handle,
|
||||
uint32_t domid,
|
||||
uint32_t domid,
|
||||
unsigned long nr_extents,
|
||||
unsigned int extent_order,
|
||||
unsigned long *extent_start)
|
||||
{
|
||||
int err;
|
||||
struct xen_memory_reservation reservation = {
|
||||
.extent_start = extent_start,
|
||||
.extent_start = extent_start,
|
||||
.nr_extents = nr_extents,
|
||||
.extent_order = extent_order,
|
||||
.extent_order = extent_order,
|
||||
.address_bits = 0,
|
||||
.domid = domid
|
||||
};
|
||||
@@ -411,7 +411,7 @@ int xc_domain_max_vcpus(int xc_handle, uint32_t domid, unsigned int max)
|
||||
return do_dom0_op(xc_handle, &op);
|
||||
}
|
||||
|
||||
int xc_domain_sethandle(int xc_handle, uint32_t domid,
|
||||
int xc_domain_sethandle(int xc_handle, uint32_t domid,
|
||||
xen_domain_handle_t handle)
|
||||
{
|
||||
DECLARE_DOM0_OP;
|
||||
@@ -506,7 +506,7 @@ int xc_domain_iomem_permission(int xc_handle,
|
||||
op.cmd = DOM0_IOMEM_PERMISSION;
|
||||
op.u.iomem_permission.domain = domid;
|
||||
op.u.iomem_permission.first_mfn = first_mfn;
|
||||
op.u.iomem_permission.nr_mfns = nr_mfns;
|
||||
op.u.iomem_permission.nr_mfns = nr_mfns;
|
||||
op.u.iomem_permission.allow_access = allow_access;
|
||||
|
||||
return do_dom0_op(xc_handle, &op);
|
||||
|
||||
@@ -46,7 +46,7 @@ typedef uint32_t Elf64_Half;
|
||||
typedef uint16_t Elf64_Quarter;
|
||||
|
||||
/*
|
||||
* e_ident[] identification indexes
|
||||
* e_ident[] identification indexes
|
||||
* See http://www.caldera.com/developers/gabi/2000-07-17/ch4.eheader.html
|
||||
*/
|
||||
#define EI_MAG0 0 /* file ID */
|
||||
@@ -57,7 +57,7 @@ typedef uint16_t Elf64_Quarter;
|
||||
#define EI_DATA 5 /* data encoding */
|
||||
#define EI_VERSION 6 /* ELF header version */
|
||||
#define EI_OSABI 7 /* OS/ABI ID */
|
||||
#define EI_ABIVERSION 8 /* ABI version */
|
||||
#define EI_ABIVERSION 8 /* ABI version */
|
||||
#define EI_PAD 9 /* start of pad bytes */
|
||||
#define EI_NIDENT 16 /* Size of e_ident[] */
|
||||
|
||||
@@ -119,7 +119,7 @@ typedef struct elfhdr {
|
||||
Elf32_Half e_phnum; /* number of program header entries */
|
||||
Elf32_Half e_shentsize; /* section header entry size */
|
||||
Elf32_Half e_shnum; /* number of section header entries */
|
||||
Elf32_Half e_shstrndx; /* section header table's "section
|
||||
Elf32_Half e_shstrndx; /* section header table's "section
|
||||
header string table" entry offset */
|
||||
} Elf32_Ehdr;
|
||||
|
||||
@@ -160,7 +160,7 @@ typedef struct {
|
||||
#define EM_486 6 /* Intel 80486 - unused? */
|
||||
#define EM_860 7 /* Intel 80860 */
|
||||
#define EM_MIPS 8 /* MIPS R3000 Big-Endian only */
|
||||
/*
|
||||
/*
|
||||
* Don't know if EM_MIPS_RS4_BE,
|
||||
* EM_SPARC64, EM_PARISC,
|
||||
* or EM_PPC are ABI compliant
|
||||
@@ -441,7 +441,7 @@ typedef struct {
|
||||
#define DT_NUM 25 /* Number used. */
|
||||
#define DT_LOPROC 0x70000000 /* reserved range for processor */
|
||||
#define DT_HIPROC 0x7fffffff /* specific dynamic array tags */
|
||||
|
||||
|
||||
/* Standard ELF hashing function */
|
||||
unsigned int elf_hash(const unsigned char *name);
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/******************************************************************************
|
||||
* xc_evtchn.c
|
||||
*
|
||||
*
|
||||
* API for manipulating and accessing inter-domain event channels.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2004, K A Fraser.
|
||||
*/
|
||||
|
||||
@@ -44,7 +44,7 @@ int xc_evtchn_alloc_unbound(int xc_handle,
|
||||
|
||||
if ( (rc = do_evtchn_op(xc_handle, &op)) == 0 )
|
||||
rc = op.u.alloc_unbound.port;
|
||||
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -62,6 +62,6 @@ int xc_evtchn_status(int xc_handle,
|
||||
|
||||
if ( (rc = do_evtchn_op(xc_handle, &op)) == 0 )
|
||||
memcpy(status, &op.u.status, sizeof(*status));
|
||||
|
||||
|
||||
return rc;
|
||||
}
|
||||
+85
-85
@@ -22,7 +22,7 @@ unsigned long xc_ia64_fpsr_default(void)
|
||||
return FPSR_DEFAULT;
|
||||
}
|
||||
|
||||
int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */,
|
||||
int (*suspend)(int domid))
|
||||
{
|
||||
@@ -53,11 +53,11 @@ xc_plan9_build(int xc_handle,
|
||||
VMM don't handle this now.
|
||||
This method will touch guest buffer to make sure the buffer's mapping
|
||||
is tracked by VMM,
|
||||
*/
|
||||
*/
|
||||
|
||||
int xc_ia64_get_pfn_list(int xc_handle,
|
||||
uint32_t domid,
|
||||
unsigned long *pfn_buf,
|
||||
uint32_t domid,
|
||||
unsigned long *pfn_buf,
|
||||
unsigned int start_page,
|
||||
unsigned int nr_pages)
|
||||
{
|
||||
@@ -78,16 +78,16 @@ int xc_ia64_get_pfn_list(int xc_handle,
|
||||
op.u.getmemlist.buffer = __pfn_buf;
|
||||
|
||||
if ( (max_pfns != -1UL)
|
||||
&& mlock(__pfn_buf, __nr_pages * sizeof(unsigned long)) != 0 )
|
||||
&& mlock(__pfn_buf, __nr_pages * sizeof(unsigned long)) != 0 )
|
||||
{
|
||||
PERROR("Could not lock pfn list buffer");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ret = do_dom0_op(xc_handle, &op);
|
||||
|
||||
if (max_pfns != -1UL)
|
||||
(void)munlock(__pfn_buf, __nr_pages * sizeof(unsigned long));
|
||||
(void)munlock(__pfn_buf, __nr_pages * sizeof(unsigned long));
|
||||
|
||||
if (max_pfns == -1UL)
|
||||
return 0;
|
||||
@@ -97,12 +97,12 @@ int xc_ia64_get_pfn_list(int xc_handle,
|
||||
__nr_pages -= num_pfns;
|
||||
__pfn_buf += num_pfns;
|
||||
|
||||
if (ret < 0)
|
||||
// dummy write to make sure this tlb mapping is tracked by VMM
|
||||
if (ret < 0)
|
||||
// dummy write to make sure this tlb mapping is tracked by VMM
|
||||
*__pfn_buf = 0;
|
||||
else
|
||||
return nr_pages;
|
||||
}
|
||||
else
|
||||
return nr_pages;
|
||||
}
|
||||
return nr_pages;
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ long xc_get_max_pages(int xc_handle, uint32_t domid)
|
||||
dom0_op_t op;
|
||||
op.cmd = DOM0_GETDOMAININFO;
|
||||
op.u.getdomaininfo.domain = (domid_t)domid;
|
||||
return (do_dom0_op(xc_handle, &op) < 0) ?
|
||||
return (do_dom0_op(xc_handle, &op) < 0) ?
|
||||
-1 : op.u.getdomaininfo.max_pages;
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ int xc_ia64_copy_to_domain_pages(int xc_handle, uint32_t domid,
|
||||
void* src_page, unsigned long dst_pfn, int nr_pages)
|
||||
{
|
||||
// N.B. gva should be page aligned
|
||||
|
||||
|
||||
unsigned long *page_array = NULL;
|
||||
int i;
|
||||
|
||||
@@ -134,22 +134,22 @@ int xc_ia64_copy_to_domain_pages(int xc_handle, uint32_t domid,
|
||||
}
|
||||
|
||||
for ( i=0; i< nr_pages; i++ ){
|
||||
if (xc_copy_to_domain_page(xc_handle, domid, page_array[i],
|
||||
src_page + (i << PAGE_SHIFT)))
|
||||
goto error_out;
|
||||
if (xc_copy_to_domain_page(xc_handle, domid, page_array[i],
|
||||
src_page + (i << PAGE_SHIFT)))
|
||||
goto error_out;
|
||||
}
|
||||
free(page_array);
|
||||
return 0;
|
||||
|
||||
|
||||
error_out:
|
||||
free(page_array);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#define HOB_SIGNATURE 0x3436474953424f48 // "HOBSIG64"
|
||||
#define GFW_HOB_START ((4UL<<30)-(14UL<<20)) //4G -14M
|
||||
#define GFW_HOB_SIZE (1UL<<20) //1M
|
||||
#define HOB_SIGNATURE 0x3436474953424f48 // "HOBSIG64"
|
||||
#define GFW_HOB_START ((4UL<<30)-(14UL<<20)) // 4G - 14M
|
||||
#define GFW_HOB_SIZE (1UL<<20) // 1M
|
||||
#define RAW_GFW_START_NR(s) ((s) >> PAGE_SHIFT)
|
||||
#define RAW_GFW_HOB_START_NR(s) \
|
||||
(RAW_GFW_START_NR(s) + ((GFW_HOB_START - GFW_START) >> PAGE_SHIFT))
|
||||
@@ -170,7 +170,7 @@ typedef struct {
|
||||
* INFO HOB is the first data data in one HOB list
|
||||
* it contains the control information of the HOB list
|
||||
*/
|
||||
typedef struct {
|
||||
typedef struct {
|
||||
HOB_GENERIC_HEADER header;
|
||||
unsigned long length; // current length of hob
|
||||
unsigned long cur_pos; // current poisiton of hob
|
||||
@@ -251,7 +251,7 @@ hob_init( void *buffer ,unsigned long buf_size)
|
||||
// buffer too small
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
phit = (HOB_INFO*)buffer;
|
||||
phit->header.signature = HOB_SIGNATURE;
|
||||
phit->header.type = HOB_TYPE_INFO;
|
||||
@@ -259,7 +259,7 @@ hob_init( void *buffer ,unsigned long buf_size)
|
||||
phit->length = sizeof(HOB_INFO) + sizeof(HOB_GENERIC_HEADER);
|
||||
phit->cur_pos = 0;
|
||||
phit->buf_size = buf_size;
|
||||
|
||||
|
||||
terminal = (HOB_GENERIC_HEADER*) (buffer + sizeof(HOB_INFO));
|
||||
terminal->signature= HOB_SIGNATURE;
|
||||
terminal->type = HOB_TYPE_TERMINAL;
|
||||
@@ -270,7 +270,7 @@ hob_init( void *buffer ,unsigned long buf_size)
|
||||
|
||||
/*
|
||||
* Add a new HOB to the HOB List.
|
||||
*
|
||||
*
|
||||
* hob_start - start address of hob buffer
|
||||
* type - type of the hob to be added
|
||||
* data - data of the hob to be added
|
||||
@@ -285,8 +285,8 @@ hob_add(
|
||||
)
|
||||
{
|
||||
HOB_INFO *phit;
|
||||
HOB_GENERIC_HEADER *newhob,*tail;
|
||||
|
||||
HOB_GENERIC_HEADER *newhob,*tail;
|
||||
|
||||
phit = (HOB_INFO*)hob_start;
|
||||
|
||||
if (phit->length + data_size > phit->buf_size){
|
||||
@@ -294,7 +294,7 @@ hob_add(
|
||||
return -1;
|
||||
}
|
||||
|
||||
//append new HOB
|
||||
//append new HOB
|
||||
newhob = (HOB_GENERIC_HEADER*)
|
||||
(hob_start + phit->length - sizeof(HOB_GENERIC_HEADER));
|
||||
newhob->signature = HOB_SIGNATURE;
|
||||
@@ -302,7 +302,7 @@ hob_add(
|
||||
newhob->length = data_size + sizeof(HOB_GENERIC_HEADER);
|
||||
memcpy((void*)newhob + sizeof(HOB_GENERIC_HEADER), data, data_size);
|
||||
|
||||
// append terminal HOB
|
||||
// append terminal HOB
|
||||
tail = (HOB_GENERIC_HEADER*) ( hob_start + phit->length + data_size);
|
||||
tail->signature = HOB_SIGNATURE;
|
||||
tail->type = HOB_TYPE_TERMINAL;
|
||||
@@ -316,9 +316,9 @@ hob_add(
|
||||
}
|
||||
|
||||
int get_hob_size(void* hob_buf){
|
||||
|
||||
|
||||
HOB_INFO *phit = (HOB_INFO*)hob_buf;
|
||||
|
||||
|
||||
if (phit->header.signature != HOB_SIGNATURE){
|
||||
PERROR("xc_get_hob_size:Incorrect signature");
|
||||
return -1;
|
||||
@@ -328,32 +328,32 @@ int get_hob_size(void* hob_buf){
|
||||
|
||||
int build_hob (void* hob_buf, unsigned long hob_buf_size,
|
||||
unsigned long dom_mem_size)
|
||||
{
|
||||
//Init HOB List
|
||||
{
|
||||
//Init HOB List
|
||||
if (hob_init (hob_buf, hob_buf_size)<0){
|
||||
PERROR("buffer too small");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
|
||||
if ( add_mem_hob( hob_buf,dom_mem_size) < 0){
|
||||
PERROR("Add memory hob failed, buffer too small");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
|
||||
if ( add_pal_hob( hob_buf ) < 0 ){
|
||||
PERROR("Add PAL hob failed, buffer too small");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
static int
|
||||
load_hob(int xc_handle, uint32_t dom, void *hob_buf,
|
||||
unsigned long dom_mem_size)
|
||||
unsigned long dom_mem_size)
|
||||
{
|
||||
// hob_buf should be page aligned
|
||||
int hob_size;
|
||||
@@ -370,22 +370,22 @@ load_hob(int xc_handle, uint32_t dom, void *hob_buf,
|
||||
}
|
||||
|
||||
nr_pages = (hob_size + PAGE_SIZE -1) >> PAGE_SHIFT;
|
||||
|
||||
|
||||
return xc_ia64_copy_to_domain_pages(xc_handle, dom,
|
||||
hob_buf, RAW_GFW_HOB_START_NR(dom_mem_size), nr_pages );
|
||||
}
|
||||
|
||||
#define MIN(x, y) ((x) < (y)) ? (x) : (y)
|
||||
static int
|
||||
static int
|
||||
add_mem_hob(void* hob_buf, unsigned long dom_mem_size){
|
||||
hob_mem_t memhob;
|
||||
|
||||
// less than 3G
|
||||
memhob.start = 0;
|
||||
memhob.size = MIN(dom_mem_size, 0xC0000000);
|
||||
|
||||
|
||||
if (hob_add(hob_buf, HOB_TYPE_MEM, &memhob, sizeof(memhob)) < 0){
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dom_mem_size > 0xC0000000) {
|
||||
@@ -409,29 +409,29 @@ unsigned char config_pal_mem_attrib[8] = {
|
||||
};
|
||||
unsigned char config_pal_cache_info[152] = {
|
||||
3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
6, 4, 6, 7, 255, 1, 0, 1, 0, 64, 0, 0, 12, 12,
|
||||
6, 4, 6, 7, 255, 1, 0, 1, 0, 64, 0, 0, 12, 12,
|
||||
49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 6, 7, 0, 1,
|
||||
0, 1, 0, 64, 0, 0, 12, 12, 49, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 6, 8, 7, 7, 255, 7, 0, 11, 0, 0, 16, 0,
|
||||
12, 17, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 7,
|
||||
0, 1, 0, 64, 0, 0, 12, 12, 49, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 6, 8, 7, 7, 255, 7, 0, 11, 0, 0, 16, 0,
|
||||
12, 17, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 7,
|
||||
7, 7, 5, 9, 11, 0, 0, 4, 0, 12, 15, 49, 0, 254, 255,
|
||||
255, 255, 255, 255, 255, 255, 2, 8, 7, 7, 7, 5, 9,
|
||||
11, 0, 0, 4, 0, 12, 15, 49, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
255, 255, 255, 255, 255, 255, 2, 8, 7, 7, 7, 5, 9,
|
||||
11, 0, 0, 4, 0, 12, 15, 49, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 3, 12, 7, 7, 7, 14, 1, 3, 0, 0, 192, 0, 12, 20, 49, 0
|
||||
};
|
||||
unsigned char config_pal_cache_prot_info[200] = {
|
||||
3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
45, 0, 16, 8, 0, 76, 12, 64, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
8, 0, 16, 4, 0, 76, 44, 68, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,
|
||||
0, 16, 8, 0, 81, 44, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
8, 0, 16, 4, 0, 76, 44, 68, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,
|
||||
0, 16, 8, 0, 81, 44, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0,
|
||||
112, 12, 0, 79, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 254, 255, 255, 255, 255, 255, 255, 255,
|
||||
112, 12, 0, 79, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 254, 255, 255, 255, 255, 255, 255, 255,
|
||||
32, 0, 112, 12, 0, 79, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 160,
|
||||
12, 0, 84, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 160,
|
||||
12, 0, 84, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0
|
||||
};
|
||||
unsigned char config_pal_debug_info[16] = {
|
||||
@@ -444,37 +444,37 @@ unsigned char config_pal_freq_base[8] = {
|
||||
109, 219, 182, 13, 0, 0, 0, 0
|
||||
};
|
||||
unsigned char config_pal_freq_ratios[24] = {
|
||||
11, 1, 0, 0, 77, 7, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 4,
|
||||
11, 1, 0, 0, 77, 7, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 4,
|
||||
0, 0, 0, 7, 0, 0, 0
|
||||
};
|
||||
unsigned char config_pal_halt_info[64] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
unsigned char config_pal_perf_mon_info[136] = {
|
||||
12, 47, 18, 8, 0, 0, 0, 0, 241, 255, 0, 0, 255, 7, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 241, 255, 0, 0, 223, 0, 255, 255,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 240, 255, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 240, 255, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
12, 47, 18, 8, 0, 0, 0, 0, 241, 255, 0, 0, 255, 7, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 241, 255, 0, 0, 223, 0, 255, 255,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 240, 255, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 240, 255, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
unsigned char config_pal_proc_get_features[104] = {
|
||||
3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 64, 6, 64, 49, 0, 0, 0, 0, 64, 6, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0,
|
||||
231, 0, 0, 0, 0, 0, 0, 0, 228, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,
|
||||
3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 64, 6, 64, 49, 0, 0, 0, 0, 64, 6, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0,
|
||||
231, 0, 0, 0, 0, 0, 0, 0, 228, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,
|
||||
63, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
unsigned char config_pal_ptce_info[24] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
unsigned char config_pal_register_info[64] = {
|
||||
@@ -509,7 +509,7 @@ unsigned char config_pal_vm_page_size[16] = {
|
||||
typedef struct{
|
||||
hob_type_t type;
|
||||
void* data;
|
||||
unsigned long size;
|
||||
unsigned long size;
|
||||
}hob_batch_t;
|
||||
|
||||
hob_batch_t hob_batch[]={
|
||||
@@ -588,13 +588,13 @@ hob_batch_t hob_batch[]={
|
||||
{ HOB_TYPE_PAL_VM_PAGE_SIZE,
|
||||
&config_pal_vm_page_size,
|
||||
sizeof(config_pal_vm_page_size)
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static int add_pal_hob(void* hob_buf){
|
||||
int i;
|
||||
for (i=0; i<sizeof(hob_batch)/sizeof(hob_batch_t); i++){
|
||||
if (hob_add(hob_buf, hob_batch[i].type,
|
||||
if (hob_add(hob_buf, hob_batch[i].type,
|
||||
hob_batch[i].data,
|
||||
hob_batch[i].size)<0)
|
||||
return -1;
|
||||
@@ -620,7 +620,7 @@ static int setup_guest( int xc_handle,
|
||||
}
|
||||
|
||||
/* Load guest firmware */
|
||||
if( xc_ia64_copy_to_domain_pages( xc_handle, dom,
|
||||
if( xc_ia64_copy_to_domain_pages( xc_handle, dom,
|
||||
image, RAW_GFW_IMAGE_START_NR(dom_memsize, image_size),
|
||||
image_size>>PAGE_SHIFT)) {
|
||||
PERROR("Could not load guest firmware into domain");
|
||||
@@ -635,7 +635,7 @@ static int setup_guest( int xc_handle,
|
||||
|
||||
/* Retrieve special pages like io, xenstore, etc. */
|
||||
if ( xc_ia64_get_pfn_list(xc_handle, dom, page_array,
|
||||
RAW_IO_PAGE_START_NR(dom_memsize), 2) != 2 )
|
||||
RAW_IO_PAGE_START_NR(dom_memsize), 2) != 2 )
|
||||
{
|
||||
PERROR("Could not get the page frame list");
|
||||
goto error_out;
|
||||
@@ -643,9 +643,9 @@ static int setup_guest( int xc_handle,
|
||||
|
||||
*store_mfn = page_array[1];
|
||||
if ((sp = (shared_iopage_t *) xc_map_foreign_range(
|
||||
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
|
||||
page_array[0])) == 0)
|
||||
goto error_out;
|
||||
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
|
||||
page_array[0])) == 0)
|
||||
goto error_out;
|
||||
memset(sp, 0, PAGE_SIZE);
|
||||
|
||||
for (i = 0; i < vcpus; i++) {
|
||||
@@ -698,14 +698,14 @@ int xc_hvm_build(int xc_handle,
|
||||
|
||||
image_size = (image_size + PAGE_SIZE - 1) & PAGE_MASK;
|
||||
|
||||
if ( mlock(&st_ctxt, sizeof(st_ctxt) ) ){
|
||||
if ( mlock(&st_ctxt, sizeof(st_ctxt) ) ){
|
||||
PERROR("Unable to mlock ctxt");
|
||||
return 1;
|
||||
}
|
||||
|
||||
op.cmd = DOM0_GETDOMAININFO;
|
||||
op.u.getdomaininfo.domain = (domid_t)domid;
|
||||
if ( (do_dom0_op(xc_handle, &op) < 0) ||
|
||||
if ( (do_dom0_op(xc_handle, &op) < 0) ||
|
||||
((uint16_t)op.u.getdomaininfo.domain != domid) ) {
|
||||
PERROR("Could not get info on domain");
|
||||
goto error_out;
|
||||
|
||||
@@ -237,7 +237,7 @@ static int setup_pg_tables(int xc_handle, uint32_t dom,
|
||||
else
|
||||
{
|
||||
*vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT;
|
||||
if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) &&
|
||||
if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) &&
|
||||
(count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) )
|
||||
*vl1e &= ~_PAGE_RW;
|
||||
}
|
||||
@@ -314,7 +314,7 @@ static int setup_pg_tables_pae(int xc_handle, uint32_t dom,
|
||||
else
|
||||
*vl2e++ = l1tab | L2_PROT;
|
||||
}
|
||||
|
||||
|
||||
if ( shadow_mode_enabled )
|
||||
{
|
||||
*vl1e = (count << PAGE_SHIFT) | L1_PROT;
|
||||
@@ -323,12 +323,12 @@ static int setup_pg_tables_pae(int xc_handle, uint32_t dom,
|
||||
{
|
||||
*vl1e = ((uint64_t)page_array[count] << PAGE_SHIFT) | L1_PROT;
|
||||
if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) &&
|
||||
(count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) )
|
||||
(count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) )
|
||||
*vl1e &= ~_PAGE_RW;
|
||||
}
|
||||
vl1e++;
|
||||
}
|
||||
|
||||
|
||||
munmap(vl1tab, PAGE_SIZE);
|
||||
munmap(vl2tab, PAGE_SIZE);
|
||||
munmap(vl3tab, PAGE_SIZE);
|
||||
@@ -376,13 +376,13 @@ static int setup_pg_tables_64(int xc_handle, uint32_t dom,
|
||||
ctxt->ctrlreg[3] = pl4tab;
|
||||
else
|
||||
ctxt->ctrlreg[3] = l4tab;
|
||||
|
||||
|
||||
for ( count = 0; count < ((v_end-dsi_v_start)>>PAGE_SHIFT); count++)
|
||||
{
|
||||
if ( !((unsigned long)vl1e & (PAGE_SIZE-1)) )
|
||||
{
|
||||
alloc_pt(l1tab, vl1tab, pl1tab);
|
||||
|
||||
|
||||
if ( !((unsigned long)vl2e & (PAGE_SIZE-1)) )
|
||||
{
|
||||
alloc_pt(l2tab, vl2tab, pl2tab);
|
||||
@@ -410,7 +410,7 @@ static int setup_pg_tables_64(int xc_handle, uint32_t dom,
|
||||
*vl2e = l1tab | L2_PROT;
|
||||
vl2e++;
|
||||
}
|
||||
|
||||
|
||||
if ( shadow_mode_enabled )
|
||||
{
|
||||
*vl1e = (count << PAGE_SHIFT) | L1_PROT;
|
||||
@@ -419,14 +419,14 @@ static int setup_pg_tables_64(int xc_handle, uint32_t dom,
|
||||
{
|
||||
*vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT;
|
||||
if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) &&
|
||||
(count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) )
|
||||
(count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) )
|
||||
{
|
||||
*vl1e &= ~_PAGE_RW;
|
||||
}
|
||||
}
|
||||
vl1e++;
|
||||
}
|
||||
|
||||
|
||||
munmap(vl1tab, PAGE_SIZE);
|
||||
munmap(vl2tab, PAGE_SIZE);
|
||||
munmap(vl3tab, PAGE_SIZE);
|
||||
@@ -509,7 +509,7 @@ static int setup_guest(int xc_handle,
|
||||
" Loaded kernel: %p->%p\n"
|
||||
" Init. ramdisk: %p->%p\n"
|
||||
" TOTAL: %p->%p\n",
|
||||
_p(dsi.v_kernstart), _p(dsi.v_kernend),
|
||||
_p(dsi.v_kernstart), _p(dsi.v_kernend),
|
||||
_p(vinitrd_start), _p(vinitrd_end),
|
||||
_p(dsi.v_start), _p(v_end));
|
||||
printf(" ENTRY ADDRESS: %p\n", _p(dsi.v_kernentry));
|
||||
@@ -696,10 +696,10 @@ static int setup_guest(int xc_handle,
|
||||
required_features);
|
||||
|
||||
/*
|
||||
* Why do we need this? The number of page-table frames depends on the
|
||||
* size of the bootstrap address space. But the size of the address space
|
||||
* depends on the number of page-table frames (since each one is mapped
|
||||
* read-only). We have a pair of simultaneous equations in two unknowns,
|
||||
* Why do we need this? The number of page-table frames depends on the
|
||||
* size of the bootstrap address space. But the size of the address space
|
||||
* depends on the number of page-table frames (since each one is mapped
|
||||
* read-only). We have a pair of simultaneous equations in two unknowns,
|
||||
* which we solve by exhaustive search.
|
||||
*/
|
||||
v_end = round_pgup(dsi.v_end);
|
||||
@@ -731,13 +731,13 @@ static int setup_guest(int xc_handle,
|
||||
if ( dsi.pae_kernel )
|
||||
{
|
||||
/* FIXME: assumes one L2 pgtable @ 0xc0000000 */
|
||||
if ( (((v_end - dsi.v_start + ((1<<L2_PAGETABLE_SHIFT_PAE)-1)) >>
|
||||
if ( (((v_end - dsi.v_start + ((1<<L2_PAGETABLE_SHIFT_PAE)-1)) >>
|
||||
L2_PAGETABLE_SHIFT_PAE) + 2) <= nr_pt_pages )
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( (((v_end - dsi.v_start + ((1<<L2_PAGETABLE_SHIFT)-1)) >>
|
||||
if ( (((v_end - dsi.v_start + ((1<<L2_PAGETABLE_SHIFT)-1)) >>
|
||||
L2_PAGETABLE_SHIFT) + 1) <= nr_pt_pages )
|
||||
break;
|
||||
}
|
||||
@@ -873,7 +873,7 @@ static int setup_guest(int xc_handle,
|
||||
count) )
|
||||
{
|
||||
fprintf(stderr,"m2p update failure p=%lx m=%lx\n",
|
||||
count, page_array[count]);
|
||||
count, page_array[count]);
|
||||
munmap(physmap, PAGE_SIZE);
|
||||
goto error_out;
|
||||
}
|
||||
@@ -982,7 +982,7 @@ static int setup_guest(int xc_handle,
|
||||
start_info->mod_len = initrd->len;
|
||||
}
|
||||
if ( cmdline != NULL )
|
||||
{
|
||||
{
|
||||
strncpy((char *)start_info->cmd_line, cmdline, MAX_GUEST_CMDLINE);
|
||||
start_info->cmd_line[MAX_GUEST_CMDLINE-1] = '\0';
|
||||
}
|
||||
@@ -1073,14 +1073,14 @@ static int xc_linux_build_internal(int xc_handle,
|
||||
#endif
|
||||
|
||||
if ( mlock(&st_ctxt, sizeof(st_ctxt) ) )
|
||||
{
|
||||
{
|
||||
PERROR("%s: ctxt mlock failed", __func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
op.cmd = DOM0_GETDOMAININFO;
|
||||
op.u.getdomaininfo.domain = (domid_t)domid;
|
||||
if ( (xc_dom0_op(xc_handle, &op) < 0) ||
|
||||
if ( (xc_dom0_op(xc_handle, &op) < 0) ||
|
||||
((uint16_t)op.u.getdomaininfo.domain != domid) )
|
||||
{
|
||||
PERROR("Could not get info on domain");
|
||||
@@ -1089,9 +1089,9 @@ static int xc_linux_build_internal(int xc_handle,
|
||||
|
||||
memset(ctxt, 0, sizeof(*ctxt));
|
||||
|
||||
if ( setup_guest(xc_handle, domid, image, image_size,
|
||||
if ( setup_guest(xc_handle, domid, image, image_size,
|
||||
initrd,
|
||||
nr_pages,
|
||||
nr_pages,
|
||||
&vstartinfo_start, &vkern_entry,
|
||||
&vstack_start, ctxt, cmdline,
|
||||
op.u.getdomaininfo.shared_info_frame,
|
||||
@@ -1152,7 +1152,7 @@ static int xc_linux_build_internal(int xc_handle,
|
||||
|
||||
/* No LDT. */
|
||||
ctxt->ldt_ents = 0;
|
||||
|
||||
|
||||
/* Use the default Xen-provided GDT. */
|
||||
ctxt->gdt_ents = 0;
|
||||
|
||||
@@ -1184,7 +1184,7 @@ static int xc_linux_build_internal(int xc_handle,
|
||||
|
||||
launch_op.cmd = DOM0_SETVCPUCONTEXT;
|
||||
rc = xc_dom0_op(xc_handle, &launch_op);
|
||||
|
||||
|
||||
return rc;
|
||||
|
||||
error_out:
|
||||
|
||||
+199
-199
@@ -1,8 +1,8 @@
|
||||
/******************************************************************************
|
||||
* xc_linux_restore.c
|
||||
*
|
||||
*
|
||||
* Restore the state of a Linux session.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2003, K A Fraser.
|
||||
*/
|
||||
|
||||
@@ -13,13 +13,13 @@
|
||||
#include "xg_save_restore.h"
|
||||
|
||||
/* max mfn of the whole machine */
|
||||
static unsigned long max_mfn;
|
||||
static unsigned long max_mfn;
|
||||
|
||||
/* virtual starting address of the hypervisor */
|
||||
static unsigned long hvirt_start;
|
||||
static unsigned long hvirt_start;
|
||||
|
||||
/* #levels of page tables used by the currrent guest */
|
||||
static unsigned int pt_levels;
|
||||
static unsigned int pt_levels;
|
||||
|
||||
/* total number of pages used by the current guest */
|
||||
static unsigned long max_pfn;
|
||||
@@ -41,84 +41,84 @@ read_exact(int fd, void *buf, size_t count)
|
||||
s = read(fd, &b[r], count - r);
|
||||
if ((s == -1) && (errno == EINTR))
|
||||
continue;
|
||||
if (s <= 0) {
|
||||
if (s <= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
r += s;
|
||||
}
|
||||
|
||||
return (r == count) ? 1 : 0;
|
||||
return (r == count) ? 1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** In the state file (or during transfer), all page-table pages are
|
||||
** converted into a 'canonical' form where references to actual mfns
|
||||
** are replaced with references to the corresponding pfns.
|
||||
** This function inverts that operation, replacing the pfn values with
|
||||
** the (now known) appropriate mfn values.
|
||||
** In the state file (or during transfer), all page-table pages are
|
||||
** converted into a 'canonical' form where references to actual mfns
|
||||
** are replaced with references to the corresponding pfns.
|
||||
** This function inverts that operation, replacing the pfn values with
|
||||
** the (now known) appropriate mfn values.
|
||||
*/
|
||||
int uncanonicalize_pagetable(unsigned long type, void *page)
|
||||
{
|
||||
int i, pte_last;
|
||||
unsigned long pfn;
|
||||
uint64_t pte;
|
||||
int uncanonicalize_pagetable(unsigned long type, void *page)
|
||||
{
|
||||
int i, pte_last;
|
||||
unsigned long pfn;
|
||||
uint64_t pte;
|
||||
|
||||
pte_last = PAGE_SIZE / ((pt_levels == 2)? 4 : 8);
|
||||
pte_last = PAGE_SIZE / ((pt_levels == 2)? 4 : 8);
|
||||
|
||||
/* Now iterate through the page table, uncanonicalizing each PTE */
|
||||
for(i = 0; i < pte_last; i++) {
|
||||
|
||||
if(pt_levels == 2)
|
||||
pte = ((uint32_t *)page)[i];
|
||||
else
|
||||
pte = ((uint64_t *)page)[i];
|
||||
for(i = 0; i < pte_last; i++) {
|
||||
|
||||
if(pte & _PAGE_PRESENT) {
|
||||
if(pt_levels == 2)
|
||||
pte = ((uint32_t *)page)[i];
|
||||
else
|
||||
pte = ((uint64_t *)page)[i];
|
||||
|
||||
if(pte & _PAGE_PRESENT) {
|
||||
|
||||
pfn = (pte >> PAGE_SHIFT) & 0xffffffff;
|
||||
|
||||
if(pfn >= max_pfn) {
|
||||
|
||||
if(pfn >= max_pfn) {
|
||||
/* This "page table page" is probably not one; bail. */
|
||||
ERR("Frame number in type %lu page table is out of range: "
|
||||
"i=%d pfn=0x%lx max_pfn=%lu",
|
||||
"i=%d pfn=0x%lx max_pfn=%lu",
|
||||
type >> 28, i, pfn, max_pfn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
pte &= 0xffffff0000000fffULL;
|
||||
pte |= (uint64_t)p2m[pfn] << PAGE_SHIFT;
|
||||
|
||||
if(pt_levels == 2)
|
||||
((uint32_t *)page)[i] = (uint32_t)pte;
|
||||
else
|
||||
((uint64_t *)page)[i] = (uint64_t)pte;
|
||||
if(pt_levels == 2)
|
||||
((uint32_t *)page)[i] = (uint32_t)pte;
|
||||
else
|
||||
((uint64_t *)page)[i] = (uint64_t)pte;
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int xc_linux_restore(int xc_handle, int io_fd,
|
||||
uint32_t dom, unsigned long nr_pfns,
|
||||
int xc_linux_restore(int xc_handle, int io_fd,
|
||||
uint32_t dom, unsigned long nr_pfns,
|
||||
unsigned int store_evtchn, unsigned long *store_mfn,
|
||||
unsigned int console_evtchn, unsigned long *console_mfn)
|
||||
{
|
||||
DECLARE_DOM0_OP;
|
||||
int rc = 1, i, n;
|
||||
unsigned long mfn, pfn;
|
||||
unsigned long mfn, pfn;
|
||||
unsigned int prev_pc, this_pc;
|
||||
int verify = 0;
|
||||
int nraces = 0;
|
||||
int nraces = 0;
|
||||
|
||||
/* The new domain's shared-info frame number. */
|
||||
unsigned long shared_info_frame;
|
||||
unsigned char shared_info_page[PAGE_SIZE]; /* saved contents from file */
|
||||
shared_info_t *shared_info = (shared_info_t *)shared_info_page;
|
||||
|
||||
|
||||
/* A copy of the CPU context of the guest. */
|
||||
vcpu_guest_context_t ctxt;
|
||||
|
||||
@@ -135,7 +135,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
|
||||
unsigned long *page = NULL;
|
||||
|
||||
/* A copy of the pfn-to-mfn table frame list. */
|
||||
unsigned long *p2m_frame_list = NULL;
|
||||
unsigned long *p2m_frame_list = NULL;
|
||||
|
||||
/* A temporary mapping of the guest's start_info page. */
|
||||
start_info_t *start_info;
|
||||
@@ -148,17 +148,17 @@ int xc_linux_restore(int xc_handle, int io_fd,
|
||||
unsigned long buf[PAGE_SIZE/sizeof(unsigned long)];
|
||||
|
||||
struct mmuext_op pin[MAX_PIN_BATCH];
|
||||
unsigned int nr_pins;
|
||||
unsigned int nr_pins;
|
||||
|
||||
|
||||
max_pfn = nr_pfns;
|
||||
max_pfn = nr_pfns;
|
||||
|
||||
DPRINTF("xc_linux_restore start: max_pfn = %lx\n", max_pfn);
|
||||
|
||||
|
||||
if(!get_platform_info(xc_handle, dom,
|
||||
if(!get_platform_info(xc_handle, dom,
|
||||
&max_mfn, &hvirt_start, &pt_levels)) {
|
||||
ERR("Unable to get platform info.");
|
||||
ERR("Unable to get platform info.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -171,20 +171,20 @@ int xc_linux_restore(int xc_handle, int io_fd,
|
||||
|
||||
|
||||
/* Read the saved P2M frame list */
|
||||
if(!(p2m_frame_list = malloc(P2M_FL_SIZE))) {
|
||||
if(!(p2m_frame_list = malloc(P2M_FL_SIZE))) {
|
||||
ERR("Couldn't allocate p2m_frame_list array");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!read_exact(io_fd, p2m_frame_list, P2M_FL_SIZE)) {
|
||||
|
||||
if (!read_exact(io_fd, p2m_frame_list, P2M_FL_SIZE)) {
|
||||
ERR("read p2m_frame_list failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* We want zeroed memory so use calloc rather than malloc. */
|
||||
p2m = calloc(sizeof(unsigned long), max_pfn);
|
||||
pfn_type = calloc(sizeof(unsigned long), max_pfn);
|
||||
p2m = calloc(sizeof(unsigned long), max_pfn);
|
||||
pfn_type = calloc(sizeof(unsigned long), max_pfn);
|
||||
region_mfn = calloc(sizeof(unsigned long), MAX_BATCH_SIZE);
|
||||
|
||||
if ((p2m == NULL) || (pfn_type == NULL) || (region_mfn == NULL)) {
|
||||
@@ -192,7 +192,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
|
||||
errno = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
if (mlock(region_mfn, sizeof(unsigned long) * MAX_BATCH_SIZE)) {
|
||||
ERR("Could not mlock region_mfn");
|
||||
goto out;
|
||||
@@ -207,27 +207,27 @@ int xc_linux_restore(int xc_handle, int io_fd,
|
||||
}
|
||||
shared_info_frame = op.u.getdomaininfo.shared_info_frame;
|
||||
|
||||
if(xc_domain_setmaxmem(xc_handle, dom, PFN_TO_KB(max_pfn)) != 0) {
|
||||
if(xc_domain_setmaxmem(xc_handle, dom, PFN_TO_KB(max_pfn)) != 0) {
|
||||
errno = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
if(xc_domain_memory_increase_reservation(
|
||||
xc_handle, dom, max_pfn, 0, 0, NULL) != 0) {
|
||||
xc_handle, dom, max_pfn, 0, 0, NULL) != 0) {
|
||||
ERR("Failed to increase reservation by %lx KB", PFN_TO_KB(max_pfn));
|
||||
errno = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
DPRINTF("Increased domain reservation by %lx KB\n", PFN_TO_KB(max_pfn));
|
||||
DPRINTF("Increased domain reservation by %lx KB\n", PFN_TO_KB(max_pfn));
|
||||
|
||||
/* Build the pfn-to-mfn table. We choose MFN ordering returned by Xen. */
|
||||
if (xc_get_pfn_list(xc_handle, dom, p2m, max_pfn) != max_pfn) {
|
||||
ERR("Did not read correct number of frame numbers for new dom");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(!(mmu = xc_init_mmu_updates(xc_handle, dom))) {
|
||||
|
||||
if(!(mmu = xc_init_mmu_updates(xc_handle, dom))) {
|
||||
ERR("Could not initialise for MMU updates");
|
||||
goto out;
|
||||
}
|
||||
@@ -242,7 +242,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
|
||||
prev_pc = 0;
|
||||
|
||||
n = 0;
|
||||
while (1) {
|
||||
while (1) {
|
||||
|
||||
int j;
|
||||
|
||||
@@ -253,13 +253,13 @@ int xc_linux_restore(int xc_handle, int io_fd,
|
||||
prev_pc = this_pc;
|
||||
}
|
||||
|
||||
if (!read_exact(io_fd, &j, sizeof(int))) {
|
||||
if (!read_exact(io_fd, &j, sizeof(int))) {
|
||||
ERR("Error when reading batch size");
|
||||
goto out;
|
||||
}
|
||||
|
||||
PPRINTF("batch %d\n",j);
|
||||
|
||||
|
||||
if (j == -1) {
|
||||
verify = 1;
|
||||
fprintf(stderr, "Entering page verify mode\n");
|
||||
@@ -269,27 +269,27 @@ int xc_linux_restore(int xc_handle, int io_fd,
|
||||
if (j == 0)
|
||||
break; /* our work here is done */
|
||||
|
||||
if (j > MAX_BATCH_SIZE) {
|
||||
if (j > MAX_BATCH_SIZE) {
|
||||
ERR("Max batch size exceeded. Giving up.");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!read_exact(io_fd, region_pfn_type, j*sizeof(unsigned long))) {
|
||||
|
||||
if (!read_exact(io_fd, region_pfn_type, j*sizeof(unsigned long))) {
|
||||
ERR("Error when reading region pfn types");
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < j; i++) {
|
||||
for (i = 0; i < j; i++) {
|
||||
|
||||
if ((region_pfn_type[i] & LTAB_MASK) == XTAB)
|
||||
region_mfn[i] = 0; /* we know map will fail, but don't care */
|
||||
else
|
||||
region_mfn[i] = p2m[region_pfn_type[i] & ~LTAB_MASK];
|
||||
else
|
||||
region_mfn[i] = p2m[region_pfn_type[i] & ~LTAB_MASK];
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (!(region_base = xc_map_foreign_batch(
|
||||
xc_handle, dom, PROT_WRITE, region_mfn, j))) {
|
||||
xc_handle, dom, PROT_WRITE, region_mfn, j))) {
|
||||
ERR("map batch failed");
|
||||
goto out;
|
||||
}
|
||||
@@ -297,12 +297,12 @@ int xc_linux_restore(int xc_handle, int io_fd,
|
||||
for ( i = 0; i < j; i++ )
|
||||
{
|
||||
void *page;
|
||||
unsigned long pagetype;
|
||||
unsigned long pagetype;
|
||||
|
||||
pfn = region_pfn_type[i] & ~LTAB_MASK;
|
||||
pagetype = region_pfn_type[i] & LTAB_MASK;
|
||||
pagetype = region_pfn_type[i] & LTAB_MASK;
|
||||
|
||||
if (pagetype == XTAB)
|
||||
if (pagetype == XTAB)
|
||||
/* a bogus/unmapped page: skip it */
|
||||
continue;
|
||||
|
||||
@@ -311,72 +311,72 @@ int xc_linux_restore(int xc_handle, int io_fd,
|
||||
goto out;
|
||||
}
|
||||
|
||||
pfn_type[pfn] = pagetype;
|
||||
pfn_type[pfn] = pagetype;
|
||||
|
||||
mfn = p2m[pfn];
|
||||
|
||||
/* In verify mode, we use a copy; otherwise we work in place */
|
||||
page = verify ? (void *)buf : (region_base + i*PAGE_SIZE);
|
||||
page = verify ? (void *)buf : (region_base + i*PAGE_SIZE);
|
||||
|
||||
if (!read_exact(io_fd, page, PAGE_SIZE)) {
|
||||
if (!read_exact(io_fd, page, PAGE_SIZE)) {
|
||||
ERR("Error when reading page (type was %lx)", pagetype);
|
||||
goto out;
|
||||
}
|
||||
|
||||
pagetype &= LTABTYPE_MASK;
|
||||
pagetype &= LTABTYPE_MASK;
|
||||
|
||||
if(pagetype >= L1TAB && pagetype <= L4TAB) {
|
||||
|
||||
/*
|
||||
** A page table page - need to 'uncanonicalize' it, i.e.
|
||||
** replace all the references to pfns with the corresponding
|
||||
** mfns for the new domain.
|
||||
**
|
||||
** On PAE we need to ensure that PGDs are in MFNs < 4G, and
|
||||
** so we may need to update the p2m after the main loop.
|
||||
** Hence we defer canonicalization of L1s until then.
|
||||
if(pagetype >= L1TAB && pagetype <= L4TAB) {
|
||||
|
||||
/*
|
||||
** A page table page - need to 'uncanonicalize' it, i.e.
|
||||
** replace all the references to pfns with the corresponding
|
||||
** mfns for the new domain.
|
||||
**
|
||||
** On PAE we need to ensure that PGDs are in MFNs < 4G, and
|
||||
** so we may need to update the p2m after the main loop.
|
||||
** Hence we defer canonicalization of L1s until then.
|
||||
*/
|
||||
if(pt_levels != 3 || pagetype != L1TAB) {
|
||||
if(pt_levels != 3 || pagetype != L1TAB) {
|
||||
|
||||
if(!uncanonicalize_pagetable(pagetype, page)) {
|
||||
/*
|
||||
/*
|
||||
** Failing to uncanonicalize a page table can be ok
|
||||
** under live migration since the pages type may have
|
||||
** changed by now (and we'll get an update later).
|
||||
** changed by now (and we'll get an update later).
|
||||
*/
|
||||
DPRINTF("PT L%ld race on pfn=%08lx mfn=%08lx\n",
|
||||
pagetype >> 28, pfn, mfn);
|
||||
nraces++;
|
||||
continue;
|
||||
DPRINTF("PT L%ld race on pfn=%08lx mfn=%08lx\n",
|
||||
pagetype >> 28, pfn, mfn);
|
||||
nraces++;
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else if(pagetype != NOTAB) {
|
||||
}
|
||||
|
||||
} else if(pagetype != NOTAB) {
|
||||
|
||||
ERR("Bogus page type %lx page table is out of range: "
|
||||
"i=%d max_pfn=%lu", pagetype, i, max_pfn);
|
||||
goto out;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (verify) {
|
||||
|
||||
int res = memcmp(buf, (region_base + i*PAGE_SIZE), PAGE_SIZE);
|
||||
|
||||
if (res) {
|
||||
if (res) {
|
||||
|
||||
int v;
|
||||
|
||||
DPRINTF("************** pfn=%lx type=%lx gotcs=%08lx "
|
||||
"actualcs=%08lx\n", pfn, pfn_type[pfn],
|
||||
csum_page(region_base + i*PAGE_SIZE),
|
||||
"actualcs=%08lx\n", pfn, pfn_type[pfn],
|
||||
csum_page(region_base + i*PAGE_SIZE),
|
||||
csum_page(buf));
|
||||
|
||||
for (v = 0; v < 4; v++) {
|
||||
|
||||
unsigned long *p = (unsigned long *)
|
||||
|
||||
unsigned long *p = (unsigned long *)
|
||||
(region_base + i*PAGE_SIZE);
|
||||
if (buf[v] != p[v])
|
||||
DPRINTF(" %d: %08lx %08lx\n", v, buf[v], p[v]);
|
||||
@@ -384,8 +384,8 @@ int xc_linux_restore(int xc_handle, int io_fd,
|
||||
}
|
||||
}
|
||||
|
||||
if (xc_add_mmu_update(xc_handle, mmu,
|
||||
(((unsigned long long)mfn) << PAGE_SHIFT)
|
||||
if (xc_add_mmu_update(xc_handle, mmu,
|
||||
(((unsigned long long)mfn) << PAGE_SHIFT)
|
||||
| MMU_MACHPHYS_UPDATE, pfn)) {
|
||||
ERR("failed machpys update mfn=%lx pfn=%lx", mfn, pfn);
|
||||
goto out;
|
||||
@@ -398,149 +398,149 @@ int xc_linux_restore(int xc_handle, int io_fd,
|
||||
|
||||
DPRINTF("Received all pages (%d races)\n", nraces);
|
||||
|
||||
if(pt_levels == 3) {
|
||||
if(pt_levels == 3) {
|
||||
|
||||
/*
|
||||
** XXX SMH on PAE we need to ensure PGDs are in MFNs < 4G. This
|
||||
/*
|
||||
** XXX SMH on PAE we need to ensure PGDs are in MFNs < 4G. This
|
||||
** is a little awkward and involves (a) finding all such PGDs and
|
||||
** replacing them with 'lowmem' versions; (b) upating the p2m[]
|
||||
** replacing them with 'lowmem' versions; (b) upating the p2m[]
|
||||
** with the new info; and (c) canonicalizing all the L1s using the
|
||||
** (potentially updated) p2m[].
|
||||
**
|
||||
** (potentially updated) p2m[].
|
||||
**
|
||||
** This is relatively slow (and currently involves two passes through
|
||||
** the pfn_type[] array), but at least seems to be correct. May wish
|
||||
** to consider more complex approaches to optimize this later.
|
||||
** to consider more complex approaches to optimize this later.
|
||||
*/
|
||||
|
||||
int j, k;
|
||||
int j, k;
|
||||
|
||||
/* First pass: find all L3TABs current in > 4G mfns and get new mfns */
|
||||
for (i = 0; i < max_pfn; i++) {
|
||||
|
||||
|
||||
if (((pfn_type[i] & LTABTYPE_MASK)==L3TAB) && (p2m[i]>0xfffffUL)) {
|
||||
|
||||
unsigned long new_mfn;
|
||||
uint64_t l3ptes[4];
|
||||
uint64_t *l3tab;
|
||||
unsigned long new_mfn;
|
||||
uint64_t l3ptes[4];
|
||||
uint64_t *l3tab;
|
||||
|
||||
l3tab = (uint64_t *)
|
||||
xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
|
||||
PROT_READ, p2m[i]);
|
||||
xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
|
||||
PROT_READ, p2m[i]);
|
||||
|
||||
for(j = 0; j < 4; j++)
|
||||
l3ptes[j] = l3tab[j];
|
||||
|
||||
munmap(l3tab, PAGE_SIZE);
|
||||
for(j = 0; j < 4; j++)
|
||||
l3ptes[j] = l3tab[j];
|
||||
|
||||
munmap(l3tab, PAGE_SIZE);
|
||||
|
||||
if (!(new_mfn=xc_make_page_below_4G(xc_handle, dom, p2m[i]))) {
|
||||
ERR("Couldn't get a page below 4GB :-(");
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
p2m[i] = new_mfn;
|
||||
if (xc_add_mmu_update(xc_handle, mmu,
|
||||
(((unsigned long long)new_mfn)
|
||||
<< PAGE_SHIFT) |
|
||||
if (xc_add_mmu_update(xc_handle, mmu,
|
||||
(((unsigned long long)new_mfn)
|
||||
<< PAGE_SHIFT) |
|
||||
MMU_MACHPHYS_UPDATE, i)) {
|
||||
ERR("Couldn't m2p on PAE root pgdir");
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
l3tab = (uint64_t *)
|
||||
xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
|
||||
PROT_READ | PROT_WRITE, p2m[i]);
|
||||
|
||||
for(j = 0; j < 4; j++)
|
||||
l3tab[j] = l3ptes[j];
|
||||
|
||||
munmap(l3tab, PAGE_SIZE);
|
||||
|
||||
xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
|
||||
PROT_READ | PROT_WRITE, p2m[i]);
|
||||
|
||||
for(j = 0; j < 4; j++)
|
||||
l3tab[j] = l3ptes[j];
|
||||
|
||||
munmap(l3tab, PAGE_SIZE);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Second pass: find all L1TABs and uncanonicalize them */
|
||||
j = 0;
|
||||
j = 0;
|
||||
|
||||
for(i = 0; i < max_pfn; i++) {
|
||||
|
||||
if (((pfn_type[i] & LTABTYPE_MASK)==L1TAB)) {
|
||||
region_mfn[j] = p2m[i];
|
||||
j++;
|
||||
for(i = 0; i < max_pfn; i++) {
|
||||
|
||||
if (((pfn_type[i] & LTABTYPE_MASK)==L1TAB)) {
|
||||
region_mfn[j] = p2m[i];
|
||||
j++;
|
||||
}
|
||||
|
||||
if(i == (max_pfn-1) || j == MAX_BATCH_SIZE) {
|
||||
if(i == (max_pfn-1) || j == MAX_BATCH_SIZE) {
|
||||
|
||||
if (!(region_base = xc_map_foreign_batch(
|
||||
xc_handle, dom, PROT_READ | PROT_WRITE,
|
||||
region_mfn, j))) {
|
||||
xc_handle, dom, PROT_READ | PROT_WRITE,
|
||||
region_mfn, j))) {
|
||||
ERR("map batch failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
for(k = 0; k < j; k++) {
|
||||
if(!uncanonicalize_pagetable(L1TAB,
|
||||
if(!uncanonicalize_pagetable(L1TAB,
|
||||
region_base + k*PAGE_SIZE)) {
|
||||
ERR("failed uncanonicalize pt!");
|
||||
goto out;
|
||||
}
|
||||
ERR("failed uncanonicalize pt!");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
munmap(region_base, j*PAGE_SIZE);
|
||||
j = 0;
|
||||
|
||||
munmap(region_base, j*PAGE_SIZE);
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (xc_finish_mmu_updates(xc_handle, mmu)) {
|
||||
ERR("Error doing finish_mmu_updates()");
|
||||
if (xc_finish_mmu_updates(xc_handle, mmu)) {
|
||||
ERR("Error doing finish_mmu_updates()");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Pin page tables. Do this after writing to them as otherwise Xen
|
||||
* will barf when doing the type-checking.
|
||||
*/
|
||||
nr_pins = 0;
|
||||
nr_pins = 0;
|
||||
for (i = 0; i < max_pfn; i++) {
|
||||
|
||||
if (i == (max_pfn-1) || nr_pins == MAX_PIN_BATCH) {
|
||||
if (xc_mmuext_op(xc_handle, pin, nr_pins, dom) < 0) {
|
||||
ERR("Failed to pin batch of %d page tables", nr_pins);
|
||||
if (xc_mmuext_op(xc_handle, pin, nr_pins, dom) < 0) {
|
||||
ERR("Failed to pin batch of %d page tables", nr_pins);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
nr_pins = 0;
|
||||
}
|
||||
|
||||
if ( (pfn_type[i] & LPINTAB) == 0 )
|
||||
continue;
|
||||
|
||||
switch(pfn_type[i]) {
|
||||
switch(pfn_type[i]) {
|
||||
|
||||
case (L1TAB|LPINTAB):
|
||||
case (L1TAB|LPINTAB):
|
||||
pin[nr_pins].cmd = MMUEXT_PIN_L1_TABLE;
|
||||
break;
|
||||
|
||||
case (L2TAB|LPINTAB):
|
||||
break;
|
||||
|
||||
case (L2TAB|LPINTAB):
|
||||
pin[nr_pins].cmd = MMUEXT_PIN_L2_TABLE;
|
||||
break;
|
||||
|
||||
case (L3TAB|LPINTAB):
|
||||
break;
|
||||
|
||||
case (L3TAB|LPINTAB):
|
||||
pin[nr_pins].cmd = MMUEXT_PIN_L3_TABLE;
|
||||
break;
|
||||
break;
|
||||
|
||||
case (L4TAB|LPINTAB):
|
||||
pin[nr_pins].cmd = MMUEXT_PIN_L4_TABLE;
|
||||
break;
|
||||
|
||||
default:
|
||||
continue;
|
||||
break;
|
||||
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
pin[nr_pins].arg1.mfn = p2m[i];
|
||||
nr_pins++;
|
||||
nr_pins++;
|
||||
|
||||
}
|
||||
|
||||
@@ -553,17 +553,17 @@ int xc_linux_restore(int xc_handle, int io_fd,
|
||||
unsigned long *pfntab;
|
||||
int rc;
|
||||
|
||||
if (!read_exact(io_fd, &count, sizeof(count))) {
|
||||
if (!read_exact(io_fd, &count, sizeof(count))) {
|
||||
ERR("Error when reading pfn count");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(!(pfntab = malloc(sizeof(unsigned long) * count))) {
|
||||
if(!(pfntab = malloc(sizeof(unsigned long) * count))) {
|
||||
ERR("Out of memory");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!read_exact(io_fd, pfntab, sizeof(unsigned long)*count)) {
|
||||
|
||||
if (!read_exact(io_fd, pfntab, sizeof(unsigned long)*count)) {
|
||||
ERR("Error when reading pfntab");
|
||||
goto out;
|
||||
}
|
||||
@@ -572,14 +572,14 @@ int xc_linux_restore(int xc_handle, int io_fd,
|
||||
|
||||
unsigned long pfn = pfntab[i];
|
||||
|
||||
if(pfn > max_pfn)
|
||||
if(pfn > max_pfn)
|
||||
/* shouldn't happen - continue optimistically */
|
||||
continue;
|
||||
continue;
|
||||
|
||||
pfntab[i] = p2m[pfn];
|
||||
p2m[pfn] = INVALID_P2M_ENTRY; // not in pseudo-physical map
|
||||
pfntab[i] = p2m[pfn];
|
||||
p2m[pfn] = INVALID_P2M_ENTRY; // not in pseudo-physical map
|
||||
}
|
||||
|
||||
|
||||
if (count > 0) {
|
||||
|
||||
struct xen_memory_reservation reservation = {
|
||||
@@ -590,16 +590,16 @@ int xc_linux_restore(int xc_handle, int io_fd,
|
||||
};
|
||||
|
||||
if ((rc = xc_memory_op(xc_handle, XENMEM_decrease_reservation,
|
||||
&reservation)) != count) {
|
||||
&reservation)) != count) {
|
||||
ERR("Could not decrease reservation : %d", rc);
|
||||
goto out;
|
||||
} else
|
||||
DPRINTF("Decreased reservation by %d pages\n", count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!read_exact(io_fd, &ctxt, sizeof(ctxt)) ||
|
||||
!read_exact(io_fd, shared_info_page, PAGE_SIZE)) {
|
||||
if (!read_exact(io_fd, &ctxt, sizeof(ctxt)) ||
|
||||
!read_exact(io_fd, shared_info_page, PAGE_SIZE)) {
|
||||
ERR("Error when reading ctxt or shared info page");
|
||||
goto out;
|
||||
}
|
||||
@@ -642,15 +642,15 @@ int xc_linux_restore(int xc_handle, int io_fd,
|
||||
|
||||
if (pfn >= max_pfn) {
|
||||
ERR("PT base is bad: pfn=%lu max_pfn=%lu type=%08lx",
|
||||
pfn, max_pfn, pfn_type[pfn]);
|
||||
pfn, max_pfn, pfn_type[pfn]);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ( (pfn_type[pfn] & LTABTYPE_MASK) !=
|
||||
if ( (pfn_type[pfn] & LTABTYPE_MASK) !=
|
||||
((unsigned long)pt_levels<<LTAB_SHIFT) ) {
|
||||
ERR("PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx",
|
||||
pfn, max_pfn, pfn_type[pfn],
|
||||
(unsigned long)pt_levels<<LTAB_SHIFT);
|
||||
pfn, max_pfn, pfn_type[pfn],
|
||||
(unsigned long)pt_levels<<LTAB_SHIFT);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -667,7 +667,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
|
||||
xc_handle, dom, PAGE_SIZE, PROT_WRITE, shared_info_frame);
|
||||
memcpy(page, shared_info, sizeof(shared_info_t));
|
||||
munmap(page, PAGE_SIZE);
|
||||
|
||||
|
||||
/* Uncanonicalise the pfn-to-mfn table frame-number list. */
|
||||
for (i = 0; i < P2M_FL_ENTRIES; i++) {
|
||||
pfn = p2m_frame_list[i];
|
||||
@@ -678,16 +678,16 @@ int xc_linux_restore(int xc_handle, int io_fd,
|
||||
|
||||
p2m_frame_list[i] = p2m[pfn];
|
||||
}
|
||||
|
||||
|
||||
/* Copy the P2M we've constructed to the 'live' P2M */
|
||||
if (!(live_p2m = xc_map_foreign_batch(xc_handle, dom, PROT_WRITE,
|
||||
if (!(live_p2m = xc_map_foreign_batch(xc_handle, dom, PROT_WRITE,
|
||||
p2m_frame_list, P2M_FL_ENTRIES))) {
|
||||
ERR("Couldn't map p2m table");
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(live_p2m, p2m, P2M_SIZE);
|
||||
munmap(live_p2m, P2M_SIZE);
|
||||
memcpy(live_p2m, p2m, P2M_SIZE);
|
||||
munmap(live_p2m, P2M_SIZE);
|
||||
|
||||
/*
|
||||
* Safety checking of saved context:
|
||||
|
||||
+290
-290
File diff suppressed because it is too large.
Load diff
@@ -22,7 +22,7 @@ static void copyout(int, uint32_t, unsigned long *, unsigned long, const char *,
|
||||
struct Exec *get_header(const char *, unsigned long, struct Exec *);
|
||||
|
||||
|
||||
int
|
||||
int
|
||||
probe_aout9(
|
||||
const char *image,
|
||||
unsigned long image_size,
|
||||
@@ -40,7 +40,7 @@ probe_aout9(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
static int
|
||||
parseaout9image(
|
||||
const char *image,
|
||||
unsigned long image_size,
|
||||
@@ -74,7 +74,7 @@ parseaout9image(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
static int
|
||||
loadaout9image(
|
||||
const char *image,
|
||||
unsigned long image_size,
|
||||
@@ -123,7 +123,7 @@ copyout(
|
||||
if(chunksz > PAGE_SIZE - pgoff)
|
||||
chunksz = PAGE_SIZE - pgoff;
|
||||
|
||||
pg = xc_map_foreign_range(xch, dom, PAGE_SIZE, PROT_WRITE,
|
||||
pg = xc_map_foreign_range(xch, dom, PAGE_SIZE, PROT_WRITE,
|
||||
parray[off>>PAGE_SHIFT]);
|
||||
memcpy(pg + pgoff, buf, chunksz);
|
||||
munmap(pg, PAGE_SIZE);
|
||||
|
||||
@@ -161,7 +161,7 @@ findtable(const char *image, unsigned long image_size)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int parsebinimage(const char *image,
|
||||
static int parsebinimage(const char *image,
|
||||
unsigned long image_size,
|
||||
struct domain_setup_info *dsi)
|
||||
{
|
||||
|
||||
@@ -51,7 +51,7 @@ static inline int is_loadable_phdr(Elf_Phdr *phdr)
|
||||
((phdr->p_flags & (PF_W|PF_X)) != 0));
|
||||
}
|
||||
|
||||
static int parseelfimage(const char *image,
|
||||
static int parseelfimage(const char *image,
|
||||
unsigned long elfsize,
|
||||
struct domain_setup_info *dsi)
|
||||
{
|
||||
@@ -102,10 +102,10 @@ static int parseelfimage(const char *image,
|
||||
ERROR("ELF image has no section-header strings table (shstrtab).");
|
||||
return -EINVAL;
|
||||
}
|
||||
shdr = (Elf_Shdr *)(image + ehdr->e_shoff +
|
||||
shdr = (Elf_Shdr *)(image + ehdr->e_shoff +
|
||||
(ehdr->e_shstrndx*ehdr->e_shentsize));
|
||||
shstrtab = image + shdr->sh_offset;
|
||||
|
||||
|
||||
/* Find the special '__xen_guest' section and check its contents. */
|
||||
for ( h = 0; h < ehdr->e_shnum; h++ )
|
||||
{
|
||||
@@ -148,7 +148,7 @@ static int parseelfimage(const char *image,
|
||||
|
||||
dsi->xen_guest_string = guestinfo;
|
||||
|
||||
for ( h = 0; h < ehdr->e_phnum; h++ )
|
||||
for ( h = 0; h < ehdr->e_phnum; h++ )
|
||||
{
|
||||
phdr = (Elf_Phdr *)(image + ehdr->e_phoff + (h*ehdr->e_phentsize));
|
||||
if ( !is_loadable_phdr(phdr) )
|
||||
@@ -159,8 +159,8 @@ static int parseelfimage(const char *image,
|
||||
kernend = phdr->p_paddr + phdr->p_memsz;
|
||||
}
|
||||
|
||||
if ( (kernstart > kernend) ||
|
||||
(ehdr->e_entry < kernstart) ||
|
||||
if ( (kernstart > kernend) ||
|
||||
(ehdr->e_entry < kernstart) ||
|
||||
(ehdr->e_entry > kernend) )
|
||||
{
|
||||
ERROR("Malformed ELF image.");
|
||||
@@ -196,12 +196,12 @@ loadelfimage(
|
||||
char *va;
|
||||
unsigned long pa, done, chunksz;
|
||||
|
||||
for ( h = 0; h < ehdr->e_phnum; h++ )
|
||||
for ( h = 0; h < ehdr->e_phnum; h++ )
|
||||
{
|
||||
phdr = (Elf_Phdr *)(image + ehdr->e_phoff + (h*ehdr->e_phentsize));
|
||||
if ( !is_loadable_phdr(phdr) )
|
||||
continue;
|
||||
|
||||
|
||||
for ( done = 0; done < phdr->p_filesz; done += chunksz )
|
||||
{
|
||||
pa = (phdr->p_paddr + done) - dsi->v_start;
|
||||
@@ -265,7 +265,7 @@ loadelfsymtab(
|
||||
shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr));
|
||||
memcpy(shdr, image + ehdr->e_shoff, ehdr->e_shnum * sizeof(Elf_Shdr));
|
||||
|
||||
for ( h = 0; h < ehdr->e_shnum; h++ )
|
||||
for ( h = 0; h < ehdr->e_shnum; h++ )
|
||||
{
|
||||
if ( shdr[h].sh_type == SHT_STRTAB )
|
||||
{
|
||||
|
||||
+13
-13
@@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
* xc_misc.c
|
||||
*
|
||||
*
|
||||
* Miscellaneous control interface functions.
|
||||
*/
|
||||
|
||||
@@ -21,7 +21,7 @@ int xc_interface_close(int xc_handle)
|
||||
|
||||
int xc_readconsolering(int xc_handle,
|
||||
char **pbuffer,
|
||||
unsigned int *pnr_chars,
|
||||
unsigned int *pnr_chars,
|
||||
int clear)
|
||||
{
|
||||
int ret;
|
||||
@@ -46,14 +46,14 @@ int xc_readconsolering(int xc_handle,
|
||||
safe_munlock(buffer, nr_chars);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
int xc_physinfo(int xc_handle,
|
||||
xc_physinfo_t *put_info)
|
||||
{
|
||||
int ret;
|
||||
DECLARE_DOM0_OP;
|
||||
|
||||
|
||||
op.cmd = DOM0_PHYSINFO;
|
||||
op.interface_version = DOM0_INTERFACE_VERSION;
|
||||
|
||||
@@ -70,15 +70,15 @@ int xc_sched_id(int xc_handle,
|
||||
{
|
||||
int ret;
|
||||
DECLARE_DOM0_OP;
|
||||
|
||||
|
||||
op.cmd = DOM0_SCHED_ID;
|
||||
op.interface_version = DOM0_INTERFACE_VERSION;
|
||||
|
||||
|
||||
if ( (ret = do_dom0_op(xc_handle, &op)) != 0 )
|
||||
return ret;
|
||||
|
||||
|
||||
*sched_id = op.u.sched_id.sched_id;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -100,9 +100,9 @@ int xc_perfc_control(int xc_handle,
|
||||
|
||||
long long xc_msr_read(int xc_handle, int cpu_mask, int msr)
|
||||
{
|
||||
int rc;
|
||||
int rc;
|
||||
DECLARE_DOM0_OP;
|
||||
|
||||
|
||||
op.cmd = DOM0_MSR;
|
||||
op.u.msr.write = 0;
|
||||
op.u.msr.msr = msr;
|
||||
@@ -116,9 +116,9 @@ long long xc_msr_read(int xc_handle, int cpu_mask, int msr)
|
||||
int xc_msr_write(int xc_handle, int cpu_mask, int msr, unsigned int low,
|
||||
unsigned int high)
|
||||
{
|
||||
int rc;
|
||||
int rc;
|
||||
DECLARE_DOM0_OP;
|
||||
|
||||
|
||||
op.cmd = DOM0_MSR;
|
||||
op.u.msr.write = 1;
|
||||
op.u.msr.msr = msr;
|
||||
@@ -127,7 +127,7 @@ int xc_msr_write(int xc_handle, int cpu_mask, int msr, unsigned int low,
|
||||
op.u.msr.in2 = high;
|
||||
|
||||
rc = do_dom0_op(xc_handle, &op);
|
||||
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/******************************************************************************
|
||||
* xc_physdev.c
|
||||
*
|
||||
*
|
||||
* API for manipulating physical-device access permissions.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2004, Rolf Neugebauer (Intel Research Cambridge)
|
||||
* Copyright (c) 2004, K A Fraser (University of Cambridge)
|
||||
*/
|
||||
|
||||
+16
-16
@@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
* xc_private.c
|
||||
*
|
||||
*
|
||||
* Helper functions for the rest of the library.
|
||||
*/
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
void *xc_map_foreign_batch(int xc_handle, uint32_t dom, int prot,
|
||||
unsigned long *arr, int num )
|
||||
{
|
||||
privcmd_mmapbatch_t ioctlx;
|
||||
privcmd_mmapbatch_t ioctlx;
|
||||
void *addr;
|
||||
addr = mmap(NULL, num*PAGE_SIZE, prot, MAP_SHARED, xc_handle, 0);
|
||||
if ( addr == MAP_FAILED )
|
||||
@@ -38,8 +38,8 @@ void *xc_map_foreign_range(int xc_handle, uint32_t dom,
|
||||
int size, int prot,
|
||||
unsigned long mfn )
|
||||
{
|
||||
privcmd_mmap_t ioctlx;
|
||||
privcmd_mmap_entry_t entry;
|
||||
privcmd_mmap_t ioctlx;
|
||||
privcmd_mmap_entry_t entry;
|
||||
void *addr;
|
||||
addr = mmap(NULL, size, prot, MAP_SHARED, xc_handle, 0);
|
||||
if ( addr == MAP_FAILED )
|
||||
@@ -64,7 +64,7 @@ void *xc_map_foreign_range(int xc_handle, uint32_t dom,
|
||||
/*******************/
|
||||
|
||||
/* NB: arr must be mlock'ed */
|
||||
int xc_get_pfn_type_batch(int xc_handle,
|
||||
int xc_get_pfn_type_batch(int xc_handle,
|
||||
uint32_t dom, int num, unsigned long *arr)
|
||||
{
|
||||
DECLARE_DOM0_OP;
|
||||
@@ -76,8 +76,8 @@ int xc_get_pfn_type_batch(int xc_handle,
|
||||
}
|
||||
|
||||
#define GETPFN_ERR (~0U)
|
||||
unsigned int get_pfn_type(int xc_handle,
|
||||
unsigned long mfn,
|
||||
unsigned int get_pfn_type(int xc_handle,
|
||||
unsigned long mfn,
|
||||
uint32_t dom)
|
||||
{
|
||||
DECLARE_DOM0_OP;
|
||||
@@ -119,7 +119,7 @@ int xc_mmuext_op(
|
||||
|
||||
out1:
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
static int flush_mmu_updates(int xc_handle, xc_mmu_t *mmu)
|
||||
{
|
||||
@@ -166,7 +166,7 @@ xc_mmu_t *xc_init_mmu_updates(int xc_handle, domid_t dom)
|
||||
return mmu;
|
||||
}
|
||||
|
||||
int xc_add_mmu_update(int xc_handle, xc_mmu_t *mmu,
|
||||
int xc_add_mmu_update(int xc_handle, xc_mmu_t *mmu,
|
||||
unsigned long long ptr, unsigned long long val)
|
||||
{
|
||||
mmu->updates[mmu->idx].ptr = ptr;
|
||||
@@ -288,7 +288,7 @@ int xc_memory_op(int xc_handle,
|
||||
|
||||
out1:
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
long long xc_domain_get_cpu_usage( int xc_handle, domid_t domid, int vcpu )
|
||||
@@ -308,8 +308,8 @@ long long xc_domain_get_cpu_usage( int xc_handle, domid_t domid, int vcpu )
|
||||
|
||||
|
||||
int xc_get_pfn_list(int xc_handle,
|
||||
uint32_t domid,
|
||||
unsigned long *pfn_buf,
|
||||
uint32_t domid,
|
||||
unsigned long *pfn_buf,
|
||||
unsigned long max_pfns)
|
||||
{
|
||||
DECLARE_DOM0_OP;
|
||||
@@ -327,7 +327,7 @@ int xc_get_pfn_list(int xc_handle,
|
||||
{
|
||||
PERROR("xc_get_pfn_list: pfn_buf mlock failed");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ret = do_dom0_op(xc_handle, &op);
|
||||
|
||||
@@ -356,13 +356,13 @@ long xc_get_tot_pages(int xc_handle, uint32_t domid)
|
||||
DECLARE_DOM0_OP;
|
||||
op.cmd = DOM0_GETDOMAININFO;
|
||||
op.u.getdomaininfo.domain = (domid_t)domid;
|
||||
return (do_dom0_op(xc_handle, &op) < 0) ?
|
||||
return (do_dom0_op(xc_handle, &op) < 0) ?
|
||||
-1 : op.u.getdomaininfo.tot_pages;
|
||||
}
|
||||
|
||||
int xc_copy_to_domain_page(int xc_handle,
|
||||
uint32_t domid,
|
||||
unsigned long dst_pfn,
|
||||
unsigned long dst_pfn,
|
||||
const char *src_page)
|
||||
{
|
||||
void *vaddr = xc_map_foreign_range(
|
||||
@@ -481,7 +481,7 @@ unsigned long xc_make_page_below_4G(
|
||||
{
|
||||
unsigned long new_mfn;
|
||||
|
||||
if ( xc_domain_memory_decrease_reservation(
|
||||
if ( xc_domain_memory_decrease_reservation(
|
||||
xc_handle, domid, 1, 0, &mfn) != 0 )
|
||||
{
|
||||
fprintf(stderr,"xc_make_page_below_4G decrease failed. mfn=%lx\n",mfn);
|
||||
|
||||
@@ -57,7 +57,7 @@ static inline void safe_munlock(const void *addr, size_t len)
|
||||
}
|
||||
|
||||
static inline int do_privcmd(int xc_handle,
|
||||
unsigned int cmd,
|
||||
unsigned int cmd,
|
||||
unsigned long data)
|
||||
{
|
||||
return ioctl(xc_handle, cmd, data);
|
||||
@@ -67,7 +67,7 @@ static inline int do_xen_hypercall(int xc_handle,
|
||||
privcmd_hypercall_t *hypercall)
|
||||
{
|
||||
return do_privcmd(xc_handle,
|
||||
IOCTL_PRIVCMD_HYPERCALL,
|
||||
IOCTL_PRIVCMD_HYPERCALL,
|
||||
(unsigned long)hypercall);
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ static inline int do_xen_version(int xc_handle, int cmd, void *dest)
|
||||
hypercall.op = __HYPERVISOR_xen_version;
|
||||
hypercall.arg[0] = (unsigned long) cmd;
|
||||
hypercall.arg[1] = (unsigned long) dest;
|
||||
|
||||
|
||||
return do_xen_hypercall(xc_handle, &hypercall);
|
||||
}
|
||||
|
||||
@@ -121,13 +121,13 @@ typedef struct privcmd_mmap_entry {
|
||||
unsigned long va;
|
||||
unsigned long mfn;
|
||||
unsigned long npages;
|
||||
} privcmd_mmap_entry_t;
|
||||
} privcmd_mmap_entry_t;
|
||||
|
||||
typedef struct privcmd_mmap {
|
||||
int num;
|
||||
domid_t dom;
|
||||
privcmd_mmap_entry_t *entry;
|
||||
} privcmd_mmap_t;
|
||||
} privcmd_mmap_t;
|
||||
*/
|
||||
|
||||
#endif /* __XC_PRIVATE_H__ */
|
||||
+49
-49
@@ -46,7 +46,7 @@ static cpumap_t regs_valid;
|
||||
static vcpu_guest_context_t ctxt[MAX_VIRT_CPUS];
|
||||
|
||||
extern int ffsll(long long int);
|
||||
#define FOREACH_CPU(cpumap, i) for ( cpumap = online_cpumap; (i = ffsll(cpumap)); cpumap &= ~(1 << (index - 1)) )
|
||||
#define FOREACH_CPU(cpumap, i) for ( cpumap = online_cpumap; (i = ffsll(cpumap)); cpumap &= ~(1 << (index - 1)) )
|
||||
|
||||
|
||||
static int
|
||||
@@ -58,22 +58,22 @@ fetch_regs(int xc_handle, int cpu, int *online)
|
||||
if (online)
|
||||
*online = 0;
|
||||
if ( !(regs_valid & (1 << cpu)) )
|
||||
{
|
||||
retval = xc_vcpu_getcontext(xc_handle, current_domid,
|
||||
cpu, &ctxt[cpu]);
|
||||
if ( retval )
|
||||
{
|
||||
retval = xc_vcpu_getcontext(xc_handle, current_domid,
|
||||
cpu, &ctxt[cpu]);
|
||||
if ( retval )
|
||||
goto done;
|
||||
regs_valid |= (1 << cpu);
|
||||
regs_valid |= (1 << cpu);
|
||||
|
||||
}
|
||||
if ( online == NULL )
|
||||
goto done;
|
||||
if ( online == NULL )
|
||||
goto done;
|
||||
|
||||
retval = xc_vcpu_getinfo(xc_handle, current_domid, cpu, &info);
|
||||
*online = info.online;
|
||||
|
||||
retval = xc_vcpu_getinfo(xc_handle, current_domid, cpu, &info);
|
||||
*online = info.online;
|
||||
|
||||
done:
|
||||
return retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
static struct thr_ev_handlers {
|
||||
@@ -81,8 +81,8 @@ static struct thr_ev_handlers {
|
||||
thr_ev_handler_t td_death;
|
||||
} handlers;
|
||||
|
||||
void
|
||||
xc_register_event_handler(thr_ev_handler_t h,
|
||||
void
|
||||
xc_register_event_handler(thr_ev_handler_t h,
|
||||
td_event_e e)
|
||||
{
|
||||
switch (e) {
|
||||
@@ -97,7 +97,7 @@ xc_register_event_handler(thr_ev_handler_t h,
|
||||
}
|
||||
}
|
||||
|
||||
static inline int
|
||||
static inline int
|
||||
paging_enabled(vcpu_guest_context_t *v)
|
||||
{
|
||||
unsigned long cr0 = v->ctrlreg[0];
|
||||
@@ -114,19 +114,19 @@ static int
|
||||
get_online_cpumap(int xc_handle, dom0_getdomaininfo_t *d, cpumap_t *cpumap)
|
||||
{
|
||||
int i, online, retval;
|
||||
|
||||
|
||||
*cpumap = 0;
|
||||
for (i = 0; i <= d->max_vcpu_id; i++) {
|
||||
if ((retval = fetch_regs(xc_handle, i, &online)))
|
||||
return retval;
|
||||
if (online)
|
||||
*cpumap |= (1 << i);
|
||||
*cpumap |= (1 << i);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* Notify GDB of any vcpus that have come online or gone offline
|
||||
* update online_cpumap
|
||||
*
|
||||
@@ -137,7 +137,7 @@ online_vcpus_changed(cpumap_t cpumap)
|
||||
{
|
||||
cpumap_t changed_cpumap = cpumap ^ online_cpumap;
|
||||
int index;
|
||||
|
||||
|
||||
while ( (index = ffsll(changed_cpumap)) ) {
|
||||
if ( cpumap & (1 << (index - 1)) )
|
||||
{
|
||||
@@ -149,7 +149,7 @@ online_vcpus_changed(cpumap_t cpumap)
|
||||
changed_cpumap &= ~(1 << (index - 1));
|
||||
}
|
||||
online_cpumap = cpumap;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* --------------------- */
|
||||
@@ -172,7 +172,7 @@ map_domain_va_32(
|
||||
static unsigned long pde_phys[MAX_VIRT_CPUS];
|
||||
static uint32_t *pde_virt[MAX_VIRT_CPUS];
|
||||
static unsigned long page_phys[MAX_VIRT_CPUS];
|
||||
static uint32_t *page_virt[MAX_VIRT_CPUS];
|
||||
static uint32_t *page_virt[MAX_VIRT_CPUS];
|
||||
static int prev_perm[MAX_VIRT_CPUS];
|
||||
|
||||
if (ctxt[cpu].ctrlreg[3] == 0)
|
||||
@@ -221,7 +221,7 @@ map_domain_va_32(
|
||||
return NULL;
|
||||
}
|
||||
prev_perm[cpu] = perm;
|
||||
}
|
||||
}
|
||||
|
||||
return (void *)(((unsigned long)page_virt[cpu]) | (va & BSD_PAGE_MASK));
|
||||
}
|
||||
@@ -284,7 +284,7 @@ map_domain_va_64(
|
||||
if ((ctxt[cpu].ctrlreg[4] & 0x20) == 0 ) /* legacy ia32 mode */
|
||||
return map_domain_va_32(xc_handle, cpu, guest_va, perm);
|
||||
|
||||
l4 = xc_map_foreign_range( xc_handle, current_domid, PAGE_SIZE,
|
||||
l4 = xc_map_foreign_range( xc_handle, current_domid, PAGE_SIZE,
|
||||
PROT_READ, ctxt[cpu].ctrlreg[3] >> PAGE_SHIFT);
|
||||
if ( l4 == NULL )
|
||||
return NULL;
|
||||
@@ -349,7 +349,7 @@ map_domain_va(
|
||||
mode = MODE_64;
|
||||
else if ( strstr(caps, "-x86_32p") )
|
||||
mode = MODE_PAE;
|
||||
else if ( strstr(caps, "-x86_32") )
|
||||
else if ( strstr(caps, "-x86_32") )
|
||||
mode = MODE_32;
|
||||
}
|
||||
|
||||
@@ -374,7 +374,7 @@ map_domain_va(
|
||||
if (fetch_regs(xc_handle, cpu, NULL))
|
||||
return NULL;
|
||||
|
||||
if (!paging_enabled(&ctxt[cpu])) {
|
||||
if (!paging_enabled(&ctxt[cpu])) {
|
||||
static void * v;
|
||||
unsigned long page;
|
||||
|
||||
@@ -383,9 +383,9 @@ map_domain_va(
|
||||
|
||||
page = page_array[va >> PAGE_SHIFT] << PAGE_SHIFT;
|
||||
|
||||
v = xc_map_foreign_range( xc_handle, current_domid, PAGE_SIZE,
|
||||
v = xc_map_foreign_range( xc_handle, current_domid, PAGE_SIZE,
|
||||
perm, page >> PAGE_SHIFT);
|
||||
|
||||
|
||||
if ( v == NULL )
|
||||
return NULL;
|
||||
|
||||
@@ -403,7 +403,7 @@ map_domain_va(
|
||||
|
||||
int control_c_pressed_flag = 0;
|
||||
|
||||
static int
|
||||
static int
|
||||
__xc_waitdomain(
|
||||
int xc_handle,
|
||||
int domain,
|
||||
@@ -420,7 +420,7 @@ __xc_waitdomain(
|
||||
|
||||
op.cmd = DOM0_GETDOMAININFO;
|
||||
op.u.getdomaininfo.domain = domain;
|
||||
|
||||
|
||||
retry:
|
||||
retval = do_dom0_op(xc_handle, &op);
|
||||
if ( retval || (op.u.getdomaininfo.domain != domain) )
|
||||
@@ -429,7 +429,7 @@ __xc_waitdomain(
|
||||
goto done;
|
||||
}
|
||||
*status = op.u.getdomaininfo.flags;
|
||||
|
||||
|
||||
if ( options & WNOHANG )
|
||||
goto done;
|
||||
|
||||
@@ -472,16 +472,16 @@ xc_ptrace(
|
||||
void *data = (char *)edata;
|
||||
|
||||
cpu = (request != PTRACE_ATTACH) ? domid_tid : 0;
|
||||
|
||||
|
||||
switch ( request )
|
||||
{
|
||||
{
|
||||
case PTRACE_PEEKTEXT:
|
||||
case PTRACE_PEEKDATA:
|
||||
if (current_isfile)
|
||||
guest_va = (unsigned long *)map_domain_va_core(current_domid,
|
||||
guest_va = (unsigned long *)map_domain_va_core(current_domid,
|
||||
cpu, addr, ctxt);
|
||||
else
|
||||
guest_va = (unsigned long *)map_domain_va(xc_handle,
|
||||
guest_va = (unsigned long *)map_domain_va(xc_handle,
|
||||
cpu, addr, PROT_READ);
|
||||
if ( guest_va == NULL )
|
||||
goto out_error;
|
||||
@@ -492,26 +492,26 @@ xc_ptrace(
|
||||
case PTRACE_POKEDATA:
|
||||
/* XXX assume that all CPUs have the same address space */
|
||||
if (current_isfile)
|
||||
guest_va = (unsigned long *)map_domain_va_core(current_domid,
|
||||
guest_va = (unsigned long *)map_domain_va_core(current_domid,
|
||||
cpu, addr, ctxt);
|
||||
else
|
||||
guest_va = (unsigned long *)map_domain_va(xc_handle,
|
||||
guest_va = (unsigned long *)map_domain_va(xc_handle,
|
||||
cpu, addr, PROT_READ|PROT_WRITE);
|
||||
if ( guest_va == NULL )
|
||||
if ( guest_va == NULL )
|
||||
goto out_error;
|
||||
*guest_va = (unsigned long)data;
|
||||
break;
|
||||
|
||||
case PTRACE_GETREGS:
|
||||
if (!current_isfile && fetch_regs(xc_handle, cpu, NULL))
|
||||
if (!current_isfile && fetch_regs(xc_handle, cpu, NULL))
|
||||
goto out_error;
|
||||
SET_PT_REGS(pt, ctxt[cpu].user_regs);
|
||||
SET_PT_REGS(pt, ctxt[cpu].user_regs);
|
||||
memcpy(data, &pt, sizeof(struct gdb_regs));
|
||||
break;
|
||||
|
||||
case PTRACE_GETFPREGS:
|
||||
case PTRACE_GETFPXREGS:
|
||||
if (!current_isfile && fetch_regs(xc_handle, cpu, NULL))
|
||||
if (!current_isfile && fetch_regs(xc_handle, cpu, NULL))
|
||||
goto out_error;
|
||||
memcpy(data, &ctxt[cpu].fpu_ctxt, sizeof(ctxt[cpu].fpu_ctxt));
|
||||
break;
|
||||
@@ -520,7 +520,7 @@ xc_ptrace(
|
||||
if (current_isfile)
|
||||
goto out_unspported; /* XXX not yet supported */
|
||||
SET_XC_REGS(((struct gdb_regs *)data), ctxt[cpu].user_regs);
|
||||
if ((retval = xc_vcpu_setcontext(xc_handle, current_domid, cpu,
|
||||
if ((retval = xc_vcpu_setcontext(xc_handle, current_domid, cpu,
|
||||
&ctxt[cpu])))
|
||||
goto out_error_dom0;
|
||||
break;
|
||||
@@ -531,8 +531,8 @@ xc_ptrace(
|
||||
/* XXX we can still have problems if the user switches threads
|
||||
* during single-stepping - but that just seems retarded
|
||||
*/
|
||||
ctxt[cpu].user_regs.eflags |= PSL_T;
|
||||
if ((retval = xc_vcpu_setcontext(xc_handle, current_domid, cpu,
|
||||
ctxt[cpu].user_regs.eflags |= PSL_T;
|
||||
if ((retval = xc_vcpu_setcontext(xc_handle, current_domid, cpu,
|
||||
&ctxt[cpu])))
|
||||
goto out_error_dom0;
|
||||
/* FALLTHROUGH */
|
||||
@@ -545,13 +545,13 @@ xc_ptrace(
|
||||
{
|
||||
FOREACH_CPU(cpumap, index) {
|
||||
cpu = index - 1;
|
||||
if (fetch_regs(xc_handle, cpu, NULL))
|
||||
if (fetch_regs(xc_handle, cpu, NULL))
|
||||
goto out_error;
|
||||
/* Clear trace flag */
|
||||
if ( ctxt[cpu].user_regs.eflags & PSL_T )
|
||||
if ( ctxt[cpu].user_regs.eflags & PSL_T )
|
||||
{
|
||||
ctxt[cpu].user_regs.eflags &= ~PSL_T;
|
||||
if ((retval = xc_vcpu_setcontext(xc_handle, current_domid,
|
||||
if ((retval = xc_vcpu_setcontext(xc_handle, current_domid,
|
||||
cpu, &ctxt[cpu])))
|
||||
goto out_error_dom0;
|
||||
}
|
||||
@@ -566,7 +566,7 @@ xc_ptrace(
|
||||
goto out_error_dom0;
|
||||
}
|
||||
regs_valid = 0;
|
||||
if ((retval = xc_domain_unpause(xc_handle, current_domid > 0 ?
|
||||
if ((retval = xc_domain_unpause(xc_handle, current_domid > 0 ?
|
||||
current_domid : -current_domid)))
|
||||
goto out_error_dom0;
|
||||
break;
|
||||
@@ -627,7 +627,7 @@ xc_ptrace(
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
xc_waitdomain(
|
||||
int xc_handle,
|
||||
int domain,
|
||||
|
||||
@@ -107,7 +107,7 @@ struct gdb_regs {
|
||||
long esi; /* 12 */
|
||||
long edi; /* 16 */
|
||||
long ebp; /* 20 */
|
||||
long eax; /* 24 */
|
||||
long eax; /* 24 */
|
||||
int xds; /* 28 */
|
||||
int xes; /* 32 */
|
||||
int xfs; /* 36 */
|
||||
@@ -116,7 +116,7 @@ struct gdb_regs {
|
||||
long eip; /* 48 */
|
||||
int xcs; /* 52 */
|
||||
long eflags; /* 56 */
|
||||
long esp; /* 60 */
|
||||
long esp; /* 60 */
|
||||
int xss; /* 64 */
|
||||
};
|
||||
|
||||
@@ -169,20 +169,20 @@ struct gdb_regs {
|
||||
typedef void (*thr_ev_handler_t)(long);
|
||||
|
||||
void xc_register_event_handler(
|
||||
thr_ev_handler_t h,
|
||||
thr_ev_handler_t h,
|
||||
td_event_e e);
|
||||
|
||||
long xc_ptrace(
|
||||
int xc_handle,
|
||||
enum __ptrace_request request,
|
||||
enum __ptrace_request request,
|
||||
uint32_t domid,
|
||||
long addr,
|
||||
long addr,
|
||||
long data);
|
||||
|
||||
int xc_waitdomain(
|
||||
int xc_handle,
|
||||
int domain,
|
||||
int *status,
|
||||
int domain,
|
||||
int *status,
|
||||
int options);
|
||||
|
||||
#endif /* XC_PTRACE */
|
||||
@@ -39,7 +39,7 @@ map_domain_va_core(unsigned long domfd, int cpu, void * guest_va,
|
||||
static unsigned long page_phys[MAX_VIRT_CPUS];
|
||||
static unsigned long *page_virt[MAX_VIRT_CPUS];
|
||||
|
||||
if (cr3[cpu] != cr3_phys[cpu])
|
||||
if (cr3[cpu] != cr3_phys[cpu])
|
||||
{
|
||||
cr3_phys[cpu] = cr3[cpu];
|
||||
if (cr3_virt[cpu])
|
||||
@@ -53,12 +53,12 @@ map_domain_va_core(unsigned long domfd, int cpu, void * guest_va,
|
||||
return NULL;
|
||||
}
|
||||
cr3_virt[cpu] = v;
|
||||
}
|
||||
}
|
||||
if ((pde = cr3_virt[cpu][vtopdi(va)]) == 0) /* logical address */
|
||||
return NULL;
|
||||
if (ctxt[cpu].flags & VGCF_HVM_GUEST)
|
||||
pde = p2m_array[pde >> PAGE_SHIFT] << PAGE_SHIFT;
|
||||
if (pde != pde_phys[cpu])
|
||||
if (pde != pde_phys[cpu])
|
||||
{
|
||||
pde_phys[cpu] = pde;
|
||||
if (pde_virt[cpu])
|
||||
@@ -74,7 +74,7 @@ map_domain_va_core(unsigned long domfd, int cpu, void * guest_va,
|
||||
return NULL;
|
||||
if (ctxt[cpu].flags & VGCF_HVM_GUEST)
|
||||
page = p2m_array[page >> PAGE_SHIFT] << PAGE_SHIFT;
|
||||
if (page != page_phys[cpu])
|
||||
if (page != page_phys[cpu])
|
||||
{
|
||||
page_phys[cpu] = page;
|
||||
if (page_virt[cpu])
|
||||
@@ -89,11 +89,11 @@ map_domain_va_core(unsigned long domfd, int cpu, void * guest_va,
|
||||
return NULL;
|
||||
}
|
||||
page_virt[cpu] = v;
|
||||
}
|
||||
}
|
||||
return (void *)(((unsigned long)page_virt[cpu]) | (va & BSD_PAGE_MASK));
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
xc_waitdomain_core(
|
||||
int xc_handle,
|
||||
int domfd,
|
||||
@@ -122,7 +122,7 @@ xc_waitdomain_core(
|
||||
nr_vcpus = header.xch_nr_vcpus;
|
||||
pages_offset = header.xch_pages_offset;
|
||||
|
||||
if (read(domfd, ctxt, sizeof(vcpu_guest_context_t)*nr_vcpus) !=
|
||||
if (read(domfd, ctxt, sizeof(vcpu_guest_context_t)*nr_vcpus) !=
|
||||
sizeof(vcpu_guest_context_t)*nr_vcpus)
|
||||
return -1;
|
||||
|
||||
@@ -134,7 +134,7 @@ xc_waitdomain_core(
|
||||
printf("Could not allocate p2m_array\n");
|
||||
return -1;
|
||||
}
|
||||
if (read(domfd, p2m_array, sizeof(unsigned long)*nr_pages) !=
|
||||
if (read(domfd, p2m_array, sizeof(unsigned long)*nr_pages) !=
|
||||
sizeof(unsigned long)*nr_pages)
|
||||
return -1;
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/******************************************************************************
|
||||
* xc_sedf.c
|
||||
*
|
||||
*
|
||||
* API for manipulating parameters of the Simple EDF scheduler.
|
||||
*
|
||||
*
|
||||
* changes by Stephan Diestelhorst
|
||||
* based on code
|
||||
* by Mark Williamson, Copyright (c) 2004 Intel Research Cambridge.
|
||||
@@ -35,7 +35,7 @@ int xc_sedf_domain_get(int xc_handle, uint32_t domid, uint64_t *period, uint64_t
|
||||
int ret;
|
||||
struct sedf_adjdom *p = &op.u.adjustdom.u.sedf;
|
||||
|
||||
op.cmd = DOM0_ADJUSTDOM;
|
||||
op.cmd = DOM0_ADJUSTDOM;
|
||||
op.u.adjustdom.domain = (domid_t)domid;
|
||||
op.u.adjustdom.sched_id = SCHED_SEDF;
|
||||
op.u.adjustdom.direction = SCHED_INFO_GET;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/******************************************************************************
|
||||
* xc_tbuf.c
|
||||
*
|
||||
*
|
||||
* API for manipulating and accessing trace buffer parameters
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2005, Rob Gardner
|
||||
*/
|
||||
|
||||
@@ -18,7 +18,7 @@ int xc_tbuf_enable(int xc_handle, int enable)
|
||||
op.u.tbufcontrol.op = DOM0_TBUF_ENABLE;
|
||||
else
|
||||
op.u.tbufcontrol.op = DOM0_TBUF_DISABLE;
|
||||
|
||||
|
||||
return xc_dom0_op(xc_handle, &op);
|
||||
}
|
||||
|
||||
@@ -30,10 +30,10 @@ int xc_tbuf_set_size(int xc_handle, uint32_t size)
|
||||
op.interface_version = DOM0_INTERFACE_VERSION;
|
||||
op.u.tbufcontrol.op = DOM0_TBUF_SET_SIZE;
|
||||
op.u.tbufcontrol.size = size;
|
||||
|
||||
|
||||
return xc_dom0_op(xc_handle, &op);
|
||||
}
|
||||
|
||||
|
||||
int xc_tbuf_get_size(int xc_handle, uint32_t *size)
|
||||
{
|
||||
int rc;
|
||||
|
||||
+32
-32
@@ -1,8 +1,8 @@
|
||||
/******************************************************************************
|
||||
* xenctrl.h
|
||||
*
|
||||
*
|
||||
* A library for low-level access to the Xen control interfaces.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2003-2004, K A Fraser.
|
||||
*/
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
/*
|
||||
* DEFINITIONS FOR CPU BARRIERS
|
||||
*/
|
||||
*/
|
||||
|
||||
#if defined(__i386__)
|
||||
#define mb() __asm__ __volatile__ ( "lock; addl $0,0(%%esp)" : : : "memory" )
|
||||
@@ -51,7 +51,7 @@
|
||||
|
||||
/*
|
||||
* INITIALIZATION FUNCTIONS
|
||||
*/
|
||||
*/
|
||||
|
||||
/**
|
||||
* This function opens a handle to the hypervisor interface. This function can
|
||||
@@ -96,20 +96,20 @@ typedef struct xc_core_header {
|
||||
|
||||
long xc_ptrace_core(
|
||||
int xc_handle,
|
||||
enum __ptrace_request request,
|
||||
uint32_t domid,
|
||||
long addr,
|
||||
enum __ptrace_request request,
|
||||
uint32_t domid,
|
||||
long addr,
|
||||
long data,
|
||||
vcpu_guest_context_t *ctxt);
|
||||
void * map_domain_va_core(
|
||||
unsigned long domfd,
|
||||
int cpu,
|
||||
unsigned long domfd,
|
||||
int cpu,
|
||||
void *guest_va,
|
||||
vcpu_guest_context_t *ctxt);
|
||||
int xc_waitdomain_core(
|
||||
int xc_handle,
|
||||
int domain,
|
||||
int *status,
|
||||
int domain,
|
||||
int *status,
|
||||
int options,
|
||||
vcpu_guest_context_t *ctxt);
|
||||
|
||||
@@ -120,7 +120,7 @@ int xc_waitdomain_core(
|
||||
typedef struct {
|
||||
uint32_t domid;
|
||||
uint32_t ssidref;
|
||||
unsigned int dying:1, crashed:1, shutdown:1,
|
||||
unsigned int dying:1, crashed:1, shutdown:1,
|
||||
paused:1, blocked:1, running:1;
|
||||
unsigned int shutdown_reason; /* only meaningful if shutdown==1 */
|
||||
unsigned long nr_pages;
|
||||
@@ -133,7 +133,7 @@ typedef struct {
|
||||
} xc_dominfo_t;
|
||||
|
||||
typedef dom0_getdomaininfo_t xc_domaininfo_t;
|
||||
int xc_domain_create(int xc_handle,
|
||||
int xc_domain_create(int xc_handle,
|
||||
uint32_t ssidref,
|
||||
xen_domain_handle_t handle,
|
||||
uint32_t *pdomid);
|
||||
@@ -144,7 +144,7 @@ int xc_domain_create(int xc_handle,
|
||||
* xc_domain_dumpcore_via_callback - produces a dump, using a specified
|
||||
* callback function
|
||||
*/
|
||||
int xc_domain_dumpcore(int xc_handle,
|
||||
int xc_domain_dumpcore(int xc_handle,
|
||||
uint32_t domid,
|
||||
const char *corename);
|
||||
|
||||
@@ -156,7 +156,7 @@ int xc_domain_dumpcore(int xc_handle,
|
||||
*/
|
||||
typedef int (dumpcore_rtn_t)(void *arg, char *buffer, unsigned int length);
|
||||
|
||||
int xc_domain_dumpcore_via_callback(int xc_handle,
|
||||
int xc_domain_dumpcore_via_callback(int xc_handle,
|
||||
uint32_t domid,
|
||||
void *arg,
|
||||
dumpcore_rtn_t dump_rtn);
|
||||
@@ -170,7 +170,7 @@ int xc_domain_dumpcore_via_callback(int xc_handle,
|
||||
* @return 0 on success, -1 on failure.
|
||||
*/
|
||||
int xc_domain_max_vcpus(int xc_handle,
|
||||
uint32_t domid,
|
||||
uint32_t domid,
|
||||
unsigned int max);
|
||||
|
||||
/**
|
||||
@@ -181,7 +181,7 @@ int xc_domain_max_vcpus(int xc_handle,
|
||||
* @parm domid the domain id to pause
|
||||
* @return 0 on success, -1 on failure.
|
||||
*/
|
||||
int xc_domain_pause(int xc_handle,
|
||||
int xc_domain_pause(int xc_handle,
|
||||
uint32_t domid);
|
||||
/**
|
||||
* This function unpauses a domain. The domain should have been previously
|
||||
@@ -191,7 +191,7 @@ int xc_domain_pause(int xc_handle,
|
||||
* @parm domid the domain id to unpause
|
||||
* return 0 on success, -1 on failure
|
||||
*/
|
||||
int xc_domain_unpause(int xc_handle,
|
||||
int xc_domain_unpause(int xc_handle,
|
||||
uint32_t domid);
|
||||
|
||||
/**
|
||||
@@ -203,7 +203,7 @@ int xc_domain_unpause(int xc_handle,
|
||||
* @parm domid the domain id to destroy
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int xc_domain_destroy(int xc_handle,
|
||||
int xc_domain_destroy(int xc_handle,
|
||||
uint32_t domid);
|
||||
|
||||
/**
|
||||
@@ -217,7 +217,7 @@ int xc_domain_destroy(int xc_handle,
|
||||
* @parm reason is the reason (SHUTDOWN_xxx) for the shutdown
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int xc_domain_shutdown(int xc_handle,
|
||||
int xc_domain_shutdown(int xc_handle,
|
||||
uint32_t domid,
|
||||
int reason);
|
||||
|
||||
@@ -242,7 +242,7 @@ int xc_vcpu_setaffinity(int xc_handle,
|
||||
* @return the number of domains enumerated or -1 on error
|
||||
*/
|
||||
int xc_domain_getinfo(int xc_handle,
|
||||
uint32_t first_domid,
|
||||
uint32_t first_domid,
|
||||
unsigned int max_doms,
|
||||
xc_dominfo_t *info);
|
||||
|
||||
@@ -307,12 +307,12 @@ long long xc_domain_get_cpu_usage(int xc_handle,
|
||||
domid_t domid,
|
||||
int vcpu);
|
||||
|
||||
int xc_domain_sethandle(int xc_handle, uint32_t domid,
|
||||
int xc_domain_sethandle(int xc_handle, uint32_t domid,
|
||||
xen_domain_handle_t handle);
|
||||
|
||||
typedef dom0_shadow_control_stats_t xc_shadow_control_stats_t;
|
||||
int xc_shadow_control(int xc_handle,
|
||||
uint32_t domid,
|
||||
uint32_t domid,
|
||||
unsigned int sop,
|
||||
unsigned long *dirty_bitmap,
|
||||
unsigned long pages,
|
||||
@@ -386,7 +386,7 @@ int xc_physdev_pci_access_modify(int xc_handle,
|
||||
|
||||
int xc_readconsolering(int xc_handle,
|
||||
char **pbuffer,
|
||||
unsigned int *pnr_chars,
|
||||
unsigned int *pnr_chars,
|
||||
int clear);
|
||||
|
||||
typedef dom0_physinfo_t xc_physinfo_t;
|
||||
@@ -397,18 +397,18 @@ int xc_sched_id(int xc_handle,
|
||||
int *sched_id);
|
||||
|
||||
int xc_domain_setmaxmem(int xc_handle,
|
||||
uint32_t domid,
|
||||
uint32_t domid,
|
||||
unsigned int max_memkb);
|
||||
|
||||
int xc_domain_memory_increase_reservation(int xc_handle,
|
||||
uint32_t domid,
|
||||
uint32_t domid,
|
||||
unsigned long nr_extents,
|
||||
unsigned int extent_order,
|
||||
unsigned int address_bits,
|
||||
unsigned long *extent_start);
|
||||
|
||||
int xc_domain_memory_decrease_reservation(int xc_handle,
|
||||
uint32_t domid,
|
||||
uint32_t domid,
|
||||
unsigned long nr_extents,
|
||||
unsigned int extent_order,
|
||||
unsigned long *extent_start);
|
||||
@@ -443,7 +443,7 @@ int xc_domain_iomem_permission(int xc_handle,
|
||||
unsigned long nr_mfns,
|
||||
uint8_t allow_access);
|
||||
|
||||
unsigned long xc_make_page_below_4G(int xc_handle, uint32_t domid,
|
||||
unsigned long xc_make_page_below_4G(int xc_handle, uint32_t domid,
|
||||
unsigned long mfn);
|
||||
|
||||
typedef dom0_perfc_desc_t xc_perfc_desc_t;
|
||||
@@ -492,11 +492,11 @@ void *xc_map_foreign_batch(int xc_handle, uint32_t dom, int prot,
|
||||
unsigned long xc_translate_foreign_address(int xc_handle, uint32_t dom,
|
||||
int vcpu, unsigned long long virt);
|
||||
|
||||
int xc_get_pfn_list(int xc_handle, uint32_t domid, unsigned long *pfn_buf,
|
||||
int xc_get_pfn_list(int xc_handle, uint32_t domid, unsigned long *pfn_buf,
|
||||
unsigned long max_pfns);
|
||||
|
||||
int xc_ia64_get_pfn_list(int xc_handle, uint32_t domid,
|
||||
unsigned long *pfn_buf,
|
||||
unsigned long *pfn_buf,
|
||||
unsigned int start_page, unsigned int nr_pages);
|
||||
|
||||
int xc_copy_to_domain_page(int xc_handle, uint32_t domid,
|
||||
@@ -551,7 +551,7 @@ int xc_tbuf_enable(int xc_handle, int enable);
|
||||
int xc_tbuf_set_size(int xc_handle, uint32_t size);
|
||||
|
||||
/**
|
||||
* This function retrieves the current size of the trace buffers.
|
||||
* This function retrieves the current size of the trace buffers.
|
||||
* Note that the size returned is in terms of bytes, not pages.
|
||||
|
||||
* @parm xc_handle a handle to an open hypervisor interface
|
||||
@@ -577,7 +577,7 @@ struct xc_mmu {
|
||||
};
|
||||
typedef struct xc_mmu xc_mmu_t;
|
||||
xc_mmu_t *xc_init_mmu_updates(int xc_handle, domid_t dom);
|
||||
int xc_add_mmu_update(int xc_handle, xc_mmu_t *mmu,
|
||||
int xc_add_mmu_update(int xc_handle, xc_mmu_t *mmu,
|
||||
unsigned long long ptr, unsigned long long val);
|
||||
int xc_finish_mmu_updates(int xc_handle, xc_mmu_t *mmu);
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/******************************************************************************
|
||||
* xenguest.h
|
||||
*
|
||||
*
|
||||
* A library for guest domain management in Xen.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2003-2004, K A Fraser.
|
||||
*/
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
* @parm dom the id of the domain
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */,
|
||||
int (*suspend)(int domid));
|
||||
|
||||
@@ -37,8 +37,8 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
* @parm store_mfn returned with the mfn of the store page
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int xc_linux_restore(int xc_handle, int io_fd, uint32_t dom,
|
||||
unsigned long nr_pfns, unsigned int store_evtchn,
|
||||
int xc_linux_restore(int xc_handle, int io_fd, uint32_t dom,
|
||||
unsigned long nr_pfns, unsigned int store_evtchn,
|
||||
unsigned long *store_mfn, unsigned int console_evtchn,
|
||||
unsigned long *console_mfn);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
* xg_private.c
|
||||
*
|
||||
*
|
||||
* Helper functions for the rest of the library.
|
||||
*/
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "xenctrl.h"
|
||||
#include "xenguest.h"
|
||||
#include "xenguest.h"
|
||||
|
||||
#include <xen/linux/privcmd.h>
|
||||
#include <xen/memory.h>
|
||||
@@ -62,7 +62,7 @@ unsigned long csum_page (void * page);
|
||||
#define L2_PAGETABLE_ENTRIES_PAE 512
|
||||
#define L3_PAGETABLE_ENTRIES_PAE 4
|
||||
|
||||
#if defined(__i386__)
|
||||
#if defined(__i386__)
|
||||
#define L1_PAGETABLE_ENTRIES 1024
|
||||
#define L2_PAGETABLE_ENTRIES 1024
|
||||
#elif defined(__x86_64__)
|
||||
@@ -71,7 +71,7 @@ unsigned long csum_page (void * page);
|
||||
#define L3_PAGETABLE_ENTRIES 512
|
||||
#define L4_PAGETABLE_ENTRIES 512
|
||||
#endif
|
||||
|
||||
|
||||
#define PAGE_SHIFT XC_PAGE_SHIFT
|
||||
#define PAGE_SIZE (1UL << PAGE_SHIFT)
|
||||
#define PAGE_MASK (~(PAGE_SIZE-1))
|
||||
@@ -167,8 +167,8 @@ typedef struct mfn_mapper {
|
||||
int error;
|
||||
int max_queue_size;
|
||||
void * addr;
|
||||
privcmd_mmap_t ioctl;
|
||||
|
||||
privcmd_mmap_t ioctl;
|
||||
|
||||
} mfn_mapper_t;
|
||||
|
||||
int xc_copy_to_domain_page(int xc_handle, uint32_t domid,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
** xg_save_restore.h
|
||||
**
|
||||
** Defintions and utilities for save / restore.
|
||||
**
|
||||
** Defintions and utilities for save / restore.
|
||||
*/
|
||||
|
||||
#include "xc_private.h"
|
||||
@@ -29,8 +29,8 @@ while (0)
|
||||
|
||||
|
||||
/*
|
||||
** We process save/restore/migrate in batches of pages; the below
|
||||
** determines how many pages we (at maximum) deal with in each batch.
|
||||
** We process save/restore/migrate in batches of pages; the below
|
||||
** determines how many pages we (at maximum) deal with in each batch.
|
||||
*/
|
||||
#define MAX_BATCH_SIZE 1024 /* up to 1024 pages (4MB) at a time */
|
||||
|
||||
@@ -40,56 +40,56 @@ while (0)
|
||||
|
||||
|
||||
/*
|
||||
** Determine various platform information required for save/restore, in
|
||||
** particular:
|
||||
** Determine various platform information required for save/restore, in
|
||||
** particular:
|
||||
**
|
||||
** - the maximum MFN on this machine, used to compute the size of
|
||||
** the M2P table;
|
||||
**
|
||||
** - the starting virtual address of the the hypervisor; we use this
|
||||
** to determine which parts of guest address space(s) do and don't
|
||||
** require canonicalization during save/restore; and
|
||||
**
|
||||
** - the number of page-table levels for save/ restore. This should
|
||||
** be a property of the domain, but for the moment we just read it
|
||||
** - the maximum MFN on this machine, used to compute the size of
|
||||
** the M2P table;
|
||||
**
|
||||
** - the starting virtual address of the the hypervisor; we use this
|
||||
** to determine which parts of guest address space(s) do and don't
|
||||
** require canonicalization during save/restore; and
|
||||
**
|
||||
** - the number of page-table levels for save/ restore. This should
|
||||
** be a property of the domain, but for the moment we just read it
|
||||
** from the hypervisor.
|
||||
**
|
||||
** Returns 1 on success, 0 on failure.
|
||||
** Returns 1 on success, 0 on failure.
|
||||
*/
|
||||
static int get_platform_info(int xc_handle, uint32_t dom,
|
||||
/* OUT */ unsigned long *max_mfn,
|
||||
/* OUT */ unsigned long *hvirt_start,
|
||||
static int get_platform_info(int xc_handle, uint32_t dom,
|
||||
/* OUT */ unsigned long *max_mfn,
|
||||
/* OUT */ unsigned long *hvirt_start,
|
||||
/* OUT */ unsigned int *pt_levels)
|
||||
|
||||
{
|
||||
|
||||
{
|
||||
xen_capabilities_info_t xen_caps = "";
|
||||
xen_platform_parameters_t xen_params;
|
||||
|
||||
if (xc_version(xc_handle, XENVER_platform_parameters, &xen_params) != 0)
|
||||
return 0;
|
||||
|
||||
|
||||
if (xc_version(xc_handle, XENVER_capabilities, &xen_caps) != 0)
|
||||
return 0;
|
||||
|
||||
*max_mfn = xc_memory_op(xc_handle, XENMEM_maximum_ram_page, NULL);
|
||||
|
||||
|
||||
*hvirt_start = xen_params.virt_start;
|
||||
|
||||
if (strstr(xen_caps, "xen-3.0-x86_64"))
|
||||
*pt_levels = 4;
|
||||
else if (strstr(xen_caps, "xen-3.0-x86_32p"))
|
||||
*pt_levels = 3;
|
||||
*pt_levels = 3;
|
||||
else if (strstr(xen_caps, "xen-3.0-x86_32"))
|
||||
*pt_levels = 2;
|
||||
else
|
||||
return 0;
|
||||
|
||||
*pt_levels = 2;
|
||||
else
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Save/restore deal with the mfn_to_pfn (M2P) and pfn_to_mfn (P2M) tables.
|
||||
/*
|
||||
** Save/restore deal with the mfn_to_pfn (M2P) and pfn_to_mfn (P2M) tables.
|
||||
** The M2P simply holds the corresponding PFN, while the top bit of a P2M
|
||||
** entry tell us whether or not the the PFN is currently mapped.
|
||||
*/
|
||||
@@ -98,18 +98,18 @@ static int get_platform_info(int xc_handle, uint32_t dom,
|
||||
#define ROUNDUP(_x,_w) (((unsigned long)(_x)+(1UL<<(_w))-1) & ~((1UL<<(_w))-1))
|
||||
|
||||
|
||||
/*
|
||||
** The M2P is made up of some number of 'chunks' of at least 2MB in size.
|
||||
** The below definitions and utility function(s) deal with mapping the M2P
|
||||
** regarldess of the underlying machine memory size or architecture.
|
||||
/*
|
||||
** The M2P is made up of some number of 'chunks' of at least 2MB in size.
|
||||
** The below definitions and utility function(s) deal with mapping the M2P
|
||||
** regarldess of the underlying machine memory size or architecture.
|
||||
*/
|
||||
#define M2P_SHIFT L2_PAGETABLE_SHIFT_PAE
|
||||
#define M2P_CHUNK_SIZE (1 << M2P_SHIFT)
|
||||
#define M2P_SIZE(_m) ROUNDUP(((_m) * sizeof(unsigned long)), M2P_SHIFT)
|
||||
#define M2P_SHIFT L2_PAGETABLE_SHIFT_PAE
|
||||
#define M2P_CHUNK_SIZE (1 << M2P_SHIFT)
|
||||
#define M2P_SIZE(_m) ROUNDUP(((_m) * sizeof(unsigned long)), M2P_SHIFT)
|
||||
#define M2P_CHUNKS(_m) (M2P_SIZE((_m)) >> M2P_SHIFT)
|
||||
|
||||
/* Size in bytes of the P2M (rounded up to the nearest PAGE_SIZE bytes) */
|
||||
#define P2M_SIZE ROUNDUP((max_pfn * sizeof(unsigned long)), PAGE_SHIFT)
|
||||
#define P2M_SIZE ROUNDUP((max_pfn * sizeof(unsigned long)), PAGE_SHIFT)
|
||||
|
||||
/* Number of unsigned longs in a page */
|
||||
#define ulpp (PAGE_SIZE/sizeof(unsigned long))
|
||||
@@ -127,12 +127,12 @@ static int get_platform_info(int xc_handle, uint32_t dom,
|
||||
#define NR_SLACK_ENTRIES ((8 * 1024 * 1024) / PAGE_SIZE)
|
||||
|
||||
/* Is the given PFN within the 'slack' region at the top of the P2M? */
|
||||
#define IS_REAL_PFN(_pfn) ((max_pfn - (_pfn)) > NR_SLACK_ENTRIES)
|
||||
#define IS_REAL_PFN(_pfn) ((max_pfn - (_pfn)) > NR_SLACK_ENTRIES)
|
||||
|
||||
/* Returns TRUE if the PFN is currently mapped */
|
||||
#define is_mapped(pfn_type) (!((pfn_type) & 0x80000000UL))
|
||||
|
||||
#define INVALID_P2M_ENTRY (~0UL)
|
||||
#define INVALID_P2M_ENTRY (~0UL)
|
||||
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ else
|
||||
|
||||
# Turn linux into xenolinux then build it
|
||||
cd xenolinux-${LINUX_VER}-sparse
|
||||
./mkbuildtree ../../linux-${LINUX_VER}
|
||||
bash ./mkbuildtree ../../linux-${LINUX_VER}
|
||||
cd ../..
|
||||
mv linux-${LINUX_VER} xenolinux-${LINUX_VER}
|
||||
cd xenolinux-${LINUX_VER}
|
||||
|
||||
@@ -589,7 +589,7 @@ static PyObject *xspy_transaction_end(XsHandle *self, PyObject *args,
|
||||
|
||||
static PyObject *xspy_introduce_domain(XsHandle *self, PyObject *args)
|
||||
{
|
||||
domid_t dom;
|
||||
uint32_t dom;
|
||||
unsigned long page;
|
||||
unsigned int port;
|
||||
|
||||
@@ -620,7 +620,7 @@ static PyObject *xspy_introduce_domain(XsHandle *self, PyObject *args)
|
||||
|
||||
static PyObject *xspy_release_domain(XsHandle *self, PyObject *args)
|
||||
{
|
||||
domid_t dom;
|
||||
uint32_t dom;
|
||||
|
||||
struct xs_handle *xh = xshandle(self);
|
||||
bool result = 0;
|
||||
@@ -677,7 +677,7 @@ static PyObject *xspy_close(XsHandle *self)
|
||||
static PyObject *xspy_get_domain_path(XsHandle *self, PyObject *args)
|
||||
{
|
||||
struct xs_handle *xh = xshandle(self);
|
||||
int domid;
|
||||
uint32_t domid;
|
||||
char *xsval;
|
||||
|
||||
if (!xh)
|
||||
|
||||
@@ -53,7 +53,7 @@ def read_exact(fd, size, errmsg):
|
||||
|
||||
|
||||
|
||||
def save(fd, dominfo, live):
|
||||
def save(fd, dominfo, live, dst):
|
||||
write_exact(fd, SIGNATURE, "could not write guest state file: signature")
|
||||
|
||||
config = sxp.to_string(dominfo.sxpr())
|
||||
@@ -65,6 +65,8 @@ def save(fd, dominfo, live):
|
||||
dominfo.setName('migrating-' + domain_name)
|
||||
|
||||
try:
|
||||
dominfo.migrateDevices(live, dst, 1, domain_name)
|
||||
|
||||
write_exact(fd, pack("!i", len(config)),
|
||||
"could not write guest state file: config len")
|
||||
write_exact(fd, config, "could not write guest state file: config")
|
||||
@@ -85,7 +87,9 @@ def save(fd, dominfo, live):
|
||||
log.debug("Suspending %d ...", dominfo.getDomid())
|
||||
dominfo.shutdown('suspend')
|
||||
dominfo.waitForShutdown()
|
||||
dominfo.migrateDevices(live, dst, 2, domain_name)
|
||||
log.info("Domain %d suspended.", dominfo.getDomid())
|
||||
dominfo.migrateDevices(live, dst, 3, domain_name)
|
||||
tochild.write("done\n")
|
||||
tochild.flush()
|
||||
log.debug('Written done')
|
||||
|
||||
@@ -405,6 +405,9 @@ class XendDomain:
|
||||
if dominfo.getDomid() == PRIV_DOMAIN:
|
||||
raise XendError("Cannot migrate privileged domain %i" % domid)
|
||||
|
||||
""" The following call may raise a XendError exception """
|
||||
dominfo.testMigrateDevices(live, dst)
|
||||
|
||||
if port == 0:
|
||||
port = xroot.get_xend_relocation_port()
|
||||
try:
|
||||
@@ -414,8 +417,8 @@ class XendDomain:
|
||||
raise XendError("can't connect: %s" % err[1])
|
||||
|
||||
sock.send("receive\n")
|
||||
sock.recv(80)
|
||||
XendCheckpoint.save(sock.fileno(), dominfo, live)
|
||||
sock.recv(80)
|
||||
XendCheckpoint.save(sock.fileno(), dominfo, live, dst)
|
||||
|
||||
|
||||
def domain_save(self, domid, dst):
|
||||
@@ -435,7 +438,7 @@ class XendDomain:
|
||||
fd = os.open(dst, os.O_WRONLY | os.O_CREAT | os.O_TRUNC)
|
||||
try:
|
||||
# For now we don't support 'live checkpoint'
|
||||
return XendCheckpoint.save(fd, dominfo, False)
|
||||
return XendCheckpoint.save(fd, dominfo, False, dst)
|
||||
finally:
|
||||
os.close(fd)
|
||||
except OSError, ex:
|
||||
|
||||
@@ -1395,6 +1395,38 @@ class XendDomainInfo:
|
||||
if self.image:
|
||||
self.image.createDeviceModel()
|
||||
|
||||
## public:
|
||||
|
||||
def testMigrateDevices(self, live, dst):
|
||||
""" Notify all device about intention of migration
|
||||
@raise: XendError for a device that cannot be migrated
|
||||
"""
|
||||
for (n, c) in self.info['device']:
|
||||
rc = self.migrateDevice(n, c, live, dst, 0)
|
||||
if rc != 0:
|
||||
raise XendError("Device of type '%s' refuses migration." % n)
|
||||
|
||||
def migrateDevices(self, live, dst, step, domName=''):
|
||||
"""Notify the devices about migration
|
||||
"""
|
||||
ctr = 0
|
||||
try:
|
||||
for (n, c) in self.info['device']:
|
||||
self.migrateDevice(n, c, live, dst, step, domName)
|
||||
ctr = ctr + 1
|
||||
except:
|
||||
for (n, c) in self.info['device']:
|
||||
if ctr == 0:
|
||||
step = step - 1
|
||||
ctr = ctr - 1
|
||||
self.recoverMigrateDevice(n, c, live, dst, step, domName)
|
||||
raise
|
||||
|
||||
def migrateDevice(self, deviceClass, deviceConfig, live, dst, step, domName=''):
|
||||
return self.getDeviceController(deviceClass).migrate(deviceConfig, live, dst, step, domName)
|
||||
|
||||
def recoverMigrateDevice(self, deviceClass, deviceConfig, live, dst, step, domName=''):
|
||||
return self.getDeviceController(deviceClass).recover_migrate(deviceConfig, live, dst, step, domName)
|
||||
|
||||
def waitForDevices(self):
|
||||
"""Wait for this domain's configured devices to connect.
|
||||
|
||||
@@ -86,6 +86,9 @@ class XendRoot:
|
||||
server (deprecated)."""
|
||||
xend_unix_server_default = 'no'
|
||||
|
||||
"""Default external migration tool """
|
||||
external_migration_tool_default = ''
|
||||
|
||||
"""Default path the unix-domain server listens at."""
|
||||
xend_unix_path_default = '/var/lib/xend/xend-socket'
|
||||
|
||||
@@ -250,6 +253,9 @@ class XendRoot:
|
||||
else:
|
||||
return None
|
||||
|
||||
def get_external_migration_tool(self):
|
||||
"""@return the name of the tool to handle virtual TPM migration."""
|
||||
return self.get_config_value('external-migration-tool', self.external_migration_tool_default)
|
||||
|
||||
def get_enable_dump(self):
|
||||
return self.get_config_bool('enable-dump', 'no')
|
||||
|
||||
@@ -267,6 +267,41 @@ class DevController:
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
def migrate(self, deviceConfig, live, dst, step, domName):
|
||||
""" Migration of a device. The 'live' parameter indicates
|
||||
whether the device is live-migrated (live=1). 'dst' then gives
|
||||
the hostname of the machine to migrate to.
|
||||
This function is called for 4 steps:
|
||||
If step == 0: Check whether the device is ready to be migrated
|
||||
or can at all be migrated; return a '-1' if
|
||||
the device is NOT ready, a '0' otherwise. If it is
|
||||
not ready ( = not possible to migrate this device),
|
||||
migration will not take place.
|
||||
step == 1: Called immediately after step 0; migration
|
||||
of the kernel has started;
|
||||
step == 2: Called after the suspend has been issued
|
||||
to the domain and the domain is not scheduled anymore.
|
||||
Synchronize with what was started in step 1, if necessary.
|
||||
Now the device should initiate its transfer to the
|
||||
given target. Since there might be more than just
|
||||
one device initiating a migration, this step should
|
||||
put the process performing the transfer into the
|
||||
background and return immediately to achieve as much
|
||||
concurrency as possible.
|
||||
step == 3: Synchronize with the migration of the device that
|
||||
was initiated in step 2.
|
||||
Make sure that the migration has finished and only
|
||||
then return from the call.
|
||||
"""
|
||||
return 0
|
||||
|
||||
|
||||
def recover_migrate(self, deviceConfig, list, dst, step, domName):
|
||||
""" Recover from device migration. The given step was the
|
||||
last one that was successfully executed.
|
||||
"""
|
||||
return 0
|
||||
|
||||
|
||||
def getDomid(self):
|
||||
"""Stub to {@link XendDomainInfo.getDomid}, for use by our
|
||||
|
||||
@@ -23,9 +23,17 @@
|
||||
|
||||
from xen.xend import sxp
|
||||
from xen.xend.XendLogging import log
|
||||
from xen.xend.XendError import XendError
|
||||
from xen.xend import XendRoot
|
||||
|
||||
from xen.xend.server.DevController import DevController
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
|
||||
xroot = XendRoot.instance()
|
||||
|
||||
|
||||
class TPMifController(DevController):
|
||||
"""TPM interface controller. Handles all TPM devices for a domain.
|
||||
@@ -61,3 +69,43 @@ class TPMifController(DevController):
|
||||
result.append(['instance', instance])
|
||||
|
||||
return result
|
||||
|
||||
def migrate(self, deviceConfig, live, dst, step, domName):
|
||||
"""@see DevContoller.migrate"""
|
||||
if live:
|
||||
tool = xroot.get_external_migration_tool()
|
||||
if tool != '':
|
||||
log.info("Request to live-migrate device to %s. step=%d.",
|
||||
dst, step)
|
||||
|
||||
if step == 0:
|
||||
"""Assuming for now that everything is ok and migration
|
||||
with the given tool can proceed.
|
||||
"""
|
||||
return 0
|
||||
else:
|
||||
fd = os.popen("%s -type vtpm -step %d -host %s -domname %s" %
|
||||
(tool, step, dst, domName),
|
||||
'r')
|
||||
for line in fd.readlines():
|
||||
mo = re.search('Error', line)
|
||||
if mo:
|
||||
raise XendError("vtpm: Fatal error in migration step %d." %
|
||||
step)
|
||||
return 0
|
||||
else:
|
||||
log.debug("External migration tool not in configuration.")
|
||||
return -1
|
||||
return 0
|
||||
|
||||
def recover_migrate(self, deviceConfig, live, dst, step, domName):
|
||||
"""@see DevContoller.recover_migrate"""
|
||||
if live:
|
||||
tool = xroot.get_external_migration_tool()
|
||||
if tool != '':
|
||||
log.info("Request to recover live-migrated device. last good step=%d.",
|
||||
step)
|
||||
fd = os.popen("%s -type vtpm -step %d -host %s -domname %s -recover" %
|
||||
(tool, step, dst, domName),
|
||||
'r')
|
||||
return 0
|
||||
@@ -158,7 +158,7 @@ gopts.var('cpu', val='CPU',
|
||||
use="CPU to run the VCPU0 on.")
|
||||
|
||||
gopts.var('cpus', val='CPUS',
|
||||
fn=set_int, default=None,
|
||||
fn=set_value, default=None,
|
||||
use="CPUS to run the domain on.")
|
||||
|
||||
gopts.var('pae', val='PAE',
|
||||
|
||||
@@ -84,6 +84,16 @@ Usage Notes and issues
|
||||
events cause a trace record to be emitted.
|
||||
- To exit xenmon, type 'q'
|
||||
- To cycle the display to other physical cpu's, type 'c'
|
||||
- The first time xenmon is run, it attempts to allocate xen trace buffers
|
||||
using a default size. If you wish to use a non-default value for the
|
||||
trace buffer size, run the 'setsize' program (located in tools/xentrace)
|
||||
and specify the number of memory pages as a parameter. The default is 20.
|
||||
- Not well tested with domains using more than 1 virtual cpu
|
||||
- If you create a lot of domains, or repeatedly kill a domain and restart it,
|
||||
and the domain id's get to be bigger than NDOMAINS, then xenmon behaves badly.
|
||||
This is a bug that is due to xenbaked's treatment of domain id's vs. domain
|
||||
indices in a data array. Will be fixed in a future release; Workaround:
|
||||
Increase NDOMAINS in xenbaked and rebuild.
|
||||
|
||||
Future Work
|
||||
-----------
|
||||
|
||||
+142
-11
@@ -7,6 +7,7 @@
|
||||
*
|
||||
* Copyright (C) 2004 by Intel Research Cambridge
|
||||
* Copyright (C) 2005 by Hewlett Packard, Palo Alto and Fort Collins
|
||||
* Copyright (C) 2006 by Hewlett Packard Fort Collins
|
||||
*
|
||||
* Authors: Diwaker Gupta, diwaker.gupta@hp.com
|
||||
* Rob Gardner, rob.gardner@hp.com
|
||||
@@ -42,6 +43,8 @@
|
||||
#include <xenctrl.h>
|
||||
#include <xen/xen.h>
|
||||
#include <string.h>
|
||||
#include <sys/select.h>
|
||||
#include <xen/linux/evtchn.h>
|
||||
|
||||
#include "xc_private.h"
|
||||
typedef struct { int counter; } atomic_t;
|
||||
@@ -81,6 +84,7 @@ settings_t opts;
|
||||
|
||||
int interrupted = 0; /* gets set if we get a SIGHUP */
|
||||
int rec_count = 0;
|
||||
int wakeups = 0;
|
||||
time_t start_time;
|
||||
int dom0_flips = 0;
|
||||
|
||||
@@ -88,8 +92,6 @@ _new_qos_data *new_qos;
|
||||
_new_qos_data **cpu_qos_data;
|
||||
|
||||
|
||||
#define ID(X) ((X>NDOMAINS-1)?(NDOMAINS-1):X)
|
||||
|
||||
// array of currently running domains, indexed by cpu
|
||||
int *running = NULL;
|
||||
|
||||
@@ -223,6 +225,9 @@ void dump_stats(void)
|
||||
printf("processed %d total records in %d seconds (%ld per second)\n",
|
||||
rec_count, (int)run_time, rec_count/run_time);
|
||||
|
||||
printf("woke up %d times in %d seconds (%ld per second)\n", wakeups,
|
||||
(int) run_time, wakeups/run_time);
|
||||
|
||||
check_gotten_sum();
|
||||
}
|
||||
|
||||
@@ -243,6 +248,112 @@ void log_event(int event_id)
|
||||
stat_map[0].event_count++; // other
|
||||
}
|
||||
|
||||
#define EVTCHN_DEV_NAME "/dev/xen/evtchn"
|
||||
#define EVTCHN_DEV_MAJOR 10
|
||||
#define EVTCHN_DEV_MINOR 201
|
||||
|
||||
int virq_port;
|
||||
int eventchn_fd = -1;
|
||||
|
||||
/* Returns the event channel handle. */
|
||||
/* Stolen from xenstore code */
|
||||
int eventchn_init(void)
|
||||
{
|
||||
struct stat st;
|
||||
struct ioctl_evtchn_bind_virq bind;
|
||||
int rc;
|
||||
|
||||
// to revert to old way:
|
||||
if (0)
|
||||
return -1;
|
||||
|
||||
/* Make sure any existing device file links to correct device. */
|
||||
if ((lstat(EVTCHN_DEV_NAME, &st) != 0) || !S_ISCHR(st.st_mode) ||
|
||||
(st.st_rdev != makedev(EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR)))
|
||||
(void)unlink(EVTCHN_DEV_NAME);
|
||||
|
||||
reopen:
|
||||
eventchn_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR);
|
||||
if (eventchn_fd == -1) {
|
||||
if ((errno == ENOENT) &&
|
||||
((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) &&
|
||||
(mknod(EVTCHN_DEV_NAME, S_IFCHR|0600,
|
||||
makedev(EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR)) == 0))
|
||||
goto reopen;
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (eventchn_fd < 0)
|
||||
perror("Failed to open evtchn device");
|
||||
|
||||
bind.virq = VIRQ_TBUF;
|
||||
rc = ioctl(eventchn_fd, IOCTL_EVTCHN_BIND_VIRQ, &bind);
|
||||
if (rc == -1)
|
||||
perror("Failed to bind to domain exception virq port");
|
||||
virq_port = rc;
|
||||
|
||||
return eventchn_fd;
|
||||
}
|
||||
|
||||
void wait_for_event(void)
|
||||
{
|
||||
int ret;
|
||||
fd_set inset;
|
||||
evtchn_port_t port;
|
||||
struct timeval tv;
|
||||
|
||||
if (eventchn_fd < 0) {
|
||||
nanosleep(&opts.poll_sleep, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
FD_ZERO(&inset);
|
||||
FD_SET(eventchn_fd, &inset);
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
// tv = millis_to_timespec(&opts.poll_sleep);
|
||||
ret = select(eventchn_fd+1, &inset, NULL, NULL, &tv);
|
||||
|
||||
if ( (ret == 1) && FD_ISSET(eventchn_fd, &inset)) {
|
||||
if (read(eventchn_fd, &port, sizeof(port)) != sizeof(port))
|
||||
perror("Failed to read from event fd");
|
||||
|
||||
// if (port == virq_port)
|
||||
// printf("got the event I was looking for\r\n");
|
||||
|
||||
if (write(eventchn_fd, &port, sizeof(port)) != sizeof(port))
|
||||
perror("Failed to write to event fd");
|
||||
}
|
||||
}
|
||||
|
||||
void enable_tracing_or_die(int xc_handle)
|
||||
{
|
||||
int enable = 1;
|
||||
int tbsize = DEFAULT_TBUF_SIZE;
|
||||
|
||||
if (xc_tbuf_enable(xc_handle, enable) != 0) {
|
||||
if (xc_tbuf_set_size(xc_handle, tbsize) != 0) {
|
||||
perror("set_size Hypercall failure");
|
||||
exit(1);
|
||||
}
|
||||
printf("Set default trace buffer allocation (%d pages)\n", tbsize);
|
||||
if (xc_tbuf_enable(xc_handle, enable) != 0) {
|
||||
perror("Could not enable trace buffers\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
printf("Tracing enabled\n");
|
||||
}
|
||||
|
||||
void disable_tracing(void)
|
||||
{
|
||||
int enable = 0;
|
||||
int xc_handle = xc_interface_open();
|
||||
|
||||
xc_tbuf_enable(xc_handle, enable);
|
||||
xc_interface_close(xc_handle);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@@ -258,6 +369,17 @@ void get_tbufs(unsigned long *mfn, unsigned long *size)
|
||||
int ret;
|
||||
dom0_op_t op; /* dom0 op we'll build */
|
||||
int xc_handle = xc_interface_open(); /* for accessing control interface */
|
||||
unsigned int tbsize;
|
||||
|
||||
enable_tracing_or_die(xc_handle);
|
||||
|
||||
if (xc_tbuf_get_size(xc_handle, &tbsize) != 0) {
|
||||
perror("Failure to get tbuf info from Xen. Guess size is 0?");
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
printf("Current tbuf size: 0x%x\n", tbsize);
|
||||
|
||||
|
||||
op.cmd = DOM0_TBUFCONTROL;
|
||||
op.interface_version = DOM0_INTERFACE_VERSION;
|
||||
@@ -448,6 +570,11 @@ int monitor_tbufs(void)
|
||||
meta = init_bufs_ptrs (tbufs_mapped, num, size);
|
||||
data = init_rec_ptrs(meta, num);
|
||||
|
||||
// Set up event channel for select()
|
||||
if (eventchn_init() < 0) {
|
||||
fprintf(stderr, "Failed to initialize event channel; Using POLL method\r\n");
|
||||
}
|
||||
|
||||
/* now, scan buffers for events */
|
||||
while ( !interrupted )
|
||||
{
|
||||
@@ -460,7 +587,8 @@ int monitor_tbufs(void)
|
||||
meta[i]->cons++;
|
||||
}
|
||||
|
||||
nanosleep(&opts.poll_sleep, NULL);
|
||||
wait_for_event();
|
||||
wakeups++;
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
@@ -640,6 +768,7 @@ int main(int argc, char **argv)
|
||||
|
||||
dump_stats();
|
||||
msync(new_qos, sizeof(_new_qos_data), MS_SYNC);
|
||||
disable_tracing();
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -737,7 +866,9 @@ void qos_update_thread(int cpu, int domid, uint64_t now)
|
||||
start = new_qos->domain_info[id].start_time;
|
||||
if (start > now) { // wrapped around
|
||||
run_time = now + (~0ULL - start);
|
||||
printf("warning: start > now\n");
|
||||
// this could happen if there is nothing going on within a cpu;
|
||||
// in this case the idle domain would run forever
|
||||
// printf("warning: start > now\n");
|
||||
}
|
||||
else
|
||||
run_time = now - start;
|
||||
@@ -746,11 +877,11 @@ void qos_update_thread(int cpu, int domid, uint64_t now)
|
||||
new_qos->domain_info[id].ns_oncpu_since_boot += run_time;
|
||||
new_qos->domain_info[id].start_time = now;
|
||||
new_qos->domain_info[id].ns_since_boot += time_since_update;
|
||||
#if 1
|
||||
|
||||
new_qos->qdata[n].ns_gotten[id] += run_time;
|
||||
if (domid == 0 && cpu == 1)
|
||||
printf("adding run time for dom0 on cpu1\r\n");
|
||||
#endif
|
||||
// if (domid == 0 && cpu == 1)
|
||||
// printf("adding run time for dom0 on cpu1\r\n");
|
||||
|
||||
}
|
||||
|
||||
new_qos->domain_info[id].runnable_at_last_update = domain_runnable(domid);
|
||||
@@ -916,13 +1047,13 @@ void qos_state_runnable(int cpu, int domid, uint64_t now)
|
||||
{
|
||||
int id = ID(domid);
|
||||
|
||||
qos_update_thread_stats(cpu, domid, now);
|
||||
|
||||
if (domain_runnable(id)) // double call?
|
||||
return;
|
||||
new_qos->domain_info[id].runnable = 1;
|
||||
update_blocked_time(domid, now);
|
||||
|
||||
qos_update_thread_stats(cpu, domid, now);
|
||||
|
||||
new_qos->domain_info[id].blocked_start_time = 0; /* invalidate */
|
||||
new_qos->domain_info[id].runnable_start_time = now;
|
||||
// runnable_start_time[id] = now;
|
||||
@@ -951,7 +1082,7 @@ int domain_ok(int cpu, int domid, uint64_t now)
|
||||
if (domid == IDLE_DOMAIN_ID)
|
||||
domid = NDOMAINS-1;
|
||||
if (domid < 0 || domid >= NDOMAINS) {
|
||||
printf("bad domain id: %d\n", domid);
|
||||
printf("bad domain id: %d\r\n", domid);
|
||||
return 0;
|
||||
}
|
||||
if (new_qos->domain_info[domid].in_use == 0)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/******************************************************************************
|
||||
* tools/xenbaked.h
|
||||
* TOOLS/xenbaked.h
|
||||
*
|
||||
* Header file for xenbaked
|
||||
*
|
||||
@@ -30,6 +30,7 @@
|
||||
#define million 1000000LL
|
||||
#define billion 1000000000LL
|
||||
|
||||
// caution: don't use QOS_ADD with negative numbers!
|
||||
#define QOS_ADD(N,A) ((N+A)<(NSAMPLES-1) ? (N+A) : A)
|
||||
#define QOS_INCR(N) ((N<(NSAMPLES-2)) ? (N+1) : 0)
|
||||
#define QOS_DECR(N) ((N==0) ? (NSAMPLES-1) : (N-1))
|
||||
@@ -43,6 +44,8 @@
|
||||
/* Number of data points to keep */
|
||||
#define NSAMPLES 100
|
||||
|
||||
#define ID(X) ((X>NDOMAINS-1)?(NDOMAINS-1):X)
|
||||
#define DEFAULT_TBUF_SIZE 20
|
||||
|
||||
// per domain stuff
|
||||
typedef struct
|
||||
|
||||
+128
-80
@@ -5,7 +5,7 @@
|
||||
# There is a curses interface for live monitoring. XenMon also allows
|
||||
# logging to a file. For options, run python xenmon.py -h
|
||||
#
|
||||
# Copyright (C) 2005 by Hewlett Packard, Palo Alto and Fort Collins
|
||||
# Copyright (C) 2005,2006 by Hewlett Packard, Palo Alto and Fort Collins
|
||||
# Authors: Lucy Cherkasova, lucy.cherkasova@hp.com
|
||||
# Rob Gardner, rob.gardner@hp.com
|
||||
# Diwaker Gupta, diwaker.gupta@hp.com
|
||||
@@ -85,6 +85,33 @@ def setup_cmdline_parser():
|
||||
parser.add_option("--ms_per_sample", dest="mspersample",
|
||||
action="store", type="int", default=100,
|
||||
help = "determines how many ms worth of data goes in a sample")
|
||||
parser.add_option("--cpu", dest="cpu", action="store", type="int", default=0,
|
||||
help = "specifies which cpu to display data for")
|
||||
|
||||
parser.add_option("--allocated", dest="allocated", action="store_true",
|
||||
default=False, help="Display allocated time for each domain")
|
||||
parser.add_option("--noallocated", dest="allocated", action="store_false",
|
||||
default=False, help="Don't display allocated time for each domain")
|
||||
|
||||
parser.add_option("--blocked", dest="blocked", action="store_true",
|
||||
default=True, help="Display blocked time for each domain")
|
||||
parser.add_option("--noblocked", dest="blocked", action="store_false",
|
||||
default=True, help="Don't display blocked time for each domain")
|
||||
|
||||
parser.add_option("--waited", dest="waited", action="store_true",
|
||||
default=True, help="Display waiting time for each domain")
|
||||
parser.add_option("--nowaited", dest="waited", action="store_false",
|
||||
default=True, help="Don't display waiting time for each domain")
|
||||
|
||||
parser.add_option("--excount", dest="excount", action="store_true",
|
||||
default=False, help="Display execution count for each domain")
|
||||
parser.add_option("--noexcount", dest="excount", action="store_false",
|
||||
default=False, help="Don't display execution count for each domain")
|
||||
parser.add_option("--iocount", dest="iocount", action="store_true",
|
||||
default=False, help="Display I/O count for each domain")
|
||||
parser.add_option("--noiocount", dest="iocount", action="store_false",
|
||||
default=False, help="Don't display I/O count for each domain")
|
||||
|
||||
return parser
|
||||
|
||||
# encapsulate information about a domain
|
||||
@@ -227,20 +254,18 @@ def display(scr, row, col, str, attr=0):
|
||||
|
||||
|
||||
# the live monitoring code
|
||||
def show_livestats():
|
||||
cpu = 0 # cpu of interest to display data for
|
||||
def show_livestats(cpu):
|
||||
ncpu = 1 # number of cpu's on this platform
|
||||
slen = 0 # size of shared data structure, incuding padding
|
||||
global dom_in_use
|
||||
cpu_1sec_usage = 0.0
|
||||
cpu_10sec_usage = 0.0
|
||||
heartbeat = 1
|
||||
global dom_in_use, options
|
||||
|
||||
# mmap the (the first chunk of the) file
|
||||
shmf = open(SHM_FILE, "r+")
|
||||
shm = mmap.mmap(shmf.fileno(), QOS_DATA_SIZE)
|
||||
|
||||
samples = []
|
||||
doms = []
|
||||
dom_in_use = []
|
||||
|
||||
# initialize curses
|
||||
stdscr = _c.initscr()
|
||||
_c.noecho()
|
||||
@@ -253,7 +278,8 @@ def show_livestats():
|
||||
# display in a loop
|
||||
while True:
|
||||
|
||||
for cpuidx in range(0, ncpu):
|
||||
cpuidx = 0
|
||||
while cpuidx < ncpu:
|
||||
|
||||
# calculate offset in mmap file to start from
|
||||
idx = cpuidx * slen
|
||||
@@ -261,6 +287,7 @@ def show_livestats():
|
||||
|
||||
samples = []
|
||||
doms = []
|
||||
dom_in_use = []
|
||||
|
||||
# read in data
|
||||
for i in range(0, NSAMPLES):
|
||||
@@ -279,6 +306,8 @@ def show_livestats():
|
||||
# dom_in_use.append(in_use)
|
||||
dom_in_use.append(dom[8])
|
||||
idx += len
|
||||
# print "dom_in_use(cpu=%d): " % cpuidx, dom_in_use
|
||||
|
||||
|
||||
len = struct.calcsize("4i")
|
||||
oldncpu = ncpu
|
||||
@@ -295,6 +324,8 @@ def show_livestats():
|
||||
if cpuidx == cpu:
|
||||
break
|
||||
|
||||
cpuidx = cpuidx + 1
|
||||
|
||||
# calculate starting and ending datapoints; never look at "next" since
|
||||
# it represents live data that may be in transition.
|
||||
startat = next - 1
|
||||
@@ -312,13 +343,16 @@ def show_livestats():
|
||||
row = 0
|
||||
display(stdscr, row, 1, "CPU = %d" % cpu, _c.A_STANDOUT)
|
||||
|
||||
display(stdscr, row, 10, "%sLast 10 seconds%sLast 1 second" % (6*' ', 30*' '), _c.A_BOLD)
|
||||
display(stdscr, row, 10, "%sLast 10 seconds (%3.2f%%)%sLast 1 second (%3.2f%%)" % (6*' ', cpu_10sec_usage, 30*' ', cpu_1sec_usage), _c.A_BOLD)
|
||||
row +=1
|
||||
display(stdscr, row, 1, "%s" % ((maxx-2)*'='))
|
||||
|
||||
total_h1_cpu = 0
|
||||
total_h2_cpu = 0
|
||||
|
||||
cpu_1sec_usage = 0.0
|
||||
cpu_10sec_usage = 0.0
|
||||
|
||||
for dom in range(0, NDOMAINS):
|
||||
if not dom_in_use[dom]:
|
||||
continue
|
||||
@@ -332,92 +366,102 @@ def show_livestats():
|
||||
display(stdscr, row, col, "%s" % time_scale(h2[dom][0][0]))
|
||||
col += 12
|
||||
display(stdscr, row, col, "%3.2f%%" % h2[dom][0][1])
|
||||
if dom != NDOMAINS - 1:
|
||||
cpu_10sec_usage += h2[dom][0][1]
|
||||
col += 12
|
||||
display(stdscr, row, col, "%s/ex" % time_scale(h2[dom][0][2]))
|
||||
col += 18
|
||||
display(stdscr, row, col, "%s" % time_scale(h1[dom][0][0]))
|
||||
col += 12
|
||||
display(stdscr, row, col, "%3.2f%%" % h1[dom][0][1])
|
||||
display(stdscr, row, col, "%3.2f%%" % h1[dom][0][1], _c.A_STANDOUT)
|
||||
col += 12
|
||||
display(stdscr, row, col, "%s/ex" % time_scale(h1[dom][0][2]))
|
||||
col += 18
|
||||
display(stdscr, row, col, "Gotten")
|
||||
|
||||
if dom != NDOMAINS - 1:
|
||||
cpu_1sec_usage = cpu_1sec_usage + h1[dom][0][1]
|
||||
|
||||
# display allocated
|
||||
row += 1
|
||||
col = 2
|
||||
display(stdscr, row, col, "%d" % dom)
|
||||
col += 28
|
||||
display(stdscr, row, col, "%s/ex" % time_scale(h2[dom][1]))
|
||||
col += 42
|
||||
display(stdscr, row, col, "%s/ex" % time_scale(h1[dom][1]))
|
||||
col += 18
|
||||
display(stdscr, row, col, "Allocated")
|
||||
if options.allocated:
|
||||
row += 1
|
||||
col = 2
|
||||
display(stdscr, row, col, "%d" % dom)
|
||||
col += 28
|
||||
display(stdscr, row, col, "%s/ex" % time_scale(h2[dom][1]))
|
||||
col += 42
|
||||
display(stdscr, row, col, "%s/ex" % time_scale(h1[dom][1]))
|
||||
col += 18
|
||||
display(stdscr, row, col, "Allocated")
|
||||
|
||||
# display blocked
|
||||
row += 1
|
||||
col = 2
|
||||
display(stdscr, row, col, "%d" % dom)
|
||||
col += 4
|
||||
display(stdscr, row, col, "%s" % time_scale(h2[dom][2][0]))
|
||||
col += 12
|
||||
display(stdscr, row, col, "%3.2f%%" % h2[dom][2][1])
|
||||
col += 12
|
||||
display(stdscr, row, col, "%s/io" % time_scale(h2[dom][2][2]))
|
||||
col += 18
|
||||
display(stdscr, row, col, "%s" % time_scale(h1[dom][2][0]))
|
||||
col += 12
|
||||
display(stdscr, row, col, "%3.2f%%" % h1[dom][2][1])
|
||||
col += 12
|
||||
display(stdscr, row, col, "%s/io" % time_scale(h1[dom][2][2]))
|
||||
col += 18
|
||||
display(stdscr, row, col, "Blocked")
|
||||
if options.blocked:
|
||||
row += 1
|
||||
col = 2
|
||||
display(stdscr, row, col, "%d" % dom)
|
||||
col += 4
|
||||
display(stdscr, row, col, "%s" % time_scale(h2[dom][2][0]))
|
||||
col += 12
|
||||
display(stdscr, row, col, "%3.2f%%" % h2[dom][2][1])
|
||||
col += 12
|
||||
display(stdscr, row, col, "%s/io" % time_scale(h2[dom][2][2]))
|
||||
col += 18
|
||||
display(stdscr, row, col, "%s" % time_scale(h1[dom][2][0]))
|
||||
col += 12
|
||||
display(stdscr, row, col, "%3.2f%%" % h1[dom][2][1])
|
||||
col += 12
|
||||
display(stdscr, row, col, "%s/io" % time_scale(h1[dom][2][2]))
|
||||
col += 18
|
||||
display(stdscr, row, col, "Blocked")
|
||||
|
||||
# display waited
|
||||
row += 1
|
||||
col = 2
|
||||
display(stdscr, row, col, "%d" % dom)
|
||||
col += 4
|
||||
display(stdscr, row, col, "%s" % time_scale(h2[dom][3][0]))
|
||||
col += 12
|
||||
display(stdscr, row, col, "%3.2f%%" % h2[dom][3][1])
|
||||
col += 12
|
||||
display(stdscr, row, col, "%s/ex" % time_scale(h2[dom][3][2]))
|
||||
col += 18
|
||||
display(stdscr, row, col, "%s" % time_scale(h1[dom][3][0]))
|
||||
col += 12
|
||||
display(stdscr, row, col, "%3.2f%%" % h1[dom][3][1])
|
||||
col += 12
|
||||
display(stdscr, row, col, "%s/ex" % time_scale(h1[dom][3][2]))
|
||||
col += 18
|
||||
display(stdscr, row, col, "Waited")
|
||||
if options.waited:
|
||||
row += 1
|
||||
col = 2
|
||||
display(stdscr, row, col, "%d" % dom)
|
||||
col += 4
|
||||
display(stdscr, row, col, "%s" % time_scale(h2[dom][3][0]))
|
||||
col += 12
|
||||
display(stdscr, row, col, "%3.2f%%" % h2[dom][3][1])
|
||||
col += 12
|
||||
display(stdscr, row, col, "%s/ex" % time_scale(h2[dom][3][2]))
|
||||
col += 18
|
||||
display(stdscr, row, col, "%s" % time_scale(h1[dom][3][0]))
|
||||
col += 12
|
||||
display(stdscr, row, col, "%3.2f%%" % h1[dom][3][1])
|
||||
col += 12
|
||||
display(stdscr, row, col, "%s/ex" % time_scale(h1[dom][3][2]))
|
||||
col += 18
|
||||
display(stdscr, row, col, "Waited")
|
||||
|
||||
# display ex count
|
||||
row += 1
|
||||
col = 2
|
||||
display(stdscr, row, col, "%d" % dom)
|
||||
|
||||
col += 28
|
||||
display(stdscr, row, col, "%d/s" % h2[dom][4])
|
||||
col += 42
|
||||
display(stdscr, row, col, "%d" % h1[dom][4])
|
||||
col += 18
|
||||
display(stdscr, row, col, "Execution count")
|
||||
if options.excount:
|
||||
row += 1
|
||||
col = 2
|
||||
display(stdscr, row, col, "%d" % dom)
|
||||
|
||||
col += 28
|
||||
display(stdscr, row, col, "%d/s" % h2[dom][4])
|
||||
col += 42
|
||||
display(stdscr, row, col, "%d" % h1[dom][4])
|
||||
col += 18
|
||||
display(stdscr, row, col, "Execution count")
|
||||
|
||||
# display io count
|
||||
row += 1
|
||||
col = 2
|
||||
display(stdscr, row, col, "%d" % dom)
|
||||
col += 4
|
||||
display(stdscr, row, col, "%d/s" % h2[dom][5][0])
|
||||
col += 24
|
||||
display(stdscr, row, col, "%d/ex" % h2[dom][5][1])
|
||||
col += 18
|
||||
display(stdscr, row, col, "%d" % h1[dom][5][0])
|
||||
col += 24
|
||||
display(stdscr, row, col, "%3.2f/ex" % h1[dom][5][1])
|
||||
col += 18
|
||||
display(stdscr, row, col, "I/O Count")
|
||||
if options.iocount:
|
||||
row += 1
|
||||
col = 2
|
||||
display(stdscr, row, col, "%d" % dom)
|
||||
col += 4
|
||||
display(stdscr, row, col, "%d/s" % h2[dom][5][0])
|
||||
col += 24
|
||||
display(stdscr, row, col, "%d/ex" % h2[dom][5][1])
|
||||
col += 18
|
||||
display(stdscr, row, col, "%d" % h1[dom][5][0])
|
||||
col += 24
|
||||
display(stdscr, row, col, "%3.2f/ex" % h1[dom][5][1])
|
||||
col += 18
|
||||
display(stdscr, row, col, "I/O Count")
|
||||
|
||||
#row += 1
|
||||
#stdscr.hline(row, 1, '-', maxx - 2)
|
||||
@@ -426,6 +470,9 @@ def show_livestats():
|
||||
|
||||
|
||||
row += 1
|
||||
star = heartbeat * '*'
|
||||
heartbeat = 1 - heartbeat
|
||||
display(stdscr, row, 1, star)
|
||||
display(stdscr, row, 2, TOTALS % (total_h2_cpu, total_h1_cpu))
|
||||
row += 1
|
||||
# display(stdscr, row, 2,
|
||||
@@ -515,11 +562,11 @@ def writelog():
|
||||
outfiles[dom].delayed_write("# passed cpu dom cpu(tot) cpu(%) cpu/ex allocated/ex blocked(tot) blocked(%) blocked/io waited(tot) waited(%) waited/ex ex/s io(tot) io/ex\n")
|
||||
|
||||
while options.duration == 0 or interval < (options.duration * 1000):
|
||||
for cpuidx in range(0, ncpu):
|
||||
cpuidx = 0
|
||||
while cpuidx < ncpu:
|
||||
|
||||
idx = cpuidx * slen # offset needed in mmap file
|
||||
|
||||
|
||||
samples = []
|
||||
doms = []
|
||||
dom_in_use = []
|
||||
@@ -571,6 +618,7 @@ def writelog():
|
||||
curr = time.time()
|
||||
interval += (curr - last) * 1000
|
||||
last = curr
|
||||
cpuidx = cpuidx + 1
|
||||
time.sleep(options.interval / 1000.0)
|
||||
|
||||
for dom in range(0, NDOMAINS):
|
||||
@@ -601,7 +649,7 @@ def main():
|
||||
|
||||
start_xenbaked()
|
||||
if options.live:
|
||||
show_livestats()
|
||||
show_livestats(options.cpu)
|
||||
else:
|
||||
try:
|
||||
writelog()
|
||||
|
||||
@@ -77,6 +77,10 @@ static void check_store(void);
|
||||
} while (0)
|
||||
|
||||
|
||||
int quota_nb_entry_per_domain = 1000;
|
||||
int quota_nb_watch_per_domain = 128;
|
||||
int quota_max_entry_size = 2048; /* 2K */
|
||||
|
||||
#ifdef TESTING
|
||||
static bool failtest = false;
|
||||
|
||||
@@ -455,6 +459,10 @@ static bool write_node(struct connection *conn, const struct node *node)
|
||||
data.dsize = 3*sizeof(uint32_t)
|
||||
+ node->num_perms*sizeof(node->perms[0])
|
||||
+ node->datalen + node->childlen;
|
||||
|
||||
if (data.dsize >= quota_max_entry_size)
|
||||
goto error;
|
||||
|
||||
data.dptr = talloc_size(node, data.dsize);
|
||||
((uint32_t *)data.dptr)[0] = node->num_perms;
|
||||
((uint32_t *)data.dptr)[1] = node->datalen;
|
||||
@@ -470,10 +478,12 @@ static bool write_node(struct connection *conn, const struct node *node)
|
||||
/* TDB should set errno, but doesn't even set ecode AFAICT. */
|
||||
if (tdb_store(tdb_context(conn), key, data, TDB_REPLACE) != 0) {
|
||||
corrupt(conn, "Write of %s = %s failed", key, data);
|
||||
errno = ENOSPC;
|
||||
return false;
|
||||
goto error;
|
||||
}
|
||||
return true;
|
||||
error:
|
||||
errno = ENOSPC;
|
||||
return false;
|
||||
}
|
||||
|
||||
static enum xs_perm_type perm_for_conn(struct connection *conn,
|
||||
@@ -765,8 +775,11 @@ static void delete_node_single(struct connection *conn, struct node *node)
|
||||
key.dptr = (void *)node->name;
|
||||
key.dsize = strlen(node->name);
|
||||
|
||||
if (tdb_delete(tdb_context(conn), key) != 0)
|
||||
if (tdb_delete(tdb_context(conn), key) != 0) {
|
||||
corrupt(conn, "Could not delete '%s'", node->name);
|
||||
return;
|
||||
}
|
||||
domain_entry_dec(conn);
|
||||
}
|
||||
|
||||
/* Must not be / */
|
||||
@@ -788,7 +801,10 @@ static struct node *construct_node(struct connection *conn, const char *name)
|
||||
parent = construct_node(conn, parentname);
|
||||
if (!parent)
|
||||
return NULL;
|
||||
|
||||
|
||||
if (domain_entry(conn) >= quota_nb_entry_per_domain)
|
||||
return NULL;
|
||||
|
||||
/* Add child to parent. */
|
||||
base = basename(name);
|
||||
baselen = strlen(base) + 1;
|
||||
@@ -814,6 +830,7 @@ static struct node *construct_node(struct connection *conn, const char *name)
|
||||
node->children = node->data = NULL;
|
||||
node->childlen = node->datalen = 0;
|
||||
node->parent = parent;
|
||||
domain_entry_inc(conn);
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -848,8 +865,10 @@ static struct node *create_node(struct connection *conn,
|
||||
/* We write out the nodes down, setting destructor in case
|
||||
* something goes wrong. */
|
||||
for (i = node; i; i = i->parent) {
|
||||
if (!write_node(conn, i))
|
||||
if (!write_node(conn, i)) {
|
||||
domain_entry_dec(conn);
|
||||
return NULL;
|
||||
}
|
||||
talloc_set_destructor(i, destroy_node);
|
||||
}
|
||||
|
||||
@@ -1706,6 +1725,9 @@ static void usage(void)
|
||||
" --no-fork to request that the daemon does not fork,\n"
|
||||
" --output-pid to request that the pid of the daemon is output,\n"
|
||||
" --trace-file <file> giving the file for logging, and\n"
|
||||
" --entry-nb <nb> limit the number of entries per domain,\n"
|
||||
" --entry-size <size> limit the size of entry per domain, and\n"
|
||||
" --entry-watch <nb> limit the number of watches per domain,\n"
|
||||
" --no-recovery to request that no recovery should be attempted when\n"
|
||||
" the store is corrupted (debug only),\n"
|
||||
" --preserve-local to request that /local is preserved on start-up,\n"
|
||||
@@ -1715,14 +1737,17 @@ static void usage(void)
|
||||
|
||||
static struct option options[] = {
|
||||
{ "no-domain-init", 0, NULL, 'D' },
|
||||
{ "entry-nb", 1, NULL, 'E' },
|
||||
{ "pid-file", 1, NULL, 'F' },
|
||||
{ "help", 0, NULL, 'H' },
|
||||
{ "no-fork", 0, NULL, 'N' },
|
||||
{ "output-pid", 0, NULL, 'P' },
|
||||
{ "entry-size", 1, NULL, 'S' },
|
||||
{ "trace-file", 1, NULL, 'T' },
|
||||
{ "no-recovery", 0, NULL, 'R' },
|
||||
{ "preserve-local", 0, NULL, 'L' },
|
||||
{ "verbose", 0, NULL, 'V' },
|
||||
{ "watch-nb", 1, NULL, 'W' },
|
||||
{ NULL, 0, NULL, 0 } };
|
||||
|
||||
extern void dump_conn(struct connection *conn);
|
||||
@@ -1737,12 +1762,15 @@ int main(int argc, char *argv[])
|
||||
bool no_domain_init = false;
|
||||
const char *pidfile = NULL;
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "DF:HNPT:RLV", options,
|
||||
while ((opt = getopt_long(argc, argv, "DE:F:HNPS:T:RLVW:", options,
|
||||
NULL)) != -1) {
|
||||
switch (opt) {
|
||||
case 'D':
|
||||
no_domain_init = true;
|
||||
break;
|
||||
case 'E':
|
||||
quota_nb_entry_per_domain = strtol(optarg, NULL, 10);
|
||||
break;
|
||||
case 'F':
|
||||
pidfile = optarg;
|
||||
break;
|
||||
@@ -1761,12 +1789,18 @@ int main(int argc, char *argv[])
|
||||
case 'L':
|
||||
remove_local = false;
|
||||
break;
|
||||
case 'S':
|
||||
quota_max_entry_size = strtol(optarg, NULL, 10);
|
||||
break;
|
||||
case 'T':
|
||||
tracefile = optarg;
|
||||
break;
|
||||
case 'V':
|
||||
verbose = true;
|
||||
break;
|
||||
case 'W':
|
||||
quota_nb_watch_per_domain = strtol(optarg, NULL, 10);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (optind != argc)
|
||||
|
||||
@@ -74,6 +74,12 @@ struct domain
|
||||
|
||||
/* Have we noticed that this domain is shutdown? */
|
||||
int shutdown;
|
||||
|
||||
/* number of entry from this domain in the store */
|
||||
int nbentry;
|
||||
|
||||
/* number of watch for this domain */
|
||||
int nbwatch;
|
||||
};
|
||||
|
||||
static LIST_HEAD(domains);
|
||||
@@ -285,6 +291,8 @@ static struct domain *new_domain(void *context, unsigned int domid,
|
||||
domain->conn->id = domid;
|
||||
|
||||
domain->remote_port = port;
|
||||
domain->nbentry = 0;
|
||||
domain->nbwatch = 0;
|
||||
|
||||
return domain;
|
||||
}
|
||||
@@ -562,6 +570,50 @@ int domain_init(void)
|
||||
return eventchn_fd;
|
||||
}
|
||||
|
||||
void domain_entry_inc(struct connection *conn)
|
||||
{
|
||||
if (!conn || !conn->domain)
|
||||
return;
|
||||
conn->domain->nbentry++;
|
||||
}
|
||||
|
||||
void domain_entry_dec(struct connection *conn)
|
||||
{
|
||||
if (!conn || !conn->domain)
|
||||
return;
|
||||
if (conn->domain->nbentry)
|
||||
conn->domain->nbentry--;
|
||||
}
|
||||
|
||||
int domain_entry(struct connection *conn)
|
||||
{
|
||||
return (conn && conn->domain && conn->domain->domid)
|
||||
? conn->domain->nbentry
|
||||
: 0;
|
||||
}
|
||||
|
||||
void domain_watch_inc(struct connection *conn)
|
||||
{
|
||||
if (!conn || !conn->domain)
|
||||
return;
|
||||
conn->domain->nbwatch++;
|
||||
}
|
||||
|
||||
void domain_watch_dec(struct connection *conn)
|
||||
{
|
||||
if (!conn || !conn->domain)
|
||||
return;
|
||||
if (conn->domain->nbwatch)
|
||||
conn->domain->nbwatch--;
|
||||
}
|
||||
|
||||
int domain_watch(struct connection *conn)
|
||||
{
|
||||
return (conn && conn->domain && conn->domain->domid)
|
||||
? conn->domain->nbwatch
|
||||
: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-file-style: "linux"
|
||||
|
||||
@@ -47,4 +47,12 @@ void restore_existing_connections(void);
|
||||
bool domain_can_read(struct connection *conn);
|
||||
bool domain_can_write(struct connection *conn);
|
||||
|
||||
/* Quota manipulation */
|
||||
void domain_entry_inc(struct connection *conn);
|
||||
void domain_entry_dec(struct connection *conn);
|
||||
int domain_entry(struct connection *conn);
|
||||
void domain_watch_inc(struct connection *conn);
|
||||
void domain_watch_dec(struct connection *conn);
|
||||
int domain_watch(struct connection *conn);
|
||||
|
||||
#endif /* _XENSTORED_DOMAIN_H */
|
||||
@@ -32,6 +32,8 @@
|
||||
#include "xenstored_test.h"
|
||||
#include "xenstored_domain.h"
|
||||
|
||||
extern int quota_nb_watch_per_domain;
|
||||
|
||||
struct watch
|
||||
{
|
||||
/* Watches on this connection */
|
||||
@@ -135,6 +137,11 @@ void do_watch(struct connection *conn, struct buffered_data *in)
|
||||
}
|
||||
}
|
||||
|
||||
if (domain_watch(conn) > quota_nb_watch_per_domain) {
|
||||
send_error(conn, E2BIG);
|
||||
return;
|
||||
}
|
||||
|
||||
watch = talloc(conn, struct watch);
|
||||
watch->node = talloc_strdup(watch, vec[0]);
|
||||
watch->token = talloc_strdup(watch, vec[1]);
|
||||
@@ -145,6 +152,7 @@ void do_watch(struct connection *conn, struct buffered_data *in)
|
||||
|
||||
INIT_LIST_HEAD(&watch->events);
|
||||
|
||||
domain_watch_inc(conn);
|
||||
list_add_tail(&watch->list, &conn->watches);
|
||||
trace_create(watch, "watch");
|
||||
talloc_set_destructor(watch, destroy_watch);
|
||||
@@ -169,6 +177,7 @@ void do_unwatch(struct connection *conn, struct buffered_data *in)
|
||||
if (streq(watch->node, node) && streq(watch->token, vec[1])) {
|
||||
list_del(&watch->list);
|
||||
talloc_free(watch);
|
||||
domain_watch_dec(conn);
|
||||
send_ack(conn, XS_UNWATCH);
|
||||
return;
|
||||
}
|
||||
|
||||
+20
-26
@@ -10,19 +10,22 @@ export BASEDIR := $(CURDIR)
|
||||
.PHONY: default
|
||||
default: build
|
||||
|
||||
ifeq ($(XEN_ROOT),)
|
||||
.PHONY: dist
|
||||
dist: install
|
||||
|
||||
.PHONY: build install clean
|
||||
build install clean:
|
||||
make -f Rules.mk $@
|
||||
.PHONY: debug
|
||||
debug:
|
||||
objdump -D -S $(TARGET)-syms > $(TARGET).s
|
||||
|
||||
else
|
||||
.PHONY: build install clean cscope TAGS tags
|
||||
build install clean cscope TAGS tags::
|
||||
make -f Rules.mk _$@
|
||||
|
||||
.PHONY: build
|
||||
build: $(TARGET).gz
|
||||
.PHONY: _build
|
||||
_build: $(TARGET).gz
|
||||
|
||||
.PHONY: install
|
||||
install: $(TARGET).gz
|
||||
.PHONY: _install
|
||||
_install: $(TARGET).gz
|
||||
[ -d $(DESTDIR)/boot ] || $(INSTALL_DIR) $(DESTDIR)/boot
|
||||
$(INSTALL_DATA) $(TARGET).gz $(DESTDIR)/boot/$(notdir $(TARGET))-$(XEN_FULLVERSION).gz
|
||||
ln -f -s $(notdir $(TARGET))-$(XEN_FULLVERSION).gz $(DESTDIR)/boot/$(notdir $(TARGET))-$(XEN_VERSION).$(XEN_SUBVERSION).gz
|
||||
@@ -35,8 +38,8 @@ install: $(TARGET).gz
|
||||
$(INSTALL_DATA) include/public/io/*.h $(DESTDIR)/usr/include/xen/io
|
||||
$(INSTALL_DATA) include/public/COPYING $(DESTDIR)/usr/include/xen
|
||||
|
||||
.PHONY: clean
|
||||
clean:: delete-unfresh-files
|
||||
.PHONY: _clean
|
||||
_clean: delete-unfresh-files
|
||||
$(MAKE) -C tools clean
|
||||
$(MAKE) -f $(BASEDIR)/Rules.mk -C common clean
|
||||
$(MAKE) -f $(BASEDIR)/Rules.mk -C drivers clean
|
||||
@@ -46,15 +49,6 @@ clean:: delete-unfresh-files
|
||||
rm -f include/asm-*/asm-offsets.h
|
||||
rm -f include/xen/acm_policy.h
|
||||
|
||||
endif
|
||||
|
||||
.PHONY: dist
|
||||
dist: install
|
||||
|
||||
.PHONY: debug
|
||||
debug:
|
||||
objdump -D -S $(TARGET)-syms > $(TARGET).s
|
||||
|
||||
$(TARGET).gz: $(TARGET)
|
||||
gzip -f -9 < $< > $@.new
|
||||
mv $@.new $@
|
||||
@@ -135,16 +129,16 @@ define all_sources
|
||||
find $(SUBDIRS) -name SCCS -prune -o -name '*.[chS]' -print )
|
||||
endef
|
||||
|
||||
.PHONY: TAGS
|
||||
TAGS:
|
||||
.PHONY: _TAGS
|
||||
_TAGS:
|
||||
$(all_sources) | etags -
|
||||
|
||||
.PHONY: tags
|
||||
tags:
|
||||
.PHONY: _tags
|
||||
_tags:
|
||||
$(all_sources) | xargs ctags
|
||||
|
||||
.PHONY: cscope
|
||||
cscope:
|
||||
.PHONY: _cscope
|
||||
_cscope:
|
||||
$(all_sources) > cscope.files
|
||||
cscope -k -b -q
|
||||
|
||||
|
||||
@@ -76,6 +76,7 @@ boot/mkelf32: boot/mkelf32.c
|
||||
$(HOSTCC) $(HOSTCFLAGS) -o $@ $<
|
||||
|
||||
shadow_guest32.o: shadow.c
|
||||
shadow_guest32pae.o: shadow.c
|
||||
|
||||
.PHONY: clean
|
||||
clean::
|
||||
|
||||
@@ -639,7 +639,7 @@ void _audit_domain(struct domain *d, int flags)
|
||||
void scan_for_pfn_in_grant_table(struct domain *d, unsigned xmfn)
|
||||
{
|
||||
int i;
|
||||
active_grant_entry_t *act = d->grant_table->active;
|
||||
struct active_grant_entry *act = d->grant_table->active;
|
||||
|
||||
spin_lock(&d->grant_table->lock);
|
||||
|
||||
|
||||
@@ -208,8 +208,9 @@ int register_io_handler(unsigned long addr, unsigned long size,
|
||||
|
||||
static void pit_cal_count(struct hvm_virpit *vpit)
|
||||
{
|
||||
u64 nsec_delta = (unsigned int)((NOW() - vpit->inject_point));
|
||||
u64 nsec_delta = (unsigned int)((NOW() - vpit->count_point));
|
||||
|
||||
nsec_delta += vpit->count_advance;
|
||||
if (nsec_delta > vpit->period)
|
||||
HVM_DBG_LOG(DBG_LEVEL_1,
|
||||
"HVM_PIT: long time has passed from last injection!");
|
||||
|
||||
@@ -79,7 +79,8 @@ interrupt_post_injection(struct vcpu * v, int vector, int type)
|
||||
} else {
|
||||
vpit->pending_intr_nr--;
|
||||
}
|
||||
vpit->inject_point = NOW();
|
||||
vpit->count_advance = 0;
|
||||
vpit->count_point = NOW();
|
||||
|
||||
vpit->last_pit_gtime += vpit->period_cycles;
|
||||
svm_set_guest_time(v, vpit->last_pit_gtime);
|
||||
|
||||
+210
-50
@@ -315,19 +315,29 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
|
||||
{
|
||||
case MSR_EFER:
|
||||
#ifdef __x86_64__
|
||||
if ((msr_content & EFER_LME) ^ test_bit(SVM_CPU_STATE_LME_ENABLED,
|
||||
&vc->arch.hvm_svm.cpu_state))
|
||||
/* offending reserved bit will cause #GP */
|
||||
if ( msr_content & ~(EFER_LME | EFER_LMA | EFER_NX | EFER_SCE) )
|
||||
{
|
||||
if (test_bit(SVM_CPU_STATE_PG_ENABLED, &vc->arch.hvm_svm.cpu_state)
|
||||
|| !test_bit(SVM_CPU_STATE_PAE_ENABLED,
|
||||
&vc->arch.hvm_svm.cpu_state))
|
||||
{
|
||||
svm_inject_exception(vmcb, TRAP_gp_fault, 1, 0);
|
||||
}
|
||||
printk("trying to set reserved bit in EFER\n");
|
||||
svm_inject_exception(vmcb, TRAP_gp_fault, 1, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (msr_content & EFER_LME)
|
||||
/* LME: 0 -> 1 */
|
||||
if ( msr_content & EFER_LME &&
|
||||
!test_bit(SVM_CPU_STATE_LME_ENABLED, &vc->arch.hvm_svm.cpu_state) )
|
||||
{
|
||||
if ( svm_paging_enabled(vc) ||
|
||||
!test_bit(SVM_CPU_STATE_PAE_ENABLED,
|
||||
&vc->arch.hvm_svm.cpu_state) )
|
||||
{
|
||||
printk("trying to set LME bit when "
|
||||
"in paging mode or PAE bit is not set\n");
|
||||
svm_inject_exception(vmcb, TRAP_gp_fault, 1, 0);
|
||||
return 0;
|
||||
}
|
||||
set_bit(SVM_CPU_STATE_LME_ENABLED, &vc->arch.hvm_svm.cpu_state);
|
||||
}
|
||||
|
||||
/* We have already recorded that we want LME, so it will be set
|
||||
* next time CR0 gets updated. So we clear that bit and continue.
|
||||
@@ -669,6 +679,7 @@ static void svm_freeze_time(struct vcpu *v)
|
||||
|
||||
if ( vpit->first_injected && !v->domain->arch.hvm_domain.guest_time ) {
|
||||
v->domain->arch.hvm_domain.guest_time = svm_get_guest_time(v);
|
||||
vpit->count_advance += (NOW() - vpit->count_point);
|
||||
stop_timer(&(vpit->pit_timer));
|
||||
}
|
||||
}
|
||||
@@ -757,7 +768,8 @@ void arch_svm_do_resume(struct vcpu *v)
|
||||
reset_stack_and_jump( svm_asm_do_resume );
|
||||
}
|
||||
else {
|
||||
printk("VCPU core pinned: %d to %d\n", v->arch.hvm_svm.launch_core, smp_processor_id() );
|
||||
printk("VCPU core pinned: %d to %d\n",
|
||||
v->arch.hvm_svm.launch_core, smp_processor_id() );
|
||||
v->arch.hvm_svm.launch_core = smp_processor_id();
|
||||
svm_migrate_timers( v );
|
||||
svm_do_resume( v );
|
||||
@@ -922,6 +934,7 @@ static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
|
||||
clear_bit(X86_FEATURE_APIC, &edx);
|
||||
|
||||
#if CONFIG_PAGING_LEVELS < 3
|
||||
clear_bit(X86_FEATURE_NX, &edx);
|
||||
clear_bit(X86_FEATURE_PAE, &edx);
|
||||
clear_bit(X86_FEATURE_PSE, &edx);
|
||||
clear_bit(X86_FEATURE_PSE36, &edx);
|
||||
@@ -929,12 +942,14 @@ static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
|
||||
if ( v->domain->arch.ops->guest_paging_levels == PAGING_L2 )
|
||||
{
|
||||
if ( !v->domain->arch.hvm_domain.pae_enabled )
|
||||
clear_bit(X86_FEATURE_PAE, &edx);
|
||||
{
|
||||
clear_bit(X86_FEATURE_PAE, &edx);
|
||||
clear_bit(X86_FEATURE_NX, &edx);
|
||||
}
|
||||
clear_bit(X86_FEATURE_PSE, &edx);
|
||||
clear_bit(X86_FEATURE_PSE36, &edx);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/* Clear out reserved bits. */
|
||||
ecx &= ~SVM_VCPU_CPUID_L1_RESERVED; /* mask off reserved bits */
|
||||
clear_bit(X86_FEATURE_MWAIT & 31, &ecx);
|
||||
@@ -1312,8 +1327,7 @@ static int svm_set_cr0(unsigned long value)
|
||||
unsigned long mfn;
|
||||
int paging_enabled;
|
||||
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
|
||||
unsigned long crn;
|
||||
|
||||
|
||||
ASSERT(vmcb);
|
||||
|
||||
/* We don't want to lose PG. ET is reserved and should be always be 1*/
|
||||
@@ -1358,37 +1372,39 @@ static int svm_set_cr0(unsigned long value)
|
||||
set_bit(SVM_CPU_STATE_LMA_ENABLED,
|
||||
&v->arch.hvm_svm.cpu_state);
|
||||
vmcb->efer |= (EFER_LMA | EFER_LME);
|
||||
|
||||
#if CONFIG_PAGING_LEVELS >= 4
|
||||
if (!shadow_set_guest_paging_levels(v->domain, 4))
|
||||
if (!shadow_set_guest_paging_levels(v->domain, PAGING_L4) )
|
||||
{
|
||||
printk("Unsupported guest paging levels\n");
|
||||
domain_crash_synchronous(); /* need to take a clean path */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif /* __x86_64__ */
|
||||
{
|
||||
#if CONFIG_PAGING_LEVELS >= 3
|
||||
if (!shadow_set_guest_paging_levels(v->domain, 2))
|
||||
/* seems it's a 32-bit or 32-bit PAE guest */
|
||||
if ( test_bit(SVM_CPU_STATE_PAE_ENABLED,
|
||||
&v->arch.hvm_svm.cpu_state) )
|
||||
{
|
||||
printk("Unsupported guest paging levels\n");
|
||||
domain_crash_synchronous(); /* need to take a clean path */
|
||||
/* The guest enables PAE first and then it enables PG, it is
|
||||
* really a PAE guest */
|
||||
if ( !shadow_set_guest_paging_levels(v->domain, PAGING_L3) )
|
||||
{
|
||||
printk("Unsupported guest paging levels\n");
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !shadow_set_guest_paging_levels(v->domain, PAGING_L2) )
|
||||
{
|
||||
printk("Unsupported guest paging levels\n");
|
||||
domain_crash_synchronous(); /* need to take a clean path */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* update CR4's PAE if needed */
|
||||
crn = vmcb->cr4;
|
||||
if ((!(crn & X86_CR4_PAE))
|
||||
&& test_bit(SVM_CPU_STATE_PAE_ENABLED,
|
||||
&v->arch.hvm_svm.cpu_state))
|
||||
{
|
||||
HVM_DBG_LOG(DBG_LEVEL_1, "enable PAE on cr4\n");
|
||||
vmcb->cr4 |= X86_CR4_PAE;
|
||||
}
|
||||
|
||||
/* Now arch.guest_table points to machine physical. */
|
||||
v->arch.guest_table = mk_pagetable((u64)mfn << PAGE_SHIFT);
|
||||
update_pagetables(v);
|
||||
@@ -1402,8 +1418,17 @@ static int svm_set_cr0(unsigned long value)
|
||||
/* arch->shadow_table should hold the next CR3 for shadow */
|
||||
HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx\n",
|
||||
v->arch.hvm_svm.cpu_cr3, mfn);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( !((value & X86_CR0_PE) && (value & X86_CR0_PG)) && paging_enabled )
|
||||
if ( v->arch.hvm_svm.cpu_cr3 ) {
|
||||
put_page(mfn_to_page(get_mfn_from_gpfn(
|
||||
v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT)));
|
||||
v->arch.guest_table = mk_pagetable(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* SVM implements paged real-mode and when we return to real-mode
|
||||
* we revert back to the physical mappings that the domain builder
|
||||
@@ -1415,6 +1440,14 @@ static int svm_set_cr0(unsigned long value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
clear_all_shadow_status( v->domain );
|
||||
set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
|
||||
vmcb->cr3 = pagetable_get_paddr(v->domain->arch.phys_table);
|
||||
}
|
||||
else if ( (value & (X86_CR0_PE | X86_CR0_PG)) == X86_CR0_PE )
|
||||
{
|
||||
/* we should take care of this kind of situation */
|
||||
clear_all_shadow_status(v->domain);
|
||||
set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
|
||||
vmcb->cr3 = pagetable_get_paddr(v->domain->arch.phys_table);
|
||||
}
|
||||
@@ -1438,15 +1471,21 @@ static void mov_from_cr(int cr, int gp, struct cpu_user_regs *regs)
|
||||
{
|
||||
case 0:
|
||||
value = v->arch.hvm_svm.cpu_shadow_cr0;
|
||||
break;
|
||||
if (svm_dbg_on)
|
||||
printk("CR0 read =%lx \n", value );
|
||||
break;
|
||||
case 2:
|
||||
value = vmcb->cr2;
|
||||
break;
|
||||
case 3:
|
||||
value = (unsigned long) v->arch.hvm_svm.cpu_cr3;
|
||||
break;
|
||||
if (svm_dbg_on)
|
||||
printk("CR3 read =%lx \n", value );
|
||||
break;
|
||||
case 4:
|
||||
value = (unsigned long) v->arch.hvm_svm.cpu_shadow_cr4;
|
||||
if (svm_dbg_on)
|
||||
printk( "CR4 read=%lx\n", value );
|
||||
break;
|
||||
case 8:
|
||||
#if 0
|
||||
@@ -1466,6 +1505,12 @@ static void mov_from_cr(int cr, int gp, struct cpu_user_regs *regs)
|
||||
}
|
||||
|
||||
|
||||
static inline int svm_pgbit_test(struct vcpu *v)
|
||||
{
|
||||
return v->arch.hvm_svm.cpu_shadow_cr0 & X86_CR0_PG;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write to control registers
|
||||
*/
|
||||
@@ -1486,12 +1531,15 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
|
||||
switch (cr)
|
||||
{
|
||||
case 0:
|
||||
if (svm_dbg_on)
|
||||
printk("CR0 write =%lx \n", value );
|
||||
return svm_set_cr0(value);
|
||||
|
||||
case 3:
|
||||
{
|
||||
unsigned long old_base_mfn, mfn;
|
||||
|
||||
if (svm_dbg_on)
|
||||
printk("CR3 write =%lx \n", value );
|
||||
/* If paging is not enabled yet, simply copy the value to CR3. */
|
||||
if (!svm_paging_enabled(v)) {
|
||||
v->arch.hvm_svm.cpu_cr3 = value;
|
||||
@@ -1533,19 +1581,104 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
|
||||
if (old_base_mfn)
|
||||
put_page(mfn_to_page(old_base_mfn));
|
||||
|
||||
update_pagetables(v);
|
||||
|
||||
/* arch.shadow_table should now hold the next CR3 for shadow*/
|
||||
/*
|
||||
* arch.shadow_table should now hold the next CR3 for shadow
|
||||
*/
|
||||
#if CONFIG_PAGING_LEVELS >= 3
|
||||
if ( v->domain->arch.ops->guest_paging_levels == PAGING_L3 )
|
||||
shadow_sync_all(v->domain);
|
||||
#endif
|
||||
v->arch.hvm_svm.cpu_cr3 = value;
|
||||
update_pagetables(v);
|
||||
HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx", value);
|
||||
vmcb->cr3 = pagetable_get_paddr(v->arch.shadow_table);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
/* CR4 */
|
||||
if (value & X86_CR4_PAE) {
|
||||
case 4: /* CR4 */
|
||||
{
|
||||
if (svm_dbg_on)
|
||||
printk( "write cr4=%lx, cr0=%lx\n",
|
||||
value, v->arch.hvm_svm.cpu_shadow_cr0 );
|
||||
old_cr = v->arch.hvm_svm.cpu_shadow_cr4;
|
||||
if ( value & X86_CR4_PAE && !(old_cr & X86_CR4_PAE) )
|
||||
{
|
||||
set_bit(SVM_CPU_STATE_PAE_ENABLED, &v->arch.hvm_svm.cpu_state);
|
||||
if ( svm_pgbit_test(v) )
|
||||
{
|
||||
/* The guest is a 32-bit PAE guest. */
|
||||
#if CONFIG_PAGING_LEVELS >= 4
|
||||
unsigned long mfn, old_base_mfn;
|
||||
|
||||
if( !shadow_set_guest_paging_levels(v->domain, PAGING_L3) )
|
||||
{
|
||||
printk("Unsupported guest paging levels\n");
|
||||
domain_crash_synchronous(); /* need to take a clean path */
|
||||
}
|
||||
|
||||
if ( !VALID_MFN(mfn = get_mfn_from_gpfn(
|
||||
v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT)) ||
|
||||
!get_page(mfn_to_page(mfn), v->domain) )
|
||||
{
|
||||
printk("Invalid CR3 value = %lx", v->arch.hvm_svm.cpu_cr3);
|
||||
domain_crash_synchronous(); /* need to take a clean path */
|
||||
}
|
||||
|
||||
old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
|
||||
if ( old_base_mfn )
|
||||
put_page(mfn_to_page(old_base_mfn));
|
||||
|
||||
/*
|
||||
* Now arch.guest_table points to machine physical.
|
||||
*/
|
||||
|
||||
v->arch.guest_table = mk_pagetable((u64)mfn << PAGE_SHIFT);
|
||||
update_pagetables(v);
|
||||
|
||||
HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx",
|
||||
(unsigned long) (mfn << PAGE_SHIFT));
|
||||
|
||||
vmcb->cr3 = pagetable_get_paddr(v->arch.shadow_table);
|
||||
|
||||
/*
|
||||
* arch->shadow_table should hold the next CR3 for shadow
|
||||
*/
|
||||
|
||||
HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx",
|
||||
v->arch.hvm_svm.cpu_cr3, mfn);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The guest is a 64 bit or 32-bit PAE guest. */
|
||||
#if CONFIG_PAGING_LEVELS >= 4
|
||||
if ( (v->domain->arch.ops != NULL) &&
|
||||
v->domain->arch.ops->guest_paging_levels == PAGING_L2)
|
||||
{
|
||||
/* Seems the guest first enables PAE without enabling PG,
|
||||
* it must enable PG after that, and it is a 32-bit PAE
|
||||
* guest */
|
||||
|
||||
if ( !shadow_set_guest_paging_levels(v->domain, PAGING_L3) )
|
||||
{
|
||||
printk("Unsupported guest paging levels\n");
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !shadow_set_guest_paging_levels(v->domain,
|
||||
PAGING_L4) )
|
||||
{
|
||||
printk("Unsupported guest paging levels\n");
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if (value & X86_CR4_PAE) {
|
||||
set_bit(SVM_CPU_STATE_PAE_ENABLED, &v->arch.hvm_svm.cpu_state);
|
||||
} else {
|
||||
if (test_bit(SVM_CPU_STATE_LMA_ENABLED,
|
||||
@@ -1555,7 +1688,6 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
|
||||
clear_bit(SVM_CPU_STATE_PAE_ENABLED, &v->arch.hvm_svm.cpu_state);
|
||||
}
|
||||
|
||||
old_cr = v->arch.hvm_svm.cpu_shadow_cr4;
|
||||
v->arch.hvm_svm.cpu_shadow_cr4 = value;
|
||||
vmcb->cr4 = value | SVM_CR4_HOST_MASK;
|
||||
|
||||
@@ -1569,6 +1701,7 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
|
||||
shadow_sync_all(v->domain);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
printk("invalid cr: %d\n", cr);
|
||||
@@ -1933,6 +2066,7 @@ static int svm_do_vmmcall_reset_to_realmode(struct vcpu *v,
|
||||
|
||||
vmcb->cr4 = SVM_CR4_HOST_MASK;
|
||||
v->arch.hvm_svm.cpu_shadow_cr4 = 0;
|
||||
clear_bit(SVM_CPU_STATE_PAE_ENABLED, &v->arch.hvm_svm.cpu_state);
|
||||
|
||||
/* This will jump to ROMBIOS */
|
||||
vmcb->rip = 0xFFF0;
|
||||
@@ -1989,6 +2123,7 @@ static int svm_do_vmmcall_reset_to_realmode(struct vcpu *v,
|
||||
vmcb->idtr.base = 0x00;
|
||||
|
||||
vmcb->rax = 0;
|
||||
vmcb->rsp = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2280,7 +2415,8 @@ void walk_shadow_and_guest_pt(unsigned long gva)
|
||||
gpte.l1 = 0;
|
||||
__copy_from_user(&gpte, &linear_pg_table[ l1_linear_offset(gva) ], sizeof(gpte) );
|
||||
printk( "G-PTE = %x, flags=%x\n", gpte.l1, l1e_get_flags(gpte) );
|
||||
__copy_from_user( &spte, &phys_to_machine_mapping[ l1e_get_pfn( gpte ) ], sizeof(spte) );
|
||||
__copy_from_user( &spte, &phys_to_machine_mapping[ l1e_get_pfn( gpte ) ],
|
||||
sizeof(spte) );
|
||||
printk( "S-PTE = %x, flags=%x\n", spte.l1, l1e_get_flags(spte));
|
||||
}
|
||||
#endif /* SVM_WALK_GUEST_PAGES */
|
||||
@@ -2313,6 +2449,17 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs regs)
|
||||
if (svm_dbg_on && exit_reason == VMEXIT_EXCEPTION_PF)
|
||||
{
|
||||
if (svm_paging_enabled(v) && !mmio_space(gva_to_gpa(vmcb->exitinfo2)))
|
||||
{
|
||||
printk("I%08ld,ExC=%s(%d),IP=%x:%llx,I1=%llx,I2=%llx,INT=%llx, gpa=%llx\n",
|
||||
intercepts_counter,
|
||||
exit_reasons[exit_reason], exit_reason, regs.cs,
|
||||
(unsigned long long) regs.rip,
|
||||
(unsigned long long) vmcb->exitinfo1,
|
||||
(unsigned long long) vmcb->exitinfo2,
|
||||
(unsigned long long) vmcb->exitintinfo.bytes,
|
||||
(unsigned long long) gva_to_gpa( vmcb->exitinfo2 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
printk("I%08ld,ExC=%s(%d),IP=%x:%llx,I1=%llx,I2=%llx,INT=%llx\n",
|
||||
intercepts_counter,
|
||||
@@ -2320,12 +2467,12 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs regs)
|
||||
(unsigned long long) regs.rip,
|
||||
(unsigned long long) vmcb->exitinfo1,
|
||||
(unsigned long long) vmcb->exitinfo2,
|
||||
(unsigned long long) vmcb->exitintinfo.bytes);
|
||||
(unsigned long long) vmcb->exitintinfo.bytes );
|
||||
}
|
||||
}
|
||||
else if (svm_dbg_on
|
||||
&& exit_reason != VMEXIT_IOIO
|
||||
&& exit_reason != VMEXIT_INTR)
|
||||
else if ( svm_dbg_on
|
||||
&& exit_reason != VMEXIT_IOIO
|
||||
&& exit_reason != VMEXIT_INTR)
|
||||
{
|
||||
|
||||
if (exit_reasons[exit_reason])
|
||||
@@ -2350,7 +2497,9 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs regs)
|
||||
}
|
||||
|
||||
#ifdef SVM_WALK_GUEST_PAGES
|
||||
if( exit_reason == VMEXIT_EXCEPTION_PF && ( ( vmcb->exitinfo2 == vmcb->rip )|| vmcb->exitintinfo.bytes) )
|
||||
if( exit_reason == VMEXIT_EXCEPTION_PF
|
||||
&& ( ( vmcb->exitinfo2 == vmcb->rip )
|
||||
|| vmcb->exitintinfo.bytes) )
|
||||
{
|
||||
if (svm_paging_enabled(v) && !mmio_space(gva_to_gpa(vmcb->exitinfo2)))
|
||||
walk_shadow_and_guest_pt( vmcb->exitinfo2 );
|
||||
@@ -2434,13 +2583,24 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs regs)
|
||||
*/
|
||||
break;
|
||||
|
||||
#ifdef XEN_DEBUGGER
|
||||
case VMEXIT_INIT:
|
||||
/*
|
||||
* Nothing to do, in fact we should never get to this point.
|
||||
*/
|
||||
break;
|
||||
|
||||
case VMEXIT_EXCEPTION_BP:
|
||||
#ifdef XEN_DEBUGGER
|
||||
svm_debug_save_cpu_user_regs(®s);
|
||||
pdb_handle_exception(3, ®s, 1);
|
||||
svm_debug_restore_cpu_user_regs(®s);
|
||||
break;
|
||||
#else
|
||||
if ( test_bit(_DOMF_debugging, &v->domain->domain_flags) )
|
||||
domain_pause_for_debugger();
|
||||
else
|
||||
svm_inject_exception(vmcb, TRAP_int3, 0, 0);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case VMEXIT_EXCEPTION_NM:
|
||||
svm_do_no_device_fault(vmcb);
|
||||
|
||||
@@ -257,7 +257,8 @@ static int construct_init_vmcb_guest(struct arch_svm_struct *arch_svm,
|
||||
/* CR3 is set in svm_final_setup_guest */
|
||||
|
||||
__asm__ __volatile__ ("mov %%cr4,%0" : "=r" (crn) :);
|
||||
arch_svm->cpu_shadow_cr4 = crn & ~(X86_CR4_PGE | X86_CR4_PSE);
|
||||
crn &= ~(X86_CR4_PGE | X86_CR4_PSE | X86_CR4_PAE);
|
||||
arch_svm->cpu_shadow_cr4 = crn;
|
||||
vmcb->cr4 = crn | SVM_CR4_HOST_MASK;
|
||||
|
||||
vmcb->rsp = 0;
|
||||
@@ -484,6 +485,7 @@ void svm_do_resume(struct vcpu *v)
|
||||
if ( vpit->first_injected ) {
|
||||
if ( v->domain->arch.hvm_domain.guest_time ) {
|
||||
svm_set_guest_time(v, v->domain->arch.hvm_domain.guest_time);
|
||||
vpit->count_point = NOW();
|
||||
v->domain->arch.hvm_domain.guest_time = 0;
|
||||
}
|
||||
pickup_deactive_ticks(vpit);
|
||||
|
||||
@@ -84,7 +84,8 @@ interrupt_post_injection(struct vcpu * v, int vector, int type)
|
||||
} else {
|
||||
vpit->pending_intr_nr--;
|
||||
}
|
||||
vpit->inject_point = NOW();
|
||||
vpit->count_advance = 0;
|
||||
vpit->count_point = NOW();
|
||||
|
||||
vpit->last_pit_gtime += vpit->period_cycles;
|
||||
set_guest_time(v, vpit->last_pit_gtime);
|
||||
@@ -208,6 +209,7 @@ void vmx_do_resume(struct vcpu *v)
|
||||
/* pick up the elapsed PIT ticks and re-enable pit_timer */
|
||||
if ( vpit->first_injected ) {
|
||||
if ( v->domain->arch.hvm_domain.guest_time ) {
|
||||
vpit->count_point = NOW();
|
||||
set_guest_time(v, v->domain->arch.hvm_domain.guest_time);
|
||||
v->domain->arch.hvm_domain.guest_time = 0;
|
||||
}
|
||||
|
||||
@@ -362,6 +362,7 @@ static void vmx_freeze_time(struct vcpu *v)
|
||||
|
||||
if ( vpit->first_injected && !v->domain->arch.hvm_domain.guest_time ) {
|
||||
v->domain->arch.hvm_domain.guest_time = get_guest_time(v);
|
||||
vpit->count_advance += (NOW() - vpit->count_point);
|
||||
stop_timer(&(vpit->pit_timer));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +94,7 @@
|
||||
ENTRY(vmx_asm_vmexit_handler)
|
||||
/* selectors are restored/saved by VMX */
|
||||
HVM_SAVE_ALL_NOSEGREGS
|
||||
call vmx_trace_vmexit
|
||||
call vmx_vmexit_handler
|
||||
jmp vmx_asm_do_resume
|
||||
|
||||
@@ -114,6 +115,7 @@ ENTRY(vmx_asm_vmexit_handler)
|
||||
/* vmx_restore_all_guest */
|
||||
call vmx_intr_assist
|
||||
call vmx_load_cr2
|
||||
call vmx_trace_vmentry
|
||||
.endif
|
||||
/*
|
||||
* Check if we are going back to VMX-based VM
|
||||
|
||||
@@ -318,7 +318,7 @@ void __init init_8259A(int auto_eoi)
|
||||
* outb_p - this has to work on a wide range of PC hardware.
|
||||
*/
|
||||
outb_p(0x11, 0x20); /* ICW1: select 8259A-1 init */
|
||||
outb_p(0x20 + 0, 0x21); /* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */
|
||||
outb_p(FIRST_LEGACY_VECTOR + 0, 0x21); /* ICW2: 8259A-1 IR0-7 */
|
||||
outb_p(0x04, 0x21); /* 8259A-1 (the master) has a slave on IR2 */
|
||||
if (auto_eoi)
|
||||
outb_p(0x03, 0x21); /* master does Auto EOI */
|
||||
@@ -326,7 +326,7 @@ void __init init_8259A(int auto_eoi)
|
||||
outb_p(0x01, 0x21); /* master expects normal EOI */
|
||||
|
||||
outb_p(0x11, 0xA0); /* ICW1: select 8259A-2 init */
|
||||
outb_p(0x20 + 8, 0xA1); /* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */
|
||||
outb_p(FIRST_LEGACY_VECTOR + 8, 0xA1); /* ICW2: 8259A-2 IR0-7 */
|
||||
outb_p(0x02, 0xA1); /* 8259A-2 is a slave on master's IR2 */
|
||||
outb_p(0x01, 0xA1); /* (slave's support for AEOI in flat mode
|
||||
is to be investigated) */
|
||||
|
||||
+67
-7
@@ -657,11 +657,11 @@ static inline int IO_APIC_irq_trigger(int irq)
|
||||
}
|
||||
|
||||
/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
|
||||
u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 };
|
||||
u8 irq_vector[NR_IRQ_VECTORS] __read_mostly;
|
||||
|
||||
int assign_irq_vector(int irq)
|
||||
{
|
||||
static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
|
||||
static int current_vector = FIRST_DYNAMIC_VECTOR, offset = 0;
|
||||
|
||||
BUG_ON(irq >= NR_IRQ_VECTORS);
|
||||
if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0)
|
||||
@@ -677,11 +677,11 @@ next:
|
||||
if (current_vector == 0x80)
|
||||
goto next;
|
||||
|
||||
if (current_vector >= FIRST_SYSTEM_VECTOR) {
|
||||
if (current_vector > LAST_DYNAMIC_VECTOR) {
|
||||
offset++;
|
||||
if (!(offset%8))
|
||||
return -ENOSPC;
|
||||
current_vector = FIRST_DEVICE_VECTOR + offset;
|
||||
current_vector = FIRST_DYNAMIC_VECTOR + offset;
|
||||
}
|
||||
|
||||
vector_irq[current_vector] = irq;
|
||||
@@ -1321,11 +1321,26 @@ static unsigned int startup_level_ioapic_irq (unsigned int irq)
|
||||
return 0; /* don't check for pending */
|
||||
}
|
||||
|
||||
int ioapic_ack_new = 1;
|
||||
static void setup_ioapic_ack(char *s)
|
||||
{
|
||||
if ( !strcmp(s, "old") )
|
||||
ioapic_ack_new = 0;
|
||||
else if ( !strcmp(s, "new") )
|
||||
ioapic_ack_new = 1;
|
||||
else
|
||||
printk("Unknown ioapic_ack value specified: '%s'\n", s);
|
||||
}
|
||||
custom_param("ioapic_ack", setup_ioapic_ack);
|
||||
|
||||
static void mask_and_ack_level_ioapic_irq (unsigned int irq)
|
||||
{
|
||||
unsigned long v;
|
||||
int i;
|
||||
|
||||
if ( ioapic_ack_new )
|
||||
return;
|
||||
|
||||
mask_IO_APIC_irq(irq);
|
||||
/*
|
||||
* It appears there is an erratum which affects at least version 0x11
|
||||
@@ -1363,7 +1378,51 @@ static void mask_and_ack_level_ioapic_irq (unsigned int irq)
|
||||
|
||||
static void end_level_ioapic_irq (unsigned int irq)
|
||||
{
|
||||
unmask_IO_APIC_irq(irq);
|
||||
unsigned long v;
|
||||
int i;
|
||||
|
||||
if ( !ioapic_ack_new )
|
||||
{
|
||||
if ( !(irq_desc[IO_APIC_VECTOR(irq)].status & IRQ_DISABLED) )
|
||||
unmask_IO_APIC_irq(irq);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* It appears there is an erratum which affects at least version 0x11
|
||||
* of I/O APIC (that's the 82093AA and cores integrated into various
|
||||
* chipsets). Under certain conditions a level-triggered interrupt is
|
||||
* erroneously delivered as edge-triggered one but the respective IRR
|
||||
* bit gets set nevertheless. As a result the I/O unit expects an EOI
|
||||
* message but it will never arrive and further interrupts are blocked
|
||||
* from the source. The exact reason is so far unknown, but the
|
||||
* phenomenon was observed when two consecutive interrupt requests
|
||||
* from a given source get delivered to the same CPU and the source is
|
||||
* temporarily disabled in between.
|
||||
*
|
||||
* A workaround is to simulate an EOI message manually. We achieve it
|
||||
* by setting the trigger mode to edge and then to level when the edge
|
||||
* trigger mode gets detected in the TMR of a local APIC for a
|
||||
* level-triggered interrupt. We mask the source for the time of the
|
||||
* operation to prevent an edge-triggered interrupt escaping meanwhile.
|
||||
* The idea is from Manfred Spraul. --macro
|
||||
*/
|
||||
i = IO_APIC_VECTOR(irq);
|
||||
|
||||
v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
|
||||
|
||||
ack_APIC_irq();
|
||||
|
||||
if (!(v & (1 << (i & 0x1f)))) {
|
||||
atomic_inc(&irq_mis_count);
|
||||
spin_lock(&ioapic_lock);
|
||||
__mask_IO_APIC_irq(irq);
|
||||
__edge_IO_APIC_irq(irq);
|
||||
__level_IO_APIC_irq(irq);
|
||||
if ( !(irq_desc[IO_APIC_VECTOR(irq)].status & IRQ_DISABLED) )
|
||||
__unmask_IO_APIC_irq(irq);
|
||||
spin_unlock(&ioapic_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int startup_edge_ioapic_vector(unsigned int vector)
|
||||
@@ -1695,6 +1754,7 @@ void __init setup_IO_APIC(void)
|
||||
io_apic_irqs = ~PIC_IRQS;
|
||||
|
||||
printk("ENABLING IO-APIC IRQs\n");
|
||||
printk(" -> Using %s ACK method\n", ioapic_ack_new ? "new" : "old");
|
||||
|
||||
/*
|
||||
* Set up IO-APIC IRQ routing.
|
||||
@@ -1956,9 +2016,9 @@ int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( old_rte.vector >= FIRST_DEVICE_VECTOR )
|
||||
if ( old_rte.vector >= FIRST_DYNAMIC_VECTOR )
|
||||
old_irq = vector_irq[old_rte.vector];
|
||||
if ( new_rte.vector >= FIRST_DEVICE_VECTOR )
|
||||
if ( new_rte.vector >= FIRST_DYNAMIC_VECTOR )
|
||||
new_irq = vector_irq[new_rte.vector];
|
||||
|
||||
if ( (old_irq != new_irq) && (old_irq != -1) && IO_APIC_IRQ(old_irq) )
|
||||
|
||||
+314
-32
@@ -148,48 +148,236 @@ typedef struct {
|
||||
u8 nr_guests;
|
||||
u8 in_flight;
|
||||
u8 shareable;
|
||||
u8 ack_type;
|
||||
#define ACKTYPE_NONE 0 /* No final acknowledgement is required */
|
||||
#define ACKTYPE_UNMASK 1 /* Unmask PIC hardware (from any CPU) */
|
||||
#define ACKTYPE_EOI 2 /* EOI on the CPU that was interrupted */
|
||||
cpumask_t cpu_eoi_map; /* CPUs that need to EOI this interrupt */
|
||||
struct domain *guest[IRQ_MAX_GUESTS];
|
||||
} irq_guest_action_t;
|
||||
|
||||
/*
|
||||
* Stack of interrupts awaiting EOI on each CPU. These must be popped in
|
||||
* order, as only the current highest-priority pending irq can be EOIed.
|
||||
*/
|
||||
static struct {
|
||||
u8 vector; /* Vector awaiting EOI */
|
||||
u8 ready; /* Ready for EOI now? */
|
||||
} pending_eoi[NR_CPUS][NR_VECTORS] __cacheline_aligned;
|
||||
#define pending_eoi_sp(cpu) (pending_eoi[cpu][NR_VECTORS-1].vector)
|
||||
|
||||
static void __do_IRQ_guest(int vector)
|
||||
{
|
||||
unsigned int irq = vector_to_irq(vector);
|
||||
irq_desc_t *desc = &irq_desc[vector];
|
||||
irq_guest_action_t *action = (irq_guest_action_t *)desc->action;
|
||||
struct domain *d;
|
||||
int i;
|
||||
int i, sp, cpu = smp_processor_id();
|
||||
|
||||
if ( unlikely(action->nr_guests == 0) )
|
||||
{
|
||||
/* An interrupt may slip through while freeing an ACKTYPE_EOI irq. */
|
||||
ASSERT(action->ack_type == ACKTYPE_EOI);
|
||||
ASSERT(desc->status & IRQ_DISABLED);
|
||||
desc->handler->end(vector);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( action->ack_type == ACKTYPE_EOI )
|
||||
{
|
||||
sp = pending_eoi_sp(cpu);
|
||||
ASSERT((sp == 0) || (pending_eoi[cpu][sp-1].vector < vector));
|
||||
ASSERT(sp < (NR_VECTORS-1));
|
||||
pending_eoi[cpu][sp].vector = vector;
|
||||
pending_eoi[cpu][sp].ready = 0;
|
||||
pending_eoi_sp(cpu) = sp+1;
|
||||
cpu_set(cpu, action->cpu_eoi_map);
|
||||
}
|
||||
|
||||
for ( i = 0; i < action->nr_guests; i++ )
|
||||
{
|
||||
d = action->guest[i];
|
||||
if ( !test_and_set_bit(irq, &d->pirq_mask) )
|
||||
if ( (action->ack_type != ACKTYPE_NONE) &&
|
||||
!test_and_set_bit(irq, &d->pirq_mask) )
|
||||
action->in_flight++;
|
||||
send_guest_pirq(d, irq);
|
||||
}
|
||||
}
|
||||
|
||||
/* Flush all ready EOIs from the top of this CPU's pending-EOI stack. */
|
||||
static void flush_ready_eoi(void *unused)
|
||||
{
|
||||
irq_desc_t *desc;
|
||||
int vector, sp, cpu = smp_processor_id();
|
||||
|
||||
ASSERT(!local_irq_is_enabled());
|
||||
|
||||
sp = pending_eoi_sp(cpu);
|
||||
|
||||
while ( (--sp >= 0) && pending_eoi[cpu][sp].ready )
|
||||
{
|
||||
vector = pending_eoi[cpu][sp].vector;
|
||||
desc = &irq_desc[vector];
|
||||
spin_lock(&desc->lock);
|
||||
desc->handler->end(vector);
|
||||
spin_unlock(&desc->lock);
|
||||
}
|
||||
|
||||
pending_eoi_sp(cpu) = sp+1;
|
||||
}
|
||||
|
||||
static void __set_eoi_ready(irq_desc_t *desc)
|
||||
{
|
||||
irq_guest_action_t *action = (irq_guest_action_t *)desc->action;
|
||||
int vector, sp, cpu = smp_processor_id();
|
||||
|
||||
vector = desc - irq_desc;
|
||||
|
||||
if ( !(desc->status & IRQ_GUEST) ||
|
||||
(action->in_flight != 0) ||
|
||||
!test_and_clear_bit(cpu, &action->cpu_eoi_map) )
|
||||
return;
|
||||
|
||||
sp = pending_eoi_sp(cpu);
|
||||
do {
|
||||
ASSERT(sp > 0);
|
||||
} while ( pending_eoi[cpu][--sp].vector != vector );
|
||||
ASSERT(!pending_eoi[cpu][sp].ready);
|
||||
pending_eoi[cpu][sp].ready = 1;
|
||||
}
|
||||
|
||||
/* Mark specified IRQ as ready-for-EOI (if it really is) and attempt to EOI. */
|
||||
static void set_eoi_ready(void *data)
|
||||
{
|
||||
irq_desc_t *desc = data;
|
||||
|
||||
ASSERT(!local_irq_is_enabled());
|
||||
|
||||
spin_lock(&desc->lock);
|
||||
__set_eoi_ready(desc);
|
||||
spin_unlock(&desc->lock);
|
||||
|
||||
flush_ready_eoi(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Forcibly flush all pending EOIs on this CPU by emulating end-of-ISR
|
||||
* notifications from guests. The caller of this function must ensure that
|
||||
* all CPUs execute flush_ready_eoi().
|
||||
*/
|
||||
static void flush_all_pending_eoi(void *unused)
|
||||
{
|
||||
irq_desc_t *desc;
|
||||
irq_guest_action_t *action;
|
||||
int i, vector, sp, cpu = smp_processor_id();
|
||||
|
||||
ASSERT(!local_irq_is_enabled());
|
||||
|
||||
sp = pending_eoi_sp(cpu);
|
||||
while ( --sp >= 0 )
|
||||
{
|
||||
if ( pending_eoi[cpu][sp].ready )
|
||||
continue;
|
||||
vector = pending_eoi[cpu][sp].vector;
|
||||
desc = &irq_desc[vector];
|
||||
spin_lock(&desc->lock);
|
||||
action = (irq_guest_action_t *)desc->action;
|
||||
ASSERT(action->ack_type == ACKTYPE_EOI);
|
||||
ASSERT(desc->status & IRQ_GUEST);
|
||||
for ( i = 0; i < action->nr_guests; i++ )
|
||||
clear_bit(vector_to_irq(vector), &action->guest[i]->pirq_mask);
|
||||
action->in_flight = 0;
|
||||
spin_unlock(&desc->lock);
|
||||
}
|
||||
|
||||
flush_ready_eoi(NULL);
|
||||
}
|
||||
|
||||
int pirq_guest_unmask(struct domain *d)
|
||||
{
|
||||
irq_desc_t *desc;
|
||||
unsigned int pirq;
|
||||
shared_info_t *s = d->shared_info;
|
||||
irq_desc_t *desc;
|
||||
irq_guest_action_t *action;
|
||||
cpumask_t cpu_eoi_map = CPU_MASK_NONE;
|
||||
unsigned int pirq, cpu = smp_processor_id();
|
||||
shared_info_t *s = d->shared_info;
|
||||
|
||||
for ( pirq = find_first_bit(d->pirq_mask, NR_PIRQS);
|
||||
pirq < NR_PIRQS;
|
||||
pirq = find_next_bit(d->pirq_mask, NR_PIRQS, pirq+1) )
|
||||
{
|
||||
desc = &irq_desc[irq_to_vector(pirq)];
|
||||
desc = &irq_desc[irq_to_vector(pirq)];
|
||||
action = (irq_guest_action_t *)desc->action;
|
||||
|
||||
spin_lock_irq(&desc->lock);
|
||||
|
||||
if ( !test_bit(d->pirq_to_evtchn[pirq], &s->evtchn_mask[0]) &&
|
||||
test_and_clear_bit(pirq, &d->pirq_mask) &&
|
||||
(--((irq_guest_action_t *)desc->action)->in_flight == 0) )
|
||||
desc->handler->end(irq_to_vector(pirq));
|
||||
spin_unlock_irq(&desc->lock);
|
||||
test_and_clear_bit(pirq, &d->pirq_mask) )
|
||||
{
|
||||
ASSERT(action->ack_type != ACKTYPE_NONE);
|
||||
if ( --action->in_flight == 0 )
|
||||
{
|
||||
if ( action->ack_type == ACKTYPE_UNMASK )
|
||||
desc->handler->end(irq_to_vector(pirq));
|
||||
cpu_eoi_map = action->cpu_eoi_map;
|
||||
}
|
||||
}
|
||||
|
||||
if ( __test_and_clear_bit(cpu, &cpu_eoi_map) )
|
||||
{
|
||||
__set_eoi_ready(desc);
|
||||
spin_unlock(&desc->lock);
|
||||
flush_ready_eoi(NULL);
|
||||
local_irq_enable();
|
||||
}
|
||||
else
|
||||
{
|
||||
spin_unlock_irq(&desc->lock);
|
||||
}
|
||||
|
||||
if ( !cpus_empty(cpu_eoi_map) )
|
||||
{
|
||||
on_selected_cpus(cpu_eoi_map, set_eoi_ready, desc, 1, 0);
|
||||
cpu_eoi_map = CPU_MASK_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern int ioapic_ack_new;
|
||||
int pirq_acktype(int irq)
|
||||
{
|
||||
irq_desc_t *desc;
|
||||
unsigned int vector;
|
||||
|
||||
vector = irq_to_vector(irq);
|
||||
if ( vector == 0 )
|
||||
return ACKTYPE_NONE;
|
||||
|
||||
desc = &irq_desc[vector];
|
||||
|
||||
/*
|
||||
* Edge-triggered IO-APIC interrupts need no final acknowledgement:
|
||||
* we ACK early during interrupt processing.
|
||||
*/
|
||||
if ( !strcmp(desc->handler->typename, "IO-APIC-edge") )
|
||||
return ACKTYPE_NONE;
|
||||
|
||||
/* Legacy PIC interrupts can be acknowledged from any CPU. */
|
||||
if ( !strcmp(desc->handler->typename, "XT-PIC") )
|
||||
return ACKTYPE_UNMASK;
|
||||
|
||||
/*
|
||||
* Level-triggered IO-APIC interrupts need to be acknowledged on the CPU
|
||||
* on which they were received. This is because we tickle the LAPIC to EOI.
|
||||
*/
|
||||
if ( !strcmp(desc->handler->typename, "IO-APIC-level") )
|
||||
return ioapic_ack_new ? ACKTYPE_EOI : ACKTYPE_UNMASK;
|
||||
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pirq_guest_bind(struct vcpu *v, int irq, int will_share)
|
||||
{
|
||||
unsigned int vector;
|
||||
@@ -202,6 +390,7 @@ int pirq_guest_bind(struct vcpu *v, int irq, int will_share)
|
||||
if ( (irq < 0) || (irq >= NR_IRQS) )
|
||||
return -EINVAL;
|
||||
|
||||
retry:
|
||||
vector = irq_to_vector(irq);
|
||||
if ( vector == 0 )
|
||||
return -EINVAL;
|
||||
@@ -230,10 +419,12 @@ int pirq_guest_bind(struct vcpu *v, int irq, int will_share)
|
||||
goto out;
|
||||
}
|
||||
|
||||
action->nr_guests = 0;
|
||||
action->in_flight = 0;
|
||||
action->shareable = will_share;
|
||||
|
||||
action->nr_guests = 0;
|
||||
action->in_flight = 0;
|
||||
action->shareable = will_share;
|
||||
action->ack_type = pirq_acktype(irq);
|
||||
action->cpu_eoi_map = CPU_MASK_NONE;
|
||||
|
||||
desc->depth = 0;
|
||||
desc->status |= IRQ_GUEST;
|
||||
desc->status &= ~IRQ_DISABLED;
|
||||
@@ -251,6 +442,18 @@ int pirq_guest_bind(struct vcpu *v, int irq, int will_share)
|
||||
rc = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
else if ( action->nr_guests == 0 )
|
||||
{
|
||||
/*
|
||||
* Indicates that an ACKTYPE_EOI interrupt is being released.
|
||||
* Wait for that to happen before continuing.
|
||||
*/
|
||||
ASSERT(action->ack_type == ACKTYPE_EOI);
|
||||
ASSERT(desc->status & IRQ_DISABLED);
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
cpu_relax();
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if ( action->nr_guests == IRQ_MAX_GUESTS )
|
||||
{
|
||||
@@ -271,6 +474,7 @@ int pirq_guest_unbind(struct domain *d, int irq)
|
||||
unsigned int vector = irq_to_vector(irq);
|
||||
irq_desc_t *desc = &irq_desc[vector];
|
||||
irq_guest_action_t *action;
|
||||
cpumask_t cpu_eoi_map;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
@@ -280,28 +484,68 @@ int pirq_guest_unbind(struct domain *d, int irq)
|
||||
|
||||
action = (irq_guest_action_t *)desc->action;
|
||||
|
||||
if ( test_and_clear_bit(irq, &d->pirq_mask) &&
|
||||
(--action->in_flight == 0) )
|
||||
desc->handler->end(vector);
|
||||
i = 0;
|
||||
while ( action->guest[i] && (action->guest[i] != d) )
|
||||
i++;
|
||||
memmove(&action->guest[i], &action->guest[i+1], IRQ_MAX_GUESTS-i-1);
|
||||
action->nr_guests--;
|
||||
|
||||
if ( action->nr_guests == 1 )
|
||||
switch ( action->ack_type )
|
||||
{
|
||||
desc->action = NULL;
|
||||
xfree(action);
|
||||
desc->depth = 1;
|
||||
desc->status |= IRQ_DISABLED;
|
||||
desc->status &= ~IRQ_GUEST;
|
||||
desc->handler->shutdown(vector);
|
||||
}
|
||||
else
|
||||
{
|
||||
i = 0;
|
||||
while ( action->guest[i] && (action->guest[i] != d) )
|
||||
i++;
|
||||
memmove(&action->guest[i], &action->guest[i+1], IRQ_MAX_GUESTS-i-1);
|
||||
action->nr_guests--;
|
||||
case ACKTYPE_UNMASK:
|
||||
if ( test_and_clear_bit(irq, &d->pirq_mask) &&
|
||||
(--action->in_flight == 0) )
|
||||
desc->handler->end(vector);
|
||||
break;
|
||||
case ACKTYPE_EOI:
|
||||
/* NB. If #guests == 0 then we clear the eoi_map later on. */
|
||||
if ( test_and_clear_bit(irq, &d->pirq_mask) &&
|
||||
(--action->in_flight == 0) &&
|
||||
(action->nr_guests != 0) )
|
||||
{
|
||||
cpu_eoi_map = action->cpu_eoi_map;
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
on_selected_cpus(cpu_eoi_map, set_eoi_ready, desc, 1, 0);
|
||||
spin_lock_irqsave(&desc->lock, flags);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
BUG_ON(test_bit(irq, &d->pirq_mask));
|
||||
|
||||
if ( action->nr_guests != 0 )
|
||||
goto out;
|
||||
|
||||
BUG_ON(action->in_flight != 0);
|
||||
|
||||
/* Disabling IRQ before releasing the desc_lock avoids an IRQ storm. */
|
||||
desc->depth = 1;
|
||||
desc->status |= IRQ_DISABLED;
|
||||
desc->handler->disable(vector);
|
||||
|
||||
/*
|
||||
* We may have a EOI languishing anywhere in one of the per-CPU
|
||||
* EOI stacks. Forcibly flush the stack on every CPU where this might
|
||||
* be the case.
|
||||
*/
|
||||
cpu_eoi_map = action->cpu_eoi_map;
|
||||
if ( !cpus_empty(cpu_eoi_map) )
|
||||
{
|
||||
BUG_ON(action->ack_type != ACKTYPE_EOI);
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
on_selected_cpus(cpu_eoi_map, flush_all_pending_eoi, NULL, 1, 1);
|
||||
on_selected_cpus(cpu_online_map, flush_ready_eoi, NULL, 1, 1);
|
||||
spin_lock_irqsave(&desc->lock, flags);
|
||||
}
|
||||
|
||||
BUG_ON(!cpus_empty(action->cpu_eoi_map));
|
||||
|
||||
desc->action = NULL;
|
||||
xfree(action);
|
||||
desc->status &= ~IRQ_GUEST;
|
||||
desc->handler->shutdown(vector);
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
@@ -373,3 +617,41 @@ static int __init setup_dump_irqs(void)
|
||||
return 0;
|
||||
}
|
||||
__initcall(setup_dump_irqs);
|
||||
|
||||
static struct timer end_irq_timer[NR_CPUS];
|
||||
|
||||
/*
|
||||
* force_intack: Forcibly emit all pending EOIs on each CPU every second.
|
||||
* Mainly useful for debugging or poking lazy guests ISRs.
|
||||
*/
|
||||
|
||||
static void end_irq_timeout(void *unused)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
local_irq_disable();
|
||||
flush_all_pending_eoi(NULL);
|
||||
local_irq_enable();
|
||||
|
||||
on_selected_cpus(cpu_online_map, flush_ready_eoi, NULL, 1, 0);
|
||||
|
||||
set_timer(&end_irq_timer[cpu], NOW() + MILLISECS(1000));
|
||||
}
|
||||
|
||||
static void __init __setup_irq_timeout(void *unused)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
init_timer(&end_irq_timer[cpu], end_irq_timeout, NULL, cpu);
|
||||
set_timer(&end_irq_timer[cpu], NOW() + MILLISECS(1000));
|
||||
}
|
||||
|
||||
static int force_intack;
|
||||
boolean_param("force_intack", force_intack);
|
||||
|
||||
static int __init setup_irq_timeout(void)
|
||||
{
|
||||
if ( force_intack )
|
||||
on_each_cpu(__setup_irq_timeout, NULL, 1, 1);
|
||||
return 0;
|
||||
}
|
||||
__initcall(setup_irq_timeout);
|
||||
@@ -18,6 +18,9 @@ ioapic_guest_read(
|
||||
extern int
|
||||
ioapic_guest_write(
|
||||
unsigned long physbase, unsigned int reg, u32 pval);
|
||||
extern int
|
||||
pirq_acktype(
|
||||
int irq);
|
||||
|
||||
/*
|
||||
* Demuxing hypercall.
|
||||
@@ -43,8 +46,7 @@ long do_physdev_op(GUEST_HANDLE(physdev_op_t) uop)
|
||||
if ( (irq < 0) || (irq >= NR_IRQS) )
|
||||
break;
|
||||
op.u.irq_status_query.flags = 0;
|
||||
/* Edge-triggered interrupts don't need an explicit unmask downcall. */
|
||||
if ( !strstr(irq_desc[irq_to_vector(irq)].handler->typename, "edge") )
|
||||
if ( pirq_acktype(irq) != 0 )
|
||||
op.u.irq_status_query.flags |= PHYSDEVOP_IRQ_NEEDS_UNMASK_NOTIFY;
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
+85
-12
@@ -1531,14 +1531,10 @@ static void resync_pae_guest_l3(struct domain *d)
|
||||
|
||||
idx = get_cr3_idxval(v);
|
||||
smfn = __shadow_status(
|
||||
d, ((unsigned long)(idx << PGT_score_shift) | entry->gpfn), PGT_l4_shadow);
|
||||
d, ((unsigned long)(idx << PGT_pae_idx_shift) | entry->gpfn), PGT_l4_shadow);
|
||||
|
||||
#ifndef NDEBUG
|
||||
if ( !smfn )
|
||||
{
|
||||
BUG();
|
||||
}
|
||||
#endif
|
||||
continue;
|
||||
|
||||
guest = (pgentry_64_t *)map_domain_page(entry->gmfn);
|
||||
snapshot = (pgentry_64_t *)map_domain_page(entry->snapshot_mfn);
|
||||
@@ -1550,9 +1546,35 @@ static void resync_pae_guest_l3(struct domain *d)
|
||||
if ( entry_has_changed(
|
||||
guest[index], snapshot[index], PAGE_FLAG_MASK) )
|
||||
{
|
||||
unsigned long gpfn;
|
||||
|
||||
/*
|
||||
* Looks like it's no longer a page table.
|
||||
*/
|
||||
if ( unlikely(entry_get_value(guest[index]) & PAE_PDPT_RESERVED) )
|
||||
{
|
||||
if ( entry_get_flags(shadow_l3[i]) & _PAGE_PRESENT )
|
||||
put_shadow_ref(entry_get_pfn(shadow_l3[i]));
|
||||
|
||||
shadow_l3[i] = entry_empty();
|
||||
continue;
|
||||
}
|
||||
|
||||
gpfn = entry_get_pfn(guest[index]);
|
||||
|
||||
if ( unlikely(gpfn != (gpfn & PGT_mfn_mask)) )
|
||||
{
|
||||
if ( entry_get_flags(shadow_l3[i]) & _PAGE_PRESENT )
|
||||
put_shadow_ref(entry_get_pfn(shadow_l3[i]));
|
||||
|
||||
shadow_l3[i] = entry_empty();
|
||||
continue;
|
||||
}
|
||||
|
||||
validate_entry_change(d, &guest[index],
|
||||
&shadow_l3[i], PAGING_L3);
|
||||
}
|
||||
|
||||
if ( entry_get_value(guest[index]) != 0 )
|
||||
max = i;
|
||||
|
||||
@@ -1676,6 +1698,19 @@ static int resync_all(struct domain *d, u32 stype)
|
||||
{
|
||||
int error;
|
||||
|
||||
#if CONFIG_PAGING_LEVELS == 4
|
||||
unsigned long gpfn;
|
||||
|
||||
gpfn = guest_l1e_get_paddr(guest1[i]) >> PAGE_SHIFT;
|
||||
|
||||
if ( unlikely(gpfn != (gpfn & PGT_mfn_mask)) )
|
||||
{
|
||||
guest_l1_pgentry_t tmp_gl1e = guest_l1e_empty();
|
||||
validate_pte_change(d, tmp_gl1e, sl1e_p);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
error = validate_pte_change(d, guest1[i], sl1e_p);
|
||||
if ( error == -1 )
|
||||
unshadow_l1 = 1;
|
||||
@@ -1698,6 +1733,7 @@ static int resync_all(struct domain *d, u32 stype)
|
||||
perfc_incrc(resync_l1);
|
||||
perfc_incr_histo(wpt_updates, changed, PT_UPDATES);
|
||||
perfc_incr_histo(l1_entries_checked, max_shadow - min_shadow + 1, PT_UPDATES);
|
||||
|
||||
if ( d->arch.ops->guest_paging_levels >= PAGING_L3 &&
|
||||
unshadow_l1 ) {
|
||||
pgentry_64_t l2e = { 0 };
|
||||
@@ -1804,18 +1840,22 @@ static int resync_all(struct domain *d, u32 stype)
|
||||
for ( i = min_shadow; i <= max_shadow; i++ )
|
||||
{
|
||||
if ( (i < min_snapshot) || (i > max_snapshot) ||
|
||||
entry_has_changed(
|
||||
guest_pt[i], snapshot_pt[i], PAGE_FLAG_MASK) )
|
||||
entry_has_changed(
|
||||
guest_pt[i], snapshot_pt[i], PAGE_FLAG_MASK) )
|
||||
{
|
||||
|
||||
unsigned long gpfn;
|
||||
|
||||
gpfn = entry_get_pfn(guest_pt[i]);
|
||||
/*
|
||||
* Looks like it's longer a page table.
|
||||
* Looks like it's no longer a page table.
|
||||
*/
|
||||
if ( unlikely(gpfn != (gpfn & PGT_mfn_mask)) )
|
||||
{
|
||||
if ( entry_get_flags(shadow_pt[i]) & _PAGE_PRESENT )
|
||||
put_shadow_ref(entry_get_pfn(shadow_pt[i]));
|
||||
shadow_pt[i] = entry_empty();
|
||||
continue;
|
||||
}
|
||||
|
||||
need_flush |= validate_entry_change(
|
||||
d, &guest_pt[i], &shadow_pt[i],
|
||||
@@ -1864,11 +1904,17 @@ static int resync_all(struct domain *d, u32 stype)
|
||||
unsigned long gpfn;
|
||||
|
||||
gpfn = l4e_get_pfn(new_root_e);
|
||||
|
||||
/*
|
||||
* Looks like it's longer a page table.
|
||||
* Looks like it's no longer a page table.
|
||||
*/
|
||||
if ( unlikely(gpfn != (gpfn & PGT_mfn_mask)) )
|
||||
{
|
||||
if ( l4e_get_flags(shadow4[i]) & _PAGE_PRESENT )
|
||||
put_shadow_ref(l4e_get_pfn(shadow4[i]));
|
||||
shadow4[i] = l4e_empty();
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( d->arch.ops->guest_paging_levels == PAGING_L4 )
|
||||
{
|
||||
@@ -2372,7 +2418,7 @@ static void shadow_update_pagetables(struct vcpu *v)
|
||||
if ( SH_GUEST_32PAE && d->arch.ops->guest_paging_levels == PAGING_L3 )
|
||||
{
|
||||
u32 index = get_cr3_idxval(v);
|
||||
gpfn = (index << PGT_score_shift) | gpfn;
|
||||
gpfn = ((unsigned long)index << PGT_pae_idx_shift) | gpfn;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -3233,8 +3279,35 @@ update_top_level_shadow(struct vcpu *v, unsigned long smfn)
|
||||
int i;
|
||||
|
||||
for ( i = 0; i < PAE_L3_PAGETABLE_ENTRIES; i++ )
|
||||
{
|
||||
unsigned long gpfn;
|
||||
|
||||
/*
|
||||
* Looks like it's no longer a page table.
|
||||
*/
|
||||
if ( unlikely(entry_get_value(gple[index*4+i]) & PAE_PDPT_RESERVED) )
|
||||
{
|
||||
if ( entry_get_flags(sple[i]) & _PAGE_PRESENT )
|
||||
put_shadow_ref(entry_get_pfn(sple[i]));
|
||||
|
||||
sple[i] = entry_empty();
|
||||
continue;
|
||||
}
|
||||
|
||||
gpfn = entry_get_pfn(gple[index*4+i]);
|
||||
|
||||
if ( unlikely(gpfn != (gpfn & PGT_mfn_mask)) )
|
||||
{
|
||||
if ( entry_get_flags(sple[i]) & _PAGE_PRESENT )
|
||||
put_shadow_ref(entry_get_pfn(sple[i]));
|
||||
|
||||
sple[i] = entry_empty();
|
||||
continue;
|
||||
}
|
||||
|
||||
validate_entry_change(
|
||||
v->domain, &gple[index*4+i], &sple[i], PAGING_L3);
|
||||
}
|
||||
|
||||
unmap_domain_page(sple);
|
||||
}
|
||||
|
||||
+35
-9
@@ -583,6 +583,13 @@ static void free_shadow_pages(struct domain *d)
|
||||
{
|
||||
put_shadow_ref(pagetable_get_pfn(v->arch.shadow_table));
|
||||
v->arch.shadow_table = mk_pagetable(0);
|
||||
|
||||
if ( shadow_mode_external(d) )
|
||||
{
|
||||
if ( v->arch.shadow_vtable )
|
||||
unmap_domain_page_global(v->arch.shadow_vtable);
|
||||
v->arch.shadow_vtable = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ( v->arch.monitor_shadow_ref )
|
||||
@@ -2886,7 +2893,7 @@ int shadow_fault(unsigned long va, struct cpu_user_regs *regs)
|
||||
SH_VVLOG("shadow_fault( va=%lx, code=%lu )",
|
||||
va, (unsigned long)regs->error_code);
|
||||
perfc_incrc(shadow_fault_calls);
|
||||
|
||||
|
||||
check_pagetable(v, "pre-sf");
|
||||
|
||||
/*
|
||||
@@ -2917,7 +2924,16 @@ int shadow_fault(unsigned long va, struct cpu_user_regs *regs)
|
||||
// the mapping is in-sync, so the check of the PDE's present bit, above,
|
||||
// covers this access.
|
||||
//
|
||||
orig_gpte = gpte = linear_pg_table[l1_linear_offset(va)];
|
||||
if ( __copy_from_user(&gpte,
|
||||
&linear_pg_table[l1_linear_offset(va)],
|
||||
sizeof(gpte)) ) {
|
||||
printk("%s() failed, crashing domain %d "
|
||||
"due to a unaccessible linear page table (gpde=%" PRIpte "), va=%lx\n",
|
||||
__func__, d->domain_id, l2e_get_intpte(gpde), va);
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
orig_gpte = gpte;
|
||||
|
||||
if ( unlikely(!(l1e_get_flags(gpte) & _PAGE_PRESENT)) )
|
||||
{
|
||||
SH_VVLOG("shadow_fault - EXIT: gpte not present (%" PRIpte ") (gpde %" PRIpte ")",
|
||||
@@ -2928,7 +2944,7 @@ int shadow_fault(unsigned long va, struct cpu_user_regs *regs)
|
||||
}
|
||||
|
||||
/* Write fault? */
|
||||
if ( regs->error_code & 2 )
|
||||
if ( regs->error_code & 2 )
|
||||
{
|
||||
int allow_writes = 0;
|
||||
|
||||
@@ -2942,7 +2958,7 @@ int shadow_fault(unsigned long va, struct cpu_user_regs *regs)
|
||||
else
|
||||
{
|
||||
/* Write fault on a read-only mapping. */
|
||||
SH_VVLOG("shadow_fault - EXIT: wr fault on RO page (%" PRIpte ")",
|
||||
SH_VVLOG("shadow_fault - EXIT: wr fault on RO page (%" PRIpte ")",
|
||||
l1e_get_intpte(gpte));
|
||||
perfc_incrc(shadow_fault_bail_ro_mapping);
|
||||
goto fail;
|
||||
@@ -2955,10 +2971,10 @@ int shadow_fault(unsigned long va, struct cpu_user_regs *regs)
|
||||
}
|
||||
|
||||
/* User access violation in guest? */
|
||||
if ( unlikely((regs->error_code & 4) &&
|
||||
if ( unlikely((regs->error_code & 4) &&
|
||||
!(l1e_get_flags(gpte) & _PAGE_USER)))
|
||||
{
|
||||
SH_VVLOG("shadow_fault - EXIT: wr fault on super page (%" PRIpte ")",
|
||||
SH_VVLOG("shadow_fault - EXIT: wr fault on super page (%" PRIpte ")",
|
||||
l1e_get_intpte(gpte));
|
||||
goto fail;
|
||||
|
||||
@@ -2980,7 +2996,7 @@ int shadow_fault(unsigned long va, struct cpu_user_regs *regs)
|
||||
/* Read-protection violation in guest? */
|
||||
if ( unlikely((regs->error_code & 1) ))
|
||||
{
|
||||
SH_VVLOG("shadow_fault - EXIT: read fault on super page (%" PRIpte ")",
|
||||
SH_VVLOG("shadow_fault - EXIT: read fault on super page (%" PRIpte ")",
|
||||
l1e_get_intpte(gpte));
|
||||
goto fail;
|
||||
|
||||
@@ -3275,19 +3291,29 @@ void __update_pagetables(struct vcpu *v)
|
||||
|
||||
void clear_all_shadow_status(struct domain *d)
|
||||
{
|
||||
struct vcpu *v = current;
|
||||
|
||||
/*
|
||||
* Don't clean up while other vcpus are working.
|
||||
*/
|
||||
if ( v->vcpu_id )
|
||||
return;
|
||||
|
||||
shadow_lock(d);
|
||||
|
||||
free_shadow_pages(d);
|
||||
free_shadow_ht_entries(d);
|
||||
d->arch.shadow_ht =
|
||||
d->arch.shadow_ht =
|
||||
xmalloc_array(struct shadow_status, shadow_ht_buckets);
|
||||
if ( d->arch.shadow_ht == NULL ) {
|
||||
printk("clear all shadow status:xmalloc fail\n");
|
||||
printk("clear all shadow status: xmalloc failed\n");
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
memset(d->arch.shadow_ht, 0,
|
||||
shadow_ht_buckets * sizeof(struct shadow_status));
|
||||
|
||||
free_out_of_sync_entries(d);
|
||||
|
||||
shadow_unlock(d);
|
||||
}
|
||||
|
||||
|
||||
@@ -102,6 +102,15 @@ void free_shadow_pages(struct domain *d);
|
||||
|
||||
int shadow_set_guest_paging_levels(struct domain *d, int levels)
|
||||
{
|
||||
struct vcpu *v = current;
|
||||
|
||||
/*
|
||||
* Need to wait for VCPU0 to complete the on-going shadow ops.
|
||||
*/
|
||||
|
||||
if ( v->vcpu_id )
|
||||
return 1;
|
||||
|
||||
shadow_lock(d);
|
||||
|
||||
switch(levels) {
|
||||
@@ -692,7 +701,6 @@ void free_fake_shadow_l2(struct domain *d, unsigned long smfn)
|
||||
void free_shadow_page(unsigned long smfn)
|
||||
{
|
||||
struct page_info *page = mfn_to_page(smfn);
|
||||
|
||||
unsigned long gmfn = page->u.inuse.type_info & PGT_mfn_mask;
|
||||
struct domain *d = page_get_owner(mfn_to_page(gmfn));
|
||||
unsigned long gpfn = mfn_to_gmfn(d, gmfn);
|
||||
@@ -709,10 +717,9 @@ void free_shadow_page(unsigned long smfn)
|
||||
if ( !mfn )
|
||||
gpfn |= (1UL << 63);
|
||||
}
|
||||
if (d->arch.ops->guest_paging_levels == PAGING_L3)
|
||||
if (type == PGT_l4_shadow ) {
|
||||
gpfn = ((unsigned long)page->tlbflush_timestamp << PGT_score_shift) | gpfn;
|
||||
}
|
||||
if ( d->arch.ops->guest_paging_levels == PAGING_L3 )
|
||||
if ( type == PGT_l4_shadow )
|
||||
gpfn = ((unsigned long)page->tlbflush_timestamp << PGT_pae_idx_shift) | gpfn;
|
||||
#endif
|
||||
|
||||
delete_shadow_status(d, gpfn, gmfn, type);
|
||||
@@ -743,9 +750,24 @@ void free_shadow_page(unsigned long smfn)
|
||||
#if CONFIG_PAGING_LEVELS >= 3
|
||||
case PGT_l2_shadow:
|
||||
case PGT_l3_shadow:
|
||||
shadow_demote(d, gpfn, gmfn);
|
||||
free_shadow_tables(d, smfn, shadow_type_to_level(type));
|
||||
d->arch.shadow_page_count--;
|
||||
break;
|
||||
|
||||
case PGT_l4_shadow:
|
||||
gpfn = gpfn & PGT_mfn_mask;
|
||||
shadow_demote(d, gpfn, gmfn);
|
||||
if ( d->arch.ops->guest_paging_levels == PAGING_L3 )
|
||||
{
|
||||
/*
|
||||
* Since a single PDPT page can have multiple PDPs, it's possible
|
||||
* that shadow_demote() has been already called for gmfn.
|
||||
*/
|
||||
if ( mfn_is_page_table(gmfn) )
|
||||
shadow_demote(d, gpfn, gmfn);
|
||||
} else
|
||||
shadow_demote(d, gpfn, gmfn);
|
||||
|
||||
free_shadow_tables(d, smfn, shadow_type_to_level(type));
|
||||
d->arch.shadow_page_count--;
|
||||
break;
|
||||
@@ -898,6 +920,13 @@ void free_shadow_pages(struct domain *d)
|
||||
{
|
||||
put_shadow_ref(pagetable_get_pfn(v->arch.shadow_table));
|
||||
v->arch.shadow_table = mk_pagetable(0);
|
||||
|
||||
if ( shadow_mode_external(d) )
|
||||
{
|
||||
if ( v->arch.shadow_vtable )
|
||||
unmap_domain_page_global(v->arch.shadow_vtable);
|
||||
v->arch.shadow_vtable = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ( v->arch.monitor_shadow_ref )
|
||||
@@ -2034,7 +2063,16 @@ void shadow_sync_and_drop_references(
|
||||
|
||||
void clear_all_shadow_status(struct domain *d)
|
||||
{
|
||||
struct vcpu *v = current;
|
||||
|
||||
/*
|
||||
* Don't clean up while other vcpus are working.
|
||||
*/
|
||||
if ( v->vcpu_id )
|
||||
return;
|
||||
|
||||
shadow_lock(d);
|
||||
|
||||
free_shadow_pages(d);
|
||||
free_shadow_ht_entries(d);
|
||||
d->arch.shadow_ht =
|
||||
@@ -2047,6 +2085,7 @@ void clear_all_shadow_status(struct domain *d)
|
||||
shadow_ht_buckets * sizeof(struct shadow_status));
|
||||
|
||||
free_out_of_sync_entries(d);
|
||||
|
||||
shadow_unlock(d);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -261,7 +261,7 @@ int smp_call_function(
|
||||
return on_selected_cpus(allbutself, func, info, retry, wait);
|
||||
}
|
||||
|
||||
extern int on_selected_cpus(
|
||||
int on_selected_cpus(
|
||||
cpumask_t selected,
|
||||
void (*func) (void *info),
|
||||
void *info,
|
||||
|
||||
+16
-2
@@ -41,6 +41,7 @@
|
||||
#include <xen/irq.h>
|
||||
#include <xen/delay.h>
|
||||
#include <xen/softirq.h>
|
||||
#include <xen/serial.h>
|
||||
#include <asm/current.h>
|
||||
#include <asm/mc146818rtc.h>
|
||||
#include <asm/desc.h>
|
||||
@@ -1231,12 +1232,25 @@ void __init smp_cpus_done(unsigned int max_cpus)
|
||||
|
||||
void __init smp_intr_init(void)
|
||||
{
|
||||
int irq, seridx;
|
||||
|
||||
/*
|
||||
* IRQ0 must be given a fixed assignment and initialized,
|
||||
* because it's used before the IO-APIC is set up.
|
||||
*/
|
||||
irq_vector[0] = FIRST_DEVICE_VECTOR;
|
||||
vector_irq[FIRST_DEVICE_VECTOR] = 0;
|
||||
irq_vector[0] = FIRST_HIPRIORITY_VECTOR;
|
||||
vector_irq[FIRST_HIPRIORITY_VECTOR] = 0;
|
||||
|
||||
/*
|
||||
* Also ensure serial interrupts are high priority. We do not
|
||||
* want them to be blocked by unacknowledged guest-bound interrupts.
|
||||
*/
|
||||
for (seridx = 0; seridx < 2; seridx++) {
|
||||
if ((irq = serial_irq(seridx)) < 0)
|
||||
continue;
|
||||
irq_vector[irq] = FIRST_HIPRIORITY_VECTOR + seridx + 1;
|
||||
vector_irq[FIRST_HIPRIORITY_VECTOR + seridx + 1] = irq;
|
||||
}
|
||||
|
||||
/* IPI for event checking. */
|
||||
set_intr_gate(EVENT_CHECK_VECTOR, event_check_interrupt);
|
||||
|
||||
+15
-4
@@ -581,20 +581,31 @@ long do_dom0_op(GUEST_HANDLE(dom0_op_t) u_dom0_op)
|
||||
case DOM0_SETDOMAINMAXMEM:
|
||||
{
|
||||
struct domain *d;
|
||||
unsigned long new_max;
|
||||
|
||||
ret = -ESRCH;
|
||||
d = find_domain_by_id(op->u.setdomainmaxmem.domain);
|
||||
if ( d != NULL )
|
||||
if ( d == NULL )
|
||||
break;
|
||||
|
||||
ret = -EINVAL;
|
||||
new_max = op->u.setdomainmaxmem.max_memkb >> (PAGE_SHIFT-10);
|
||||
|
||||
spin_lock(&d->page_alloc_lock);
|
||||
if ( new_max >= d->tot_pages )
|
||||
{
|
||||
d->max_pages = op->u.setdomainmaxmem.max_memkb >> (PAGE_SHIFT-10);
|
||||
put_domain(d);
|
||||
d->max_pages = new_max;
|
||||
ret = 0;
|
||||
}
|
||||
spin_unlock(&d->page_alloc_lock);
|
||||
|
||||
put_domain(d);
|
||||
}
|
||||
break;
|
||||
|
||||
case DOM0_SETDOMAINHANDLE:
|
||||
{
|
||||
struct domain *d;
|
||||
struct domain *d;
|
||||
ret = -ESRCH;
|
||||
d = find_domain_by_id(op->u.setdomainhandle.domain);
|
||||
if ( d != NULL )
|
||||
|
||||
+50
-51
@@ -41,21 +41,21 @@
|
||||
|
||||
static inline int
|
||||
get_maptrack_handle(
|
||||
grant_table_t *t)
|
||||
struct grant_table *t)
|
||||
{
|
||||
unsigned int h;
|
||||
if ( unlikely((h = t->maptrack_head) == (t->maptrack_limit - 1)) )
|
||||
return -1;
|
||||
t->maptrack_head = t->maptrack[h].ref_and_flags >> MAPTRACK_REF_SHIFT;
|
||||
t->maptrack_head = t->maptrack[h].ref;
|
||||
t->map_count++;
|
||||
return h;
|
||||
}
|
||||
|
||||
static inline void
|
||||
put_maptrack_handle(
|
||||
grant_table_t *t, int handle)
|
||||
struct grant_table *t, int handle)
|
||||
{
|
||||
t->maptrack[handle].ref_and_flags = t->maptrack_head << MAPTRACK_REF_SHIFT;
|
||||
t->maptrack[handle].ref = t->maptrack_head;
|
||||
t->maptrack_head = handle;
|
||||
t->map_count--;
|
||||
}
|
||||
@@ -76,7 +76,7 @@ __gnttab_map_grant_ref(
|
||||
int handle;
|
||||
unsigned long frame = 0;
|
||||
int rc = GNTST_okay;
|
||||
active_grant_entry_t *act;
|
||||
struct active_grant_entry *act;
|
||||
|
||||
/* Entry details from @rd's shared grant table. */
|
||||
grant_entry_t *sha;
|
||||
@@ -123,9 +123,9 @@ __gnttab_map_grant_ref(
|
||||
/* Get a maptrack handle. */
|
||||
if ( unlikely((handle = get_maptrack_handle(ld->grant_table)) == -1) )
|
||||
{
|
||||
int i;
|
||||
grant_mapping_t *new_mt;
|
||||
grant_table_t *lgt = ld->grant_table;
|
||||
int i;
|
||||
struct grant_mapping *new_mt;
|
||||
struct grant_table *lgt = ld->grant_table;
|
||||
|
||||
if ( (lgt->maptrack_limit << 1) > MAPTRACK_MAX_ENTRIES )
|
||||
{
|
||||
@@ -147,7 +147,7 @@ __gnttab_map_grant_ref(
|
||||
|
||||
memcpy(new_mt, lgt->maptrack, PAGE_SIZE << lgt->maptrack_order);
|
||||
for ( i = lgt->maptrack_limit; i < (lgt->maptrack_limit << 1); i++ )
|
||||
new_mt[i].ref_and_flags = (i+1) << MAPTRACK_REF_SHIFT;
|
||||
new_mt[i].ref = i+1;
|
||||
|
||||
free_xenheap_pages(lgt->maptrack, lgt->maptrack_order);
|
||||
lgt->maptrack = new_mt;
|
||||
@@ -264,10 +264,9 @@ __gnttab_map_grant_ref(
|
||||
|
||||
TRACE_1D(TRC_MEM_PAGE_GRANT_MAP, op->dom);
|
||||
|
||||
ld->grant_table->maptrack[handle].domid = op->dom;
|
||||
ld->grant_table->maptrack[handle].ref_and_flags =
|
||||
(op->ref << MAPTRACK_REF_SHIFT) |
|
||||
(op->flags & MAPTRACK_GNTMAP_MASK);
|
||||
ld->grant_table->maptrack[handle].domid = op->dom;
|
||||
ld->grant_table->maptrack[handle].ref = op->ref;
|
||||
ld->grant_table->maptrack[handle].flags = op->flags;
|
||||
|
||||
op->dev_bus_addr = (u64)frame << PAGE_SHIFT;
|
||||
op->handle = handle;
|
||||
@@ -326,9 +325,9 @@ __gnttab_unmap_grant_ref(
|
||||
domid_t dom;
|
||||
grant_ref_t ref;
|
||||
struct domain *ld, *rd;
|
||||
active_grant_entry_t *act;
|
||||
struct active_grant_entry *act;
|
||||
grant_entry_t *sha;
|
||||
grant_mapping_t *map;
|
||||
struct grant_mapping *map;
|
||||
u16 flags;
|
||||
s16 rc = 0;
|
||||
unsigned long frame;
|
||||
@@ -340,7 +339,7 @@ __gnttab_unmap_grant_ref(
|
||||
map = &ld->grant_table->maptrack[op->handle];
|
||||
|
||||
if ( unlikely(op->handle >= ld->grant_table->maptrack_limit) ||
|
||||
unlikely(!(map->ref_and_flags & MAPTRACK_GNTMAP_MASK)) )
|
||||
unlikely(!map->flags) )
|
||||
{
|
||||
DPRINTK("Bad handle (%d).\n", op->handle);
|
||||
op->status = GNTST_bad_handle;
|
||||
@@ -348,8 +347,8 @@ __gnttab_unmap_grant_ref(
|
||||
}
|
||||
|
||||
dom = map->domid;
|
||||
ref = map->ref_and_flags >> MAPTRACK_REF_SHIFT;
|
||||
flags = map->ref_and_flags & MAPTRACK_GNTMAP_MASK;
|
||||
ref = map->ref;
|
||||
flags = map->flags;
|
||||
|
||||
if ( unlikely((rd = find_domain_by_id(dom)) == NULL) ||
|
||||
unlikely(ld == rd) )
|
||||
@@ -380,7 +379,7 @@ __gnttab_unmap_grant_ref(
|
||||
if ( flags & GNTMAP_device_map )
|
||||
{
|
||||
ASSERT(act->pin & (GNTPIN_devw_mask | GNTPIN_devr_mask));
|
||||
map->ref_and_flags &= ~GNTMAP_device_map;
|
||||
map->flags &= ~GNTMAP_device_map;
|
||||
if ( flags & GNTMAP_readonly )
|
||||
{
|
||||
act->pin -= GNTPIN_devr_inc;
|
||||
@@ -401,7 +400,7 @@ __gnttab_unmap_grant_ref(
|
||||
goto unmap_out;
|
||||
|
||||
ASSERT(act->pin & (GNTPIN_hstw_mask | GNTPIN_hstr_mask));
|
||||
map->ref_and_flags &= ~GNTMAP_host_map;
|
||||
map->flags &= ~GNTMAP_host_map;
|
||||
if ( flags & GNTMAP_readonly )
|
||||
{
|
||||
act->pin -= GNTPIN_hstr_inc;
|
||||
@@ -414,9 +413,9 @@ __gnttab_unmap_grant_ref(
|
||||
}
|
||||
}
|
||||
|
||||
if ( (map->ref_and_flags & (GNTMAP_device_map|GNTMAP_host_map)) == 0 )
|
||||
if ( (map->flags & (GNTMAP_device_map|GNTMAP_host_map)) == 0 )
|
||||
{
|
||||
map->ref_and_flags = 0;
|
||||
map->flags = 0;
|
||||
put_maptrack_handle(ld->grant_table, op->handle);
|
||||
}
|
||||
|
||||
@@ -534,12 +533,12 @@ static int
|
||||
gnttab_prepare_for_transfer(
|
||||
struct domain *rd, struct domain *ld, grant_ref_t ref)
|
||||
{
|
||||
grant_table_t *rgt;
|
||||
grant_entry_t *sha;
|
||||
domid_t sdom;
|
||||
u16 sflags;
|
||||
u32 scombo, prev_scombo;
|
||||
int retries = 0;
|
||||
struct grant_table *rgt;
|
||||
struct grant_entry *sha;
|
||||
domid_t sdom;
|
||||
u16 sflags;
|
||||
u32 scombo, prev_scombo;
|
||||
int retries = 0;
|
||||
|
||||
if ( unlikely((rgt = rd->grant_table) == NULL) ||
|
||||
unlikely(ref >= NR_GRANT_ENTRIES) )
|
||||
@@ -775,10 +774,11 @@ int
|
||||
grant_table_create(
|
||||
struct domain *d)
|
||||
{
|
||||
grant_table_t *t;
|
||||
int i;
|
||||
struct grant_table *t;
|
||||
int i;
|
||||
|
||||
if ( (t = xmalloc(grant_table_t)) == NULL )
|
||||
BUG_ON(MAPTRACK_MAX_ENTRIES < NR_GRANT_ENTRIES);
|
||||
if ( (t = xmalloc(struct grant_table)) == NULL )
|
||||
goto no_mem;
|
||||
|
||||
/* Simple stuff. */
|
||||
@@ -786,19 +786,19 @@ grant_table_create(
|
||||
spin_lock_init(&t->lock);
|
||||
|
||||
/* Active grant table. */
|
||||
if ( (t->active = xmalloc_array(active_grant_entry_t, NR_GRANT_ENTRIES))
|
||||
== NULL )
|
||||
t->active = xmalloc_array(struct active_grant_entry, NR_GRANT_ENTRIES);
|
||||
if ( t->active == NULL )
|
||||
goto no_mem;
|
||||
memset(t->active, 0, sizeof(active_grant_entry_t) * NR_GRANT_ENTRIES);
|
||||
memset(t->active, 0, sizeof(struct active_grant_entry) * NR_GRANT_ENTRIES);
|
||||
|
||||
/* Tracking of mapped foreign frames table */
|
||||
if ( (t->maptrack = alloc_xenheap_page()) == NULL )
|
||||
goto no_mem;
|
||||
t->maptrack_order = 0;
|
||||
t->maptrack_limit = PAGE_SIZE / sizeof(grant_mapping_t);
|
||||
t->maptrack_limit = PAGE_SIZE / sizeof(struct grant_mapping);
|
||||
memset(t->maptrack, 0, PAGE_SIZE);
|
||||
for ( i = 0; i < t->maptrack_limit; i++ )
|
||||
t->maptrack[i].ref_and_flags = (i+1) << MAPTRACK_REF_SHIFT;
|
||||
t->maptrack[i].ref = i+1;
|
||||
|
||||
/* Shared grant table. */
|
||||
t->shared = alloc_xenheap_pages(ORDER_GRANT_FRAMES);
|
||||
@@ -828,27 +828,26 @@ void
|
||||
gnttab_release_mappings(
|
||||
struct domain *d)
|
||||
{
|
||||
grant_table_t *gt = d->grant_table;
|
||||
grant_mapping_t *map;
|
||||
struct grant_table *gt = d->grant_table;
|
||||
struct grant_mapping *map;
|
||||
grant_ref_t ref;
|
||||
grant_handle_t handle;
|
||||
struct domain *rd;
|
||||
active_grant_entry_t *act;
|
||||
grant_entry_t *sha;
|
||||
struct active_grant_entry *act;
|
||||
struct grant_entry *sha;
|
||||
|
||||
BUG_ON(!test_bit(_DOMF_dying, &d->domain_flags));
|
||||
|
||||
for ( handle = 0; handle < gt->maptrack_limit; handle++ )
|
||||
{
|
||||
map = >->maptrack[handle];
|
||||
if ( !(map->ref_and_flags & (GNTMAP_device_map|GNTMAP_host_map)) )
|
||||
if ( !(map->flags & (GNTMAP_device_map|GNTMAP_host_map)) )
|
||||
continue;
|
||||
|
||||
ref = map->ref_and_flags >> MAPTRACK_REF_SHIFT;
|
||||
ref = map->ref;
|
||||
|
||||
DPRINTK("Grant release (%hu) ref:(%hu) flags:(%x) dom:(%hu)\n",
|
||||
handle, ref, map->ref_and_flags & MAPTRACK_GNTMAP_MASK,
|
||||
map->domid);
|
||||
handle, ref, map->flags, map->domid);
|
||||
|
||||
rd = find_domain_by_id(map->domid);
|
||||
BUG_ON(rd == NULL);
|
||||
@@ -858,16 +857,16 @@ gnttab_release_mappings(
|
||||
act = &rd->grant_table->active[ref];
|
||||
sha = &rd->grant_table->shared[ref];
|
||||
|
||||
if ( map->ref_and_flags & GNTMAP_readonly )
|
||||
if ( map->flags & GNTMAP_readonly )
|
||||
{
|
||||
if ( map->ref_and_flags & GNTMAP_device_map )
|
||||
if ( map->flags & GNTMAP_device_map )
|
||||
{
|
||||
BUG_ON(!(act->pin & GNTPIN_devr_mask));
|
||||
act->pin -= GNTPIN_devr_inc;
|
||||
put_page(mfn_to_page(act->frame));
|
||||
}
|
||||
|
||||
if ( map->ref_and_flags & GNTMAP_host_map )
|
||||
if ( map->flags & GNTMAP_host_map )
|
||||
{
|
||||
BUG_ON(!(act->pin & GNTPIN_hstr_mask));
|
||||
act->pin -= GNTPIN_hstr_inc;
|
||||
@@ -877,14 +876,14 @@ gnttab_release_mappings(
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( map->ref_and_flags & GNTMAP_device_map )
|
||||
if ( map->flags & GNTMAP_device_map )
|
||||
{
|
||||
BUG_ON(!(act->pin & GNTPIN_devw_mask));
|
||||
act->pin -= GNTPIN_devw_inc;
|
||||
put_page_and_type(mfn_to_page(act->frame));
|
||||
}
|
||||
|
||||
if ( map->ref_and_flags & GNTMAP_host_map )
|
||||
if ( map->flags & GNTMAP_host_map )
|
||||
{
|
||||
BUG_ON(!(act->pin & GNTPIN_hstw_mask));
|
||||
act->pin -= GNTPIN_hstw_inc;
|
||||
@@ -903,7 +902,7 @@ gnttab_release_mappings(
|
||||
|
||||
put_domain(rd);
|
||||
|
||||
map->ref_and_flags = 0;
|
||||
map->flags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -912,7 +911,7 @@ void
|
||||
grant_table_destroy(
|
||||
struct domain *d)
|
||||
{
|
||||
grant_table_t *t = d->grant_table;
|
||||
struct grant_table *t = d->grant_table;
|
||||
|
||||
if ( t == NULL )
|
||||
return;
|
||||
|
||||
@@ -65,11 +65,12 @@ spinlock_t console_lock = SPIN_LOCK_UNLOCKED;
|
||||
#define COLUMNS 80
|
||||
#define LINES 25
|
||||
#define ATTRIBUTE 7
|
||||
#define VIDEO_SIZE (COLUMNS * LINES * 2)
|
||||
|
||||
/* Clear the screen and initialize VIDEO, XPOS and YPOS. */
|
||||
static void cls(void)
|
||||
{
|
||||
memset(video, 0, COLUMNS * LINES * 2);
|
||||
memset(video, 0, VIDEO_SIZE);
|
||||
xpos = ypos = 0;
|
||||
outw(10+(1<<(5+8)), 0x3d4); /* cursor off */
|
||||
}
|
||||
@@ -107,9 +108,9 @@ static int detect_vga(void)
|
||||
*
|
||||
* These checks are basically to detect headless server boxes.
|
||||
*/
|
||||
return (detect_video(__va(0xA0000)) ||
|
||||
detect_video(__va(0xB0000)) ||
|
||||
detect_video(__va(0xB8000)));
|
||||
return (detect_video(ioremap(0xA0000, VIDEO_SIZE)) ||
|
||||
detect_video(ioremap(0xB0000, VIDEO_SIZE)) ||
|
||||
detect_video(ioremap(0xB8000, VIDEO_SIZE)));
|
||||
}
|
||||
|
||||
/* This is actually code from vgaHWRestore in an old version of XFree86 :-) */
|
||||
@@ -143,7 +144,7 @@ static void init_vga(void)
|
||||
return;
|
||||
}
|
||||
|
||||
video = __va(0xB8000);
|
||||
video = ioremap(0xB8000, VIDEO_SIZE);
|
||||
|
||||
tmp = inb(0x3da);
|
||||
outb(0x00, 0x3c0);
|
||||
@@ -180,12 +181,10 @@ static void put_newline(void)
|
||||
|
||||
if (ypos >= LINES)
|
||||
{
|
||||
static char zeroarr[2*COLUMNS] = { 0 };
|
||||
ypos = LINES-1;
|
||||
memcpy((char*)video,
|
||||
(char*)video + 2*COLUMNS, (LINES-1)*2*COLUMNS);
|
||||
memcpy((char*)video + (LINES-1)*2*COLUMNS,
|
||||
zeroarr, 2*COLUMNS);
|
||||
memmove((char*)video,
|
||||
(char*)video + 2*COLUMNS, (LINES-1)*2*COLUMNS);
|
||||
memset((char*)video + (LINES-1)*2*COLUMNS, 0, 2*COLUMNS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -260,13 +260,20 @@ static void ns16550_endboot(struct serial_port *port)
|
||||
#define ns16550_endboot NULL
|
||||
#endif
|
||||
|
||||
static int ns16550_irq(struct serial_port *port)
|
||||
{
|
||||
struct ns16550 *uart = port->uart;
|
||||
return ((uart->irq > 0) ? uart->irq : -1);
|
||||
}
|
||||
|
||||
static struct uart_driver ns16550_driver = {
|
||||
.init_preirq = ns16550_init_preirq,
|
||||
.init_postirq = ns16550_init_postirq,
|
||||
.endboot = ns16550_endboot,
|
||||
.tx_empty = ns16550_tx_empty,
|
||||
.putc = ns16550_putc,
|
||||
.getc = ns16550_getc
|
||||
.getc = ns16550_getc,
|
||||
.irq = ns16550_irq
|
||||
};
|
||||
|
||||
static int parse_parity_char(int c)
|
||||
|
||||
Loaded 100 of 112 files, more files were not shown because too many files have changed in this diff.
Show more