aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.hgignore4
-rw-r--r--Makefile9
-rw-r--r--buildconfigs/linux-defconfig_xen0_x86_321
-rw-r--r--buildconfigs/linux-defconfig_xenU_x86_321
-rw-r--r--buildconfigs/linux-defconfig_xen_x86_321
-rw-r--r--docs/man/xm.pod.13
-rw-r--r--docs/man/xmdomain.cfg.pod.549
-rw-r--r--docs/xen-api/wire-protocol.tex2
-rw-r--r--extras/mini-os/Makefile160
-rw-r--r--extras/mini-os/arch/x86/Makefile29
-rw-r--r--extras/mini-os/arch/x86/arch.mk28
-rw-r--r--extras/mini-os/arch/x86/minios-x86_32.lds (renamed from extras/mini-os/minios-x86_32.lds)0
-rw-r--r--extras/mini-os/arch/x86/minios-x86_64.lds (renamed from extras/mini-os/minios-x86_64.lds)0
-rw-r--r--extras/mini-os/arch/x86/x86_32.S (renamed from extras/mini-os/x86_32.S)0
-rw-r--r--extras/mini-os/arch/x86/x86_64.S (renamed from extras/mini-os/x86_64.S)0
-rw-r--r--extras/mini-os/gnttab.c32
-rw-r--r--extras/mini-os/include/hypervisor.h1
-rw-r--r--extras/mini-os/include/netfront.h2
-rw-r--r--extras/mini-os/include/x86/x86_32/hypercall-x86_32.h8
-rw-r--r--extras/mini-os/include/x86/x86_64/hypercall-x86_64.h8
-rw-r--r--extras/mini-os/include/xenbus.h3
-rw-r--r--extras/mini-os/kernel.c11
-rw-r--r--extras/mini-os/minios.mk62
-rw-r--r--extras/mini-os/netfront.c455
-rw-r--r--extras/mini-os/xenbus/xenbus.c84
-rw-r--r--linux-2.6-xen-sparse/arch/i386/Kconfig2
-rw-r--r--linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c2
-rw-r--r--linux-2.6-xen-sparse/arch/i386/kernel/pci-dma-xen.c19
-rw-r--r--linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c72
-rw-r--r--linux-2.6-xen-sparse/arch/i386/mm/fault-xen.c18
-rw-r--r--linux-2.6-xen-sparse/arch/i386/mm/highmem-xen.c1
-rw-r--r--linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c28
-rw-r--r--linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c16
-rw-r--r--linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c32
-rw-r--r--linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c30
-rw-r--r--linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c4
-rw-r--r--linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/dma-mapping.h6
-rw-r--r--linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/kmap_types.h31
-rw-r--r--linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgalloc.h2
-rw-r--r--linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/swiotlb.h4
-rw-r--r--linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgalloc.h81
-rw-r--r--linux-2.6-xen-sparse/kernel/kexec.c8
-rw-r--r--patches/linux-2.6.18/ipv6-no-autoconf.patch19
-rw-r--r--patches/linux-2.6.18/series1
-rwxr-xr-xtools/check/check_udev4
-rw-r--r--tools/examples/vtpm-common.sh4
-rw-r--r--tools/examples/xen-network-common.sh5
-rw-r--r--tools/examples/xmexample134
-rw-r--r--tools/examples/xmexample234
-rw-r--r--tools/examples/xmexample334
-rw-r--r--tools/libfsimage/common/fsimage.c2
-rw-r--r--tools/libfsimage/common/fsimage_grub.c2
-rw-r--r--tools/libfsimage/common/fsimage_plugin.c8
-rw-r--r--tools/libfsimage/common/fsimage_plugin.h5
-rw-r--r--tools/libfsimage/common/mapfile-GNU3
-rw-r--r--tools/libfsimage/common/mapfile-SunOS3
-rw-r--r--tools/libfsimage/ext2fs-lib/ext2fs-lib.c2
-rw-r--r--tools/libxc/xc_hvm_build.c3
-rw-r--r--tools/libxc/xc_linux_build.c2
-rw-r--r--tools/libxc/xc_linux_restore.c191
-rw-r--r--tools/libxc/xc_linux_save.c7
-rw-r--r--tools/libxc/xc_load_elf.c14
-rw-r--r--tools/libxc/xc_ptrace.c16
-rw-r--r--tools/pygrub/src/pygrub272
-rw-r--r--tools/python/xen/xend/XendBootloader.py6
-rw-r--r--tools/python/xen/xend/XendCheckpoint.py8
-rw-r--r--tools/python/xen/xend/XendConfig.py10
-rw-r--r--tools/python/xen/xend/XendDomain.py8
-rw-r--r--tools/python/xen/xend/XendDomainInfo.py35
-rw-r--r--tools/python/xen/xend/XendNode.py10
-rw-r--r--tools/python/xen/xend/osdep.py5
-rw-r--r--tools/python/xen/xend/server/blkif.py1
-rw-r--r--tools/python/xen/xm/create.py20
-rw-r--r--tools/tests/Makefile13
-rw-r--r--tools/tests/blowfish.c439
-rw-r--r--tools/tests/blowfish.mk23
-rw-r--r--tools/tests/test_x86_emulator.c132
-rw-r--r--tools/xenstat/xentop/xentop.c2
-rw-r--r--tools/xm-test/README43
-rw-r--r--tools/xm-test/configure.ac1
-rw-r--r--tools/xm-test/grouptest/xapi1
-rw-r--r--tools/xm-test/lib/XmTestLib/DomainTracking.py61
-rw-r--r--tools/xm-test/lib/XmTestLib/XenAPIDomain.py (renamed from tools/xm-test/lib/XmTestLib/XenManagedDomain.py)49
-rw-r--r--tools/xm-test/lib/XmTestLib/XenDomain.py28
-rw-r--r--tools/xm-test/lib/XmTestLib/Xm.py2
-rw-r--r--tools/xm-test/lib/XmTestLib/xapi.py79
-rw-r--r--tools/xm-test/ramdisk/Makefile.am13
-rw-r--r--tools/xm-test/ramdisk/skel/etc/init.d/rcS11
-rwxr-xr-xtools/xm-test/runtest.sh8
-rw-r--r--tools/xm-test/tests/sched-credit/01_sched_credit_weight_cap_pos.py33
-rw-r--r--tools/xm-test/tests/vtpm/09_vtpm-xapi.py99
-rw-r--r--tools/xm-test/tests/xapi/01_xapi-vm_basic.py61
-rw-r--r--tools/xm-test/tests/xapi/Makefile.am19
-rw-r--r--unmodified_drivers/linux-2.6/platform-pci/platform-pci.c28
-rw-r--r--unmodified_drivers/linux-2.6/platform-pci/platform-pci.h4
-rw-r--r--xen/arch/ia64/linux-xen/unaligned.c2
-rw-r--r--xen/arch/ia64/xen/xenmisc.c4
-rw-r--r--xen/arch/x86/domain.c2
-rw-r--r--xen/arch/x86/hvm/hpet.c2
-rw-r--r--xen/arch/x86/hvm/hvm.c2
-rw-r--r--xen/arch/x86/hvm/i8254.c14
-rw-r--r--xen/arch/x86/hvm/irq.c148
-rw-r--r--xen/arch/x86/hvm/svm/svm.c4
-rw-r--r--xen/arch/x86/hvm/vioapic.c11
-rw-r--r--xen/arch/x86/hvm/vmx/vmcs.c9
-rw-r--r--xen/arch/x86/hvm/vmx/vmx.c140
-rw-r--r--xen/arch/x86/hvm/vmx/x86_32/exits.S33
-rw-r--r--xen/arch/x86/hvm/vmx/x86_64/exits.S29
-rw-r--r--xen/arch/x86/microcode.c9
-rw-r--r--xen/arch/x86/mm.c114
-rw-r--r--xen/arch/x86/mm/shadow/common.c27
-rw-r--r--xen/arch/x86/mm/shadow/multi.c6
-rw-r--r--xen/arch/x86/mm/shadow/private.h5
-rw-r--r--xen/arch/x86/oprofile/nmi_int.c2
-rw-r--r--xen/arch/x86/setup.c25
-rw-r--r--xen/arch/x86/traps.c18
-rw-r--r--xen/arch/x86/x86_64/compat/mm.c18
-rw-r--r--xen/arch/x86/x86_emulate.c1009
-rw-r--r--xen/common/elf.c2
-rw-r--r--xen/common/kexec.c114
-rw-r--r--xen/common/keyhandler.c13
-rw-r--r--xen/common/lib.c626
-rw-r--r--xen/common/symbols.c3
-rw-r--r--xen/common/xencomm.c4
-rw-r--r--xen/drivers/video/vga.c7
-rw-r--r--xen/include/Makefile52
-rw-r--r--xen/include/asm-powerpc/byteorder.h80
-rw-r--r--xen/include/asm-x86/byteorder.h36
-rw-r--r--xen/include/asm-x86/guest_access.h18
-rw-r--r--xen/include/asm-x86/hvm/irq.h16
-rw-r--r--xen/include/asm-x86/x86_32/kexec.h1
-rw-r--r--xen/include/asm-x86/x86_64/kexec.h1
-rw-r--r--xen/include/asm-x86/x86_emulate.h23
-rw-r--r--xen/include/public/elfnote.h9
-rw-r--r--xen/include/public/hvm/params.h22
-rw-r--r--xen/include/xen/byteorder/big_endian.h106
-rw-r--r--xen/include/xen/byteorder/generic.h68
-rw-r--r--xen/include/xen/byteorder/little_endian.h106
-rw-r--r--xen/include/xen/byteorder/swab.h185
-rw-r--r--xen/include/xen/config.h2
-rw-r--r--xen/include/xen/elfcore.h57
-rw-r--r--xen/include/xen/types.h7
-rwxr-xr-xxen/tools/compat-build-header.py21
-rwxr-xr-xxen/tools/compat-build-source.py27
-rw-r--r--xen/tools/get-fields.sh53
145 files changed, 4879 insertions, 1639 deletions
diff --git a/.hgignore b/.hgignore
index 0e77280f96..481c9f3745 100644
--- a/.hgignore
+++ b/.hgignore
@@ -58,7 +58,7 @@
^docs/xen-api/xenapi-datamodel-graph.eps$
^extras/mini-os/h/hypervisor-ifs$
^extras/mini-os/h/xen-public$
-^extras/mini-os/mini-os\..*$
+^extras/mini-os/mini-os.*$
^install/.*$
^linux-[^/]*-native/.*$
^linux-[^/]*-xen/.*$
@@ -142,6 +142,8 @@
^tools/python/build/.*$
^tools/security/secpol_tool$
^tools/security/xen/.*$
+^tools/tests/blowfish\.bin$
+^tools/tests/blowfish\.h$
^tools/tests/test_x86_emulator$
^tools/vnet/Make.local$
^tools/vnet/build/.*$
diff --git a/Makefile b/Makefile
index c7004c0ae2..cac9547a3d 100644
--- a/Makefile
+++ b/Makefile
@@ -2,18 +2,15 @@
# Grand Unified Makefile for Xen.
#
-# Export target architecture overrides to Xen and Linux sub-trees.
-ifneq ($(XEN_TARGET_ARCH),)
-SUBARCH := $(subst x86_32,i386,$(XEN_TARGET_ARCH))
-export XEN_TARGET_ARCH SUBARCH XEN_SYSTYPE
-endif
-
# Default target must appear before any include lines
.PHONY: all
all: dist
export XEN_ROOT=$(CURDIR)
include Config.mk
+
+SUBARCH := $(subst x86_32,i386,$(XEN_TARGET_ARCH))
+export XEN_TARGET_ARCH SUBARCH XEN_SYSTYPE
include buildconfigs/Rules.mk
ifeq ($(XEN_TARGET_X86_PAE),y)
diff --git a/buildconfigs/linux-defconfig_xen0_x86_32 b/buildconfigs/linux-defconfig_xen0_x86_32
index 6a999db809..76b2840685 100644
--- a/buildconfigs/linux-defconfig_xen0_x86_32
+++ b/buildconfigs/linux-defconfig_xen0_x86_32
@@ -177,6 +177,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4096
CONFIG_RESOURCES_64BIT=y
+# CONFIG_HIGHPTE is not set
CONFIG_MTRR=y
# CONFIG_REGPARM is not set
CONFIG_SECCOMP=y
diff --git a/buildconfigs/linux-defconfig_xenU_x86_32 b/buildconfigs/linux-defconfig_xenU_x86_32
index 289a73effc..67650c73d5 100644
--- a/buildconfigs/linux-defconfig_xenU_x86_32
+++ b/buildconfigs/linux-defconfig_xenU_x86_32
@@ -174,6 +174,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4096
CONFIG_RESOURCES_64BIT=y
+# CONFIG_HIGHPTE is not set
# CONFIG_REGPARM is not set
CONFIG_SECCOMP=y
CONFIG_HZ_100=y
diff --git a/buildconfigs/linux-defconfig_xen_x86_32 b/buildconfigs/linux-defconfig_xen_x86_32
index 7ac4abd0a2..4928f8d32e 100644
--- a/buildconfigs/linux-defconfig_xen_x86_32
+++ b/buildconfigs/linux-defconfig_xen_x86_32
@@ -182,6 +182,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SPLIT_PTLOCK_CPUS=4096
CONFIG_RESOURCES_64BIT=y
+# CONFIG_HIGHPTE is not set
CONFIG_MTRR=y
CONFIG_REGPARM=y
CONFIG_SECCOMP=y
diff --git a/docs/man/xm.pod.1 b/docs/man/xm.pod.1
index b0ba7f8fb2..3cd8b80ac6 100644
--- a/docs/man/xm.pod.1
+++ b/docs/man/xm.pod.1
@@ -451,6 +451,7 @@ make the man page more readable):
xen_minor : 0
xen_extra : -devel
xen_caps : xen-3.0-x86_32
+ xen_scheduler : credit
xen_pagesize : 4096
platform_params : virt_start=0xfc000000
xen_changeset : Mon Nov 14 18:13:38 2005 +0100
@@ -460,7 +461,7 @@ make the man page more readable):
cc_compile_by : sdague
cc_compile_domain : (none)
cc_compile_date : Mon Nov 14 14:16:48 EST 2005
- xend_config_format : 2
+ xend_config_format : 3
B<FIELDS>
diff --git a/docs/man/xmdomain.cfg.pod.5 b/docs/man/xmdomain.cfg.pod.5
index 03faf68caf..6fe1da79f7 100644
--- a/docs/man/xmdomain.cfg.pod.5
+++ b/docs/man/xmdomain.cfg.pod.5
@@ -135,6 +135,55 @@ one will be randomly chosen by xen with the 00:16:3e vendor id prefix.
=back
+=item B<vfb>
+
+A virtual frame buffer stanza in the form:
+
+ vfb = [ "stanza" ]
+
+The stanza specifies a set of I<name = value> options separated by
+commas, in the form: "name1=value1, name2=value2, ..."
+
+B<OPTIONS>
+
+=over 4
+
+=item I<type>
+
+There are currently two valid options: I<vnc> starts a VNC server that
+lets you connect an external VNC viewer, and I<sdl> starts an internal
+viewer.
+
+=item I<vncdisplay>
+
+The VNC display number to use, defaults to the domain ID. The
+VNC server listens on port 5900 + display number.
+
+=item I<vnclisten>
+
+The listening address for the VNC server, default 127.0.0.1.
+
+=item I<vncunused>
+
+If non-zero, the VNC server listens on the first unused port above
+5900.
+
+=item I<vncpasswd>
+
+Overrides the XenD configured default password.
+
+=item I<display>
+
+Display to use for the internal viewer, defaults to environment
+variable I<DISPLAY>.
+
+=item I<xauthority>
+
+Authority file to use for the internal viewer, defaults to environment
+variable I<XAUTHORITY>.
+
+=back
+
=back
=head1 ADDITIONAL OPTIONS
diff --git a/docs/xen-api/wire-protocol.tex b/docs/xen-api/wire-protocol.tex
index bcb228379e..1548f41c9e 100644
--- a/docs/xen-api/wire-protocol.tex
+++ b/docs/xen-api/wire-protocol.tex
@@ -153,7 +153,7 @@ you must login and initiate a session. For example:
\end{verbatim}
Where {\tt uname} and {\tt password} refer to your username and password
respectively, as defined by the Xen administrator.
-The {\tt session\_id} returned by {\tt session.login_with_password} is passed
+The {\tt session\_id} returned by {\tt session.login\_with\_password} is passed
to subequent RPC calls as an authentication token.
A session can be terminated with the {\tt session.logout} function:
diff --git a/extras/mini-os/Makefile b/extras/mini-os/Makefile
index 01176a625f..ad4ff8d910 100644
--- a/extras/mini-os/Makefile
+++ b/extras/mini-os/Makefile
@@ -1,106 +1,88 @@
-debug ?= y
+# Common Makefile for mini-os.
+#
+# Every architecture directory below mini-os/arch has to have a
+# Makefile and a arch.mk.
+#
+
pae ?= n
XEN_ROOT = ../..
include $(XEN_ROOT)/Config.mk
+XEN_INTERFACE_VERSION := 0x00030204
+export XEN_INTERFACE_VERSION
+
# Set TARGET_ARCH
-override TARGET_ARCH := $(XEN_TARGET_ARCH)
+override TARGET_ARCH := $(XEN_TARGET_ARCH)
-XEN_INTERFACE_VERSION := 0x00030203
+# Set mini-os root path, used in mini-os.mk.
+MINI-OS_ROOT=$(PWD)
+export MINI-OS_ROOT
-# NB. '-Wcast-qual' is nasty, so I omitted it.
-CFLAGS := -fno-builtin -Wall -Werror -Wredundant-decls -Wno-format
-CFLAGS += -Wstrict-prototypes -Wnested-externs -Wpointer-arith -Winline
-CFLAGS += -D__XEN_INTERFACE_VERSION__=$(XEN_INTERFACE_VERSION)
+# Try to find out the architecture family TARGET_ARCH_FAM.
+# First check whether x86_... is contained (for x86_32, x86_32y, x86_64).
+# If not x86 then use $(TARGET_ARCH) -> for ia64, ...
+ifeq ($(findstring x86_,$(TARGET_ARCH)),x86_)
+TARGET_ARCH_FAM = x86
+else
+TARGET_ARCH_FAM = $(TARGET_ARCH)
+endif
-ASFLAGS = -D__ASSEMBLY__
+# The architecture family directory below mini-os.
+TARGET_ARCH_DIR := arch/$(TARGET_ARCH_FAM)
-LDLIBS = -L. -lminios
-LDFLAGS := -N -T minios-$(TARGET_ARCH).lds
+# Export these variables for possible use in architecture dependent makefiles.
+export TARGET_ARCH
+export TARGET_ARCH_DIR
+export TARGET_ARCH_FAM
-# For possible special source directories.
-EXTRA_SRC =
-# For possible special header directories.
-EXTRA_INC =
-
-# Standard name for architecture specific subdirectories.
-TARGET_ARCH_DIR = $(TARGET_ARCH)
# This is used for architecture specific links.
+# This can be overwritten from arch specific rules.
ARCH_LINKS =
-ifeq ($(TARGET_ARCH),x86_32)
-CFLAGS += -m32 -march=i686
-LDFLAGS += -m elf_i386
-TARGET_ARCH_DIR = x86
-EXTRA_INC += $(TARGET_ARCH_DIR)/$(TARGET_ARCH)
-EXTRA_SRC += arch/$(EXTRA_INC)
-endif
+# For possible special header directories.
+# This can be overwritten from arch specific rules.
+EXTRA_INC =
-ifeq ($(TARGET_ARCH)$(pae),x86_32y)
-CFLAGS += -DCONFIG_X86_PAE=1
-ASFLAGS += -DCONFIG_X86_PAE=1
-TARGET_ARCH_DIR = x86
-EXTRA_INC += $(TARGET_ARCH_DIR)/$(TARGET_ARCH)
-EXTRA_SRC += arch/$(EXTRA_INC)
-endif
+# Special build dependencies.
+# Build all after touching this/these file(s) (see minios.mk)
+SPEC_DEPENDS = minios.mk
-ifeq ($(TARGET_ARCH),x86_64)
-CFLAGS += -m64 -mno-red-zone -fpic -fno-reorder-blocks
-CFLAGS += -fno-asynchronous-unwind-tables
-LDFLAGS += -m elf_x86_64
-TARGET_ARCH_DIR = x86
-EXTRA_INC += $(TARGET_ARCH_DIR)/$(TARGET_ARCH)
-EXTRA_SRC += arch/$(EXTRA_INC)
-endif
+# Include the architecture family's special makerules.
+# This must be before include minios.mk!
+include $(TARGET_ARCH_DIR)/arch.mk
-ifeq ($(TARGET_ARCH),ia64)
-CFLAGS += -mfixed-range=f2-f5,f12-f15,f32-f127 -mconstant-gp
-ASFLAGS += -x assembler-with-cpp -Wall
-ASFLAGS += -mfixed-range=f2-f5,f12-f15,f32-f127 -fomit-frame-pointer
-ASFLAGS += -fno-builtin -fno-common -fno-strict-aliasing -mconstant-gp
-ARCH_LINKS = IA64_LINKS # Special link on ia64 needed
-define arch_links
-[ -e include/ia64/asm-xsi-offsets.h ] || ln -sf ../../../../xen/include/asm-ia64/asm-xsi-offsets.h include/ia64/asm-xsi-offsets.h
-endef
-endif
+# Include common mini-os makerules.
+include minios.mk
-ifeq ($(debug),y)
-CFLAGS += -g
-else
-CFLAGS += -O3
-endif
+# Define some default flags for linking.
+LDLIBS :=
+LDFLAGS :=
+LDARCHLIB := -L$(TARGET_ARCH_DIR) -l$(ARCH_LIB_NAME)
+LDFLAGS_FINAL := -N -T $(TARGET_ARCH_DIR)/minios-$(TARGET_ARCH).lds
-# Add the special header directories to the include paths.
-extra_incl := $(foreach dir,$(EXTRA_INC),-Iinclude/$(dir))
-override CPPFLAGS := -Iinclude $(CPPFLAGS) -Iinclude/$(TARGET_ARCH_DIR) $(extra_incl)
+# Prefix for global API names. All other symbols are localised before
+# linking with EXTRA_OBJS.
+GLOBAL_PREFIX := xenos_
+EXTRA_OBJS =
TARGET := mini-os
-HEAD := $(TARGET_ARCH).o
+# Subdirectories common to mini-os
+SUBDIRS := lib xenbus console
+
+# The common mini-os objects to build.
OBJS := $(patsubst %.c,%.o,$(wildcard *.c))
OBJS += $(patsubst %.c,%.o,$(wildcard lib/*.c))
OBJS += $(patsubst %.c,%.o,$(wildcard xenbus/*.c))
OBJS += $(patsubst %.c,%.o,$(wildcard console/*.c))
-OBJS += $(patsubst %.S,%.o,$(wildcard arch/$(TARGET_ARCH_DIR)/*.S))
-OBJS += $(patsubst %.c,%.o,$(wildcard arch/$(TARGET_ARCH_DIR)/*.c))
-# For special wanted source directories.
-extra_objs := $(foreach dir,$(EXTRA_SRC),$(patsubst %.c,%.o,$(wildcard $(dir)/*.c)))
-OBJS += $(extra_objs)
-extra_objs := $(foreach dir,$(EXTRA_SRC),$(patsubst %.S,%.o,$(wildcard $(dir)/*.S)))
-OBJS += $(extra_objs)
-
-HDRS := $(wildcard include/*.h)
-HDRS += $(wildcard include/xen/*.h)
-HDRS += $(wildcard include/$(TARGET_ARCH_DIR)/*.h)
-# For special wanted header directories.
-extra_heads := $(foreach dir,$(EXTRA_INC),$(wildcard $(dir)/*.h))
-HDRS += $(extra_heads)
+
.PHONY: default
default: $(TARGET)
-# Create special architecture specific links.
+# Create special architecture specific links. The function arch_links
+# has to be defined in arch.mk (see include above).
ifneq ($(ARCH_LINKS),)
$(ARCH_LINKS):
$(arch_links)
@@ -110,26 +92,29 @@ endif
links: $(ARCH_LINKS)
[ -e include/xen ] || ln -sf ../../../xen/include/public include/xen
-libminios.a: links $(OBJS) $(HEAD)
- $(AR) r libminios.a $(HEAD) $(OBJS)
+.PHONY: arch_lib
+arch_lib:
+ $(MAKE) --directory=$(TARGET_ARCH_DIR) || exit 1;
+
+$(TARGET): links $(OBJS) arch_lib
+ $(LD) -r $(LDFLAGS) $(HEAD_OBJ) $(OBJS) $(LDARCHLIB) -o $@.o
+ $(OBJCOPY) -w -G $(GLOBAL_PREFIX)* -G _start $@.o $@.o
+ $(LD) $(LDFLAGS) $(LDFLAGS_FINAL) $@.o $(EXTRA_OBJS) -o $@
+ gzip -f -9 -c $@ >$@.gz
+
+.PHONY: clean arch_clean
-$(TARGET): libminios.a $(HEAD)
- $(LD) $(LDFLAGS) $(HEAD) $(LDLIBS) -o $@.elf
- gzip -f -9 -c $@.elf >$@.gz
+arch_clean:
+ $(MAKE) --directory=$(TARGET_ARCH_DIR) clean || exit 1;
-.PHONY: clean
-clean:
- find . -type f -name '*.o' | xargs rm -f
+clean: arch_clean
+ for dir in $(SUBDIRS); do \
+ rm -f $$dir/*.o; \
+ done
rm -f *.o *~ core $(TARGET).elf $(TARGET).raw $(TARGET) $(TARGET).gz
- rm -f libminios.a
find . -type l | xargs rm -f
rm -f tags TAGS
-%.o: %.c $(HDRS) Makefile
- $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
-
-%.o: %.S $(HDRS) Makefile
- $(CC) $(ASFLAGS) $(CPPFLAGS) -c $< -o $@
define all_sources
( find . -follow -name SCCS -prune -o -name '*.[chS]' -print )
@@ -143,3 +128,4 @@ cscope:
.PHONY: tags
tags:
$(all_sources) | xargs ctags
+
diff --git a/extras/mini-os/arch/x86/Makefile b/extras/mini-os/arch/x86/Makefile
new file mode 100644
index 0000000000..45cfe19136
--- /dev/null
+++ b/extras/mini-os/arch/x86/Makefile
@@ -0,0 +1,29 @@
+#
+# x86 architecture specific makefiles.
+# It's is used for x86_32, x86_32y and x86_64
+#
+
+# Rebuild all after touching this/these extra file(s) (see mini-os.mk)
+SPEC_DEP = arch.mk
+
+# include arch.mk has to be before mini-os.mk!
+include arch.mk
+include ../../minios.mk
+
+# Sources here are all *.c *.S without $(TARGET_ARCH).S
+# This is handled in $(HEAD_ARCH_OBJ)
+ARCH_SRCS := $(wildcard *.c)
+
+# The objects built from the sources.
+ARCH_OBJS := $(patsubst %.c,%.o,$(ARCH_SRCS))
+
+all: $(ARCH_LIB)
+
+# $(HEAD_ARCH_OBJ) is only build here, needed on linking
+# in ../../Makefile.
+$(ARCH_LIB): $(ARCH_OBJS) $(HEAD_ARCH_OBJ)
+ $(AR) rv $(ARCH_LIB) $(ARCH_OBJS)
+
+clean:
+ rm -f $(ARCH_LIB) $(ARCH_OBJS)
+
diff --git a/extras/mini-os/arch/x86/arch.mk b/extras/mini-os/arch/x86/arch.mk
new file mode 100644
index 0000000000..5d0ee4add7
--- /dev/null
+++ b/extras/mini-os/arch/x86/arch.mk
@@ -0,0 +1,28 @@
+#
+# Architecture special makerules for x86 family
+# (including x86_32, x86_32y and x86_64).
+#
+
+ifeq ($(TARGET_ARCH),x86_32)
+ARCH_CFLAGS := -m32 -march=i686
+ARCH_LDFLAGS := -m elf_i386
+EXTRA_INC += $(TARGET_ARCH_FAM)/$(TARGET_ARCH)
+EXTRA_SRC += arch/$(EXTRA_INC)
+endif
+
+ifeq ($(TARGET_ARCH)$(pae),x86_32y)
+ARCH_CFLAGS := -DCONFIG_X86_PAE=1
+ARCH_ASFLAGS := -DCONFIG_X86_PAE=1
+EXTRA_INC += $(TARGET_ARCH_FAM)/$(TARGET_ARCH)
+EXTRA_SRC += arch/$(EXTRA_INC)
+endif
+
+ifeq ($(TARGET_ARCH),x86_64)
+ARCH_CFLAGS := -m64 -mno-red-zone -fpic -fno-reorder-blocks
+ARCH_CFLAGS := -fno-asynchronous-unwind-tables
+ARCH_LDFLAGS := -m elf_x86_64
+EXTRA_INC += $(TARGET_ARCH_FAM)/$(TARGET_ARCH)
+EXTRA_SRC += arch/$(EXTRA_INC)
+endif
+
+
diff --git a/extras/mini-os/minios-x86_32.lds b/extras/mini-os/arch/x86/minios-x86_32.lds
index 09d84ad96f..09d84ad96f 100644
--- a/extras/mini-os/minios-x86_32.lds
+++ b/extras/mini-os/arch/x86/minios-x86_32.lds
diff --git a/extras/mini-os/minios-x86_64.lds b/extras/mini-os/arch/x86/minios-x86_64.lds
index e6ef04a511..e6ef04a511 100644
--- a/extras/mini-os/minios-x86_64.lds
+++ b/extras/mini-os/arch/x86/minios-x86_64.lds
diff --git a/extras/mini-os/x86_32.S b/extras/mini-os/arch/x86/x86_32.S
index 46fce169ca..46fce169ca 100644
--- a/extras/mini-os/x86_32.S
+++ b/extras/mini-os/arch/x86/x86_32.S
diff --git a/extras/mini-os/x86_64.S b/extras/mini-os/arch/x86/x86_64.S
index 2b621784ed..2b621784ed 100644
--- a/extras/mini-os/x86_64.S
+++ b/extras/mini-os/arch/x86/x86_64.S
diff --git a/extras/mini-os/gnttab.c b/extras/mini-os/gnttab.c
index 7f9f0096f1..da92fc33c9 100644
--- a/extras/mini-os/gnttab.c
+++ b/extras/mini-os/gnttab.c
@@ -23,31 +23,24 @@
#define NR_GRANT_FRAMES 4
#define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t))
-#define GNTTAB_LIST_END (NR_GRANT_ENTRIES + 1)
static grant_entry_t *gnttab_table;
static grant_ref_t gnttab_list[NR_GRANT_ENTRIES];
-static grant_ref_t gnttab_free_head;
-static grant_ref_t
-get_free_entries(int count)
+static void
+put_free_entry(grant_ref_t ref)
{
- grant_ref_t ref;
- grant_ref_t head;
+ gnttab_list[ref] = gnttab_list[0];
+ gnttab_list[0] = ref;
- ref = head = gnttab_free_head;
- while (count-- > 1)
- head = gnttab_list[head];
- gnttab_free_head = gnttab_list[head];
- gnttab_list[head] = GNTTAB_LIST_END;
- return ref;
}
-static void
-put_free_entry(grant_ref_t gref)
+static grant_ref_t
+get_free_entry(void)
{
- gnttab_list[gref] = gnttab_free_head;
- gnttab_free_head = gref;
+ unsigned int ref = gnttab_list[0];
+ gnttab_list[0] = gnttab_list[ref];
+ return ref;
}
grant_ref_t
@@ -55,7 +48,7 @@ gnttab_grant_access(domid_t domid, unsigned long frame, int readonly)
{
grant_ref_t ref;
- ref = get_free_entries(1);
+ ref = get_free_entry();
gnttab_table[ref].frame = frame;
gnttab_table[ref].domid = domid;
wmb();
@@ -70,7 +63,7 @@ gnttab_grant_transfer(domid_t domid, unsigned long pfn)
{
grant_ref_t ref;
- ref = get_free_entries(1);
+ ref = get_free_entry();
gnttab_table[ref].frame = pfn;
gnttab_table[ref].domid = domid;
wmb();
@@ -157,8 +150,7 @@ init_gnttab(void)
int i;
for (i = NR_RESERVED_ENTRIES; i < NR_GRANT_ENTRIES; i++)
- gnttab_list[i] = i + 1;
- gnttab_free_head = NR_RESERVED_ENTRIES;
+ put_free_entry(i);
setup.dom = DOMID_SELF;
setup.nr_frames = NR_GRANT_FRAMES;
diff --git a/extras/mini-os/include/hypervisor.h b/extras/mini-os/include/hypervisor.h
index e3f149e35f..1b7ea72ac3 100644
--- a/extras/mini-os/include/hypervisor.h
+++ b/extras/mini-os/include/hypervisor.h
@@ -15,7 +15,6 @@
#include <types.h>
#include <xen/xen.h>
-#include <xen/dom0_ops.h>
#if defined(__i386__)
#include <hypercall-x86_32.h>
#elif defined(__x86_64__)
diff --git a/extras/mini-os/include/netfront.h b/extras/mini-os/include/netfront.h
new file mode 100644
index 0000000000..2d3bf5c3fb
--- /dev/null
+++ b/extras/mini-os/include/netfront.h
@@ -0,0 +1,2 @@
+void init_netfront(void*);
+void netfront_xmit(unsigned char* data,int len);
diff --git a/extras/mini-os/include/x86/x86_32/hypercall-x86_32.h b/extras/mini-os/include/x86/x86_32/hypercall-x86_32.h
index 5f8b51f872..9c41c946b2 100644
--- a/extras/mini-os/include/x86/x86_32/hypercall-x86_32.h
+++ b/extras/mini-os/include/x86/x86_32/hypercall-x86_32.h
@@ -182,14 +182,6 @@ HYPERVISOR_set_timer_op(
}
static inline int
-HYPERVISOR_dom0_op(
- dom0_op_t *dom0_op)
-{
- dom0_op->interface_version = DOM0_INTERFACE_VERSION;
- return _hypercall1(int, dom0_op, dom0_op);
-}
-
-static inline int
HYPERVISOR_set_debugreg(
int reg, unsigned long value)
{
diff --git a/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h b/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h
index 2d2904a218..3a4aa049e8 100644
--- a/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h
+++ b/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h
@@ -184,14 +184,6 @@ HYPERVISOR_set_timer_op(
}
static inline int
-HYPERVISOR_dom0_op(
- dom0_op_t *dom0_op)
-{
- dom0_op->interface_version = DOM0_INTERFACE_VERSION;
- return _hypercall1(int, dom0_op, dom0_op);
-}
-
-static inline int
HYPERVISOR_set_debugreg(
int reg, unsigned long value)
{
diff --git a/extras/mini-os/include/xenbus.h b/extras/mini-os/include/xenbus.h
index 4bf35ce8fb..3866a8bbce 100644
--- a/extras/mini-os/include/xenbus.h
+++ b/extras/mini-os/include/xenbus.h
@@ -12,6 +12,9 @@ void init_xenbus(void);
set to a malloc'd copy of the value. */
char *xenbus_read(xenbus_transaction_t xbt, const char *path, char **value);
+char *xenbus_watch_path(xenbus_transaction_t xbt, const char *path);
+char* xenbus_wait_for_value(const char*,const char*);
+
/* Associates a value with a path. Returns a malloc'd error string on
failure. */
char *xenbus_write(xenbus_transaction_t xbt, const char *path, const char *value);
diff --git a/extras/mini-os/kernel.c b/extras/mini-os/kernel.c
index 0799116aa6..4594e25e3c 100644
--- a/extras/mini-os/kernel.c
+++ b/extras/mini-os/kernel.c
@@ -37,6 +37,7 @@
#include <sched.h>
#include <xenbus.h>
#include <gnttab.h>
+#include <netfront.h>
#include <xen/features.h>
#include <xen/version.h>
@@ -61,13 +62,13 @@ void setup_xen_features(void)
void test_xenbus(void);
-void xenbus_tester(void *p)
+static void xenbus_tester(void *p)
{
printk("Xenbus tests disabled, because of a Xend bug.\n");
/* test_xenbus(); */
}
-void periodic_thread(void *p)
+static void periodic_thread(void *p)
{
struct timeval tv;
printk("Periodic thread started.\n");
@@ -79,12 +80,18 @@ void periodic_thread(void *p)
}
}
+static void netfront_thread(void *p)
+{
+ init_netfront(&start_info);
+}
+
/* This should be overridden by the application we are linked against. */
__attribute__((weak)) int app_main(start_info_t *si)
{
printk("Dummy main: start_info=%p\n", si);
create_thread("xenbus_tester", xenbus_tester, si);
create_thread("periodic_thread", periodic_thread, si);
+ create_thread("netfront", netfront_thread, si);
return 0;
}
diff --git a/extras/mini-os/minios.mk b/extras/mini-os/minios.mk
new file mode 100644
index 0000000000..47542a5852
--- /dev/null
+++ b/extras/mini-os/minios.mk
@@ -0,0 +1,62 @@
+#
+# The file contains the common make rules for building mini-os.
+#
+
+debug = y
+
+# Define some default flags.
+# NB. '-Wcast-qual' is nasty, so I omitted it.
+DEF_CFLAGS := -fno-builtin -Wall -Werror -Wredundant-decls -Wno-format
+DEF_CFLAGS += -Wstrict-prototypes -Wnested-externs -Wpointer-arith -Winline
+DEF_CFLAGS += -D__XEN_INTERFACE_VERSION__=$(XEN_INTERFACE_VERSION)
+
+DEF_ASFLAGS = -D__ASSEMBLY__
+
+ifeq ($(debug),y)
+DEF_CFLAGS += -g
+else
+DEF_CFLAGS += -O3
+endif
+
+# Build the CFLAGS and ASFLAGS for compiling and assembling.
+# DEF_... flags are the common mini-os flags,
+# ARCH_... flags may be defined in arch/$(TARGET_ARCH_FAM/rules.mk
+CFLAGS := $(DEF_CFLAGS) $(ARCH_CFLAGS)
+ASFLAGS := $(DEF_ASFLAGS) $(ARCH_ASFLAGS)
+
+# The path pointing to the architecture specific header files.
+ARCH_SPEC_INC := $(MINI-OS_ROOT)/include/$(TARGET_ARCH_FAM)
+
+# Find all header files for checking dependencies.
+HDRS := $(wildcard $(MINI-OS_ROOT)/include/*.h)
+HDRS += $(wildcard $(MINI-OS_ROOT)/include/xen/*.h)
+HDRS += $(wildcard $(ARCH_SPEC_INC)/*.h)
+# For special wanted header directories.
+extra_heads := $(foreach dir,$(EXTRA_INC),$(wildcard $(dir)/*.h))
+HDRS += $(extra_heads)
+
+# Add the special header directories to the include paths.
+extra_incl := $(foreach dir,$(EXTRA_INC),-I$(MINI-OS_ROOT)/include/$(dir))
+override CPPFLAGS := -I$(MINI-OS_ROOT)/include $(CPPFLAGS) -I$(ARCH_SPEC_INC) $(extra_incl)
+
+# The name of the architecture specific library.
+# This is on x86_32: libx86_32.a
+# $(ARCH_LIB) has to built in the architecture specific directory.
+ARCH_LIB_NAME = $(TARGET_ARCH)
+ARCH_LIB := lib$(ARCH_LIB_NAME).a
+
+# This object contains the entrypoint for startup from Xen.
+# $(HEAD_ARCH_OBJ) has to be built in the architecture specific directory.
+HEAD_ARCH_OBJ := $(TARGET_ARCH).o
+HEAD_OBJ := $(TARGET_ARCH_DIR)/$(HEAD_ARCH_OBJ)
+
+
+%.o: %.c $(HDRS) Makefile $(SPEC_DEPENDS)
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
+
+%.o: %.S $(HDRS) Makefile $(SPEC_DEPENDS)
+ $(CC) $(ASFLAGS) $(CPPFLAGS) -c $< -o $@
+
+
+
+
diff --git a/extras/mini-os/netfront.c b/extras/mini-os/netfront.c
new file mode 100644
index 0000000000..a013cdbe80
--- /dev/null
+++ b/extras/mini-os/netfront.c
@@ -0,0 +1,455 @@
+/* Minimal network driver for Mini-OS.
+ * Copyright (c) 2006-2007 Jacob Gorm Hansen, University of Copenhagen.
+ * Based on netfront.c from Xen Linux.
+ *
+ * Does not handle fragments or extras.
+ */
+
+#include <os.h>
+#include <xenbus.h>
+#include <events.h>
+#include <errno.h>
+#include <xen/io/netif.h>
+#include <gnttab.h>
+#include <xmalloc.h>
+#include <time.h>
+
+void init_rx_buffers(void);
+
+struct net_info {
+ struct netif_tx_front_ring tx;
+ struct netif_rx_front_ring rx;
+ int tx_ring_ref;
+ int rx_ring_ref;
+ unsigned int evtchn, local_port;
+
+} net_info;
+
+
+char* xenbus_printf(xenbus_transaction_t xbt,
+ char* node,char* path,
+ char* fmt,unsigned int arg)
+{
+ char fullpath[256];
+ char val[256];
+
+ sprintf(fullpath,"%s/%s",node,path);
+ sprintf(val,fmt,arg);
+ xenbus_write(xbt,fullpath,val);
+
+ return NULL;
+}
+
+
+#define NET_TX_RING_SIZE __RING_SIZE((struct netif_tx_sring *)0, PAGE_SIZE)
+#define NET_RX_RING_SIZE __RING_SIZE((struct netif_rx_sring *)0, PAGE_SIZE)
+#define GRANT_INVALID_REF 0
+
+
+unsigned short rx_freelist[NET_RX_RING_SIZE];
+unsigned short tx_freelist[NET_TX_RING_SIZE];
+
+struct net_buffer {
+ void* page;
+ int gref;
+};
+struct net_buffer rx_buffers[NET_RX_RING_SIZE];
+struct net_buffer tx_buffers[NET_TX_RING_SIZE];
+
+static inline void add_id_to_freelist(unsigned int id,unsigned short* freelist)
+{
+ freelist[id] = freelist[0];
+ freelist[0] = id;
+}
+
+static inline unsigned short get_id_from_freelist(unsigned short* freelist)
+{
+ unsigned int id = freelist[0];
+ freelist[0] = freelist[id];
+ return id;
+}
+
+__attribute__((weak)) void netif_rx(unsigned char* data,int len)
+{
+ printk("%d bytes incoming at %p\n",len,data);
+}
+
+__attribute__((weak)) void net_app_main(void*si,unsigned char*mac) {}
+
+static inline int xennet_rxidx(RING_IDX idx)
+{
+ return idx & (NET_RX_RING_SIZE - 1);
+}
+
+void network_rx(void)
+{
+ struct net_info *np = &net_info;
+ RING_IDX rp,cons;
+ struct netif_rx_response *rx;
+
+
+moretodo:
+ rp = np->rx.sring->rsp_prod;
+ rmb(); /* Ensure we see queued responses up to 'rp'. */
+ cons = np->rx.rsp_cons;
+
+ int nr_consumed=0;
+ while ((cons != rp))
+ {
+ struct net_buffer* buf;
+ unsigned char* page;
+
+ rx = RING_GET_RESPONSE(&np->rx, cons);
+
+ if (rx->flags & NETRXF_extra_info)
+ {
+ printk("+++++++++++++++++++++ we have extras!\n");
+ continue;
+ }
+
+
+ if (rx->status == NETIF_RSP_NULL) continue;
+
+ int id = rx->id;
+
+ buf = &rx_buffers[id];
+ page = (unsigned char*)buf->page;
+ gnttab_end_access(buf->gref);
+
+ if(rx->status>0)
+ {
+ netif_rx(page+rx->offset,rx->status);
+ }
+
+ add_id_to_freelist(id,rx_freelist);
+
+ nr_consumed++;
+
+ ++cons;
+ }
+ np->rx.rsp_cons=rp;
+
+ int more;
+ RING_FINAL_CHECK_FOR_RESPONSES(&np->rx,more);
+ if(more) goto moretodo;
+
+ RING_IDX req_prod = np->rx.req_prod_pvt;
+
+ int i;
+ netif_rx_request_t *req;
+
+ for(i=0; i<nr_consumed; i++)
+ {
+ int id = xennet_rxidx(req_prod + i);
+ req = RING_GET_REQUEST(&np->rx, req_prod + i);
+ struct net_buffer* buf = &rx_buffers[id];
+ void* page = buf->page;
+
+ buf->gref = req->gref =
+ gnttab_grant_access(0,virt_to_mfn(page),0);
+
+ req->id = id;
+ }
+
+ wmb();
+
+ np->rx.req_prod_pvt = req_prod + i;
+
+ int notify;
+ RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->rx, notify);
+ if (notify)
+ notify_remote_via_evtchn(np->evtchn);
+
+}
+
+void network_tx_buf_gc(void)
+{
+
+
+ RING_IDX cons, prod;
+ unsigned short id;
+ struct net_info *np = &net_info;
+
+ do {
+ prod = np->tx.sring->rsp_prod;
+ rmb(); /* Ensure we see responses up to 'rp'. */
+
+ for (cons = np->tx.rsp_cons; cons != prod; cons++)
+ {
+ struct netif_tx_response *txrsp;
+
+ txrsp = RING_GET_RESPONSE(&np->tx, cons);
+ if (txrsp->status == NETIF_RSP_NULL)
+ continue;
+
+ id = txrsp->id;
+ struct net_buffer* buf = &tx_buffers[id];
+ gnttab_end_access(buf->gref);
+ buf->gref=GRANT_INVALID_REF;
+
+ add_id_to_freelist(id,tx_freelist);
+ }
+
+ np->tx.rsp_cons = prod;
+
+ /*
+ * Set a new event, then check for race with update of tx_cons.
+ * Note that it is essential to schedule a callback, no matter
+ * how few tx_buffers are pending. Even if there is space in the
+ * transmit ring, higher layers may be blocked because too much
+ * data is outstanding: in such cases notification from Xen is
+ * likely to be the only kick that we'll get.
+ */
+ np->tx.sring->rsp_event =
+ prod + ((np->tx.sring->req_prod - prod) >> 1) + 1;
+ mb();
+ } while ((cons == prod) && (prod != np->tx.sring->rsp_prod));
+
+
+}
+
+void netfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
+{
+ int flags;
+
+ local_irq_save(flags);
+
+ network_tx_buf_gc();
+ network_rx();
+
+ local_irq_restore(flags);
+}
+
+char* backend;
+
+void init_netfront(void* si)
+{
+ xenbus_transaction_t xbt;
+ struct net_info* info = &net_info;
+ char* err;
+ char* message=NULL;
+ char nodename[] = "device/vif/0";
+ struct netif_tx_sring *txs;
+ struct netif_rx_sring *rxs;
+ int retry=0;
+ int i;
+ char* mac;
+ char* msg;
+
+ printk("************************ NETFRONT **********\n\n\n");
+
+ for(i=0;i<NET_TX_RING_SIZE;i++)
+ {
+ add_id_to_freelist(i,tx_freelist);
+ tx_buffers[i].page = (char*)alloc_page();
+ }
+
+ for(i=0;i<NET_RX_RING_SIZE;i++)
+ {
+ add_id_to_freelist(i,rx_freelist);
+ rx_buffers[i].page = (char*)alloc_page();
+ }
+
+ txs = (struct netif_tx_sring*) alloc_page();
+ rxs = (struct netif_rx_sring *) alloc_page();
+ memset(txs,0,PAGE_SIZE);
+ memset(rxs,0,PAGE_SIZE);
+
+
+ SHARED_RING_INIT(txs);
+ SHARED_RING_INIT(rxs);
+ FRONT_RING_INIT(&info->tx, txs, PAGE_SIZE);
+ FRONT_RING_INIT(&info->rx, rxs, PAGE_SIZE);
+
+ info->tx_ring_ref = gnttab_grant_access(0,virt_to_mfn(txs),0);
+ info->rx_ring_ref = gnttab_grant_access(0,virt_to_mfn(rxs),0);
+
+ evtchn_alloc_unbound_t op;
+ op.dom = DOMID_SELF;
+ op.remote_dom = 0;
+ HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
+ clear_evtchn(op.port); /* Without, handler gets invoked now! */
+ info->local_port = bind_evtchn(op.port, netfront_handler, NULL);
+ info->evtchn=op.port;
+
+again:
+ err = xenbus_transaction_start(&xbt);
+ if (err) {
+ printk("starting transaction\n");
+ }
+
+ err = xenbus_printf(xbt, nodename, "tx-ring-ref","%u",
+ info->tx_ring_ref);
+ if (err) {
+ message = "writing tx ring-ref";
+ goto abort_transaction;
+ }
+ err = xenbus_printf(xbt, nodename, "rx-ring-ref","%u",
+ info->rx_ring_ref);
+ if (err) {
+ message = "writing rx ring-ref";
+ goto abort_transaction;
+ }
+ err = xenbus_printf(xbt, nodename,
+ "event-channel", "%u", info->evtchn);
+ if (err) {
+ message = "writing event-channel";
+ goto abort_transaction;
+ }
+
+ err = xenbus_printf(xbt, nodename, "request-rx-copy", "%u", 1);
+
+ if (err) {
+ message = "writing request-rx-copy";
+ goto abort_transaction;
+ }
+
+ err = xenbus_printf(xbt, nodename, "state", "%u",
+ 4); /* connected */
+
+
+ err = xenbus_transaction_end(xbt, 0, &retry);
+ if (retry) {
+ goto again;
+ printk("completing transaction\n");
+ }
+
+ goto done;
+
+abort_transaction:
+ xenbus_transaction_end(xbt, 1, &retry);
+
+done:
+
+ msg = xenbus_read(XBT_NIL, "device/vif/0/backend", &backend);
+ msg = xenbus_read(XBT_NIL, "device/vif/0/mac", &mac);
+
+ printk("backend at %s\n",backend);
+ printk("mac is %s\n",mac);
+
+ char *res;
+ char path[256];
+ sprintf(path,"%s/state",backend);
+
+ xenbus_watch_path(XBT_NIL, path);
+
+ xenbus_wait_for_value(path,"4");
+
+ //free(backend);
+ free(res);
+
+ printk("**************************\n");
+
+ init_rx_buffers();
+
+ unsigned char rawmac[6];
+ sscanf(mac,"%x:%x:%x:%x:%x:%x",
+ &rawmac[0],
+ &rawmac[1],
+ &rawmac[2],
+ &rawmac[3],
+ &rawmac[4],
+ &rawmac[5]);
+
+ net_app_main(si,rawmac);
+}
+
+void shutdown_netfront(void)
+{
+ //xenbus_transaction_t xbt;
+ char* err;
+ char nodename[] = "device/vif/0";
+
+ char path[256];
+
+ printk("close network: backend at %s\n",backend);
+
+ err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6); /* closing */
+ sprintf(path,"%s/state",backend);
+
+ xenbus_wait_for_value(path,"6");
+
+ err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
+
+ xenbus_wait_for_value(path,"2");
+
+ unbind_all_ports();
+
+}
+
+
+void init_rx_buffers(void)
+{
+ struct net_info* np = &net_info;
+ int i, requeue_idx;
+ netif_rx_request_t *req;
+ int notify;
+
+ np->rx.req_prod_pvt = requeue_idx;
+
+
+ /* Step 2: Rebuild the RX buffer freelist and the RX ring itself. */
+ for (requeue_idx = 0, i = 0; i < NET_RX_RING_SIZE; i++)
+ {
+ struct net_buffer* buf = &rx_buffers[requeue_idx];
+ req = RING_GET_REQUEST(&np->rx, requeue_idx);
+
+ buf->gref = req->gref =
+ gnttab_grant_access(0,virt_to_mfn(buf->page),0);
+
+ req->id = requeue_idx;
+
+ requeue_idx++;
+ }
+
+ np->rx.req_prod_pvt = requeue_idx;
+
+
+
+ RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->rx, notify);
+
+ if(notify)
+ notify_remote_via_evtchn(np->evtchn);
+
+ np->rx.sring->rsp_event = np->rx.rsp_cons + 1;
+
+
+}
+
+
+void netfront_xmit(unsigned char* data,int len)
+{
+ int flags;
+ local_irq_save(flags);
+
+ struct net_info* info = &net_info;
+ struct netif_tx_request *tx;
+ RING_IDX i = info->tx.req_prod_pvt;
+ int notify;
+ int id = get_id_from_freelist(tx_freelist);
+ struct net_buffer* buf = &tx_buffers[id];
+ void* page = buf->page;
+
+ tx = RING_GET_REQUEST(&info->tx, i);
+
+ memcpy(page,data,len);
+
+ buf->gref =
+ tx->gref = gnttab_grant_access(0,virt_to_mfn(page),0);
+
+ tx->offset=0;
+ tx->size = len;
+ tx->flags=0;
+ tx->id = id;
+ info->tx.req_prod_pvt = i + 1;
+
+ wmb();
+
+ RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&info->tx, notify);
+
+ if(notify) notify_remote_via_evtchn(info->evtchn);
+
+ network_tx_buf_gc();
+
+ local_irq_restore(flags);
+}
diff --git a/extras/mini-os/xenbus/xenbus.c b/extras/mini-os/xenbus/xenbus.c
index cb62eb3ef6..09ededbab1 100644
--- a/extras/mini-os/xenbus/xenbus.c
+++ b/extras/mini-os/xenbus/xenbus.c
@@ -45,9 +45,9 @@
#define DEBUG(_f, _a...) ((void)0)
#endif
-
static struct xenstore_domain_interface *xenstore_buf;
static DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
+static DECLARE_WAIT_QUEUE_HEAD(watch_queue);
struct xenbus_req_info
{
int in_use:1;
@@ -72,6 +72,34 @@ static void memcpy_from_ring(const void *Ring,
memcpy(dest + c1, ring, c2);
}
+static inline void wait_for_watch(void)
+{
+ DEFINE_WAIT(w);
+ add_waiter(w,watch_queue);
+ schedule();
+ wake(current);
+}
+
+char* xenbus_wait_for_value(const char* path,const char* value)
+{
+ for(;;)
+ {
+ char *res, *msg;
+ int r;
+
+ msg = xenbus_read(XBT_NIL, path, &res);
+ if(msg) return msg;
+
+ r = strcmp(value,res);
+ free(res);
+
+ if(r==0) break;
+ else wait_for_watch();
+ }
+ return NULL;
+}
+
+
static void xenbus_thread_func(void *ign)
{
struct xsd_sockmsg msg;
@@ -101,13 +129,35 @@ static void xenbus_thread_func(void *ign)
break;
DEBUG("Message is good.\n");
- req_info[msg.req_id].reply = malloc(sizeof(msg) + msg.len);
- memcpy_from_ring(xenstore_buf->rsp,
+
+ if(msg.type == XS_WATCH_EVENT)
+ {
+ char* payload = (char*)malloc(sizeof(msg) + msg.len);
+ char *path,*token;
+
+ memcpy_from_ring(xenstore_buf->rsp,
+ payload,
+ MASK_XENSTORE_IDX(xenstore_buf->rsp_cons),
+ msg.len + sizeof(msg));
+
+ path = payload + sizeof(msg);
+ token = path + strlen(path) + 1;
+
+ xenstore_buf->rsp_cons += msg.len + sizeof(msg);
+ free(payload);
+ wake_up(&watch_queue);
+ }
+
+ else
+ {
+ req_info[msg.req_id].reply = malloc(sizeof(msg) + msg.len);
+ memcpy_from_ring(xenstore_buf->rsp,
req_info[msg.req_id].reply,
MASK_XENSTORE_IDX(xenstore_buf->rsp_cons),
msg.len + sizeof(msg));
- wake_up(&req_info[msg.req_id].waitq);
- xenstore_buf->rsp_cons += msg.len + sizeof(msg);
+ xenstore_buf->rsp_cons += msg.len + sizeof(msg);
+ wake_up(&req_info[msg.req_id].waitq);
+ }
}
}
}
@@ -381,12 +431,32 @@ char *xenbus_write(xenbus_transaction_t xbt, const char *path, const char *value
struct xsd_sockmsg *rep;
rep = xenbus_msg_reply(XS_WRITE, xbt, req, ARRAY_SIZE(req));
char *msg = errmsg(rep);
- if (msg)
- return msg;
+ if (msg) return msg;
free(rep);
return NULL;
}
+char* xenbus_watch_path( xenbus_transaction_t xbt, const char *path)
+{
+ /* in the future one could have multiple watch queues, and use
+ * the token for demuxing. For now the token is 0. */
+
+ struct xsd_sockmsg *rep;
+
+ struct write_req req[] = {
+ {path, strlen(path) + 1},
+ {"0",2 },
+ };
+
+ rep = xenbus_msg_reply(XS_WATCH, xbt, req, ARRAY_SIZE(req));
+
+ char *msg = errmsg(rep);
+ if (msg) return msg;
+ free(rep);
+
+ return NULL;
+}
+
char *xenbus_rm(xenbus_transaction_t xbt, const char *path)
{
struct write_req req[] = { {path, strlen(path) + 1} };
diff --git a/linux-2.6-xen-sparse/arch/i386/Kconfig b/linux-2.6-xen-sparse/arch/i386/Kconfig
index 921c175aa7..d9746de7a1 100644
--- a/linux-2.6-xen-sparse/arch/i386/Kconfig
+++ b/linux-2.6-xen-sparse/arch/i386/Kconfig
@@ -629,7 +629,7 @@ config HAVE_ARCH_EARLY_PFN_TO_NID
config HIGHPTE
bool "Allocate 3rd-level pagetables from highmem"
- depends on (HIGHMEM4G || HIGHMEM64G) && !X86_XEN
+ depends on HIGHMEM4G || HIGHMEM64G
help
The VM uses one page table entry for each page of physical memory.
For systems with a lot of RAM, this can be wasteful of precious
diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c
index e9c59c403d..55a416c885 100644
--- a/linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c
@@ -89,7 +89,7 @@ static ssize_t microcode_write (struct file *file, const char __user *buf, size_
{
ssize_t ret;
- if (len < DEFAULT_UCODE_TOTALSIZE) {
+ if (len < MC_HEADER_SIZE) {
printk(KERN_ERR "microcode: not enough data\n");
return -EINVAL;
}
diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/pci-dma-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/pci-dma-xen.c
index 8a60f1f91e..70ba380bdb 100644
--- a/linux-2.6-xen-sparse/arch/i386/kernel/pci-dma-xen.c
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/pci-dma-xen.c
@@ -114,13 +114,7 @@ dma_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents,
}
EXPORT_SYMBOL(dma_unmap_sg);
-/*
- * XXX This file is also used by xenLinux/ia64.
- * "defined(__i386__) || defined (__x86_64__)" means "!defined(__ia64__)".
- * This #if work around should be removed once this file is merbed back into
- * i386' pci-dma or is moved to drivers/xen/core.
- */
-#if defined(__i386__) || defined(__x86_64__)
+#ifdef CONFIG_HIGHMEM
dma_addr_t
dma_map_page(struct device *dev, struct page *page, unsigned long offset,
size_t size, enum dma_data_direction direction)
@@ -150,7 +144,7 @@ dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
swiotlb_unmap_page(dev, dma_address, size, direction);
}
EXPORT_SYMBOL(dma_unmap_page);
-#endif /* defined(__i386__) || defined(__x86_64__) */
+#endif /* CONFIG_HIGHMEM */
int
dma_mapping_error(dma_addr_t dma_addr)
@@ -181,6 +175,8 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
unsigned int order = get_order(size);
unsigned long vstart;
+ u64 mask;
+
/* ignore region specifiers */
gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
@@ -203,9 +199,14 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
vstart = __get_free_pages(gfp, order);
ret = (void *)vstart;
+ if (dev != NULL && dev->coherent_dma_mask)
+ mask = dev->coherent_dma_mask;
+ else
+ mask = 0xffffffff;
+
if (ret != NULL) {
if (xen_create_contiguous_region(vstart, order,
- dma_bits) != 0) {
+ fls64(mask)) != 0) {
free_pages(vstart, order);
return NULL;
}
diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c b/linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c
index ac2c0da536..8738cfca7e 100644
--- a/linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c
@@ -47,9 +47,6 @@ EXPORT_SYMBOL(swiotlb);
*/
#define IO_TLB_SHIFT 11
-/* Width of DMA addresses. 30 bits is a b44 limitation. */
-#define DEFAULT_DMA_BITS 30
-
static int swiotlb_force;
static char *iotlb_virt_start;
static unsigned long iotlb_nslabs;
@@ -98,11 +95,12 @@ static struct phys_addr {
*/
static DEFINE_SPINLOCK(io_tlb_lock);
-unsigned int dma_bits = DEFAULT_DMA_BITS;
+static unsigned int dma_bits;
+static unsigned int __initdata max_dma_bits = 32;
static int __init
setup_dma_bits(char *str)
{
- dma_bits = simple_strtoul(str, NULL, 0);
+ max_dma_bits = simple_strtoul(str, NULL, 0);
return 0;
}
__setup("dma_bits=", setup_dma_bits);
@@ -143,6 +141,7 @@ void
swiotlb_init_with_default_size (size_t default_size)
{
unsigned long i, bytes;
+ int rc;
if (!iotlb_nslabs) {
iotlb_nslabs = (default_size >> IO_TLB_SHIFT);
@@ -159,16 +158,33 @@ swiotlb_init_with_default_size (size_t default_size)
*/
iotlb_virt_start = alloc_bootmem_low_pages(bytes);
if (!iotlb_virt_start)
- panic("Cannot allocate SWIOTLB buffer!\n"
- "Use dom0_mem Xen boot parameter to reserve\n"
- "some DMA memory (e.g., dom0_mem=-128M).\n");
+ panic("Cannot allocate SWIOTLB buffer!\n");
+ dma_bits = get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT) + PAGE_SHIFT;
for (i = 0; i < iotlb_nslabs; i += IO_TLB_SEGSIZE) {
- int rc = xen_create_contiguous_region(
- (unsigned long)iotlb_virt_start + (i << IO_TLB_SHIFT),
- get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT),
- dma_bits);
- BUG_ON(rc);
+ do {
+ rc = xen_create_contiguous_region(
+ (unsigned long)iotlb_virt_start + (i << IO_TLB_SHIFT),
+ get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT),
+ dma_bits);
+ } while (rc && dma_bits++ < max_dma_bits);
+ if (rc) {
+ if (i == 0)
+ panic("No suitable physical memory available for SWIOTLB buffer!\n"
+ "Use dom0_mem Xen boot parameter to reserve\n"
+ "some DMA memory (e.g., dom0_mem=-128M).\n");
+ iotlb_nslabs = i;
+ i <<= IO_TLB_SHIFT;
+ free_bootmem(__pa(iotlb_virt_start + i), bytes - i);
+ bytes = i;
+ for (dma_bits = 0; i > 0; i -= IO_TLB_SEGSIZE << IO_TLB_SHIFT) {
+ unsigned int bits = fls64(virt_to_bus(iotlb_virt_start + i - 1));
+
+ if (bits > dma_bits)
+ dma_bits = bits;
+ }
+ break;
+ }
}
/*
@@ -186,17 +202,27 @@ swiotlb_init_with_default_size (size_t default_size)
* Get the overflow emergency buffer
*/
io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow);
+ if (!io_tlb_overflow_buffer)
+ panic("Cannot allocate SWIOTLB overflow buffer!\n");
+
+ do {
+ rc = xen_create_contiguous_region(
+ (unsigned long)io_tlb_overflow_buffer,
+ get_order(io_tlb_overflow),
+ dma_bits);
+ } while (rc && dma_bits++ < max_dma_bits);
+ if (rc)
+ panic("No suitable physical memory available for SWIOTLB overflow buffer!\n");
iotlb_pfn_start = __pa(iotlb_virt_start) >> PAGE_SHIFT;
iotlb_pfn_end = iotlb_pfn_start + (bytes >> PAGE_SHIFT);
printk(KERN_INFO "Software IO TLB enabled: \n"
" Aperture: %lu megabytes\n"
- " Kernel range: 0x%016lx - 0x%016lx\n"
+ " Kernel range: %p - %p\n"
" Address size: %u bits\n",
bytes >> 20,
- (unsigned long)iotlb_virt_start,
- (unsigned long)iotlb_virt_start + bytes,
+ iotlb_virt_start, iotlb_virt_start + bytes,
dma_bits);
}
@@ -238,9 +264,12 @@ __sync_single(struct phys_addr buffer, char *dma_addr, size_t size, int dir)
char *dev, *host, *kmp;
len = size;
while (len != 0) {
+ unsigned long flags;
+
if (((bytes = len) + buffer.offset) > PAGE_SIZE)
bytes = PAGE_SIZE - buffer.offset;
- kmp = kmap_atomic(buffer.page, KM_SWIOTLB);
+ local_irq_save(flags); /* protects KM_BOUNCE_READ */
+ kmp = kmap_atomic(buffer.page, KM_BOUNCE_READ);
dev = dma_addr + size - len;
host = kmp + buffer.offset;
if (dir == DMA_FROM_DEVICE) {
@@ -248,7 +277,8 @@ __sync_single(struct phys_addr buffer, char *dma_addr, size_t size, int dir)
/* inaccessible */;
} else
memcpy(dev, host, bytes);
- kunmap_atomic(kmp, KM_SWIOTLB);
+ kunmap_atomic(kmp, KM_BOUNCE_READ);
+ local_irq_restore(flags);
len -= bytes;
buffer.page++;
buffer.offset = 0;
@@ -617,6 +647,8 @@ swiotlb_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
sg->dma_length, dir);
}
+#ifdef CONFIG_HIGHMEM
+
dma_addr_t
swiotlb_map_page(struct device *hwdev, struct page *page,
unsigned long offset, size_t size,
@@ -650,6 +682,8 @@ swiotlb_unmap_page(struct device *hwdev, dma_addr_t dma_address,
unmap_single(hwdev, bus_to_virt(dma_address), size, direction);
}
+#endif
+
int
swiotlb_dma_mapping_error(dma_addr_t dma_addr)
{
@@ -677,7 +711,5 @@ EXPORT_SYMBOL(swiotlb_sync_single_for_cpu);
EXPORT_SYMBOL(swiotlb_sync_single_for_device);
EXPORT_SYMBOL(swiotlb_sync_sg_for_cpu);
EXPORT_SYMBOL(swiotlb_sync_sg_for_device);
-EXPORT_SYMBOL(swiotlb_map_page);
-EXPORT_SYMBOL(swiotlb_unmap_page);
EXPORT_SYMBOL(swiotlb_dma_mapping_error);
EXPORT_SYMBOL(swiotlb_dma_supported);
diff --git a/linux-2.6-xen-sparse/arch/i386/mm/fault-xen.c b/linux-2.6-xen-sparse/arch/i386/mm/fault-xen.c
index a40e09fb45..a9e9bcf576 100644
--- a/linux-2.6-xen-sparse/arch/i386/mm/fault-xen.c
+++ b/linux-2.6-xen-sparse/arch/i386/mm/fault-xen.c
@@ -262,16 +262,19 @@ static void dump_fault_path(unsigned long address)
p += (address >> 30) * 2;
printk(KERN_ALERT "%08lx -> *pde = %08lx:%08lx\n", page, p[1], p[0]);
if (p[0] & 1) {
- mfn = (p[0] >> PAGE_SHIFT) | ((p[1] & 0x7) << 20);
+ mfn = (p[0] >> PAGE_SHIFT) | (p[1] << 20);
page = mfn_to_pfn(mfn) << PAGE_SHIFT;
p = (unsigned long *)__va(page);
address &= 0x3fffffff;
p += (address >> 21) * 2;
printk(KERN_ALERT "%08lx -> *pme = %08lx:%08lx\n",
page, p[1], p[0]);
-#ifndef CONFIG_HIGHPTE
+ mfn = (p[0] >> PAGE_SHIFT) | (p[1] << 20);
+#ifdef CONFIG_HIGHPTE
+ if (mfn_to_pfn(mfn) >= highstart_pfn)
+ return;
+#endif
if (p[0] & 1) {
- mfn = (p[0] >> PAGE_SHIFT) | ((p[1] & 0x7) << 20);
page = mfn_to_pfn(mfn) << PAGE_SHIFT;
p = (unsigned long *) __va(page);
address &= 0x001fffff;
@@ -279,7 +282,6 @@ static void dump_fault_path(unsigned long address)
printk(KERN_ALERT "%08lx -> *pte = %08lx:%08lx\n",
page, p[1], p[0]);
}
-#endif
}
}
#else
@@ -294,11 +296,14 @@ static void dump_fault_path(unsigned long address)
machine_to_phys(page));
/*
* We must not directly access the pte in the highpte
- * case, the page table might be allocated in highmem.
+ * case if the page table is located in highmem.
* And lets rather not kmap-atomic the pte, just in case
* it's allocated already.
*/
-#ifndef CONFIG_HIGHPTE
+#ifdef CONFIG_HIGHPTE
+ if ((page >> PAGE_SHIFT) >= highstart_pfn)
+ return;
+#endif
if ((page & 1) && oops_may_print()) {
page &= PAGE_MASK;
address &= 0x003ff000;
@@ -307,7 +312,6 @@ static void dump_fault_path(unsigned long address)
printk(KERN_ALERT "*pte = ma %08lx pa %08lx\n", page,
machine_to_phys(page));
}
-#endif
}
#endif
diff --git a/linux-2.6-xen-sparse/arch/i386/mm/highmem-xen.c b/linux-2.6-xen-sparse/arch/i386/mm/highmem-xen.c
index 23f0e1b2e9..ee7deae2a7 100644
--- a/linux-2.6-xen-sparse/arch/i386/mm/highmem-xen.c
+++ b/linux-2.6-xen-sparse/arch/i386/mm/highmem-xen.c
@@ -129,5 +129,6 @@ struct page *kmap_atomic_to_page(void *ptr)
EXPORT_SYMBOL(kmap);
EXPORT_SYMBOL(kunmap);
EXPORT_SYMBOL(kmap_atomic);
+EXPORT_SYMBOL(kmap_atomic_pte);
EXPORT_SYMBOL(kunmap_atomic);
EXPORT_SYMBOL(kmap_atomic_to_page);
diff --git a/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c b/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c
index e073fb621d..2af24831ec 100644
--- a/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c
+++ b/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c
@@ -239,23 +239,41 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
#ifdef CONFIG_HIGHPTE
pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT|__GFP_ZERO, 0);
+ if (pte && PageHighMem(pte)) {
+ struct mmuext_op op;
+
+ kmap_flush_unused();
+ op.cmd = MMUEXT_PIN_L1_TABLE;
+ op.arg1.mfn = pfn_to_mfn(page_to_pfn(pte));
+ BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
+ }
#else
pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
+#endif
if (pte) {
SetPageForeign(pte, pte_free);
init_page_count(pte);
}
-#endif
return pte;
}
void pte_free(struct page *pte)
{
- unsigned long va = (unsigned long)__va(page_to_pfn(pte)<<PAGE_SHIFT);
+ unsigned long pfn = page_to_pfn(pte);
- if (!pte_write(*virt_to_ptep(va)))
- BUG_ON(HYPERVISOR_update_va_mapping(
- va, pfn_pte(page_to_pfn(pte), PAGE_KERNEL), 0));
+ if (!PageHighMem(pte)) {
+ unsigned long va = (unsigned long)__va(pfn << PAGE_SHIFT);
+
+ if (!pte_write(*virt_to_ptep(va)))
+ BUG_ON(HYPERVISOR_update_va_mapping(
+ va, pfn_pte(pfn, PAGE_KERNEL), 0));
+ } else {
+ struct mmuext_op op;
+
+ op.cmd = MMUEXT_UNPIN_TABLE;
+ op.arg1.mfn = pfn_to_mfn(pfn);
+ BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
+ }
ClearPageForeign(pte);
init_page_count(pte);
diff --git a/linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c b/linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c
index 9fdf9eba80..a0f1d0535d 100644
--- a/linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c
+++ b/linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c
@@ -163,6 +163,18 @@ void _arch_exit_mmap(struct mm_struct *mm)
mm_unpin(mm);
}
+struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+ struct page *pte;
+
+ pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
+ if (pte) {
+ SetPageForeign(pte, pte_free);
+ init_page_count(pte);
+ }
+ return pte;
+}
+
void pte_free(struct page *pte)
{
unsigned long va = (unsigned long)__va(page_to_pfn(pte)<<PAGE_SHIFT);
@@ -170,6 +182,10 @@ void pte_free(struct page *pte)
if (!pte_write(*virt_to_ptep(va)))
BUG_ON(HYPERVISOR_update_va_mapping(
va, pfn_pte(page_to_pfn(pte), PAGE_KERNEL), 0));
+
+ ClearPageForeign(pte);
+ init_page_count(pte);
+
__free_page(pte);
}
#endif /* CONFIG_XEN */
diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c
index 349ae64d0f..b22712e80c 100644
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c
@@ -42,9 +42,30 @@ static int connect_ring(struct backend_info *);
static void backend_changed(struct xenbus_watch *, const char **,
unsigned int);
+static int blkback_name(blkif_t *blkif, char *buf)
+{
+ char *devpath, *devname;
+ struct xenbus_device *dev = blkif->be->dev;
+
+ devpath = xenbus_read(XBT_NIL, dev->nodename, "dev", NULL);
+ if (IS_ERR(devpath))
+ return PTR_ERR(devpath);
+
+ if ((devname = strstr(devpath, "/dev/")) != NULL)
+ devname += strlen("/dev/");
+ else
+ devname = devpath;
+
+ snprintf(buf, TASK_COMM_LEN, "blkback.%d.%s", blkif->domid, devname);
+ kfree(devpath);
+
+ return 0;
+}
+
static void update_blkif_status(blkif_t *blkif)
{
int err;
+ char name[TASK_COMM_LEN];
/* Not ready to connect? */
if (!blkif->irq || !blkif->vbd.bdev)
@@ -59,10 +80,13 @@ static void update_blkif_status(blkif_t *blkif)
if (blkif->be->dev->state != XenbusStateConnected)
return;
- blkif->xenblkd = kthread_run(blkif_schedule, blkif,
- "xvd %d %02x:%02x",
- blkif->domid,
- blkif->be->major, blkif->be->minor);
+ err = blkback_name(blkif, name);
+ if (err) {
+ xenbus_dev_error(blkif->be->dev, err, "get blkback dev name");
+ return;
+ }
+
+ blkif->xenblkd = kthread_run(blkif_schedule, blkif, name);
if (IS_ERR(blkif->xenblkd)) {
err = PTR_ERR(blkif->xenblkd);
blkif->xenblkd = NULL;
diff --git a/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c
index 553ad45c48..fb2979b70b 100644
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c
@@ -92,9 +92,30 @@ static long get_id(const char *str)
return simple_strtol(num, NULL, 10);
}
+static int blktap_name(blkif_t *blkif, char *buf)
+{
+ char *devpath, *devname;
+ struct xenbus_device *dev = blkif->be->dev;
+
+ devpath = xenbus_read(XBT_NIL, dev->nodename, "dev", NULL);
+ if (IS_ERR(devpath))
+ return PTR_ERR(devpath);
+
+ if ((devname = strstr(devpath, "/dev/")) != NULL)
+ devname += strlen("/dev/");
+ else
+ devname = devpath;
+
+ snprintf(buf, TASK_COMM_LEN, "blktap.%d.%s", blkif->domid, devname);
+ kfree(devpath);
+
+ return 0;
+}
+
static void tap_update_blkif_status(blkif_t *blkif)
{
int err;
+ char name[TASK_COMM_LEN];
/* Not ready to connect? */
if(!blkif->irq || !blkif->sectors) {
@@ -110,10 +131,13 @@ static void tap_update_blkif_status(blkif_t *blkif)
if (blkif->be->dev->state != XenbusStateConnected)
return;
- blkif->xenblkd = kthread_run(tap_blkif_schedule, blkif,
- "xvd %d",
- blkif->domid);
+ err = blktap_name(blkif, name);
+ if (err) {
+ xenbus_dev_error(blkif->be->dev, err, "get blktap dev name");
+ return;
+ }
+ blkif->xenblkd = kthread_run(tap_blkif_schedule, blkif, name);
if (IS_ERR(blkif->xenblkd)) {
err = PTR_ERR(blkif->xenblkd);
blkif->xenblkd = NULL;
diff --git a/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c b/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c
index a16e9d9a22..41b1405ff7 100644
--- a/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c
+++ b/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c
@@ -98,8 +98,8 @@ void xen_machine_kexec_setup_resources(void)
err:
/*
* It isn't possible to free xen_phys_cpus this early in the
- * boot. Since failure at this stage is unexpected and the
- * amount is small we leak the memory.
+ * boot. Failure at this stage is unexpected and the amount of
+ * memory is small therefore we tolerate the potential leak.
*/
xen_max_nr_phys_cpus = 0;
return;
diff --git a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/dma-mapping.h b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/dma-mapping.h
index 17ef0c2afd..38befd4ed0 100644
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/dma-mapping.h
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/dma-mapping.h
@@ -53,6 +53,7 @@ extern int dma_map_sg(struct device *hwdev, struct scatterlist *sg,
extern void dma_unmap_sg(struct device *hwdev, struct scatterlist *sg,
int nents, enum dma_data_direction direction);
+#ifdef CONFIG_HIGHMEM
extern dma_addr_t
dma_map_page(struct device *dev, struct page *page, unsigned long offset,
size_t size, enum dma_data_direction direction);
@@ -60,6 +61,11 @@ dma_map_page(struct device *dev, struct page *page, unsigned long offset,
extern void
dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
enum dma_data_direction direction);
+#else
+#define dma_map_page(dev, page, offset, size, dir) \
+ dma_map_single(dev, page_address(page) + (offset), (size), (dir))
+#define dma_unmap_page dma_unmap_single
+#endif
extern void
dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
diff --git a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/kmap_types.h b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/kmap_types.h
deleted file mode 100644
index 1783b70590..0000000000
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/kmap_types.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef _ASM_KMAP_TYPES_H
-#define _ASM_KMAP_TYPES_H
-
-
-#ifdef CONFIG_DEBUG_HIGHMEM
-# define D(n) __KM_FENCE_##n ,
-#else
-# define D(n)
-#endif
-
-enum km_type {
-D(0) KM_BOUNCE_READ,
-D(1) KM_SKB_SUNRPC_DATA,
-D(2) KM_SKB_DATA_SOFTIRQ,
-D(3) KM_USER0,
-D(4) KM_USER1,
-D(5) KM_BIO_SRC_IRQ,
-D(6) KM_BIO_DST_IRQ,
-D(7) KM_PTE0,
-D(8) KM_PTE1,
-D(9) KM_IRQ0,
-D(10) KM_IRQ1,
-D(11) KM_SOFTIRQ0,
-D(12) KM_SOFTIRQ1,
-D(13) KM_SWIOTLB,
-D(14) KM_TYPE_NR
-};
-
-#undef D
-
-#endif
diff --git a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgalloc.h b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgalloc.h
index ce2603f204..7ec46d4ebc 100644
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgalloc.h
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgalloc.h
@@ -41,7 +41,7 @@ extern struct page *pte_alloc_one(struct mm_struct *, unsigned long);
static inline void pte_free_kernel(pte_t *pte)
{
free_page((unsigned long)pte);
- make_page_writable(pte, XENFEAT_writable_page_tables);
+ make_lowmem_page_writable(pte, XENFEAT_writable_page_tables);
}
extern void pte_free(struct page *pte);
diff --git a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/swiotlb.h b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/swiotlb.h
index bb3d7d2416..cf3efdeed6 100644
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/swiotlb.h
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/swiotlb.h
@@ -26,16 +26,16 @@ extern int swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg,
extern void swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg,
int nents, int direction);
extern int swiotlb_dma_mapping_error(dma_addr_t dma_addr);
+#ifdef CONFIG_HIGHMEM
extern dma_addr_t swiotlb_map_page(struct device *hwdev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction direction);
extern void swiotlb_unmap_page(struct device *hwdev, dma_addr_t dma_address,
size_t size, enum dma_data_direction direction);
+#endif
extern int swiotlb_dma_supported(struct device *hwdev, u64 mask);
extern void swiotlb_init(void);
-extern unsigned int dma_bits;
-
#ifdef CONFIG_SWIOTLB
extern int swiotlb;
#else
diff --git a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgalloc.h b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgalloc.h
index 61cf7ec389..ccd88f9aa3 100644
--- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgalloc.h
+++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgalloc.h
@@ -64,42 +64,35 @@ static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
}
}
-static inline void pmd_free(pmd_t *pmd)
+extern struct page *pte_alloc_one(struct mm_struct *mm, unsigned long addr);
+extern void pte_free(struct page *pte);
+
+static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
{
- pte_t *ptep = virt_to_ptep(pmd);
+ struct page *pg;
- if (!pte_write(*ptep)) {
- BUG_ON(HYPERVISOR_update_va_mapping(
- (unsigned long)pmd,
- pfn_pte(virt_to_phys(pmd)>>PAGE_SHIFT, PAGE_KERNEL),
- 0));
- }
- free_page((unsigned long)pmd);
+ pg = pte_alloc_one(mm, addr);
+ return pg ? page_address(pg) : NULL;
}
-static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
+static inline void pmd_free(pmd_t *pmd)
{
- pmd_t *pmd = (pmd_t *) get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
- return pmd;
+ BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
+ pte_free(virt_to_page(pmd));
}
static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
{
- pud_t *pud = (pud_t *) get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
- return pud;
+ struct page *pg;
+
+ pg = pte_alloc_one(mm, addr);
+ return pg ? page_address(pg) : NULL;
}
static inline void pud_free(pud_t *pud)
{
- pte_t *ptep = virt_to_ptep(pud);
-
- if (!pte_write(*ptep)) {
- BUG_ON(HYPERVISOR_update_va_mapping(
- (unsigned long)pud,
- pfn_pte(virt_to_phys(pud)>>PAGE_SHIFT, PAGE_KERNEL),
- 0));
- }
- free_page((unsigned long)pud);
+ BUG_ON((unsigned long)pud & (PAGE_SIZE-1));
+ pte_free(virt_to_page(pud));
}
static inline void pgd_list_add(pgd_t *pgd)
@@ -130,10 +123,10 @@ static inline void pgd_list_del(pgd_t *pgd)
static inline pgd_t *pgd_alloc(struct mm_struct *mm)
{
- /*
- * We allocate two contiguous pages for kernel and user.
- */
- unsigned boundary;
+ /*
+ * We allocate two contiguous pages for kernel and user.
+ */
+ unsigned boundary;
pgd_t *pgd = (pgd_t *)__get_free_pages(GFP_KERNEL|__GFP_REPEAT, 1);
if (!pgd)
return NULL;
@@ -150,11 +143,11 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
(PTRS_PER_PGD - boundary) * sizeof(pgd_t));
memset(__user_pgd(pgd), 0, PAGE_SIZE); /* clean up user pgd */
- /*
- * Set level3_user_pgt for vsyscall area
- */
+ /*
+ * Set level3_user_pgt for vsyscall area
+ */
set_pgd(__user_pgd(pgd) + pgd_index(VSYSCALL_START),
- mk_kernel_pgd(__pa_symbol(level3_user_pgt)));
+ mk_kernel_pgd(__pa_symbol(level3_user_pgt)));
return pgd;
}
@@ -187,39 +180,25 @@ static inline void pgd_free(pgd_t *pgd)
static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
{
- pte_t *pte = (pte_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
- if (pte)
+ pte_t *pte = (pte_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
+ if (pte)
make_page_readonly(pte, XENFEAT_writable_page_tables);
return pte;
}
-static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
-{
- struct page *pte;
-
- pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
- return pte;
-}
-
/* Should really implement gc for free page table pages. This could be
done with a reference count in struct page. */
static inline void pte_free_kernel(pte_t *pte)
{
BUG_ON((unsigned long)pte & (PAGE_SIZE-1));
- make_page_writable(pte, XENFEAT_writable_page_tables);
+ make_page_writable(pte, XENFEAT_writable_page_tables);
free_page((unsigned long)pte);
}
-extern void pte_free(struct page *pte);
-
-//#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte))
-//#define __pmd_free_tlb(tlb,x) tlb_remove_page((tlb),virt_to_page(x))
-//#define __pud_free_tlb(tlb,x) tlb_remove_page((tlb),virt_to_page(x))
-
-#define __pte_free_tlb(tlb,x) pte_free((x))
-#define __pmd_free_tlb(tlb,x) pmd_free((x))
-#define __pud_free_tlb(tlb,x) pud_free((x))
+#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte))
+#define __pmd_free_tlb(tlb,x) tlb_remove_page((tlb),virt_to_page(x))
+#define __pud_free_tlb(tlb,x) tlb_remove_page((tlb),virt_to_page(x))
#endif /* _X86_64_PGALLOC_H */
diff --git a/linux-2.6-xen-sparse/kernel/kexec.c b/linux-2.6-xen-sparse/kernel/kexec.c
index 921415a803..c46558f7da 100644
--- a/linux-2.6-xen-sparse/kernel/kexec.c
+++ b/linux-2.6-xen-sparse/kernel/kexec.c
@@ -1012,9 +1012,11 @@ asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments,
goto out;
}
#ifdef CONFIG_XEN
- result = xen_machine_kexec_load(image);
- if (result)
- goto out;
+ if (image) {
+ result = xen_machine_kexec_load(image);
+ if (result)
+ goto out;
+ }
#endif
/* Install the new kernel, and Uninstall the old */
image = xchg(dest_image, image);
diff --git a/patches/linux-2.6.18/ipv6-no-autoconf.patch b/patches/linux-2.6.18/ipv6-no-autoconf.patch
deleted file mode 100644
index 84c72e956b..0000000000
--- a/patches/linux-2.6.18/ipv6-no-autoconf.patch
+++ /dev/null
@@ -1,19 +0,0 @@
-diff -pruN ../orig-linux-2.6.18/net/ipv6/addrconf.c ./net/ipv6/addrconf.c
---- ../orig-linux-2.6.18/net/ipv6/addrconf.c 2006-09-20 04:42:06.000000000 +0100
-+++ ./net/ipv6/addrconf.c 2007-01-12 16:08:07.000000000 +0000
-@@ -2514,6 +2514,7 @@ static void addrconf_dad_start(struct in
- spin_lock_bh(&ifp->lock);
-
- if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) ||
-+ !(dev->flags&IFF_MULTICAST) ||
- !(ifp->flags&IFA_F_TENTATIVE)) {
- ifp->flags &= ~IFA_F_TENTATIVE;
- spin_unlock_bh(&ifp->lock);
-@@ -2598,6 +2599,7 @@ static void addrconf_dad_completed(struc
- if (ifp->idev->cnf.forwarding == 0 &&
- ifp->idev->cnf.rtr_solicits > 0 &&
- (dev->flags&IFF_LOOPBACK) == 0 &&
-+ (dev->flags & IFF_MULTICAST) &&
- (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) {
- struct in6_addr all_routers;
-
diff --git a/patches/linux-2.6.18/series b/patches/linux-2.6.18/series
index 8917c01dfb..9a007ac3ab 100644
--- a/patches/linux-2.6.18/series
+++ b/patches/linux-2.6.18/series
@@ -5,7 +5,6 @@ linux-2.6.19-rc1-kexec-move_segment_code-x86_64.patch
blktap-aio-16_03_06.patch
fix-ide-cd-pio-mode.patch
i386-mach-io-check-nmi.patch
-ipv6-no-autoconf.patch
net-csum.patch
net-gso-5-rcv-mss.patch
net-gso-6-linear-segmentation.patch
diff --git a/tools/check/check_udev b/tools/check/check_udev
index c84cb98029..a4295cf4fa 100755
--- a/tools/check/check_udev
+++ b/tools/check/check_udev
@@ -11,7 +11,7 @@ OpenBSD|NetBSD|FreeBSD)
Linux)
TOOL="udevinfo"
UDEV_VERSION="0"
- test -x "$(which ${TOOL})" && \
+ test -x "$(which ${TOOL} 2>/dev/null)" && \
UDEV_VERSION=$(${TOOL} -V | sed -e 's/^[^0-9]* \([0-9]\{1,\}\)[^0-9]\{0,\}/\1/')
if test "${UDEV_VERSION}" -ge 059; then
RC=0
@@ -28,7 +28,7 @@ esac
if test ${RC} -ne 0; then
echo
- echo ' *** Check for ${TOOL} FAILED'
+ echo " *** Check for ${TOOL} FAILED"
fi
exit ${RC}
diff --git a/tools/examples/vtpm-common.sh b/tools/examples/vtpm-common.sh
index bf50f323e3..8af4f321e9 100644
--- a/tools/examples/vtpm-common.sh
+++ b/tools/examples/vtpm-common.sh
@@ -24,7 +24,9 @@ VTPMDB="/etc/xen/vtpm.db"
#In the vtpm-impl file some commands should be defined:
# vtpm_create, vtpm_setup, vtpm_start, etc. (see below)
-if [ -r "$dir/vtpm-impl" ]; then
+if [ -r "$dir/vtpm-impl.alt" ]; then
+ . "$dir/vtpm-impl.alt"
+elif [ -r "$dir/vtpm-impl" ]; then
. "$dir/vtpm-impl"
else
function vtpm_create () {
diff --git a/tools/examples/xen-network-common.sh b/tools/examples/xen-network-common.sh
index 46708347e3..6823a76a30 100644
--- a/tools/examples/xen-network-common.sh
+++ b/tools/examples/xen-network-common.sh
@@ -117,7 +117,12 @@ create_bridge () {
ip link set ${bridge} arp off
ip link set ${bridge} multicast off
fi
+
+ # A small MTU disables IPv6 (and therefore IPv6 addrconf).
+ mtu=$(ip link show ${bridge} | sed -n 's/.* mtu \([0-9]\+\).*/\1/p')
+ ip link set ${bridge} mtu 68
ip link set ${bridge} up
+ ip link set ${bridge} mtu ${mtu:-1500}
}
# Usage: add_to_bridge bridge dev
diff --git a/tools/examples/xmexample1 b/tools/examples/xmexample1
index 741e330bfb..fc17ca84d9 100644
--- a/tools/examples/xmexample1
+++ b/tools/examples/xmexample1
@@ -66,6 +66,40 @@ vif = [ '' ]
disk = [ 'phy:hda1,hda1,w' ]
#----------------------------------------------------------------------------
+# Define frame buffer device.
+#
+# By default, no frame buffer device is configured.
+#
+# To create one using the SDL backend and sensible defaults:
+#
+# vfb = [ 'type=sdl' ]
+#
+# This uses environment variables XAUTHORITY and DISPLAY. You
+# can override that:
+#
+# vfb = [ 'type=sdl,xauthority=/home/bozo/.Xauthority,display=:1' ]
+#
+# To create one using the VNC backend and sensible defaults:
+#
+# vfb = [ 'type=vnc' ]
+#
+# The backend listens on 127.0.0.1 port 5900+N by default, where N is
+# the domain ID. You can override both address and N:
+#
+# vfb = [ 'type=vnc,vnclisten=127.0.0.1,vncdisplay=1' ]
+#
+# Or you can bind the first unused port above 5900:
+#
+# vfb = [ 'type=vnc,vnclisten=0.0.0.0,vnunused=1' ]
+#
+# You can override the password:
+#
+# vfb = [ 'type=vnc,vncpasswd=MYPASSWD' ]
+#
+# Empty password disables authentication. Defaults to the vncpasswd
+# configured in xend-config.sxp.
+
+#----------------------------------------------------------------------------
# Define to which TPM instance the user domain should communicate.
# The vtpm entry is of the form 'instance=INSTANCE,backend=DOM'
# where INSTANCE indicates the instance number of the TPM the VM
diff --git a/tools/examples/xmexample2 b/tools/examples/xmexample2
index 3d4f67701f..4d9595c05c 100644
--- a/tools/examples/xmexample2
+++ b/tools/examples/xmexample2
@@ -102,6 +102,40 @@ disk = [ 'phy:sda%d,sda1,w' % (7+vmid),
'phy:sda6,sda6,r' ]
#----------------------------------------------------------------------------
+# Define frame buffer device.
+#
+# By default, no frame buffer device is configured.
+#
+# To create one using the SDL backend and sensible defaults:
+#
+# vfb = [ 'type=sdl' ]
+#
+# This uses environment variables XAUTHORITY and DISPLAY. You
+# can override that:
+#
+# vfb = [ 'type=sdl,xauthority=/home/bozo/.Xauthority,display=:1' ]
+#
+# To create one using the VNC backend and sensible defaults:
+#
+# vfb = [ 'type=vnc' ]
+#
+# The backend listens on 127.0.0.1 port 5900+N by default, where N is
+# the domain ID. You can override both address and N:
+#
+# vfb = [ 'type=vnc,vnclisten=127.0.0.1,vncdisplay=%d' % vmid ]
+#
+# Or you can bind the first unused port above 5900:
+#
+# vfb = [ 'type=vnc,vnclisten=0.0.0.0,vnunused=1' ]
+#
+# You can override the password:
+#
+# vfb = [ 'type=vnc,vncpasswd=MYPASSWD' ]
+#
+# Empty password disables authentication. Defaults to the vncpasswd
+# configured in xend-config.sxp.
+
+#----------------------------------------------------------------------------
# Define to which TPM instance the user domain should communicate.
# The vtpm entry is of the form 'instance=INSTANCE,backend=DOM'
# where INSTANCE indicates the instance number of the TPM the VM
diff --git a/tools/examples/xmexample3 b/tools/examples/xmexample3
index 8c66b4038e..dd442d642b 100644
--- a/tools/examples/xmexample3
+++ b/tools/examples/xmexample3
@@ -87,6 +87,40 @@ vif = [ 'ip=192.168.%d.1/24' % (vmid)]
disk = [ 'phy:hda%d,hda1,w' % (vmid)]
#----------------------------------------------------------------------------
+# Define frame buffer device.
+#
+# By default, no frame buffer device is configured.
+#
+# To create one using the SDL backend and sensible defaults:
+#
+# vfb = [ 'type=sdl' ]
+#
+# This uses environment variables XAUTHORITY and DISPLAY. You
+# can override that:
+#
+# vfb = [ 'type=sdl,xauthority=/home/bozo/.Xauthority,display=:1' ]
+#
+# To create one using the VNC backend and sensible defaults:
+#
+# vfb = [ 'type=vnc' ]
+#
+# The backend listens on 127.0.0.1 port 5900+N by default, where N is
+# the domain ID. You can override both address and N:
+#
+# vfb = [ 'type=vnc,vnclisten=127.0.0.1,vncdisplay=%d' % vmid ]
+#
+# Or you can bind the first unused port above 5900:
+#
+# vfb = [ 'type=vnc,vnclisten=0.0.0.0,vnunused=1' ]
+#
+# You can override the password:
+#
+# vfb = [ 'type=vnc,vncpasswd=MYPASSWD' ]
+#
+# Empty password disables authentication. Defaults to the vncpasswd
+# configured in xend-config.sxp.
+
+#----------------------------------------------------------------------------
# Define to which TPM instance the user domain should communicate.
# The vtpm entry is of the form 'instance=INSTANCE,backend=DOM'
# where INSTANCE indicates the instance number of the TPM the VM
diff --git a/tools/libfsimage/common/fsimage.c b/tools/libfsimage/common/fsimage.c
index a326fd7644..08262f81ce 100644
--- a/tools/libfsimage/common/fsimage.c
+++ b/tools/libfsimage/common/fsimage.c
@@ -74,7 +74,7 @@ void fsi_close_fsimage(fsi_t *fsi)
pthread_mutex_lock(&fsi_lock);
fsi->f_plugin->fp_ops->fpo_umount(fsi);
(void) close(fsi->f_fd);
- fsip_fs_free(fsi);
+ free(fsi);
pthread_mutex_unlock(&fsi_lock);
}
diff --git a/tools/libfsimage/common/fsimage_grub.c b/tools/libfsimage/common/fsimage_grub.c
index 252445f58e..99481064a9 100644
--- a/tools/libfsimage/common/fsimage_grub.c
+++ b/tools/libfsimage/common/fsimage_grub.c
@@ -193,6 +193,7 @@ fsig_mount(fsi_t *fsi, const char *path)
static int
fsig_umount(fsi_t *fsi)
{
+ free(fsi->f_data);
return (0);
}
@@ -250,6 +251,7 @@ fsig_read(fsi_file_t *ffi, void *buf, size_t nbytes)
static int
fsig_close(fsi_file_t *ffi)
{
+ free(ffi->ff_data);
fsip_file_free(ffi);
return (0);
}
diff --git a/tools/libfsimage/common/fsimage_plugin.c b/tools/libfsimage/common/fsimage_plugin.c
index 71099ba2ff..f961648164 100644
--- a/tools/libfsimage/common/fsimage_plugin.c
+++ b/tools/libfsimage/common/fsimage_plugin.c
@@ -40,13 +40,6 @@ fsip_fs_set_data(fsi_t *fsi, void *data)
fsi->f_data = data;
}
-void
-fsip_fs_free(fsi_t *fsi)
-{
- free(fsi->f_data);
- free(fsi);
-}
-
fsi_file_t *
fsip_file_alloc(fsi_t *fsi, void *data)
{
@@ -64,7 +57,6 @@ fsip_file_alloc(fsi_t *fsi, void *data)
void
fsip_file_free(fsi_file_t *ffi)
{
- free(ffi->ff_data);
free(ffi);
}
diff --git a/tools/libfsimage/common/fsimage_plugin.h b/tools/libfsimage/common/fsimage_plugin.h
index 4592e08be7..f1c83fab95 100644
--- a/tools/libfsimage/common/fsimage_plugin.h
+++ b/tools/libfsimage/common/fsimage_plugin.h
@@ -50,11 +50,10 @@ typedef fsi_plugin_ops_t *
(*fsi_plugin_init_t)(int, fsi_plugin_t *, const char **);
void fsip_fs_set_data(fsi_t *, void *);
-void fsip_fs_free(fsi_t *);
fsi_file_t *fsip_file_alloc(fsi_t *, void *);
void fsip_file_free(fsi_file_t *);
-fsi_t * fsip_fs(fsi_file_t *ffi);
-uint64_t fsip_fs_offset(fsi_t *fsi);
+fsi_t *fsip_fs(fsi_file_t *);
+uint64_t fsip_fs_offset(fsi_t *);
void *fsip_fs_data(fsi_t *);
void *fsip_file_data(fsi_file_t *);
diff --git a/tools/libfsimage/common/mapfile-GNU b/tools/libfsimage/common/mapfile-GNU
index f15060cba4..4bffdeafb0 100644
--- a/tools/libfsimage/common/mapfile-GNU
+++ b/tools/libfsimage/common/mapfile-GNU
@@ -1,5 +1,5 @@
VERSION {
- libfsimage.so.1.1 {
+ libfsimage.so.1.0 {
global:
fsi_open_fsimage;
fsi_close_fsimage;
@@ -10,7 +10,6 @@ VERSION {
fsi_pread_file;
fsip_fs_set_data;
- fsip_fs_free;
fsip_file_alloc;
fsip_file_free;
fsip_fs;
diff --git a/tools/libfsimage/common/mapfile-SunOS b/tools/libfsimage/common/mapfile-SunOS
index 1ea38bed04..63f17e1832 100644
--- a/tools/libfsimage/common/mapfile-SunOS
+++ b/tools/libfsimage/common/mapfile-SunOS
@@ -1,4 +1,4 @@
-libfsimage.so.1.1 {
+libfsimage.so.1.0 {
global:
fsi_open_fsimage;
fsi_close_fsimage;
@@ -9,7 +9,6 @@ libfsimage.so.1.1 {
fsi_pread_file;
fsip_fs_set_data;
- fsip_fs_free;
fsip_file_alloc;
fsip_file_free;
fsip_fs;
diff --git a/tools/libfsimage/ext2fs-lib/ext2fs-lib.c b/tools/libfsimage/ext2fs-lib/ext2fs-lib.c
index b6f60ce65f..aa8e7a63f4 100644
--- a/tools/libfsimage/ext2fs-lib/ext2fs-lib.c
+++ b/tools/libfsimage/ext2fs-lib/ext2fs-lib.c
@@ -58,9 +58,11 @@ ext2lib_umount(fsi_t *fsi)
{
ext2_filsys *fs = fsip_fs_data(fsi);
if (ext2fs_close(*fs) != 0) {
+ free(fs);
errno = EINVAL;
return (-1);
}
+ free(fs);
return (0);
}
diff --git a/tools/libxc/xc_hvm_build.c b/tools/libxc/xc_hvm_build.c
index 21e20ffaf9..8c0c52238b 100644
--- a/tools/libxc/xc_hvm_build.c
+++ b/tools/libxc/xc_hvm_build.c
@@ -233,8 +233,7 @@ static int setup_guest(int xc_handle,
SCRATCH_PFN)) == NULL) )
goto error_out;
memset(shared_info, 0, PAGE_SIZE);
- for ( i = 0; i < MAX_VIRT_CPUS; i++ )
- shared_info->vcpu_info[i].evtchn_upcall_mask = 1;
+ /* NB. evtchn_upcall_mask is unused: leave as zero. */
memset(&shared_info->evtchn_mask[0], 0xff,
sizeof(shared_info->evtchn_mask));
munmap(shared_info, PAGE_SIZE);
diff --git a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c
index 8066d5a047..a92e77a8a6 100644
--- a/tools/libxc/xc_linux_build.c
+++ b/tools/libxc/xc_linux_build.c
@@ -741,7 +741,7 @@ static int setup_guest(int xc_handle,
/*
* Enable shadow translate mode. This must happen after
* populate physmap because the p2m reservation is based on
- * the domains current memory allocation.
+ * the domain's current memory allocation.
*/
if ( xc_shadow_control(xc_handle, dom,
XEN_DOMCTL_SHADOW_OP_ENABLE_TRANSLATE,
diff --git a/tools/libxc/xc_linux_restore.c b/tools/libxc/xc_linux_restore.c
index 827c45693e..10e03971ab 100644
--- a/tools/libxc/xc_linux_restore.c
+++ b/tools/libxc/xc_linux_restore.c
@@ -12,7 +12,7 @@
#include "xg_private.h"
#include "xg_save_restore.h"
-/* max mfn of the whole machine */
+/* max mfn of the current host machine */
static unsigned long max_mfn;
/* virtual starting address of the hypervisor */
@@ -30,6 +30,9 @@ static xen_pfn_t *live_p2m = NULL;
/* A table mapping each PFN to its new MFN. */
static xen_pfn_t *p2m = NULL;
+/* A table of P2M mappings in the current region */
+static xen_pfn_t *p2m_batch = NULL;
+
static ssize_t
read_exact(int fd, void *buf, size_t count)
@@ -57,46 +60,78 @@ read_exact(int fd, void *buf, size_t count)
** This function inverts that operation, replacing the pfn values with
** the (now known) appropriate mfn values.
*/
-static int uncanonicalize_pagetable(unsigned long type, void *page)
+static int uncanonicalize_pagetable(int xc_handle, uint32_t dom,
+ unsigned long type, void *page)
{
int i, pte_last;
unsigned long pfn;
uint64_t pte;
+ int nr_mfns = 0;
pte_last = PAGE_SIZE / ((pt_levels == 2)? 4 : 8);
- /* Now iterate through the page table, uncanonicalizing each PTE */
+ /* First pass: work out how many (if any) MFNs we need to alloc */
for(i = 0; i < pte_last; i++) {
-
+
if(pt_levels == 2)
pte = ((uint32_t *)page)[i];
else
pte = ((uint64_t *)page)[i];
+
+ /* XXX SMH: below needs fixing for PROT_NONE etc */
+ if(!(pte & _PAGE_PRESENT))
+ continue;
+
+ pfn = (pte >> PAGE_SHIFT) & 0xffffffff;
+
+ if(pfn >= max_pfn) {
+ /* This "page table page" is probably not one; bail. */
+ ERROR("Frame number in type %lu page table is out of range: "
+ "i=%d pfn=0x%lx max_pfn=%lu",
+ type >> 28, i, pfn, max_pfn);
+ return 0;
+ }
+
+ if(p2m[pfn] == INVALID_P2M_ENTRY) {
+ /* Have a 'valid' PFN without a matching MFN - need to alloc */
+ p2m_batch[nr_mfns++] = pfn;
+ }
+ }
+
+
+ /* Alllocate the requistite number of mfns */
+ if (nr_mfns && xc_domain_memory_populate_physmap(
+ xc_handle, dom, nr_mfns, 0, 0, p2m_batch) != 0) {
+ ERROR("Failed to allocate memory for batch.!\n");
+ errno = ENOMEM;
+ return 0;
+ }
+
+ /* Second pass: uncanonicalize each present PTE */
+ nr_mfns = 0;
+ for(i = 0; i < pte_last; i++) {
- if(pte & _PAGE_PRESENT) {
-
- pfn = (pte >> PAGE_SHIFT) & 0xffffffff;
-
- if(pfn >= max_pfn) {
- /* This "page table page" is probably not one; bail. */
- ERROR("Frame number in type %lu page table is out of range: "
- "i=%d pfn=0x%lx max_pfn=%lu",
- type >> 28, i, pfn, max_pfn);
- 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)
+ pte = ((uint32_t *)page)[i];
+ else
+ pte = ((uint64_t *)page)[i];
+
+ /* XXX SMH: below needs fixing for PROT_NONE etc */
+ if(!(pte & _PAGE_PRESENT))
+ continue;
+
+ pfn = (pte >> PAGE_SHIFT) & 0xffffffff;
+
+ if(p2m[pfn] == INVALID_P2M_ENTRY)
+ p2m[pfn] = p2m_batch[nr_mfns++];
+ 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;
}
return 1;
@@ -140,6 +175,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
/* A temporary mapping of the guest's start_info page. */
start_info_t *start_info;
+ /* Our mapping of the current region (batch) */
char *region_base;
xc_mmu_t *mmu = NULL;
@@ -244,8 +280,10 @@ int xc_linux_restore(int xc_handle, int io_fd,
p2m = calloc(max_pfn, sizeof(xen_pfn_t));
pfn_type = calloc(max_pfn, sizeof(unsigned long));
region_mfn = calloc(MAX_BATCH_SIZE, sizeof(xen_pfn_t));
+ p2m_batch = calloc(MAX_BATCH_SIZE, sizeof(xen_pfn_t));
- if ((p2m == NULL) || (pfn_type == NULL) || (region_mfn == NULL)) {
+ if ((p2m == NULL) || (pfn_type == NULL) ||
+ (region_mfn == NULL) || (p2m_batch == NULL)) {
ERROR("memory alloc failed");
errno = ENOMEM;
goto out;
@@ -256,6 +294,11 @@ int xc_linux_restore(int xc_handle, int io_fd,
goto out;
}
+ if (lock_pages(p2m_batch, sizeof(xen_pfn_t) * MAX_BATCH_SIZE)) {
+ ERROR("Could not lock p2m_batch");
+ goto out;
+ }
+
/* Get the domain's shared-info frame. */
domctl.cmd = XEN_DOMCTL_getdomaininfo;
domctl.domain = (domid_t)dom;
@@ -270,17 +313,9 @@ int xc_linux_restore(int xc_handle, int io_fd,
goto out;
}
+ /* Mark all PFNs as invalid; we allocate on demand */
for ( pfn = 0; pfn < max_pfn; pfn++ )
- p2m[pfn] = pfn;
-
- if (xc_domain_memory_populate_physmap(xc_handle, dom, max_pfn,
- 0, 0, p2m) != 0) {
- ERROR("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));
+ p2m[pfn] = INVALID_P2M_ENTRY;
if(!(mmu = xc_init_mmu_updates(xc_handle, dom))) {
ERROR("Could not initialise for MMU updates");
@@ -298,7 +333,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
n = 0;
while (1) {
- int j;
+ int j, nr_mfns = 0;
this_pc = (n * 100) / max_pfn;
if ( (this_pc - prev_pc) >= 5 )
@@ -333,20 +368,57 @@ int xc_linux_restore(int xc_handle, int io_fd,
goto out;
}
+ /* First pass for this batch: work out how much memory to alloc */
+ nr_mfns = 0;
for ( i = 0; i < j; i++ )
{
unsigned long pfn, pagetype;
pfn = region_pfn_type[i] & ~XEN_DOMCTL_PFINFO_LTAB_MASK;
pagetype = region_pfn_type[i] & XEN_DOMCTL_PFINFO_LTAB_MASK;
- if ( pagetype == XEN_DOMCTL_PFINFO_XTAB)
- region_mfn[i] = 0; /* we know map will fail, but don't care */
- else
- region_mfn[i] = p2m[pfn];
+ if ( (pagetype != XEN_DOMCTL_PFINFO_XTAB) &&
+ (p2m[pfn] == INVALID_P2M_ENTRY) )
+ {
+ /* Have a live PFN which hasn't had an MFN allocated */
+ p2m_batch[nr_mfns++] = pfn;
+ }
+ }
+
+
+ /* Now allocate a bunch of mfns for this batch */
+ if (nr_mfns && xc_domain_memory_populate_physmap(
+ xc_handle, dom, nr_mfns, 0, 0, p2m_batch) != 0) {
+ ERROR("Failed to allocate memory for batch.!\n");
+ errno = ENOMEM;
+ goto out;
}
+ /* Second pass for this batch: update p2m[] and region_mfn[] */
+ nr_mfns = 0;
+ for ( i = 0; i < j; i++ )
+ {
+ unsigned long pfn, pagetype;
+ pfn = region_pfn_type[i] & ~XEN_DOMCTL_PFINFO_LTAB_MASK;
+ pagetype = region_pfn_type[i] & XEN_DOMCTL_PFINFO_LTAB_MASK;
+
+ if ( pagetype == XEN_DOMCTL_PFINFO_XTAB)
+ region_mfn[i] = ~0UL; /* map will fail but we don't care */
+ else
+ {
+ if (p2m[pfn] == INVALID_P2M_ENTRY) {
+ /* We just allocated a new mfn above; update p2m */
+ p2m[pfn] = p2m_batch[nr_mfns++];
+ }
+
+ /* setup region_mfn[] for batch map */
+ region_mfn[i] = p2m[pfn];
+ }
+ }
+
+ /* Map relevant mfns */
region_base = xc_map_foreign_batch(
xc_handle, dom, PROT_WRITE, region_mfn, j);
+
if ( region_base == NULL )
{
ERROR("map batch failed");
@@ -401,7 +473,8 @@ int xc_linux_restore(int xc_handle, int io_fd,
pae_extended_cr3 ||
(pagetype != XEN_DOMCTL_PFINFO_L1TAB)) {
- if (!uncanonicalize_pagetable(pagetype, page)) {
+ if (!uncanonicalize_pagetable(xc_handle, dom,
+ pagetype, page)) {
/*
** Failing to uncanonicalize a page table can be ok
** under live migration since the pages type may have
@@ -411,10 +484,8 @@ int xc_linux_restore(int xc_handle, int io_fd,
pagetype >> 28, pfn, mfn);
nraces++;
continue;
- }
-
+ }
}
-
}
else if ( pagetype != XEN_DOMCTL_PFINFO_NOTAB )
{
@@ -486,7 +557,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
*/
int j, k;
-
+
/* First pass: find all L3TABs current in > 4G mfns and get new mfns */
for ( i = 0; i < max_pfn; i++ )
{
@@ -555,7 +626,8 @@ int xc_linux_restore(int xc_handle, int io_fd,
}
for(k = 0; k < j; k++) {
- if(!uncanonicalize_pagetable(XEN_DOMCTL_PFINFO_L1TAB,
+ if(!uncanonicalize_pagetable(xc_handle, dom,
+ XEN_DOMCTL_PFINFO_L1TAB,
region_base + k*PAGE_SIZE)) {
ERROR("failed uncanonicalize pt!");
goto out;
@@ -631,7 +703,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
{
unsigned int count;
unsigned long *pfntab;
- int rc;
+ int nr_frees, rc;
if (!read_exact(io_fd, &count, sizeof(count))) {
ERROR("Error when reading pfn count");
@@ -648,29 +720,30 @@ int xc_linux_restore(int xc_handle, int io_fd,
goto out;
}
+ nr_frees = 0;
for (i = 0; i < count; i++) {
unsigned long pfn = pfntab[i];
- if(pfn > max_pfn)
- /* shouldn't happen - continue optimistically */
- continue;
-
- pfntab[i] = p2m[pfn];
- p2m[pfn] = INVALID_P2M_ENTRY; // not in pseudo-physical map
+ if(p2m[pfn] != INVALID_P2M_ENTRY) {
+ /* pfn is not in physmap now, but was at some point during
+ the save/migration process - need to free it */
+ pfntab[nr_frees++] = p2m[pfn];
+ p2m[pfn] = INVALID_P2M_ENTRY; // not in pseudo-physical map
+ }
}
- if (count > 0) {
+ if (nr_frees > 0) {
struct xen_memory_reservation reservation = {
- .nr_extents = count,
+ .nr_extents = nr_frees,
.extent_order = 0,
.domid = dom
};
set_xen_guest_handle(reservation.extent_start, pfntab);
if ((rc = xc_memory_op(xc_handle, XENMEM_decrease_reservation,
- &reservation)) != count) {
+ &reservation)) != nr_frees) {
ERROR("Could not decrease reservation : %d", rc);
goto out;
} else
@@ -791,6 +864,6 @@ int xc_linux_restore(int xc_handle, int io_fd,
free(pfn_type);
DPRINTF("Restore exit with rc=%d\n", rc);
-
+
return rc;
}
diff --git a/tools/libxc/xc_linux_save.c b/tools/libxc/xc_linux_save.c
index 7ca8453848..ef64d1ef50 100644
--- a/tools/libxc/xc_linux_save.c
+++ b/tools/libxc/xc_linux_save.c
@@ -660,13 +660,6 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
goto out;
}
- /* cheesy sanity check */
- if ((info.max_memkb >> (PAGE_SHIFT - 10)) > max_mfn) {
- ERROR("Invalid state record -- pfn count out of range: %lu",
- (info.max_memkb >> (PAGE_SHIFT - 10)));
- goto out;
- }
-
/* Map the shared info frame */
if(!(live_shinfo = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
PROT_READ, shared_info_frame))) {
diff --git a/tools/libxc/xc_load_elf.c b/tools/libxc/xc_load_elf.c
index cabc164cca..4d7d9823a5 100644
--- a/tools/libxc/xc_load_elf.c
+++ b/tools/libxc/xc_load_elf.c
@@ -406,17 +406,19 @@ static int parseelfimage(const char *image,
}
/*
- * A "bimodal" ELF note indicates the kernel will adjust to the
- * current paging mode, including handling extended cr3 syntax.
- * If we have ELF notes then PAE=yes implies that we must support
- * the extended cr3 syntax. Otherwise we need to find the
- * [extended-cr3] syntax in the __xen_guest string.
+ * A "bimodal" ELF note indicates the kernel will adjust to the current
+ * paging mode, including handling extended cr3 syntax. If we have ELF
+ * notes then PAE=yes implies that we must support the extended cr3 syntax.
+ * Otherwise we need to find the [extended-cr3] syntax in the __xen_guest
+ * string. We use strstr() to look for "bimodal" to allow guests to use
+ * "yes,bimodal" or "no,bimodal" for compatibility reasons.
*/
+
dsi->pae_kernel = PAEKERN_no;
if ( dsi->__elfnote_section )
{
p = xen_elfnote_string(dsi, XEN_ELFNOTE_PAE_MODE);
- if ( p != NULL && strncmp(p, "bimodal", 7) == 0 )
+ if ( p != NULL && strstr(p, "bimodal") != NULL )
dsi->pae_kernel = PAEKERN_bimodal;
else if ( p != NULL && strncmp(p, "yes", 3) == 0 )
dsi->pae_kernel = PAEKERN_extended_cr3;
diff --git a/tools/libxc/xc_ptrace.c b/tools/libxc/xc_ptrace.c
index 66bbf9539b..11309a2b24 100644
--- a/tools/libxc/xc_ptrace.c
+++ b/tools/libxc/xc_ptrace.c
@@ -166,14 +166,11 @@ static unsigned long *page_array = NULL;
* tables.
*
*/
-static unsigned long
-to_ma(int cpu,
- unsigned long in_addr)
+static uint64_t
+to_ma(int cpu, uint64_t maddr)
{
- unsigned long maddr = in_addr;
-
if ( current_is_hvm && paging_enabled(&ctxt[cpu]) )
- maddr = page_array[maddr >> PAGE_SHIFT] << PAGE_SHIFT;
+ maddr = (uint64_t)page_array[maddr >> PAGE_SHIFT] << PAGE_SHIFT;
return maddr;
}
@@ -225,7 +222,8 @@ map_domain_va_pae(
void *guest_va,
int perm)
{
- unsigned long l3e, l2e, l1e, l2p, l1p, p, va = (unsigned long)guest_va;
+ uint64_t l3e, l2e, l1e, l2p, l1p, p;
+ unsigned long va = (unsigned long)guest_va;
uint64_t *l3, *l2, *l1;
static void *v[MAX_VIRT_CPUS];
@@ -380,12 +378,12 @@ map_domain_va(
if (!paging_enabled(&ctxt[cpu])) {
static void * v;
- unsigned long page;
+ uint64_t page;
if ( v != NULL )
munmap(v, PAGE_SIZE);
- page = to_ma(cpu, page_array[va >> PAGE_SHIFT]);
+ page = to_ma(cpu, va);
v = xc_map_foreign_range( xc_handle, current_domid, PAGE_SIZE,
perm, page >> PAGE_SHIFT);
diff --git a/tools/pygrub/src/pygrub b/tools/pygrub/src/pygrub
index 8fb43ca680..a0de67df67 100644
--- a/tools/pygrub/src/pygrub
+++ b/tools/pygrub/src/pygrub
@@ -13,7 +13,7 @@
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
-import os, sys, string, struct, tempfile
+import os, sys, string, struct, tempfile, re
import copy
import logging
@@ -48,8 +48,7 @@ def is_disk_image(file):
return True
return False
-SECTOR_SIZE=512
-def get_active_offset(file):
+def get_active_partition(file):
"""Find the offset for the start of the first active partition "
"in the disk image file."""
@@ -58,13 +57,56 @@ def get_active_offset(file):
for poff in (446, 462, 478, 494): # partition offsets
# active partition has 0x80 as the first byte
if struct.unpack("<c", buf[poff:poff+1]) == ('\x80',):
- return struct.unpack("<L",
- buf[poff+8:poff+12])[0] * SECTOR_SIZE
+ return buf[poff:poff+16]
# if there's not a partition marked as active, fall back to
# the first partition
- P1 = 446
- return struct.unpack("<L", buf[P1+8:P1+12])[0] * SECTOR_SIZE
+ return buf[446:446+16]
+
+SECTOR_SIZE=512
+DK_LABEL_LOC=1
+DKL_MAGIC=0xdabe
+V_ROOT=0x2
+
+def get_solaris_slice(file, offset):
+ """Find the root slice in a Solaris VTOC."""
+
+ fd = os.open(file, os.O_RDONLY)
+ os.lseek(fd, offset + (DK_LABEL_LOC * SECTOR_SIZE), 0)
+ buf = os.read(fd, 512)
+ if struct.unpack("<H", buf[508:510])[0] != DKL_MAGIC:
+ raise RuntimeError, "Invalid disklabel magic"
+
+ nslices = struct.unpack("<H", buf[30:32])[0]
+
+ for i in range(nslices):
+ sliceoff = 72 + 12 * i
+ slicetag = struct.unpack("<H", buf[sliceoff:sliceoff+2])[0]
+ slicesect = struct.unpack("<L", buf[sliceoff+4:sliceoff+8])[0]
+ if slicetag == V_ROOT:
+ return slicesect * SECTOR_SIZE
+
+ raise RuntimeError, "No root slice found"
+
+FDISK_PART_SOLARIS=0xbf
+FDISK_PART_SOLARIS_OLD=0x82
+
+def get_fs_offset(file):
+ if not is_disk_image(file):
+ return 0
+
+ partbuf = get_active_partition(file)
+ if len(partbuf) == 0:
+ raise RuntimeError, "Unable to find active partition on disk"
+
+ offset = struct.unpack("<L", partbuf[8:12])[0] * SECTOR_SIZE
+
+ type = struct.unpack("<B", partbuf[4:5])[0]
+
+ if type == FDISK_PART_SOLARIS or type == FDISK_PART_SOLARIS_OLD:
+ offset += get_solaris_slice(file, offset)
+
+ return offset
class GrubLineEditor(curses.textpad.Textbox):
def __init__(self, screen, startx, starty, line = ""):
@@ -143,12 +185,12 @@ class GrubLineEditor(curses.textpad.Textbox):
class Grub:
- def __init__(self, file, isconfig = False):
+ def __init__(self, file, fs = None):
self.screen = None
self.entry_win = None
self.text_win = None
if file:
- self.read_config(file, isconfig)
+ self.read_config(file, fs)
def draw_main_windows(self):
if self.screen is None: #only init stuff once
@@ -295,8 +337,8 @@ class Grub:
# else, we cancelled and should just go back
break
- def read_config(self, fn, isConfig = False):
- """Read the given file to parse the config. If isconfig, then
+ def read_config(self, fn, fs = None):
+ """Read the given file to parse the config. If fs = None, then
we're being given a raw config file rather than a disk image."""
if not os.access(fn, os.R_OK):
@@ -304,38 +346,25 @@ class Grub:
self.cf = grub.GrubConf.GrubConfigFile()
- if isConfig:
+ if not fs:
# set the config file and parse it
self.cf.filename = fn
self.cf.parse()
return
- offset = 0
- if is_disk_image(fn):
- offset = get_active_offset(fn)
- if offset == -1:
- raise RuntimeError, "Unable to find active partition on disk"
-
- # open the image and read the grub config
- fs = fsimage.open(fn, offset)
-
- if fs is not None:
- grubfile = None
- for f in ("/boot/grub/menu.lst", "/boot/grub/grub.conf",
- "/grub/menu.lst", "/grub/grub.conf"):
- if fs.file_exists(f):
- grubfile = f
- break
- if grubfile is None:
- raise RuntimeError, "we couldn't find grub config file in the image provided."
- f = fs.open_file(grubfile)
- buf = f.read()
- del f
- del fs
- # then parse the grub config
- self.cf.parse(buf)
- else:
- raise RuntimeError, "Unable to read filesystem"
+ grubfile = None
+ for f in ("/boot/grub/menu.lst", "/boot/grub/grub.conf",
+ "/grub/menu.lst", "/grub/grub.conf"):
+ if fs.file_exists(f):
+ grubfile = f
+ break
+ if grubfile is None:
+ raise RuntimeError, "we couldn't find grub config file in the image provided."
+ f = fs.open_file(grubfile)
+ buf = f.read()
+ del f
+ # then parse the grub config
+ self.cf.parse(buf)
def run(self):
timeout = int(self.cf.timeout)
@@ -376,6 +405,9 @@ class Grub:
c = self.screen.getch()
if mytime != -1:
mytime += 1
+ if mytime >= int(timeout):
+ self.isdone = True
+ break
# handle keypresses
if c == ord('c'):
@@ -431,19 +463,93 @@ def get_entry_idx(cf, entry):
return None
-if __name__ == "__main__":
- sel = None
-
+def run_grub(file, entry, fs):
+ global g
+ global sel
+
def run_main(scr, *args):
global sel
+ global g
sel = g.run()
+ g = Grub(file, fs)
+ if interactive:
+ curses.wrapper(run_main)
+ else:
+ sel = g.cf.default
+
+ # set the entry to boot as requested
+ if entry is not None:
+ idx = get_entry_idx(g.cf, entry)
+ if idx is not None and idx > 0 and idx < len(g.cf.images):
+ sel = idx
+
+ if sel == -1:
+ print "No kernel image selected!"
+ sys.exit(1)
+
+ img = g.cf.images[sel]
+
+ grubcfg = { "kernel": None, "ramdisk": None, "args": None }
+
+ grubcfg["kernel"] = img.kernel[1]
+ if img.initrd:
+ grubcfg["ramdisk"] = img.initrd[1]
+ if img.args:
+ grubcfg["args"] = img.args
+
+ return grubcfg
+
+# If nothing has been specified, look for a Solaris domU. If found, perform the
+# necessary tweaks.
+def sniff_solaris(fs, cfg):
+ if not fs.file_exists("/platform/i86xen/kernel/unix"):
+ return cfg
+
+ # darned python
+ longmode = (sys.maxint != 2147483647L)
+ if not longmode:
+ longmode = os.uname()[4] == "x86_64"
+ if not longmode:
+ if (os.access("/usr/bin/isainfo", os.R_OK) and
+ os.popen("/usr/bin/isainfo -b").read() == "64\n"):
+ longmode = True
+
+ if not cfg["kernel"]:
+ cfg["kernel"] = "/platform/i86xen/kernel/unix"
+ cfg["ramdisk"] = "/platform/i86pc/boot_archive"
+ if longmode:
+ cfg["kernel"] = "/platform/i86xen/kernel/amd64/unix"
+ cfg["ramdisk"] = "/platform/i86pc/amd64/boot_archive"
+
+ # Unpleasant. Typically we'll have 'root=foo -k' or 'root=foo /kernel -k',
+ # and we need to maintain Xen properties (root= and ip=) and the kernel
+ # before any user args.
+
+ xenargs = ""
+ userargs = ""
+
+ if not cfg["args"]:
+ cfg["args"] = cfg["kernel"]
+ else:
+ for arg in cfg["args"].split():
+ if re.match("^root=", arg) or re.match("^ip=", arg):
+ xenargs += arg + " "
+ elif arg != cfg["kernel"]:
+ userargs += arg + " "
+ cfg["args"] = xenargs + " " + cfg["kernel"] + " " + userargs
+
+ return cfg
+
+if __name__ == "__main__":
+ sel = None
+
def usage():
- print >> sys.stderr, "Usage: %s [-q|--quiet] [--output=] [--entry=] <image>" %(sys.argv[0],)
+ print >> sys.stderr, "Usage: %s [-q|--quiet] [--output=] [--kernel=] [--ramdisk=] [--args=] [--entry=] <image>" %(sys.argv[0],)
try:
opts, args = getopt.gnu_getopt(sys.argv[1:], 'qh::',
- ["quiet", "help", "output=", "entry=",
+ ["quiet", "help", "output=", "entry=", "kernel=", "ramdisk=", "args=",
"isconfig"])
except getopt.GetoptError:
usage()
@@ -458,6 +564,14 @@ if __name__ == "__main__":
entry = None
interactive = True
isconfig = False
+
+ # what was passed in
+ incfg = { "kernel": None, "ramdisk": None, "args": None }
+ # what grub or sniffing chose
+ chosencfg = { "kernel": None, "ramdisk": None, "args": None }
+ # what to boot
+ bootcfg = { "kernel": None, "ramdisk": None, "args": None }
+
for o, a in opts:
if o in ("-q", "--quiet"):
interactive = False
@@ -466,6 +580,12 @@ if __name__ == "__main__":
sys.exit()
elif o in ("--output",):
output = a
+ elif o in ("--kernel",):
+ incfg["kernel"] = a
+ elif o in ("--ramdisk",):
+ incfg["ramdisk"] = a
+ elif o in ("--args",):
+ incfg["args"] = a
elif o in ("--entry",):
entry = a
# specifying the entry to boot implies non-interactive
@@ -478,58 +598,42 @@ if __name__ == "__main__":
else:
fd = os.open(output, os.O_WRONLY)
- g = Grub(file, isconfig)
- if interactive:
- curses.wrapper(run_main)
- else:
- sel = g.cf.default
-
- # set the entry to boot as requested
- if entry is not None:
- idx = get_entry_idx(g.cf, entry)
- if idx is not None and idx > 0 and idx < len(g.cf.images):
- sel = idx
-
- if sel == -1:
- print "No kernel image selected!"
- sys.exit(1)
-
- img = g.cf.images[sel]
- print "Going to boot %s" %(img.title)
- print " kernel: %s" %(img.kernel[1],)
- if img.initrd:
- print " initrd: %s" %(img.initrd[1],)
-
+ # debug
if isconfig:
- print " args: %s" %(img.args,)
+ chosencfg = run_grub(file, entry)
+ print " kernel: %s" % chosencfg["kernel"]
+ if img.initrd:
+ print " initrd: %s" % chosencfg["ramdisk"]
+ print " args: %s" % chosencfg["args"]
sys.exit(0)
-
- offset = 0
- if is_disk_image(file):
- offset = get_active_offset(file)
- if offset == -1:
- raise RuntimeError, "Unable to find active partition on disk"
- # read the kernel and initrd onto the hostfs
- fs = fsimage.open(file, offset)
+ fs = fsimage.open(file, get_fs_offset(file))
- kernel = fs.open_file(img.kernel[1],).read()
- (tfd, fn) = tempfile.mkstemp(prefix="boot_kernel.",
+ chosencfg = sniff_solaris(fs, incfg)
+
+ if not chosencfg["kernel"]:
+ chosencfg = run_grub(file, entry, fs)
+
+ data = fs.open_file(chosencfg["kernel"]).read()
+ (tfd, bootcfg["kernel"]) = tempfile.mkstemp(prefix="boot_kernel.",
dir="/var/run/xend/boot")
- os.write(tfd, kernel)
+ os.write(tfd, data)
os.close(tfd)
- sxp = "linux (kernel %s)" %(fn,)
- if img.initrd:
- initrd = fs.open_file(img.initrd[1],).read()
- (tfd, fn) = tempfile.mkstemp(prefix="boot_ramdisk.",
+ if chosencfg["ramdisk"]:
+ data = fs.open_file(chosencfg["ramdisk"],).read()
+ (tfd, bootcfg["ramdisk"]) = tempfile.mkstemp(prefix="boot_ramdisk.",
dir="/var/run/xend/boot")
- os.write(tfd, initrd)
+ os.write(tfd, data)
os.close(tfd)
- sxp += "(ramdisk %s)" %(fn,)
else:
initrd = None
- sxp += "(args '%s')" %(img.args,)
+
+ sxp = "linux (kernel %s)" % bootcfg["kernel"]
+ if bootcfg["ramdisk"]:
+ sxp += "(ramdisk %s)" % bootcfg["ramdisk"]
+ if chosencfg["args"]:
+ sxp += "(args \"%s\")" % chosencfg["args"]
sys.stdout.flush()
os.write(fd, sxp)
diff --git a/tools/python/xen/xend/XendBootloader.py b/tools/python/xen/xend/XendBootloader.py
index 170b637222..66d8427bff 100644
--- a/tools/python/xen/xend/XendBootloader.py
+++ b/tools/python/xen/xend/XendBootloader.py
@@ -53,6 +53,12 @@ def bootloader(blexec, disk, quiet = False, blargs = '', kernel = '',
child = os.fork()
if (not child):
args = [ blexec ]
+ if kernel:
+ args.append("--kernel=%s" % kernel)
+ if ramdisk:
+ args.append("--ramdisk=%s" % ramdisk)
+ if kernel_args:
+ args.append("--args=%s" % kernel_args)
if quiet:
args.append("-q")
args.append("--output=%s" % fifo)
diff --git a/tools/python/xen/xend/XendCheckpoint.py b/tools/python/xen/xend/XendCheckpoint.py
index 85a59e5d22..106e20fb3d 100644
--- a/tools/python/xen/xend/XendCheckpoint.py
+++ b/tools/python/xen/xend/XendCheckpoint.py
@@ -147,18 +147,20 @@ def restore(xd, fd, dominfo = None, paused = False):
assert store_port
assert console_port
+ nr_pfns = (dominfo.getMemoryTarget() + 3) / 4
+
try:
l = read_exact(fd, sizeof_unsigned_long,
"not a valid guest state file: pfn count read")
- nr_pfns = unpack("L", l)[0] # native sizeof long
- if nr_pfns > 16*1024*1024: # XXX
+ max_pfn = unpack("L", l)[0] # native sizeof long
+ if max_pfn > 16*1024*1024: # XXX
raise XendError(
"not a valid guest state file: pfn count out of range")
balloon.free(xc.pages_to_kib(nr_pfns))
cmd = map(str, [xen.util.auxbin.pathTo(XC_RESTORE),
- fd, dominfo.getDomid(), nr_pfns,
+ fd, dominfo.getDomid(), max_pfn,
store_port, console_port])
log.debug("[xc_restore]: %s", string.join(cmd))
diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py
index cfd2c20e6e..fd9afb0b3a 100644
--- a/tools/python/xen/xend/XendConfig.py
+++ b/tools/python/xen/xend/XendConfig.py
@@ -126,6 +126,7 @@ XENAPI_CFG_TYPES = {
'memory_dynamic_min': int,
'memory_dynamic_max': int,
'memory_actual': int,
+ 'cpus': list,
'vcpus_policy': str,
'vcpus_params': str,
'vcpus_number': int,
@@ -1020,10 +1021,11 @@ class XendConfig(dict):
@return: Returns True if succesfully found and updated a device conf
"""
if dev_uuid in self['devices']:
- config = sxp.child0(cfg_sxp)
- dev_type = sxp.name(config)
- dev_info = {}
-
+ if sxp.child0(cfg_sxp) == 'device':
+ config = sxp.child0(cfg_sxp)
+ else:
+ config = cfg_sxp
+
for opt_val in config[1:]:
try:
opt, val = opt_val
diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py
index 6ea6ae075b..4257057398 100644
--- a/tools/python/xen/xend/XendDomain.py
+++ b/tools/python/xen/xend/XendDomain.py
@@ -377,7 +377,7 @@ class XendDomain:
dom0.setVCpuCount(target)
- def _refresh(self):
+ def _refresh(self, refresh_shutdown = True):
"""Refresh the domain list. Needs to be called when
either xenstore has changed or when a method requires
up to date information (like uptime, cputime stats).
@@ -393,7 +393,7 @@ class XendDomain:
for dom in running:
domid = dom['domid']
if domid in self.domains:
- self.domains[domid].update(dom)
+ self.domains[domid].update(dom, refresh_shutdown)
elif domid not in self.domains and dom['dying'] != 1:
try:
new_dom = XendDomainInfo.recreate(dom, False)
@@ -495,7 +495,7 @@ class XendDomain:
"""
self.domains_lock.acquire()
try:
- self._refresh()
+ self._refresh(refresh_shutdown = False)
dom = self.domain_lookup_nr(domid)
if not dom:
raise XendError("No domain named '%s'." % str(domid))
@@ -731,7 +731,7 @@ class XendDomain:
self.domains_lock.acquire()
try:
- self._refresh()
+ self._refresh(refresh_shutdown = False)
# active domains
active_domains = self.domains.values()
diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py
index 3a2fa3ef4f..f80c3f5be7 100644
--- a/tools/python/xen/xend/XendDomainInfo.py
+++ b/tools/python/xen/xend/XendDomainInfo.py
@@ -37,7 +37,7 @@ from xen.util import asserts
from xen.util.blkif import blkdev_uname_to_file
from xen.util import security
-from xen.xend import balloon, sxp, uuid, image, arch
+from xen.xend import balloon, sxp, uuid, image, arch, osdep
from xen.xend import XendRoot, XendNode, XendConfig
from xen.xend.XendConfig import scrub_password
@@ -496,7 +496,7 @@ class XendDomainInfo:
self._waitForDevice(dev_type, devid)
return self.getDeviceController(dev_type).sxpr(devid)
- def device_configure(self, dev_config, devid = None):
+ def device_configure(self, dev_sxp, devid = None):
"""Configure an existing device.
@param dev_config: device configuration
@@ -506,19 +506,24 @@ class XendDomainInfo:
@return: Returns True if successfully updated device
@rtype: boolean
"""
- deviceClass = sxp.name(dev_config)
-
- # look up uuid of the device
- dev_control = self.getDeviceController(deviceClass)
- dev_sxpr = dev_control.sxpr(devid)
- dev_uuid = sxp.child_value(dev_sxpr, 'uuid')
- if not dev_uuid:
- return False
- self.info.device_update(dev_uuid, dev_config)
- dev_config_dict = self.info['devices'].get(dev_uuid)
- if dev_config_dict:
- dev_control.reconfigureDevice(devid, dev_config_dict[1])
+ # convert device sxp to a dict
+ dev_class = sxp.name(dev_sxp)
+ dev_config = {}
+ for opt_val in dev_sxp[1:]:
+ try:
+ dev_config[opt_val[0]] = opt_val[1]
+ except IndexError:
+ pass
+
+ # use DevController.reconfigureDevice to change device config
+ dev_control = self.getDeviceController(dev_class)
+ dev_uuid = dev_control.reconfigureDevice(devid, dev_config)
+
+ # update XendConfig with new device info
+ if dev_uuid:
+ self.info.device_update(dev_uuid, dev_sxp)
+
return True
def waitForDevices(self):
@@ -1575,7 +1580,7 @@ class XendDomainInfo:
else:
# Boot using bootloader
if not blexec or blexec == 'pygrub':
- blexec = '/usr/bin/pygrub'
+ blexec = osdep.pygrub_path
blcfg = None
for (devtype, devinfo) in self.info.all_devices_sxpr():
diff --git a/tools/python/xen/xend/XendNode.py b/tools/python/xen/xend/XendNode.py
index 117ca3d25d..932c05d207 100644
--- a/tools/python/xen/xend/XendNode.py
+++ b/tools/python/xen/xend/XendNode.py
@@ -365,14 +365,24 @@ class XendNode:
return [[k, info[k]] for k in ITEM_ORDER]
+ def xenschedinfo(self):
+ sched_id = self.xc.sched_id_get()
+ if sched_id == xen.lowlevel.xc.XEN_SCHEDULER_SEDF:
+ return 'sedf'
+ elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT:
+ return 'credit'
+ else:
+ return 'unknown'
def xeninfo(self):
info = self.xc.xeninfo()
+ info['xen_scheduler'] = self.xenschedinfo()
ITEM_ORDER = ['xen_major',
'xen_minor',
'xen_extra',
'xen_caps',
+ 'xen_scheduler',
'xen_pagesize',
'platform_params',
'xen_changeset',
diff --git a/tools/python/xen/xend/osdep.py b/tools/python/xen/xend/osdep.py
index 35af7c55af..1dd3c7c1dd 100644
--- a/tools/python/xen/xend/osdep.py
+++ b/tools/python/xen/xend/osdep.py
@@ -29,8 +29,13 @@ _xend_autorestart = {
"SunOS": False,
}
+_pygrub_path = {
+ "SunOS": "/usr/lib/xen/bin/pygrub"
+}
+
def _get(var, default=None):
return var.get(os.uname()[0], default)
scripts_dir = _get(_scripts_dir, "/etc/xen/scripts")
xend_autorestart = _get(_xend_autorestart)
+pygrub_path = _get(_pygrub_path, "/usr/bin/pygrub")
diff --git a/tools/python/xen/xend/server/blkif.py b/tools/python/xen/xend/server/blkif.py
index 44d1a1e1ff..72a0787d93 100644
--- a/tools/python/xen/xend/server/blkif.py
+++ b/tools/python/xen/xend/server/blkif.py
@@ -101,6 +101,7 @@ class BlkifController(DevController):
self.writeBackend(devid,
'type', new_back['type'],
'params', new_back['params'])
+ return new_back.get('uuid')
else:
raise VmError('Refusing to reconfigure device %s:%d to %s' %
(self.deviceClass, devid, config))
diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py
index 1726979aaa..e0fe857885 100644
--- a/tools/python/xen/xm/create.py
+++ b/tools/python/xen/xm/create.py
@@ -28,6 +28,7 @@ import xmlrpclib
from xen.xend import sxp
from xen.xend import PrettyPrint
+from xen.xend import osdep
import xen.xend.XendClient
from xen.xend.XendBootloader import bootloader
from xen.util import blkif
@@ -291,7 +292,8 @@ gopts.var('vfb', val="type={vnc,sdl},vncunused=1,vncdisplay=N,vnclisten=ADDR,dis
For type=vnc, connect an external vncviewer. The server will listen
on ADDR (default 127.0.0.1) on port N+5900. N defaults to the
domain id. If vncunused=1, the server will try to find an arbitrary
- unused port above 5900.
+ unused port above 5900. vncpasswd overrides the XenD configured
+ default password.
For type=sdl, a viewer will be started automatically using the
given DISPLAY and XAUTHORITY, which default to the current user's
ones.""")
@@ -718,8 +720,11 @@ def run_bootloader(vals, config_image):
"--entry= directly.")
vals.bootargs = "--entry=%s" %(vals.bootentry,)
+ kernel = sxp.child_value(config_image, 'kernel')
+ ramdisk = sxp.child_value(config_image, 'ramdisk')
+ args = sxp.child_value(config_image, 'args')
return bootloader(vals.bootloader, file, not vals.console_autoconnect,
- vals.bootargs, config_image)
+ vals.bootargs, kernel, ramdisk, args)
def make_config(vals):
"""Create the domain configuration.
@@ -759,7 +764,14 @@ def make_config(vals):
config_image = configure_image(vals)
if vals.bootloader:
- config_image = run_bootloader(vals, config_image)
+ if vals.bootloader == "pygrub":
+ vals.bootloader = osdep.pygrub_path
+
+ # if a kernel is specified, we're using the bootloader
+ # non-interactively, and need to let xend run it so we preserve the
+ # real kernel choice.
+ if not vals.kernel:
+ config_image = run_bootloader(vals, config_image)
config.append(['bootloader', vals.bootloader])
if vals.bootargs:
config.append(['bootloader_args', vals.bootargs])
@@ -990,8 +1002,6 @@ def preprocess_vnc(vals):
vals.extra = vnc + ' ' + vals.extra
def preprocess(vals):
- if not vals.kernel and not vals.bootloader:
- err("No kernel specified")
preprocess_disk(vals)
preprocess_pci(vals)
preprocess_ioports(vals)
diff --git a/tools/tests/Makefile b/tools/tests/Makefile
index 263caffb46..45d4294f9a 100644
--- a/tools/tests/Makefile
+++ b/tools/tests/Makefile
@@ -7,12 +7,21 @@ TARGET := test_x86_emulator
.PHONY: all
all: $(TARGET)
+.PHONY: blowfish.bin
+blowfish.bin:
+ make -f blowfish.mk all
+
+blowfish.h: blowfish.bin
+ (echo "static unsigned int blowfish_code[] = {"; \
+ od -v -t x $< | sed 's/^[0-9]* /0x/' | sed 's/ /, 0x/g' | sed 's/$$/,/';\
+ echo "};") >$@
+
$(TARGET): x86_emulate.o test_x86_emulator.o
$(HOSTCC) -o $@ $^
.PHONY: clean
clean:
- rm -rf $(TARGET) *.o *~ core
+ rm -rf $(TARGET) *.o *~ core blowfish.h blowfish.bin
.PHONY: install
install:
@@ -20,5 +29,5 @@ install:
x86_emulate.o: $(XEN_ROOT)/xen/arch/x86/x86_emulate.c
$(HOSTCC) $(HOSTCFLAGS) -I$(XEN_ROOT)/xen/include -c -o $@ $<
-%.o: %.c
+test_x86_emulator.o: test_x86_emulator.c blowfish.h
$(HOSTCC) $(HOSTCFLAGS) -I$(XEN_ROOT)/xen/include -c -o $@ $<
diff --git a/tools/tests/blowfish.c b/tools/tests/blowfish.c
new file mode 100644
index 0000000000..12e77c29dc
--- /dev/null
+++ b/tools/tests/blowfish.c
@@ -0,0 +1,439 @@
+/*
+blowfish.c: C implementation of the Blowfish algorithm.
+
+Copyright (C) 1997 by Paul Kocher
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
+#define __attribute_used__ __attribute__((__used__))
+#else
+#define __attribute_used__ __attribute__((__unused__))
+#endif
+
+static unsigned long long blowfish_test(unsigned long long input)
+ __attribute_used__;
+
+asm (
+ ".globl _start\n"
+ "_start:\n"
+ "push %edx; push %eax; "
+ "call blowfish_test; "
+ "addl $8,%esp; "
+ "ret"
+ );
+
+typedef struct {
+ unsigned long P[16 + 2];
+ unsigned long S[4][256];
+} BLOWFISH_CTX;
+
+#define N 16
+
+static const unsigned long ORIG_P[16 + 2] = {
+ 0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L,
+ 0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L,
+ 0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL,
+ 0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L,
+ 0x9216D5D9L, 0x8979FB1BL
+};
+
+static const unsigned long ORIG_S[4][256] = {
+ { 0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L,
+ 0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L,
+ 0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L,
+ 0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL,
+ 0x0D95748FL, 0x728EB658L, 0x718BCD58L, 0x82154AEEL,
+ 0x7B54A41DL, 0xC25A59B5L, 0x9C30D539L, 0x2AF26013L,
+ 0xC5D1B023L, 0x286085F0L, 0xCA417918L, 0xB8DB38EFL,
+ 0x8E79DCB0L, 0x603A180EL, 0x6C9E0E8BL, 0xB01E8A3EL,
+ 0xD71577C1L, 0xBD314B27L, 0x78AF2FDAL, 0x55605C60L,
+ 0xE65525F3L, 0xAA55AB94L, 0x57489862L, 0x63E81440L,
+ 0x55CA396AL, 0x2AAB10B6L, 0xB4CC5C34L, 0x1141E8CEL,
+ 0xA15486AFL, 0x7C72E993L, 0xB3EE1411L, 0x636FBC2AL,
+ 0x2BA9C55DL, 0x741831F6L, 0xCE5C3E16L, 0x9B87931EL,
+ 0xAFD6BA33L, 0x6C24CF5CL, 0x7A325381L, 0x28958677L,
+ 0x3B8F4898L, 0x6B4BB9AFL, 0xC4BFE81BL, 0x66282193L,
+ 0x61D809CCL, 0xFB21A991L, 0x487CAC60L, 0x5DEC8032L,
+ 0xEF845D5DL, 0xE98575B1L, 0xDC262302L, 0xEB651B88L,
+ 0x23893E81L, 0xD396ACC5L, 0x0F6D6FF3L, 0x83F44239L,
+ 0x2E0B4482L, 0xA4842004L, 0x69C8F04AL, 0x9E1F9B5EL,
+ 0x21C66842L, 0xF6E96C9AL, 0x670C9C61L, 0xABD388F0L,
+ 0x6A51A0D2L, 0xD8542F68L, 0x960FA728L, 0xAB5133A3L,
+ 0x6EEF0B6CL, 0x137A3BE4L, 0xBA3BF050L, 0x7EFB2A98L,
+ 0xA1F1651DL, 0x39AF0176L, 0x66CA593EL, 0x82430E88L,
+ 0x8CEE8619L, 0x456F9FB4L, 0x7D84A5C3L, 0x3B8B5EBEL,
+ 0xE06F75D8L, 0x85C12073L, 0x401A449FL, 0x56C16AA6L,
+ 0x4ED3AA62L, 0x363F7706L, 0x1BFEDF72L, 0x429B023DL,
+ 0x37D0D724L, 0xD00A1248L, 0xDB0FEAD3L, 0x49F1C09BL,
+ 0x075372C9L, 0x80991B7BL, 0x25D479D8L, 0xF6E8DEF7L,
+ 0xE3FE501AL, 0xB6794C3BL, 0x976CE0BDL, 0x04C006BAL,
+ 0xC1A94FB6L, 0x409F60C4L, 0x5E5C9EC2L, 0x196A2463L,
+ 0x68FB6FAFL, 0x3E6C53B5L, 0x1339B2EBL, 0x3B52EC6FL,
+ 0x6DFC511FL, 0x9B30952CL, 0xCC814544L, 0xAF5EBD09L,
+ 0xBEE3D004L, 0xDE334AFDL, 0x660F2807L, 0x192E4BB3L,
+ 0xC0CBA857L, 0x45C8740FL, 0xD20B5F39L, 0xB9D3FBDBL,
+ 0x5579C0BDL, 0x1A60320AL, 0xD6A100C6L, 0x402C7279L,
+ 0x679F25FEL, 0xFB1FA3CCL, 0x8EA5E9F8L, 0xDB3222F8L,
+ 0x3C7516DFL, 0xFD616B15L, 0x2F501EC8L, 0xAD0552ABL,
+ 0x323DB5FAL, 0xFD238760L, 0x53317B48L, 0x3E00DF82L,
+ 0x9E5C57BBL, 0xCA6F8CA0L, 0x1A87562EL, 0xDF1769DBL,
+ 0xD542A8F6L, 0x287EFFC3L, 0xAC6732C6L, 0x8C4F5573L,
+ 0x695B27B0L, 0xBBCA58C8L, 0xE1FFA35DL, 0xB8F011A0L,
+ 0x10FA3D98L, 0xFD2183B8L, 0x4AFCB56CL, 0x2DD1D35BL,
+ 0x9A53E479L, 0xB6F84565L, 0xD28E49BCL, 0x4BFB9790L,
+ 0xE1DDF2DAL, 0xA4CB7E33L, 0x62FB1341L, 0xCEE4C6E8L,
+ 0xEF20CADAL, 0x36774C01L, 0xD07E9EFEL, 0x2BF11FB4L,
+ 0x95DBDA4DL, 0xAE909198L, 0xEAAD8E71L, 0x6B93D5A0L,
+ 0xD08ED1D0L, 0xAFC725E0L, 0x8E3C5B2FL, 0x8E7594B7L,
+ 0x8FF6E2FBL, 0xF2122B64L, 0x8888B812L, 0x900DF01CL,
+ 0x4FAD5EA0L, 0x688FC31CL, 0xD1CFF191L, 0xB3A8C1ADL,
+ 0x2F2F2218L, 0xBE0E1777L, 0xEA752DFEL, 0x8B021FA1L,
+ 0xE5A0CC0FL, 0xB56F74E8L, 0x18ACF3D6L, 0xCE89E299L,
+ 0xB4A84FE0L, 0xFD13E0B7L, 0x7CC43B81L, 0xD2ADA8D9L,
+ 0x165FA266L, 0x80957705L, 0x93CC7314L, 0x211A1477L,
+ 0xE6AD2065L, 0x77B5FA86L, 0xC75442F5L, 0xFB9D35CFL,
+ 0xEBCDAF0CL, 0x7B3E89A0L, 0xD6411BD3L, 0xAE1E7E49L,
+ 0x00250E2DL, 0x2071B35EL, 0x226800BBL, 0x57B8E0AFL,
+ 0x2464369BL, 0xF009B91EL, 0x5563911DL, 0x59DFA6AAL,
+ 0x78C14389L, 0xD95A537FL, 0x207D5BA2L, 0x02E5B9C5L,
+ 0x83260376L, 0x6295CFA9L, 0x11C81968L, 0x4E734A41L,
+ 0xB3472DCAL, 0x7B14A94AL, 0x1B510052L, 0x9A532915L,
+ 0xD60F573FL, 0xBC9BC6E4L, 0x2B60A476L, 0x81E67400L,
+ 0x08BA6FB5L, 0x571BE91FL, 0xF296EC6BL, 0x2A0DD915L,
+ 0xB6636521L, 0xE7B9F9B6L, 0xFF34052EL, 0xC5855664L,
+ 0x53B02D5DL, 0xA99F8FA1L, 0x08BA4799L, 0x6E85076AL },
+ { 0x4B7A70E9L, 0xB5B32944L, 0xDB75092EL, 0xC4192623L,
+ 0xAD6EA6B0L, 0x49A7DF7DL, 0x9CEE60B8L, 0x8FEDB266L,
+ 0xECAA8C71L, 0x699A17FFL, 0x5664526CL, 0xC2B19EE1L,
+ 0x193602A5L, 0x75094C29L, 0xA0591340L, 0xE4183A3EL,
+ 0x3F54989AL, 0x5B429D65L, 0x6B8FE4D6L, 0x99F73FD6L,
+ 0xA1D29C07L, 0xEFE830F5L, 0x4D2D38E6L, 0xF0255DC1L,
+ 0x4CDD2086L, 0x8470EB26L, 0x6382E9C6L, 0x021ECC5EL,
+ 0x09686B3FL, 0x3EBAEFC9L, 0x3C971814L, 0x6B6A70A1L,
+ 0x687F3584L, 0x52A0E286L, 0xB79C5305L, 0xAA500737L,
+ 0x3E07841CL, 0x7FDEAE5CL, 0x8E7D44ECL, 0x5716F2B8L,
+ 0xB03ADA37L, 0xF0500C0DL, 0xF01C1F04L, 0x0200B3FFL,
+ 0xAE0CF51AL, 0x3CB574B2L, 0x25837A58L, 0xDC0921BDL,
+ 0xD19113F9L, 0x7CA92FF6L, 0x94324773L, 0x22F54701L,
+ 0x3AE5E581L, 0x37C2DADCL, 0xC8B57634L, 0x9AF3DDA7L,
+ 0xA9446146L, 0x0FD0030EL, 0xECC8C73EL, 0xA4751E41L,
+ 0xE238CD99L, 0x3BEA0E2FL, 0x3280BBA1L, 0x183EB331L,
+ 0x4E548B38L, 0x4F6DB908L, 0x6F420D03L, 0xF60A04BFL,
+ 0x2CB81290L, 0x24977C79L, 0x5679B072L, 0xBCAF89AFL,
+ 0xDE9A771FL, 0xD9930810L, 0xB38BAE12L, 0xDCCF3F2EL,
+ 0x5512721FL, 0x2E6B7124L, 0x501ADDE6L, 0x9F84CD87L,
+ 0x7A584718L, 0x7408DA17L, 0xBC9F9ABCL, 0xE94B7D8CL,
+ 0xEC7AEC3AL, 0xDB851DFAL, 0x63094366L, 0xC464C3D2L,
+ 0xEF1C1847L, 0x3215D908L, 0xDD433B37L, 0x24C2BA16L,
+ 0x12A14D43L, 0x2A65C451L, 0x50940002L, 0x133AE4DDL,
+ 0x71DFF89EL, 0x10314E55L, 0x81AC77D6L, 0x5F11199BL,
+ 0x043556F1L, 0xD7A3C76BL, 0x3C11183BL, 0x5924A509L,
+ 0xF28FE6EDL, 0x97F1FBFAL, 0x9EBABF2CL, 0x1E153C6EL,
+ 0x86E34570L, 0xEAE96FB1L, 0x860E5E0AL, 0x5A3E2AB3L,
+ 0x771FE71CL, 0x4E3D06FAL, 0x2965DCB9L, 0x99E71D0FL,
+ 0x803E89D6L, 0x5266C825L, 0x2E4CC978L, 0x9C10B36AL,
+ 0xC6150EBAL, 0x94E2EA78L, 0xA5FC3C53L, 0x1E0A2DF4L,
+ 0xF2F74EA7L, 0x361D2B3DL, 0x1939260FL, 0x19C27960L,
+ 0x5223A708L, 0xF71312B6L, 0xEBADFE6EL, 0xEAC31F66L,
+ 0xE3BC4595L, 0xA67BC883L, 0xB17F37D1L, 0x018CFF28L,
+ 0xC332DDEFL, 0xBE6C5AA5L, 0x65582185L, 0x68AB9802L,
+ 0xEECEA50FL, 0xDB2F953BL, 0x2AEF7DADL, 0x5B6E2F84L,
+ 0x1521B628L, 0x29076170L, 0xECDD4775L, 0x619F1510L,
+ 0x13CCA830L, 0xEB61BD96L, 0x0334FE1EL, 0xAA0363CFL,
+ 0xB5735C90L, 0x4C70A239L, 0xD59E9E0BL, 0xCBAADE14L,
+ 0xEECC86BCL, 0x60622CA7L, 0x9CAB5CABL, 0xB2F3846EL,
+ 0x648B1EAFL, 0x19BDF0CAL, 0xA02369B9L, 0x655ABB50L,
+ 0x40685A32L, 0x3C2AB4B3L, 0x319EE9D5L, 0xC021B8F7L,
+ 0x9B540B19L, 0x875FA099L, 0x95F7997EL, 0x623D7DA8L,
+ 0xF837889AL, 0x97E32D77L, 0x11ED935FL, 0x16681281L,
+ 0x0E358829L, 0xC7E61FD6L, 0x96DEDFA1L, 0x7858BA99L,
+ 0x57F584A5L, 0x1B227263L, 0x9B83C3FFL, 0x1AC24696L,
+ 0xCDB30AEBL, 0x532E3054L, 0x8FD948E4L, 0x6DBC3128L,
+ 0x58EBF2EFL, 0x34C6FFEAL, 0xFE28ED61L, 0xEE7C3C73L,
+ 0x5D4A14D9L, 0xE864B7E3L, 0x42105D14L, 0x203E13E0L,
+ 0x45EEE2B6L, 0xA3AAABEAL, 0xDB6C4F15L, 0xFACB4FD0L,
+ 0xC742F442L, 0xEF6ABBB5L, 0x654F3B1DL, 0x41CD2105L,
+ 0xD81E799EL, 0x86854DC7L, 0xE44B476AL, 0x3D816250L,
+ 0xCF62A1F2L, 0x5B8D2646L, 0xFC8883A0L, 0xC1C7B6A3L,
+ 0x7F1524C3L, 0x69CB7492L, 0x47848A0BL, 0x5692B285L,
+ 0x095BBF00L, 0xAD19489DL, 0x1462B174L, 0x23820E00L,
+ 0x58428D2AL, 0x0C55F5EAL, 0x1DADF43EL, 0x233F7061L,
+ 0x3372F092L, 0x8D937E41L, 0xD65FECF1L, 0x6C223BDBL,
+ 0x7CDE3759L, 0xCBEE7460L, 0x4085F2A7L, 0xCE77326EL,
+ 0xA6078084L, 0x19F8509EL, 0xE8EFD855L, 0x61D99735L,
+ 0xA969A7AAL, 0xC50C06C2L, 0x5A04ABFCL, 0x800BCADCL,
+ 0x9E447A2EL, 0xC3453484L, 0xFDD56705L, 0x0E1E9EC9L,
+ 0xDB73DBD3L, 0x105588CDL, 0x675FDA79L, 0xE3674340L,
+ 0xC5C43465L, 0x713E38D8L, 0x3D28F89EL, 0xF16DFF20L,
+ 0x153E21E7L, 0x8FB03D4AL, 0xE6E39F2BL, 0xDB83ADF7L },
+ { 0xE93D5A68L, 0x948140F7L, 0xF64C261CL, 0x94692934L,
+ 0x411520F7L, 0x7602D4F7L, 0xBCF46B2EL, 0xD4A20068L,
+ 0xD4082471L, 0x3320F46AL, 0x43B7D4B7L, 0x500061AFL,
+ 0x1E39F62EL, 0x97244546L, 0x14214F74L, 0xBF8B8840L,
+ 0x4D95FC1DL, 0x96B591AFL, 0x70F4DDD3L, 0x66A02F45L,
+ 0xBFBC09ECL, 0x03BD9785L, 0x7FAC6DD0L, 0x31CB8504L,
+ 0x96EB27B3L, 0x55FD3941L, 0xDA2547E6L, 0xABCA0A9AL,
+ 0x28507825L, 0x530429F4L, 0x0A2C86DAL, 0xE9B66DFBL,
+ 0x68DC1462L, 0xD7486900L, 0x680EC0A4L, 0x27A18DEEL,
+ 0x4F3FFEA2L, 0xE887AD8CL, 0xB58CE006L, 0x7AF4D6B6L,
+ 0xAACE1E7CL, 0xD3375FECL, 0xCE78A399L, 0x406B2A42L,
+ 0x20FE9E35L, 0xD9F385B9L, 0xEE39D7ABL, 0x3B124E8BL,
+ 0x1DC9FAF7L, 0x4B6D1856L, 0x26A36631L, 0xEAE397B2L,
+ 0x3A6EFA74L, 0xDD5B4332L, 0x6841E7F7L, 0xCA7820FBL,
+ 0xFB0AF54EL, 0xD8FEB397L, 0x454056ACL, 0xBA489527L,
+ 0x55533A3AL, 0x20838D87L, 0xFE6BA9B7L, 0xD096954BL,
+ 0x55A867BCL, 0xA1159A58L, 0xCCA92963L, 0x99E1DB33L,
+ 0xA62A4A56L, 0x3F3125F9L, 0x5EF47E1CL, 0x9029317CL,
+ 0xFDF8E802L, 0x04272F70L, 0x80BB155CL, 0x05282CE3L,
+ 0x95C11548L, 0xE4C66D22L, 0x48C1133FL, 0xC70F86DCL,
+ 0x07F9C9EEL, 0x41041F0FL, 0x404779A4L, 0x5D886E17L,
+ 0x325F51EBL, 0xD59BC0D1L, 0xF2BCC18FL, 0x41113564L,
+ 0x257B7834L, 0x602A9C60L, 0xDFF8E8A3L, 0x1F636C1BL,
+ 0x0E12B4C2L, 0x02E1329EL, 0xAF664FD1L, 0xCAD18115L,
+ 0x6B2395E0L, 0x333E92E1L, 0x3B240B62L, 0xEEBEB922L,
+ 0x85B2A20EL, 0xE6BA0D99L, 0xDE720C8CL, 0x2DA2F728L,
+ 0xD0127845L, 0x95B794FDL, 0x647D0862L, 0xE7CCF5F0L,
+ 0x5449A36FL, 0x877D48FAL, 0xC39DFD27L, 0xF33E8D1EL,
+ 0x0A476341L, 0x992EFF74L, 0x3A6F6EABL, 0xF4F8FD37L,
+ 0xA812DC60L, 0xA1EBDDF8L, 0x991BE14CL, 0xDB6E6B0DL,
+ 0xC67B5510L, 0x6D672C37L, 0x2765D43BL, 0xDCD0E804L,
+ 0xF1290DC7L, 0xCC00FFA3L, 0xB5390F92L, 0x690FED0BL,
+ 0x667B9FFBL, 0xCEDB7D9CL, 0xA091CF0BL, 0xD9155EA3L,
+ 0xBB132F88L, 0x515BAD24L, 0x7B9479BFL, 0x763BD6EBL,
+ 0x37392EB3L, 0xCC115979L, 0x8026E297L, 0xF42E312DL,
+ 0x6842ADA7L, 0xC66A2B3BL, 0x12754CCCL, 0x782EF11CL,
+ 0x6A124237L, 0xB79251E7L, 0x06A1BBE6L, 0x4BFB6350L,
+ 0x1A6B1018L, 0x11CAEDFAL, 0x3D25BDD8L, 0xE2E1C3C9L,
+ 0x44421659L, 0x0A121386L, 0xD90CEC6EL, 0xD5ABEA2AL,
+ 0x64AF674EL, 0xDA86A85FL, 0xBEBFE988L, 0x64E4C3FEL,
+ 0x9DBC8057L, 0xF0F7C086L, 0x60787BF8L, 0x6003604DL,
+ 0xD1FD8346L, 0xF6381FB0L, 0x7745AE04L, 0xD736FCCCL,
+ 0x83426B33L, 0xF01EAB71L, 0xB0804187L, 0x3C005E5FL,
+ 0x77A057BEL, 0xBDE8AE24L, 0x55464299L, 0xBF582E61L,
+ 0x4E58F48FL, 0xF2DDFDA2L, 0xF474EF38L, 0x8789BDC2L,
+ 0x5366F9C3L, 0xC8B38E74L, 0xB475F255L, 0x46FCD9B9L,
+ 0x7AEB2661L, 0x8B1DDF84L, 0x846A0E79L, 0x915F95E2L,
+ 0x466E598EL, 0x20B45770L, 0x8CD55591L, 0xC902DE4CL,
+ 0xB90BACE1L, 0xBB8205D0L, 0x11A86248L, 0x7574A99EL,
+ 0xB77F19B6L, 0xE0A9DC09L, 0x662D09A1L, 0xC4324633L,
+ 0xE85A1F02L, 0x09F0BE8CL, 0x4A99A025L, 0x1D6EFE10L,
+ 0x1AB93D1DL, 0x0BA5A4DFL, 0xA186F20FL, 0x2868F169L,
+ 0xDCB7DA83L, 0x573906FEL, 0xA1E2CE9BL, 0x4FCD7F52L,
+ 0x50115E01L, 0xA70683FAL, 0xA002B5C4L, 0x0DE6D027L,
+ 0x9AF88C27L, 0x773F8641L, 0xC3604C06L, 0x61A806B5L,
+ 0xF0177A28L, 0xC0F586E0L, 0x006058AAL, 0x30DC7D62L,
+ 0x11E69ED7L, 0x2338EA63L, 0x53C2DD94L, 0xC2C21634L,
+ 0xBBCBEE56L, 0x90BCB6DEL, 0xEBFC7DA1L, 0xCE591D76L,
+ 0x6F05E409L, 0x4B7C0188L, 0x39720A3DL, 0x7C927C24L,
+ 0x86E3725FL, 0x724D9DB9L, 0x1AC15BB4L, 0xD39EB8FCL,
+ 0xED545578L, 0x08FCA5B5L, 0xD83D7CD3L, 0x4DAD0FC4L,
+ 0x1E50EF5EL, 0xB161E6F8L, 0xA28514D9L, 0x6C51133CL,
+ 0x6FD5C7E7L, 0x56E14EC4L, 0x362ABFCEL, 0xDDC6C837L,
+ 0xD79A3234L, 0x92638212L, 0x670EFA8EL, 0x406000E0L },
+ { 0x3A39CE37L, 0xD3FAF5CFL, 0xABC27737L, 0x5AC52D1BL,
+ 0x5CB0679EL, 0x4FA33742L, 0xD3822740L, 0x99BC9BBEL,
+ 0xD5118E9DL, 0xBF0F7315L, 0xD62D1C7EL, 0xC700C47BL,
+ 0xB78C1B6BL, 0x21A19045L, 0xB26EB1BEL, 0x6A366EB4L,
+ 0x5748AB2FL, 0xBC946E79L, 0xC6A376D2L, 0x6549C2C8L,
+ 0x530FF8EEL, 0x468DDE7DL, 0xD5730A1DL, 0x4CD04DC6L,
+ 0x2939BBDBL, 0xA9BA4650L, 0xAC9526E8L, 0xBE5EE304L,
+ 0xA1FAD5F0L, 0x6A2D519AL, 0x63EF8CE2L, 0x9A86EE22L,
+ 0xC089C2B8L, 0x43242EF6L, 0xA51E03AAL, 0x9CF2D0A4L,
+ 0x83C061BAL, 0x9BE96A4DL, 0x8FE51550L, 0xBA645BD6L,
+ 0x2826A2F9L, 0xA73A3AE1L, 0x4BA99586L, 0xEF5562E9L,
+ 0xC72FEFD3L, 0xF752F7DAL, 0x3F046F69L, 0x77FA0A59L,
+ 0x80E4A915L, 0x87B08601L, 0x9B09E6ADL, 0x3B3EE593L,
+ 0xE990FD5AL, 0x9E34D797L, 0x2CF0B7D9L, 0x022B8B51L,
+ 0x96D5AC3AL, 0x017DA67DL, 0xD1CF3ED6L, 0x7C7D2D28L,
+ 0x1F9F25CFL, 0xADF2B89BL, 0x5AD6B472L, 0x5A88F54CL,
+ 0xE029AC71L, 0xE019A5E6L, 0x47B0ACFDL, 0xED93FA9BL,
+ 0xE8D3C48DL, 0x283B57CCL, 0xF8D56629L, 0x79132E28L,
+ 0x785F0191L, 0xED756055L, 0xF7960E44L, 0xE3D35E8CL,
+ 0x15056DD4L, 0x88F46DBAL, 0x03A16125L, 0x0564F0BDL,
+ 0xC3EB9E15L, 0x3C9057A2L, 0x97271AECL, 0xA93A072AL,
+ 0x1B3F6D9BL, 0x1E6321F5L, 0xF59C66FBL, 0x26DCF319L,
+ 0x7533D928L, 0xB155FDF5L, 0x03563482L, 0x8ABA3CBBL,
+ 0x28517711L, 0xC20AD9F8L, 0xABCC5167L, 0xCCAD925FL,
+ 0x4DE81751L, 0x3830DC8EL, 0x379D5862L, 0x9320F991L,
+ 0xEA7A90C2L, 0xFB3E7BCEL, 0x5121CE64L, 0x774FBE32L,
+ 0xA8B6E37EL, 0xC3293D46L, 0x48DE5369L, 0x6413E680L,
+ 0xA2AE0810L, 0xDD6DB224L, 0x69852DFDL, 0x09072166L,
+ 0xB39A460AL, 0x6445C0DDL, 0x586CDECFL, 0x1C20C8AEL,
+ 0x5BBEF7DDL, 0x1B588D40L, 0xCCD2017FL, 0x6BB4E3BBL,
+ 0xDDA26A7EL, 0x3A59FF45L, 0x3E350A44L, 0xBCB4CDD5L,
+ 0x72EACEA8L, 0xFA6484BBL, 0x8D6612AEL, 0xBF3C6F47L,
+ 0xD29BE463L, 0x542F5D9EL, 0xAEC2771BL, 0xF64E6370L,
+ 0x740E0D8DL, 0xE75B1357L, 0xF8721671L, 0xAF537D5DL,
+ 0x4040CB08L, 0x4EB4E2CCL, 0x34D2466AL, 0x0115AF84L,
+ 0xE1B00428L, 0x95983A1DL, 0x06B89FB4L, 0xCE6EA048L,
+ 0x6F3F3B82L, 0x3520AB82L, 0x011A1D4BL, 0x277227F8L,
+ 0x611560B1L, 0xE7933FDCL, 0xBB3A792BL, 0x344525BDL,
+ 0xA08839E1L, 0x51CE794BL, 0x2F32C9B7L, 0xA01FBAC9L,
+ 0xE01CC87EL, 0xBCC7D1F6L, 0xCF0111C3L, 0xA1E8AAC7L,
+ 0x1A908749L, 0xD44FBD9AL, 0xD0DADECBL, 0xD50ADA38L,
+ 0x0339C32AL, 0xC6913667L, 0x8DF9317CL, 0xE0B12B4FL,
+ 0xF79E59B7L, 0x43F5BB3AL, 0xF2D519FFL, 0x27D9459CL,
+ 0xBF97222CL, 0x15E6FC2AL, 0x0F91FC71L, 0x9B941525L,
+ 0xFAE59361L, 0xCEB69CEBL, 0xC2A86459L, 0x12BAA8D1L,
+ 0xB6C1075EL, 0xE3056A0CL, 0x10D25065L, 0xCB03A442L,
+ 0xE0EC6E0EL, 0x1698DB3BL, 0x4C98A0BEL, 0x3278E964L,
+ 0x9F1F9532L, 0xE0D392DFL, 0xD3A0342BL, 0x8971F21EL,
+ 0x1B0A7441L, 0x4BA3348CL, 0xC5BE7120L, 0xC37632D8L,
+ 0xDF359F8DL, 0x9B992F2EL, 0xE60B6F47L, 0x0FE3F11DL,
+ 0xE54CDA54L, 0x1EDAD891L, 0xCE6279CFL, 0xCD3E7E6FL,
+ 0x1618B166L, 0xFD2C1D05L, 0x848FD2C5L, 0xF6FB2299L,
+ 0xF523F357L, 0xA6327623L, 0x93A83531L, 0x56CCCD02L,
+ 0xACF08162L, 0x5A75EBB5L, 0x6E163697L, 0x88D273CCL,
+ 0xDE966292L, 0x81B949D0L, 0x4C50901BL, 0x71C65614L,
+ 0xE6C6C7BDL, 0x327A140AL, 0x45E1D006L, 0xC3F27B9AL,
+ 0xC9AA53FDL, 0x62A80F00L, 0xBB25BFE2L, 0x35BDD2F6L,
+ 0x71126905L, 0xB2040222L, 0xB6CBCF7CL, 0xCD769C2BL,
+ 0x53113EC0L, 0x1640E3D3L, 0x38ABBD60L, 0x2547ADF0L,
+ 0xBA38209CL, 0xF746CE76L, 0x77AFA1C5L, 0x20756060L,
+ 0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL,
+ 0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L,
+ 0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL,
+ 0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L }
+};
+
+
+static unsigned long F(BLOWFISH_CTX *ctx, unsigned long x) {
+ unsigned short a, b, c, d;
+ unsigned long y;
+
+ d = (unsigned short)(x & 0xFF);
+ x >>= 8;
+ c = (unsigned short)(x & 0xFF);
+ x >>= 8;
+ b = (unsigned short)(x & 0xFF);
+ x >>= 8;
+ a = (unsigned short)(x & 0xFF);
+ y = ctx->S[0][a] + ctx->S[1][b];
+ y = y ^ ctx->S[2][c];
+ y = y + ctx->S[3][d];
+
+ return y;
+}
+
+
+static void Blowfish_Encrypt(BLOWFISH_CTX *ctx, unsigned long *xl, unsigned long *xr){
+ unsigned long Xl;
+ unsigned long Xr;
+ unsigned long temp;
+ short i;
+
+ Xl = *xl;
+ Xr = *xr;
+
+ for (i = 0; i < N; ++i) {
+ Xl = Xl ^ ctx->P[i];
+ Xr = F(ctx, Xl) ^ Xr;
+
+ temp = Xl;
+ Xl = Xr;
+ Xr = temp;
+ }
+
+ temp = Xl;
+ Xl = Xr;
+ Xr = temp;
+
+ Xr = Xr ^ ctx->P[N];
+ Xl = Xl ^ ctx->P[N + 1];
+
+ *xl = Xl;
+ *xr = Xr;
+}
+
+
+static void Blowfish_Decrypt(BLOWFISH_CTX *ctx, unsigned long *xl, unsigned long *xr){
+ unsigned long Xl;
+ unsigned long Xr;
+ unsigned long temp;
+ short i;
+
+ Xl = *xl;
+ Xr = *xr;
+
+ for (i = N + 1; i > 1; --i) {
+ Xl = Xl ^ ctx->P[i];
+ Xr = F(ctx, Xl) ^ Xr;
+
+ /* Exchange Xl and Xr */
+ temp = Xl;
+ Xl = Xr;
+ Xr = temp;
+ }
+
+ /* Exchange Xl and Xr */
+ temp = Xl;
+ Xl = Xr;
+ Xr = temp;
+
+ Xr = Xr ^ ctx->P[1];
+ Xl = Xl ^ ctx->P[0];
+
+ *xl = Xl;
+ *xr = Xr;
+}
+
+static void Blowfish_Init(BLOWFISH_CTX *ctx, unsigned char *key, int keyLen) {
+ int i, j, k;
+ unsigned long data, datal, datar;
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < 256; j++)
+ ctx->S[i][j] = ORIG_S[i][j];
+ }
+
+ j = 0;
+ for (i = 0; i < N + 2; ++i) {
+ data = 0x00000000;
+ for (k = 0; k < 4; ++k) {
+ data = (data << 8) | key[j];
+ j = j + 1;
+ if (j >= keyLen)
+ j = 0;
+ }
+ ctx->P[i] = ORIG_P[i] ^ data;
+ }
+
+ datal = 0x00000000;
+ datar = 0x00000000;
+
+ for (i = 0; i < N + 2; i += 2) {
+ Blowfish_Encrypt(ctx, &datal, &datar);
+ ctx->P[i] = datal;
+ ctx->P[i + 1] = datar;
+ }
+
+ for (i = 0; i < 4; ++i) {
+ for (j = 0; j < 256; j += 2) {
+ Blowfish_Encrypt(ctx, &datal, &datar);
+ ctx->S[i][j] = datal;
+ ctx->S[i][j + 1] = datar;
+ }
+ }
+}
+
+static unsigned long long blowfish_test(unsigned long long input)
+{
+ unsigned long L = input >> 32, R = input;
+ BLOWFISH_CTX ctx;
+ Blowfish_Init(&ctx, (unsigned char*)"TESTKEY", 7);
+ Blowfish_Encrypt(&ctx, &L, &R);
+ Blowfish_Decrypt(&ctx, &L, &R);
+ return ((unsigned long long)L << 32) | R;
+}
diff --git a/tools/tests/blowfish.mk b/tools/tests/blowfish.mk
new file mode 100644
index 0000000000..a66a4ee401
--- /dev/null
+++ b/tools/tests/blowfish.mk
@@ -0,0 +1,23 @@
+
+override XEN_TARGET_ARCH = x86_32
+XEN_ROOT = ../..
+CFLAGS :=
+include $(XEN_ROOT)/tools/Rules.mk
+
+# Disable PIE/SSP if GCC supports them. They can break us.
+CFLAGS += $(call cc-option,$(CC),-nopie,)
+CFLAGS += $(call cc-option,$(CC),-fno-stack-protector,)
+CFLAGS += $(call cc-option,$(CC),-fno-stack-protector-all,)
+
+OBJCOPY = objcopy
+CFLAGS += -fno-builtin -O2 -msoft-float
+LDFLAGS = -nostdlib -Wl,-N -Wl,-Ttext -Wl,0x100000
+
+.PHONY: all
+all: blowfish.bin
+
+blowfish.bin: blowfish.c
+ $(CC) $(CFLAGS) -c blowfish.c
+ $(CC) $(CFLAGS) $(LDFLAGS) -o blowfish.tmp blowfish.o
+ $(OBJCOPY) -O binary blowfish.tmp blowfish.bin
+ rm -f blowfish.tmp
diff --git a/tools/tests/test_x86_emulator.c b/tools/tests/test_x86_emulator.c
index 8bbfa3af28..2d8d49e43f 100644
--- a/tools/tests/test_x86_emulator.c
+++ b/tools/tests/test_x86_emulator.c
@@ -15,6 +15,19 @@ typedef int64_t s64;
#include <asm-x86/x86_emulate.h>
#include <sys/mman.h>
+#include "blowfish.h"
+
+#define MMAP_SZ 16384
+
+/* EFLAGS bit definitions. */
+#define EFLG_OF (1<<11)
+#define EFLG_DF (1<<10)
+#define EFLG_SF (1<<7)
+#define EFLG_ZF (1<<6)
+#define EFLG_AF (1<<4)
+#define EFLG_PF (1<<2)
+#define EFLG_CF (1<<0)
+
static int read(
unsigned int seg,
unsigned long offset,
@@ -97,20 +110,25 @@ int main(int argc, char **argv)
{
struct x86_emulate_ctxt ctxt;
struct cpu_user_regs regs;
- char instr[20] = { 0x01, 0x08 }; /* add %ecx,(%eax) */
- unsigned int *res;
+ char *instr;
+ unsigned int *res, i;
int rc;
+#ifndef __x86_64__
+ unsigned int bcdres_native, bcdres_emul;
+#endif
ctxt.regs = &regs;
- ctxt.address_bytes = 4;
+ ctxt.addr_size = 32;
+ ctxt.sp_size = 32;
- res = mmap((void *)0x100000, 0x1000, PROT_READ|PROT_WRITE,
+ res = mmap((void *)0x100000, MMAP_SZ, PROT_READ|PROT_WRITE,
MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
if ( res == MAP_FAILED )
{
fprintf(stderr, "mmap to low address failed\n");
exit(1);
}
+ instr = (char *)res + 0x100;
printf("%-40s", "Testing addl %%ecx,(%%eax)...");
instr[0] = 0x01; instr[1] = 0x08;
@@ -399,6 +417,112 @@ int main(int argc, char **argv)
goto fail;
printf("okay\n");
+ printf("%-40s", "Testing daa/das (all inputs)...");
+#ifndef __x86_64__
+ /* Bits 0-7: AL; Bit 8: EFLG_AF; Bit 9: EFLG_CF; Bit 10: DAA vs. DAS. */
+ for ( i = 0; i < 0x800; i++ )
+ {
+ regs.eflags = (i & 0x200) ? EFLG_CF : 0;
+ regs.eflags |= (i & 0x100) ? EFLG_AF : 0;
+ if ( i & 0x400 )
+ __asm__ (
+ "pushf; and $0xffffffee,(%%esp); or %1,(%%esp); popf; das; "
+ "pushf; popl %1"
+ : "=a" (bcdres_native), "=r" (regs.eflags)
+ : "0" (i & 0xff), "1" (regs.eflags) );
+ else
+ __asm__ (
+ "pushf; and $0xffffffee,(%%esp); or %1,(%%esp); popf; daa; "
+ "pushf; popl %1"
+ : "=a" (bcdres_native), "=r" (regs.eflags)
+ : "0" (i & 0xff), "1" (regs.eflags) );
+ bcdres_native |= (regs.eflags & EFLG_PF) ? 0x1000 : 0;
+ bcdres_native |= (regs.eflags & EFLG_ZF) ? 0x800 : 0;
+ bcdres_native |= (regs.eflags & EFLG_SF) ? 0x400 : 0;
+ bcdres_native |= (regs.eflags & EFLG_CF) ? 0x200 : 0;
+ bcdres_native |= (regs.eflags & EFLG_AF) ? 0x100 : 0;
+
+ instr[0] = (i & 0x400) ? 0x2f: 0x27; /* daa/das */
+ regs.eflags = (i & 0x200) ? EFLG_CF : 0;
+ regs.eflags |= (i & 0x100) ? EFLG_AF : 0;
+ regs.eip = (unsigned long)&instr[0];
+ regs.eax = (unsigned char)i;
+ rc = x86_emulate(&ctxt, &emulops);
+ bcdres_emul = regs.eax;
+ bcdres_emul |= (regs.eflags & EFLG_PF) ? 0x1000 : 0;
+ bcdres_emul |= (regs.eflags & EFLG_ZF) ? 0x800 : 0;
+ bcdres_emul |= (regs.eflags & EFLG_SF) ? 0x400 : 0;
+ bcdres_emul |= (regs.eflags & EFLG_CF) ? 0x200 : 0;
+ bcdres_emul |= (regs.eflags & EFLG_AF) ? 0x100 : 0;
+ if ( (rc != 0) || (regs.eax > 255) ||
+ (regs.eip != (unsigned long)&instr[1]) )
+ goto fail;
+
+ if ( bcdres_emul != bcdres_native )
+ {
+ printf("%s: AL=%02x %s %s\n"
+ "Output: AL=%02x %s %s %s %s %s\n"
+ "Emul.: AL=%02x %s %s %s %s %s\n",
+ (i & 0x400) ? "DAS" : "DAA",
+ (unsigned char)i,
+ (i & 0x200) ? "CF" : " ",
+ (i & 0x100) ? "AF" : " ",
+ (unsigned char)bcdres_native,
+ (bcdres_native & 0x200) ? "CF" : " ",
+ (bcdres_native & 0x100) ? "AF" : " ",
+ (bcdres_native & 0x1000) ? "PF" : " ",
+ (bcdres_native & 0x800) ? "ZF" : " ",
+ (bcdres_native & 0x400) ? "SF" : " ",
+ (unsigned char)bcdres_emul,
+ (bcdres_emul & 0x200) ? "CF" : " ",
+ (bcdres_emul & 0x100) ? "AF" : " ",
+ (bcdres_emul & 0x1000) ? "PF" : " ",
+ (bcdres_emul & 0x800) ? "ZF" : " ",
+ (bcdres_emul & 0x400) ? "SF" : " ");
+ goto fail;
+ }
+ }
+ printf("okay\n");
+#else
+ printf("skipped\n");
+#endif
+
+ printf("Testing blowfish code sequence");
+ memcpy(res, blowfish_code, sizeof(blowfish_code));
+ regs.eax = 2;
+ regs.edx = 1;
+ regs.eip = (unsigned long)res;
+ regs.esp = (unsigned long)res + MMAP_SZ - 4;
+ *(uint32_t *)(unsigned long)regs.esp = 0x12345678;
+ regs.eflags = 2;
+ i = 0;
+ while ( (uint32_t)regs.eip != 0x12345678 )
+ {
+ if ( (i++ & 8191) == 0 )
+ printf(".");
+ rc = x86_emulate(&ctxt, &emulops);
+ if ( rc != 0 )
+ {
+ printf("failed at %%eip == %08x\n", (unsigned int)regs.eip);
+ return 1;
+ }
+ }
+ if ( (regs.esp != ((unsigned long)res + MMAP_SZ)) ||
+ (regs.eax != 2) || (regs.edx != 1) )
+ goto fail;
+ printf("okay\n");
+
+#ifndef __x86_64__
+ printf("%-40s", "Testing blowfish native execution...");
+ asm volatile (
+ "movl $0x100000,%%ecx; call *%%ecx"
+ : "=a" (regs.eax), "=d" (regs.edx)
+ : "0" (2), "1" (1) : "ecx" );
+ if ( (regs.eax != 2) || (regs.edx != 1) )
+ goto fail;
+ printf("okay\n");
+#endif
+
return 0;
fail:
diff --git a/tools/xenstat/xentop/xentop.c b/tools/xenstat/xentop/xentop.c
index 4b610c3668..1c0d8ac63d 100644
--- a/tools/xenstat/xentop/xentop.c
+++ b/tools/xenstat/xentop/xentop.c
@@ -1067,9 +1067,9 @@ int main(int argc, char **argv)
gettimeofday(&curtime, NULL);
top();
oldtime = curtime;
- sleep(delay);
if ((!loop) && !(--iterations))
break;
+ sleep(delay);
} while (1);
}
diff --git a/tools/xm-test/README b/tools/xm-test/README
index 9157f7681d..b63a34be32 100644
--- a/tools/xm-test/README
+++ b/tools/xm-test/README
@@ -207,6 +207,49 @@ dedicated machine. As such, the library automatically destroys any
running DomUs on the system to provide each test with a "clean slate".
+Testing the XML-RPC and Xen-API interfaces of xend
+==================================================
+
+The xm-test suite can be used to test xm's interface with xend using
+either XML-RPC or the Xen-API. In order to use either one of these modes,
+xm needs to be configured using its configuration file
+'/etc/xen/xm-config.xml'.
+Note: The current default configuration after a fresh install of the xen
+sources currently is to use the XML-RPC interface for communication with xend.
+
+Example content for the xm-config.xml for using the Xen-API looks as
+follows:
+
+<xm>
+ <server type='Xen-API'
+ uri='http://localhost:9363/'
+ username='me'
+ password='mypassword' />
+</xm>
+
+This configuration makes xm talk to xend using port 9363. For this to
+work, also xend needs to be configured to listen to port 9363. Therefore
+The following line must be in /etc/xen/xend-config.sxp.
+
+(xen-api-server (( 127.0.0.1:9363 none )))
+
+To communicate via the legacy XML-RPC interface, the file
+'/etc/xen/xm-config.xml' may simply have the following content or
+may be complete remove from the /etc/xen directory.
+
+<xm>
+</xm>
+
+A few tests have been written for the xm-test suite that test the
+Xen-API interface directly without relying on 'xm'. These tests can be
+found in the grouptest 'xapi' and for them to work properly, xm must have
+been configured to use the Xen-API following the instructions above. To
+run these test, the following command line can be invoked:
+
+ # ./runtest.sh -g xapi <logfile>
+
+
+
Extending
=========
diff --git a/tools/xm-test/configure.ac b/tools/xm-test/configure.ac
index 87df5cd6bd..ffbf146f34 100644
--- a/tools/xm-test/configure.ac
+++ b/tools/xm-test/configure.ac
@@ -150,6 +150,7 @@ AC_CONFIG_FILES([
tests/vcpu-pin/Makefile
tests/vcpu-disable/Makefile
tests/vtpm/Makefile
+ tests/xapi/Makefile
tests/enforce_dom0_cpus/Makefile
lib/XmTestReport/xmtest.py
lib/XmTestLib/config.py
diff --git a/tools/xm-test/grouptest/xapi b/tools/xm-test/grouptest/xapi
index 407368e6b4..3b049219dd 100644
--- a/tools/xm-test/grouptest/xapi
+++ b/tools/xm-test/grouptest/xapi
@@ -1 +1,2 @@
+xapi
vtpm 09_vtpm-xapi.test
diff --git a/tools/xm-test/lib/XmTestLib/DomainTracking.py b/tools/xm-test/lib/XmTestLib/DomainTracking.py
new file mode 100644
index 0000000000..7e0bb3013a
--- /dev/null
+++ b/tools/xm-test/lib/XmTestLib/DomainTracking.py
@@ -0,0 +1,61 @@
+#!/usr/bin/python
+"""
+ Copyright (C) International Business Machines Corp., 2005
+ Author: Dan Smith <danms@us.ibm.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; under version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+"""
+
+import atexit
+import Test
+import xapi
+
+# Tracking of managed domains
+_managedDomains = []
+_VMuuids = []
+registered = 0
+
+def addManagedDomain(name):
+ global registered
+ _managedDomains.append(name)
+ if not registered:
+ atexit.register(destroyManagedDomains)
+ registered = 1
+
+def delManagedDomain(name):
+ if name in _managedDomains:
+ del _managedDomains[_managedDomains.index(name)]
+
+def addXAPIDomain(uuid):
+ global registered
+ _VMuuids.append(uuid)
+ if not registered:
+ atexit.register(destroyManagedDomains)
+ registered = 1
+
+def delXAPIDomain(uuid):
+ _VMuuids.remove(uuid)
+
+def destroyManagedDomains():
+ if len(_managedDomains) > 0:
+ for m in _managedDomains:
+ Test.traceCommand("xm destroy %s" % m)
+ Test.traceCommand("xm delete %s" % m)
+ if len(_VMuuids) > 0:
+ for uuid in _VMuuids:
+ Test.traceCommand("xm destroy %s" % uuid)
+ Test.traceCommand("xm delete %s" % uuid)
+
+
diff --git a/tools/xm-test/lib/XmTestLib/XenManagedDomain.py b/tools/xm-test/lib/XmTestLib/XenAPIDomain.py
index 1b211fe016..cfec7911ee 100644
--- a/tools/xm-test/lib/XmTestLib/XenManagedDomain.py
+++ b/tools/xm-test/lib/XmTestLib/XenAPIDomain.py
@@ -26,7 +26,7 @@ from xen.util.xmlrpclib2 import ServerProxy
from types import DictType
-class XenManagedConfig:
+class XenAPIConfig:
"""An object to help create a VM configuration usable via Xen-API"""
def __init__(self):
self.opts = {}
@@ -36,9 +36,9 @@ class XenManagedConfig:
'memory_static_min' ,
'memory_dynamic_min',
'memory_dynamic_max' ],
- 'kernel' : 'kernel_kernel',
- 'ramdisk': 'kernel_initrd',
- 'root' : 'kernel_args'}
+ 'kernel' : 'PV_kernel',
+ 'ramdisk': 'PV_ramdisk',
+ 'root' : 'PV_args'}
def setOpt(self, name, value):
"""Set an option in the config"""
@@ -69,7 +69,7 @@ class XenManagedConfig:
return self.opts
-class XenManagedDomain(XenDomain):
+class XenAPIDomain(XenDomain):
def __init__(self, name=None, config=None):
if name:
@@ -81,12 +81,11 @@ class XenManagedDomain(XenDomain):
self.console = None
self.netEnv = "bridge"
- self.server, self.session = xapi._connect()
- server = self.server
+ self.session = xapi.connect()
+ session = self.session
try:
- self.vm_uuid = xapi.execute(server.VM.create, self.session,
- self.config.getOpts())
- xapi._VMuuids.append(self.vm_uuid)
+ self.vm_uuid = session.xenapi.VM.create(self.config.getOpts())
+ addXAPIDomain(self.vm_uuid)
except:
raise DomainError("Could not create VM config file for "
"managed domain.")
@@ -96,15 +95,17 @@ class XenManagedDomain(XenDomain):
def start(self, noConsole=False, startpaused=False):
#start the VM
- server = self.server
+ session = self.session
if self.vm_uuid:
try:
- xapi.execute(server.VM.start, self.session, self.vm_uuid,
- startpaused)
+ session.xenapi.VM.start(self.vm_uuid, startpaused)
except:
raise DomainError("Could not start domain")
else:
- raise DomainError("VM has not UUID - VM config does not exist?")
+ raise DomainError("VM has no UUID - does VM config exist?")
+
+ if startpaused:
+ return
if self.getDomainType() == "HVM":
waitForBoot()
@@ -120,20 +121,18 @@ class XenManagedDomain(XenDomain):
def stop(self):
if self.vm_uuid:
- server = self.server
- xapi.execute(server.VM.hard_shutdown, self.session, self.vm_uuid)
+ self.session.xenapi.VM.hard_shutdown(self.vm_uuid)
else:
- raise DomainError("VM has not UUID - VM config does not exist?")
+ raise DomainError("VM has no UUID - does VM config exist?")
def destroy(self):
#Stop VM first.
self.stop()
if self.vm_uuid:
- server = self.server
- xapi.execute(server.VM.destroy, self.session, self.vm_uuid)
- xapi._VMuuids.remove(self.vm_uuid)
+ self.session.xenapi.VM.destroy(self.vm_uuid)
+ delXAPIDomain(self.vm_uuid)
else:
- raise DomainError("VM has not UUID - VM config does not exist?")
+ raise DomainError("VM has no UUID - does VM config exist?")
def get_uuid(self):
return self.vm_uuid
@@ -154,7 +153,7 @@ class XenManagedDomain(XenDomain):
raise DomainError("No support for getDevice().")
-class XmTestManagedDomain(XenManagedDomain):
+class XmTestAPIDomain(XenAPIDomain):
"""Create a new managed xm-test domain
@param name: The requested domain name
@@ -163,7 +162,7 @@ class XmTestManagedDomain(XenManagedDomain):
"""
def __init__(self, name=None, extraConfig=None,
baseConfig=arch.configDefaults):
- config = XenManagedConfig()
+ config = XenAPIConfig()
config.setOpts(baseConfig)
if extraConfig:
config.setOpts(extraConfig)
@@ -173,5 +172,5 @@ class XmTestManagedDomain(XenManagedDomain):
elif not config.getOpt("name_label"):
config.setOpt("name_label", getUniqueName())
- XenManagedDomain.__init__(self, config.getOpt("name_label"),
- config=config)
+ XenAPIDomain.__init__(self, config.getOpt("name_label"),
+ config=config)
diff --git a/tools/xm-test/lib/XmTestLib/XenDomain.py b/tools/xm-test/lib/XmTestLib/XenDomain.py
index 40aaebf9b4..3fcfcea4f1 100644
--- a/tools/xm-test/lib/XmTestLib/XenDomain.py
+++ b/tools/xm-test/lib/XmTestLib/XenDomain.py
@@ -29,6 +29,7 @@ from Test import *
from config import *
from Console import *
from XenDevice import *
+from DomainTracking import *
from acm import *
@@ -147,7 +148,7 @@ class DomainError(Exception):
class XenDomain:
- def __init__(self, name=None, config=None):
+ def __init__(self, name=None, config=None, isManaged=False):
"""Create a domain object.
@param config: String filename of config file
"""
@@ -162,6 +163,10 @@ class XenDomain:
self.devices = {}
self.netEnv = "bridge"
+ if os.getenv("XM_MANAGED_DOMAINS"):
+ isManaged = True
+ self.isManaged = isManaged
+
# Set domain type, either PV for ParaVirt domU or HVM for
# FullVirt domain
if ENABLE_HVM_SUPPORT:
@@ -171,7 +176,17 @@ class XenDomain:
def start(self, noConsole=False):
- ret, output = traceCommand("xm create %s" % self.config)
+ if not self.isManaged:
+ ret, output = traceCommand("xm create %s" % self.config)
+ else:
+ ret, output = traceCommand("xm new %s" % self.config)
+ if ret != 0:
+ _ret, output = traceCommand("xm delete " +
+ self.config.getOpt("name"))
+ else:
+ ret, output = traceCommand("xm start " +
+ self.config.getOpt("name"))
+ addManagedDomain(self.config.getOpt("name"))
if ret != 0:
raise DomainError("Failed to create domain",
@@ -218,6 +233,10 @@ class XenDomain:
self.closeConsole()
ret, output = traceCommand(prog + cmd + self.config.getOpt("name"))
+ if self.isManaged:
+ ret, output = traceCommand(prog + " delete " +
+ self.config.getOpt("name"))
+ delManagedDomain(self.config.getOpt("name"))
return ret
@@ -296,7 +315,7 @@ class XenDomain:
class XmTestDomain(XenDomain):
def __init__(self, name=None, extraConfig=None,
- baseConfig=arch.configDefaults):
+ baseConfig=arch.configDefaults, isManaged=False):
"""Create a new xm-test domain
@param name: The requested domain name
@param extraConfig: Additional configuration options
@@ -312,7 +331,8 @@ class XmTestDomain(XenDomain):
elif not config.getOpt("name"):
config.setOpt("name", getUniqueName())
- XenDomain.__init__(self, config.getOpt("name"), config=config)
+ XenDomain.__init__(self, config.getOpt("name"), config=config,
+ isManaged=isManaged)
def minSafeMem(self):
return arch.minSafeMem
diff --git a/tools/xm-test/lib/XmTestLib/Xm.py b/tools/xm-test/lib/XmTestLib/Xm.py
index 43ee90dd7c..6f1e33c153 100644
--- a/tools/xm-test/lib/XmTestLib/Xm.py
+++ b/tools/xm-test/lib/XmTestLib/Xm.py
@@ -49,6 +49,8 @@ def domid(name):
if status != 0 or "Traceback" in output:
return -1
+ if output == "None":
+ return -1
try:
return int(output)
except:
diff --git a/tools/xm-test/lib/XmTestLib/xapi.py b/tools/xm-test/lib/XmTestLib/xapi.py
index bab0e103d9..773b3c1739 100644
--- a/tools/xm-test/lib/XmTestLib/xapi.py
+++ b/tools/xm-test/lib/XmTestLib/xapi.py
@@ -17,50 +17,49 @@
# Copyright (C) 2006 IBM Corporation
#============================================================================
+import atexit
import os
import sys
from XmTestLib import *
-from xen.util.xmlrpclib2 import ServerProxy
+from xen.xm import main as xmmain
+from xen.xm import XenAPI
+from xen.xm.opts import OptionError
from types import DictType
+import xml.dom.minidom
+def get_login_pwd():
+ if xmmain.serverType == xmmain.SERVER_XEN_API:
+ try:
+ login, password = xmmain.parseAuthentication()
+ return (login, password)
+ except:
+ raise OptionError("Configuration for login/pwd not found. "
+ "Need to run xapi-setup.py?")
+ raise OptionError("Xm configuration file not using Xen-API for "
+ "communication with xend.")
-XAPI_DEFAULT_LOGIN = " "
-XAPI_DEFAULT_PASSWORD = " "
+sessions=[]
-class XenAPIError(Exception):
- pass
-
-
-#A list of VMs' UUIDs that were created using vm_create
-_VMuuids = []
-
-#Terminate previously created managed(!) VMs and destroy their configs
-def vm_destroy_all():
- server, session = _connect()
- for uuid in _VMuuids:
- execute(server.VM.hard_shutdown, session, uuid)
- execute(server.VM.destroy , session, uuid)
-
-
-def execute(fn, *args):
- result = fn(*args)
- if type(result) != DictType:
- raise TypeError("Function returned object of type: %s" %
- str(type(result)))
- if 'Value' not in result:
- raise XenAPIError(*result['ErrorDescription'])
- return result['Value']
-
-_initialised = False
-_server = None
-_session = None
-def _connect(*args):
- global _server, _session, _initialised
- if not _initialised:
- _server = ServerProxy('httpu:///var/run/xend/xen-api.sock')
- login = XAPI_DEFAULT_LOGIN
- password = XAPI_DEFAULT_PASSWORD
- creds = (login, password)
- _session = execute(_server.session.login_with_password, *creds)
- _initialised = True
- return (_server, _session)
+def connect(*args):
+ try:
+ creds = get_login_pwd()
+ except Exception, e:
+ FAIL("%s" % str(e))
+ try:
+ session = XenAPI.Session(xmmain.serverURI)
+ except:
+ raise OptionError("Could not create XenAPI session with Xend." \
+ "URI=%s" % xmmain.serverURI)
+ try:
+ session.login_with_password(*creds)
+ except:
+ raise OptionError("Could not login to Xend. URI=%s" % xmmain.serverURI)
+ def logout():
+ try:
+ for s in sessions:
+ s.xenapi.session.logout()
+ except:
+ pass
+ sessions.append(session)
+ atexit.register(logout)
+ return session
diff --git a/tools/xm-test/ramdisk/Makefile.am b/tools/xm-test/ramdisk/Makefile.am
index b6c59d60e5..1de0d1423d 100644
--- a/tools/xm-test/ramdisk/Makefile.am
+++ b/tools/xm-test/ramdisk/Makefile.am
@@ -36,7 +36,12 @@ XMTEST_MAJ_VER = $(shell echo @PACKAGE_VERSION@ | perl -pe 's/(\d+)\.(\d+)\.\d+/
XMTEST_VER_IMG = initrd-$(XMTEST_MAJ_VER)-$(BR_ARCH).img
XMTEST_DL_IMG = $(shell echo $(XMTEST_VER_IMG) | sed -e 's/x86_64/i386/g')
-EXTRA_ROOT_DIRS = sys
+EXTRA_ROOT_DIRS = sys modules
+
+BLKDRV = /lib/modules/$(shell uname -r)/kernel/drivers/xen/blkfront/xenblk.ko
+NETDRV = /lib/modules/$(shell uname -r)/kernel/drivers/xen/netfront/xennet.ko
+PKTDRV = /lib/modules/$(shell uname -r)/kernel/net/packet/af_packet.ko
+
if HVM
all: initrd.img disk.img
@@ -60,7 +65,11 @@ $(BR_IMG): $(BR_SRC)
$(XMTEST_VER_IMG): $(BR_IMG)
chmod a+x skel/etc/init.d/rcS
- (cd skel; mkdir -p $(EXTRA_ROOT_DIRS); tar cf - .) \
+ cd skel && mkdir -p $(EXTRA_ROOT_DIRS)
+ -[ -e "$(BLKDRV)" ] && cp $(BLKDRV) skel/modules
+ -[ -e "$(NETDRV)" ] && cp $(NETDRV) skel/modules
+ -[ -e "$(PKTDRV)" ] && cp $(PKTDRV) skel/modules
+ (cd skel; tar cf - .) \
| (cd $(BR_SRC)/$(BR_ROOT); tar xvf -)
cd $(BR_SRC) && make
cp $(BR_IMG) $(XMTEST_VER_IMG)
diff --git a/tools/xm-test/ramdisk/skel/etc/init.d/rcS b/tools/xm-test/ramdisk/skel/etc/init.d/rcS
index b3a92109e9..4c294f3dff 100644
--- a/tools/xm-test/ramdisk/skel/etc/init.d/rcS
+++ b/tools/xm-test/ramdisk/skel/etc/init.d/rcS
@@ -6,3 +6,14 @@ mount -a
if uname -r | grep -q '^2.6'; then
mount -t sysfs none /sys
fi
+
+# If the block, net, and packet drivers are modules, we need to load them
+if test -e /modules/xenblk.ko; then
+ insmod /modules/xenblk.ko > /dev/null 2>&1
+fi
+if test -e /modules/xennet.ko; then
+ insmod /modules/xennet.ko > /dev/null 2>&1
+fi
+if test -e /modules/af_packet.ko; then
+ insmod /modules/af_packet.ko > /dev/null 2>&1
+fi
diff --git a/tools/xm-test/runtest.sh b/tools/xm-test/runtest.sh
index 22c0736bf2..5b102b7f45 100755
--- a/tools/xm-test/runtest.sh
+++ b/tools/xm-test/runtest.sh
@@ -16,6 +16,7 @@ usage() {
echo " -r <url> : url of test results repository to use"
echo " -s <report> : just submit report <report>"
echo " -u : unsafe -- do not run the sanity checks before starting"
+ echo " -md : all created domains are xend-'managed' domains"
echo " -h | --help : show this help"
}
@@ -218,11 +219,14 @@ run=yes
unsafe=no
GROUPENTERED=default
+#Prepare for usage with ACM
if [ -d /etc/xen/acm-security/policies ]; then
cp -f tests/security-acm/xm-test-security_policy.xml \
/etc/xen/acm-security/policies
fi
+unset XM_MANAGED_DOMAINS
+
# Resolve options
while [ $# -gt 0 ]
do
@@ -260,6 +264,10 @@ while [ $# -gt 0 ]
unsafe=yes
report=no
;;
+ -md)
+ echo "(use managed domains)"
+ export XM_MANAGED_DOMAINS=1
+ ;;
-h|--help)
usage
exit 0
diff --git a/tools/xm-test/tests/sched-credit/01_sched_credit_weight_cap_pos.py b/tools/xm-test/tests/sched-credit/01_sched_credit_weight_cap_pos.py
index e0b1fe5846..cdbca0f757 100644
--- a/tools/xm-test/tests/sched-credit/01_sched_credit_weight_cap_pos.py
+++ b/tools/xm-test/tests/sched-credit/01_sched_credit_weight_cap_pos.py
@@ -2,14 +2,27 @@
#
# Sched-credit tests modified from SEDF tests
#
+
+import re
+
from XmTestLib import *
+paramsRE = re.compile(r'^[^ ]* *[^ ]* *([^ ]*) *([^ ]*)$')
+
def get_sched_credit_params(domain):
- status, output = traceCommand("xm sched-credit -d %s" %(domain.getName()))
- params = output.strip('{}').split(', ')
- cap = int(params[0].split(':')[1].strip(' '))
- weight = int(params[1].split(':')[1].strip(' '))
- return (status, (weight, cap))
+ status, output = traceCommand("xm sched-credit -d %s | tail -1" %
+ domain.getName())
+
+ if status != 0:
+ FAIL("Getting sched-credit parameters return non-zero rv (%d)",
+ status)
+
+ m = paramsRE.match(output)
+ if not m:
+ FAIL("xm sched-credit gave bad output")
+ weight = int(m.group(1))
+ cap = int(m.group(2))
+ return (weight, cap)
def set_sched_credit_weight(domain, weight):
status, output = traceCommand("xm sched-credit -d %s -w %d" %(domain.getName(), weight))
@@ -31,11 +44,8 @@ except DomainError, e:
FAIL(str(e))
# check default param values
-(status, params) = get_sched_credit_params(domain)
-if status != 0:
- FAIL("Getting sched-credit parameters return non-zero rv (%d)", status)
+(weight, cap) = get_sched_credit_params(domain)
-(weight, cap) = params
if weight != 256:
FAIL("default weight is 256 (got %d)", weight)
if cap != 0:
@@ -51,11 +61,8 @@ if status != 0:
FAIL("Setting sched-credit cap return non-zero rv (%d)", status)
# check new param values
-(status, params) = get_sched_credit_params(domain)
-if status != 0:
- FAIL("Getting sched-credit parameters return non-zero rv (%d)", status)
+(weight, cap) = get_sched_credit_params(domain)
-(weight, cap) = params
if weight != 512:
FAIL("expected weight of 512 (got %d)", weight)
if cap != 100:
diff --git a/tools/xm-test/tests/vtpm/09_vtpm-xapi.py b/tools/xm-test/tests/vtpm/09_vtpm-xapi.py
index 8547a08b03..89975d077f 100644
--- a/tools/xm-test/tests/vtpm/09_vtpm-xapi.py
+++ b/tools/xm-test/tests/vtpm/09_vtpm-xapi.py
@@ -6,71 +6,66 @@
# Test to test the vtpm class through the Xen-API
from XmTestLib import xapi
-from XmTestLib.XenManagedDomain import XmTestManagedDomain
+from XmTestLib.XenAPIDomain import XmTestAPIDomain
from XmTestLib import *
from vtpm_utils import *
import commands
import os
-def do_test():
- domain = XmTestManagedDomain()
- vm_uuid = domain.get_uuid()
-
- vtpmcfg = {}
- vtpmcfg['type'] = "paravirtualised"
- vtpmcfg['backend'] = "Domain-0"
- vtpmcfg['instance'] = 1
- vtpmcfg['VM'] = vm_uuid
-
- server, session = xapi._connect()
-
- vtpm_uuid = xapi.execute(server.VTPM.create, session, vtpmcfg)
-
- vtpm_id = xapi.execute(server.VTPM.get_instance, session, vtpm_uuid)
- vtpm_be = xapi.execute(server.VTPM.get_backend , session, vtpm_uuid)
- if vtpm_be != vtpmcfg['backend']:
- FAIL("vTPM's backend is in '%s', expected: '%s'" %
- (vtpm_be, vtpmcfg['backend']))
-
- driver = xapi.execute(server.VTPM.get_driver, session, vtpm_uuid)
- if driver != vtpmcfg['type']:
- FAIL("vTPM has driver type '%s', expected: '%s'" %
- (driver, vtpmcfg['type']))
+try:
+ # XmTestAPIDomain tries to establish a connection to XenD
+ domain = XmTestAPIDomain()
+except Exception, e:
+ SKIP("Skipping test. Error: %s" % str(e))
+vm_uuid = domain.get_uuid()
- vtpm_rec = xapi.execute(server.VTPM.get_record, session, vtpm_uuid)
+vtpmcfg = {}
+vtpmcfg['type'] = "paravirtualised"
+vtpmcfg['backend'] = "Domain-0"
+vtpmcfg['instance'] = 1
+vtpmcfg['VM'] = vm_uuid
- if vtpm_rec['driver'] != vtpmcfg['type']:
- FAIL("vTPM record shows driver type '%s', expected: '%s'" %
- (vtpm_rec['driver'], vtpmcfg['type']))
- if vtpm_rec['uuid'] != vtpm_uuid:
- FAIL("vTPM record shows vtpm uuid '%s', expected: '%s'" %
- (vtpm_rec['uuid'], vtpm_uuid))
- if vtpm_rec['VM'] != vm_uuid:
- FAIL("vTPM record shows VM uuid '%s', expected: '%s'" %
- (vtpm_rec['VM'], vm_uuid))
+session = xapi.connect()
- success = domain.start()
+vtpm_uuid = session.xenapi.VTPM.create(vtpmcfg)
- console = domain.getConsole()
+vtpm_id = session.xenapi.VTPM.get_instance(vtpm_uuid)
+vtpm_be = session.xenapi.VTPM.get_backend(vtpm_uuid)
+if vtpm_be != vtpmcfg['backend']:
+ FAIL("vTPM's backend is in '%s', expected: '%s'" %
+ (vtpm_be, vtpmcfg['backend']))
- try:
- run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs")
- except ConsoleError, e:
- saveLog(console.getHistory())
- vtpm_cleanup(domName)
- FAIL("No result from dumping the PCRs")
+driver = session.xenapi.VTPM.get_driver(vtpm_uuid)
+if driver != vtpmcfg['type']:
+ FAIL("vTPM has driver type '%s', expected: '%s'" %
+ (driver, vtpmcfg['type']))
- if re.search("No such file",run["output"]):
- vtpm_cleanup(domName)
- FAIL("TPM frontend support not compiled into (domU?) kernel")
+vtpm_rec = session.xenapi.VTPM.get_record(vtpm_uuid)
- domain.stop()
- domain.destroy()
+if vtpm_rec['driver'] != vtpmcfg['type']:
+ FAIL("vTPM record shows driver type '%s', expected: '%s'" %
+ (vtpm_rec['driver'], vtpmcfg['type']))
+if vtpm_rec['uuid'] != vtpm_uuid:
+ FAIL("vTPM record shows vtpm uuid '%s', expected: '%s'" %
+ (vtpm_rec['uuid'], vtpm_uuid))
+if vtpm_rec['VM'] != vm_uuid:
+ FAIL("vTPM record shows VM uuid '%s', expected: '%s'" %
+ (vtpm_rec['VM'], vm_uuid))
+success = domain.start()
+console = domain.getConsole()
try:
- do_test()
-finally:
- #Make sure all domains are gone that were created in this test case
- xapi.vm_destroy_all()
+ run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs")
+except ConsoleError, e:
+ saveLog(console.getHistory())
+ vtpm_cleanup(domName)
+ FAIL("No result from dumping the PCRs")
+
+if re.search("No such file",run["output"]):
+ vtpm_cleanup(domName)
+ FAIL("TPM frontend support not compiled into (domU?) kernel")
+
+domain.stop()
+domain.destroy()
diff --git a/tools/xm-test/tests/xapi/01_xapi-vm_basic.py b/tools/xm-test/tests/xapi/01_xapi-vm_basic.py
new file mode 100644
index 0000000000..6f149a0dd9
--- /dev/null
+++ b/tools/xm-test/tests/xapi/01_xapi-vm_basic.py
@@ -0,0 +1,61 @@
+#!/usr/bin/python
+
+# Copyright (C) International Business Machines Corp., 2006
+# Author: Stefan Berger <stefanb@us.ibm.com>
+
+# Basic VM creation test
+
+from XmTestLib import xapi
+from XmTestLib.XenAPIDomain import XmTestAPIDomain
+from XmTestLib import *
+from xen.xend import XendAPIConstants
+import commands
+import os
+
+try:
+ # XmTestAPIDomain tries to establish a connection to XenD
+ domain = XmTestAPIDomain()
+except Exception, e:
+ SKIP("Skipping test. Error: %s" % str(e))
+vm_uuid = domain.get_uuid()
+
+session = xapi.connect()
+
+domain.start(startpaused=True)
+
+res = session.xenapi.VM.get_power_state(vm_uuid)
+
+if res != XendAPIConstants.XEN_API_VM_POWER_STATE[XendAPIConstants.XEN_API_VM_POWER_STATE_PAUSED]:
+ FAIL("VM was not started in 'paused' state")
+
+res = session.xenapi.VM.unpause(vm_uuid)
+
+res = session.xenapi.VM.get_power_state(vm_uuid)
+
+if res != XendAPIConstants.XEN_API_VM_POWER_STATE[XendAPIConstants.XEN_API_VM_POWER_STATE_RUNNING]:
+ FAIL("VM could not be put into 'running' state")
+
+console = domain.getConsole()
+
+try:
+ run = console.runCmd("cat /proc/interrupts")
+except ConsoleError, e:
+ saveLog(console.getHistory())
+ FAIL("Could not access proc-filesystem")
+
+res = session.xenapi.VM.pause(vm_uuid)
+
+res = session.xenapi.VM.get_power_state(vm_uuid)
+
+if res != XendAPIConstants.XEN_API_VM_POWER_STATE[XendAPIConstants.XEN_API_VM_POWER_STATE_PAUSED]:
+ FAIL("VM could not be put into 'paused' state")
+
+res = session.xenapi.VM.unpause(vm_uuid)
+
+res = session.xenapi.VM.get_power_state(vm_uuid)
+
+if res != XendAPIConstants.XEN_API_VM_POWER_STATE[XendAPIConstants.XEN_API_VM_POWER_STATE_RUNNING]:
+ FAIL("VM could not be 'unpaused'")
+
+domain.stop()
+domain.destroy()
diff --git a/tools/xm-test/tests/xapi/Makefile.am b/tools/xm-test/tests/xapi/Makefile.am
new file mode 100644
index 0000000000..2a0c44f578
--- /dev/null
+++ b/tools/xm-test/tests/xapi/Makefile.am
@@ -0,0 +1,19 @@
+SUBDIRS =
+
+TESTS = 01_xapi-vm_basic.test
+
+XFAIL_TESTS =
+
+EXTRA_DIST = $(TESTS) $(XFAIL_TESTS) xapi_utils.py
+TESTS_ENVIRONMENT=@TENV@
+
+%.test: %.py
+ cp $< $@
+ chmod +x $@
+
+clean-local: am_config_clean-local
+
+am_config_clean-local:
+ rm -f *test
+ rm -f *log
+ rm -f *~
diff --git a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c
index 3a2453a25c..409783c0c9 100644
--- a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c
+++ b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c
@@ -179,7 +179,7 @@ static int get_hypercall_stubs(void)
#define get_hypercall_stubs() (0)
#endif
-static int get_callback_irq(struct pci_dev *pdev)
+static uint64_t get_callback_via(struct pci_dev *pdev)
{
#ifdef __ia64__
int irq;
@@ -189,16 +189,24 @@ static int get_callback_irq(struct pci_dev *pdev)
}
return 0;
#else /* !__ia64__ */
- return pdev->irq;
+ if (pdev->irq < 16)
+ return pdev->irq; /* ISA IRQ */
+ /* We don't know the GSI. Specify the PCI INTx line instead. */
+ return (((uint64_t)0x01 << 56) | /* PCI INTx identifier */
+ ((uint64_t)pci_domain_nr(pdev->bus) << 32) |
+ ((uint64_t)pdev->bus->number << 16) |
+ ((uint64_t)(pdev->devfn & 0xff) << 8) |
+ ((uint64_t)(pdev->pin - 1) & 3));
#endif
}
static int __devinit platform_pci_init(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- int i, ret, callback_irq;
+ int i, ret;
long ioaddr, iolen;
long mmio_addr, mmio_len;
+ uint64_t callback_via;
i = pci_enable_device(pdev);
if (i)
@@ -210,9 +218,9 @@ static int __devinit platform_pci_init(struct pci_dev *pdev,
mmio_addr = pci_resource_start(pdev, 1);
mmio_len = pci_resource_len(pdev, 1);
- callback_irq = get_callback_irq(pdev);
+ callback_via = get_callback_via(pdev);
- if (mmio_addr == 0 || ioaddr == 0 || callback_irq == 0) {
+ if (mmio_addr == 0 || ioaddr == 0 || callback_via == 0) {
printk(KERN_WARNING DRV_NAME ":no resources found\n");
return -ENOENT;
}
@@ -242,12 +250,12 @@ static int __devinit platform_pci_init(struct pci_dev *pdev,
if ((ret = init_xen_info()))
goto out;
- if ((ret = request_irq(pdev->irq, evtchn_interrupt, SA_SHIRQ,
- "xen-platform-pci", pdev))) {
+ if ((ret = request_irq(pdev->irq, evtchn_interrupt,
+ SA_SHIRQ | SA_SAMPLE_RANDOM,
+ "xen-platform-pci", pdev)))
goto out;
- }
- if ((ret = set_callback_irq(callback_irq)))
+ if ((ret = set_callback_via(callback_via)))
goto out;
out:
@@ -297,7 +305,7 @@ static void __exit platform_pci_module_cleanup(void)
{
printk(KERN_INFO DRV_NAME ":Do platform module cleanup\n");
/* disable hypervisor for callback irq */
- set_callback_irq(0);
+ set_callback_via(0);
if (pci_device_registered)
pci_unregister_driver(&platform_driver);
}
diff --git a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.h b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.h
index 5e10413b13..ca65358599 100644
--- a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.h
+++ b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.h
@@ -24,13 +24,13 @@
#include <linux/interrupt.h>
#include <xen/interface/hvm/params.h>
-static inline int set_callback_irq(int irq)
+static inline int set_callback_via(uint64_t via)
{
struct xen_hvm_param a;
a.domid = DOMID_SELF;
a.index = HVM_PARAM_CALLBACK_IRQ;
- a.value = irq;
+ a.value = via;
return HYPERVISOR_hvm_op(HVMOP_set_param, &a);
}
diff --git a/xen/arch/ia64/linux-xen/unaligned.c b/xen/arch/ia64/linux-xen/unaligned.c
index 86ecbd9374..2cf6e806dc 100644
--- a/xen/arch/ia64/linux-xen/unaligned.c
+++ b/xen/arch/ia64/linux-xen/unaligned.c
@@ -24,7 +24,7 @@
#include <asm/uaccess.h>
#include <asm/unaligned.h>
-extern void die_if_kernel(char *str, struct pt_regs *regs, long err) __attribute__ ((noreturn));
+extern void die_if_kernel(char *str, struct pt_regs *regs, long err);
#undef DEBUG_UNALIGNED_TRAP
diff --git a/xen/arch/ia64/xen/xenmisc.c b/xen/arch/ia64/xen/xenmisc.c
index 532d812910..db4d14975b 100644
--- a/xen/arch/ia64/xen/xenmisc.c
+++ b/xen/arch/ia64/xen/xenmisc.c
@@ -77,7 +77,7 @@ void console_print(char *msg)
// called from unaligned.c
////////////////////////////////////
-void die_if_kernel(char *str, struct pt_regs *regs, long err) /* __attribute__ ((noreturn)) */
+void die_if_kernel(char *str, struct pt_regs *regs, long err)
{
if (user_mode(regs))
return;
@@ -88,7 +88,7 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err) /* __attribute__ (
domain_crash_synchronous();
}
-void vmx_die_if_kernel(char *str, struct pt_regs *regs, long err) /* __attribute__ ((noreturn)) */
+void vmx_die_if_kernel(char *str, struct pt_regs *regs, long err)
{
if (vmx_user_mode(regs))
return;
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index b03824f5ca..e23c85bbaa 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -1047,7 +1047,7 @@ void context_switch(struct vcpu *prev, struct vcpu *next)
local_irq_disable();
- if ( is_hvm_vcpu(prev) )
+ if ( is_hvm_vcpu(prev) && !list_empty(&prev->arch.hvm_vcpu.tm_list) )
pt_freeze_time(prev);
set_current(next);
diff --git a/xen/arch/x86/hvm/hpet.c b/xen/arch/x86/hvm/hpet.c
index e835382eac..5d8ec92150 100644
--- a/xen/arch/x86/hvm/hpet.c
+++ b/xen/arch/x86/hvm/hpet.c
@@ -356,8 +356,6 @@ static void hpet_timer_fn(void *opaque)
}
set_timer(&h->timers[tn], NOW() + hpet_tick_to_ns(h, h->period[tn]));
}
-
- vcpu_kick(h->vcpu);
}
void hpet_migrate_timers(struct vcpu *v)
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 8d8de4c513..febc278c23 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -800,7 +800,7 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
d->arch.hvm_domain.buffered_io_va = (unsigned long)p;
break;
case HVM_PARAM_CALLBACK_IRQ:
- hvm_set_callback_gsi(d, a.value);
+ hvm_set_callback_via(d, a.value);
break;
}
d->arch.hvm_domain.params[a.index] = a.value;
diff --git a/xen/arch/x86/hvm/i8254.c b/xen/arch/x86/hvm/i8254.c
index a81ae57722..1ab512d2ee 100644
--- a/xen/arch/x86/hvm/i8254.c
+++ b/xen/arch/x86/hvm/i8254.c
@@ -182,11 +182,9 @@ void pit_time_fired(struct vcpu *v, void *priv)
s->count_load_time = hvm_get_guest_time(v);
}
-static inline void pit_load_count(PITChannelState *s, int val)
+static inline void pit_load_count(PITChannelState *s, int channel, int val)
{
u32 period;
- PITChannelState *ch0 =
- &current->domain->arch.hvm_domain.pl_time.vpit.channels[0];
if (val == 0)
val = 0x10000;
@@ -194,7 +192,7 @@ static inline void pit_load_count(PITChannelState *s, int val)
s->count = val;
period = DIV_ROUND((val * 1000000000ULL), PIT_FREQ);
- if (s != ch0)
+ if (channel != 0)
return;
#ifdef DEBUG_PIT
@@ -282,17 +280,17 @@ static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val)
switch(s->write_state) {
default:
case RW_STATE_LSB:
- pit_load_count(s, val);
+ pit_load_count(s, addr, val);
break;
case RW_STATE_MSB:
- pit_load_count(s, val << 8);
+ pit_load_count(s, addr, val << 8);
break;
case RW_STATE_WORD0:
s->write_latch = val;
s->write_state = RW_STATE_WORD1;
break;
case RW_STATE_WORD1:
- pit_load_count(s, s->write_latch | (val << 8));
+ pit_load_count(s, addr, s->write_latch | (val << 8));
s->write_state = RW_STATE_WORD0;
break;
}
@@ -369,7 +367,7 @@ static void pit_reset(void *opaque)
destroy_periodic_time(&s->pt);
s->mode = 0xff; /* the init mode */
s->gate = (i != 2);
- pit_load_count(s, 0);
+ pit_load_count(s, i, 0);
}
}
diff --git a/xen/arch/x86/hvm/irq.c b/xen/arch/x86/hvm/irq.c
index 1b51f5905c..72f8419d46 100644
--- a/xen/arch/x86/hvm/irq.c
+++ b/xen/arch/x86/hvm/irq.c
@@ -25,7 +25,7 @@
#include <xen/sched.h>
#include <asm/hvm/domain.h>
-void hvm_pci_intx_assert(
+static void __hvm_pci_intx_assert(
struct domain *d, unsigned int device, unsigned int intx)
{
struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
@@ -33,10 +33,8 @@ void hvm_pci_intx_assert(
ASSERT((device <= 31) && (intx <= 3));
- spin_lock(&hvm_irq->lock);
-
if ( __test_and_set_bit(device*4 + intx, &hvm_irq->pci_intx) )
- goto out;
+ return;
gsi = hvm_pci_intx_gsi(device, intx);
if ( hvm_irq->gsi_assert_count[gsi]++ == 0 )
@@ -50,12 +48,19 @@ void hvm_pci_intx_assert(
vioapic_irq_positive_edge(d, isa_irq);
vpic_irq_positive_edge(d, isa_irq);
}
+}
- out:
+void hvm_pci_intx_assert(
+ struct domain *d, unsigned int device, unsigned int intx)
+{
+ struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+
+ spin_lock(&hvm_irq->lock);
+ __hvm_pci_intx_assert(d, device, intx);
spin_unlock(&hvm_irq->lock);
}
-void hvm_pci_intx_deassert(
+static void __hvm_pci_intx_deassert(
struct domain *d, unsigned int device, unsigned int intx)
{
struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
@@ -63,10 +68,8 @@ void hvm_pci_intx_deassert(
ASSERT((device <= 31) && (intx <= 3));
- spin_lock(&hvm_irq->lock);
-
if ( !__test_and_clear_bit(device*4 + intx, &hvm_irq->pci_intx) )
- goto out;
+ return;
gsi = hvm_pci_intx_gsi(device, intx);
--hvm_irq->gsi_assert_count[gsi];
@@ -76,8 +79,15 @@ void hvm_pci_intx_deassert(
if ( (--hvm_irq->pci_link_assert_count[link] == 0) && isa_irq &&
(--hvm_irq->gsi_assert_count[isa_irq] == 0) )
vpic_irq_negative_edge(d, isa_irq);
+}
- out:
+void hvm_pci_intx_deassert(
+ struct domain *d, unsigned int device, unsigned int intx)
+{
+ struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+
+ spin_lock(&hvm_irq->lock);
+ __hvm_pci_intx_deassert(d, device, intx);
spin_unlock(&hvm_irq->lock);
}
@@ -123,36 +133,47 @@ void hvm_set_callback_irq_level(void)
struct vcpu *v = current;
struct domain *d = v->domain;
struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
- unsigned int gsi = hvm_irq->callback_gsi;
+ unsigned int gsi, pdev, pintx, asserted;
/* Fast lock-free tests. */
- if ( (v->vcpu_id != 0) || (gsi == 0) )
+ if ( (v->vcpu_id != 0) ||
+ (hvm_irq->callback_via_type == HVMIRQ_callback_none) )
return;
spin_lock(&hvm_irq->lock);
- gsi = hvm_irq->callback_gsi;
- if ( gsi == 0 )
+ /* NB. Do not check the evtchn_upcall_mask. It is not used in HVM mode. */
+ asserted = !!vcpu_info(v, evtchn_upcall_pending);
+ if ( hvm_irq->callback_via_asserted == asserted )
goto out;
+ hvm_irq->callback_via_asserted = asserted;
- if ( local_events_need_delivery() )
+ /* Callback status has changed. Update the callback via. */
+ switch ( hvm_irq->callback_via_type )
{
- if ( !__test_and_set_bit(0, &hvm_irq->callback_irq_wire) &&
- (hvm_irq->gsi_assert_count[gsi]++ == 0) )
+ case HVMIRQ_callback_gsi:
+ gsi = hvm_irq->callback_via.gsi;
+ if ( asserted && (hvm_irq->gsi_assert_count[gsi]++ == 0) )
{
vioapic_irq_positive_edge(d, gsi);
if ( gsi <= 15 )
vpic_irq_positive_edge(d, gsi);
}
- }
- else
- {
- if ( __test_and_clear_bit(0, &hvm_irq->callback_irq_wire) &&
- (--hvm_irq->gsi_assert_count[gsi] == 0) )
+ else if ( !asserted && (--hvm_irq->gsi_assert_count[gsi] == 0) )
{
if ( gsi <= 15 )
vpic_irq_negative_edge(d, gsi);
}
+ break;
+ case HVMIRQ_callback_pci_intx:
+ pdev = hvm_irq->callback_via.pci.dev;
+ pintx = hvm_irq->callback_via.pci.intx;
+ if ( asserted )
+ __hvm_pci_intx_assert(d, pdev, pintx);
+ else
+ __hvm_pci_intx_deassert(d, pdev, pintx);
+ default:
+ break;
}
out:
@@ -192,40 +213,79 @@ void hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq)
d->domain_id, link, old_isa_irq, isa_irq);
}
-void hvm_set_callback_gsi(struct domain *d, unsigned int gsi)
+void hvm_set_callback_via(struct domain *d, uint64_t via)
{
struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
- unsigned int old_gsi;
+ unsigned int gsi=0, pdev=0, pintx=0;
+ uint8_t via_type;
- if ( gsi >= ARRAY_SIZE(hvm_irq->gsi_assert_count) )
- gsi = 0;
+ via_type = (uint8_t)(via >> 56) + 1;
+ if ( ((via_type == HVMIRQ_callback_gsi) && (via == 0)) ||
+ (via_type > HVMIRQ_callback_pci_intx) )
+ via_type = HVMIRQ_callback_none;
spin_lock(&hvm_irq->lock);
- old_gsi = hvm_irq->callback_gsi;
- if ( old_gsi == gsi )
- goto out;
- hvm_irq->callback_gsi = gsi;
-
- if ( !test_bit(0, &hvm_irq->callback_irq_wire) )
- goto out;
-
- if ( old_gsi && (--hvm_irq->gsi_assert_count[old_gsi] == 0) )
- if ( old_gsi <= 15 )
- vpic_irq_negative_edge(d, old_gsi);
+ /* Tear down old callback via. */
+ if ( hvm_irq->callback_via_asserted )
+ {
+ switch ( hvm_irq->callback_via_type )
+ {
+ case HVMIRQ_callback_gsi:
+ gsi = hvm_irq->callback_via.gsi;
+ if ( (--hvm_irq->gsi_assert_count[gsi] == 0) && (gsi <= 15) )
+ vpic_irq_negative_edge(d, gsi);
+ break;
+ case HVMIRQ_callback_pci_intx:
+ pdev = hvm_irq->callback_via.pci.dev;
+ pintx = hvm_irq->callback_via.pci.intx;
+ __hvm_pci_intx_deassert(d, pdev, pintx);
+ break;
+ default:
+ break;
+ }
+ }
- if ( gsi && (hvm_irq->gsi_assert_count[gsi]++ == 0) )
+ /* Set up new callback via. */
+ switch ( hvm_irq->callback_via_type = via_type )
{
- vioapic_irq_positive_edge(d, gsi);
- if ( gsi <= 15 )
- vpic_irq_positive_edge(d, gsi);
+ case HVMIRQ_callback_gsi:
+ gsi = hvm_irq->callback_via.gsi = (uint8_t)via;
+ if ( (gsi == 0) || (gsi >= ARRAY_SIZE(hvm_irq->gsi_assert_count)) )
+ hvm_irq->callback_via_type = HVMIRQ_callback_none;
+ else if ( hvm_irq->callback_via_asserted &&
+ (hvm_irq->gsi_assert_count[gsi]++ == 0) )
+ {
+ vioapic_irq_positive_edge(d, gsi);
+ if ( gsi <= 15 )
+ vpic_irq_positive_edge(d, gsi);
+ }
+ break;
+ case HVMIRQ_callback_pci_intx:
+ pdev = hvm_irq->callback_via.pci.dev = (uint8_t)(via >> 11) & 31;
+ pintx = hvm_irq->callback_via.pci.intx = (uint8_t)via & 3;
+ if ( hvm_irq->callback_via_asserted )
+ __hvm_pci_intx_assert(d, pdev, pintx);
+ break;
+ default:
+ break;
}
- out:
spin_unlock(&hvm_irq->lock);
- dprintk(XENLOG_G_INFO, "Dom%u callback GSI changed %u -> %u\n",
- d->domain_id, old_gsi, gsi);
+ dprintk(XENLOG_G_INFO, "Dom%u callback via changed to ", d->domain_id);
+ switch ( via_type )
+ {
+ case HVMIRQ_callback_gsi:
+ printk("GSI %u\n", gsi);
+ break;
+ case HVMIRQ_callback_pci_intx:
+ printk("PCI INTx Dev 0x%02x Int%c\n", pdev, 'A' + pintx);
+ break;
+ default:
+ printk("None\n");
+ break;
+ }
}
int cpu_has_pending_irq(struct vcpu *v)
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index 2a3e6370d6..ba3121618e 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -482,8 +482,8 @@ static int svm_guest_x86_mode(struct vcpu *v)
{
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
- if ( vmcb->efer & EFER_LMA )
- return (vmcb->cs.attr.fields.l ? 8 : 4);
+ if ( (vmcb->efer & EFER_LMA) && vmcb->cs.attr.fields.l )
+ return 8;
if ( svm_realmode(v) )
return 2;
diff --git a/xen/arch/x86/hvm/vioapic.c b/xen/arch/x86/hvm/vioapic.c
index 843c76a6dd..6f68a85b77 100644
--- a/xen/arch/x86/hvm/vioapic.c
+++ b/xen/arch/x86/hvm/vioapic.c
@@ -309,6 +309,13 @@ static uint32_t ioapic_get_delivery_bitmask(
return mask;
}
+static inline int pit_channel0_enabled(void)
+{
+ PITState *pit = &current->domain->arch.hvm_domain.pl_time.vpit;
+ struct periodic_time *pt = &pit->channels[0].pt;
+ return pt->enabled;
+}
+
static void vioapic_deliver(struct vioapic *vioapic, int irq)
{
uint16_t dest = vioapic->redirtbl[irq].fields.dest_id;
@@ -341,7 +348,7 @@ static void vioapic_deliver(struct vioapic *vioapic, int irq)
{
#ifdef IRQ0_SPECIAL_ROUTING
/* Force round-robin to pick VCPU 0 */
- if ( irq == hvm_isa_irq_to_gsi(0) )
+ if ( (irq == hvm_isa_irq_to_gsi(0)) && pit_channel0_enabled() )
{
v = vioapic_domain(vioapic)->vcpu[0];
target = v ? vcpu_vlapic(v) : NULL;
@@ -374,7 +381,7 @@ static void vioapic_deliver(struct vioapic *vioapic, int irq)
deliver_bitmask &= ~(1 << bit);
#ifdef IRQ0_SPECIAL_ROUTING
/* Do not deliver timer interrupts to VCPU != 0 */
- if ( irq == hvm_isa_irq_to_gsi(0) )
+ if ( (irq == hvm_isa_irq_to_gsi(0)) && pit_channel0_enabled() )
v = vioapic_domain(vioapic)->vcpu[0];
else
#endif
diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c
index 8355c6e54d..dde3a4c201 100644
--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -278,7 +278,14 @@ static void vmx_set_host_env(struct vcpu *v)
host_env.tr_base = (unsigned long) &init_tss[cpu];
__vmwrite(HOST_TR_SELECTOR, host_env.tr_selector);
__vmwrite(HOST_TR_BASE, host_env.tr_base);
- __vmwrite(HOST_RSP, (unsigned long)get_stack_bottom());
+
+ /*
+ * Skip end of cpu_user_regs when entering the hypervisor because the
+ * CPU does not save context onto the stack. SS,RSP,CS,RIP,RFLAGS,etc
+ * all get saved into the VMCS instead.
+ */
+ __vmwrite(HOST_RSP,
+ (unsigned long)&get_cpu_info()->guest_cpu_user_regs.error_code);
}
static void construct_vmcs(struct vcpu *v)
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index c8782ef8a2..a665367c6d 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -410,10 +410,6 @@ static void vmx_store_cpu_guest_regs(
regs->eflags = __vmread(GUEST_RFLAGS);
regs->ss = __vmread(GUEST_SS_SELECTOR);
regs->cs = __vmread(GUEST_CS_SELECTOR);
- regs->ds = __vmread(GUEST_DS_SELECTOR);
- regs->es = __vmread(GUEST_ES_SELECTOR);
- regs->gs = __vmread(GUEST_GS_SELECTOR);
- regs->fs = __vmread(GUEST_FS_SELECTOR);
regs->eip = __vmread(GUEST_RIP);
regs->esp = __vmread(GUEST_RSP);
}
@@ -429,62 +425,39 @@ static void vmx_store_cpu_guest_regs(
vmx_vmcs_exit(v);
}
-/*
- * The VMX spec (section 4.3.1.2, Checks on Guest Segment
- * Registers) says that virtual-8086 mode guests' segment
- * base-address fields in the VMCS must be equal to their
- * corresponding segment selector field shifted right by
- * four bits upon vmentry.
- *
- * This function (called only for VM86-mode guests) fixes
- * the bases to be consistent with the selectors in regs
- * if they're not already. Without this, we can fail the
- * vmentry check mentioned above.
- */
-static void fixup_vm86_seg_bases(struct cpu_user_regs *regs)
+static void vmx_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs)
{
unsigned long base;
- base = __vmread(GUEST_ES_BASE);
- if (regs->es << 4 != base)
- __vmwrite(GUEST_ES_BASE, regs->es << 4);
- base = __vmread(GUEST_CS_BASE);
- if (regs->cs << 4 != base)
- __vmwrite(GUEST_CS_BASE, regs->cs << 4);
- base = __vmread(GUEST_SS_BASE);
- if (regs->ss << 4 != base)
- __vmwrite(GUEST_SS_BASE, regs->ss << 4);
- base = __vmread(GUEST_DS_BASE);
- if (regs->ds << 4 != base)
- __vmwrite(GUEST_DS_BASE, regs->ds << 4);
- base = __vmread(GUEST_FS_BASE);
- if (regs->fs << 4 != base)
- __vmwrite(GUEST_FS_BASE, regs->fs << 4);
- base = __vmread(GUEST_GS_BASE);
- if (regs->gs << 4 != base)
- __vmwrite(GUEST_GS_BASE, regs->gs << 4);
-}
-
-static void vmx_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs)
-{
vmx_vmcs_enter(v);
__vmwrite(GUEST_SS_SELECTOR, regs->ss);
- __vmwrite(GUEST_DS_SELECTOR, regs->ds);
- __vmwrite(GUEST_ES_SELECTOR, regs->es);
- __vmwrite(GUEST_GS_SELECTOR, regs->gs);
- __vmwrite(GUEST_FS_SELECTOR, regs->fs);
-
__vmwrite(GUEST_RSP, regs->esp);
/* NB. Bit 1 of RFLAGS must be set for VMENTRY to succeed. */
__vmwrite(GUEST_RFLAGS, regs->eflags | 2UL);
- if (regs->eflags & EF_TF)
+
+ if ( regs->eflags & EF_TF )
__vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
else
__vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
- if (regs->eflags & EF_VM)
- fixup_vm86_seg_bases(regs);
+
+ if ( regs->eflags & EF_VM )
+ {
+ /*
+ * The VMX spec (section 4.3.1.2, Checks on Guest Segment
+ * Registers) says that virtual-8086 mode guests' segment
+ * base-address fields in the VMCS must be equal to their
+ * corresponding segment selector field shifted right by
+ * four bits upon vmentry.
+ */
+ base = __vmread(GUEST_CS_BASE);
+ if ( (regs->cs << 4) != base )
+ __vmwrite(GUEST_CS_BASE, regs->cs << 4);
+ base = __vmread(GUEST_SS_BASE);
+ if ( (regs->ss << 4) != base )
+ __vmwrite(GUEST_SS_BASE, regs->ss << 4);
+ }
__vmwrite(GUEST_CS_SELECTOR, regs->cs);
__vmwrite(GUEST_RIP, regs->eip);
@@ -518,8 +491,7 @@ static unsigned long vmx_get_segment_base(struct vcpu *v, enum x86_segment seg)
ASSERT(v == current);
#ifdef __x86_64__
- if ( vmx_long_mode_enabled(v) &&
- (__vmread(GUEST_CS_AR_BYTES) & (1u<<13)) )
+ if ( vmx_long_mode_enabled(v) && (__vmread(GUEST_CS_AR_BYTES) & (1u<<13)) )
long_mode = 1;
#endif
@@ -694,8 +666,8 @@ static int vmx_guest_x86_mode(struct vcpu *v)
cs_ar_bytes = __vmread(GUEST_CS_AR_BYTES);
- if ( vmx_long_mode_enabled(v) )
- return ((cs_ar_bytes & (1u<<13)) ? 8 : 4);
+ if ( vmx_long_mode_enabled(v) && (cs_ar_bytes & (1u<<13)) )
+ return 8;
if ( vmx_realmode(v) )
return 2;
@@ -2251,47 +2223,54 @@ static void vmx_reflect_exception(struct vcpu *v)
}
}
+static void vmx_failed_vmentry(unsigned int exit_reason)
+{
+ unsigned int failed_vmentry_reason = (uint16_t)exit_reason;
+ unsigned long exit_qualification;
+
+ exit_qualification = __vmread(EXIT_QUALIFICATION);
+ printk("Failed vm entry (exit reason 0x%x) ", exit_reason);
+ switch ( failed_vmentry_reason )
+ {
+ case EXIT_REASON_INVALID_GUEST_STATE:
+ printk("caused by invalid guest state (%ld).\n", exit_qualification);
+ break;
+ case EXIT_REASON_MSR_LOADING:
+ printk("caused by MSR entry %ld loading.\n", exit_qualification);
+ break;
+ case EXIT_REASON_MACHINE_CHECK:
+ printk("caused by machine check.\n");
+ break;
+ default:
+ printk("reason not known yet!");
+ break;
+ }
+
+ printk("************* VMCS Area **************\n");
+ vmcs_dump_vcpu();
+ printk("**************************************\n");
+
+ domain_crash(current->domain);
+}
+
asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
{
unsigned int exit_reason;
unsigned long exit_qualification, inst_len = 0;
struct vcpu *v = current;
+ TRACE_3D(TRC_VMX_VMEXIT + v->vcpu_id, 0, 0, 0);
+
exit_reason = __vmread(VM_EXIT_REASON);
perfc_incra(vmexits, exit_reason);
+ TRACE_VMEXIT(0, exit_reason);
if ( exit_reason != EXIT_REASON_EXTERNAL_INTERRUPT )
local_irq_enable();
if ( unlikely(exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) )
- {
- unsigned int failed_vmentry_reason = exit_reason & 0xFFFF;
-
- exit_qualification = __vmread(EXIT_QUALIFICATION);
- printk("Failed vm entry (exit reason 0x%x) ", exit_reason);
- switch ( failed_vmentry_reason ) {
- case EXIT_REASON_INVALID_GUEST_STATE:
- printk("caused by invalid guest state (%ld).\n", exit_qualification);
- break;
- case EXIT_REASON_MSR_LOADING:
- printk("caused by MSR entry %ld loading.\n", exit_qualification);
- break;
- case EXIT_REASON_MACHINE_CHECK:
- printk("caused by machine check.\n");
- break;
- default:
- printk("reason not known yet!");
- break;
- }
-
- printk("************* VMCS Area **************\n");
- vmcs_dump_vcpu();
- printk("**************************************\n");
- goto exit_and_crash;
- }
-
- TRACE_VMEXIT(0, exit_reason);
+ return vmx_failed_vmentry(exit_reason);
switch ( exit_reason )
{
@@ -2519,11 +2498,6 @@ asmlinkage void vmx_trace_vmentry(void)
TRACE_VMEXIT(4, 0);
}
-asmlinkage void vmx_trace_vmexit (void)
-{
- TRACE_3D(TRC_VMX_VMEXIT + current->vcpu_id, 0, 0, 0);
-}
-
/*
* Local variables:
* mode: C
diff --git a/xen/arch/x86/hvm/vmx/x86_32/exits.S b/xen/arch/x86/hvm/vmx/x86_32/exits.S
index 144dd174d4..ef24dce0ea 100644
--- a/xen/arch/x86/hvm/vmx/x86_32/exits.S
+++ b/xen/arch/x86/hvm/vmx/x86_32/exits.S
@@ -29,35 +29,7 @@
andl $~3,reg; \
movl (reg),reg;
-/*
- * At VMExit time the processor saves the guest selectors, esp, eip,
- * and eflags. Therefore we don't save them, but simply decrement
- * the kernel stack pointer to make it consistent with the stack frame
- * at usual interruption time. The eflags of the host is not saved by VMX,
- * and we set it to the fixed value.
- *
- * We also need the room, especially because orig_eax field is used
- * by do_IRQ(). Compared the cpu_user_regs, we skip pushing for the following:
- * (10) u32 gs;
- * (9) u32 fs;
- * (8) u32 ds;
- * (7) u32 es;
- * <- get_stack_bottom() (= HOST_ESP)
- * (6) u32 ss;
- * (5) u32 esp;
- * (4) u32 eflags;
- * (3) u32 cs;
- * (2) u32 eip;
- * (2/1) u16 entry_vector;
- * (1/1) u16 error_code;
- * However, get_stack_bottom() actually returns 20 bytes before the real
- * bottom of the stack to allow space for:
- * domain pointer, DS, ES, FS, GS. Therefore, we effectively skip 6 registers.
- */
-
-#define NR_SKIPPED_REGS 6 /* See the above explanation */
#define HVM_SAVE_ALL_NOSEGREGS \
- subl $(NR_SKIPPED_REGS*4), %esp; \
movl $0, 0xc(%esp); /* XXX why do we need to force eflags==0 ?? */ \
pushl %eax; \
pushl %ebp; \
@@ -74,14 +46,11 @@
popl %esi; \
popl %edi; \
popl %ebp; \
- popl %eax; \
- addl $(NR_SKIPPED_REGS*4), %esp
+ popl %eax
ALIGN
ENTRY(vmx_asm_vmexit_handler)
- /* selectors are restored/saved by VMX */
HVM_SAVE_ALL_NOSEGREGS
- call vmx_trace_vmexit
movl %esp,%eax
push %eax
call vmx_vmexit_handler
diff --git a/xen/arch/x86/hvm/vmx/x86_64/exits.S b/xen/arch/x86/hvm/vmx/x86_64/exits.S
index d427ac2cd5..0bebeb6ec3 100644
--- a/xen/arch/x86/hvm/vmx/x86_64/exits.S
+++ b/xen/arch/x86/hvm/vmx/x86_64/exits.S
@@ -29,31 +29,7 @@
andq $~7,reg; \
movq (reg),reg;
-/*
- * At VMExit time the processor saves the guest selectors, rsp, rip,
- * and rflags. Therefore we don't save them, but simply decrement
- * the kernel stack pointer to make it consistent with the stack frame
- * at usual interruption time. The rflags of the host is not saved by VMX,
- * and we set it to the fixed value.
- *
- * We also need the room, especially because orig_eax field is used
- * by do_IRQ(). Compared the cpu_user_regs, we skip pushing for the following:
- * (10) u64 gs;
- * (9) u64 fs;
- * (8) u64 ds;
- * (7) u64 es;
- * <- get_stack_bottom() (= HOST_ESP)
- * (6) u64 ss;
- * (5) u64 rsp;
- * (4) u64 rflags;
- * (3) u64 cs;
- * (2) u64 rip;
- * (2/1) u32 entry_vector;
- * (1/1) u32 error_code;
- */
-#define NR_SKIPPED_REGS 6 /* See the above explanation */
#define HVM_SAVE_ALL_NOSEGREGS \
- subq $(NR_SKIPPED_REGS*8), %rsp; \
pushq %rdi; \
pushq %rsi; \
pushq %rdx; \
@@ -85,14 +61,11 @@
popq %rcx; \
popq %rdx; \
popq %rsi; \
- popq %rdi; \
- addq $(NR_SKIPPED_REGS*8), %rsp;
+ popq %rdi
ALIGN
ENTRY(vmx_asm_vmexit_handler)
- /* selectors are restored/saved by VMX */
HVM_SAVE_ALL_NOSEGREGS
- call vmx_trace_vmexit
movq %rsp,%rdi
call vmx_vmexit_handler
jmp vmx_asm_do_vmentry
diff --git a/xen/arch/x86/microcode.c b/xen/arch/x86/microcode.c
index 3dcac7d124..89138c9a79 100644
--- a/xen/arch/x86/microcode.c
+++ b/xen/arch/x86/microcode.c
@@ -249,14 +249,14 @@ static int find_matching_ucodes (void)
}
total_size = get_totalsize(&mc_header);
- if ((cursor + total_size > user_buffer_size) || (total_size < DEFAULT_UCODE_TOTALSIZE)) {
+ if (cursor + total_size > user_buffer_size) {
printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
error = -EINVAL;
goto out;
}
data_size = get_datasize(&mc_header);
- if ((data_size + MC_HEADER_SIZE > total_size) || (data_size < DEFAULT_UCODE_DATASIZE)) {
+ if (data_size + MC_HEADER_SIZE > total_size) {
printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
error = -EINVAL;
goto out;
@@ -459,11 +459,6 @@ int microcode_update(XEN_GUEST_HANDLE(void) buf, unsigned long len)
{
int ret;
- if (len < DEFAULT_UCODE_TOTALSIZE) {
- printk(KERN_ERR "microcode: not enough data\n");
- return -EINVAL;
- }
-
if (len != (typeof(user_buffer_size))len) {
printk(KERN_ERR "microcode: too much data\n");
return -E2BIG;
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 026180c11a..49501411e6 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -154,6 +154,15 @@ l2_pgentry_t *compat_idle_pg_table_l2 = NULL;
#define l3_disallow_mask(d) L3_DISALLOW_MASK
#endif
+static void queue_deferred_ops(struct domain *d, unsigned int ops)
+{
+ if ( d == current->domain )
+ this_cpu(percpu_mm_info).deferred_ops |= ops;
+ else
+ BUG_ON(!test_bit(_DOMF_paused, &d->domain_flags) ||
+ !cpus_empty(d->domain_dirty_cpumask));
+}
+
void __init init_frametable(void)
{
unsigned long nr_pages, page_step, i, mfn;
@@ -416,8 +425,7 @@ void invalidate_shadow_ldt(struct vcpu *v)
}
/* Dispose of the (now possibly invalid) mappings from the TLB. */
- ASSERT(v->processor == smp_processor_id());
- this_cpu(percpu_mm_info).deferred_ops |= DOP_FLUSH_TLB | DOP_RELOAD_LDT;
+ queue_deferred_ops(v->domain, DOP_FLUSH_TLB | DOP_RELOAD_LDT);
}
@@ -826,7 +834,7 @@ static void put_page_from_l2e(l2_pgentry_t l2e, unsigned long pfn)
{
if ( (l2e_get_flags(l2e) & _PAGE_PRESENT) &&
(l2e_get_pfn(l2e) != pfn) )
- put_page_and_type(mfn_to_page(l2e_get_pfn(l2e)));
+ put_page_and_type(l2e_get_page(l2e));
}
@@ -835,7 +843,7 @@ static void put_page_from_l3e(l3_pgentry_t l3e, unsigned long pfn)
{
if ( (l3e_get_flags(l3e) & _PAGE_PRESENT) &&
(l3e_get_pfn(l3e) != pfn) )
- put_page_and_type(mfn_to_page(l3e_get_pfn(l3e)));
+ put_page_and_type(l3e_get_page(l3e));
}
#endif
@@ -844,7 +852,7 @@ static void put_page_from_l4e(l4_pgentry_t l4e, unsigned long pfn)
{
if ( (l4e_get_flags(l4e) & _PAGE_PRESENT) &&
(l4e_get_pfn(l4e) != pfn) )
- put_page_and_type(mfn_to_page(l4e_get_pfn(l4e)));
+ put_page_and_type(l4e_get_page(l4e));
}
#endif
@@ -945,7 +953,8 @@ static int create_pae_xen_mappings(struct domain *d, l3_pgentry_t *pl3e)
}
#else
memcpy(&pl2e[COMPAT_L2_PAGETABLE_FIRST_XEN_SLOT(d)],
- &compat_idle_pg_table_l2[l2_table_offset(HIRO_COMPAT_MPT_VIRT_START)],
+ &compat_idle_pg_table_l2[
+ l2_table_offset(HIRO_COMPAT_MPT_VIRT_START)],
COMPAT_L2_PAGETABLE_XEN_SLOTS(d) * sizeof(*pl2e));
#endif
unmap_domain_page(pl2e);
@@ -1376,7 +1385,7 @@ static int mod_l2_entry(l2_pgentry_t *pl2e,
if ( !l2e_has_changed(ol2e, nl2e, _PAGE_PRESENT))
return UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, current);
- if ( unlikely(!get_page_from_l2e(nl2e, pfn, current->domain)) )
+ if ( unlikely(!get_page_from_l2e(nl2e, pfn, d)) )
return 0;
if ( unlikely(!UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, current)) )
@@ -1439,7 +1448,7 @@ static int mod_l3_entry(l3_pgentry_t *pl3e,
if (!l3e_has_changed(ol3e, nl3e, _PAGE_PRESENT))
return UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, pfn, current);
- if ( unlikely(!get_page_from_l3e(nl3e, pfn, current->domain)) )
+ if ( unlikely(!get_page_from_l3e(nl3e, pfn, d)) )
return 0;
if ( unlikely(!UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, pfn, current)) )
@@ -1561,7 +1570,7 @@ void free_page_type(struct page_info *page, unsigned long type)
* (e.g., update_va_mapping()) or we could end up modifying a page
* that is no longer a page table (and hence screw up ref counts).
*/
- this_cpu(percpu_mm_info).deferred_ops |= DOP_FLUSH_ALL_TLBS;
+ queue_deferred_ops(owner, DOP_FLUSH_ALL_TLBS);
if ( unlikely(shadow_mode_enabled(owner)) )
{
@@ -1759,24 +1768,14 @@ int new_guest_cr3(unsigned long mfn)
int okay;
unsigned long old_base_mfn;
- if ( is_hvm_domain(d) && !hvm_paging_enabled(v) )
- return 0;
-
#ifdef CONFIG_COMPAT
if ( IS_COMPAT(d) )
{
- l4_pgentry_t l4e = l4e_from_pfn(mfn, _PAGE_PRESENT|_PAGE_RW|_PAGE_USER|_PAGE_ACCESSED);
-
- if ( shadow_mode_refcounts(d) )
- {
- okay = get_page_from_pagenr(mfn, d);
- old_base_mfn = l4e_get_pfn(l4e);
- if ( okay && old_base_mfn )
- put_page(mfn_to_page(old_base_mfn));
- }
- else
- okay = mod_l4_entry(__va(pagetable_get_paddr(v->arch.guest_table)),
- l4e, 0);
+ okay = shadow_mode_refcounts(d)
+ ? 0 /* Old code was broken, but what should it be? */
+ : mod_l4_entry(__va(pagetable_get_paddr(v->arch.guest_table)),
+ l4e_from_pfn(mfn, (_PAGE_PRESENT|_PAGE_RW|
+ _PAGE_USER|_PAGE_ACCESSED)), 0);
if ( unlikely(!okay) )
{
MEM_LOG("Error while installing new compat baseptr %lx", mfn);
@@ -1789,41 +1788,13 @@ int new_guest_cr3(unsigned long mfn)
return 1;
}
#endif
- if ( shadow_mode_refcounts(d) )
- {
- okay = get_page_from_pagenr(mfn, d);
- if ( unlikely(!okay) )
- {
- MEM_LOG("Error while installing new baseptr %lx", mfn);
- return 0;
- }
- }
- else
+ okay = shadow_mode_refcounts(d)
+ ? get_page_from_pagenr(mfn, d)
+ : get_page_and_type_from_pagenr(mfn, PGT_root_page_table, d);
+ if ( unlikely(!okay) )
{
- okay = get_page_and_type_from_pagenr(mfn, PGT_root_page_table, d);
- if ( unlikely(!okay) )
- {
- /* Switch to idle pagetable: this VCPU has no active p.t. now. */
- MEM_LOG("New baseptr %lx: slow path via idle pagetables", mfn);
- old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
- v->arch.guest_table = pagetable_null();
- update_cr3(v);
- write_cr3(__pa(idle_pg_table));
- if ( old_base_mfn != 0 )
- put_page_and_type(mfn_to_page(old_base_mfn));
-
- /* Retry the validation with no active p.t. for this VCPU. */
- okay = get_page_and_type_from_pagenr(mfn, PGT_root_page_table, d);
- if ( !okay )
- {
- /* Failure here is unrecoverable: the VCPU has no pagetable! */
- MEM_LOG("Fatal error while installing new baseptr %lx", mfn);
- domain_crash(d);
- ASSERT(v->processor == smp_processor_id());
- this_cpu(percpu_mm_info).deferred_ops = 0;
- return 0;
- }
- }
+ MEM_LOG("Error while installing new baseptr %lx", mfn);
+ return 0;
}
invalidate_shadow_ldt(v);
@@ -1831,7 +1802,7 @@ int new_guest_cr3(unsigned long mfn)
old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
v->arch.guest_table = pagetable_from_pfn(mfn);
- update_cr3(v); /* update shadow_table and cr3 fields of vcpu struct */
+ update_cr3(v);
write_ptbase(v);
@@ -3182,7 +3153,7 @@ static int ptwr_emulated_update(
unsigned int do_cmpxchg,
struct ptwr_emulate_ctxt *ptwr_ctxt)
{
- unsigned long gmfn, mfn;
+ unsigned long mfn;
struct page_info *page;
l1_pgentry_t pte, ol1e, nl1e, *pl1e;
struct vcpu *v = current;
@@ -3222,8 +3193,7 @@ static int ptwr_emulated_update(
}
pte = ptwr_ctxt->pte;
- gmfn = l1e_get_pfn(pte);
- mfn = gmfn_to_mfn(d, gmfn);
+ mfn = l1e_get_pfn(pte);
page = mfn_to_page(mfn);
/* We are looking only for read-only mappings of p.t. pages. */
@@ -3237,15 +3207,14 @@ static int ptwr_emulated_update(
if ( unlikely(!get_page_from_l1e(gl1e_to_ml1e(d, nl1e), d)) )
{
if ( (CONFIG_PAGING_LEVELS == 3 || IS_COMPAT(d)) &&
- (bytes == 4) &&
- !do_cmpxchg &&
+ (bytes == 4) && (addr & 4) && !do_cmpxchg &&
(l1e_get_flags(nl1e) & _PAGE_PRESENT) )
{
/*
- * If this is a half-write to a PAE PTE then we assume that the
- * guest has simply got the two writes the wrong way round. We
- * zap the PRESENT bit on the assumption the bottom half will be
- * written immediately after we return to the guest.
+ * If this is an upper-half write to a PAE PTE then we assume that
+ * the guest has simply got the two writes the wrong way round. We
+ * zap the PRESENT bit on the assumption that the bottom half will
+ * be written immediately after we return to the guest.
*/
MEM_LOG("ptwr_emulate: fixing up invalid PAE PTE %"PRIpte,
l1e_get_intpte(nl1e));
@@ -3354,7 +3323,6 @@ int ptwr_do_page_fault(struct vcpu *v, unsigned long addr,
struct cpu_user_regs *regs)
{
struct domain *d = v->domain;
- unsigned long pfn;
struct page_info *page;
l1_pgentry_t pte;
struct ptwr_emulate_ctxt ptwr_ctxt;
@@ -3368,8 +3336,7 @@ int ptwr_do_page_fault(struct vcpu *v, unsigned long addr,
guest_get_eff_l1e(v, addr, &pte);
if ( !(l1e_get_flags(pte) & _PAGE_PRESENT) )
goto bail;
- pfn = l1e_get_pfn(pte);
- page = mfn_to_page(pfn);
+ page = l1e_get_page(pte);
/* We are looking only for read-only mappings of p.t. pages. */
if ( ((l1e_get_flags(pte) & (_PAGE_PRESENT|_PAGE_RW)) != _PAGE_PRESENT) ||
@@ -3378,8 +3345,9 @@ int ptwr_do_page_fault(struct vcpu *v, unsigned long addr,
(page_get_owner(page) != d) )
goto bail;
- ptwr_ctxt.ctxt.regs = guest_cpu_user_regs();
- ptwr_ctxt.ctxt.address_bytes = IS_COMPAT(d) ? 4 : sizeof(long);
+ ptwr_ctxt.ctxt.regs = regs;
+ ptwr_ctxt.ctxt.addr_size = ptwr_ctxt.ctxt.sp_size =
+ IS_COMPAT(d) ? 32 : BITS_PER_LONG;
ptwr_ctxt.cr2 = addr;
ptwr_ctxt.pte = pte;
if ( x86_emulate(&ptwr_ctxt.ctxt, &ptwr_emulate_ops) )
diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c
index e1a2e44447..115ad74d72 100644
--- a/xen/arch/x86/mm/shadow/common.c
+++ b/xen/arch/x86/mm/shadow/common.c
@@ -110,7 +110,7 @@ static int hvm_translate_linear_addr(
unsigned long limit, addr = offset;
uint32_t last_byte;
- if ( sh_ctxt->ctxt.address_bytes != 8 )
+ if ( sh_ctxt->ctxt.addr_size != 64 )
{
/*
* COMPATIBILITY MODE: Apply segment checks and add base.
@@ -399,7 +399,7 @@ static struct x86_emulate_ops pv_shadow_emulator_ops = {
struct x86_emulate_ops *shadow_init_emulation(
struct sh_emulate_ctxt *sh_ctxt, struct cpu_user_regs *regs)
{
- struct segment_register *creg;
+ struct segment_register *creg, *sreg;
struct vcpu *v = current;
unsigned long addr;
@@ -407,7 +407,7 @@ struct x86_emulate_ops *shadow_init_emulation(
if ( !is_hvm_vcpu(v) )
{
- sh_ctxt->ctxt.address_bytes = sizeof(long);
+ sh_ctxt->ctxt.addr_size = sh_ctxt->ctxt.sp_size = BITS_PER_LONG;
return &pv_shadow_emulator_ops;
}
@@ -416,12 +416,20 @@ struct x86_emulate_ops *shadow_init_emulation(
creg = hvm_get_seg_reg(x86_seg_cs, sh_ctxt);
/* Work out the emulation mode. */
- if ( hvm_long_mode_enabled(v) )
- sh_ctxt->ctxt.address_bytes = creg->attr.fields.l ? 8 : 4;
+ if ( hvm_long_mode_enabled(v) && creg->attr.fields.l )
+ {
+ sh_ctxt->ctxt.addr_size = sh_ctxt->ctxt.sp_size = 64;
+ }
else if ( regs->eflags & X86_EFLAGS_VM )
- sh_ctxt->ctxt.address_bytes = 2;
+ {
+ sh_ctxt->ctxt.addr_size = sh_ctxt->ctxt.sp_size = 16;
+ }
else
- sh_ctxt->ctxt.address_bytes = creg->attr.fields.db ? 4 : 2;
+ {
+ sreg = hvm_get_seg_reg(x86_seg_ss, sh_ctxt);
+ sh_ctxt->ctxt.addr_size = creg->attr.fields.db ? 32 : 16;
+ sh_ctxt->ctxt.sp_size = sreg->attr.fields.db ? 32 : 16;
+ }
/* Attempt to prefetch whole instruction. */
sh_ctxt->insn_buf_bytes =
@@ -1303,6 +1311,9 @@ shadow_alloc_p2m_table(struct domain *d)
if ( !shadow_set_p2m_entry(d, gfn, mfn) )
goto error;
+ /* Build a p2m map that matches the m2p entries for this domain's
+ * allocated pages. Skip any pages that have an explicitly invalid
+ * or obviously bogus m2p entry. */
for ( entry = d->page_list.next;
entry != &d->page_list;
entry = entry->next )
@@ -1318,6 +1329,8 @@ shadow_alloc_p2m_table(struct domain *d)
(gfn != 0x55555555L)
#endif
&& gfn != INVALID_M2P_ENTRY
+ && (gfn <
+ (RO_MPT_VIRT_END - RO_MPT_VIRT_START) / sizeof (l1_pgentry_t))
&& !shadow_set_p2m_entry(d, gfn, mfn) )
goto error;
}
diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c
index ba4659d325..0546cb1a66 100644
--- a/xen/arch/x86/mm/shadow/multi.c
+++ b/xen/arch/x86/mm/shadow/multi.c
@@ -851,9 +851,7 @@ static inline void safe_write_entry(void *dst, void *src)
* then writing the high word before the low word. */
BUILD_BUG_ON(sizeof (shadow_l1e_t) != 2 * sizeof (unsigned long));
d[0] = 0;
- wmb();
d[1] = s[1];
- wmb();
d[0] = s[0];
#else
/* In 32-bit and 64-bit, sizeof(pte) == sizeof(ulong) == 1 word,
@@ -3946,7 +3944,7 @@ sh_x86_emulate_write(struct vcpu *v, unsigned long vaddr, void *src,
if ( !skip ) sh_validate_guest_pt_write(v, mfn, addr, bytes);
/* If we are writing zeros to this page, might want to unshadow */
- if ( likely(bytes >= 4) && (*(u32 *)addr == 0) )
+ if ( likely(bytes >= 4) && (*(u32 *)addr == 0) && is_lo_pte(vaddr) )
check_for_early_unshadow(v, mfn);
sh_unmap_domain_page(addr);
@@ -3998,7 +3996,7 @@ sh_x86_emulate_cmpxchg(struct vcpu *v, unsigned long vaddr,
vaddr, prev, old, new, *(unsigned long *)addr, bytes);
/* If we are writing zeros to this page, might want to unshadow */
- if ( likely(bytes >= 4) && (*(u32 *)addr == 0) )
+ if ( likely(bytes >= 4) && (*(u32 *)addr == 0) && is_lo_pte(vaddr) )
check_for_early_unshadow(v, mfn);
sh_unmap_domain_page(addr);
diff --git a/xen/arch/x86/mm/shadow/private.h b/xen/arch/x86/mm/shadow/private.h
index 913fa43770..21d78eb2de 100644
--- a/xen/arch/x86/mm/shadow/private.h
+++ b/xen/arch/x86/mm/shadow/private.h
@@ -427,6 +427,11 @@ extern int sh_remove_write_access(struct vcpu *v, mfn_t readonly_mfn,
#undef mfn_valid
#define mfn_valid(_mfn) (mfn_x(_mfn) < max_page)
+#if GUEST_PAGING_LEVELS >= 3
+# define is_lo_pte(_vaddr) (((_vaddr)&0x4)==0)
+#else
+# define is_lo_pte(_vaddr) (1)
+#endif
static inline int
sh_mfn_is_a_page_table(mfn_t gmfn)
diff --git a/xen/arch/x86/oprofile/nmi_int.c b/xen/arch/x86/oprofile/nmi_int.c
index 15e2818edb..ffefe3bf2d 100644
--- a/xen/arch/x86/oprofile/nmi_int.c
+++ b/xen/arch/x86/oprofile/nmi_int.c
@@ -42,7 +42,7 @@ extern int is_profiled(struct domain *d);
extern size_t strlcpy(char *dest, const char *src, size_t size);
-int nmi_callback(struct cpu_user_regs *regs, int cpu)
+static int nmi_callback(struct cpu_user_regs *regs, int cpu)
{
int xen_mode, ovf;
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index 8770a29509..0b4da62dee 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -411,6 +411,23 @@ void __init __start_xen(multiboot_info_t *mbi)
printk("WARNING: Buggy e820 map detected and fixed "
"(truncated length fields).\n");
+ /* Ensure that all E820 RAM regions are page-aligned and -sized. */
+ for ( i = 0; i < e820_raw_nr; i++ )
+ {
+ uint64_t s, e;
+ if ( e820_raw[i].type != E820_RAM )
+ continue;
+ s = PFN_UP(e820_raw[i].addr);
+ e = PFN_DOWN(e820_raw[i].addr + e820_raw[i].size);
+ e820_raw[i].size = 0; /* discarded later */
+ if ( s < e )
+ {
+ e820_raw[i].addr = s << PAGE_SHIFT;
+ e820_raw[i].size = (e - s) << PAGE_SHIFT;
+ }
+ }
+
+ /* Sanitise the raw E820 map to produce a final clean version. */
max_page = init_e820(e820_raw, &e820_raw_nr);
modules_length = mod[mbi->mods_count-1].mod_end - mod[0].mod_start;
@@ -423,7 +440,7 @@ void __init __start_xen(multiboot_info_t *mbi)
printk("Not enough memory to stash the DOM0 kernel image.\n");
for ( ; ; ) ;
}
-
+
if ( (e820.map[i].type == E820_RAM) &&
(e820.map[i].size >= modules_length) &&
((e820.map[i].addr + e820.map[i].size) >=
@@ -474,10 +491,10 @@ void __init __start_xen(multiboot_info_t *mbi)
start = PFN_UP(e820.map[i].addr);
end = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
/* Clip the range to exclude what the bootstrapper initialised. */
- if ( end < init_mapped )
- continue;
if ( start < init_mapped )
start = init_mapped;
+ if ( end <= start )
+ continue;
/* Request the mapping. */
map_pages_to_xen(
PAGE_OFFSET + (start << PAGE_SHIFT),
@@ -486,7 +503,7 @@ void __init __start_xen(multiboot_info_t *mbi)
#endif
}
- if ( kexec_crash_area.size > 0 )
+ if ( kexec_crash_area.size > 0 && kexec_crash_area.start > 0)
{
unsigned long kdump_start, kdump_size, k;
diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index cf1defeae3..1525882b8e 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -1121,7 +1121,7 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
{
struct vcpu *v = current;
unsigned long *reg, eip = regs->eip, res;
- u8 opcode, modrm_reg = 0, modrm_rm = 0, rep_prefix = 0, rex = 0;
+ u8 opcode, modrm_reg = 0, modrm_rm = 0, rep_prefix = 0, lock = 0, rex = 0;
enum { lm_seg_none, lm_seg_fs, lm_seg_gs } lm_ovr = lm_seg_none;
unsigned int port, i, data_sel, ar, data, rc;
unsigned int op_bytes, op_default, ad_bytes, ad_default;
@@ -1184,6 +1184,7 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
data_sel = regs->ss;
continue;
case 0xf0: /* LOCK */
+ lock = 1;
continue;
case 0xf2: /* REPNE/REPNZ */
case 0xf3: /* REP/REPE/REPZ */
@@ -1210,6 +1211,9 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
if ( opcode == 0x0f )
goto twobyte_opcode;
+ if ( lock )
+ goto fail;
+
/* Input/Output String instructions. */
if ( (opcode >= 0x6c) && (opcode <= 0x6f) )
{
@@ -1472,6 +1476,8 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
/* Privileged (ring 0) instructions. */
opcode = insn_fetch(u8, code_base, eip, code_limit);
+ if ( lock && (opcode & ~3) != 0x20 )
+ goto fail;
switch ( opcode )
{
case 0x06: /* CLTS */
@@ -1490,7 +1496,7 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
case 0x20: /* MOV CR?,<reg> */
opcode = insn_fetch(u8, code_base, eip, code_limit);
- modrm_reg |= (opcode >> 3) & 7;
+ modrm_reg += ((opcode >> 3) & 7) + (lock << 3);
modrm_rm |= (opcode >> 0) & 7;
reg = decode_register(modrm_rm, regs, 0);
switch ( modrm_reg )
@@ -1530,7 +1536,7 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
case 0x21: /* MOV DR?,<reg> */
opcode = insn_fetch(u8, code_base, eip, code_limit);
- modrm_reg |= (opcode >> 3) & 7;
+ modrm_reg += ((opcode >> 3) & 7) + (lock << 3);
modrm_rm |= (opcode >> 0) & 7;
reg = decode_register(modrm_rm, regs, 0);
if ( (res = do_get_debugreg(modrm_reg)) > (unsigned long)-256 )
@@ -1540,7 +1546,7 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
case 0x22: /* MOV <reg>,CR? */
opcode = insn_fetch(u8, code_base, eip, code_limit);
- modrm_reg |= (opcode >> 3) & 7;
+ modrm_reg += ((opcode >> 3) & 7) + (lock << 3);
modrm_rm |= (opcode >> 0) & 7;
reg = decode_register(modrm_rm, regs, 0);
switch ( modrm_reg )
@@ -1588,7 +1594,7 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
case 0x23: /* MOV <reg>,DR? */
opcode = insn_fetch(u8, code_base, eip, code_limit);
- modrm_reg |= (opcode >> 3) & 7;
+ modrm_reg += ((opcode >> 3) & 7) + (lock << 3);
modrm_rm |= (opcode >> 0) & 7;
reg = decode_register(modrm_rm, regs, 0);
if ( do_set_debugreg(modrm_reg, *reg) != 0 )
@@ -1854,7 +1860,7 @@ static int dummy_nmi_callback(struct cpu_user_regs *regs, int cpu)
}
static nmi_callback_t nmi_callback = dummy_nmi_callback;
-
+
asmlinkage void do_nmi(struct cpu_user_regs *regs)
{
unsigned int cpu = smp_processor_id();
diff --git a/xen/arch/x86/x86_64/compat/mm.c b/xen/arch/x86/x86_64/compat/mm.c
index ae833ff4a6..a9c136323f 100644
--- a/xen/arch/x86/x86_64/compat/mm.c
+++ b/xen/arch/x86/x86_64/compat/mm.c
@@ -1,6 +1,7 @@
#ifdef CONFIG_COMPAT
#include <xen/event.h>
+#include <xen/multicall.h>
#include <compat/memory.h>
#include <compat/xen.h>
@@ -289,20 +290,27 @@ int compat_mmuext_op(XEN_GUEST_HANDLE(mmuext_op_compat_t) cmp_uops,
if ( err == __HYPERVISOR_mmuext_op )
{
struct cpu_user_regs *regs = guest_cpu_user_regs();
- unsigned int left = regs->ecx & ~MMU_UPDATE_PREEMPTED;
+ struct mc_state *mcs = &this_cpu(mc_state);
+ unsigned int arg1 = !test_bit(_MCSF_in_multicall, &mcs->flags)
+ ? regs->ecx
+ : mcs->call.args[1];
+ unsigned int left = arg1 & ~MMU_UPDATE_PREEMPTED;
- BUG_ON(!(regs->ecx & MMU_UPDATE_PREEMPTED));
+ BUG_ON(left == arg1);
BUG_ON(left > count);
guest_handle_add_offset(nat_ops, count - left);
BUG_ON(left + i < count);
guest_handle_add_offset(cmp_uops, (signed int)(count - left - i));
left = 1;
BUG_ON(!hypercall_xlat_continuation(&left, 0x01, nat_ops, cmp_uops));
- BUG_ON(left != regs->ecx);
- regs->ecx += count - i;
+ BUG_ON(left != arg1);
+ if (!test_bit(_MCSF_in_multicall, &mcs->flags))
+ regs->_ecx += count - i;
+ else
+ mcs->compat_call.args[1] += count - i;
}
else
- BUG_ON(rc > 0);
+ BUG_ON(err > 0);
rc = err;
}
diff --git a/xen/arch/x86/x86_emulate.c b/xen/arch/x86/x86_emulate.c
index b4118c4318..7788961f36 100644
--- a/xen/arch/x86/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate.c
@@ -3,7 +3,21 @@
*
* Generic x86 (32-bit and 64-bit) instruction decoder and emulator.
*
- * Copyright (c) 2005 Keir Fraser
+ * Copyright (c) 2005-2007 Keir Fraser
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __XEN__
@@ -33,9 +47,8 @@
#define SrcReg (1<<3) /* Register operand. */
#define SrcMem (2<<3) /* Memory operand. */
#define SrcMem16 (3<<3) /* Memory operand (16-bit). */
-#define SrcMem32 (4<<3) /* Memory operand (32-bit). */
-#define SrcImm (5<<3) /* Immediate operand. */
-#define SrcImmByte (6<<3) /* 8-bit sign-extended immediate operand. */
+#define SrcImm (4<<3) /* Immediate operand. */
+#define SrcImmByte (5<<3) /* 8-bit sign-extended immediate operand. */
#define SrcMask (7<<3)
/* Generic ModRM decode. */
#define ModRM (1<<6)
@@ -62,19 +75,19 @@ static uint8_t opcode_table[256] = {
/* 0x20 - 0x27 */
ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
- ByteOp|DstReg|SrcImm, DstReg|SrcImm, 0, 0,
+ ByteOp|DstReg|SrcImm, DstReg|SrcImm, 0, ImplicitOps,
/* 0x28 - 0x2F */
ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
- ByteOp|DstReg|SrcImm, DstReg|SrcImm, 0, 0,
+ ByteOp|DstReg|SrcImm, DstReg|SrcImm, 0, ImplicitOps,
/* 0x30 - 0x37 */
ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
- ByteOp|DstReg|SrcImm, DstReg|SrcImm, 0, 0,
+ ByteOp|DstReg|SrcImm, DstReg|SrcImm, 0, ImplicitOps,
/* 0x38 - 0x3F */
ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
- ByteOp|DstReg|SrcImm, DstReg|SrcImm, 0, 0,
+ ByteOp|DstReg|SrcImm, DstReg|SrcImm, 0, ImplicitOps,
/* 0x40 - 0x4F */
ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
@@ -85,9 +98,13 @@ static uint8_t opcode_table[256] = {
ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov,
ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov,
ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov,
- /* 0x60 - 0x6F */
- 0, 0, 0, DstReg|SrcMem32|ModRM|Mov /* movsxd (x86/64) */,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x60 - 0x67 */
+ ImplicitOps, ImplicitOps, DstReg|SrcMem|ModRM, DstReg|SrcMem16|ModRM|Mov,
+ 0, 0, 0, 0,
+ /* 0x68 - 0x6F */
+ ImplicitOps|Mov, DstMem|SrcImm|ModRM|Mov,
+ ImplicitOps|Mov, DstMem|SrcImmByte|ModRM|Mov,
+ 0, 0, 0, 0,
/* 0x70 - 0x77 */
ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
@@ -107,13 +124,14 @@ static uint8_t opcode_table[256] = {
ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
/* 0x98 - 0x9F */
- 0, 0, 0, 0, 0, 0, 0, 0,
+ ImplicitOps, ImplicitOps, 0, 0, 0, 0, ImplicitOps, ImplicitOps,
/* 0xA0 - 0xA7 */
ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
ByteOp|ImplicitOps|Mov, ImplicitOps|Mov, 0, 0,
/* 0xA8 - 0xAF */
- 0, 0, ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
+ ByteOp|DstReg|SrcImm, DstReg|SrcImm,
+ ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,
ByteOp|ImplicitOps|Mov, ImplicitOps|Mov, 0, 0,
/* 0xB0 - 0xB7 */
ByteOp|DstReg|SrcImm|Mov, ByteOp|DstReg|SrcImm|Mov,
@@ -124,20 +142,21 @@ static uint8_t opcode_table[256] = {
DstReg|SrcImm|Mov, DstReg|SrcImm|Mov, DstReg|SrcImm|Mov, DstReg|SrcImm|Mov,
DstReg|SrcImm|Mov, DstReg|SrcImm|Mov, DstReg|SrcImm|Mov, DstReg|SrcImm|Mov,
/* 0xC0 - 0xC7 */
- ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImmByte|ModRM, 0, 0,
+ ByteOp|DstMem|SrcImm|ModRM, DstMem|SrcImmByte|ModRM,
+ ImplicitOps, ImplicitOps,
0, 0, ByteOp|DstMem|SrcImm|ModRM|Mov, DstMem|SrcImm|ModRM|Mov,
/* 0xC8 - 0xCF */
0, 0, 0, 0, 0, 0, 0, 0,
/* 0xD0 - 0xD7 */
ByteOp|DstMem|SrcImplicit|ModRM, DstMem|SrcImplicit|ModRM,
ByteOp|DstMem|SrcImplicit|ModRM, DstMem|SrcImplicit|ModRM,
- 0, 0, 0, 0,
+ ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
/* 0xD8 - 0xDF */
0, 0, 0, 0, 0, 0, 0, 0,
/* 0xE0 - 0xE7 */
- 0, 0, 0, ImplicitOps, 0, 0, 0, 0,
+ ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, 0, 0, 0, 0,
/* 0xE8 - 0xEF */
- 0, ImplicitOps, 0, ImplicitOps, 0, 0, 0, 0,
+ ImplicitOps, ImplicitOps, 0, ImplicitOps, 0, 0, 0, 0,
/* 0xF0 - 0xF7 */
0, 0, 0, 0,
0, ImplicitOps, ByteOp|DstMem|SrcNone|ModRM, DstMem|SrcNone|ModRM,
@@ -149,8 +168,11 @@ static uint8_t opcode_table[256] = {
static uint8_t twobyte_table[256] = {
/* 0x00 - 0x0F */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, 0, 0,
- /* 0x10 - 0x1F */
- 0, 0, 0, 0, 0, 0, 0, 0, ImplicitOps|ModRM, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x10 - 0x17 */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x18 - 0x1F */
+ ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM,
+ ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM, ImplicitOps|ModRM,
/* 0x20 - 0x2F */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x30 - 0x3F */
@@ -177,24 +199,34 @@ static uint8_t twobyte_table[256] = {
/* 0x88 - 0x8F */
ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
- /* 0x90 - 0x9F */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x90 - 0x97 */
+ ByteOp|DstMem|SrcNone|ModRM|Mov, ByteOp|DstMem|SrcNone|ModRM|Mov,
+ ByteOp|DstMem|SrcNone|ModRM|Mov, ByteOp|DstMem|SrcNone|ModRM|Mov,
+ ByteOp|DstMem|SrcNone|ModRM|Mov, ByteOp|DstMem|SrcNone|ModRM|Mov,
+ ByteOp|DstMem|SrcNone|ModRM|Mov, ByteOp|DstMem|SrcNone|ModRM|Mov,
+ /* 0x98 - 0x9F */
+ ByteOp|DstMem|SrcNone|ModRM|Mov, ByteOp|DstMem|SrcNone|ModRM|Mov,
+ ByteOp|DstMem|SrcNone|ModRM|Mov, ByteOp|DstMem|SrcNone|ModRM|Mov,
+ ByteOp|DstMem|SrcNone|ModRM|Mov, ByteOp|DstMem|SrcNone|ModRM|Mov,
+ ByteOp|DstMem|SrcNone|ModRM|Mov, ByteOp|DstMem|SrcNone|ModRM|Mov,
/* 0xA0 - 0xA7 */
0, 0, 0, DstBitBase|SrcReg|ModRM, 0, 0, 0, 0,
/* 0xA8 - 0xAF */
- 0, 0, 0, DstBitBase|SrcReg|ModRM, 0, 0, 0, 0,
+ 0, 0, 0, DstBitBase|SrcReg|ModRM, 0, 0, 0, DstReg|SrcMem|ModRM,
/* 0xB0 - 0xB7 */
ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM,
0, DstBitBase|SrcReg|ModRM,
0, 0, ByteOp|DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem16|ModRM|Mov,
/* 0xB8 - 0xBF */
0, 0, DstBitBase|SrcImmByte|ModRM, DstBitBase|SrcReg|ModRM,
- 0, 0, ByteOp|DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem16|ModRM|Mov,
+ DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM,
+ ByteOp|DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem16|ModRM|Mov,
/* 0xC0 - 0xC7 */
ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, 0, 0,
0, 0, 0, ImplicitOps|ModRM,
/* 0xC8 - 0xCF */
- 0, 0, 0, 0, 0, 0, 0, 0,
+ ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
+ ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,
/* 0xD0 - 0xDF */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xE0 - 0xEF */
@@ -205,7 +237,7 @@ static uint8_t twobyte_table[256] = {
/* Type, address-of, and value of an instruction's operand. */
struct operand {
- enum { OP_REG, OP_MEM, OP_IMM } type;
+ enum { OP_REG, OP_MEM, OP_IMM, OP_NONE } type;
unsigned int bytes;
unsigned long val, orig_val;
union {
@@ -228,6 +260,12 @@ struct operand {
#define EFLG_PF (1<<2)
#define EFLG_CF (1<<0)
+/* Exception definitions. */
+#define EXC_DE 0
+#define EXC_BR 5
+#define EXC_UD 6
+#define EXC_GP 13
+
/*
* Instruction emulation:
* Most instructions are emulated directly via a fragment of inline assembly
@@ -285,7 +323,8 @@ do{ unsigned long _tmp; \
_op"w %"_wx"3,%1; " \
_POST_EFLAGS("0","4","2") \
: "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \
- : _wy ((_src).val), "i" (EFLAGS_MASK) ); \
+ : _wy ((_src).val), "i" (EFLAGS_MASK), \
+ "m" (_eflags), "m" ((_dst).val) ); \
break; \
case 4: \
__asm__ __volatile__ ( \
@@ -293,7 +332,8 @@ do{ unsigned long _tmp; \
_op"l %"_lx"3,%1; " \
_POST_EFLAGS("0","4","2") \
: "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \
- : _ly ((_src).val), "i" (EFLAGS_MASK) ); \
+ : _ly ((_src).val), "i" (EFLAGS_MASK), \
+ "m" (_eflags), "m" ((_dst).val) ); \
break; \
case 8: \
__emulate_2op_8byte(_op, _src, _dst, _eflags, _qx, _qy); \
@@ -310,7 +350,8 @@ do{ unsigned long _tmp; \
_op"b %"_bx"3,%1; " \
_POST_EFLAGS("0","4","2") \
: "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \
- : _by ((_src).val), "i" (EFLAGS_MASK) ); \
+ : _by ((_src).val), "i" (EFLAGS_MASK), \
+ "m" (_eflags), "m" ((_dst).val) ); \
break; \
default: \
__emulate_2op_nobyte(_op,_src,_dst,_eflags,_wx,_wy,_lx,_ly,_qx,_qy);\
@@ -341,7 +382,7 @@ do{ unsigned long _tmp; \
_op"b %1; " \
_POST_EFLAGS("0","3","2") \
: "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \
- : "i" (EFLAGS_MASK) ); \
+ : "i" (EFLAGS_MASK), "m" (_eflags), "m" ((_dst).val) ); \
break; \
case 2: \
__asm__ __volatile__ ( \
@@ -349,7 +390,7 @@ do{ unsigned long _tmp; \
_op"w %1; " \
_POST_EFLAGS("0","3","2") \
: "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \
- : "i" (EFLAGS_MASK) ); \
+ : "i" (EFLAGS_MASK), "m" (_eflags), "m" ((_dst).val) ); \
break; \
case 4: \
__asm__ __volatile__ ( \
@@ -357,7 +398,7 @@ do{ unsigned long _tmp; \
_op"l %1; " \
_POST_EFLAGS("0","3","2") \
: "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \
- : "i" (EFLAGS_MASK) ); \
+ : "i" (EFLAGS_MASK), "m" (_eflags), "m" ((_dst).val) ); \
break; \
case 8: \
__emulate_1op_8byte(_op, _dst, _eflags); \
@@ -373,7 +414,8 @@ do{ __asm__ __volatile__ ( \
_op"q %"_qx"3,%1; " \
_POST_EFLAGS("0","4","2") \
: "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \
- : _qy ((_src).val), "i" (EFLAGS_MASK) ); \
+ : _qy ((_src).val), "i" (EFLAGS_MASK), \
+ "m" (_eflags), "m" ((_dst).val) ); \
} while (0)
#define __emulate_1op_8byte(_op, _dst, _eflags) \
do{ __asm__ __volatile__ ( \
@@ -381,7 +423,7 @@ do{ __asm__ __volatile__ ( \
_op"q %1; " \
_POST_EFLAGS("0","3","2") \
: "=m" (_eflags), "=m" ((_dst).val), "=&r" (_tmp) \
- : "i" (EFLAGS_MASK) ); \
+ : "i" (EFLAGS_MASK), "m" (_eflags), "m" ((_dst).val) ); \
} while (0)
#elif defined(__i386__)
#define __emulate_2op_8byte(_op, _src, _dst, _eflags, _qx, _qy)
@@ -390,39 +432,70 @@ do{ __asm__ __volatile__ ( \
/* Fetch next part of the instruction being emulated. */
#define insn_fetch_bytes(_size) \
-({ unsigned long _x, _eip = _truncate_ea(_regs.eip, def_ad_bytes); \
+({ unsigned long _x, _eip = _regs.eip; \
if ( !mode_64bit() ) _eip = (uint32_t)_eip; /* ignore upper dword */ \
+ _regs.eip += (_size); /* real hardware doesn't truncate */ \
+ generate_exception_if((uint8_t)(_regs.eip - ctxt->regs->eip) > 15, \
+ EXC_GP); \
rc = ops->insn_fetch(x86_seg_cs, _eip, &_x, (_size), ctxt); \
if ( rc ) goto done; \
- _regs.eip += (_size); /* real hardware doesn't truncate */ \
_x; \
})
#define insn_fetch_type(_type) ((_type)insn_fetch_bytes(sizeof(_type)))
-#define _truncate_ea(ea, byte_width) \
-({ unsigned long __ea = (ea); \
- (((byte_width) == sizeof(unsigned long)) ? __ea : \
- (__ea & ((1UL << ((byte_width) << 3)) - 1))); \
+#define _truncate_ea(ea, byte_width) \
+({ unsigned long __ea = (ea); \
+ unsigned int _width = (byte_width); \
+ ((_width == sizeof(unsigned long)) ? __ea : \
+ (__ea & ((1UL << (_width << 3)) - 1))); \
})
#define truncate_ea(ea) _truncate_ea((ea), ad_bytes)
#define mode_64bit() (def_ad_bytes == 8)
+#define fail_if(p) \
+do { \
+ rc = (p) ? X86EMUL_UNHANDLEABLE : 0; \
+ if ( rc ) goto done; \
+} while (0)
+
+/* In future we will be able to generate arbitrary exceptions. */
+#define generate_exception_if(p, e) fail_if(p)
+
+/* Given byte has even parity (even number of 1s)? */
+static int even_parity(uint8_t v)
+{
+ __asm__ ( "test %%al,%%al; setp %%al"
+ : "=a" (v) : "0" (v) );
+ return v;
+}
+
/* Update address held in a register, based on addressing mode. */
#define _register_address_increment(reg, inc, byte_width) \
do { \
int _inc = (inc); /* signed type ensures sign extension to long */ \
- if ( (byte_width) == sizeof(unsigned long) ) \
+ unsigned int _width = (byte_width); \
+ if ( _width == sizeof(unsigned long) ) \
(reg) += _inc; \
else if ( mode_64bit() ) \
- (reg) = ((reg) + _inc) & ((1UL << ((byte_width) << 3)) - 1); \
+ (reg) = ((reg) + _inc) & ((1UL << (_width << 3)) - 1); \
else \
- (reg) = ((reg) & ~((1UL << ((byte_width) << 3)) - 1)) | \
- (((reg) + _inc) & ((1UL << ((byte_width) << 3)) - 1)); \
+ (reg) = ((reg) & ~((1UL << (_width << 3)) - 1)) | \
+ (((reg) + _inc) & ((1UL << (_width << 3)) - 1)); \
} while (0)
#define register_address_increment(reg, inc) \
_register_address_increment((reg), (inc), ad_bytes)
+#define sp_pre_dec(dec) ({ \
+ _register_address_increment(_regs.esp, -(dec), ctxt->sp_size/8); \
+ _truncate_ea(_regs.esp, ctxt->sp_size/8); \
+})
+#define sp_post_inc(inc) ({ \
+ unsigned long __esp = _truncate_ea(_regs.esp, ctxt->sp_size/8); \
+ _register_address_increment(_regs.esp, (inc), ctxt->sp_size/8); \
+ __esp; \
+})
+
#define jmp_rel(rel) \
do { \
_regs.eip += (int)(rel); \
@@ -431,6 +504,92 @@ do { \
? (uint16_t)_regs.eip : (uint32_t)_regs.eip); \
} while (0)
+/*
+ * Unsigned multiplication with double-word result.
+ * IN: Multiplicand=m[0], Multiplier=m[1]
+ * OUT: Return CF/OF (overflow status); Result=m[1]:m[0]
+ */
+static int mul_dbl(unsigned long m[2])
+{
+ int rc;
+ asm ( "mul %4; seto %b2"
+ : "=a" (m[0]), "=d" (m[1]), "=q" (rc)
+ : "0" (m[0]), "1" (m[1]), "2" (0) );
+ return rc;
+}
+
+/*
+ * Signed multiplication with double-word result.
+ * IN: Multiplicand=m[0], Multiplier=m[1]
+ * OUT: Return CF/OF (overflow status); Result=m[1]:m[0]
+ */
+static int imul_dbl(unsigned long m[2])
+{
+ int rc;
+ asm ( "imul %4; seto %b2"
+ : "=a" (m[0]), "=d" (m[1]), "=q" (rc)
+ : "0" (m[0]), "1" (m[1]), "2" (0) );
+ return rc;
+}
+
+/*
+ * Unsigned division of double-word dividend.
+ * IN: Dividend=u[1]:u[0], Divisor=v
+ * OUT: Return 1: #DE
+ * Return 0: Quotient=u[0], Remainder=u[1]
+ */
+static int div_dbl(unsigned long u[2], unsigned long v)
+{
+ if ( (v == 0) || (u[1] > v) || ((u[1] == v) && (u[0] != 0)) )
+ return 1;
+ asm ( "div %4"
+ : "=a" (u[0]), "=d" (u[1])
+ : "0" (u[0]), "1" (u[1]), "r" (v) );
+ return 0;
+}
+
+/*
+ * Signed division of double-word dividend.
+ * IN: Dividend=u[1]:u[0], Divisor=v
+ * OUT: Return 1: #DE
+ * Return 0: Quotient=u[0], Remainder=u[1]
+ * NB. We don't use idiv directly as it's moderately hard to work out
+ * ahead of time whether it will #DE, which we cannot allow to happen.
+ */
+static int idiv_dbl(unsigned long u[2], unsigned long v)
+{
+ int negu = (long)u[1] < 0, negv = (long)v < 0;
+
+ /* u = abs(u) */
+ if ( negu )
+ {
+ u[1] = ~u[1];
+ if ( (u[0] = -u[0]) == 0 )
+ u[1]++;
+ }
+
+ /* abs(u) / abs(v) */
+ if ( div_dbl(u, negv ? -v : v) )
+ return 1;
+
+ /* Remainder has same sign as dividend. It cannot overflow. */
+ if ( negu )
+ u[1] = -u[1];
+
+ /* Quotient is overflowed if sign bit is set. */
+ if ( negu ^ negv )
+ {
+ if ( (long)u[0] >= 0 )
+ u[0] = -u[0];
+ else if ( (u[0] << 1) != 0 ) /* == 0x80...0 is okay */
+ return 1;
+ }
+ else if ( (long)u[0] < 0 )
+ return 1;
+
+ return 0;
+}
+
static int
test_cc(
unsigned int condition, unsigned int flags)
@@ -519,8 +678,8 @@ x86_emulate(
uint8_t b, d, sib, sib_index, sib_base, twobyte = 0, rex_prefix = 0;
uint8_t modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0;
- unsigned int op_bytes, ad_bytes, def_ad_bytes;
- unsigned int lock_prefix = 0, rep_prefix = 0, i;
+ unsigned int op_bytes, def_op_bytes, ad_bytes, def_ad_bytes;
+ unsigned int lock_prefix = 0, rep_prefix = 0;
int rc = 0;
struct operand src, dst;
@@ -532,28 +691,25 @@ x86_emulate(
ea.mem.seg = x86_seg_ds;
ea.mem.off = 0;
- op_bytes = ad_bytes = def_ad_bytes = ctxt->address_bytes;
+ op_bytes = def_op_bytes = ad_bytes = def_ad_bytes = ctxt->addr_size/8;
if ( op_bytes == 8 )
{
- op_bytes = 4;
+ op_bytes = def_op_bytes = 4;
#ifndef __x86_64__
return -1;
#endif
}
/* Prefix bytes. */
- for ( i = 0; i < 8; i++ )
+ for ( ; ; )
{
switch ( b = insn_fetch_type(uint8_t) )
{
case 0x66: /* operand-size override */
- op_bytes ^= 6; /* switch between 2/4 bytes */
+ op_bytes = def_op_bytes ^ 6;
break;
case 0x67: /* address-size override */
- if ( mode_64bit() )
- ad_bytes ^= 12; /* switch between 4/8 bytes */
- else
- ad_bytes ^= 6; /* switch between 2/4 bytes */
+ ad_bytes = def_ad_bytes ^ (mode_64bit() ? 12 : 6);
break;
case 0x2e: /* CS override */
ea.mem.seg = x86_seg_cs;
@@ -614,6 +770,9 @@ x86_emulate(
goto cannot_emulate;
}
+ /* Lock prefix is allowed only on RMW instructions. */
+ generate_exception_if((d & Mov) && lock_prefix, EXC_GP);
+
/* ModRM and SIB bytes. */
if ( d & ModRM )
{
@@ -746,9 +905,6 @@ x86_emulate(
case SrcMem16:
ea.bytes = 2;
goto srcmem_common;
- case SrcMem32:
- ea.bytes = 4;
- goto srcmem_common;
case SrcMem:
ea.bytes = (d & ByteOp) ? 1 : op_bytes;
srcmem_common:
@@ -817,7 +973,7 @@ x86_emulate(
{
/*
* EA += BitOffset DIV op_bytes*8
- * BitOffset = BitOffset MOD op_byte*8
+ * BitOffset = BitOffset MOD op_bytes*8
* DIV truncates towards negative infinity.
* MOD always produces a positive result.
*/
@@ -853,13 +1009,18 @@ x86_emulate(
case 8: dst.val = *(uint64_t *)dst.reg; break;
}
}
- else if ( !(d & Mov) && /* optimisation - avoid slow emulated read */
- (rc = ops->read(dst.mem.seg, dst.mem.off,
- &dst.val, dst.bytes, ctxt)) )
- goto done;
+ else if ( !(d & Mov) ) /* optimisation - avoid slow emulated read */
+ {
+ if ( (rc = ops->read(dst.mem.seg, dst.mem.off,
+ &dst.val, dst.bytes, ctxt)) )
+ goto done;
+ dst.orig_val = dst.val;
+ }
break;
}
- dst.orig_val = dst.val;
+
+ /* LOCK prefix allowed only on instructions with memory destination. */
+ generate_exception_if(lock_prefix && (dst.type != OP_MEM), EXC_GP);
if ( twobyte )
goto twobyte_insn;
@@ -868,67 +1029,136 @@ x86_emulate(
{
case 0x04 ... 0x05: /* add imm,%%eax */
dst.reg = (unsigned long *)&_regs.eax;
- dst.val = dst.orig_val = _regs.eax;
+ dst.val = _regs.eax;
case 0x00 ... 0x03: add: /* add */
emulate_2op_SrcV("add", src, dst, _regs.eflags);
break;
case 0x0c ... 0x0d: /* or imm,%%eax */
dst.reg = (unsigned long *)&_regs.eax;
- dst.val = dst.orig_val = _regs.eax;
+ dst.val = _regs.eax;
case 0x08 ... 0x0b: or: /* or */
emulate_2op_SrcV("or", src, dst, _regs.eflags);
break;
case 0x14 ... 0x15: /* adc imm,%%eax */
dst.reg = (unsigned long *)&_regs.eax;
- dst.val = dst.orig_val = _regs.eax;
+ dst.val = _regs.eax;
case 0x10 ... 0x13: adc: /* adc */
emulate_2op_SrcV("adc", src, dst, _regs.eflags);
break;
case 0x1c ... 0x1d: /* sbb imm,%%eax */
dst.reg = (unsigned long *)&_regs.eax;
- dst.val = dst.orig_val = _regs.eax;
+ dst.val = _regs.eax;
case 0x18 ... 0x1b: sbb: /* sbb */
emulate_2op_SrcV("sbb", src, dst, _regs.eflags);
break;
case 0x24 ... 0x25: /* and imm,%%eax */
dst.reg = (unsigned long *)&_regs.eax;
- dst.val = dst.orig_val = _regs.eax;
+ dst.val = _regs.eax;
case 0x20 ... 0x23: and: /* and */
emulate_2op_SrcV("and", src, dst, _regs.eflags);
break;
case 0x2c ... 0x2d: /* sub imm,%%eax */
dst.reg = (unsigned long *)&_regs.eax;
- dst.val = dst.orig_val = _regs.eax;
+ dst.val = _regs.eax;
case 0x28 ... 0x2b: sub: /* sub */
emulate_2op_SrcV("sub", src, dst, _regs.eflags);
break;
case 0x34 ... 0x35: /* xor imm,%%eax */
dst.reg = (unsigned long *)&_regs.eax;
- dst.val = dst.orig_val = _regs.eax;
+ dst.val = _regs.eax;
case 0x30 ... 0x33: xor: /* xor */
emulate_2op_SrcV("xor", src, dst, _regs.eflags);
break;
case 0x3c ... 0x3d: /* cmp imm,%%eax */
dst.reg = (unsigned long *)&_regs.eax;
- dst.val = dst.orig_val = _regs.eax;
+ dst.val = _regs.eax;
case 0x38 ... 0x3b: cmp: /* cmp */
emulate_2op_SrcV("cmp", src, dst, _regs.eflags);
break;
- case 0x63: /* movsxd */
- if ( !mode_64bit() )
- goto cannot_emulate;
- dst.val = (int32_t)src.val;
+ case 0x62: /* bound */ {
+ unsigned long src_val2;
+ int lb, ub, idx;
+ generate_exception_if(mode_64bit() || (src.type != OP_MEM), EXC_UD);
+ if ( (rc = ops->read(src.mem.seg, src.mem.off + op_bytes,
+ &src_val2, op_bytes, ctxt)) )
+ goto done;
+ ub = (op_bytes == 2) ? (int16_t)src_val2 : (int32_t)src_val2;
+ lb = (op_bytes == 2) ? (int16_t)src.val : (int32_t)src.val;
+ idx = (op_bytes == 2) ? (int16_t)dst.val : (int32_t)dst.val;
+ generate_exception_if((idx < lb) || (idx > ub), EXC_BR);
+ dst.type = OP_NONE;
break;
+ }
- case 0x80 ... 0x83: /* Grp1 */
+ case 0x63: /* movsxd (x86/64) / arpl (x86/32) */
+ if ( mode_64bit() )
+ {
+ /* movsxd */
+ if ( src.type == OP_REG )
+ src.val = *(int32_t *)src.reg;
+ else if ( (rc = ops->read(src.mem.seg, src.mem.off,
+ &src.val, 4, ctxt)) )
+ goto done;
+ dst.val = (int32_t)src.val;
+ }
+ else
+ {
+ /* arpl */
+ uint16_t src_val = dst.val;
+ dst = src;
+ _regs.eflags &= ~EFLG_ZF;
+ _regs.eflags |= ((src_val & 3) > (dst.val & 3)) ? EFLG_ZF : 0;
+ if ( _regs.eflags & EFLG_ZF )
+ dst.val = (dst.val & ~3) | (src_val & 3);
+ else
+ dst.type = OP_NONE;
+ }
+ break;
+
+ case 0x69: /* imul imm16/32 */
+ case 0x6b: /* imul imm8 */ {
+ unsigned long reg = *(long *)decode_register(modrm_reg, &_regs, 0);
+ _regs.eflags &= ~(EFLG_OF|EFLG_CF);
+ switch ( dst.bytes )
+ {
+ case 2:
+ dst.val = ((uint32_t)(int16_t)src.val *
+ (uint32_t)(int16_t)reg);
+ if ( (int16_t)dst.val != (uint32_t)dst.val )
+ _regs.eflags |= EFLG_OF|EFLG_CF;
+ break;
+#ifdef __x86_64__
+ case 4:
+ dst.val = ((uint64_t)(int32_t)src.val *
+ (uint64_t)(int32_t)reg);
+ if ( (int32_t)dst.val != dst.val )
+ _regs.eflags |= EFLG_OF|EFLG_CF;
+ break;
+#endif
+ default: {
+ unsigned long m[2] = { src.val, reg };
+ if ( imul_dbl(m) )
+ _regs.eflags |= EFLG_OF|EFLG_CF;
+ dst.val = m[0];
+ break;
+ }
+ }
+ dst.type = OP_REG;
+ dst.reg = decode_register(modrm_reg, &_regs, 0);
+ break;
+ }
+
+ case 0x82: /* Grp1 (x86/32 only) */
+ generate_exception_if(mode_64bit(), EXC_UD);
+ case 0x80: case 0x81: case 0x83: /* Grp1 */
switch ( modrm_reg & 7 )
{
case 0: goto add;
@@ -942,6 +1172,9 @@ x86_emulate(
}
break;
+ case 0xa8 ... 0xa9: /* test imm,%%eax */
+ dst.reg = (unsigned long *)&_regs.eax;
+ dst.val = _regs.eax;
case 0x84 ... 0x85: test: /* test */
emulate_2op_SrcV("test", src, dst, _regs.eflags);
break;
@@ -960,8 +1193,9 @@ x86_emulate(
lock_prefix = 1;
break;
- case 0x88 ... 0x8b: /* mov */
case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */
+ generate_exception_if((modrm_reg & 7) != 0, EXC_UD);
+ case 0x88 ... 0x8b: /* mov */
dst.val = src.val;
break;
@@ -970,13 +1204,13 @@ x86_emulate(
break;
case 0x8f: /* pop (sole member of Grp1a) */
+ generate_exception_if((modrm_reg & 7) != 0, EXC_UD);
/* 64-bit mode: POP defaults to a 64-bit operand. */
if ( mode_64bit() && (dst.bytes == 4) )
dst.bytes = 8;
- if ( (rc = ops->read(x86_seg_ss, truncate_ea(_regs.esp),
+ if ( (rc = ops->read(x86_seg_ss, sp_post_inc(dst.bytes),
&dst.val, dst.bytes, ctxt)) != 0 )
goto done;
- register_address_increment(_regs.esp, dst.bytes);
break;
case 0xb0 ... 0xb7: /* mov imm8,r8 */
@@ -1051,12 +1285,191 @@ x86_emulate(
case 3: /* neg */
emulate_1op("neg", dst, _regs.eflags);
break;
+ case 4: /* mul */
+ src = dst;
+ dst.type = OP_REG;
+ dst.reg = (unsigned long *)&_regs.eax;
+ dst.val = *dst.reg;
+ _regs.eflags &= ~(EFLG_OF|EFLG_CF);
+ switch ( src.bytes )
+ {
+ case 1:
+ dst.val *= src.val;
+ if ( (uint8_t)dst.val != (uint16_t)dst.val )
+ _regs.eflags |= EFLG_OF|EFLG_CF;
+ break;
+ case 2:
+ dst.val *= src.val;
+ if ( (uint16_t)dst.val != (uint32_t)dst.val )
+ _regs.eflags |= EFLG_OF|EFLG_CF;
+ *(uint16_t *)&_regs.edx = dst.val >> 16;
+ break;
+#ifdef __x86_64__
+ case 4:
+ dst.val *= src.val;
+ if ( (uint32_t)dst.val != dst.val )
+ _regs.eflags |= EFLG_OF|EFLG_CF;
+ _regs.edx = (uint32_t)(dst.val >> 32);
+ break;
+#endif
+ default: {
+ unsigned long m[2] = { src.val, dst.val };
+ if ( mul_dbl(m) )
+ _regs.eflags |= EFLG_OF|EFLG_CF;
+ _regs.edx = m[1];
+ dst.val = m[0];
+ break;
+ }
+ }
+ break;
+ case 5: /* imul */
+ src = dst;
+ dst.type = OP_REG;
+ dst.reg = (unsigned long *)&_regs.eax;
+ dst.val = *dst.reg;
+ _regs.eflags &= ~(EFLG_OF|EFLG_CF);
+ switch ( src.bytes )
+ {
+ case 1:
+ dst.val = ((uint16_t)(int8_t)src.val *
+ (uint16_t)(int8_t)dst.val);
+ if ( (int8_t)dst.val != (uint16_t)dst.val )
+ _regs.eflags |= EFLG_OF|EFLG_CF;
+ break;
+ case 2:
+ dst.val = ((uint32_t)(int16_t)src.val *
+ (uint32_t)(int16_t)dst.val);
+ if ( (int16_t)dst.val != (uint32_t)dst.val )
+ _regs.eflags |= EFLG_OF|EFLG_CF;
+ *(uint16_t *)&_regs.edx = dst.val >> 16;
+ break;
+#ifdef __x86_64__
+ case 4:
+ dst.val = ((uint64_t)(int32_t)src.val *
+ (uint64_t)(int32_t)dst.val);
+ if ( (int32_t)dst.val != dst.val )
+ _regs.eflags |= EFLG_OF|EFLG_CF;
+ _regs.edx = (uint32_t)(dst.val >> 32);
+ break;
+#endif
+ default: {
+ unsigned long m[2] = { src.val, dst.val };
+ if ( imul_dbl(m) )
+ _regs.eflags |= EFLG_OF|EFLG_CF;
+ _regs.edx = m[1];
+ dst.val = m[0];
+ break;
+ }
+ }
+ break;
+ case 6: /* div */ {
+ unsigned long u[2], v;
+ src = dst;
+ dst.type = OP_REG;
+ dst.reg = (unsigned long *)&_regs.eax;
+ switch ( src.bytes )
+ {
+ case 1:
+ u[0] = (uint16_t)_regs.eax;
+ u[1] = 0;
+ v = (uint8_t)src.val;
+ generate_exception_if(
+ div_dbl(u, v) || ((uint8_t)u[0] != (uint16_t)u[0]),
+ EXC_DE);
+ dst.val = (uint8_t)u[0];
+ ((uint8_t *)&_regs.eax)[1] = u[1];
+ break;
+ case 2:
+ u[0] = ((uint32_t)_regs.edx << 16) | (uint16_t)_regs.eax;
+ u[1] = 0;
+ v = (uint16_t)src.val;
+ generate_exception_if(
+ div_dbl(u, v) || ((uint16_t)u[0] != (uint32_t)u[0]),
+ EXC_DE);
+ dst.val = (uint16_t)u[0];
+ *(uint16_t *)&_regs.edx = u[1];
+ break;
+#ifdef __x86_64__
+ case 4:
+ u[0] = (_regs.edx << 32) | (uint32_t)_regs.eax;
+ u[1] = 0;
+ v = (uint32_t)src.val;
+ generate_exception_if(
+ div_dbl(u, v) || ((uint32_t)u[0] != u[0]),
+ EXC_DE);
+ dst.val = (uint32_t)u[0];
+ _regs.edx = (uint32_t)u[1];
+ break;
+#endif
+ default:
+ u[0] = _regs.eax;
+ u[1] = _regs.edx;
+ v = src.val;
+ generate_exception_if(div_dbl(u, v), EXC_DE);
+ dst.val = u[0];
+ _regs.edx = u[1];
+ break;
+ }
+ break;
+ }
+ case 7: /* idiv */ {
+ unsigned long u[2], v;
+ src = dst;
+ dst.type = OP_REG;
+ dst.reg = (unsigned long *)&_regs.eax;
+ switch ( src.bytes )
+ {
+ case 1:
+ u[0] = (int16_t)_regs.eax;
+ u[1] = ((long)u[0] < 0) ? ~0UL : 0UL;
+ v = (int8_t)src.val;
+ generate_exception_if(
+ idiv_dbl(u, v) || ((int8_t)u[0] != (int16_t)u[0]),
+ EXC_DE);
+ dst.val = (int8_t)u[0];
+ ((int8_t *)&_regs.eax)[1] = u[1];
+ break;
+ case 2:
+ u[0] = (int32_t)((_regs.edx << 16) | (uint16_t)_regs.eax);
+ u[1] = ((long)u[0] < 0) ? ~0UL : 0UL;
+ v = (int16_t)src.val;
+ generate_exception_if(
+ idiv_dbl(u, v) || ((int16_t)u[0] != (int32_t)u[0]),
+ EXC_DE);
+ dst.val = (int16_t)u[0];
+ *(int16_t *)&_regs.edx = u[1];
+ break;
+#ifdef __x86_64__
+ case 4:
+ u[0] = (_regs.edx << 32) | (uint32_t)_regs.eax;
+ u[1] = ((long)u[0] < 0) ? ~0UL : 0UL;
+ v = (int32_t)src.val;
+ generate_exception_if(
+ idiv_dbl(u, v) || ((int32_t)u[0] != u[0]),
+ EXC_DE);
+ dst.val = (int32_t)u[0];
+ _regs.edx = (uint32_t)u[1];
+ break;
+#endif
+ default:
+ u[0] = _regs.eax;
+ u[1] = _regs.edx;
+ v = src.val;
+ generate_exception_if(idiv_dbl(u, v), EXC_DE);
+ dst.val = u[0];
+ _regs.edx = u[1];
+ break;
+ }
+ break;
+ }
default:
goto cannot_emulate;
}
break;
- case 0xfe ... 0xff: /* Grp4/Grp5 */
+ case 0xfe: /* Grp4 */
+ generate_exception_if((modrm_reg & 7) >= 2, EXC_UD);
+ case 0xff: /* Grp5 */
switch ( modrm_reg & 7 )
{
case 0: /* inc */
@@ -1065,6 +1478,20 @@ x86_emulate(
case 1: /* dec */
emulate_1op("dec", dst, _regs.eflags);
break;
+ case 2: /* call (near) */
+ case 4: /* jmp (near) */
+ if ( ((op_bytes = dst.bytes) != 8) && mode_64bit() )
+ {
+ dst.bytes = op_bytes = 8;
+ if ( (rc = ops->read(dst.mem.seg, dst.mem.off,
+ &dst.val, 8, ctxt)) != 0 )
+ goto done;
+ }
+ src.val = _regs.eip;
+ _regs.eip = dst.val;
+ if ( (modrm_reg & 7) == 2 )
+ goto push; /* call */
+ break;
case 6: /* push */
/* 64-bit mode: PUSH defaults to a 64-bit operand. */
if ( mode_64bit() && (dst.bytes == 4) )
@@ -1074,12 +1501,13 @@ x86_emulate(
&dst.val, 8, ctxt)) != 0 )
goto done;
}
- register_address_increment(_regs.esp, -dst.bytes);
- if ( (rc = ops->write(x86_seg_ss, truncate_ea(_regs.esp),
+ if ( (rc = ops->write(x86_seg_ss, sp_pre_dec(dst.bytes),
dst.val, dst.bytes, ctxt)) != 0 )
goto done;
- dst.val = dst.orig_val; /* skanky: disable writeback */
+ dst.type = OP_NONE;
break;
+ case 7:
+ generate_exception_if(1, EXC_UD);
default:
goto cannot_emulate;
}
@@ -1087,33 +1515,32 @@ x86_emulate(
}
writeback:
- if ( (d & Mov) || (dst.orig_val != dst.val) )
+ switch ( dst.type )
{
- switch ( dst.type )
+ case OP_REG:
+ /* The 4-byte case *is* correct: in 64-bit mode we zero-extend. */
+ switch ( dst.bytes )
{
- case OP_REG:
- /* The 4-byte case *is* correct: in 64-bit mode we zero-extend. */
- switch ( dst.bytes )
- {
- case 1: *(uint8_t *)dst.reg = (uint8_t)dst.val; break;
- case 2: *(uint16_t *)dst.reg = (uint16_t)dst.val; break;
- case 4: *dst.reg = (uint32_t)dst.val; break; /* 64b: zero-ext */
- case 8: *dst.reg = dst.val; break;
- }
- break;
- case OP_MEM:
- if ( lock_prefix )
- rc = ops->cmpxchg(
- dst.mem.seg, dst.mem.off, dst.orig_val,
- dst.val, dst.bytes, ctxt);
- else
- rc = ops->write(
- dst.mem.seg, dst.mem.off, dst.val, dst.bytes, ctxt);
- if ( rc != 0 )
- goto done;
- default:
- break;
+ case 1: *(uint8_t *)dst.reg = (uint8_t)dst.val; break;
+ case 2: *(uint16_t *)dst.reg = (uint16_t)dst.val; break;
+ case 4: *dst.reg = (uint32_t)dst.val; break; /* 64b: zero-ext */
+ case 8: *dst.reg = dst.val; break;
}
+ break;
+ case OP_MEM:
+ if ( !(d & Mov) && (dst.orig_val == dst.val) )
+ /* nothing to do */;
+ else if ( lock_prefix )
+ rc = ops->cmpxchg(
+ dst.mem.seg, dst.mem.off, dst.orig_val,
+ dst.val, dst.bytes, ctxt);
+ else
+ rc = ops->write(
+ dst.mem.seg, dst.mem.off, dst.val, dst.bytes, ctxt);
+ if ( rc != 0 )
+ goto done;
+ default:
+ break;
}
/* Commit shadow register state. */
@@ -1123,8 +1550,13 @@ x86_emulate(
return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0;
special_insn:
- /* Default action: disable writeback. There may be no dest operand. */
- dst.orig_val = dst.val;
+ dst.type = OP_NONE;
+
+ /*
+ * The only implicit-operands instruction allowed a LOCK prefix is
+ * CMPXCHG{8,16}B.
+ */
+ generate_exception_if(lock_prefix && (b != 0xc7), EXC_GP);
if ( twobyte )
goto twobyte_special_insn;
@@ -1142,11 +1574,70 @@ x86_emulate(
switch ( b )
{
+ case 0x27: /* daa */ {
+ uint8_t al = _regs.eax;
+ unsigned long eflags = _regs.eflags;
+ generate_exception_if(mode_64bit(), EXC_UD);
+ _regs.eflags &= ~(EFLG_CF|EFLG_AF);
+ if ( ((al & 0x0f) > 9) || (eflags & EFLG_AF) )
+ {
+ *(uint8_t *)&_regs.eax += 6;
+ _regs.eflags |= EFLG_AF;
+ }
+ if ( (al > 0x99) || (eflags & EFLG_CF) )
+ {
+ *(uint8_t *)&_regs.eax += 0x60;
+ _regs.eflags |= EFLG_CF;
+ }
+ _regs.eflags &= ~(EFLG_SF|EFLG_ZF|EFLG_PF);
+ _regs.eflags |= ((uint8_t)_regs.eax == 0) ? EFLG_ZF : 0;
+ _regs.eflags |= (( int8_t)_regs.eax < 0) ? EFLG_SF : 0;
+ _regs.eflags |= even_parity(_regs.eax) ? EFLG_PF : 0;
+ break;
+ }
+
+ case 0x2f: /* das */ {
+ uint8_t al = _regs.eax;
+ unsigned long eflags = _regs.eflags;
+ generate_exception_if(mode_64bit(), EXC_UD);
+ _regs.eflags &= ~(EFLG_CF|EFLG_AF);
+ if ( ((al & 0x0f) > 9) || (eflags & EFLG_AF) )
+ {
+ _regs.eflags |= EFLG_AF;
+ if ( (al < 6) || (eflags & EFLG_CF) )
+ _regs.eflags |= EFLG_CF;
+ *(uint8_t *)&_regs.eax -= 6;
+ }
+ if ( (al > 0x99) || (eflags & EFLG_CF) )
+ {
+ *(uint8_t *)&_regs.eax -= 0x60;
+ _regs.eflags |= EFLG_CF;
+ }
+ _regs.eflags &= ~(EFLG_SF|EFLG_ZF|EFLG_PF);
+ _regs.eflags |= ((uint8_t)_regs.eax == 0) ? EFLG_ZF : 0;
+ _regs.eflags |= (( int8_t)_regs.eax < 0) ? EFLG_SF : 0;
+ _regs.eflags |= even_parity(_regs.eax) ? EFLG_PF : 0;
+ break;
+ }
+
+ case 0x37: /* aaa */
+ case 0x3f: /* aas */
+ generate_exception_if(mode_64bit(), EXC_UD);
+ _regs.eflags &= ~EFLG_CF;
+ if ( ((uint8_t)_regs.eax > 9) || (_regs.eflags & EFLG_AF) )
+ {
+ ((uint8_t *)&_regs.eax)[0] += (b == 0x37) ? 6 : -6;
+ ((uint8_t *)&_regs.eax)[1] += (b == 0x37) ? 1 : -1;
+ _regs.eflags |= EFLG_CF | EFLG_AF;
+ }
+ ((uint8_t *)&_regs.eax)[0] &= 0x0f;
+ break;
+
case 0x40 ... 0x4f: /* inc/dec reg */
dst.type = OP_REG;
dst.reg = decode_register(b & 7, &_regs, 0);
dst.bytes = op_bytes;
- dst.orig_val = dst.val = *dst.reg;
+ dst.val = *dst.reg;
if ( b & 8 )
emulate_1op("dec", dst, _regs.eflags);
else
@@ -1154,16 +1645,9 @@ x86_emulate(
break;
case 0x50 ... 0x57: /* push reg */
- dst.type = OP_MEM;
- dst.bytes = op_bytes;
- if ( mode_64bit() && (dst.bytes == 4) )
- dst.bytes = 8;
- dst.val = *(unsigned long *)decode_register(
+ src.val = *(unsigned long *)decode_register(
(b & 7) | ((rex_prefix & 1) << 3), &_regs, 0);
- register_address_increment(_regs.esp, -dst.bytes);
- dst.mem.seg = x86_seg_ss;
- dst.mem.off = truncate_ea(_regs.esp);
- break;
+ goto push;
case 0x58 ... 0x5f: /* pop reg */
dst.type = OP_REG;
@@ -1172,10 +1656,56 @@ x86_emulate(
dst.bytes = op_bytes;
if ( mode_64bit() && (dst.bytes == 4) )
dst.bytes = 8;
- if ( (rc = ops->read(x86_seg_ss, truncate_ea(_regs.esp),
+ if ( (rc = ops->read(x86_seg_ss, sp_post_inc(dst.bytes),
&dst.val, dst.bytes, ctxt)) != 0 )
goto done;
- register_address_increment(_regs.esp, dst.bytes);
+ break;
+
+ case 0x60: /* pusha */ {
+ int i;
+ unsigned long regs[] = {
+ _regs.eax, _regs.ecx, _regs.edx, _regs.ebx,
+ _regs.esp, _regs.ebp, _regs.esi, _regs.edi };
+ generate_exception_if(mode_64bit(), EXC_UD);
+ for ( i = 0; i < 8; i++ )
+ if ( (rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes),
+ regs[i], op_bytes, ctxt)) != 0 )
+ goto done;
+ break;
+ }
+
+ case 0x61: /* popa */ {
+ int i;
+ unsigned long dummy_esp, *regs[] = {
+ (unsigned long *)&_regs.edi, (unsigned long *)&_regs.esi,
+ (unsigned long *)&_regs.ebp, (unsigned long *)&dummy_esp,
+ (unsigned long *)&_regs.ebx, (unsigned long *)&_regs.edx,
+ (unsigned long *)&_regs.ecx, (unsigned long *)&_regs.eax };
+ generate_exception_if(mode_64bit(), EXC_UD);
+ for ( i = 0; i < 8; i++ )
+ if ( (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes),
+ regs[i], op_bytes, ctxt)) != 0 )
+ goto done;
+ break;
+ }
+
+ case 0x68: /* push imm{16,32,64} */
+ src.val = ((op_bytes == 2)
+ ? (int32_t)insn_fetch_type(int16_t)
+ : insn_fetch_type(int32_t));
+ goto push;
+
+ case 0x6a: /* push imm8 */
+ src.val = insn_fetch_type(int8_t);
+ push:
+ d |= Mov; /* force writeback */
+ dst.type = OP_MEM;
+ dst.bytes = op_bytes;
+ if ( mode_64bit() && (dst.bytes == 4) )
+ dst.bytes = 8;
+ dst.val = src.val;
+ dst.mem.seg = x86_seg_ss;
+ dst.mem.off = sp_pre_dec(dst.bytes);
break;
case 0x70 ... 0x7f: /* jcc (short) */ {
@@ -1196,9 +1726,41 @@ x86_emulate(
src.val = *src.reg;
dst.reg = decode_register(
(b & 7) | ((rex_prefix & 1) << 3), &_regs, 0);
- dst.val = dst.orig_val = *dst.reg;
+ dst.val = *dst.reg;
goto xchg;
+ case 0x98: /* cbw/cwde/cdqe */
+ switch ( op_bytes )
+ {
+ case 2: *(int16_t *)&_regs.eax = (int8_t)_regs.eax; break; /* cbw */
+ case 4: _regs.eax = (uint32_t)(int16_t)_regs.eax; break; /* cwde */
+ case 8: _regs.eax = (int32_t)_regs.eax; break; /* cdqe */
+ }
+ break;
+
+ case 0x99: /* cwd/cdq/cqo */
+ switch ( op_bytes )
+ {
+ case 2:
+ *(int16_t *)&_regs.edx = ((int16_t)_regs.eax < 0) ? -1 : 0;
+ break;
+ case 4:
+ _regs.edx = (uint32_t)(((int32_t)_regs.eax < 0) ? -1 : 0);
+ break;
+ case 8:
+ _regs.edx = (_regs.eax < 0) ? -1 : 0;
+ break;
+ }
+ break;
+
+ case 0x9e: /* sahf */
+ *(uint8_t *)_regs.eflags = (((uint8_t *)&_regs.eax)[1] & 0xd7) | 0x02;
+ break;
+
+ case 0x9f: /* lahf */
+ ((uint8_t *)&_regs.eax)[1] = (_regs.eflags & 0xd7) | 0x02;
+ break;
+
case 0xa0 ... 0xa1: /* mov mem.offs,{%al,%ax,%eax,%rax} */
/* Source EA is not encoded via ModRM. */
dst.type = OP_REG;
@@ -1253,6 +1815,81 @@ x86_emulate(
_regs.esi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes);
break;
+ case 0xc2: /* ret imm16 (near) */
+ case 0xc3: /* ret (near) */ {
+ int offset = (b == 0xc2) ? insn_fetch_type(uint16_t) : 0;
+ op_bytes = mode_64bit() ? 8 : op_bytes;
+ if ( (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes + offset),
+ &dst.val, op_bytes, ctxt)) != 0 )
+ goto done;
+ _regs.eip = dst.val;
+ break;
+ }
+
+ case 0xd4: /* aam */ {
+ unsigned int base = insn_fetch_type(uint8_t);
+ uint8_t al = _regs.eax;
+ generate_exception_if(mode_64bit(), EXC_UD);
+ generate_exception_if(base == 0, EXC_DE);
+ *(uint16_t *)&_regs.eax = ((al / base) << 8) | (al % base);
+ _regs.eflags &= ~(EFLG_SF|EFLG_ZF|EFLG_PF);
+ _regs.eflags |= ((uint8_t)_regs.eax == 0) ? EFLG_ZF : 0;
+ _regs.eflags |= (( int8_t)_regs.eax < 0) ? EFLG_SF : 0;
+ _regs.eflags |= even_parity(_regs.eax) ? EFLG_PF : 0;
+ break;
+ }
+
+ case 0xd5: /* aad */ {
+ unsigned int base = insn_fetch_type(uint8_t);
+ uint16_t ax = _regs.eax;
+ generate_exception_if(mode_64bit(), EXC_UD);
+ *(uint16_t *)&_regs.eax = (uint8_t)(ax + ((ax >> 8) * base));
+ _regs.eflags &= ~(EFLG_SF|EFLG_ZF|EFLG_PF);
+ _regs.eflags |= ((uint8_t)_regs.eax == 0) ? EFLG_ZF : 0;
+ _regs.eflags |= (( int8_t)_regs.eax < 0) ? EFLG_SF : 0;
+ _regs.eflags |= even_parity(_regs.eax) ? EFLG_PF : 0;
+ break;
+ }
+
+ case 0xd6: /* salc */
+ generate_exception_if(mode_64bit(), EXC_UD);
+ *(uint8_t *)&_regs.eax = (_regs.eflags & EFLG_CF) ? 0xff : 0x00;
+ break;
+
+ case 0xd7: /* xlat */ {
+ unsigned long al = (uint8_t)_regs.eax;
+ if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.ebx + al),
+ &al, 1, ctxt)) != 0 )
+ goto done;
+ *(uint8_t *)&_regs.eax = al;
+ break;
+ }
+
+ case 0xe0 ... 0xe2: /* loop{,z,nz} */ {
+ int rel = insn_fetch_type(int8_t);
+ int do_jmp = !(_regs.eflags & EFLG_ZF); /* loopnz */
+ if ( b == 0xe1 )
+ do_jmp = !do_jmp; /* loopz */
+ else if ( b == 0xe2 )
+ do_jmp = 1; /* loop */
+ switch ( ad_bytes )
+ {
+ case 2:
+ do_jmp &= --(*(uint16_t *)&_regs.ecx) != 0;
+ break;
+ case 4:
+ do_jmp &= --(*(uint32_t *)&_regs.ecx) != 0;
+ _regs.ecx = (uint32_t)_regs.ecx; /* zero extend in x86/64 mode */
+ break;
+ default: /* case 8: */
+ do_jmp &= --_regs.ecx != 0;
+ break;
+ }
+ if ( do_jmp )
+ jmp_rel(rel);
+ break;
+ }
+
case 0xe3: /* jcxz/jecxz (short) */ {
int rel = insn_fetch_type(int8_t);
if ( (ad_bytes == 2) ? !(uint16_t)_regs.ecx :
@@ -1261,12 +1898,26 @@ x86_emulate(
break;
}
- case 0xe9: /* jmp (short) */
- jmp_rel(insn_fetch_type(int8_t));
+ case 0xe8: /* call (near) */ {
+ int rel = (((op_bytes == 2) && !mode_64bit())
+ ? (int32_t)insn_fetch_type(int16_t)
+ : insn_fetch_type(int32_t));
+ op_bytes = mode_64bit() ? 8 : op_bytes;
+ src.val = _regs.eip;
+ jmp_rel(rel);
+ goto push;
+ }
+
+ case 0xe9: /* jmp (near) */ {
+ int rel = (((op_bytes == 2) && !mode_64bit())
+ ? (int32_t)insn_fetch_type(int16_t)
+ : insn_fetch_type(int32_t));
+ jmp_rel(rel);
break;
+ }
- case 0xeb: /* jmp (near) */
- jmp_rel(insn_fetch_bytes(mode_64bit() ? 4 : op_bytes));
+ case 0xeb: /* jmp (short) */
+ jmp_rel(insn_fetch_type(int8_t));
break;
case 0xf5: /* cmc */
@@ -1294,9 +1945,14 @@ x86_emulate(
twobyte_insn:
switch ( b )
{
- case 0x40 ... 0x4f: /* cmov */
- dst.val = dst.orig_val = src.val;
- d = (d & ~Mov) | (test_cc(b, _regs.eflags) ? Mov : 0);
+ case 0x40 ... 0x4f: /* cmovcc */
+ dst.val = src.val;
+ if ( !test_cc(b, _regs.eflags) )
+ dst.type = OP_NONE;
+ break;
+
+ case 0x90 ... 0x9f: /* setcc */
+ dst.val = test_cc(b, _regs.eflags);
break;
case 0xb0 ... 0xb1: /* cmpxchg */
@@ -1331,6 +1987,34 @@ x86_emulate(
emulate_2op_SrcV_nobyte("bts", src, dst, _regs.eflags);
break;
+ case 0xaf: /* imul */
+ _regs.eflags &= ~(EFLG_OF|EFLG_CF);
+ switch ( dst.bytes )
+ {
+ case 2:
+ dst.val = ((uint32_t)(int16_t)src.val *
+ (uint32_t)(int16_t)dst.val);
+ if ( (int16_t)dst.val != (uint32_t)dst.val )
+ _regs.eflags |= EFLG_OF|EFLG_CF;
+ break;
+#ifdef __x86_64__
+ case 4:
+ dst.val = ((uint64_t)(int32_t)src.val *
+ (uint64_t)(int32_t)dst.val);
+ if ( (int32_t)dst.val != dst.val )
+ _regs.eflags |= EFLG_OF|EFLG_CF;
+ break;
+#endif
+ default: {
+ unsigned long m[2] = { src.val, dst.val };
+ if ( imul_dbl(m) )
+ _regs.eflags |= EFLG_OF|EFLG_CF;
+ dst.val = m[0];
+ break;
+ }
+ }
+ break;
+
case 0xb6: /* movzx rm8,r{16,32,64} */
/* Recompute DstReg as we may have decoded AH/BH/CH/DH. */
dst.reg = decode_register(modrm_reg, &_regs, 0);
@@ -1338,6 +2022,26 @@ x86_emulate(
dst.val = (uint8_t)src.val;
break;
+ case 0xbc: /* bsf */ {
+ int zf;
+ asm ( "bsf %2,%0; setz %b1"
+ : "=r" (dst.val), "=q" (zf)
+ : "r" (src.val), "1" (0) );
+ _regs.eflags &= ~EFLG_ZF;
+ _regs.eflags |= zf ? EFLG_ZF : 0;
+ break;
+ }
+
+ case 0xbd: /* bsr */ {
+ int zf;
+ asm ( "bsr %2,%0; setz %b1"
+ : "=r" (dst.val), "=q" (zf)
+ : "r" (src.val), "1" (0) );
+ _regs.eflags &= ~EFLG_ZF;
+ _regs.eflags |= zf ? EFLG_ZF : 0;
+ break;
+ }
+
case 0xb7: /* movzx rm16,r{16,32,64} */
dst.val = (uint16_t)src.val;
break;
@@ -1347,12 +2051,13 @@ x86_emulate(
break;
case 0xba: /* Grp8 */
- switch ( modrm_reg & 3 )
+ switch ( modrm_reg & 7 )
{
- case 0: goto bt;
- case 1: goto bts;
- case 2: goto btr;
- case 3: goto btc;
+ case 4: goto bt;
+ case 5: goto bts;
+ case 6: goto btr;
+ case 7: goto btc;
+ default: generate_exception_if(1, EXC_UD);
}
break;
@@ -1385,10 +2090,13 @@ x86_emulate(
{
case 0x0d: /* GrpP (prefetch) */
case 0x18: /* Grp16 (prefetch/nop) */
+ case 0x19 ... 0x1f: /* nop (amd-defined) */
break;
case 0x80 ... 0x8f: /* jcc (near) */ {
- int rel = insn_fetch_bytes(mode_64bit() ? 4 : op_bytes);
+ int rel = (((op_bytes == 2) && !mode_64bit())
+ ? (int32_t)insn_fetch_type(int16_t)
+ : insn_fetch_type(int32_t));
if ( test_cc(b, _regs.eflags) )
jmp_rel(rel);
break;
@@ -1398,6 +2106,7 @@ x86_emulate(
#if defined(__i386__)
{
unsigned long old_lo, old_hi;
+ generate_exception_if((modrm_reg & 7) != 1, EXC_UD);
if ( (rc = ops->read(ea.mem.seg, ea.mem.off+0, &old_lo, 4, ctxt)) ||
(rc = ops->read(ea.mem.seg, ea.mem.off+4, &old_hi, 4, ctxt)) )
goto done;
@@ -1424,6 +2133,7 @@ x86_emulate(
#elif defined(__x86_64__)
{
unsigned long old, new;
+ generate_exception_if((modrm_reg & 7) != 1, EXC_UD);
if ( (rc = ops->read(ea.mem.seg, ea.mem.off, &old, 8, ctxt)) != 0 )
goto done;
if ( ((uint32_t)(old>>0) != (uint32_t)_regs.eax) ||
@@ -1444,6 +2154,37 @@ x86_emulate(
break;
}
#endif
+
+ case 0xc8 ... 0xcf: /* bswap */
+ dst.type = OP_REG;
+ dst.reg = decode_register(b & 7, &_regs, 0);
+ dst.val = *dst.reg;
+ switch ( dst.bytes = op_bytes )
+ {
+ case 2:
+ dst.val = (((dst.val & 0x00FFUL) << 8) |
+ ((dst.val & 0xFF00UL) >> 8));
+ break;
+ case 4:
+ dst.val = (((dst.val & 0x000000FFUL) << 24) |
+ ((dst.val & 0x0000FF00UL) << 8) |
+ ((dst.val & 0x00FF0000UL) >> 8) |
+ ((dst.val & 0xFF000000UL) >> 24));
+ break;
+#ifdef __x86_64__
+ case 8:
+ dst.val = (((dst.val & 0x00000000000000FFUL) << 56) |
+ ((dst.val & 0x000000000000FF00UL) << 40) |
+ ((dst.val & 0x0000000000FF0000UL) << 24) |
+ ((dst.val & 0x00000000FF000000UL) << 8) |
+ ((dst.val & 0x000000FF00000000UL) >> 8) |
+ ((dst.val & 0x0000FF0000000000UL) >> 24) |
+ ((dst.val & 0x00FF000000000000UL) >> 40) |
+ ((dst.val & 0xFF00000000000000UL) >> 56));
+ break;
+#endif
+ }
+ break;
}
goto writeback;
diff --git a/xen/common/elf.c b/xen/common/elf.c
index 6a55053e74..8414f5e933 100644
--- a/xen/common/elf.c
+++ b/xen/common/elf.c
@@ -300,7 +300,7 @@ int parseelfimage(struct domain_setup_info *dsi)
if ( dsi->__elfnote_section )
{
p = xen_elfnote_string(dsi, XEN_ELFNOTE_PAE_MODE);
- if ( p != NULL && strncmp(p, "bimodal", 7) == 0 )
+ if ( p != NULL && strstr(p, "bimodal") != NULL )
dsi->pae_kernel = PAEKERN_bimodal;
else if ( p != NULL && strncmp(p, "yes", 3) == 0 )
dsi->pae_kernel = PAEKERN_extended_cr3;
diff --git a/xen/common/kexec.c b/xen/common/kexec.c
index 1b470a5e50..e0708ac7c9 100644
--- a/xen/common/kexec.c
+++ b/xen/common/kexec.c
@@ -26,36 +26,34 @@
typedef long ret_t;
-DEFINE_PER_CPU (crash_note_t, crash_notes);
-cpumask_t crash_saved_cpus;
+#define ELFNOTE_ALIGN(_n_) (((_n_)+3)&~3)
+#define ELFNOTE_NAME(_n_) ((void*)(_n_) + sizeof(*(_n_)))
+#define ELFNOTE_DESC(_n_) (ELFNOTE_NAME(_n_) + ELFNOTE_ALIGN((_n_)->namesz))
+#define ELFNOTE_NEXT(_n_) (ELFNOTE_DESC(_n_) + ELFNOTE_ALIGN((_n_)->descsz))
-xen_kexec_image_t kexec_image[KEXEC_IMAGE_NR];
+static DEFINE_PER_CPU(void *, crash_notes);
+
+static Elf_Note *xen_crash_note;
+
+static cpumask_t crash_saved_cpus;
+
+static xen_kexec_image_t kexec_image[KEXEC_IMAGE_NR];
#define KEXEC_FLAG_DEFAULT_POS (KEXEC_IMAGE_NR + 0)
#define KEXEC_FLAG_CRASH_POS (KEXEC_IMAGE_NR + 1)
#define KEXEC_FLAG_IN_PROGRESS (KEXEC_IMAGE_NR + 2)
-unsigned long kexec_flags = 0; /* the lowest bits are for KEXEC_IMAGE... */
+static unsigned long kexec_flags = 0; /* the lowest bits are for KEXEC_IMAGE... */
-spinlock_t kexec_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t kexec_lock = SPIN_LOCK_UNLOCKED;
xen_kexec_reserve_t kexec_crash_area;
static void __init parse_crashkernel(const char *str)
{
- unsigned long start, size;
-
- size = parse_size_and_unit(str, &str);
+ kexec_crash_area.size = parse_size_and_unit(str, &str);
if ( *str == '@' )
- start = parse_size_and_unit(str+1, NULL);
- else
- start = 0;
-
- if ( start && size )
- {
- kexec_crash_area.start = start;
- kexec_crash_area.size = size;
- }
+ kexec_crash_area.start = parse_size_and_unit(str+1, NULL);
}
custom_param("crashkernel", parse_crashkernel);
@@ -70,40 +68,29 @@ static void one_cpu_only(void)
void kexec_crash_save_cpu(void)
{
int cpu = smp_processor_id();
- crash_note_t *cntp;
+ Elf_Note *note = per_cpu(crash_notes, cpu);
+ ELF_Prstatus *prstatus;
+ crash_xen_core_t *xencore;
if ( cpu_test_and_set(cpu, crash_saved_cpus) )
return;
- cntp = &per_cpu(crash_notes, cpu);
- elf_core_save_regs(&cntp->core.desc.desc.pr_reg,
- &cntp->xen_regs.desc.desc);
+ prstatus = ELFNOTE_DESC(note);
- /* Set up crash "CORE" note. */
- setup_crash_note(cntp, core, CORE_STR, CORE_STR_LEN, NT_PRSTATUS);
+ note = ELFNOTE_NEXT(note);
+ xencore = ELFNOTE_DESC(note);
- /* Set up crash note "Xen", XEN_ELFNOTE_CRASH_REGS. */
- setup_crash_note(cntp, xen_regs, XEN_STR, XEN_STR_LEN,
- XEN_ELFNOTE_CRASH_REGS);
+ elf_core_save_regs(&prstatus->pr_reg, xencore);
}
/* Set up the single Xen-specific-info crash note. */
crash_xen_info_t *kexec_crash_save_info(void)
{
int cpu = smp_processor_id();
- crash_note_t *cntp;
- crash_xen_info_t *info;
+ crash_xen_info_t *info = ELFNOTE_DESC(xen_crash_note);
BUG_ON(!cpu_test_and_set(cpu, crash_saved_cpus));
- cntp = &per_cpu(crash_notes, cpu);
-
- /* Set up crash note "Xen", XEN_ELFNOTE_CRASH_INFO. */
- setup_crash_note(cntp, xen_info, XEN_STR, XEN_STR_LEN,
- XEN_ELFNOTE_CRASH_INFO);
-
- info = &cntp->xen_info.desc.desc;
-
info->xen_major_version = xen_major_version();
info->xen_minor_version = xen_minor_version();
info->xen_extra_version = __pa(xen_extra_version());
@@ -147,14 +134,26 @@ static __init int register_crashdump_trigger(void)
}
__initcall(register_crashdump_trigger);
+static void setup_note(Elf_Note *n, const char *name, int type, int descsz)
+{
+ strcpy(ELFNOTE_NAME(n), name);
+ n->namesz = strlen(name);
+ n->descsz = descsz;
+ n->type = type;
+}
+
#define kexec_get(x) kexec_get_##x
#endif
static int kexec_get(reserve)(xen_kexec_range_t *range)
{
- range->start = kexec_crash_area.start;
- range->size = kexec_crash_area.size;
+ if ( kexec_crash_area.size > 0 && kexec_crash_area.start > 0) {
+ range->start = kexec_crash_area.start;
+ range->size = kexec_crash_area.size;
+ }
+ else
+ range->start = range->size = 0;
return 0;
}
@@ -167,11 +166,44 @@ static int kexec_get(xen)(xen_kexec_range_t *range)
static int kexec_get(cpu)(xen_kexec_range_t *range)
{
- if ( range->nr < 0 || range->nr >= num_present_cpus() )
+ int nr = range->nr;
+ int nr_bytes = sizeof(Elf_Note) * 2
+ + ELFNOTE_ALIGN(sizeof(ELF_Prstatus))
+ + ELFNOTE_ALIGN(sizeof(crash_xen_core_t));
+
+ if ( nr < 0 || nr >= num_present_cpus() )
return -EINVAL;
- range->start = __pa((unsigned long)&per_cpu(crash_notes, range->nr));
- range->size = sizeof(crash_note_t);
+ /* The Xen info note is included in CPU0's range. */
+ if ( nr == 0 )
+ nr_bytes += sizeof(Elf_Note) + ELFNOTE_ALIGN(sizeof(crash_xen_info_t));
+
+ if ( per_cpu(crash_notes, nr) == NULL )
+ {
+ Elf_Note *note;
+
+ note = per_cpu(crash_notes, nr) = xmalloc_bytes(nr_bytes);
+
+ if ( note == NULL )
+ return -ENOMEM;
+
+ /* Setup CORE note. */
+ setup_note(note, "CORE", NT_PRSTATUS, sizeof(ELF_Prstatus));
+
+ /* Setup Xen CORE note. */
+ note = ELFNOTE_NEXT(note);
+ setup_note(note, "Xen", XEN_ELFNOTE_CRASH_REGS, sizeof(crash_xen_core_t));
+
+ if (nr == 0)
+ {
+ /* Setup system wide Xen info note. */
+ xen_crash_note = note = ELFNOTE_NEXT(note);
+ setup_note(note, "Xen", XEN_ELFNOTE_CRASH_INFO, sizeof(crash_xen_info_t));
+ }
+ }
+
+ range->start = __pa((unsigned long)per_cpu(crash_notes, nr));
+ range->size = nr_bytes;
return 0;
}
diff --git a/xen/common/keyhandler.c b/xen/common/keyhandler.c
index 3b5aeb05e2..244273addf 100644
--- a/xen/common/keyhandler.c
+++ b/xen/common/keyhandler.c
@@ -95,6 +95,11 @@ static void show_handlers(unsigned char key)
static void __dump_execstate(void *unused)
{
dump_execution_state();
+ printk("*** Dumping CPU%d guest state: ***\n", smp_processor_id());
+ if ( is_idle_vcpu(current) )
+ printk("No guest context (CPU is idle).\n");
+ else
+ show_execution_state(guest_cpu_user_regs());
}
static void dump_registers(unsigned char key, struct cpu_user_regs *regs)
@@ -104,16 +109,18 @@ static void dump_registers(unsigned char key, struct cpu_user_regs *regs)
printk("'%c' pressed -> dumping registers\n", key);
/* Get local execution state out immediately, in case we get stuck. */
- printk("\n*** Dumping CPU%d state: ***\n", smp_processor_id());
- show_execution_state(regs);
+ printk("\n*** Dumping CPU%d host state: ***\n", smp_processor_id());
+ __dump_execstate(NULL);
for_each_online_cpu ( cpu )
{
if ( cpu == smp_processor_id() )
continue;
- printk("\n*** Dumping CPU%d state: ***\n", cpu);
+ printk("\n*** Dumping CPU%d host state: ***\n", cpu);
on_selected_cpus(cpumask_of_cpu(cpu), __dump_execstate, NULL, 1, 1);
}
+
+ printk("\n");
}
static void halt_machine(unsigned char key, struct cpu_user_regs *regs)
diff --git a/xen/common/lib.c b/xen/common/lib.c
index 661f76420d..c3e77d3cfa 100644
--- a/xen/common/lib.c
+++ b/xen/common/lib.c
@@ -1,41 +1,44 @@
#include <xen/ctype.h>
#include <xen/lib.h>
+#include <xen/types.h>
-
-/* for inc/ctype.h */
+/* for ctype.h */
unsigned char _ctype[] = {
-_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
-_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
-_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
-_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
-_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
-_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
-_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
-_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
-_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
-_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
-_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
-_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
-_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
-_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
-_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
-_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
-_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
-_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
-_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
-_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
-_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
-_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
-
-
-/* a couple of 64 bit operations ported from freebsd */
-
-/*-
+ _C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
+ _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
+ _C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
+ _C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
+ _S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
+ _P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
+ _D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
+ _D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
+ _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
+ _U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
+ _U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
+ _U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
+ _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
+ _L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
+ _L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
+ _L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
+ _S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
+ _P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
+ _U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
+ _U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
+ _L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
+ _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
+
+/*
+ * A couple of 64 bit operations ported from FreeBSD.
+ * The code within the '#if BITS_PER_LONG == 32' block below, and no other
+ * code in this file, is distributed under the following licensing terms
+ * This is the modified '3-clause' BSD license with the obnoxious
+ * advertising clause removed, as permitted by University of California.
+ *
* Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
+ * The Regents of the University of California. All rights reserved.
*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
@@ -49,11 +52,7 @@ _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
@@ -68,12 +67,7 @@ _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * $FreeBSD: src/sys/libkern/divdi3.c,v 1.6 1999/08/28 00:46:31 peter Exp $
*/
-
-#include <asm/types.h>
-
#if BITS_PER_LONG == 32
/*
@@ -81,10 +75,10 @@ _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
* one or more of the following formats.
*/
union uu {
- s64 q; /* as a (signed) quad */
- s64 uq; /* as an unsigned quad */
- long sl[2]; /* as two signed longs */
- unsigned long ul[2]; /* as two unsigned longs */
+ s64 q; /* as a (signed) quad */
+ s64 uq; /* as an unsigned quad */
+ long sl[2]; /* as two signed longs */
+ unsigned long ul[2]; /* as two unsigned longs */
};
/* XXX RN: Yuck hardcoded endianess :) */
#define _QUAD_HIGHWORD 1
@@ -122,31 +116,26 @@ union uu {
* Multiprecision divide. This algorithm is from Knuth vol. 2 (2nd ed),
* section 4.3.1, pp. 257--259.
*/
-#define B (1 << HALF_BITS) /* digit base */
+#define B (1 << HALF_BITS) /* digit base */
/* Combine two `digits' to make a single two-digit number. */
-#define COMBINE(a, b) (((u_long)(a) << HALF_BITS) | (b))
+#define COMBINE(a, b) (((u_long)(a) << HALF_BITS) | (b))
-/* select a type for digits in base B: use unsigned short if they fit */
-#if ULONG_MAX == 0xffffffff && USHRT_MAX >= 0xffff
-typedef unsigned short digit;
-#else
+/* select a type for digits in base B */
typedef u_long digit;
-#endif
/*
* Shift p[0]..p[len] left `sh' bits, ignoring any bits that
* `fall out' the left (there never will be any such anyway).
* We may assume len >= 0. NOTE THAT THIS WRITES len+1 DIGITS.
*/
-static void
-shl(register digit *p, register int len, register int sh)
+static void shl(register digit *p, register int len, register int sh)
{
- register int i;
+ register int i;
- for (i = 0; i < len; i++)
- p[i] = LHALF(p[i] << sh) | (p[i + 1] >> (HALF_BITS - sh));
- p[i] = LHALF(p[i] << sh);
+ for (i = 0; i < len; i++)
+ p[i] = LHALF(p[i] << sh) | (p[i + 1] >> (HALF_BITS - sh));
+ p[i] = LHALF(p[i] << sh);
}
/*
@@ -157,234 +146,222 @@ shl(register digit *p, register int len, register int sh)
* divisor are 4 `digits' in this base (they are shorter if they have
* leading zeros).
*/
-u64
-__qdivrem(u64 uq, u64 vq, u64 *arq)
+u64 __qdivrem(u64 uq, u64 vq, u64 *arq)
{
- union uu tmp;
- digit *u, *v, *q;
- register digit v1, v2;
- u_long qhat, rhat, t;
- int m, n, d, j, i;
- digit uspace[5], vspace[5], qspace[5];
-
- /*
- * Take care of special cases: divide by zero, and u < v.
- */
- if (vq == 0) {
- /* divide by zero. */
- static volatile const unsigned int zero = 0;
-
- tmp.ul[H] = tmp.ul[L] = 1 / zero;
- if (arq)
- *arq = uq;
- return (tmp.q);
- }
- if (uq < vq) {
- if (arq)
- *arq = uq;
- return (0);
- }
- u = &uspace[0];
- v = &vspace[0];
- q = &qspace[0];
-
- /*
- * Break dividend and divisor into digits in base B, then
- * count leading zeros to determine m and n. When done, we
- * will have:
- * u = (u[1]u[2]...u[m+n]) sub B
- * v = (v[1]v[2]...v[n]) sub B
- * v[1] != 0
- * 1 < n <= 4 (if n = 1, we use a different division algorithm)
- * m >= 0 (otherwise u < v, which we already checked)
- * m + n = 4
- * and thus
- * m = 4 - n <= 2
- */
- tmp.uq = uq;
- u[0] = 0;
- u[1] = HHALF(tmp.ul[H]);
- u[2] = LHALF(tmp.ul[H]);
- u[3] = HHALF(tmp.ul[L]);
- u[4] = LHALF(tmp.ul[L]);
- tmp.uq = vq;
- v[1] = HHALF(tmp.ul[H]);
- v[2] = LHALF(tmp.ul[H]);
- v[3] = HHALF(tmp.ul[L]);
- v[4] = LHALF(tmp.ul[L]);
- for (n = 4; v[1] == 0; v++) {
- if (--n == 1) {
- u_long rbj; /* r*B+u[j] (not root boy jim) */
- digit q1, q2, q3, q4;
-
- /*
- * Change of plan, per exercise 16.
- * r = 0;
- * for j = 1..4:
- * q[j] = floor((r*B + u[j]) / v),
- * r = (r*B + u[j]) % v;
- * We unroll this completely here.
- */
- t = v[2]; /* nonzero, by definition */
- q1 = u[1] / t;
- rbj = COMBINE(u[1] % t, u[2]);
- q2 = rbj / t;
- rbj = COMBINE(rbj % t, u[3]);
- q3 = rbj / t;
- rbj = COMBINE(rbj % t, u[4]);
- q4 = rbj / t;
- if (arq)
- *arq = rbj % t;
- tmp.ul[H] = COMBINE(q1, q2);
- tmp.ul[L] = COMBINE(q3, q4);
- return (tmp.q);
- }
- }
-
- /*
- * By adjusting q once we determine m, we can guarantee that
- * there is a complete four-digit quotient at &qspace[1] when
- * we finally stop.
- */
- for (m = 4 - n; u[1] == 0; u++)
- m--;
- for (i = 4 - m; --i >= 0;)
- q[i] = 0;
- q += 4 - m;
-
- /*
- * Here we run Program D, translated from MIX to C and acquiring
- * a few minor changes.
- *
- * D1: choose multiplier 1 << d to ensure v[1] >= B/2.
- */
- d = 0;
- for (t = v[1]; t < B / 2; t <<= 1)
- d++;
- if (d > 0) {
- shl(&u[0], m + n, d); /* u <<= d */
- shl(&v[1], n - 1, d); /* v <<= d */
- }
- /*
- * D2: j = 0.
- */
- j = 0;
- v1 = v[1]; /* for D3 -- note that v[1..n] are constant */
- v2 = v[2]; /* for D3 */
- do {
- register digit uj0, uj1, uj2;
-
- /*
- * D3: Calculate qhat (\^q, in TeX notation).
- * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and
- * let rhat = (u[j]*B + u[j+1]) mod v[1].
- * While rhat < B and v[2]*qhat > rhat*B+u[j+2],
- * decrement qhat and increase rhat correspondingly.
- * Note that if rhat >= B, v[2]*qhat < rhat*B.
- */
- uj0 = u[j + 0]; /* for D3 only -- note that u[j+...] change */
- uj1 = u[j + 1]; /* for D3 only */
- uj2 = u[j + 2]; /* for D3 only */
- if (uj0 == v1) {
- qhat = B;
- rhat = uj1;
- goto qhat_too_big;
- } else {
- u_long nn = COMBINE(uj0, uj1);
- qhat = nn / v1;
- rhat = nn % v1;
- }
- while (v2 * qhat > COMBINE(rhat, uj2)) {
- qhat_too_big:
- qhat--;
- if ((rhat += v1) >= B)
- break;
- }
- /*
- * D4: Multiply and subtract.
- * The variable `t' holds any borrows across the loop.
- * We split this up so that we do not require v[0] = 0,
- * and to eliminate a final special case.
- */
- for (t = 0, i = n; i > 0; i--) {
- t = u[i + j] - v[i] * qhat - t;
- u[i + j] = LHALF(t);
- t = (B - HHALF(t)) & (B - 1);
- }
- t = u[j] - t;
- u[j] = LHALF(t);
- /*
- * D5: test remainder.
- * There is a borrow if and only if HHALF(t) is nonzero;
- * in that (rare) case, qhat was too large (by exactly 1).
- * Fix it by adding v[1..n] to u[j..j+n].
- */
- if (HHALF(t)) {
- qhat--;
- for (t = 0, i = n; i > 0; i--) { /* D6: add back. */
- t += u[i + j] + v[i];
- u[i + j] = LHALF(t);
- t = HHALF(t);
- }
- u[j] = LHALF(u[j] + t);
- }
- q[j] = qhat;
- } while (++j <= m); /* D7: loop on j. */
-
- /*
- * If caller wants the remainder, we have to calculate it as
- * u[m..m+n] >> d (this is at most n digits and thus fits in
- * u[m+1..m+n], but we may need more source digits).
- */
- if (arq) {
- if (d) {
- for (i = m + n; i > m; --i)
- u[i] = (u[i] >> d) |
- LHALF(u[i - 1] << (HALF_BITS - d));
- u[i] = 0;
- }
- tmp.ul[H] = COMBINE(uspace[1], uspace[2]);
- tmp.ul[L] = COMBINE(uspace[3], uspace[4]);
- *arq = tmp.q;
- }
-
- tmp.ul[H] = COMBINE(qspace[1], qspace[2]);
- tmp.ul[L] = COMBINE(qspace[3], qspace[4]);
- return (tmp.q);
+ union uu tmp;
+ digit *u, *v, *q;
+ register digit v1, v2;
+ u_long qhat, rhat, t;
+ int m, n, d, j, i;
+ digit uspace[5], vspace[5], qspace[5];
+
+ /*
+ * Take care of special cases: divide by zero, and u < v.
+ */
+ if (vq == 0) {
+ /* divide by zero. */
+ static volatile const unsigned int zero = 0;
+
+ tmp.ul[H] = tmp.ul[L] = 1 / zero;
+ if (arq)
+ *arq = uq;
+ return (tmp.q);
+ }
+ if (uq < vq) {
+ if (arq)
+ *arq = uq;
+ return (0);
+ }
+ u = &uspace[0];
+ v = &vspace[0];
+ q = &qspace[0];
+
+ /*
+ * Break dividend and divisor into digits in base B, then
+ * count leading zeros to determine m and n. When done, we
+ * will have:
+ * u = (u[1]u[2]...u[m+n]) sub B
+ * v = (v[1]v[2]...v[n]) sub B
+ * v[1] != 0
+ * 1 < n <= 4 (if n = 1, we use a different division algorithm)
+ * m >= 0 (otherwise u < v, which we already checked)
+ * m + n = 4
+ * and thus
+ * m = 4 - n <= 2
+ */
+ tmp.uq = uq;
+ u[0] = 0;
+ u[1] = HHALF(tmp.ul[H]);
+ u[2] = LHALF(tmp.ul[H]);
+ u[3] = HHALF(tmp.ul[L]);
+ u[4] = LHALF(tmp.ul[L]);
+ tmp.uq = vq;
+ v[1] = HHALF(tmp.ul[H]);
+ v[2] = LHALF(tmp.ul[H]);
+ v[3] = HHALF(tmp.ul[L]);
+ v[4] = LHALF(tmp.ul[L]);
+ for (n = 4; v[1] == 0; v++) {
+ if (--n == 1) {
+ u_long rbj; /* r*B+u[j] (not root boy jim) */
+ digit q1, q2, q3, q4;
+
+ /*
+ * Change of plan, per exercise 16.
+ * r = 0;
+ * for j = 1..4:
+ * q[j] = floor((r*B + u[j]) / v),
+ * r = (r*B + u[j]) % v;
+ * We unroll this completely here.
+ */
+ t = v[2]; /* nonzero, by definition */
+ q1 = u[1] / t;
+ rbj = COMBINE(u[1] % t, u[2]);
+ q2 = rbj / t;
+ rbj = COMBINE(rbj % t, u[3]);
+ q3 = rbj / t;
+ rbj = COMBINE(rbj % t, u[4]);
+ q4 = rbj / t;
+ if (arq)
+ *arq = rbj % t;
+ tmp.ul[H] = COMBINE(q1, q2);
+ tmp.ul[L] = COMBINE(q3, q4);
+ return (tmp.q);
+ }
+ }
+
+ /*
+ * By adjusting q once we determine m, we can guarantee that
+ * there is a complete four-digit quotient at &qspace[1] when
+ * we finally stop.
+ */
+ for (m = 4 - n; u[1] == 0; u++)
+ m--;
+ for (i = 4 - m; --i >= 0;)
+ q[i] = 0;
+ q += 4 - m;
+
+ /*
+ * Here we run Program D, translated from MIX to C and acquiring
+ * a few minor changes.
+ *
+ * D1: choose multiplier 1 << d to ensure v[1] >= B/2.
+ */
+ d = 0;
+ for (t = v[1]; t < B / 2; t <<= 1)
+ d++;
+ if (d > 0) {
+ shl(&u[0], m + n, d); /* u <<= d */
+ shl(&v[1], n - 1, d); /* v <<= d */
+ }
+ /*
+ * D2: j = 0.
+ */
+ j = 0;
+ v1 = v[1]; /* for D3 -- note that v[1..n] are constant */
+ v2 = v[2]; /* for D3 */
+ do {
+ register digit uj0, uj1, uj2;
+
+ /*
+ * D3: Calculate qhat (\^q, in TeX notation).
+ * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and
+ * let rhat = (u[j]*B + u[j+1]) mod v[1].
+ * While rhat < B and v[2]*qhat > rhat*B+u[j+2],
+ * decrement qhat and increase rhat correspondingly.
+ * Note that if rhat >= B, v[2]*qhat < rhat*B.
+ */
+ uj0 = u[j + 0]; /* for D3 only -- note that u[j+...] change */
+ uj1 = u[j + 1]; /* for D3 only */
+ uj2 = u[j + 2]; /* for D3 only */
+ if (uj0 == v1) {
+ qhat = B;
+ rhat = uj1;
+ goto qhat_too_big;
+ } else {
+ u_long nn = COMBINE(uj0, uj1);
+ qhat = nn / v1;
+ rhat = nn % v1;
+ }
+ while (v2 * qhat > COMBINE(rhat, uj2)) {
+ qhat_too_big:
+ qhat--;
+ if ((rhat += v1) >= B)
+ break;
+ }
+ /*
+ * D4: Multiply and subtract.
+ * The variable `t' holds any borrows across the loop.
+ * We split this up so that we do not require v[0] = 0,
+ * and to eliminate a final special case.
+ */
+ for (t = 0, i = n; i > 0; i--) {
+ t = u[i + j] - v[i] * qhat - t;
+ u[i + j] = LHALF(t);
+ t = (B - HHALF(t)) & (B - 1);
+ }
+ t = u[j] - t;
+ u[j] = LHALF(t);
+ /*
+ * D5: test remainder.
+ * There is a borrow if and only if HHALF(t) is nonzero;
+ * in that (rare) case, qhat was too large (by exactly 1).
+ * Fix it by adding v[1..n] to u[j..j+n].
+ */
+ if (HHALF(t)) {
+ qhat--;
+ for (t = 0, i = n; i > 0; i--) { /* D6: add back. */
+ t += u[i + j] + v[i];
+ u[i + j] = LHALF(t);
+ t = HHALF(t);
+ }
+ u[j] = LHALF(u[j] + t);
+ }
+ q[j] = qhat;
+ } while (++j <= m); /* D7: loop on j. */
+
+ /*
+ * If caller wants the remainder, we have to calculate it as
+ * u[m..m+n] >> d (this is at most n digits and thus fits in
+ * u[m+1..m+n], but we may need more source digits).
+ */
+ if (arq) {
+ if (d) {
+ for (i = m + n; i > m; --i)
+ u[i] = (u[i] >> d) |
+ LHALF(u[i - 1] << (HALF_BITS - d));
+ u[i] = 0;
+ }
+ tmp.ul[H] = COMBINE(uspace[1], uspace[2]);
+ tmp.ul[L] = COMBINE(uspace[3], uspace[4]);
+ *arq = tmp.q;
+ }
+
+ tmp.ul[H] = COMBINE(qspace[1], qspace[2]);
+ tmp.ul[L] = COMBINE(qspace[3], qspace[4]);
+ return (tmp.q);
}
/*
* Divide two signed quads.
- * ??? if -1/2 should produce -1 on this machine, this code is wrong
- * (Grzegorz Milos) Note for the above: -1/2 is 0. And so it should.
+ * Truncates towards zero, as required by C99.
*/
-s64
-__divdi3(s64 a, s64 b)
+s64 __divdi3(s64 a, s64 b)
{
- u64 ua, ub, uq;
- int neg;
-
- if (a < 0)
- ua = -(u64)a, neg = 1;
- else
- ua = a, neg = 0;
- if (b < 0)
- ub = -(u64)b, neg ^= 1;
- else
- ub = b;
- uq = __qdivrem(ua, ub, (u64 *)0);
- return (neg ? -uq : uq);
+ u64 ua, ub, uq;
+ int neg = (a < 0) ^ (b < 0);
+ ua = (a < 0) ? -(u64)a : a;
+ ub = (b < 0) ? -(u64)b : b;
+ uq = __qdivrem(ua, ub, (u64 *)0);
+ return (neg ? -uq : uq);
}
/*
* Divide two unsigned quads.
*/
-u64
-__udivdi3(u64 a, u64 b)
+u64 __udivdi3(u64 a, u64 b)
{
-
- return (__qdivrem(a, b, (u64 *)0));
+ return __qdivrem(a, b, (u64 *)0);
}
/*
@@ -392,87 +369,66 @@ __udivdi3(u64 a, u64 b)
*/
u64 __umoddi3(u64 a, u64 b)
{
- u64 rem;
- __qdivrem(a, b, &rem);
- return rem;
+ u64 rem;
+ __qdivrem(a, b, &rem);
+ return rem;
}
/*
* Remainder of signed quad division.
- * The result of mod is not always equal to division
- * remainder. The following example shows the result for all
- * four possible cases:
+ * Truncates towards zero, as required by C99:
* 11 % 5 = 1
- * -11 % 5 = 4
- * 11 % -5 = -4
- * -11 % -5 = -1
+ * -11 % 5 = -1
+ * 11 % -5 = 1
+ * -11 % -5 = 1
*/
s64 __moddi3(s64 a, s64 b)
{
- u64 ua, ub, urem;
- int neg1, neg2;
-
- if (a < 0)
- ua = -(u64)a, neg1 = 1;
- else
- ua = a, neg1 = 0;
-
- if (b < 0)
- ub = -(u64)b, neg2 = 1;
- else
- ub = b, neg2 = 0;
- __qdivrem(ua, ub, &urem);
-
- /* There 4 different cases: */
- if (neg1) {
- if (neg2)
- return -urem;
- else
- return ub - urem;
- } else {
- if (neg2)
- return -ub + urem;
- else
- return urem;
- }
+ u64 ua, ub, urem;
+ int neg = (a < 0);
+ ua = neg ? -(u64)a : a;
+ ub = (b < 0) ? -(u64)b : b;
+ __qdivrem(ua, ub, &urem);
+ return (neg ? -urem : urem);
}
#endif /* BITS_PER_LONG == 32 */
unsigned long long parse_size_and_unit(const char *s, const char **ps)
{
- unsigned long long ret;
- const char *s1;
-
- ret = simple_strtoull(s, &s1, 0);
-
- switch (*s1) {
- case 'G': case 'g':
- ret <<= 10;
- case 'M': case 'm':
- ret <<= 10;
- case 'K': case 'k':
- ret <<= 10;
- case 'B': case 'b':
- s1++;
- break;
- default:
- ret <<= 10; /* default to kB */
- break;
- }
-
- if (ps != NULL)
- *ps = s1;
-
- return ret;
+ unsigned long long ret;
+ const char *s1;
+
+ ret = simple_strtoull(s, &s1, 0);
+
+ switch ( *s1 )
+ {
+ case 'G': case 'g':
+ ret <<= 10;
+ case 'M': case 'm':
+ ret <<= 10;
+ case 'K': case 'k':
+ ret <<= 10;
+ case 'B': case 'b':
+ s1++;
+ break;
+ default:
+ ret <<= 10; /* default to kB */
+ break;
+ }
+
+ if ( ps != NULL )
+ *ps = s1;
+
+ return ret;
}
/*
* Local variables:
* mode: C
* c-set-style: "BSD"
- * c-basic-offset: 8
- * tab-width: 8
- * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
* End:
*/
diff --git a/xen/common/symbols.c b/xen/common/symbols.c
index 496f231f8b..fba6cf0867 100644
--- a/xen/common/symbols.c
+++ b/xen/common/symbols.c
@@ -94,9 +94,6 @@ const char *symbols_lookup(unsigned long addr,
unsigned long i, low, high, mid;
unsigned long symbol_end = 0;
- /* This kernel should never had been booted. */
- BUG_ON(!symbols_addresses);
-
namebuf[KSYM_NAME_LEN] = 0;
namebuf[0] = 0;
diff --git a/xen/common/xencomm.c b/xen/common/xencomm.c
index f33c753934..8b7e502869 100644
--- a/xen/common/xencomm.c
+++ b/xen/common/xencomm.c
@@ -119,7 +119,7 @@ xencomm_copy_from_guest(void *to, const void *from, unsigned int n,
chunksz -= chunk_skip;
skip -= chunk_skip;
- if (skip == 0) {
+ if (skip == 0 && chunksz > 0) {
unsigned long src_maddr;
unsigned long dest = (unsigned long)to + to_pos;
unsigned int bytes = min(chunksz, n - to_pos);
@@ -225,7 +225,7 @@ xencomm_copy_to_guest(void *to, const void *from, unsigned int n,
chunksz -= chunk_skip;
skip -= chunk_skip;
- if (skip == 0) {
+ if (skip == 0 && chunksz > 0) {
unsigned long dest_maddr;
unsigned long source = (unsigned long)from + from_pos;
unsigned int bytes = min(chunksz, n - from_pos);
diff --git a/xen/drivers/video/vga.c b/xen/drivers/video/vga.c
index 08a260a2b7..303210e466 100644
--- a/xen/drivers/video/vga.c
+++ b/xen/drivers/video/vga.c
@@ -557,7 +557,7 @@ static int vga_load_font(const struct font_desc *font, unsigned rows)
static int vgacon_enabled = 0;
static int vgacon_keep = 0;
-static int vgacon_lines = 25;
+static int vgacon_lines = 50;
static const struct font_desc *font;
static int xpos, ypos;
@@ -606,12 +606,9 @@ void vga_init(void)
case 60:
font = &font_vga_8x8;
break;
- default:
- vgacon_lines = 25;
- break;
}
- if ( (font != NULL) && (vga_load_font(font, vgacon_lines) < 0) )
+ if ( (font == NULL) || (vga_load_font(font, vgacon_lines) < 0) )
{
vgacon_lines = 25;
font = NULL;
diff --git a/xen/include/Makefile b/xen/include/Makefile
index d2efb237c3..1f762d1024 100644
--- a/xen/include/Makefile
+++ b/xen/include/Makefile
@@ -2,8 +2,28 @@ ifneq ($(CONFIG_COMPAT),)
compat-arch-$(CONFIG_X86) := x86_32
-headers-y := $(shell echo public/*.h | sed -e 's,[^[:space:]]*-[^[:space:]]*,,g' -e 's,public/,compat/,g')
-headers-y := $(filter-out %/dom0_ops.h,$(headers-y))
+headers-y := \
+ compat/acm.h \
+ compat/acm_ops.h \
+ compat/callback.h \
+ compat/domctl.h \
+ compat/elfnote.h \
+ compat/event_channel.h \
+ compat/features.h \
+ compat/grant_table.h \
+ compat/kexec.h \
+ compat/memory.h \
+ compat/nmi.h \
+ compat/physdev.h \
+ compat/platform.h \
+ compat/sched.h \
+ compat/sysctl.h \
+ compat/trace.h \
+ compat/vcpu.h \
+ compat/version.h \
+ compat/xen.h \
+ compat/xencomm.h \
+ compat/xenoprof.h
headers-$(CONFIG_X86) += compat/arch-x86/xen.h
headers-$(CONFIG_X86) += compat/arch-x86/xen-$(compat-arch-y).h
headers-y += compat/arch-$(compat-arch-y).h compat/xlat.h
@@ -21,24 +41,14 @@ endif
all: $(headers-y)
compat/%.h: compat/%.i Makefile
- id=_$$(echo $@ | sed 'y,abcdefghijklmnopqrstuvwxyz-/.,ABCDEFGHIJKLMNOPQRSTUVWXYZ___,'); \
+ id=_$$(echo $@ | tr '[:lower:]-/.' '[:upper:]___'); \
echo "#ifndef $$id" >$@.new; \
echo "#define $$id" >>$@.new; \
echo "#include <xen/compat.h>" >>$@.new; \
$(if $(filter-out compat/arch-%.h,$@),echo "#include <$(patsubst compat/%,public/%,$@)>" >>$@.new;) \
$(if $(prefix-y),echo "$(prefix-y)" >>$@.new;) \
- grep -v '^# [[:digit:]]' $< | \
- sed -e 's,__InClUdE__,#include,' \
- -e 's,"xen-compat.h",<public/xen-compat.h>,' \
- -e 's,\(struct\|union\|enum\)[[:space:]]\+\(xen_\?\)\?\([[:alpha:]_]\),\1 compat_\3,g' \
- -e 's,@KeeP@,,g' \
- -e 's,_t\([^[:alnum:]_]\|$$\),_compat_t\1,g' \
- -e 's,\(8\|16\|32\|64\)_compat_t\([^[:alnum:]_]\|$$\),\1_t\2,g' \
- -e 's,\(^\|[^[:alnum:]_]\)xen_\?\([[:alnum:]_]*\)_compat_t\([^[:alnum:]_]\|$$\),\1compat_\2_t\3,g' \
- -e 's,\(^\|[^[:alnum:]_]\)XEN_\?,\1COMPAT_,' \
- -e 's,\(^\|[^[:alnum:]_]\)Xen_\?,\1Compat_,' \
- -e 's,\(^\|[^[:alnum:]]\)long\([^[:alnum:]]\|$$\),\1int\2,g' | \
- uniq >>$@.new; \
+ grep -v '^# [0-9]' $< | \
+ $(BASEDIR)/tools/compat-build-header.py | uniq >>$@.new; \
$(if $(suffix-y),echo "$(suffix-y)" >>$@.new;) \
echo "#endif /* $$id */" >>$@.new
mv -f $@.new $@
@@ -49,19 +59,13 @@ compat/%.i: compat/%.c Makefile
compat/%.c: public/%.h xlat.lst Makefile
mkdir -p $(@D)
grep -v 'DEFINE_XEN_GUEST_HANDLE(long)' $< | \
- sed -e 's,^[[:space:]]*#[[:space:]]*include[[:space:]]\+,__InClUdE__ ,' \
- -e 's,^[[:space:]]*#[[:space:]]*define[[:space:]]\+\([[:upper:]_]*_GUEST_HANDLE\),#define HIDE_\1,' \
- -e 's,^[[:space:]]*#[[:space:]]*define[[:space:]]\+\([[:lower:]_]*_guest_handle\),#define hide_\1,' \
- -e 's,XEN_GUEST_HANDLE\(_[[:xdigit:]]\+\)\?,COMPAT_HANDLE,g' \
- $(foreach n,$(shell sed -n 's,^[[:space:]]*?[[:space:]]\+\([[:alnum:]_]*\)[[:space:]].*,\1,p' xlat.lst), \
- -e 's,\(struct\|union\)[[:space:]]\+\(xen_\?\)\?$n[[:space:]]\+\([[:alpha:]_]\),\1 @KeeP@\2$n \3,g') \
- >$@.new
+ $(BASEDIR)/tools/compat-build-source.py >$@.new
mv -f $@.new $@
compat/xlat.h: xlat.lst $(filter-out compat/xlat.h,$(headers-y)) $(BASEDIR)/tools/get-fields.sh Makefile
- grep -v '^[[:space:]]*#' xlat.lst | \
+ grep -v '^[ ]*#' xlat.lst | \
while read what name hdr; do \
- $(SHELL) $(BASEDIR)/tools/get-fields.sh "$$what" compat_$$name $$(echo compat/$$hdr | sed 's,@arch@,$(compat-arch-y),g') || exit $$?; \
+ /bin/bash $(BASEDIR)/tools/get-fields.sh "$$what" compat_$$name $$(echo compat/$$hdr | sed 's,@arch@,$(compat-arch-y),g') || exit $$?; \
done >$@.new
mv -f $@.new $@
diff --git a/xen/include/asm-powerpc/byteorder.h b/xen/include/asm-powerpc/byteorder.h
new file mode 100644
index 0000000000..94bbea2929
--- /dev/null
+++ b/xen/include/asm-powerpc/byteorder.h
@@ -0,0 +1,80 @@
+#ifndef _ASM_POWERPC_BYTEORDER_H
+#define _ASM_POWERPC_BYTEORDER_H
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <asm/types.h>
+#include <xen/compiler.h>
+
+static inline __u16 ld_le16(const volatile __u16 *addr)
+{
+ __u16 val;
+
+ asm volatile ("lhbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr));
+ return val;
+}
+
+static inline void st_le16(volatile __u16 *addr, const __u16 val)
+{
+ asm volatile ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
+}
+
+static inline __u32 ld_le32(const volatile __u32 *addr)
+{
+ __u32 val;
+
+ asm volatile ("lwbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr));
+ return val;
+}
+
+static inline void st_le32(volatile __u32 *addr, const __u32 val)
+{
+ asm volatile ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
+}
+
+static inline __attribute_const__ __u16 ___arch__swab16(__u16 value)
+{
+ __u16 result;
+
+ asm("rlwimi %0,%1,8,16,23"
+ : "=r" (result)
+ : "r" (value), "0" (value >> 8));
+ return result;
+}
+
+static inline __attribute_const__ __u32 ___arch__swab32(__u32 value)
+{
+ __u32 result;
+
+ asm("rlwimi %0,%1,24,16,23\n\t"
+ "rlwimi %0,%1,8,8,15\n\t"
+ "rlwimi %0,%1,24,0,7"
+ : "=r" (result)
+ : "r" (value), "0" (value >> 24));
+ return result;
+}
+
+#define __arch__swab16(x) ___arch__swab16(x)
+#define __arch__swab32(x) ___arch__swab32(x)
+
+/* The same, but returns converted value from the location pointer by addr. */
+#define __arch__swab16p(addr) ld_le16(addr)
+#define __arch__swab32p(addr) ld_le32(addr)
+
+/* The same, but do the conversion in situ, ie. put the value back to addr. */
+#define __arch__swab16s(addr) st_le16(addr,*addr)
+#define __arch__swab32s(addr) st_le32(addr,*addr)
+
+#define __BYTEORDER_HAS_U64__
+#ifndef __powerpc64__
+#define __SWAB_64_THRU_32__
+#endif /* __powerpc64__ */
+
+#include <xen/byteorder/big_endian.h>
+
+#endif /* _ASM_POWERPC_BYTEORDER_H */
diff --git a/xen/include/asm-x86/byteorder.h b/xen/include/asm-x86/byteorder.h
new file mode 100644
index 0000000000..eb52ae2f11
--- /dev/null
+++ b/xen/include/asm-x86/byteorder.h
@@ -0,0 +1,36 @@
+#ifndef __ASM_X86_BYTEORDER_H__
+#define __ASM_X86_BYTEORDER_H__
+
+#include <asm/types.h>
+#include <xen/compiler.h>
+
+static inline __attribute_const__ __u32 ___arch__swab32(__u32 x)
+{
+ asm("bswap %0" : "=r" (x) : "0" (x));
+ return x;
+}
+
+static inline __attribute_const__ __u64 ___arch__swab64(__u64 val)
+{
+ union {
+ struct { __u32 a,b; } s;
+ __u64 u;
+ } v;
+ v.u = val;
+ asm("bswapl %0 ; bswapl %1 ; xchgl %0,%1"
+ : "=r" (v.s.a), "=r" (v.s.b)
+ : "0" (v.s.a), "1" (v.s.b));
+ return v.u;
+}
+
+/* Do not define swab16. Gcc is smart enough to recognize "C" version and
+ convert it into rotation or exhange. */
+
+#define __arch__swab64(x) ___arch__swab64(x)
+#define __arch__swab32(x) ___arch__swab32(x)
+
+#define __BYTEORDER_HAS_U64__
+
+#include <xen/byteorder/little_endian.h>
+
+#endif /* __ASM_X86_BYTEORDER_H__ */
diff --git a/xen/include/asm-x86/guest_access.h b/xen/include/asm-x86/guest_access.h
index ce5c290787..0fc5bc98dc 100644
--- a/xen/include/asm-x86/guest_access.h
+++ b/xen/include/asm-x86/guest_access.h
@@ -32,7 +32,7 @@
* specifying an offset into the guest array.
*/
#define copy_to_guest_offset(hnd, off, ptr, nr) ({ \
- const typeof(ptr) _x = (hnd).p; \
+ typeof(ptr) _x = (hnd).p; \
const typeof(ptr) _y = (ptr); \
is_hvm_vcpu(current) ? \
copy_to_user_hvm(_x+(off), _y, sizeof(*_x)*(nr)) : \
@@ -45,7 +45,7 @@
*/
#define copy_from_guest_offset(ptr, hnd, off, nr) ({ \
const typeof(ptr) _x = (hnd).p; \
- const typeof(ptr) _y = (ptr); \
+ typeof(ptr) _y = (ptr); \
is_hvm_vcpu(current) ? \
copy_from_user_hvm(_y, _x+(off), sizeof(*_x)*(nr)) :\
copy_from_user(_y, _x+(off), sizeof(*_x)*(nr)); \
@@ -53,7 +53,7 @@
/* Copy sub-field of a structure to guest context via a guest handle. */
#define copy_field_to_guest(hnd, ptr, field) ({ \
- const typeof(&(ptr)->field) _x = &(hnd).p->field; \
+ typeof(&(ptr)->field) _x = &(hnd).p->field; \
const typeof(&(ptr)->field) _y = &(ptr)->field; \
is_hvm_vcpu(current) ? \
copy_to_user_hvm(_x, _y, sizeof(*_x)) : \
@@ -63,7 +63,7 @@
/* Copy sub-field of a structure from guest context via a guest handle. */
#define copy_field_from_guest(ptr, hnd, field) ({ \
const typeof(&(ptr)->field) _x = &(hnd).p->field; \
- const typeof(&(ptr)->field) _y = &(ptr)->field; \
+ typeof(&(ptr)->field) _y = &(ptr)->field; \
is_hvm_vcpu(current) ? \
copy_from_user_hvm(_y, _x, sizeof(*_x)) : \
copy_from_user(_y, _x, sizeof(*_x)); \
@@ -78,7 +78,7 @@
array_access_ok((hnd).p, (nr), sizeof(*(hnd).p)))
#define __copy_to_guest_offset(hnd, off, ptr, nr) ({ \
- const typeof(ptr) _x = (hnd).p; \
+ typeof(ptr) _x = (hnd).p; \
const typeof(ptr) _y = (ptr); \
is_hvm_vcpu(current) ? \
copy_to_user_hvm(_x+(off), _y, sizeof(*_x)*(nr)) : \
@@ -87,14 +87,14 @@
#define __copy_from_guest_offset(ptr, hnd, off, nr) ({ \
const typeof(ptr) _x = (hnd).p; \
- const typeof(ptr) _y = (ptr); \
+ typeof(ptr) _y = (ptr); \
is_hvm_vcpu(current) ? \
copy_from_user_hvm(_y, _x+(off),sizeof(*_x)*(nr)) : \
__copy_from_user(_y, _x+(off), sizeof(*_x)*(nr)); \
})
#define __copy_field_to_guest(hnd, ptr, field) ({ \
- const typeof(&(ptr)->field) _x = &(hnd).p->field; \
+ typeof(&(ptr)->field) _x = &(hnd).p->field; \
const typeof(&(ptr)->field) _y = &(ptr)->field; \
is_hvm_vcpu(current) ? \
copy_to_user_hvm(_x, _y, sizeof(*_x)) : \
@@ -103,9 +103,9 @@
#define __copy_field_from_guest(ptr, hnd, field) ({ \
const typeof(&(ptr)->field) _x = &(hnd).p->field; \
- const typeof(&(ptr)->field) _y = &(ptr)->field; \
+ typeof(&(ptr)->field) _y = &(ptr)->field; \
is_hvm_vcpu(current) ? \
- copy_from_user_hvm(_x, _y, sizeof(*_x)) : \
+ copy_from_user_hvm(_y, _x, sizeof(*_x)) : \
__copy_from_user(_y, _x, sizeof(*_x)); \
})
diff --git a/xen/include/asm-x86/hvm/irq.h b/xen/include/asm-x86/hvm/irq.h
index af66d67f2c..44e9ab1cf5 100644
--- a/xen/include/asm-x86/hvm/irq.h
+++ b/xen/include/asm-x86/hvm/irq.h
@@ -43,9 +43,17 @@ struct hvm_irq {
*/
DECLARE_BITMAP(isa_irq, 16);
- /* Virtual interrupt wire and GSI link for paravirtual platform driver. */
- DECLARE_BITMAP(callback_irq_wire, 1);
- unsigned int callback_gsi;
+ /* Virtual interrupt and via-link for paravirtual platform driver. */
+ unsigned int callback_via_asserted;
+ enum {
+ HVMIRQ_callback_none,
+ HVMIRQ_callback_gsi,
+ HVMIRQ_callback_pci_intx
+ } callback_via_type;
+ union {
+ unsigned int gsi;
+ struct { uint8_t dev, intx; } pci;
+ } callback_via;
/*
* PCI-ISA interrupt router.
@@ -105,7 +113,7 @@ void hvm_isa_irq_deassert(
void hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq);
void hvm_set_callback_irq_level(void);
-void hvm_set_callback_gsi(struct domain *d, unsigned int gsi);
+void hvm_set_callback_via(struct domain *d, uint64_t via);
int cpu_get_interrupt(struct vcpu *v, int *type);
int cpu_has_pending_irq(struct vcpu *v);
diff --git a/xen/include/asm-x86/x86_32/kexec.h b/xen/include/asm-x86/x86_32/kexec.h
index aa6db02088..cb4ada715e 100644
--- a/xen/include/asm-x86/x86_32/kexec.h
+++ b/xen/include/asm-x86/x86_32/kexec.h
@@ -10,7 +10,6 @@
#include <xen/types.h>
#include <xen/kexec.h>
-#include <asm/fixmap.h>
typedef asmlinkage void (*relocate_new_kernel_t)(
unsigned long indirection_page,
diff --git a/xen/include/asm-x86/x86_64/kexec.h b/xen/include/asm-x86/x86_64/kexec.h
index b9779aa9d7..c54dbb9ba6 100644
--- a/xen/include/asm-x86/x86_64/kexec.h
+++ b/xen/include/asm-x86/x86_64/kexec.h
@@ -10,7 +10,6 @@
#include <xen/types.h>
#include <xen/kexec.h>
-#include <asm/fixmap.h>
typedef void (*relocate_new_kernel_t)(
unsigned long indirection_page,
diff --git a/xen/include/asm-x86/x86_emulate.h b/xen/include/asm-x86/x86_emulate.h
index e1d6f1d50d..45246b8044 100644
--- a/xen/include/asm-x86/x86_emulate.h
+++ b/xen/include/asm-x86/x86_emulate.h
@@ -3,7 +3,21 @@
*
* Generic x86 (32-bit and 64-bit) instruction decoder and emulator.
*
- * Copyright (c) 2005 Keir Fraser
+ * Copyright (c) 2005-2007 Keir Fraser
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __X86_EMULATE_H__
@@ -136,8 +150,11 @@ struct x86_emulate_ctxt
/* Register state before/after emulation. */
struct cpu_user_regs *regs;
- /* Default address size in current execution mode (2, 4, or 8). */
- int address_bytes;
+ /* Default address size in current execution mode (16, 32, or 64). */
+ unsigned int addr_size;
+
+ /* Stack pointer width in bits (16, 32 or 64). */
+ unsigned int sp_size;
};
/*
diff --git a/xen/include/public/elfnote.h b/xen/include/public/elfnote.h
index 4924767d30..3d9b988dca 100644
--- a/xen/include/public/elfnote.h
+++ b/xen/include/public/elfnote.h
@@ -40,8 +40,6 @@
/*
* NAME=VALUE pair (string).
- *
- * LEGACY: FEATURES and PAE
*/
#define XEN_ELFNOTE_INFO 0
@@ -108,7 +106,12 @@
#define XEN_ELFNOTE_LOADER 8
/*
- * The kernel supports PAE (x86/32 only, string = "yes" or "no").
+ * The kernel supports PAE (x86/32 only, string = "yes", "no" or
+ * "bimodal").
+ *
+ * For compatibility with Xen 3.0.3 and earlier the "bimodal" setting
+ * may be given as "yes,bimodal" which will cause older Xen to treat
+ * this kernel as PAE.
*
* LEGACY: PAE (n.b. The legacy interface included a provision to
* indicate 'extended-cr3' support allowing L3 page tables to be
diff --git a/xen/include/public/hvm/params.h b/xen/include/public/hvm/params.h
index caa1f1f545..c3a87163e4 100644
--- a/xen/include/public/hvm/params.h
+++ b/xen/include/public/hvm/params.h
@@ -24,13 +24,33 @@
#include "hvm_op.h"
-/* Parameter space for HVMOP_{set,get}_param. */
+/*
+ * Parameter space for HVMOP_{set,get}_param.
+ */
+
+/*
+ * How should CPU0 event-channel notifications be delivered?
+ * val[63:56] == 0: val[55:0] is a delivery GSI (Global System Interrupt).
+ * val[63:56] == 1: val[55:0] is a delivery PCI INTx line, as follows:
+ * Domain = val[47:32], Bus = val[31:16],
+ * DevFn = val[15: 8], IntX = val[ 1: 0]
+ * If val == 0 then CPU0 event-channel notifications are not delivered.
+ */
#define HVM_PARAM_CALLBACK_IRQ 0
+
+/*
+ * These are not used by Xen. They are here for convenience of HVM-guest
+ * xenbus implementations.
+ */
#define HVM_PARAM_STORE_PFN 1
#define HVM_PARAM_STORE_EVTCHN 2
+
#define HVM_PARAM_PAE_ENABLED 4
+
#define HVM_PARAM_IOREQ_PFN 5
+
#define HVM_PARAM_BUFIOREQ_PFN 6
+
#define HVM_NR_PARAMS 7
#endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
diff --git a/xen/include/xen/byteorder/big_endian.h b/xen/include/xen/byteorder/big_endian.h
new file mode 100644
index 0000000000..8a815534e4
--- /dev/null
+++ b/xen/include/xen/byteorder/big_endian.h
@@ -0,0 +1,106 @@
+#ifndef __XEN_BYTEORDER_BIG_ENDIAN_H__
+#define __XEN_BYTEORDER_BIG_ENDIAN_H__
+
+#ifndef __BIG_ENDIAN
+#define __BIG_ENDIAN 4321
+#endif
+#ifndef __BIG_ENDIAN_BITFIELD
+#define __BIG_ENDIAN_BITFIELD
+#endif
+
+#include <xen/types.h>
+#include <xen/byteorder/swab.h>
+
+#define __constant_htonl(x) ((__force __be32)(__u32)(x))
+#define __constant_ntohl(x) ((__force __u32)(__be32)(x))
+#define __constant_htons(x) ((__force __be16)(__u16)(x))
+#define __constant_ntohs(x) ((__force __u16)(__be16)(x))
+#define __constant_cpu_to_le64(x) ((__force __le64)___constant_swab64((x)))
+#define __constant_le64_to_cpu(x) ___constant_swab64((__force __u64)(__le64)(x))
+#define __constant_cpu_to_le32(x) ((__force __le32)___constant_swab32((x)))
+#define __constant_le32_to_cpu(x) ___constant_swab32((__force __u32)(__le32)(x))
+#define __constant_cpu_to_le16(x) ((__force __le16)___constant_swab16((x)))
+#define __constant_le16_to_cpu(x) ___constant_swab16((__force __u16)(__le16)(x))
+#define __constant_cpu_to_be64(x) ((__force __be64)(__u64)(x))
+#define __constant_be64_to_cpu(x) ((__force __u64)(__be64)(x))
+#define __constant_cpu_to_be32(x) ((__force __be32)(__u32)(x))
+#define __constant_be32_to_cpu(x) ((__force __u32)(__be32)(x))
+#define __constant_cpu_to_be16(x) ((__force __be16)(__u16)(x))
+#define __constant_be16_to_cpu(x) ((__force __u16)(__be16)(x))
+#define __cpu_to_le64(x) ((__force __le64)__swab64((x)))
+#define __le64_to_cpu(x) __swab64((__force __u64)(__le64)(x))
+#define __cpu_to_le32(x) ((__force __le32)__swab32((x)))
+#define __le32_to_cpu(x) __swab32((__force __u32)(__le32)(x))
+#define __cpu_to_le16(x) ((__force __le16)__swab16((x)))
+#define __le16_to_cpu(x) __swab16((__force __u16)(__le16)(x))
+#define __cpu_to_be64(x) ((__force __be64)(__u64)(x))
+#define __be64_to_cpu(x) ((__force __u64)(__be64)(x))
+#define __cpu_to_be32(x) ((__force __be32)(__u32)(x))
+#define __be32_to_cpu(x) ((__force __u32)(__be32)(x))
+#define __cpu_to_be16(x) ((__force __be16)(__u16)(x))
+#define __be16_to_cpu(x) ((__force __u16)(__be16)(x))
+
+static inline __le64 __cpu_to_le64p(const __u64 *p)
+{
+ return (__force __le64)__swab64p(p);
+}
+static inline __u64 __le64_to_cpup(const __le64 *p)
+{
+ return __swab64p((__u64 *)p);
+}
+static inline __le32 __cpu_to_le32p(const __u32 *p)
+{
+ return (__force __le32)__swab32p(p);
+}
+static inline __u32 __le32_to_cpup(const __le32 *p)
+{
+ return __swab32p((__u32 *)p);
+}
+static inline __le16 __cpu_to_le16p(const __u16 *p)
+{
+ return (__force __le16)__swab16p(p);
+}
+static inline __u16 __le16_to_cpup(const __le16 *p)
+{
+ return __swab16p((__u16 *)p);
+}
+static inline __be64 __cpu_to_be64p(const __u64 *p)
+{
+ return (__force __be64)*p;
+}
+static inline __u64 __be64_to_cpup(const __be64 *p)
+{
+ return (__force __u64)*p;
+}
+static inline __be32 __cpu_to_be32p(const __u32 *p)
+{
+ return (__force __be32)*p;
+}
+static inline __u32 __be32_to_cpup(const __be32 *p)
+{
+ return (__force __u32)*p;
+}
+static inline __be16 __cpu_to_be16p(const __u16 *p)
+{
+ return (__force __be16)*p;
+}
+static inline __u16 __be16_to_cpup(const __be16 *p)
+{
+ return (__force __u16)*p;
+}
+#define __cpu_to_le64s(x) __swab64s((x))
+#define __le64_to_cpus(x) __swab64s((x))
+#define __cpu_to_le32s(x) __swab32s((x))
+#define __le32_to_cpus(x) __swab32s((x))
+#define __cpu_to_le16s(x) __swab16s((x))
+#define __le16_to_cpus(x) __swab16s((x))
+#define __cpu_to_be64s(x) do {} while (0)
+#define __be64_to_cpus(x) do {} while (0)
+#define __cpu_to_be32s(x) do {} while (0)
+#define __be32_to_cpus(x) do {} while (0)
+#define __cpu_to_be16s(x) do {} while (0)
+#define __be16_to_cpus(x) do {} while (0)
+
+#include <xen/byteorder/generic.h>
+
+#endif /* __XEN_BYTEORDER_BIG_ENDIAN_H__ */
diff --git a/xen/include/xen/byteorder/generic.h b/xen/include/xen/byteorder/generic.h
new file mode 100644
index 0000000000..8a0006b755
--- /dev/null
+++ b/xen/include/xen/byteorder/generic.h
@@ -0,0 +1,68 @@
+#ifndef __XEN_BYTEORDER_GENERIC_H__
+#define __XEN_BYTEORDER_GENERIC_H__
+
+/*
+ * Generic Byte-reordering support
+ *
+ * The "... p" macros, like le64_to_cpup, can be used with pointers
+ * to unaligned data, but there will be a performance penalty on
+ * some architectures. Use get_unaligned for unaligned data.
+ *
+ * The following macros are to be defined by <asm/byteorder.h>:
+ *
+ * Conversion of XX-bit integers (16- 32- or 64-)
+ * between native CPU format and little/big endian format
+ * 64-bit stuff only defined for proper architectures
+ * cpu_to_[bl]eXX(__uXX x)
+ * [bl]eXX_to_cpu(__uXX x)
+ *
+ * The same, but takes a pointer to the value to convert
+ * cpu_to_[bl]eXXp(__uXX x)
+ * [bl]eXX_to_cpup(__uXX x)
+ *
+ * The same, but change in situ
+ * cpu_to_[bl]eXXs(__uXX x)
+ * [bl]eXX_to_cpus(__uXX x)
+ *
+ * See asm-foo/byteorder.h for examples of how to provide
+ * architecture-optimized versions
+ */
+
+#define cpu_to_le64 __cpu_to_le64
+#define le64_to_cpu __le64_to_cpu
+#define cpu_to_le32 __cpu_to_le32
+#define le32_to_cpu __le32_to_cpu
+#define cpu_to_le16 __cpu_to_le16
+#define le16_to_cpu __le16_to_cpu
+#define cpu_to_be64 __cpu_to_be64
+#define be64_to_cpu __be64_to_cpu
+#define cpu_to_be32 __cpu_to_be32
+#define be32_to_cpu __be32_to_cpu
+#define cpu_to_be16 __cpu_to_be16
+#define be16_to_cpu __be16_to_cpu
+#define cpu_to_le64p __cpu_to_le64p
+#define le64_to_cpup __le64_to_cpup
+#define cpu_to_le32p __cpu_to_le32p
+#define le32_to_cpup __le32_to_cpup
+#define cpu_to_le16p __cpu_to_le16p
+#define le16_to_cpup __le16_to_cpup
+#define cpu_to_be64p __cpu_to_be64p
+#define be64_to_cpup __be64_to_cpup
+#define cpu_to_be32p __cpu_to_be32p
+#define be32_to_cpup __be32_to_cpup
+#define cpu_to_be16p __cpu_to_be16p
+#define be16_to_cpup __be16_to_cpup
+#define cpu_to_le64s __cpu_to_le64s
+#define le64_to_cpus __le64_to_cpus
+#define cpu_to_le32s __cpu_to_le32s
+#define le32_to_cpus __le32_to_cpus
+#define cpu_to_le16s __cpu_to_le16s
+#define le16_to_cpus __le16_to_cpus
+#define cpu_to_be64s __cpu_to_be64s
+#define be64_to_cpus __be64_to_cpus
+#define cpu_to_be32s __cpu_to_be32s
+#define be32_to_cpus __be32_to_cpus
+#define cpu_to_be16s __cpu_to_be16s
+#define be16_to_cpus __be16_to_cpus
+
+#endif /* __XEN_BYTEORDER_GENERIC_H__ */
diff --git a/xen/include/xen/byteorder/little_endian.h b/xen/include/xen/byteorder/little_endian.h
new file mode 100644
index 0000000000..24ac42701e
--- /dev/null
+++ b/xen/include/xen/byteorder/little_endian.h
@@ -0,0 +1,106 @@
+#ifndef __XEN_BYTEORDER_LITTLE_ENDIAN_H__
+#define __XEN_BYTEORDER_LITTLE_ENDIAN_H__
+
+#ifndef __LITTLE_ENDIAN
+#define __LITTLE_ENDIAN 1234
+#endif
+#ifndef __LITTLE_ENDIAN_BITFIELD
+#define __LITTLE_ENDIAN_BITFIELD
+#endif
+
+#include <xen/types.h>
+#include <xen/byteorder/swab.h>
+
+#define __constant_htonl(x) ((__force __be32)___constant_swab32((x)))
+#define __constant_ntohl(x) ___constant_swab32((__force __be32)(x))
+#define __constant_htons(x) ((__force __be16)___constant_swab16((x)))
+#define __constant_ntohs(x) ___constant_swab16((__force __be16)(x))
+#define __constant_cpu_to_le64(x) ((__force __le64)(__u64)(x))
+#define __constant_le64_to_cpu(x) ((__force __u64)(__le64)(x))
+#define __constant_cpu_to_le32(x) ((__force __le32)(__u32)(x))
+#define __constant_le32_to_cpu(x) ((__force __u32)(__le32)(x))
+#define __constant_cpu_to_le16(x) ((__force __le16)(__u16)(x))
+#define __constant_le16_to_cpu(x) ((__force __u16)(__le16)(x))
+#define __constant_cpu_to_be64(x) ((__force __be64)___constant_swab64((x)))
+#define __constant_be64_to_cpu(x) ___constant_swab64((__force __u64)(__be64)(x))
+#define __constant_cpu_to_be32(x) ((__force __be32)___constant_swab32((x)))
+#define __constant_be32_to_cpu(x) ___constant_swab32((__force __u32)(__be32)(x))
+#define __constant_cpu_to_be16(x) ((__force __be16)___constant_swab16((x)))
+#define __constant_be16_to_cpu(x) ___constant_swab16((__force __u16)(__be16)(x))
+#define __cpu_to_le64(x) ((__force __le64)(__u64)(x))
+#define __le64_to_cpu(x) ((__force __u64)(__le64)(x))
+#define __cpu_to_le32(x) ((__force __le32)(__u32)(x))
+#define __le32_to_cpu(x) ((__force __u32)(__le32)(x))
+#define __cpu_to_le16(x) ((__force __le16)(__u16)(x))
+#define __le16_to_cpu(x) ((__force __u16)(__le16)(x))
+#define __cpu_to_be64(x) ((__force __be64)__swab64((x)))
+#define __be64_to_cpu(x) __swab64((__force __u64)(__be64)(x))
+#define __cpu_to_be32(x) ((__force __be32)__swab32((x)))
+#define __be32_to_cpu(x) __swab32((__force __u32)(__be32)(x))
+#define __cpu_to_be16(x) ((__force __be16)__swab16((x)))
+#define __be16_to_cpu(x) __swab16((__force __u16)(__be16)(x))
+
+static inline __le64 __cpu_to_le64p(const __u64 *p)
+{
+ return (__force __le64)*p;
+}
+static inline __u64 __le64_to_cpup(const __le64 *p)
+{
+ return (__force __u64)*p;
+}
+static inline __le32 __cpu_to_le32p(const __u32 *p)
+{
+ return (__force __le32)*p;
+}
+static inline __u32 __le32_to_cpup(const __le32 *p)
+{
+ return (__force __u32)*p;
+}
+static inline __le16 __cpu_to_le16p(const __u16 *p)
+{
+ return (__force __le16)*p;
+}
+static inline __u16 __le16_to_cpup(const __le16 *p)
+{
+ return (__force __u16)*p;
+}
+static inline __be64 __cpu_to_be64p(const __u64 *p)
+{
+ return (__force __be64)__swab64p(p);
+}
+static inline __u64 __be64_to_cpup(const __be64 *p)
+{
+ return __swab64p((__u64 *)p);
+}
+static inline __be32 __cpu_to_be32p(const __u32 *p)
+{
+ return (__force __be32)__swab32p(p);
+}
+static inline __u32 __be32_to_cpup(const __be32 *p)
+{
+ return __swab32p((__u32 *)p);
+}
+static inline __be16 __cpu_to_be16p(const __u16 *p)
+{
+ return (__force __be16)__swab16p(p);
+}
+static inline __u16 __be16_to_cpup(const __be16 *p)
+{
+ return __swab16p((__u16 *)p);
+}
+#define __cpu_to_le64s(x) do {} while (0)
+#define __le64_to_cpus(x) do {} while (0)
+#define __cpu_to_le32s(x) do {} while (0)
+#define __le32_to_cpus(x) do {} while (0)
+#define __cpu_to_le16s(x) do {} while (0)
+#define __le16_to_cpus(x) do {} while (0)
+#define __cpu_to_be64s(x) __swab64s((x))
+#define __be64_to_cpus(x) __swab64s((x))
+#define __cpu_to_be32s(x) __swab32s((x))
+#define __be32_to_cpus(x) __swab32s((x))
+#define __cpu_to_be16s(x) __swab16s((x))
+#define __be16_to_cpus(x) __swab16s((x))
+
+#include <xen/byteorder/generic.h>
+
+#endif /* __XEN_BYTEORDER_LITTLE_ENDIAN_H__ */
diff --git a/xen/include/xen/byteorder/swab.h b/xen/include/xen/byteorder/swab.h
new file mode 100644
index 0000000000..0193ff83e7
--- /dev/null
+++ b/xen/include/xen/byteorder/swab.h
@@ -0,0 +1,185 @@
+#ifndef __XEN_BYTEORDER_SWAB_H__
+#define __XEN_BYTEORDER_SWAB_H__
+
+/*
+ * Byte-swapping, independently from CPU endianness
+ * swabXX[ps]?(foo)
+ *
+ * Francois-Rene Rideau <fare@tunes.org> 19971205
+ * separated swab functions from cpu_to_XX,
+ * to clean up support for bizarre-endian architectures.
+ */
+
+#include <xen/compiler.h>
+
+/* casts are necessary for constants, because we never know how for sure
+ * how U/UL/ULL map to __u16, __u32, __u64. At least not in a portable way.
+ */
+#define ___swab16(x) \
+({ \
+ __u16 __x = (x); \
+ ((__u16)( \
+ (((__u16)(__x) & (__u16)0x00ffU) << 8) | \
+ (((__u16)(__x) & (__u16)0xff00U) >> 8) )); \
+})
+
+#define ___swab32(x) \
+({ \
+ __u32 __x = (x); \
+ ((__u32)( \
+ (((__u32)(__x) & (__u32)0x000000ffUL) << 24) | \
+ (((__u32)(__x) & (__u32)0x0000ff00UL) << 8) | \
+ (((__u32)(__x) & (__u32)0x00ff0000UL) >> 8) | \
+ (((__u32)(__x) & (__u32)0xff000000UL) >> 24) )); \
+})
+
+#define ___swab64(x) \
+({ \
+ __u64 __x = (x); \
+ ((__u64)( \
+ (__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) | \
+ (__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) | \
+ (__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) | \
+ (__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) << 8) | \
+ (__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >> 8) | \
+ (__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) | \
+ (__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) | \
+ (__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56) )); \
+})
+
+#define ___constant_swab16(x) \
+ ((__u16)( \
+ (((__u16)(x) & (__u16)0x00ffU) << 8) | \
+ (((__u16)(x) & (__u16)0xff00U) >> 8) ))
+#define ___constant_swab32(x) \
+ ((__u32)( \
+ (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \
+ (((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \
+ (((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \
+ (((__u32)(x) & (__u32)0xff000000UL) >> 24) ))
+#define ___constant_swab64(x) \
+ ((__u64)( \
+ (__u64)(((__u64)(x) & (__u64)0x00000000000000ffULL) << 56) | \
+ (__u64)(((__u64)(x) & (__u64)0x000000000000ff00ULL) << 40) | \
+ (__u64)(((__u64)(x) & (__u64)0x0000000000ff0000ULL) << 24) | \
+ (__u64)(((__u64)(x) & (__u64)0x00000000ff000000ULL) << 8) | \
+ (__u64)(((__u64)(x) & (__u64)0x000000ff00000000ULL) >> 8) | \
+ (__u64)(((__u64)(x) & (__u64)0x0000ff0000000000ULL) >> 24) | \
+ (__u64)(((__u64)(x) & (__u64)0x00ff000000000000ULL) >> 40) | \
+ (__u64)(((__u64)(x) & (__u64)0xff00000000000000ULL) >> 56) ))
+
+/*
+ * provide defaults when no architecture-specific optimization is detected
+ */
+#ifndef __arch__swab16
+# define __arch__swab16(x) ({ __u16 __tmp = (x) ; ___swab16(__tmp); })
+#endif
+#ifndef __arch__swab32
+# define __arch__swab32(x) ({ __u32 __tmp = (x) ; ___swab32(__tmp); })
+#endif
+#ifndef __arch__swab64
+# define __arch__swab64(x) ({ __u64 __tmp = (x) ; ___swab64(__tmp); })
+#endif
+
+#ifndef __arch__swab16p
+# define __arch__swab16p(x) __arch__swab16(*(x))
+#endif
+#ifndef __arch__swab32p
+# define __arch__swab32p(x) __arch__swab32(*(x))
+#endif
+#ifndef __arch__swab64p
+# define __arch__swab64p(x) __arch__swab64(*(x))
+#endif
+
+#ifndef __arch__swab16s
+# define __arch__swab16s(x) do { *(x) = __arch__swab16p((x)); } while (0)
+#endif
+#ifndef __arch__swab32s
+# define __arch__swab32s(x) do { *(x) = __arch__swab32p((x)); } while (0)
+#endif
+#ifndef __arch__swab64s
+# define __arch__swab64s(x) do { *(x) = __arch__swab64p((x)); } while (0)
+#endif
+
+
+/*
+ * Allow constant folding
+ */
+#if defined(__GNUC__) && defined(__OPTIMIZE__)
+# define __swab16(x) \
+(__builtin_constant_p((__u16)(x)) ? \
+ ___swab16((x)) : \
+ __fswab16((x)))
+# define __swab32(x) \
+(__builtin_constant_p((__u32)(x)) ? \
+ ___swab32((x)) : \
+ __fswab32((x)))
+# define __swab64(x) \
+(__builtin_constant_p((__u64)(x)) ? \
+ ___swab64((x)) : \
+ __fswab64((x)))
+#else
+# define __swab16(x) __fswab16(x)
+# define __swab32(x) __fswab32(x)
+# define __swab64(x) __fswab64(x)
+#endif /* OPTIMIZE */
+
+
+static inline __attribute_const__ __u16 __fswab16(__u16 x)
+{
+ return __arch__swab16(x);
+}
+static inline __u16 __swab16p(const __u16 *x)
+{
+ return __arch__swab16p(x);
+}
+static inline void __swab16s(__u16 *addr)
+{
+ __arch__swab16s(addr);
+}
+
+static inline __attribute_const__ __u32 __fswab32(__u32 x)
+{
+ return __arch__swab32(x);
+}
+static inline __u32 __swab32p(const __u32 *x)
+{
+ return __arch__swab32p(x);
+}
+static inline void __swab32s(__u32 *addr)
+{
+ __arch__swab32s(addr);
+}
+
+#ifdef __BYTEORDER_HAS_U64__
+static inline __attribute_const__ __u64 __fswab64(__u64 x)
+{
+# ifdef __SWAB_64_THRU_32__
+ __u32 h = x >> 32;
+ __u32 l = x & ((1ULL<<32)-1);
+ return (((__u64)__swab32(l)) << 32) | ((__u64)(__swab32(h)));
+# else
+ return __arch__swab64(x);
+# endif
+}
+static inline __u64 __swab64p(const __u64 *x)
+{
+ return __arch__swab64p(x);
+}
+static inline void __swab64s(__u64 *addr)
+{
+ __arch__swab64s(addr);
+}
+#endif /* __BYTEORDER_HAS_U64__ */
+
+#define swab16 __swab16
+#define swab32 __swab32
+#define swab64 __swab64
+#define swab16p __swab16p
+#define swab32p __swab32p
+#define swab64p __swab64p
+#define swab16s __swab16s
+#define swab32s __swab32s
+#define swab64s __swab64s
+
+#endif /* __XEN_BYTEORDER_SWAB_H__ */
diff --git a/xen/include/xen/config.h b/xen/include/xen/config.h
index 068a550078..02e292b6d7 100644
--- a/xen/include/xen/config.h
+++ b/xen/include/xen/config.h
@@ -63,6 +63,8 @@
/* Linux 'checker' project. */
#define __iomem
#define __user
+#define __force
+#define __bitwise
#ifndef __ASSEMBLY__
diff --git a/xen/include/xen/elfcore.h b/xen/include/xen/elfcore.h
index 75ce7c49ef..fbe8ed1a6a 100644
--- a/xen/include/xen/elfcore.h
+++ b/xen/include/xen/elfcore.h
@@ -56,49 +56,6 @@ typedef struct
int pr_fpvalid; /* True if math co-processor being used. */
} ELF_Prstatus;
-/*
- * The following data structures provide 64-bit ELF notes. In theory it should
- * be possible to support both 64-bit and 32-bit ELF files, but to keep it
- * simple we only do 64-bit.
- *
- * Please note that the current code aligns the 64-bit notes in the same
- * way as Linux does. We are not following the 64-bit ELF spec, no one does.
- *
- * We are avoiding two problems by restricting us to 64-bit notes only:
- * - Alignment of notes change with the word size. Ick.
- * - We would need to tell kexec-tools which format we are using in the
- * hypervisor to make sure the right ELF format is generated.
- * That requires infrastructure. Let's not.
- */
-
-#define NOTE_ALIGN(x, n) ((x + ((1 << n) - 1)) / (1 << n))
-#define PAD32(x) u32 pad_data[NOTE_ALIGN(x, 2)]
-
-#define TYPEDEF_NOTE(type, strlen, desctype) \
- typedef struct { \
- union { \
- struct { \
- Elf_Note note; \
- unsigned char name[strlen]; \
- } note; \
- PAD32(sizeof(Elf_Note) + strlen); \
- } note; \
- union { \
- desctype desc; \
- PAD32(sizeof(desctype)); \
- } desc; \
- } __attribute__ ((packed)) type
-
-#define CORE_STR "CORE"
-#define CORE_STR_LEN 5 /* including terminating zero */
-
-TYPEDEF_NOTE(crash_note_core_t, CORE_STR_LEN, ELF_Prstatus);
-
-#define XEN_STR "Xen"
-#define XEN_STR_LEN 4 /* including terminating zero */
-
-TYPEDEF_NOTE(crash_note_xen_core_t, XEN_STR_LEN, crash_xen_core_t);
-
typedef struct {
unsigned long xen_major_version;
unsigned long xen_minor_version;
@@ -113,20 +70,6 @@ typedef struct {
#endif
} crash_xen_info_t;
-TYPEDEF_NOTE(crash_note_xen_info_t, XEN_STR_LEN, crash_xen_info_t);
-
-typedef struct {
- crash_note_core_t core;
- crash_note_xen_core_t xen_regs;
- crash_note_xen_info_t xen_info;
-} __attribute__ ((packed)) crash_note_t;
-
-#define setup_crash_note(np, member, str, str_len, id) \
- np->member.note.note.note.namesz = str_len; \
- np->member.note.note.note.descsz = sizeof(np->member.desc.desc); \
- np->member.note.note.note.type = id; \
- memcpy(np->member.note.note.name, str, str_len)
-
#endif /* __ELFCOREC_H__ */
/*
diff --git a/xen/include/xen/types.h b/xen/include/xen/types.h
index 8bafc73156..fd89c98427 100644
--- a/xen/include/xen/types.h
+++ b/xen/include/xen/types.h
@@ -51,4 +51,11 @@ typedef __s64 int64_t;
struct domain;
struct vcpu;
+typedef __u16 __le16;
+typedef __u16 __be16;
+typedef __u32 __le32;
+typedef __u32 __be32;
+typedef __u64 __le64;
+typedef __u64 __be64;
+
#endif /* __TYPES_H__ */
diff --git a/xen/tools/compat-build-header.py b/xen/tools/compat-build-header.py
new file mode 100755
index 0000000000..6fb795eaaa
--- /dev/null
+++ b/xen/tools/compat-build-header.py
@@ -0,0 +1,21 @@
+#!/usr/bin/python
+
+import re,sys
+
+pats = [
+ [ r"__InClUdE__", r"#include" ],
+ [ r"\"xen-compat.h\"", r"<public/xen-compat.h>" ],
+ [ r"(struct|union|enum)\s+(xen_?)?(\w)", r"\1 compat_\3" ],
+ [ r"@KeeP@", r"" ],
+ [ r"_t([^\w]|$)", r"_compat_t\1" ],
+ [ r"(8|16|32|64)_compat_t([^\w]|$)", r"\1_t\2" ],
+ [ r"(^|[^\w])xen_?(\w*)_compat_t([^\w]|$$)", r"\1compat_\2_t\3" ],
+ [ r"(^|[^\w])XEN_?", r"\1COMPAT_" ],
+ [ r"(^|[^\w])Xen_?", r"\1Compat_" ],
+ [ r"(^|[^\w])long([^\w]|$$)", r"\1int\2" ]
+];
+
+for line in sys.stdin.readlines():
+ for pat in pats:
+ line = re.subn(pat[0], pat[1], line)[0]
+ print line.rstrip()
diff --git a/xen/tools/compat-build-source.py b/xen/tools/compat-build-source.py
new file mode 100755
index 0000000000..449e738188
--- /dev/null
+++ b/xen/tools/compat-build-source.py
@@ -0,0 +1,27 @@
+#!/usr/bin/python
+
+import re,sys
+
+pats = [
+ [ r"^\s*#\s*include\s+", r"__InClUdE__ " ],
+ [ r"^\s*#\s*define\s+([A-Z_]*_GUEST_HANDLE)", r"#define HIDE_\1" ],
+ [ r"^\s*#\s*define\s+([a-z_]*_guest_handle)", r"#define hide_\1" ],
+ [ r"XEN_GUEST_HANDLE(_[0-9A-Fa-f]+)?", r"COMPAT_HANDLE" ],
+];
+
+xlats = []
+
+xlatf = open('xlat.lst', 'r')
+for line in xlatf.readlines():
+ match = re.subn(r"^\s*\?\s+(\w*)\s.*", r"\1", line.rstrip())
+ if match[1]:
+ xlats.append(match[0])
+xlatf.close()
+
+for line in sys.stdin.readlines():
+ for pat in pats:
+ line = re.subn(pat[0], pat[1], line)[0]
+ for xlat in xlats:
+ line = re.subn(r"(struct|union)\s+(%s|xen_%s)\s+(\w)" % (xlat, xlat),
+ r"\1 @KeeP@\2 \3", line.rstrip())[0]
+ print line.rstrip()
diff --git a/xen/tools/get-fields.sh b/xen/tools/get-fields.sh
index 01af5eaaf3..ccf5675c02 100644
--- a/xen/tools/get-fields.sh
+++ b/xen/tools/get-fields.sh
@@ -1,7 +1,10 @@
-#!/bin/sh
+#!/bin/bash
test -n "$1" -a -n "$2" -a -n "$3"
set -ef
+SED=sed
+[ -x /usr/xpg4/bin/sed ] && SED=/usr/xpg4/bin/sed
+
get_fields() {
local level=1 aggr=0 name= fields=
for token in $2
@@ -90,11 +93,15 @@ handle_field() {
then
echo -n "$1(_d_)->$3 = (_s_)->$3;"
else
- echo -n "$1XLAT_${2}_HNDL_$(echo $3 | sed 's,\.,_,g')(_d_, _s_);"
+ echo -n "$1XLAT_${2}_HNDL_$(echo $3 | $SED 's,\.,_,g')(_d_, _s_);"
fi
- elif [ -z "$(echo "$5" | sed 's,[^{}],,g')" ]
+ elif [ -z "$(echo "$5" | $SED 's,[^{}],,g')" ]
then
- local tag=$(echo "$5" | sed 's,[[:space:]]*\(struct\|union\)[[:space:]]\+\(compat_\)\?\([[:alnum:]_]\+\)[[:space:]].*,\3,')
+ local tag=$(echo "$5" | python -c '
+import re,sys
+for line in sys.stdin.readlines():
+ print re.subn(r"\s*(struct|union)\s+(compat_)?(\w+)\s.*", r"\3", line)[0].rstrip()
+')
echo " \\"
echo -n "${1}XLAT_$tag(&(_d_)->$3, &(_s_)->$3);"
else
@@ -104,13 +111,13 @@ handle_field() {
case "$token" in
struct|union)
test $level != 2 || fields=" "
- if [ $level == 1 ]
+ if [ $level = 1 ]
then
kind=$token
if [ $kind = union ]
then
echo " \\"
- echo -n "${1}switch ($(echo $3 | sed 's,\.,_,g')) {"
+ echo -n "${1}switch ($(echo $3 | $SED 's,\.,_,g')) {"
fi
fi
;;
@@ -119,7 +126,7 @@ handle_field() {
;;
"}")
level=$(expr $level - 1) id=
- if [ $level == 1 -a $kind = union ]
+ if [ $level = 1 -a $kind = union ]
then
echo " \\"
echo -n "$1}"
@@ -141,7 +148,7 @@ handle_field() {
arrlvl=$(expr $arrlvl - 1)
;;
COMPAT_HANDLE\(*\))
- if [ $level == 2 -a -z "$id" ]
+ if [ $level = 2 -a -z "$id" ]
then
type=${token#COMPAT_HANDLE?}
type=${type%?}
@@ -149,7 +156,7 @@ handle_field() {
fi
;;
compat_domain_handle_t)
- if [ $level == 2 -a -z "$id" ]
+ if [ $level = 2 -a -z "$id" ]
then
array_type=$token
fi
@@ -158,12 +165,12 @@ handle_field() {
id=$token
;;
[\,\;])
- if [ $level == 2 -a -n "$(echo $id | sed 's,^_pad[[:digit:]]*,,')" ]
+ if [ $level = 2 -a -n "$(echo $id | $SED 's,^_pad[[:digit:]]*,,')" ]
then
if [ $kind = union ]
then
echo " \\"
- echo -n "${1}case XLAT_${2}_$(echo $3.$id | sed 's,\.,_,g'):"
+ echo -n "${1}case XLAT_${2}_$(echo $3.$id | $SED 's,\.,_,g'):"
handle_field "$1 " $2 $3.$id "$type" "$fields"
elif [ -z "$array" -a -z "$array_type" ]
then
@@ -202,7 +209,7 @@ copy_array() {
}
handle_array() {
- local i="i$(echo $4 | sed 's,[^;], ,g' | wc -w)"
+ local i="i$(echo $4 | $SED 's,[^;], ,g' | wc -w | $SED 's,[[:space:]]*,,g')"
echo " \\"
echo "$1{ \\"
echo "$1 unsigned int $i; \\"
@@ -250,7 +257,7 @@ build_body() {
arrlvl=$(expr $arrlvl - 1)
;;
COMPAT_HANDLE\(*\))
- if [ $level == 2 -a -z "$id" ]
+ if [ $level = 2 -a -z "$id" ]
then
type=${token#COMPAT_HANDLE?}
type=${type%?}
@@ -258,7 +265,7 @@ build_body() {
fi
;;
compat_domain_handle_t)
- if [ $level == 2 -a -z "$id" ]
+ if [ $level = 2 -a -z "$id" ]
then
array_type=$token
fi
@@ -272,7 +279,7 @@ build_body() {
fi
;;
[\,\;])
- if [ $level == 2 -a -n "$(echo $id | sed 's,^_pad[[:digit:]]*,,')" ]
+ if [ $level = 2 -a -n "$(echo $id | $SED 's,^_pad[[:digit:]]*,,')" ]
then
if [ -z "$array" -a -z "$array_type" ]
then
@@ -300,10 +307,10 @@ build_body() {
}
check_field() {
- if [ -z "$(echo "$4" | sed 's,[^{}],,g')" ]
+ if [ -z "$(echo "$4" | $SED 's,[^{}],,g')" ]
then
echo "; \\"
- local n=$(echo $3 | sed 's,[^.], ,g' | wc -w)
+ local n=$(echo $3 | $SED 's,[^.], ,g' | wc -w | $SED 's,[[:space:]]*,,g')
if [ -n "$4" ]
then
for n in $4
@@ -325,7 +332,7 @@ check_field() {
then
echo -n " CHECK_FIELD_($1, $2, $3)"
else
- echo -n " CHECK_SUBFIELD_${n}_($1, $2, $(echo $3 | sed 's!\.!, !g'))"
+ echo -n " CHECK_SUBFIELD_${n}_($1, $2, $(echo $3 | $SED 's!\.!, !g'))"
fi
else
local level=1 fields= id= token
@@ -345,7 +352,7 @@ check_field() {
id=$token
;;
[\,\;])
- if [ $level == 2 -a -n "$(echo $id | sed 's,^_pad[[:digit:]]*,,')" ]
+ if [ $level = 2 -a -n "$(echo $id | $SED 's,^_pad[[:digit:]]*,,')" ]
then
check_field $1 $2 $3.$id "$fields"
test "$token" != ";" || fields= id=
@@ -365,11 +372,11 @@ build_check() {
do
case "$token" in
struct|union)
- if [ $level == 1 ]
+ if [ $level = 1 ]
then
kind=$token
echo -n " CHECK_SIZE_($kind, $1)"
- elif [ $level == 2 ]
+ elif [ $level = 2 ]
then
fields=" "
fi
@@ -390,7 +397,7 @@ build_check() {
test $level != 2 -o $arrlvl != 1 || id=$token
;;
[\,\;])
- if [ $level == 2 -a -n "$(echo $id | sed 's,^_pad[[:digit:]]*,,')" ]
+ if [ $level = 2 -a -n "$(echo $id | $SED 's,^_pad[[:digit:]]*,,')" ]
then
check_field $kind $1 $id "$fields"
test "$token" != ";" || fields= id=
@@ -402,7 +409,7 @@ build_check() {
echo ""
}
-fields="$(get_fields $(echo $2 | sed 's,^compat_xen,compat_,') "$(sed -e 's,^[[:space:]]#.*,,' -e 's!\([]\[,;:{}]\)! \1 !g' $3)")"
+fields="$(get_fields $(echo $2 | $SED 's,^compat_xen,compat_,') "$($SED -e 's,^[[:space:]]#.*,,' -e 's!\([]\[,;:{}]\)! \1 !g' $3)")"
if [ -z "$fields" ]
then
echo "Fields of '$2' not found in '$3'" >&2