[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [merge] with xen-unstable



# HG changeset patch
# User Christian Limpach <Christian.Limpach@xxxxxxxxxxxxx>
# Date 1169133487 0
# Node ID 8475a4e0425ed158923d9849a8e5a6821e8bdb34
# Parent  3464bb656a9c4428713bdf18b2bfb94e922f9d74
# Parent  8e79d8d87ecd371c3b1881be1fcdccfcdcf50b22
[merge] with xen-unstable
---
 extras/mini-os/minios-x86_32.lds                                   |   45 
 extras/mini-os/minios-x86_64.lds                                   |   54 
 extras/mini-os/x86_32.S                                            |  287 --
 extras/mini-os/x86_64.S                                            |  385 ---
 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/kmap_types.h    |   31 
 patches/linux-2.6.18/ipv6-no-autoconf.patch                        |   18 
 tools/xm-test/lib/XmTestLib/XenManagedDomain.py                    |  177 -
 .hgignore                                                          |    4 
 Makefile                                                           |    9 
 buildconfigs/linux-defconfig_xen0_x86_32                           |    1 
 buildconfigs/linux-defconfig_xenU_x86_32                           |    1 
 buildconfigs/linux-defconfig_xen_x86_32                            |    1 
 docs/man/xm.pod.1                                                  |    3 
 docs/man/xmdomain.cfg.pod.5                                        |   49 
 docs/xen-api/wire-protocol.tex                                     |    2 
 extras/mini-os/Makefile                                            |  160 -
 extras/mini-os/arch/x86/Makefile                                   |   29 
 extras/mini-os/arch/x86/arch.mk                                    |   28 
 extras/mini-os/arch/x86/minios-x86_32.lds                          |   45 
 extras/mini-os/arch/x86/minios-x86_64.lds                          |   54 
 extras/mini-os/arch/x86/x86_32.S                                   |  287 ++
 extras/mini-os/arch/x86/x86_64.S                                   |  385 +++
 extras/mini-os/gnttab.c                                            |   36 
 extras/mini-os/include/hypervisor.h                                |    1 
 extras/mini-os/include/netfront.h                                  |    2 
 extras/mini-os/include/x86/x86_32/hypercall-x86_32.h               |    8 
 extras/mini-os/include/x86/x86_64/hypercall-x86_64.h               |    8 
 extras/mini-os/include/xenbus.h                                    |    3 
 extras/mini-os/kernel.c                                            |   11 
 extras/mini-os/minios.mk                                           |   62 
 extras/mini-os/netfront.c                                          |  455 ++++
 extras/mini-os/xenbus/xenbus.c                                     |   86 
 linux-2.6-xen-sparse/arch/i386/Kconfig                             |    2 
 linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c              |    2 
 linux-2.6-xen-sparse/arch/i386/kernel/pci-dma-xen.c                |   19 
 linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c                    |   74 
 linux-2.6-xen-sparse/arch/i386/mm/fault-xen.c                      |   18 
 linux-2.6-xen-sparse/arch/i386/mm/highmem-xen.c                    |    1 
 linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c                    |   30 
 linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c                 |   16 
 linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c                  |   32 
 linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c                   |   32 
 linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c              |    4 
 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/dma-mapping.h   |    6 
 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgalloc.h       |    2 
 linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/swiotlb.h       |    4 
 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgalloc.h     |   87 
 linux-2.6-xen-sparse/kernel/kexec.c                                |    8 
 patches/linux-2.6.18/series                                        |    1 
 tools/check/check_udev                                             |    4 
 tools/examples/vtpm-common.sh                                      |    4 
 tools/examples/xen-network-common.sh                               |    5 
 tools/examples/xmexample1                                          |   34 
 tools/examples/xmexample2                                          |   34 
 tools/examples/xmexample3                                          |   34 
 tools/libfsimage/common/fsimage.c                                  |    2 
 tools/libfsimage/common/fsimage_grub.c                             |    2 
 tools/libfsimage/common/fsimage_plugin.c                           |    8 
 tools/libfsimage/common/fsimage_plugin.h                           |    5 
 tools/libfsimage/common/mapfile-GNU                                |    3 
 tools/libfsimage/common/mapfile-SunOS                              |    3 
 tools/libfsimage/ext2fs-lib/ext2fs-lib.c                           |    2 
 tools/libxc/xc_hvm_build.c                                         |    3 
 tools/libxc/xc_linux_build.c                                       |    2 
 tools/libxc/xc_linux_restore.c                                     |  207 +-
 tools/libxc/xc_linux_save.c                                        |    7 
 tools/libxc/xc_load_elf.c                                          |   14 
 tools/libxc/xc_ptrace.c                                            |   18 
 tools/pygrub/src/pygrub                                            |  280 +-
 tools/python/xen/xend/XendBootloader.py                            |    6 
 tools/python/xen/xend/XendCheckpoint.py                            |    8 
 tools/python/xen/xend/XendConfig.py                                |   10 
 tools/python/xen/xend/XendDomain.py                                |    8 
 tools/python/xen/xend/XendDomainInfo.py                            |   37 
 tools/python/xen/xend/XendNode.py                                  |   10 
 tools/python/xen/xend/osdep.py                                     |    5 
 tools/python/xen/xend/server/blkif.py                              |    1 
 tools/python/xen/xm/create.py                                      |   20 
 tools/tests/Makefile                                               |   13 
 tools/tests/blowfish.c                                             |  439 ++++
 tools/tests/blowfish.mk                                            |   23 
 tools/tests/test_x86_emulator.c                                    |  134 +
 tools/xenstat/xentop/xentop.c                                      |    2 
 tools/xm-test/README                                               |   43 
 tools/xm-test/configure.ac                                         |    1 
 tools/xm-test/grouptest/xapi                                       |    1 
 tools/xm-test/lib/XmTestLib/DomainTracking.py                      |   61 
 tools/xm-test/lib/XmTestLib/XenAPIDomain.py                        |  176 +
 tools/xm-test/lib/XmTestLib/XenDomain.py                           |   28 
 tools/xm-test/lib/XmTestLib/Xm.py                                  |    2 
 tools/xm-test/lib/XmTestLib/xapi.py                                |   79 
 tools/xm-test/ramdisk/Makefile.am                                  |   13 
 tools/xm-test/ramdisk/skel/etc/init.d/rcS                          |   11 
 tools/xm-test/runtest.sh                                           |    8 
 tools/xm-test/tests/sched-credit/01_sched_credit_weight_cap_pos.py |   33 
 tools/xm-test/tests/vtpm/09_vtpm-xapi.py                           |   99 
 tools/xm-test/tests/xapi/01_xapi-vm_basic.py                       |   61 
 tools/xm-test/tests/xapi/Makefile.am                               |   19 
 unmodified_drivers/linux-2.6/platform-pci/platform-pci.c           |   34 
 unmodified_drivers/linux-2.6/platform-pci/platform-pci.h           |    4 
 xen/arch/ia64/linux-xen/unaligned.c                                |    2 
 xen/arch/ia64/xen/xenmisc.c                                        |    4 
 xen/arch/x86/domain.c                                              |    2 
 xen/arch/x86/hvm/hpet.c                                            |    2 
 xen/arch/x86/hvm/hvm.c                                             |    2 
 xen/arch/x86/hvm/i8254.c                                           |   14 
 xen/arch/x86/hvm/irq.c                                             |  186 +
 xen/arch/x86/hvm/svm/svm.c                                         |    4 
 xen/arch/x86/hvm/vioapic.c                                         |   11 
 xen/arch/x86/hvm/vmx/vmcs.c                                        |    9 
 xen/arch/x86/hvm/vmx/vmx.c                                         |  140 -
 xen/arch/x86/hvm/vmx/x86_32/exits.S                                |   33 
 xen/arch/x86/hvm/vmx/x86_64/exits.S                                |   29 
 xen/arch/x86/microcode.c                                           |    9 
 xen/arch/x86/mm.c                                                  |  116 -
 xen/arch/x86/mm/shadow/common.c                                    |   27 
 xen/arch/x86/mm/shadow/multi.c                                     |    6 
 xen/arch/x86/mm/shadow/private.h                                   |    5 
 xen/arch/x86/oprofile/nmi_int.c                                    |    2 
 xen/arch/x86/setup.c                                               |   25 
 xen/arch/x86/traps.c                                               |   18 
 xen/arch/x86/x86_64/compat/mm.c                                    |   20 
 xen/arch/x86/x86_emulate.c                                         | 1027 
++++++++--
 xen/common/elf.c                                                   |    2 
 xen/common/kexec.c                                                 |  122 -
 xen/common/keyhandler.c                                            |   13 
 xen/common/lib.c                                                   |  644 
++----
 xen/common/symbols.c                                               |    3 
 xen/common/xencomm.c                                               |    4 
 xen/drivers/video/vga.c                                            |   11 
 xen/include/Makefile                                               |   52 
 xen/include/asm-powerpc/byteorder.h                                |   80 
 xen/include/asm-x86/byteorder.h                                    |   36 
 xen/include/asm-x86/guest_access.h                                 |   18 
 xen/include/asm-x86/hvm/irq.h                                      |   16 
 xen/include/asm-x86/x86_32/kexec.h                                 |    1 
 xen/include/asm-x86/x86_64/kexec.h                                 |    1 
 xen/include/asm-x86/x86_emulate.h                                  |   23 
 xen/include/public/elfnote.h                                       |    9 
 xen/include/public/hvm/params.h                                    |   22 
 xen/include/xen/byteorder/big_endian.h                             |  106 +
 xen/include/xen/byteorder/generic.h                                |   68 
 xen/include/xen/byteorder/little_endian.h                          |  106 +
 xen/include/xen/byteorder/swab.h                                   |  185 +
 xen/include/xen/config.h                                           |    2 
 xen/include/xen/elfcore.h                                          |   57 
 xen/include/xen/types.h                                            |    7 
 xen/tools/compat-build-header.py                                   |   21 
 xen/tools/compat-build-source.py                                   |   27 
 xen/tools/get-fields.sh                                            |   53 
 150 files changed, 5874 insertions(+), 2633 deletions(-)

diff -r 3464bb656a9c -r 8475a4e0425e .hgignore
--- a/.hgignore Thu Jan 18 09:54:33 2007 +0000
+++ b/.hgignore Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e Makefile
--- a/Makefile  Thu Jan 18 09:54:33 2007 +0000
+++ b/Makefile  Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e buildconfigs/linux-defconfig_xen0_x86_32
--- a/buildconfigs/linux-defconfig_xen0_x86_32  Thu Jan 18 09:54:33 2007 +0000
+++ b/buildconfigs/linux-defconfig_xen0_x86_32  Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e buildconfigs/linux-defconfig_xenU_x86_32
--- a/buildconfigs/linux-defconfig_xenU_x86_32  Thu Jan 18 09:54:33 2007 +0000
+++ b/buildconfigs/linux-defconfig_xenU_x86_32  Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e buildconfigs/linux-defconfig_xen_x86_32
--- a/buildconfigs/linux-defconfig_xen_x86_32   Thu Jan 18 09:54:33 2007 +0000
+++ b/buildconfigs/linux-defconfig_xen_x86_32   Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e docs/man/xm.pod.1
--- a/docs/man/xm.pod.1 Thu Jan 18 09:54:33 2007 +0000
+++ b/docs/man/xm.pod.1 Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e docs/man/xmdomain.cfg.pod.5
--- a/docs/man/xmdomain.cfg.pod.5       Thu Jan 18 09:54:33 2007 +0000
+++ b/docs/man/xmdomain.cfg.pod.5       Thu Jan 18 15:18:07 2007 +0000
@@ -135,6 +135,55 @@ one will be randomly chosen by xen with 
 
 =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 -r 3464bb656a9c -r 8475a4e0425e docs/xen-api/wire-protocol.tex
--- a/docs/xen-api/wire-protocol.tex    Thu Jan 18 09:54:33 2007 +0000
+++ b/docs/xen-api/wire-protocol.tex    Thu Jan 18 15:18:07 2007 +0000
@@ -153,7 +153,7 @@ you must login and initiate a session. F
 \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 -r 3464bb656a9c -r 8475a4e0425e extras/mini-os/Makefile
--- a/extras/mini-os/Makefile   Thu Jan 18 09:54:33 2007 +0000
+++ b/extras/mini-os/Makefile   Thu Jan 18 15:18:07 2007 +0000
@@ -1,106 +1,88 @@ debug ?= y
-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 =
+# This is used for architecture specific links.
+# This can be overwritten from arch specific rules.
+ARCH_LINKS =
+
 # For possible special header directories.
+# This can be overwritten from arch specific rules.
 EXTRA_INC =
 
-# Standard name for architecture specific subdirectories.
-TARGET_ARCH_DIR = $(TARGET_ARCH)
-# This is used for architecture specific links.
-ARCH_LINKS =
+# Special build dependencies.
+# Build all after touching this/these file(s) (see minios.mk)
+SPEC_DEPENDS = minios.mk
 
-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
+# Include the architecture family's special makerules.
+# This must be before include minios.mk!
+include $(TARGET_ARCH_DIR)/arch.mk
 
-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
+# Include common mini-os makerules.
+include 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
+# 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
 
-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
-
-ifeq ($(debug),y)
-CFLAGS += -g
-else
-CFLAGS += -O3
-endif
-
-# 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 @@ links:     $(ARCH_LINKS)
 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): libminios.a $(HEAD)
-       $(LD) $(LDFLAGS) $(HEAD) $(LDLIBS) -o $@.elf
-       gzip -f -9 -c $@.elf >$@.gz
+$(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
-clean:
-       find . -type f -name '*.o' | xargs rm -f
+.PHONY: clean arch_clean
+
+arch_clean:
+       $(MAKE) --directory=$(TARGET_ARCH_DIR) clean || exit 1;
+
+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 -r 3464bb656a9c -r 8475a4e0425e extras/mini-os/arch/x86/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/arch/x86/Makefile  Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e extras/mini-os/arch/x86/arch.mk
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/arch/x86/arch.mk   Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e extras/mini-os/arch/x86/minios-x86_32.lds
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/arch/x86/minios-x86_32.lds Thu Jan 18 15:18:07 2007 +0000
@@ -0,0 +1,45 @@
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+SECTIONS
+{
+  . = 0x0;
+  _text = .;                   /* Text and read-only data */
+  .text : {
+       *(.text)
+       *(.gnu.warning)
+       } = 0x9090
+
+  _etext = .;                  /* End of text section */
+
+  .rodata : { *(.rodata) *(.rodata.*) }
+
+  .data : {                    /* Data */
+       *(.data)
+       CONSTRUCTORS
+       }
+
+  _edata = .;                  /* End of data section */
+
+  __bss_start = .;             /* BSS */
+  .bss : {
+       *(.bss)
+       }
+  _end = . ;
+
+  /* Sections to be discarded */
+  /DISCARD/ : {
+       *(.text.exit)
+       *(.data.exit)
+       *(.exitcall.exit)
+       }
+
+  /* Stabs debugging sections.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  .stab.excl 0 : { *(.stab.excl) }
+  .stab.exclstr 0 : { *(.stab.exclstr) }
+  .stab.index 0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment 0 : { *(.comment) }
+}
diff -r 3464bb656a9c -r 8475a4e0425e extras/mini-os/arch/x86/minios-x86_64.lds
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/arch/x86/minios-x86_64.lds Thu Jan 18 15:18:07 2007 +0000
@@ -0,0 +1,54 @@
+OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
+OUTPUT_ARCH(i386:x86-64)
+ENTRY(_start)
+SECTIONS
+{
+  . = 0x0;
+  _text = .;                   /* Text and read-only data */
+  .text : {
+       *(.text)
+       *(.gnu.warning)
+       } = 0x9090
+
+  _etext = .;                  /* End of text section */
+
+  .rodata : { *(.rodata) *(.rodata.*) }
+
+  .data : {                    /* Data */
+       *(.data)
+       CONSTRUCTORS
+       }
+
+  _edata = .;                  /* End of data section */
+
+  . = ALIGN(8192);             /* init_task */
+  .data.init_task : { *(.data.init_task) }
+
+  . = ALIGN(4096);
+  .data.page_aligned : { *(.data.idt) }
+
+  . = ALIGN(32);
+  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
+  __bss_start = .;             /* BSS */
+  .bss : {
+       *(.bss)
+       }
+  _end = . ;
+
+  /* Sections to be discarded */
+  /DISCARD/ : {
+       *(.text.exit)
+       *(.data.exit)
+       *(.exitcall.exit)
+       }
+
+  /* Stabs debugging sections.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  .stab.excl 0 : { *(.stab.excl) }
+  .stab.exclstr 0 : { *(.stab.exclstr) }
+  .stab.index 0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment 0 : { *(.comment) }
+}
diff -r 3464bb656a9c -r 8475a4e0425e extras/mini-os/arch/x86/x86_32.S
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/arch/x86/x86_32.S  Thu Jan 18 15:18:07 2007 +0000
@@ -0,0 +1,287 @@
+#include <os.h>
+#include <xen/arch-x86_32.h>
+
+.section __xen_guest
+       .ascii  "GUEST_OS=Mini-OS"
+       .ascii  ",XEN_VER=xen-3.0"
+       .ascii  ",VIRT_BASE=0x0" /* &_text from minios_x86_32.lds */
+       .ascii  ",ELF_PADDR_OFFSET=0x0"
+       .ascii  ",HYPERCALL_PAGE=0x2"
+#ifdef CONFIG_X86_PAE
+       .ascii  ",PAE=yes"
+#else
+       .ascii  ",PAE=no"
+#endif
+       .ascii  ",LOADER=generic"
+       .byte   0
+.text
+
+.globl _start, shared_info, hypercall_page
+                        
+_start:
+        cld
+        lss stack_start,%esp
+        push %esi 
+        call start_kernel
+
+stack_start:
+       .long stack+8192, __KERNEL_SS
+
+        /* Unpleasant -- the PTE that maps this page is actually overwritten */
+        /* to map the real shared-info page! :-)                             */
+        .org 0x1000
+shared_info:
+        .org 0x2000
+
+hypercall_page:
+        .org 0x3000
+
+ES             = 0x20
+ORIG_EAX       = 0x24
+EIP            = 0x28
+CS             = 0x2C
+
+#define ENTRY(X) .globl X ; X :
+
+#define SAVE_ALL \
+       cld; \
+       pushl %es; \
+       pushl %ds; \
+       pushl %eax; \
+       pushl %ebp; \
+       pushl %edi; \
+       pushl %esi; \
+       pushl %edx; \
+       pushl %ecx; \
+       pushl %ebx; \
+       movl $(__KERNEL_DS),%edx; \
+       movl %edx,%ds; \
+       movl %edx,%es;
+
+#define RESTORE_ALL    \
+       popl %ebx;      \
+       popl %ecx;      \
+       popl %edx;      \
+       popl %esi;      \
+       popl %edi;      \
+       popl %ebp;      \
+       popl %eax;      \
+       popl %ds;       \
+       popl %es;       \
+       addl $4,%esp;   \
+       iret;           \
+
+ENTRY(divide_error)
+       pushl $0                # no error code
+       pushl $do_divide_error
+do_exception:
+    pushl %ds
+       pushl %eax
+       xorl %eax, %eax
+       pushl %ebp
+       pushl %edi
+       pushl %esi
+       pushl %edx
+       decl %eax                       # eax = -1
+       pushl %ecx
+       pushl %ebx
+       cld
+       movl %es, %ecx
+       movl ES(%esp), %edi             # get the function address
+       movl ORIG_EAX(%esp), %edx       # get the error code
+       movl %eax, ORIG_EAX(%esp)
+       movl %ecx, ES(%esp)
+       movl $(__KERNEL_DS), %ecx
+       movl %ecx, %ds
+       movl %ecx, %es
+       movl %esp,%eax                  # pt_regs pointer
+    pushl %edx
+    pushl %eax
+       call *%edi
+    jmp ret_from_exception
+    
+ret_from_exception:
+        movb CS(%esp),%cl
+       test $2,%cl          # slow return to ring 2 or 3
+       jne  safesti
+        RESTORE_ALL
+
+# A note on the "critical region" in our callback handler.
+# We want to avoid stacking callback handlers due to events occurring
+# during handling of the last event. To do this, we keep events disabled
+# until weve done all processing. HOWEVER, we must enable events before
+# popping the stack frame (cant be done atomically) and so it would still
+# be possible to get enough handler activations to overflow the stack.
+# Although unlikely, bugs of that kind are hard to track down, so wed
+# like to avoid the possibility.
+# So, on entry to the handler we detect whether we interrupted an
+# existing activation in its critical region -- if so, we pop the current
+# activation and restart the handler using the previous one.
+ENTRY(hypervisor_callback)
+        pushl %eax
+        SAVE_ALL
+        movl EIP(%esp),%eax
+        cmpl $scrit,%eax
+        jb   11f
+        cmpl $ecrit,%eax
+        jb   critical_region_fixup
+11:     push %esp
+        call do_hypervisor_callback
+        add  $4,%esp
+        movl HYPERVISOR_shared_info,%esi
+        xorl %eax,%eax
+        movb CS(%esp),%cl
+       test $2,%cl          # slow return to ring 2 or 3
+        jne  safesti
+safesti:movb $0,1(%esi)     # reenable event callbacks
+scrit:  /**** START OF CRITICAL REGION ****/
+        testb $0xFF,(%esi)
+        jnz  14f              # process more events if necessary...
+        RESTORE_ALL
+14:     movb $1,1(%esi)
+        jmp  11b
+ecrit:  /**** END OF CRITICAL REGION ****/
+# [How we do the fixup]. We want to merge the current stack frame with the
+# just-interrupted frame. How we do this depends on where in the critical
+# region the interrupted handler was executing, and so how many saved
+# registers are in each frame. We do this quickly using the lookup table
+# 'critical_fixup_table'. For each byte offset in the critical region, it
+# provides the number of bytes which have already been popped from the
+# interrupted stack frame. 
+critical_region_fixup:
+        addl $critical_fixup_table-scrit,%eax
+        movzbl (%eax),%eax    # %eax contains num bytes popped
+        mov  %esp,%esi
+        add  %eax,%esi        # %esi points at end of src region
+        mov  %esp,%edi
+        add  $0x34,%edi       # %edi points at end of dst region
+        mov  %eax,%ecx
+        shr  $2,%ecx          # convert words to bytes
+        je   16f              # skip loop if nothing to copy
+15:     subl $4,%esi          # pre-decrementing copy loop
+        subl $4,%edi
+        movl (%esi),%eax
+        movl %eax,(%edi)
+        loop 15b
+16:     movl %edi,%esp        # final %edi is top of merged stack
+        jmp  11b
+         
+critical_fixup_table:        
+        .byte 0x00,0x00,0x00                  # testb $0xff,(%esi)
+        .byte 0x00,0x00                       # jne  14f
+        .byte 0x00                            # pop  %ebx
+        .byte 0x04                            # pop  %ecx
+        .byte 0x08                            # pop  %edx
+        .byte 0x0c                            # pop  %esi
+        .byte 0x10                            # pop  %edi
+        .byte 0x14                            # pop  %ebp
+        .byte 0x18                            # pop  %eax
+        .byte 0x1c                            # pop  %ds
+        .byte 0x20                            # pop  %es
+        .byte 0x24,0x24,0x24                  # add  $4,%esp
+        .byte 0x28                            # iret
+        .byte 0x00,0x00,0x00,0x00             # movb $1,1(%esi)
+        .byte 0x00,0x00                       # jmp  11b
+       
+# Hypervisor uses this for application faults while it executes.
+ENTRY(failsafe_callback)
+      pop  %ds
+      pop  %es
+      pop  %fs
+      pop  %gs
+      iret
+                
+ENTRY(coprocessor_error)
+       pushl $0
+       pushl $do_coprocessor_error
+       jmp do_exception
+
+ENTRY(simd_coprocessor_error)
+       pushl $0
+       pushl $do_simd_coprocessor_error
+       jmp do_exception
+
+ENTRY(device_not_available)
+        iret
+
+ENTRY(debug)
+       pushl $0
+       pushl $do_debug
+       jmp do_exception
+
+ENTRY(int3)
+       pushl $0
+       pushl $do_int3
+       jmp do_exception
+
+ENTRY(overflow)
+       pushl $0
+       pushl $do_overflow
+       jmp do_exception
+
+ENTRY(bounds)
+       pushl $0
+       pushl $do_bounds
+       jmp do_exception
+
+ENTRY(invalid_op)
+       pushl $0
+       pushl $do_invalid_op
+       jmp do_exception
+
+
+ENTRY(coprocessor_segment_overrun)
+       pushl $0
+       pushl $do_coprocessor_segment_overrun
+       jmp do_exception
+
+
+ENTRY(invalid_TSS)
+       pushl $do_invalid_TSS
+       jmp do_exception
+
+
+ENTRY(segment_not_present)
+       pushl $do_segment_not_present
+       jmp do_exception
+
+
+ENTRY(stack_segment)
+       pushl $do_stack_segment
+       jmp do_exception
+
+
+ENTRY(general_protection)
+       pushl $do_general_protection
+       jmp do_exception
+
+
+ENTRY(alignment_check)
+       pushl $do_alignment_check
+       jmp do_exception
+
+
+ENTRY(page_fault)
+    pushl $do_page_fault
+    jmp do_exception
+    
+ENTRY(machine_check)
+       pushl $0
+       pushl $do_machine_check
+       jmp do_exception
+
+
+ENTRY(spurious_interrupt_bug)
+       pushl $0
+       pushl $do_spurious_interrupt_bug
+       jmp do_exception
+
+
+
+ENTRY(thread_starter)
+    popl %eax
+    popl %ebx
+    pushl %eax
+    call *%ebx
+    call exit_thread 
+    
diff -r 3464bb656a9c -r 8475a4e0425e extras/mini-os/arch/x86/x86_64.S
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/arch/x86/x86_64.S  Thu Jan 18 15:18:07 2007 +0000
@@ -0,0 +1,385 @@
+#include <os.h>
+#include <xen/features.h>
+
+.section __xen_guest
+       .ascii  "GUEST_OS=Mini-OS"
+       .ascii  ",XEN_VER=xen-3.0"
+       .ascii  ",VIRT_BASE=0x0" /* &_text from minios_x86_64.lds */
+       .ascii  ",ELF_PADDR_OFFSET=0x0"
+       .ascii  ",HYPERCALL_PAGE=0x2"
+       .ascii  ",LOADER=generic"
+       .byte   0
+.text
+
+#define ENTRY(X) .globl X ; X :
+.globl _start, shared_info, hypercall_page
+
+
+_start:
+        cld
+        movq stack_start(%rip),%rsp
+        movq %rsi,%rdi
+        call start_kernel
+
+stack_start:
+        .quad stack+8192
+
+        /* Unpleasant -- the PTE that maps this page is actually overwritten */
+        /* to map the real shared-info page! :-)                             */
+        .org 0x1000
+shared_info:
+        .org 0x2000
+
+hypercall_page:
+        .org 0x3000
+
+
+/* Offsets into shared_info_t. */                
+#define evtchn_upcall_pending          /* 0 */
+#define evtchn_upcall_mask             1
+
+NMI_MASK = 0x80000000
+
+#define RDI 112
+#define ORIG_RAX 120       /* + error_code */ 
+#define EFLAGS 144
+
+#define REST_SKIP 6*8                  
+.macro SAVE_REST
+       subq $REST_SKIP,%rsp
+#      CFI_ADJUST_CFA_OFFSET   REST_SKIP
+       movq %rbx,5*8(%rsp) 
+#      CFI_REL_OFFSET  rbx,5*8
+       movq %rbp,4*8(%rsp) 
+#      CFI_REL_OFFSET  rbp,4*8
+       movq %r12,3*8(%rsp) 
+#      CFI_REL_OFFSET  r12,3*8
+       movq %r13,2*8(%rsp) 
+#      CFI_REL_OFFSET  r13,2*8
+       movq %r14,1*8(%rsp) 
+#      CFI_REL_OFFSET  r14,1*8
+       movq %r15,(%rsp) 
+#      CFI_REL_OFFSET  r15,0*8
+.endm          
+
+
+.macro RESTORE_REST
+       movq (%rsp),%r15
+#      CFI_RESTORE r15
+       movq 1*8(%rsp),%r14
+#      CFI_RESTORE r14
+       movq 2*8(%rsp),%r13
+#      CFI_RESTORE r13
+       movq 3*8(%rsp),%r12
+#      CFI_RESTORE r12
+       movq 4*8(%rsp),%rbp
+#      CFI_RESTORE rbp
+       movq 5*8(%rsp),%rbx
+#      CFI_RESTORE rbx
+       addq $REST_SKIP,%rsp
+#      CFI_ADJUST_CFA_OFFSET   -(REST_SKIP)
+.endm
+
+
+#define ARG_SKIP 9*8
+.macro RESTORE_ARGS 
skiprax=0,addskip=0,skiprcx=0,skipr11=0,skipr8910=0,skiprdx=0
+       .if \skipr11
+       .else
+       movq (%rsp),%r11
+#      CFI_RESTORE r11
+       .endif
+       .if \skipr8910
+       .else
+       movq 1*8(%rsp),%r10
+#      CFI_RESTORE r10
+       movq 2*8(%rsp),%r9
+#      CFI_RESTORE r9
+       movq 3*8(%rsp),%r8
+#      CFI_RESTORE r8
+       .endif
+       .if \skiprax
+       .else
+       movq 4*8(%rsp),%rax
+#      CFI_RESTORE rax
+       .endif
+       .if \skiprcx
+       .else
+       movq 5*8(%rsp),%rcx
+#      CFI_RESTORE rcx
+       .endif
+       .if \skiprdx
+       .else
+       movq 6*8(%rsp),%rdx
+#      CFI_RESTORE rdx
+       .endif
+       movq 7*8(%rsp),%rsi
+#      CFI_RESTORE rsi
+       movq 8*8(%rsp),%rdi
+#      CFI_RESTORE rdi
+       .if ARG_SKIP+\addskip > 0
+       addq $ARG_SKIP+\addskip,%rsp
+#      CFI_ADJUST_CFA_OFFSET   -(ARG_SKIP+\addskip)
+       .endif
+.endm  
+
+
+.macro HYPERVISOR_IRET flag
+#    testb $3,1*8(%rsp)    /* Don't need to do that in Mini-os, as */
+#      jnz   2f               /* there is no userspace? */
+       testl $NMI_MASK,2*8(%rsp)
+       jnz   2f
+
+       testb $1,(xen_features+XENFEAT_supervisor_mode_kernel)
+       jnz   1f
+
+       /* Direct iret to kernel space. Correct CS and SS. */
+       orb   $3,1*8(%rsp)
+       orb   $3,4*8(%rsp)
+1:     iretq
+
+2:     /* Slow iret via hypervisor. */
+       andl  $~NMI_MASK, 16(%rsp)
+       pushq $\flag
+       jmp  hypercall_page + (__HYPERVISOR_iret * 32)
+.endm
+
+/*
+ * Exception entry point. This expects an error code/orig_rax on the stack
+ * and the exception handler in %rax.  
+ */                                            
+ENTRY(error_entry)
+#      _frame RDI
+       /* rdi slot contains rax, oldrax contains error code */
+       cld     
+       subq  $14*8,%rsp
+#      CFI_ADJUST_CFA_OFFSET   (14*8)
+       movq %rsi,13*8(%rsp)
+#      CFI_REL_OFFSET  rsi,RSI
+       movq 14*8(%rsp),%rsi    /* load rax from rdi slot */
+       movq %rdx,12*8(%rsp)
+#      CFI_REL_OFFSET  rdx,RDX
+       movq %rcx,11*8(%rsp)
+#      CFI_REL_OFFSET  rcx,RCX
+       movq %rsi,10*8(%rsp)    /* store rax */ 
+#      CFI_REL_OFFSET  rax,RAX
+       movq %r8, 9*8(%rsp)
+#      CFI_REL_OFFSET  r8,R8
+       movq %r9, 8*8(%rsp)
+#      CFI_REL_OFFSET  r9,R9
+       movq %r10,7*8(%rsp)
+#      CFI_REL_OFFSET  r10,R10
+       movq %r11,6*8(%rsp)
+#      CFI_REL_OFFSET  r11,R11
+       movq %rbx,5*8(%rsp) 
+#      CFI_REL_OFFSET  rbx,RBX
+       movq %rbp,4*8(%rsp) 
+#      CFI_REL_OFFSET  rbp,RBP
+       movq %r12,3*8(%rsp) 
+#      CFI_REL_OFFSET  r12,R12
+       movq %r13,2*8(%rsp) 
+#      CFI_REL_OFFSET  r13,R13
+       movq %r14,1*8(%rsp) 
+#      CFI_REL_OFFSET  r14,R14
+       movq %r15,(%rsp) 
+#      CFI_REL_OFFSET  r15,R15
+#if 0        
+       cmpl $__KERNEL_CS,CS(%rsp)
+       je  error_kernelspace
+#endif        
+error_call_handler:
+       movq %rdi, RDI(%rsp)            
+       movq %rsp,%rdi
+       movq ORIG_RAX(%rsp),%rsi        # get error code 
+       movq $-1,ORIG_RAX(%rsp)
+       call *%rax
+
+.macro zeroentry sym
+#      INTR_FRAME
+    movq (%rsp),%rcx
+    movq 8(%rsp),%r11
+    addq $0x10,%rsp /* skip rcx and r11 */
+       pushq $0        /* push error code/oldrax */ 
+#      CFI_ADJUST_CFA_OFFSET 8
+       pushq %rax      /* push real oldrax to the rdi slot */ 
+#      CFI_ADJUST_CFA_OFFSET 8
+       leaq  \sym(%rip),%rax
+       jmp error_entry
+#      CFI_ENDPROC
+.endm  
+
+.macro errorentry sym
+#      XCPT_FRAME
+        movq (%rsp),%rcx
+        movq 8(%rsp),%r11
+        addq $0x10,%rsp /* rsp points to the error code */
+       pushq %rax
+#      CFI_ADJUST_CFA_OFFSET 8
+       leaq  \sym(%rip),%rax
+       jmp error_entry
+#      CFI_ENDPROC
+.endm
+
+#define XEN_GET_VCPU_INFO(reg) movq HYPERVISOR_shared_info,reg
+#define XEN_PUT_VCPU_INFO(reg)
+#define XEN_PUT_VCPU_INFO_fixup
+#define XEN_LOCKED_BLOCK_EVENTS(reg)   movb $1,evtchn_upcall_mask(reg)
+#define XEN_LOCKED_UNBLOCK_EVENTS(reg) movb $0,evtchn_upcall_mask(reg)
+#define XEN_TEST_PENDING(reg)  testb $0xFF,evtchn_upcall_pending(reg)
+
+#define XEN_BLOCK_EVENTS(reg)  XEN_GET_VCPU_INFO(reg)                  ; \
+                                       XEN_LOCKED_BLOCK_EVENTS(reg)    ; \
+                                           XEN_PUT_VCPU_INFO(reg)
+
+#define XEN_UNBLOCK_EVENTS(reg)        XEN_GET_VCPU_INFO(reg)                  
; \
+                                               XEN_LOCKED_UNBLOCK_EVENTS(reg)  
; \
+                                       XEN_PUT_VCPU_INFO(reg)
+
+
+
+ENTRY(hypervisor_callback)
+    zeroentry hypervisor_callback2
+
+ENTRY(hypervisor_callback2)
+        movq %rdi, %rsp 
+11:     movq %gs:8,%rax
+        incl %gs:0
+        cmovzq %rax,%rsp
+        pushq %rdi
+        call do_hypervisor_callback 
+        popq %rsp
+        decl %gs:0
+        jmp error_exit
+
+#        ALIGN
+restore_all_enable_events:  
+       XEN_UNBLOCK_EVENTS(%rsi)        # %rsi is already set up...
+
+scrit: /**** START OF CRITICAL REGION ****/
+       XEN_TEST_PENDING(%rsi)
+       jnz  14f                        # process more events if necessary...
+       XEN_PUT_VCPU_INFO(%rsi)
+        RESTORE_ARGS 0,8,0
+        HYPERVISOR_IRET 0
+        
+14:    XEN_LOCKED_BLOCK_EVENTS(%rsi)
+       XEN_PUT_VCPU_INFO(%rsi)
+       SAVE_REST
+        movq %rsp,%rdi                  # set the argument again
+       jmp  11b
+ecrit:  /**** END OF CRITICAL REGION ****/
+
+
+retint_kernel:
+retint_restore_args:
+       movl EFLAGS-REST_SKIP(%rsp), %eax
+       shr $9, %eax                    # EAX[0] == IRET_EFLAGS.IF
+       XEN_GET_VCPU_INFO(%rsi)
+       andb evtchn_upcall_mask(%rsi),%al
+       andb $1,%al                     # EAX[0] == IRET_EFLAGS.IF & event_mask
+       jnz restore_all_enable_events   #        != 0 => enable event delivery
+       XEN_PUT_VCPU_INFO(%rsi)
+               
+       RESTORE_ARGS 0,8,0
+       HYPERVISOR_IRET 0
+
+
+error_exit:            
+       RESTORE_REST
+/*     cli */
+       XEN_BLOCK_EVENTS(%rsi)          
+       jmp retint_kernel
+
+
+
+ENTRY(failsafe_callback)
+        popq  %rcx
+        popq  %r11
+        iretq
+
+
+ENTRY(coprocessor_error)
+        zeroentry do_coprocessor_error
+
+
+ENTRY(simd_coprocessor_error)
+        zeroentry do_simd_coprocessor_error
+
+
+ENTRY(device_not_available)
+        zeroentry do_device_not_available
+
+
+ENTRY(debug)
+#       INTR_FRAME
+#       CFI_ADJUST_CFA_OFFSET 8 */
+        zeroentry do_debug
+#       CFI_ENDPROC
+
+
+ENTRY(int3)
+#       INTR_FRAME
+#       CFI_ADJUST_CFA_OFFSET 8 */
+        zeroentry do_int3
+#       CFI_ENDPROC
+
+ENTRY(overflow)
+        zeroentry do_overflow
+
+
+ENTRY(bounds)
+        zeroentry do_bounds
+    
+    
+ENTRY(invalid_op)
+        zeroentry do_invalid_op
+
+
+ENTRY(coprocessor_segment_overrun)
+        zeroentry do_coprocessor_segment_overrun
+
+
+ENTRY(invalid_TSS)
+        errorentry do_invalid_TSS
+
+
+ENTRY(segment_not_present)
+        errorentry do_segment_not_present
+
+
+/* runs on exception stack */
+ENTRY(stack_segment)
+#       XCPT_FRAME
+        errorentry do_stack_segment
+#       CFI_ENDPROC
+                    
+
+ENTRY(general_protection)
+        errorentry do_general_protection
+
+
+ENTRY(alignment_check)
+        errorentry do_alignment_check
+
+
+ENTRY(divide_error)
+        zeroentry do_divide_error
+
+
+ENTRY(spurious_interrupt_bug)
+        zeroentry do_spurious_interrupt_bug
+            
+
+ENTRY(page_fault)
+        errorentry do_page_fault
+
+
+
+
+
+ENTRY(thread_starter)
+        popq %rdi
+        popq %rbx
+        call *%rbx
+        call exit_thread 
+        
+
diff -r 3464bb656a9c -r 8475a4e0425e extras/mini-os/gnttab.c
--- a/extras/mini-os/gnttab.c   Thu Jan 18 09:54:33 2007 +0000
+++ b/extras/mini-os/gnttab.c   Thu Jan 18 15:18:07 2007 +0000
@@ -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 void
+put_free_entry(grant_ref_t ref)
+{
+    gnttab_list[ref] = gnttab_list[0];
+    gnttab_list[0]  = ref;
+
+}
 
 static grant_ref_t
-get_free_entries(int count)
+get_free_entry(void)
 {
-    grant_ref_t ref;
-    grant_ref_t head;
-
-    ref = head = gnttab_free_head;
-    while (count-- > 1)
-       head = gnttab_list[head];
-    gnttab_free_head = gnttab_list[head];
-    gnttab_list[head] = GNTTAB_LIST_END;
+    unsigned int ref = gnttab_list[0];
+    gnttab_list[0] = gnttab_list[ref];
     return ref;
-}
-
-static void
-put_free_entry(grant_ref_t gref)
-{
-    gnttab_list[gref] = gnttab_free_head;
-    gnttab_free_head = gref;
 }
 
 grant_ref_t
@@ -55,7 +48,7 @@ gnttab_grant_access(domid_t domid, unsig
 {
     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, uns
 {
     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 -r 3464bb656a9c -r 8475a4e0425e extras/mini-os/include/hypervisor.h
--- a/extras/mini-os/include/hypervisor.h       Thu Jan 18 09:54:33 2007 +0000
+++ b/extras/mini-os/include/hypervisor.h       Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e extras/mini-os/include/netfront.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/include/netfront.h Thu Jan 18 15:18:07 2007 +0000
@@ -0,0 +1,2 @@
+void init_netfront(void*);
+void netfront_xmit(unsigned char* data,int len);
diff -r 3464bb656a9c -r 8475a4e0425e 
extras/mini-os/include/x86/x86_32/hypercall-x86_32.h
--- a/extras/mini-os/include/x86/x86_32/hypercall-x86_32.h      Thu Jan 18 
09:54:33 2007 +0000
+++ b/extras/mini-os/include/x86/x86_32/hypercall-x86_32.h      Thu Jan 18 
15:18:07 2007 +0000
@@ -179,14 +179,6 @@ HYPERVISOR_set_timer_op(
        unsigned long timeout_hi = (unsigned long)(timeout>>32);
        unsigned long timeout_lo = (unsigned long)timeout;
        return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
-}
-
-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
diff -r 3464bb656a9c -r 8475a4e0425e 
extras/mini-os/include/x86/x86_64/hypercall-x86_64.h
--- a/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h      Thu Jan 18 
09:54:33 2007 +0000
+++ b/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h      Thu Jan 18 
15:18:07 2007 +0000
@@ -181,14 +181,6 @@ HYPERVISOR_set_timer_op(
        u64 timeout)
 {
        return _hypercall1(long, set_timer_op, timeout);
-}
-
-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
diff -r 3464bb656a9c -r 8475a4e0425e extras/mini-os/include/xenbus.h
--- a/extras/mini-os/include/xenbus.h   Thu Jan 18 09:54:33 2007 +0000
+++ b/extras/mini-os/include/xenbus.h   Thu Jan 18 15:18:07 2007 +0000
@@ -11,6 +11,9 @@ void init_xenbus(void);
    string on failure and sets *value to NULL.  On success, *value is
    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. */
diff -r 3464bb656a9c -r 8475a4e0425e extras/mini-os/kernel.c
--- a/extras/mini-os/kernel.c   Thu Jan 18 09:54:33 2007 +0000
+++ b/extras/mini-os/kernel.c   Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e extras/mini-os/minios-x86_32.lds
--- a/extras/mini-os/minios-x86_32.lds  Thu Jan 18 09:54:33 2007 +0000
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
-OUTPUT_ARCH(i386)
-ENTRY(_start)
-SECTIONS
-{
-  . = 0x0;
-  _text = .;                   /* Text and read-only data */
-  .text : {
-       *(.text)
-       *(.gnu.warning)
-       } = 0x9090
-
-  _etext = .;                  /* End of text section */
-
-  .rodata : { *(.rodata) *(.rodata.*) }
-
-  .data : {                    /* Data */
-       *(.data)
-       CONSTRUCTORS
-       }
-
-  _edata = .;                  /* End of data section */
-
-  __bss_start = .;             /* BSS */
-  .bss : {
-       *(.bss)
-       }
-  _end = . ;
-
-  /* Sections to be discarded */
-  /DISCARD/ : {
-       *(.text.exit)
-       *(.data.exit)
-       *(.exitcall.exit)
-       }
-
-  /* Stabs debugging sections.  */
-  .stab 0 : { *(.stab) }
-  .stabstr 0 : { *(.stabstr) }
-  .stab.excl 0 : { *(.stab.excl) }
-  .stab.exclstr 0 : { *(.stab.exclstr) }
-  .stab.index 0 : { *(.stab.index) }
-  .stab.indexstr 0 : { *(.stab.indexstr) }
-  .comment 0 : { *(.comment) }
-}
diff -r 3464bb656a9c -r 8475a4e0425e extras/mini-os/minios-x86_64.lds
--- a/extras/mini-os/minios-x86_64.lds  Thu Jan 18 09:54:33 2007 +0000
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
-OUTPUT_ARCH(i386:x86-64)
-ENTRY(_start)
-SECTIONS
-{
-  . = 0x0;
-  _text = .;                   /* Text and read-only data */
-  .text : {
-       *(.text)
-       *(.gnu.warning)
-       } = 0x9090
-
-  _etext = .;                  /* End of text section */
-
-  .rodata : { *(.rodata) *(.rodata.*) }
-
-  .data : {                    /* Data */
-       *(.data)
-       CONSTRUCTORS
-       }
-
-  _edata = .;                  /* End of data section */
-
-  . = ALIGN(8192);             /* init_task */
-  .data.init_task : { *(.data.init_task) }
-
-  . = ALIGN(4096);
-  .data.page_aligned : { *(.data.idt) }
-
-  . = ALIGN(32);
-  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
-  __bss_start = .;             /* BSS */
-  .bss : {
-       *(.bss)
-       }
-  _end = . ;
-
-  /* Sections to be discarded */
-  /DISCARD/ : {
-       *(.text.exit)
-       *(.data.exit)
-       *(.exitcall.exit)
-       }
-
-  /* Stabs debugging sections.  */
-  .stab 0 : { *(.stab) }
-  .stabstr 0 : { *(.stabstr) }
-  .stab.excl 0 : { *(.stab.excl) }
-  .stab.exclstr 0 : { *(.stab.exclstr) }
-  .stab.index 0 : { *(.stab.index) }
-  .stab.indexstr 0 : { *(.stab.indexstr) }
-  .comment 0 : { *(.comment) }
-}
diff -r 3464bb656a9c -r 8475a4e0425e extras/mini-os/minios.mk
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/minios.mk  Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e extras/mini-os/netfront.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/extras/mini-os/netfront.c Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e extras/mini-os/x86_32.S
--- a/extras/mini-os/x86_32.S   Thu Jan 18 09:54:33 2007 +0000
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,287 +0,0 @@
-#include <os.h>
-#include <xen/arch-x86_32.h>
-
-.section __xen_guest
-       .ascii  "GUEST_OS=Mini-OS"
-       .ascii  ",XEN_VER=xen-3.0"
-       .ascii  ",VIRT_BASE=0x0" /* &_text from minios_x86_32.lds */
-       .ascii  ",ELF_PADDR_OFFSET=0x0"
-       .ascii  ",HYPERCALL_PAGE=0x2"
-#ifdef CONFIG_X86_PAE
-       .ascii  ",PAE=yes"
-#else
-       .ascii  ",PAE=no"
-#endif
-       .ascii  ",LOADER=generic"
-       .byte   0
-.text
-
-.globl _start, shared_info, hypercall_page
-                        
-_start:
-        cld
-        lss stack_start,%esp
-        push %esi 
-        call start_kernel
-
-stack_start:
-       .long stack+8192, __KERNEL_SS
-
-        /* Unpleasant -- the PTE that maps this page is actually overwritten */
-        /* to map the real shared-info page! :-)                             */
-        .org 0x1000
-shared_info:
-        .org 0x2000
-
-hypercall_page:
-        .org 0x3000
-
-ES             = 0x20
-ORIG_EAX       = 0x24
-EIP            = 0x28
-CS             = 0x2C
-
-#define ENTRY(X) .globl X ; X :
-
-#define SAVE_ALL \
-       cld; \
-       pushl %es; \
-       pushl %ds; \
-       pushl %eax; \
-       pushl %ebp; \
-       pushl %edi; \
-       pushl %esi; \
-       pushl %edx; \
-       pushl %ecx; \
-       pushl %ebx; \
-       movl $(__KERNEL_DS),%edx; \
-       movl %edx,%ds; \
-       movl %edx,%es;
-
-#define RESTORE_ALL    \
-       popl %ebx;      \
-       popl %ecx;      \
-       popl %edx;      \
-       popl %esi;      \
-       popl %edi;      \
-       popl %ebp;      \
-       popl %eax;      \
-       popl %ds;       \
-       popl %es;       \
-       addl $4,%esp;   \
-       iret;           \
-
-ENTRY(divide_error)
-       pushl $0                # no error code
-       pushl $do_divide_error
-do_exception:
-    pushl %ds
-       pushl %eax
-       xorl %eax, %eax
-       pushl %ebp
-       pushl %edi
-       pushl %esi
-       pushl %edx
-       decl %eax                       # eax = -1
-       pushl %ecx
-       pushl %ebx
-       cld
-       movl %es, %ecx
-       movl ES(%esp), %edi             # get the function address
-       movl ORIG_EAX(%esp), %edx       # get the error code
-       movl %eax, ORIG_EAX(%esp)
-       movl %ecx, ES(%esp)
-       movl $(__KERNEL_DS), %ecx
-       movl %ecx, %ds
-       movl %ecx, %es
-       movl %esp,%eax                  # pt_regs pointer
-    pushl %edx
-    pushl %eax
-       call *%edi
-    jmp ret_from_exception
-    
-ret_from_exception:
-        movb CS(%esp),%cl
-       test $2,%cl          # slow return to ring 2 or 3
-       jne  safesti
-        RESTORE_ALL
-
-# A note on the "critical region" in our callback handler.
-# We want to avoid stacking callback handlers due to events occurring
-# during handling of the last event. To do this, we keep events disabled
-# until weve done all processing. HOWEVER, we must enable events before
-# popping the stack frame (cant be done atomically) and so it would still
-# be possible to get enough handler activations to overflow the stack.
-# Although unlikely, bugs of that kind are hard to track down, so wed
-# like to avoid the possibility.
-# So, on entry to the handler we detect whether we interrupted an
-# existing activation in its critical region -- if so, we pop the current
-# activation and restart the handler using the previous one.
-ENTRY(hypervisor_callback)
-        pushl %eax
-        SAVE_ALL
-        movl EIP(%esp),%eax
-        cmpl $scrit,%eax
-        jb   11f
-        cmpl $ecrit,%eax
-        jb   critical_region_fixup
-11:     push %esp
-        call do_hypervisor_callback
-        add  $4,%esp
-        movl HYPERVISOR_shared_info,%esi
-        xorl %eax,%eax
-        movb CS(%esp),%cl
-       test $2,%cl          # slow return to ring 2 or 3
-        jne  safesti
-safesti:movb $0,1(%esi)     # reenable event callbacks
-scrit:  /**** START OF CRITICAL REGION ****/
-        testb $0xFF,(%esi)
-        jnz  14f              # process more events if necessary...
-        RESTORE_ALL
-14:     movb $1,1(%esi)
-        jmp  11b
-ecrit:  /**** END OF CRITICAL REGION ****/
-# [How we do the fixup]. We want to merge the current stack frame with the
-# just-interrupted frame. How we do this depends on where in the critical
-# region the interrupted handler was executing, and so how many saved
-# registers are in each frame. We do this quickly using the lookup table
-# 'critical_fixup_table'. For each byte offset in the critical region, it
-# provides the number of bytes which have already been popped from the
-# interrupted stack frame. 
-critical_region_fixup:
-        addl $critical_fixup_table-scrit,%eax
-        movzbl (%eax),%eax    # %eax contains num bytes popped
-        mov  %esp,%esi
-        add  %eax,%esi        # %esi points at end of src region
-        mov  %esp,%edi
-        add  $0x34,%edi       # %edi points at end of dst region
-        mov  %eax,%ecx
-        shr  $2,%ecx          # convert words to bytes
-        je   16f              # skip loop if nothing to copy
-15:     subl $4,%esi          # pre-decrementing copy loop
-        subl $4,%edi
-        movl (%esi),%eax
-        movl %eax,(%edi)
-        loop 15b
-16:     movl %edi,%esp        # final %edi is top of merged stack
-        jmp  11b
-         
-critical_fixup_table:        
-        .byte 0x00,0x00,0x00                  # testb $0xff,(%esi)
-        .byte 0x00,0x00                       # jne  14f
-        .byte 0x00                            # pop  %ebx
-        .byte 0x04                            # pop  %ecx
-        .byte 0x08                            # pop  %edx
-        .byte 0x0c                            # pop  %esi
-        .byte 0x10                            # pop  %edi
-        .byte 0x14                            # pop  %ebp
-        .byte 0x18                            # pop  %eax
-        .byte 0x1c                            # pop  %ds
-        .byte 0x20                            # pop  %es
-        .byte 0x24,0x24,0x24                  # add  $4,%esp
-        .byte 0x28                            # iret
-        .byte 0x00,0x00,0x00,0x00             # movb $1,1(%esi)
-        .byte 0x00,0x00                       # jmp  11b
-       
-# Hypervisor uses this for application faults while it executes.
-ENTRY(failsafe_callback)
-      pop  %ds
-      pop  %es
-      pop  %fs
-      pop  %gs
-      iret
-                
-ENTRY(coprocessor_error)
-       pushl $0
-       pushl $do_coprocessor_error
-       jmp do_exception
-
-ENTRY(simd_coprocessor_error)
-       pushl $0
-       pushl $do_simd_coprocessor_error
-       jmp do_exception
-
-ENTRY(device_not_available)
-        iret
-
-ENTRY(debug)
-       pushl $0
-       pushl $do_debug
-       jmp do_exception
-
-ENTRY(int3)
-       pushl $0
-       pushl $do_int3
-       jmp do_exception
-
-ENTRY(overflow)
-       pushl $0
-       pushl $do_overflow
-       jmp do_exception
-
-ENTRY(bounds)
-       pushl $0
-       pushl $do_bounds
-       jmp do_exception
-
-ENTRY(invalid_op)
-       pushl $0
-       pushl $do_invalid_op
-       jmp do_exception
-
-
-ENTRY(coprocessor_segment_overrun)
-       pushl $0
-       pushl $do_coprocessor_segment_overrun
-       jmp do_exception
-
-
-ENTRY(invalid_TSS)
-       pushl $do_invalid_TSS
-       jmp do_exception
-
-
-ENTRY(segment_not_present)
-       pushl $do_segment_not_present
-       jmp do_exception
-
-
-ENTRY(stack_segment)
-       pushl $do_stack_segment
-       jmp do_exception
-
-
-ENTRY(general_protection)
-       pushl $do_general_protection
-       jmp do_exception
-
-
-ENTRY(alignment_check)
-       pushl $do_alignment_check
-       jmp do_exception
-
-
-ENTRY(page_fault)
-    pushl $do_page_fault
-    jmp do_exception
-    
-ENTRY(machine_check)
-       pushl $0
-       pushl $do_machine_check
-       jmp do_exception
-
-
-ENTRY(spurious_interrupt_bug)
-       pushl $0
-       pushl $do_spurious_interrupt_bug
-       jmp do_exception
-
-
-
-ENTRY(thread_starter)
-    popl %eax
-    popl %ebx
-    pushl %eax
-    call *%ebx
-    call exit_thread 
-    
diff -r 3464bb656a9c -r 8475a4e0425e extras/mini-os/x86_64.S
--- a/extras/mini-os/x86_64.S   Thu Jan 18 09:54:33 2007 +0000
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,385 +0,0 @@
-#include <os.h>
-#include <xen/features.h>
-
-.section __xen_guest
-       .ascii  "GUEST_OS=Mini-OS"
-       .ascii  ",XEN_VER=xen-3.0"
-       .ascii  ",VIRT_BASE=0x0" /* &_text from minios_x86_64.lds */
-       .ascii  ",ELF_PADDR_OFFSET=0x0"
-       .ascii  ",HYPERCALL_PAGE=0x2"
-       .ascii  ",LOADER=generic"
-       .byte   0
-.text
-
-#define ENTRY(X) .globl X ; X :
-.globl _start, shared_info, hypercall_page
-
-
-_start:
-        cld
-        movq stack_start(%rip),%rsp
-        movq %rsi,%rdi
-        call start_kernel
-
-stack_start:
-        .quad stack+8192
-
-        /* Unpleasant -- the PTE that maps this page is actually overwritten */
-        /* to map the real shared-info page! :-)                             */
-        .org 0x1000
-shared_info:
-        .org 0x2000
-
-hypercall_page:
-        .org 0x3000
-
-
-/* Offsets into shared_info_t. */                
-#define evtchn_upcall_pending          /* 0 */
-#define evtchn_upcall_mask             1
-
-NMI_MASK = 0x80000000
-
-#define RDI 112
-#define ORIG_RAX 120       /* + error_code */ 
-#define EFLAGS 144
-
-#define REST_SKIP 6*8                  
-.macro SAVE_REST
-       subq $REST_SKIP,%rsp
-#      CFI_ADJUST_CFA_OFFSET   REST_SKIP
-       movq %rbx,5*8(%rsp) 
-#      CFI_REL_OFFSET  rbx,5*8
-       movq %rbp,4*8(%rsp) 
-#      CFI_REL_OFFSET  rbp,4*8
-       movq %r12,3*8(%rsp) 
-#      CFI_REL_OFFSET  r12,3*8
-       movq %r13,2*8(%rsp) 
-#      CFI_REL_OFFSET  r13,2*8
-       movq %r14,1*8(%rsp) 
-#      CFI_REL_OFFSET  r14,1*8
-       movq %r15,(%rsp) 
-#      CFI_REL_OFFSET  r15,0*8
-.endm          
-
-
-.macro RESTORE_REST
-       movq (%rsp),%r15
-#      CFI_RESTORE r15
-       movq 1*8(%rsp),%r14
-#      CFI_RESTORE r14
-       movq 2*8(%rsp),%r13
-#      CFI_RESTORE r13
-       movq 3*8(%rsp),%r12
-#      CFI_RESTORE r12
-       movq 4*8(%rsp),%rbp
-#      CFI_RESTORE rbp
-       movq 5*8(%rsp),%rbx
-#      CFI_RESTORE rbx
-       addq $REST_SKIP,%rsp
-#      CFI_ADJUST_CFA_OFFSET   -(REST_SKIP)
-.endm
-
-
-#define ARG_SKIP 9*8
-.macro RESTORE_ARGS 
skiprax=0,addskip=0,skiprcx=0,skipr11=0,skipr8910=0,skiprdx=0
-       .if \skipr11
-       .else
-       movq (%rsp),%r11
-#      CFI_RESTORE r11
-       .endif
-       .if \skipr8910
-       .else
-       movq 1*8(%rsp),%r10
-#      CFI_RESTORE r10
-       movq 2*8(%rsp),%r9
-#      CFI_RESTORE r9
-       movq 3*8(%rsp),%r8
-#      CFI_RESTORE r8
-       .endif
-       .if \skiprax
-       .else
-       movq 4*8(%rsp),%rax
-#      CFI_RESTORE rax
-       .endif
-       .if \skiprcx
-       .else
-       movq 5*8(%rsp),%rcx
-#      CFI_RESTORE rcx
-       .endif
-       .if \skiprdx
-       .else
-       movq 6*8(%rsp),%rdx
-#      CFI_RESTORE rdx
-       .endif
-       movq 7*8(%rsp),%rsi
-#      CFI_RESTORE rsi
-       movq 8*8(%rsp),%rdi
-#      CFI_RESTORE rdi
-       .if ARG_SKIP+\addskip > 0
-       addq $ARG_SKIP+\addskip,%rsp
-#      CFI_ADJUST_CFA_OFFSET   -(ARG_SKIP+\addskip)
-       .endif
-.endm  
-
-
-.macro HYPERVISOR_IRET flag
-#    testb $3,1*8(%rsp)    /* Don't need to do that in Mini-os, as */
-#      jnz   2f               /* there is no userspace? */
-       testl $NMI_MASK,2*8(%rsp)
-       jnz   2f
-
-       testb $1,(xen_features+XENFEAT_supervisor_mode_kernel)
-       jnz   1f
-
-       /* Direct iret to kernel space. Correct CS and SS. */
-       orb   $3,1*8(%rsp)
-       orb   $3,4*8(%rsp)
-1:     iretq
-
-2:     /* Slow iret via hypervisor. */
-       andl  $~NMI_MASK, 16(%rsp)
-       pushq $\flag
-       jmp  hypercall_page + (__HYPERVISOR_iret * 32)
-.endm
-
-/*
- * Exception entry point. This expects an error code/orig_rax on the stack
- * and the exception handler in %rax.  
- */                                            
-ENTRY(error_entry)
-#      _frame RDI
-       /* rdi slot contains rax, oldrax contains error code */
-       cld     
-       subq  $14*8,%rsp
-#      CFI_ADJUST_CFA_OFFSET   (14*8)
-       movq %rsi,13*8(%rsp)
-#      CFI_REL_OFFSET  rsi,RSI
-       movq 14*8(%rsp),%rsi    /* load rax from rdi slot */
-       movq %rdx,12*8(%rsp)
-#      CFI_REL_OFFSET  rdx,RDX
-       movq %rcx,11*8(%rsp)
-#      CFI_REL_OFFSET  rcx,RCX
-       movq %rsi,10*8(%rsp)    /* store rax */ 
-#      CFI_REL_OFFSET  rax,RAX
-       movq %r8, 9*8(%rsp)
-#      CFI_REL_OFFSET  r8,R8
-       movq %r9, 8*8(%rsp)
-#      CFI_REL_OFFSET  r9,R9
-       movq %r10,7*8(%rsp)
-#      CFI_REL_OFFSET  r10,R10
-       movq %r11,6*8(%rsp)
-#      CFI_REL_OFFSET  r11,R11
-       movq %rbx,5*8(%rsp) 
-#      CFI_REL_OFFSET  rbx,RBX
-       movq %rbp,4*8(%rsp) 
-#      CFI_REL_OFFSET  rbp,RBP
-       movq %r12,3*8(%rsp) 
-#      CFI_REL_OFFSET  r12,R12
-       movq %r13,2*8(%rsp) 
-#      CFI_REL_OFFSET  r13,R13
-       movq %r14,1*8(%rsp) 
-#      CFI_REL_OFFSET  r14,R14
-       movq %r15,(%rsp) 
-#      CFI_REL_OFFSET  r15,R15
-#if 0        
-       cmpl $__KERNEL_CS,CS(%rsp)
-       je  error_kernelspace
-#endif        
-error_call_handler:
-       movq %rdi, RDI(%rsp)            
-       movq %rsp,%rdi
-       movq ORIG_RAX(%rsp),%rsi        # get error code 
-       movq $-1,ORIG_RAX(%rsp)
-       call *%rax
-
-.macro zeroentry sym
-#      INTR_FRAME
-    movq (%rsp),%rcx
-    movq 8(%rsp),%r11
-    addq $0x10,%rsp /* skip rcx and r11 */
-       pushq $0        /* push error code/oldrax */ 
-#      CFI_ADJUST_CFA_OFFSET 8
-       pushq %rax      /* push real oldrax to the rdi slot */ 
-#      CFI_ADJUST_CFA_OFFSET 8
-       leaq  \sym(%rip),%rax
-       jmp error_entry
-#      CFI_ENDPROC
-.endm  
-
-.macro errorentry sym
-#      XCPT_FRAME
-        movq (%rsp),%rcx
-        movq 8(%rsp),%r11
-        addq $0x10,%rsp /* rsp points to the error code */
-       pushq %rax
-#      CFI_ADJUST_CFA_OFFSET 8
-       leaq  \sym(%rip),%rax
-       jmp error_entry
-#      CFI_ENDPROC
-.endm
-
-#define XEN_GET_VCPU_INFO(reg) movq HYPERVISOR_shared_info,reg
-#define XEN_PUT_VCPU_INFO(reg)
-#define XEN_PUT_VCPU_INFO_fixup
-#define XEN_LOCKED_BLOCK_EVENTS(reg)   movb $1,evtchn_upcall_mask(reg)
-#define XEN_LOCKED_UNBLOCK_EVENTS(reg) movb $0,evtchn_upcall_mask(reg)
-#define XEN_TEST_PENDING(reg)  testb $0xFF,evtchn_upcall_pending(reg)
-
-#define XEN_BLOCK_EVENTS(reg)  XEN_GET_VCPU_INFO(reg)                  ; \
-                                       XEN_LOCKED_BLOCK_EVENTS(reg)    ; \
-                                           XEN_PUT_VCPU_INFO(reg)
-
-#define XEN_UNBLOCK_EVENTS(reg)        XEN_GET_VCPU_INFO(reg)                  
; \
-                                               XEN_LOCKED_UNBLOCK_EVENTS(reg)  
; \
-                                       XEN_PUT_VCPU_INFO(reg)
-
-
-
-ENTRY(hypervisor_callback)
-    zeroentry hypervisor_callback2
-
-ENTRY(hypervisor_callback2)
-        movq %rdi, %rsp 
-11:     movq %gs:8,%rax
-        incl %gs:0
-        cmovzq %rax,%rsp
-        pushq %rdi
-        call do_hypervisor_callback 
-        popq %rsp
-        decl %gs:0
-        jmp error_exit
-
-#        ALIGN
-restore_all_enable_events:  
-       XEN_UNBLOCK_EVENTS(%rsi)        # %rsi is already set up...
-
-scrit: /**** START OF CRITICAL REGION ****/
-       XEN_TEST_PENDING(%rsi)
-       jnz  14f                        # process more events if necessary...
-       XEN_PUT_VCPU_INFO(%rsi)
-        RESTORE_ARGS 0,8,0
-        HYPERVISOR_IRET 0
-        
-14:    XEN_LOCKED_BLOCK_EVENTS(%rsi)
-       XEN_PUT_VCPU_INFO(%rsi)
-       SAVE_REST
-        movq %rsp,%rdi                  # set the argument again
-       jmp  11b
-ecrit:  /**** END OF CRITICAL REGION ****/
-
-
-retint_kernel:
-retint_restore_args:
-       movl EFLAGS-REST_SKIP(%rsp), %eax
-       shr $9, %eax                    # EAX[0] == IRET_EFLAGS.IF
-       XEN_GET_VCPU_INFO(%rsi)
-       andb evtchn_upcall_mask(%rsi),%al
-       andb $1,%al                     # EAX[0] == IRET_EFLAGS.IF & event_mask
-       jnz restore_all_enable_events   #        != 0 => enable event delivery
-       XEN_PUT_VCPU_INFO(%rsi)
-               
-       RESTORE_ARGS 0,8,0
-       HYPERVISOR_IRET 0
-
-
-error_exit:            
-       RESTORE_REST
-/*     cli */
-       XEN_BLOCK_EVENTS(%rsi)          
-       jmp retint_kernel
-
-
-
-ENTRY(failsafe_callback)
-        popq  %rcx
-        popq  %r11
-        iretq
-
-
-ENTRY(coprocessor_error)
-        zeroentry do_coprocessor_error
-
-
-ENTRY(simd_coprocessor_error)
-        zeroentry do_simd_coprocessor_error
-
-
-ENTRY(device_not_available)
-        zeroentry do_device_not_available
-
-
-ENTRY(debug)
-#       INTR_FRAME
-#       CFI_ADJUST_CFA_OFFSET 8 */
-        zeroentry do_debug
-#       CFI_ENDPROC
-
-
-ENTRY(int3)
-#       INTR_FRAME
-#       CFI_ADJUST_CFA_OFFSET 8 */
-        zeroentry do_int3
-#       CFI_ENDPROC
-
-ENTRY(overflow)
-        zeroentry do_overflow
-
-
-ENTRY(bounds)
-        zeroentry do_bounds
-    
-    
-ENTRY(invalid_op)
-        zeroentry do_invalid_op
-
-
-ENTRY(coprocessor_segment_overrun)
-        zeroentry do_coprocessor_segment_overrun
-
-
-ENTRY(invalid_TSS)
-        errorentry do_invalid_TSS
-
-
-ENTRY(segment_not_present)
-        errorentry do_segment_not_present
-
-
-/* runs on exception stack */
-ENTRY(stack_segment)
-#       XCPT_FRAME
-        errorentry do_stack_segment
-#       CFI_ENDPROC
-                    
-
-ENTRY(general_protection)
-        errorentry do_general_protection
-
-
-ENTRY(alignment_check)
-        errorentry do_alignment_check
-
-
-ENTRY(divide_error)
-        zeroentry do_divide_error
-
-
-ENTRY(spurious_interrupt_bug)
-        zeroentry do_spurious_interrupt_bug
-            
-
-ENTRY(page_fault)
-        errorentry do_page_fault
-
-
-
-
-
-ENTRY(thread_starter)
-        popq %rdi
-        popq %rbx
-        call *%rbx
-        call exit_thread 
-        
-
diff -r 3464bb656a9c -r 8475a4e0425e extras/mini-os/xenbus/xenbus.c
--- a/extras/mini-os/xenbus/xenbus.c    Thu Jan 18 09:54:33 2007 +0000
+++ b/extras/mini-os/xenbus/xenbus.c    Thu Jan 18 15:18:07 2007 +0000
@@ -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;
@@ -71,6 +71,34 @@ static void memcpy_from_ring(const void 
     memcpy(dest, ring + off, c1);
     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)
 {
@@ -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,9 +431,29 @@ char *xenbus_write(xenbus_transaction_t 
     struct xsd_sockmsg *rep;
     rep = xenbus_msg_reply(XS_WRITE, xbt, req, ARRAY_SIZE(req));
     char *msg = errmsg(rep);
-    if (msg)
-       return msg;
-    free(rep);
+    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;
 }
 
diff -r 3464bb656a9c -r 8475a4e0425e linux-2.6-xen-sparse/arch/i386/Kconfig
--- a/linux-2.6-xen-sparse/arch/i386/Kconfig    Thu Jan 18 09:54:33 2007 +0000
+++ b/linux-2.6-xen-sparse/arch/i386/Kconfig    Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e 
linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c     Thu Jan 18 
09:54:33 2007 +0000
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c     Thu Jan 18 
15:18:07 2007 +0000
@@ -89,7 +89,7 @@ static ssize_t microcode_write (struct f
 {
        ssize_t ret;
 
-       if (len < DEFAULT_UCODE_TOTALSIZE) {
+       if (len < MC_HEADER_SIZE) {
                printk(KERN_ERR "microcode: not enough data\n"); 
                return -EINVAL;
        }
diff -r 3464bb656a9c -r 8475a4e0425e 
linux-2.6-xen-sparse/arch/i386/kernel/pci-dma-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/pci-dma-xen.c       Thu Jan 18 
09:54:33 2007 +0000
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/pci-dma-xen.c       Thu Jan 18 
15:18:07 2007 +0000
@@ -114,13 +114,7 @@ dma_unmap_sg(struct device *hwdev, struc
 }
 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_a
                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 *
        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 *
        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 -r 3464bb656a9c -r 8475a4e0425e 
linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c   Thu Jan 18 09:54:33 
2007 +0000
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c   Thu Jan 18 15:18:07 
2007 +0000
@@ -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 @@ swiotlb_init_with_default_size (size_t d
 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 d
         */
        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 d
         * 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, c
                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, c
                                        /* 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
                                    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,
                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_de
 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 -r 3464bb656a9c -r 8475a4e0425e 
linux-2.6-xen-sparse/arch/i386/mm/fault-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/mm/fault-xen.c     Thu Jan 18 09:54:33 
2007 +0000
+++ b/linux-2.6-xen-sparse/arch/i386/mm/fault-xen.c     Thu Jan 18 15:18:07 
2007 +0000
@@ -262,16 +262,19 @@ static void dump_fault_path(unsigned lon
        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 lon
                        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 lon
                       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 lon
                printk(KERN_ALERT "*pte = ma %08lx pa %08lx\n", page,
                       machine_to_phys(page));
        }
-#endif
 }
 #endif
 
diff -r 3464bb656a9c -r 8475a4e0425e 
linux-2.6-xen-sparse/arch/i386/mm/highmem-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/mm/highmem-xen.c   Thu Jan 18 09:54:33 
2007 +0000
+++ b/linux-2.6-xen-sparse/arch/i386/mm/highmem-xen.c   Thu Jan 18 15:18:07 
2007 +0000
@@ -129,5 +129,6 @@ EXPORT_SYMBOL(kmap);
 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 -r 3464bb656a9c -r 8475a4e0425e 
linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c   Thu Jan 18 09:54:33 
2007 +0000
+++ b/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c   Thu Jan 18 15:18:07 
2007 +0000
@@ -239,23 +239,41 @@ struct page *pte_alloc_one(struct mm_str
 
 #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);
-
-       if (!pte_write(*virt_to_ptep(va)))
-               BUG_ON(HYPERVISOR_update_va_mapping(
-                       va, pfn_pte(page_to_pfn(pte), PAGE_KERNEL), 0));
+       unsigned long pfn = page_to_pfn(pte);
+
+       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 -r 3464bb656a9c -r 8475a4e0425e 
linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c
--- a/linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c        Thu Jan 18 
09:54:33 2007 +0000
+++ b/linux-2.6-xen-sparse/arch/x86_64/mm/pageattr-xen.c        Thu Jan 18 
15:18:07 2007 +0000
@@ -163,6 +163,18 @@ void _arch_exit_mmap(struct mm_struct *m
         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 -r 3464bb656a9c -r 8475a4e0425e 
linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Thu Jan 18 09:54:33 
2007 +0000
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Thu Jan 18 15:18:07 
2007 +0000
@@ -42,9 +42,30 @@ static void backend_changed(struct xenbu
 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 
        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 -r 3464bb656a9c -r 8475a4e0425e 
linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c  Thu Jan 18 09:54:33 
2007 +0000
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c  Thu Jan 18 15:18:07 
2007 +0000
@@ -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(blki
        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 -r 3464bb656a9c -r 8475a4e0425e 
linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c
--- a/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c     Thu Jan 18 
09:54:33 2007 +0000
+++ b/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c     Thu Jan 18 
15:18:07 2007 +0000
@@ -98,8 +98,8 @@ void xen_machine_kexec_setup_resources(v
  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 -r 3464bb656a9c -r 8475a4e0425e 
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/dma-mapping.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/dma-mapping.h  Thu Jan 
18 09:54:33 2007 +0000
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/dma-mapping.h  Thu Jan 
18 15:18:07 2007 +0000
@@ -53,6 +53,7 @@ extern void dma_unmap_sg(struct device *
 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 @@ extern void
 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 -r 3464bb656a9c -r 8475a4e0425e 
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/kmap_types.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/kmap_types.h   Thu Jan 
18 09:54:33 2007 +0000
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e 
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgalloc.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgalloc.h      Thu Jan 
18 09:54:33 2007 +0000
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgalloc.h      Thu Jan 
18 15:18:07 2007 +0000
@@ -41,7 +41,7 @@ static inline void pte_free_kernel(pte_t
 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 -r 3464bb656a9c -r 8475a4e0425e 
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/swiotlb.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/swiotlb.h      Thu Jan 
18 09:54:33 2007 +0000
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/swiotlb.h      Thu Jan 
18 15:18:07 2007 +0000
@@ -26,15 +26,15 @@ extern void swiotlb_unmap_sg(struct devi
 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;
diff -r 3464bb656a9c -r 8475a4e0425e 
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgalloc.h
--- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgalloc.h    Thu Jan 
18 09:54:33 2007 +0000
+++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgalloc.h    Thu Jan 
18 15:18:07 2007 +0000
@@ -64,42 +64,35 @@ static inline void pgd_populate(struct m
        }
 }
 
+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)
+{
+       struct page *pg;
+
+       pg = pte_alloc_one(mm, addr);
+       return pg ? page_address(pg) : NULL;
+}
+
 static inline void pmd_free(pmd_t *pmd)
 {
-       pte_t *ptep = virt_to_ptep(pmd);
-
-       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);
-}
-
-static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
-{
-        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 *p
 
 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
               (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,18 +180,10 @@ 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;
 }
 
@@ -208,18 +193,12 @@ static inline void pte_free_kernel(pte_t
 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 -r 3464bb656a9c -r 8475a4e0425e linux-2.6-xen-sparse/kernel/kexec.c
--- a/linux-2.6-xen-sparse/kernel/kexec.c       Thu Jan 18 09:54:33 2007 +0000
+++ b/linux-2.6-xen-sparse/kernel/kexec.c       Thu Jan 18 15:18:07 2007 +0000
@@ -1012,9 +1012,11 @@ asmlinkage long sys_kexec_load(unsigned 
                        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 -r 3464bb656a9c -r 8475a4e0425e patches/linux-2.6.18/ipv6-no-autoconf.patch
--- a/patches/linux-2.6.18/ipv6-no-autoconf.patch       Thu Jan 18 09:54:33 
2007 +0000
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e patches/linux-2.6.18/series
--- a/patches/linux-2.6.18/series       Thu Jan 18 09:54:33 2007 +0000
+++ b/patches/linux-2.6.18/series       Thu Jan 18 15:18:07 2007 +0000
@@ -5,7 +5,6 @@ blktap-aio-16_03_06.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 -r 3464bb656a9c -r 8475a4e0425e tools/check/check_udev
--- a/tools/check/check_udev    Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/check/check_udev    Thu Jan 18 15:18:07 2007 +0000
@@ -11,7 +11,7 @@ Linux)
 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 -r 3464bb656a9c -r 8475a4e0425e tools/examples/vtpm-common.sh
--- a/tools/examples/vtpm-common.sh     Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/examples/vtpm-common.sh     Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e tools/examples/xen-network-common.sh
--- a/tools/examples/xen-network-common.sh      Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/examples/xen-network-common.sh      Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e tools/examples/xmexample1
--- a/tools/examples/xmexample1 Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/examples/xmexample1 Thu Jan 18 15:18:07 2007 +0000
@@ -64,6 +64,40 @@ vif = [ '' ]
 # and MODE is r for read-only, w for read-write.
 
 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.
diff -r 3464bb656a9c -r 8475a4e0425e tools/examples/xmexample2
--- a/tools/examples/xmexample2 Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/examples/xmexample2 Thu Jan 18 15:18:07 2007 +0000
@@ -100,6 +100,40 @@ vif = [ '' ]
 # All domains get sda6 read-only (to use for /usr, see below).
 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.
diff -r 3464bb656a9c -r 8475a4e0425e tools/examples/xmexample3
--- a/tools/examples/xmexample3 Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/examples/xmexample3 Thu Jan 18 15:18:07 2007 +0000
@@ -85,6 +85,40 @@ vif = [ 'ip=192.168.%d.1/24' % (vmid)]
 # to all domains as sda1.
 # All domains get sda6 read-only (to use for /usr, see below).
 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.
diff -r 3464bb656a9c -r 8475a4e0425e tools/libfsimage/common/fsimage.c
--- a/tools/libfsimage/common/fsimage.c Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/libfsimage/common/fsimage.c Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e tools/libfsimage/common/fsimage_grub.c
--- a/tools/libfsimage/common/fsimage_grub.c    Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/libfsimage/common/fsimage_grub.c    Thu Jan 18 15:18:07 2007 +0000
@@ -193,6 +193,7 @@ static int
 static int
 fsig_umount(fsi_t *fsi)
 {
+       free(fsi->f_data);
        return (0);
 }
 
@@ -250,6 +251,7 @@ static int
 static int
 fsig_close(fsi_file_t *ffi)
 {
+       free(ffi->ff_data);
        fsip_file_free(ffi);
        return (0);
 }
diff -r 3464bb656a9c -r 8475a4e0425e tools/libfsimage/common/fsimage_plugin.c
--- a/tools/libfsimage/common/fsimage_plugin.c  Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/libfsimage/common/fsimage_plugin.c  Thu Jan 18 15:18:07 2007 +0000
@@ -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 @@ void
 void
 fsip_file_free(fsi_file_t *ffi)
 {
-       free(ffi->ff_data);
        free(ffi);
 }
 
diff -r 3464bb656a9c -r 8475a4e0425e tools/libfsimage/common/fsimage_plugin.h
--- a/tools/libfsimage/common/fsimage_plugin.h  Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/libfsimage/common/fsimage_plugin.h  Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e tools/libfsimage/common/mapfile-GNU
--- a/tools/libfsimage/common/mapfile-GNU       Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/libfsimage/common/mapfile-GNU       Thu Jan 18 15:18:07 2007 +0000
@@ -1,5 +1,5 @@ VERSION {
 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 -r 3464bb656a9c -r 8475a4e0425e tools/libfsimage/common/mapfile-SunOS
--- a/tools/libfsimage/common/mapfile-SunOS     Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/libfsimage/common/mapfile-SunOS     Thu Jan 18 15:18:07 2007 +0000
@@ -1,4 +1,4 @@ libfsimage.so.1.1 {
-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 -r 3464bb656a9c -r 8475a4e0425e tools/libfsimage/ext2fs-lib/ext2fs-lib.c
--- a/tools/libfsimage/ext2fs-lib/ext2fs-lib.c  Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/libfsimage/ext2fs-lib/ext2fs-lib.c  Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e tools/libxc/xc_hvm_build.c
--- a/tools/libxc/xc_hvm_build.c        Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/libxc/xc_hvm_build.c        Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e tools/libxc/xc_linux_build.c
--- a/tools/libxc/xc_linux_build.c      Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/libxc/xc_linux_build.c      Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e tools/libxc/xc_linux_restore.c
--- a/tools/libxc/xc_linux_restore.c    Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/libxc/xc_linux_restore.c    Thu Jan 18 15:18:07 2007 +0000
@@ -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 */
@@ -29,6 +29,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
@@ -57,46 +60,78 @@ read_exact(int fd, void *buf, size_t cou
 ** 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];
-
-        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;
-
-
-
-        }
+        
+        /* 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(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 
     /* 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 
     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));
-
-    if ((p2m == NULL) || (pfn_type == NULL) || (region_mfn == NULL)) {
+    p2m_batch  = calloc(MAX_BATCH_SIZE, sizeof(xen_pfn_t));
+
+    if ((p2m == NULL) || (pfn_type == NULL) ||
+        (region_mfn == NULL) || (p2m_batch == NULL)) {
         ERROR("memory alloc failed");
         errno = ENOMEM;
         goto out;
@@ -253,6 +291,11 @@ int xc_linux_restore(int xc_handle, int 
 
     if (lock_pages(region_mfn, sizeof(xen_pfn_t) * MAX_BATCH_SIZE)) {
         ERROR("Could not lock region_mfn");
+        goto out;
+    }
+
+    if (lock_pages(p2m_batch, sizeof(xen_pfn_t) * MAX_BATCH_SIZE)) {
+        ERROR("Could not lock p2m_batch");
         goto out;
     }
 
@@ -270,17 +313,9 @@ int xc_linux_restore(int xc_handle, int 
         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 
     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 
             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) && 
+                 (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] = 0; /* we know map will fail, but don't care */
-            else
-                region_mfn[i] = p2m[pfn];
-        }
-
+                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 
                     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 
                                 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 
         */
 
         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 
                 }
 
                 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 
     {
         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 
             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 (count > 0) {
+            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 (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 
     free(pfn_type);
 
     DPRINTF("Restore exit with rc=%d\n", rc);
-
+    
     return rc;
 }
diff -r 3464bb656a9c -r 8475a4e0425e tools/libxc/xc_linux_save.c
--- a/tools/libxc/xc_linux_save.c       Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/libxc/xc_linux_save.c       Thu Jan 18 15:18:07 2007 +0000
@@ -660,13 +660,6 @@ int xc_linux_save(int xc_handle, int io_
         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 -r 3464bb656a9c -r 8475a4e0425e tools/libxc/xc_load_elf.c
--- a/tools/libxc/xc_load_elf.c Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/libxc/xc_load_elf.c Thu Jan 18 15:18:07 2007 +0000
@@ -406,17 +406,19 @@ static int parseelfimage(const char *ima
     }
 
     /*
-     * 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 -r 3464bb656a9c -r 8475a4e0425e tools/libxc/xc_ptrace.c
--- a/tools/libxc/xc_ptrace.c   Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/libxc/xc_ptrace.c   Thu Jan 18 15:18:07 2007 +0000
@@ -166,14 +166,11 @@ static unsigned long           *page_arr
  * tables.
  *
  */
-static unsigned long
-to_ma(int cpu,
-      unsigned long in_addr)
-{
-    unsigned long maddr = in_addr;
-
+static uint64_t
+to_ma(int cpu, uint64_t maddr)
+{
     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 -r 3464bb656a9c -r 8475a4e0425e tools/pygrub/src/pygrub
--- a/tools/pygrub/src/pygrub   Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/pygrub/src/pygrub   Thu Jan 18 15:18:07 2007 +0000
@@ -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.Text
         
 
 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
 
+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 run_main(scr, *args):
-        global sel
-        sel = g.run()
-
     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)
-
-    kernel = fs.open_file(img.kernel[1],).read()
-    (tfd, fn) = tempfile.mkstemp(prefix="boot_kernel.",
+
+    fs = fsimage.open(file, get_fs_offset(file))
+
+    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 -r 3464bb656a9c -r 8475a4e0425e tools/python/xen/xend/XendBootloader.py
--- a/tools/python/xen/xend/XendBootloader.py   Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/python/xen/xend/XendBootloader.py   Thu Jan 18 15:18:07 2007 +0000
@@ -53,6 +53,12 @@ def bootloader(blexec, disk, quiet = Fal
     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 -r 3464bb656a9c -r 8475a4e0425e tools/python/xen/xend/XendCheckpoint.py
--- a/tools/python/xen/xend/XendCheckpoint.py   Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/python/xen/xend/XendCheckpoint.py   Thu Jan 18 15:18:07 2007 +0000
@@ -147,18 +147,20 @@ def restore(xd, fd, dominfo = None, paus
     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 -r 3464bb656a9c -r 8475a4e0425e tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py       Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/python/xen/xend/XendConfig.py       Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e tools/python/xen/xend/XendDomain.py
--- a/tools/python/xen/xend/XendDomain.py       Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/python/xen/xend/XendDomain.py       Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/python/xen/xend/XendDomainInfo.py   Thu Jan 18 15:18:07 2007 +0000
@@ -37,7 +37,7 @@ from xen.util.blkif import blkdev_uname_
 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 -r 3464bb656a9c -r 8475a4e0425e tools/python/xen/xend/XendNode.py
--- a/tools/python/xen/xend/XendNode.py Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/python/xen/xend/XendNode.py Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e tools/python/xen/xend/osdep.py
--- a/tools/python/xen/xend/osdep.py    Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/python/xen/xend/osdep.py    Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e tools/python/xen/xend/server/blkif.py
--- a/tools/python/xen/xend/server/blkif.py     Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/python/xen/xend/server/blkif.py     Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py     Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/python/xen/xm/create.py     Thu Jan 18 15:18:07 2007 +0000
@@ -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},vnc
           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 -r 3464bb656a9c -r 8475a4e0425e tools/tests/Makefile
--- a/tools/tests/Makefile      Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/tests/Makefile      Thu Jan 18 15:18:07 2007 +0000
@@ -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 @@ x86_emulate.o: $(XEN_ROOT)/xen/arch/x86/
 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 -r 3464bb656a9c -r 8475a4e0425e tools/tests/blowfish.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/tests/blowfish.c    Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e tools/tests/blowfish.mk
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/tests/blowfish.mk   Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e tools/tests/test_x86_emulator.c
--- a/tools/tests/test_x86_emulator.c   Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/tests/test_x86_emulator.c   Thu Jan 18 15:18:07 2007 +0000
@@ -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;
-
-    res = mmap((void *)0x100000, 0x1000, PROT_READ|PROT_WRITE,
+    ctxt.addr_size = 32;
+    ctxt.sp_size   = 32;
+
+    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 -r 3464bb656a9c -r 8475a4e0425e tools/xenstat/xentop/xentop.c
--- a/tools/xenstat/xentop/xentop.c     Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/xenstat/xentop/xentop.c     Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e tools/xm-test/README
--- a/tools/xm-test/README      Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/xm-test/README      Thu Jan 18 15:18:07 2007 +0000
@@ -207,6 +207,49 @@ running DomUs on the system to provide e
 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 -r 3464bb656a9c -r 8475a4e0425e tools/xm-test/configure.ac
--- a/tools/xm-test/configure.ac        Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/xm-test/configure.ac        Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e tools/xm-test/grouptest/xapi
--- a/tools/xm-test/grouptest/xapi      Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/xm-test/grouptest/xapi      Thu Jan 18 15:18:07 2007 +0000
@@ -1,1 +1,2 @@ vtpm 09_vtpm-xapi.test
+xapi
 vtpm 09_vtpm-xapi.test
diff -r 3464bb656a9c -r 8475a4e0425e 
tools/xm-test/lib/XmTestLib/DomainTracking.py
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/xm-test/lib/XmTestLib/DomainTracking.py     Thu Jan 18 15:18:07 
2007 +0000
@@ -0,0 +1,61 @@
+#!/usr/bin/python
+"""
+ Copyright (C) International Business Machines Corp., 2005
+ Author: Dan Smith <danms@xxxxxxxxxx>
+
+ 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 -r 3464bb656a9c -r 8475a4e0425e tools/xm-test/lib/XmTestLib/XenAPIDomain.py
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/xm-test/lib/XmTestLib/XenAPIDomain.py       Thu Jan 18 15:18:07 
2007 +0000
@@ -0,0 +1,176 @@
+#!/usr/bin/python
+"""
+ Copyright (C) International Business Machines Corp., 2005
+ Author: Stefan Berger <stefanb@xxxxxxxxxx>
+
+ Based on XenDomain.py by Dan Smith <danms@xxxxxxxxxx>
+
+ 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 os
+import sys
+from XmTestLib import *
+from xen.util.xmlrpclib2 import ServerProxy
+from types import DictType
+
+
+class XenAPIConfig:
+    """An object to help create a VM configuration usable via Xen-API"""
+    def __init__(self):
+        self.opts = {}
+        #Array to translate old option to new ones
+        self.opttrlate = { 'name' : 'name_label' ,
+                           'memory' : [ 'memory_static_max' ,
+                                        'memory_static_min' ,
+                                        'memory_dynamic_min',
+                                        'memory_dynamic_max' ],
+                           'kernel' : 'PV_kernel',
+                           'ramdisk': 'PV_ramdisk',
+                           'root'   : 'PV_args'}
+
+    def setOpt(self, name, value):
+        """Set an option in the config"""
+        if name in self.opttrlate.keys():
+            _name = self.opttrlate[name]
+        else:
+            _name = name
+
+        if isinstance(_name, list):
+            for _n in _name:
+                self.opts[_n] = value
+        else:
+            self.opts[_name] = value
+
+    def getOpt(self, name):
+        """Return the value of a config option"""
+        if name in self.opts.keys():
+            return self.opts[name]
+        else:
+            return None
+
+    def setOpts(self, opts):
+        """Batch-set options from a dictionary"""
+        for k, v in opts.items():
+            self.setOpt(k, v)
+
+    def getOpts(self):
+        return self.opts
+
+
+class XenAPIDomain(XenDomain):
+
+    def __init__(self, name=None, config=None):
+        if name:
+            self.name = name
+        else:
+            self.name = getUniqueName()
+
+        self.config = config
+        self.console = None
+        self.netEnv = "bridge"
+
+        self.session = xapi.connect()
+        session = self.session
+        try:
+            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.")
+
+        #Only support PV for now.
+        self.type = "PV"
+
+    def start(self, noConsole=False, startpaused=False):
+        #start the VM
+        session = self.session
+        if self.vm_uuid:
+            try:
+                session.xenapi.VM.start(self.vm_uuid, startpaused)
+            except:
+                raise DomainError("Could not start domain")
+        else:
+            raise DomainError("VM has no UUID - does VM config exist?")
+
+        if startpaused:
+           return
+
+        if self.getDomainType() == "HVM":
+           waitForBoot()
+
+        if self.console and noConsole == True:
+            self.closeConsole()
+
+        elif self.console and noConsole == False:
+            return self.console
+
+        elif not self.console and noConsole == False:
+            return self.getConsole()
+
+    def stop(self):
+        if self.vm_uuid:
+            self.session.xenapi.VM.hard_shutdown(self.vm_uuid)
+        else:
+            raise DomainError("VM has no UUID - does VM config exist?")
+
+    def destroy(self):
+        #Stop VM first.
+        self.stop()
+        if self.vm_uuid:
+            self.session.xenapi.VM.destroy(self.vm_uuid)
+            delXAPIDomain(self.vm_uuid)
+        else:
+            raise DomainError("VM has no UUID - does VM config exist?")
+
+    def get_uuid(self):
+        return self.vm_uuid
+
+    def newDevice(self, Device, *args):
+        raise DomainError("No support for newDevice().")
+
+    def removeDevice(self, id):
+        raise DomainError("No support for removeDevice().")
+
+    def removeAllDevices(self, id):
+        raise DomainError("No support for removeAllDevices().")
+
+    def isRunning(self):
+        return isDomainRunning(self.name)
+
+    def getDevice(self, id):
+        raise DomainError("No support for getDevice().")
+
+
+class XmTestAPIDomain(XenAPIDomain):
+
+    """Create a new managed xm-test domain
+    @param name: The requested domain name
+    @param extraConfig: Additional configuration options
+    @param baseConfig: The initial configuration defaults to use
+    """
+    def __init__(self, name=None, extraConfig=None,
+                 baseConfig=arch.configDefaults):
+        config = XenAPIConfig()
+        config.setOpts(baseConfig)
+        if extraConfig:
+            config.setOpts(extraConfig)
+
+        if name:
+            config.setOpt("name_label", name)
+        elif not config.getOpt("name_label"):
+            config.setOpt("name_label", getUniqueName())
+
+        XenAPIDomain.__init__(self, config.getOpt("name_label"),
+                              config=config)
diff -r 3464bb656a9c -r 8475a4e0425e tools/xm-test/lib/XmTestLib/XenDomain.py
--- a/tools/xm-test/lib/XmTestLib/XenDomain.py  Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/xm-test/lib/XmTestLib/XenDomain.py  Thu Jan 18 15:18:07 2007 +0000
@@ -29,6 +29,7 @@ from config 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 XmTestDomain(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 -r 3464bb656a9c -r 8475a4e0425e 
tools/xm-test/lib/XmTestLib/XenManagedDomain.py
--- a/tools/xm-test/lib/XmTestLib/XenManagedDomain.py   Thu Jan 18 09:54:33 
2007 +0000
+++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
@@ -1,177 +0,0 @@
-#!/usr/bin/python
-"""
- Copyright (C) International Business Machines Corp., 2005
- Author: Stefan Berger <stefanb@xxxxxxxxxx>
-
- Based on XenDomain.py by Dan Smith <danms@xxxxxxxxxx>
-
- 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 os
-import sys
-from XmTestLib import *
-from xen.util.xmlrpclib2 import ServerProxy
-from types import DictType
-
-
-class XenManagedConfig:
-    """An object to help create a VM configuration usable via Xen-API"""
-    def __init__(self):
-        self.opts = {}
-        #Array to translate old option to new ones
-        self.opttrlate = { 'name' : 'name_label' ,
-                           'memory' : [ 'memory_static_max' ,
-                                        'memory_static_min' ,
-                                        'memory_dynamic_min',
-                                        'memory_dynamic_max' ],
-                           'kernel' : 'kernel_kernel',
-                           'ramdisk': 'kernel_initrd',
-                           'root'   : 'kernel_args'}
-
-    def setOpt(self, name, value):
-        """Set an option in the config"""
-        if name in self.opttrlate.keys():
-            _name = self.opttrlate[name]
-        else:
-            _name = name
-
-        if isinstance(_name, list):
-            for _n in _name:
-                self.opts[_n] = value
-        else:
-            self.opts[_name] = value
-
-    def getOpt(self, name):
-        """Return the value of a config option"""
-        if name in self.opts.keys():
-            return self.opts[name]
-        else:
-            return None
-
-    def setOpts(self, opts):
-        """Batch-set options from a dictionary"""
-        for k, v in opts.items():
-            self.setOpt(k, v)
-
-    def getOpts(self):
-        return self.opts
-
-
-class XenManagedDomain(XenDomain):
-
-    def __init__(self, name=None, config=None):
-        if name:
-            self.name = name
-        else:
-            self.name = getUniqueName()
-
-        self.config = config
-        self.console = None
-        self.netEnv = "bridge"
-
-        self.server, self.session = xapi._connect()
-        server = self.server
-        try:
-            self.vm_uuid = xapi.execute(server.VM.create, self.session,
-                                        self.config.getOpts())
-            xapi._VMuuids.append(self.vm_uuid)
-        except:
-            raise DomainError("Could not create VM config file for "
-                              "managed domain.")
-
-        #Only support PV for now.
-        self.type = "PV"
-
-    def start(self, noConsole=False, startpaused=False):
-        #start the VM
-        server = self.server
-        if self.vm_uuid:
-            try:
-                xapi.execute(server.VM.start, self.session, self.vm_uuid,
-                             startpaused)
-            except:
-                raise DomainError("Could not start domain")
-        else:
-            raise DomainError("VM has not UUID - VM config does not exist?")
-
-        if self.getDomainType() == "HVM":
-           waitForBoot()
-
-        if self.console and noConsole == True:
-            self.closeConsole()
-
-        elif self.console and noConsole == False:
-            return self.console
-
-        elif not self.console and noConsole == False:
-            return self.getConsole()
-
-    def stop(self):
-        if self.vm_uuid:
-            server = self.server
-            xapi.execute(server.VM.hard_shutdown, self.session, self.vm_uuid)
-        else:
-            raise DomainError("VM has not UUID - VM config does not 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)
-        else:
-            raise DomainError("VM has not UUID - VM config does not exist?")
-
-    def get_uuid(self):
-        return self.vm_uuid
-
-    def newDevice(self, Device, *args):
-        raise DomainError("No support for newDevice().")
-
-    def removeDevice(self, id):
-        raise DomainError("No support for removeDevice().")
-
-    def removeAllDevices(self, id):
-        raise DomainError("No support for removeAllDevices().")
-
-    def isRunning(self):
-        return isDomainRunning(self.name)
-
-    def getDevice(self, id):
-        raise DomainError("No support for getDevice().")
-
-
-class XmTestManagedDomain(XenManagedDomain):
-
-    """Create a new managed xm-test domain
-    @param name: The requested domain name
-    @param extraConfig: Additional configuration options
-    @param baseConfig: The initial configuration defaults to use
-    """
-    def __init__(self, name=None, extraConfig=None,
-                 baseConfig=arch.configDefaults):
-        config = XenManagedConfig()
-        config.setOpts(baseConfig)
-        if extraConfig:
-            config.setOpts(extraConfig)
-
-        if name:
-            config.setOpt("name_label", name)
-        elif not config.getOpt("name_label"):
-            config.setOpt("name_label", getUniqueName())
-
-        XenManagedDomain.__init__(self, config.getOpt("name_label"),
-                                  config=config)
diff -r 3464bb656a9c -r 8475a4e0425e tools/xm-test/lib/XmTestLib/Xm.py
--- a/tools/xm-test/lib/XmTestLib/Xm.py Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/xm-test/lib/XmTestLib/Xm.py Thu Jan 18 15:18:07 2007 +0000
@@ -48,6 +48,8 @@ def domid(name):
     status, output = traceCommand("xm domid " + name);
 
     if status != 0 or "Traceback" in output:
+        return -1
+    if output == "None":
         return -1
     try:
         return int(output)
diff -r 3464bb656a9c -r 8475a4e0425e tools/xm-test/lib/XmTestLib/xapi.py
--- a/tools/xm-test/lib/XmTestLib/xapi.py       Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/xm-test/lib/XmTestLib/xapi.py       Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e tools/xm-test/ramdisk/Makefile.am
--- a/tools/xm-test/ramdisk/Makefile.am Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/xm-test/ramdisk/Makefile.am Thu Jan 18 15:18:07 2007 +0000
@@ -36,7 +36,12 @@ XMTEST_VER_IMG = initrd-$(XMTEST_MAJ_VER
 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 @@ endif
 
 $(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 -r 3464bb656a9c -r 8475a4e0425e tools/xm-test/ramdisk/skel/etc/init.d/rcS
--- a/tools/xm-test/ramdisk/skel/etc/init.d/rcS Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/xm-test/ramdisk/skel/etc/init.d/rcS Thu Jan 18 15:18:07 2007 +0000
@@ -6,3 +6,14 @@ if uname -r | grep -q '^2.6'; then
 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 -r 3464bb656a9c -r 8475a4e0425e tools/xm-test/runtest.sh
--- a/tools/xm-test/runtest.sh  Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/xm-test/runtest.sh  Thu Jan 18 15:18:07 2007 +0000
@@ -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,10 +219,13 @@ unsafe=no
 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 ]
@@ -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 -r 3464bb656a9c -r 8475a4e0425e 
tools/xm-test/tests/sched-credit/01_sched_credit_weight_cap_pos.py
--- a/tools/xm-test/tests/sched-credit/01_sched_credit_weight_cap_pos.py        
Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/xm-test/tests/sched-credit/01_sched_credit_weight_cap_pos.py        
Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e tools/xm-test/tests/vtpm/09_vtpm-xapi.py
--- a/tools/xm-test/tests/vtpm/09_vtpm-xapi.py  Thu Jan 18 09:54:33 2007 +0000
+++ b/tools/xm-test/tests/vtpm/09_vtpm-xapi.py  Thu Jan 18 15:18:07 2007 +0000
@@ -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()
+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()
 
-    vtpmcfg = {}
-    vtpmcfg['type'] = "paravirtualised"
-    vtpmcfg['backend'] = "Domain-0"
-    vtpmcfg['instance'] = 1
-    vtpmcfg['VM'] = vm_uuid
+vtpmcfg = {}
+vtpmcfg['type'] = "paravirtualised"
+vtpmcfg['backend'] = "Domain-0"
+vtpmcfg['instance'] = 1
+vtpmcfg['VM'] = vm_uuid
 
-    server, session = xapi._connect()
+session = xapi.connect()
 
-    vtpm_uuid = xapi.execute(server.VTPM.create, session, vtpmcfg)
+vtpm_uuid = session.xenapi.VTPM.create(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']))
+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']))
 
-    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']))
+driver = session.xenapi.VTPM.get_driver(vtpm_uuid)
+if driver != vtpmcfg['type']:
+    FAIL("vTPM has driver type '%s', expected: '%s'" %
+         (driver, vtpmcfg['type']))
 
-    vtpm_rec = xapi.execute(server.VTPM.get_record, session, vtpm_uuid)
+vtpm_rec = session.xenapi.VTPM.get_record(vtpm_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))
+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()
+success = domain.start()
 
-    console = domain.getConsole()
-
-    try:
-        run = console.runCmd("cat /sys/devices/xen/vtpm-0/pcrs")
-    except ConsoleError, e:
-        saveLog(console.getHistory())
-        vtpm_cleanup(domName)
-        FAIL("No result from dumping the PCRs")
-
-    if re.search("No such file",run["output"]):
-        vtpm_cleanup(domName)
-        FAIL("TPM frontend support not compiled into (domU?) kernel")
-
-    domain.stop()
-    domain.destroy()
-
-
+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 -r 3464bb656a9c -r 8475a4e0425e 
tools/xm-test/tests/xapi/01_xapi-vm_basic.py
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/xm-test/tests/xapi/01_xapi-vm_basic.py      Thu Jan 18 15:18:07 
2007 +0000
@@ -0,0 +1,61 @@
+#!/usr/bin/python
+
+# Copyright (C) International Business Machines Corp., 2006
+# Author: Stefan Berger <stefanb@xxxxxxxxxx>
+
+# 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 -r 3464bb656a9c -r 8475a4e0425e tools/xm-test/tests/xapi/Makefile.am
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/xm-test/tests/xapi/Makefile.am      Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e 
unmodified_drivers/linux-2.6/platform-pci/platform-pci.c
--- a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c  Thu Jan 18 
09:54:33 2007 +0000
+++ b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c  Thu Jan 18 
15:18:07 2007 +0000
@@ -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_d
        }
        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(s
        mmio_addr = pci_resource_start(pdev, 1);
        mmio_len = pci_resource_len(pdev, 1);
 
-       callback_irq = get_callback_irq(pdev);
-
-       if (mmio_addr == 0 || ioaddr == 0 || callback_irq == 0) {
+       callback_via = get_callback_via(pdev);
+
+       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(s
        if ((ret = init_xen_info()))
                goto out;
 
-       if ((ret = request_irq(pdev->irq, evtchn_interrupt, SA_SHIRQ,
-                              "xen-platform-pci", pdev))) {
-               goto out;
-       }
-
-       if ((ret = set_callback_irq(callback_irq)))
+       if ((ret = request_irq(pdev->irq, evtchn_interrupt,
+                              SA_SHIRQ | SA_SAMPLE_RANDOM,
+                              "xen-platform-pci", pdev)))
+               goto out;
+
+       if ((ret = set_callback_via(callback_via)))
                goto out;
 
  out:
@@ -297,7 +305,7 @@ static void __exit platform_pci_module_c
 {
        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 -r 3464bb656a9c -r 8475a4e0425e 
unmodified_drivers/linux-2.6/platform-pci/platform-pci.h
--- a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.h  Thu Jan 18 
09:54:33 2007 +0000
+++ b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.h  Thu Jan 18 
15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e xen/arch/ia64/linux-xen/unaligned.c
--- a/xen/arch/ia64/linux-xen/unaligned.c       Thu Jan 18 09:54:33 2007 +0000
+++ b/xen/arch/ia64/linux-xen/unaligned.c       Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e xen/arch/ia64/xen/xenmisc.c
--- a/xen/arch/ia64/xen/xenmisc.c       Thu Jan 18 09:54:33 2007 +0000
+++ b/xen/arch/ia64/xen/xenmisc.c       Thu Jan 18 15:18:07 2007 +0000
@@ -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_
        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 -r 3464bb656a9c -r 8475a4e0425e xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Thu Jan 18 09:54:33 2007 +0000
+++ b/xen/arch/x86/domain.c     Thu Jan 18 15:18:07 2007 +0000
@@ -1047,7 +1047,7 @@ void context_switch(struct vcpu *prev, s
 
     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 -r 3464bb656a9c -r 8475a4e0425e xen/arch/x86/hvm/hpet.c
--- a/xen/arch/x86/hvm/hpet.c   Thu Jan 18 09:54:33 2007 +0000
+++ b/xen/arch/x86/hvm/hpet.c   Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Thu Jan 18 09:54:33 2007 +0000
+++ b/xen/arch/x86/hvm/hvm.c    Thu Jan 18 15:18:07 2007 +0000
@@ -800,7 +800,7 @@ long do_hvm_op(unsigned long op, XEN_GUE
                 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 -r 3464bb656a9c -r 8475a4e0425e xen/arch/x86/hvm/i8254.c
--- a/xen/arch/x86/hvm/i8254.c  Thu Jan 18 09:54:33 2007 +0000
+++ b/xen/arch/x86/hvm/i8254.c  Thu Jan 18 15:18:07 2007 +0000
@@ -182,11 +182,9 @@ void pit_time_fired(struct vcpu *v, void
     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(PITCha
     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 *opaqu
         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 -r 3464bb656a9c -r 8475a4e0425e xen/arch/x86/hvm/irq.c
--- a/xen/arch/x86/hvm/irq.c    Thu Jan 18 09:54:33 2007 +0000
+++ b/xen/arch/x86/hvm/irq.c    Thu Jan 18 15:18:07 2007 +0000
@@ -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:
-    spin_unlock(&hvm_irq->lock);
-}
-
-void hvm_pci_intx_deassert(
+}
+
+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);
+}
+
+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;
-
-    if ( local_events_need_delivery() )
-    {
-        if ( !__test_and_set_bit(0, &hvm_irq->callback_irq_wire) &&
-             (hvm_irq->gsi_assert_count[gsi]++ == 0) )
+    hvm_irq->callback_via_asserted = asserted;
+
+    /* Callback status has changed. Update the callback via. */
+    switch ( hvm_irq->callback_via_type )
+    {
+    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 domai
             d->domain_id, link, old_isa_irq, isa_irq);
 }
 
-void hvm_set_callback_gsi(struct domain *d, unsigned int gsi)
-{
-    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
-    unsigned int old_gsi;
-
-    if ( gsi >= ARRAY_SIZE(hvm_irq->gsi_assert_count) )
-        gsi = 0;
-
-    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);
-
-    if ( gsi && (hvm_irq->gsi_assert_count[gsi]++ == 0) )
-    {
-        vioapic_irq_positive_edge(d, gsi);
-        if ( gsi <= 15 )
-            vpic_irq_positive_edge(d, gsi);
-    }
-
- out:
-    spin_unlock(&hvm_irq->lock);
-
-    dprintk(XENLOG_G_INFO, "Dom%u callback GSI changed %u -> %u\n",
-            d->domain_id, old_gsi, gsi);
+void hvm_set_callback_via(struct domain *d, uint64_t via)
+{
+    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+    unsigned int gsi=0, pdev=0, pintx=0;
+    uint8_t via_type;
+
+    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);
+
+    /* 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;
+        }
+    }
+
+    /* Set up new callback via. */
+    switch ( hvm_irq->callback_via_type = via_type )
+    {
+    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;
+    }
+
+    spin_unlock(&hvm_irq->lock);
+
+    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 -r 3464bb656a9c -r 8475a4e0425e xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Thu Jan 18 09:54:33 2007 +0000
+++ b/xen/arch/x86/hvm/svm/svm.c        Thu Jan 18 15:18:07 2007 +0000
@@ -482,8 +482,8 @@ static int svm_guest_x86_mode(struct vcp
 {
     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 -r 3464bb656a9c -r 8475a4e0425e xen/arch/x86/hvm/vioapic.c
--- a/xen/arch/x86/hvm/vioapic.c        Thu Jan 18 09:54:33 2007 +0000
+++ b/xen/arch/x86/hvm/vioapic.c        Thu Jan 18 15:18:07 2007 +0000
@@ -309,6 +309,13 @@ static uint32_t ioapic_get_delivery_bitm
     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 vioap
     {
 #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 vioap
             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 -r 3464bb656a9c -r 8475a4e0425e xen/arch/x86/hvm/vmx/vmcs.c
--- a/xen/arch/x86/hvm/vmx/vmcs.c       Thu Jan 18 09:54:33 2007 +0000
+++ b/xen/arch/x86/hvm/vmx/vmcs.c       Thu Jan 18 15:18:07 2007 +0000
@@ -278,7 +278,14 @@ static void vmx_set_host_env(struct vcpu
     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 -r 3464bb656a9c -r 8475a4e0425e xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Thu Jan 18 09:54:33 2007 +0000
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Thu Jan 18 15:18:07 2007 +0000
@@ -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_bas
     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 vcp
 
     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
     }
 }
 
+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 -r 3464bb656a9c -r 8475a4e0425e xen/arch/x86/hvm/vmx/x86_32/exits.S
--- a/xen/arch/x86/hvm/vmx/x86_32/exits.S       Thu Jan 18 09:54:33 2007 +0000
+++ b/xen/arch/x86/hvm/vmx/x86_32/exits.S       Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e xen/arch/x86/hvm/vmx/x86_64/exits.S
--- a/xen/arch/x86/hvm/vmx/x86_64/exits.S       Thu Jan 18 09:54:33 2007 +0000
+++ b/xen/arch/x86/hvm/vmx/x86_64/exits.S       Thu Jan 18 15:18:07 2007 +0000
@@ -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 -r 3464bb656a9c -r 8475a4e0425e xen/arch/x86/microcode.c
--- a/xen/arch/x86/microcode.c  Thu Jan 18 09:54:33 2007 +0000
+++ b/xen/arch/x86/microcode.c  Thu Jan 18 15:18:07 2007 +0000
@@ -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(vo
 {
        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 -r 3464bb656a9c -r 8475a4e0425e xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Thu Jan 18 09:54:33 2007 +0000
+++ b/xen/arch/x86/mm.c Thu Jan 18 15:18:07 2007 +0000
@@ -154,6 +154,15 @@ l2_pgentry_t *compat_idle_pg_table_l2 = 
 #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 *
     }
 
     /* 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
 {
     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
 {
     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
 {
     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(struc
     }
 #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 *pl
         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 *pl
         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 *pa
          * (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 = 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;
-            }
-        }
+    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) )
+    {
+        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, u
                        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, u
     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, u
          (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 -r 3464bb656a9c -r 8475a4e0425e xen/arch/x86/mm/shadow/common.c
--- a/xen/arch/x86/mm/shadow/common.c   Thu Jan 18 09:54:33 2007 +0000
+++ b/xen/arch/x86/mm/shadow/common.c   Thu Jan 18 15:18:07 2007 +0000
@@ -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 @@ struct x86_emulate_ops *shadow_init_emul
 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_emul
 
     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_emul
     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 -r 3464bb656a9c -r 8475a4e0425e xen/arch/x86/mm/shadow/multi.c
--- a/xen/arch/x86/mm/shadow/multi.c    Thu Jan 18 09:54:33 2007 +0000
+++ b/xen/arch/x86/mm/shadow/multi.c    Thu Jan 18 15:18:07 2007 +0000
@@ -851,9 +851,7 @@ static inline void safe_write_entry(void
      * 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, uns
     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, u
                   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 -r 3464bb656a9c -r 8475a4e0425e xen/arch/x86/mm/shadow/private.h
--- a/xen/arch/x86/mm/shadow/private.h  Thu Jan 18 09:54:33 2007 +0000
+++ b/xen/arch/x86/mm/shadow/private.h  Thu Jan 18 15:18:07 2007 +0000
@@ -427,6 +427,11 @@ extern int sh_remove_write_access(struct
 #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 -r 3464bb656a9c -r 8475a4e0425e xen/arch/x86/oprofile/nmi_int.c
--- a/xen/arch/x86/oprofile/nmi_int.c   Thu Jan 18 09:54:33 2007 +0000
+++ b/xen/arch/x86/oprofile/nmi_int.c   Thu Jan 18 15:18:07 2007 +0000
@@ -42,7 +42,7 @@ extern size_t strlcpy(char *dest, const 
 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 -r 3464bb656a9c -r 8475a4e0425e xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c      Thu Jan 18 09:54:33 2007 +0000
+++ b/xen/arch/x86/setup.c      Thu Jan 18 15:18:07 2007 +0000
@@ -411,6 +411,23 @@ void __init __start_xen(multiboot_info_t
         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
             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
             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
 #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 -r 3464bb656a9c -r 8475a4e0425e xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c      Thu Jan 18 09:54:33 2007 +0000
+++ b/xen/arch/x86/traps.c      Thu Jan 18 15:18:07 2007 +0000
@@ -1121,7 +1121,7 @@ static int emulate_privileged_op(struct 
 {
     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 
             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 
     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 
 
     /* 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 
 
     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 
 
     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 
 
     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 
 
     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
 }
  
 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 -r 3464bb656a9c -r 8475a4e0425e xen/arch/x86/x86_64/compat/mm.c
--- a/xen/arch/x86/x86_64/compat/mm.c   Thu Jan 18 09:54:33 2007 +0000
+++ b/xen/arch/x86/x86_64/compat/mm.c   Thu Jan 18 15:18:07 2007 +0000
@@ -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(mm
             if ( err == __HYPERVISOR_mmuext_op )
             {
                 struct cpu_user_regs *regs = guest_cpu_user_regs();
-                unsigned int left = regs->ecx & ~MMU_UPDATE_PREEMPTED;
-
-                BUG_ON(!(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(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 -r 3464bb656a9c -r 8475a4e0425e xen/arch/x86/x86_emulate.c
--- a/xen/arch/x86/x86_emulate.c        Thu Jan 18 09:54:33 2007 +0000
+++ b/xen/arch/x86/x86_emulate.c        Thu Jan 18 15:18:07 2007 +0000
@@ -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 twobyte_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 {
@@ -227,6 +259,12 @@ struct operand {
 #define EFLG_AF (1<<4)
 #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:
@@ -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,38 +432,69 @@ 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 {                                                                    \
@@ -430,6 +503,92 @@ do {                                    
         _regs.eip = ((op_bytes == 2)                                    \
                      ? (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(
@@ -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;
@@ -613,6 +769,9 @@ x86_emulate(
         if ( d == 0 )
             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;
-        break;
-    }
-    dst.orig_val = dst.val;
+        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;
+    }
+
+    /* 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;
-        break;
-
-    case 0x80 ... 0x83: /* Grp1 */
+    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 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 0xc6 ... 0xc7: /* mov (sole member of Grp11) */
+        generate_exception_if((modrm_reg & 7) != 0, EXC_UD);
     case 0x88 ... 0x8b: /* mov */
-    case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */
         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 */
@@ -1064,6 +1477,20 @@ x86_emulate(
             break;
         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. */
@@ -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 */
-            break;
+            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 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 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 ( !(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,8 +1726,40 @@ 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. */
@@ -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) */
+    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 (short) */
         jmp_rel(insn_fetch_type(int8_t));
-        break;
-
-    case 0xeb: /* jmp (near) */
-        jmp_rel(insn_fetch_bytes(mode_64bit() ? 4 : op_bytes));
         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 )
-        {
-        case 0: goto bt;
-        case 1: goto bts;
-        case 2: goto btr;
-        case 3: goto btc;
+        switch ( modrm_reg & 7 )
+        {
+        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 -r 3464bb656a9c -r 8475a4e0425e xen/common/elf.c
--- a/xen/common/elf.c  Thu Jan 18 09:54:33 2007 +0000
+++ b/xen/common/elf.c  Thu Jan 18 15:18:07 2007 +0000
@@ -300,7 +300,7 @@ int parseelfimage(struct domain_setup_in
     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 -r 3464bb656a9c -r 8475a4e0425e xen/common/kexec.c
--- a/xen/common/kexec.c        Thu Jan 18 09:54:33 2007 +0000
+++ b/xen/common/kexec.c        Thu Jan 18 15:18:07 2007 +0000
@@ -26,36 +26,34 @@
 
 typedef long ret_t;
 
-DEFINE_PER_CPU (crash_note_t, crash_notes);
-cpumask_t crash_saved_cpus;
-
-xen_kexec_image_t kexec_image[KEXEC_IMAGE_NR];
+#define ELFNOTE_ALIGN(_n_) (((_n_)+3)&~3)

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.