aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.hgignore3
-rw-r--r--.hgtags1
-rw-r--r--Config.mk56
-rw-r--r--Makefile5
-rw-r--r--buildconfigs/Rules.mk3
-rw-r--r--config/Linux.mk8
-rw-r--r--config/OpenBSD.mk1
-rw-r--r--config/StdGNU.mk30
-rw-r--r--config/SunOS.mk35
-rw-r--r--config/ia64.mk2
-rw-r--r--config/powerpc64.mk1
-rw-r--r--config/x86_32.mk10
-rw-r--r--config/x86_64.mk12
-rw-r--r--docs/Makefile5
-rw-r--r--docs/man/xm.pod.14
-rw-r--r--docs/src/interface.tex42
-rw-r--r--linux-2.6-xen-sparse/arch/i386/kernel/fixup.c3
-rw-r--r--linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c38
-rw-r--r--linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c11
-rw-r--r--linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c76
-rw-r--r--linux-2.6-xen-sparse/drivers/xen/netback/interface.c2
-rw-r--r--linux-2.6-xen-sparse/drivers/xen/netback/netback.c6
-rw-r--r--linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c7
-rw-r--r--linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c4
-rw-r--r--patches/linux-2.6.16.29/net-gso-5-rcv-mss.patch13
-rw-r--r--tools/Makefile2
-rw-r--r--tools/Rules.mk8
-rw-r--r--tools/blktap/drivers/Makefile6
-rw-r--r--tools/blktap/lib/Makefile8
-rwxr-xr-xtools/check/check_brctl31
-rwxr-xr-xtools/check/check_iproute29
-rwxr-xr-xtools/check/check_python17
-rwxr-xr-xtools/check/check_zlib_devel17
-rwxr-xr-xtools/check/check_zlib_lib17
-rwxr-xr-xtools/check/chk19
-rw-r--r--tools/console/Makefile8
-rw-r--r--tools/console/daemon/io.c2
-rw-r--r--tools/console/daemon/utils.c2
-rw-r--r--tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c2
-rw-r--r--tools/examples/Makefile5
-rw-r--r--tools/examples/vtpm-common.sh6
-rw-r--r--tools/examples/xend-config.sxp4
-rw-r--r--tools/examples/xmexample.hvm5
-rw-r--r--tools/examples/xmexample.vti5
-rw-r--r--tools/firmware/Makefile6
-rw-r--r--tools/firmware/acpi/Makefile2
-rw-r--r--tools/firmware/hvmloader/Makefile10
-rw-r--r--tools/firmware/vmxassist/Makefile9
-rw-r--r--tools/firmware/vmxassist/head.S2
-rw-r--r--tools/firmware/vmxassist/trap.S2
-rw-r--r--tools/firmware/vmxassist/util.c25
-rw-r--r--tools/firmware/vmxassist/util.h1
-rw-r--r--tools/firmware/vmxassist/vm86.c44
-rw-r--r--tools/guest-headers/Makefile12
-rw-r--r--tools/ioemu/Makefile.target20
-rw-r--r--tools/ioemu/d3des.c434
-rw-r--r--tools/ioemu/d3des.h51
-rw-r--r--tools/ioemu/hw/ide.c4
-rw-r--r--tools/ioemu/hw/xen_platform.c8
-rw-r--r--tools/ioemu/target-i386-dm/rtc-dm.c107
-rw-r--r--tools/ioemu/vl.c14
-rw-r--r--tools/ioemu/vl.h4
-rw-r--r--tools/ioemu/vnc.c110
-rw-r--r--tools/ioemu/xenstore.c51
-rw-r--r--tools/libxc/Makefile18
-rw-r--r--tools/libxc/ia64/xc_ia64_linux_restore.c44
-rw-r--r--tools/libxc/ia64/xc_ia64_linux_save.c64
-rw-r--r--tools/libxc/xc_hvm_build.c35
-rw-r--r--tools/libxc/xc_linux_restore.c94
-rw-r--r--tools/libxc/xc_linux_save.c104
-rw-r--r--tools/libxc/xc_private.h8
-rw-r--r--tools/libxc/xc_ptrace.c2
-rw-r--r--tools/libxc/xc_ptrace.h24
-rw-r--r--tools/libxc/xc_ptrace_core.c2
-rw-r--r--tools/libxc/xc_solaris.c235
-rw-r--r--tools/libxc/xenctrl.h35
-rw-r--r--tools/libxc/xg_private.c1
-rw-r--r--tools/libxc/xg_private.h4
-rw-r--r--tools/misc/Makefile10
-rw-r--r--tools/misc/lomount/Makefile5
-rw-r--r--tools/misc/mbootpack/GPL340
-rw-r--r--tools/misc/mbootpack/Makefile68
-rw-r--r--tools/misc/mbootpack/README77
-rw-r--r--tools/misc/mbootpack/bin2c.c356
-rw-r--r--tools/misc/mbootpack/bootsect.S136
-rw-r--r--tools/misc/mbootpack/buildimage.c176
-rw-r--r--tools/misc/mbootpack/mb_header.h90
-rw-r--r--tools/misc/mbootpack/mb_info.h217
-rw-r--r--tools/misc/mbootpack/mbootpack.c704
-rw-r--r--tools/misc/mbootpack/mbootpack.h109
-rw-r--r--tools/misc/mbootpack/setup.S1064
-rw-r--r--tools/misc/miniterm/Makefile4
-rw-r--r--tools/misc/xend10
-rw-r--r--tools/pygrub/Makefile6
-rw-r--r--tools/python/Makefile6
-rw-r--r--tools/python/xen/util/auxbin.py2
-rw-r--r--tools/python/xen/util/security.py23
-rw-r--r--tools/python/xen/xend/XendDomainInfo.py2
-rw-r--r--tools/python/xen/xend/XendRoot.py11
-rw-r--r--tools/python/xen/xend/arch.py1
-rw-r--r--tools/python/xen/xend/image.py35
-rw-r--r--tools/python/xen/xend/osdep.py36
-rw-r--r--tools/python/xen/xend/server/SrvDaemon.py9
-rw-r--r--tools/python/xen/xend/server/blkif.py3
-rw-r--r--tools/python/xen/xm/addlabel.py9
-rw-r--r--tools/python/xen/xm/cfgbootpolicy.py132
-rw-r--r--tools/python/xen/xm/create.py5
-rw-r--r--tools/python/xen/xm/getlabel.py3
-rw-r--r--tools/python/xen/xm/rmlabel.py3
-rw-r--r--tools/security/example.txt376
-rw-r--r--tools/security/install.txt87
-rw-r--r--tools/security/policy.txt155
-rw-r--r--tools/security/policytools.txt148
-rw-r--r--tools/security/readme.txt31
-rw-r--r--tools/security/secpol_tool.c14
-rw-r--r--tools/security/secpol_xml2bin.c10
-rw-r--r--tools/vnet/doc/Makefile5
-rw-r--r--tools/vnet/examples/Makefile6
-rw-r--r--tools/vnet/libxutil/Makefile7
-rw-r--r--tools/vnet/scripts/Makefile6
-rw-r--r--tools/vnet/vnetd/Makefile2
-rw-r--r--tools/vtpm/Rules.mk5
-rw-r--r--tools/vtpm_manager/Rules.mk5
-rw-r--r--tools/xcutils/Makefile6
-rw-r--r--tools/xcutils/readnotes.c6
-rw-r--r--tools/xenmon/Makefile9
-rw-r--r--tools/xenstat/libxenstat/Makefile12
-rw-r--r--tools/xenstat/xentop/Makefile7
-rw-r--r--tools/xenstat/xentop/xentop.c15
-rw-r--r--tools/xenstore/Makefile26
-rw-r--r--tools/xenstore/xenstored_core.c7
-rw-r--r--tools/xenstore/xenstored_core.h3
-rw-r--r--tools/xenstore/xenstored_linux.c4
-rw-r--r--tools/xenstore/xenstored_solaris.c66
-rw-r--r--tools/xenstore/xs_lib.c9
-rw-r--r--tools/xenstore/xsls.c1
-rw-r--r--tools/xentrace/Makefile5
-rw-r--r--tools/xentrace/formats29
-rw-r--r--tools/xm-test/README32
-rw-r--r--tools/xm-test/configure.ac15
-rw-r--r--tools/xm-test/grouptest/default1
-rw-r--r--tools/xm-test/grouptest/security1
-rw-r--r--tools/xm-test/lib/XmTestLib/XenDomain.py5
-rw-r--r--tools/xm-test/lib/XmTestLib/acm.py91
-rw-r--r--tools/xm-test/lib/XmTestLib/block_utils.py2
-rwxr-xr-xtools/xm-test/runtest.sh2
-rw-r--r--tools/xm-test/tests/Makefile.am1
-rw-r--r--tools/xm-test/tests/security-acm/01_security-acm_basic.py121
-rw-r--r--tools/xm-test/tests/security-acm/02_security-acm_dom_start.py64
-rw-r--r--tools/xm-test/tests/security-acm/03_security-acm_dom_conflict.py60
-rw-r--r--tools/xm-test/tests/security-acm/04_security-acm_dom_res.py69
-rw-r--r--tools/xm-test/tests/security-acm/05_security-acm_dom_res_conf.py38
-rw-r--r--tools/xm-test/tests/security-acm/06_security-acm_dom_block_attach.py82
-rw-r--r--tools/xm-test/tests/security-acm/Makefile.am28
-rw-r--r--tools/xm-test/tests/security-acm/acm_utils.py15
-rw-r--r--tools/xm-test/tests/security-acm/xm-test-security_policy.xml110
-rw-r--r--unmodified_drivers/linux-2.6/mkbuildtree55
-rw-r--r--xen/Makefile10
-rw-r--r--xen/Rules.mk23
-rw-r--r--xen/acm/acm_chinesewall_hooks.c2
-rw-r--r--xen/acm/acm_core.c99
-rw-r--r--xen/acm/acm_simple_type_enforcement_hooks.c2
-rw-r--r--xen/arch/ia64/Rules.mk2
-rw-r--r--xen/arch/ia64/linux-xen/smpboot.c3
-rw-r--r--xen/arch/ia64/xen/xenmisc.c4
-rw-r--r--xen/arch/powerpc/Makefile2
-rw-r--r--xen/arch/powerpc/domain.c4
-rw-r--r--xen/arch/x86/Makefile5
-rw-r--r--xen/arch/x86/Rules.mk37
-rw-r--r--xen/arch/x86/boot/mkelf32.c5
-rw-r--r--xen/arch/x86/domain.c14
-rw-r--r--xen/arch/x86/domain_build.c5
-rw-r--r--xen/arch/x86/hvm/Makefile1
-rw-r--r--xen/arch/x86/hvm/hvm.c11
-rw-r--r--xen/arch/x86/hvm/i8254.c16
-rw-r--r--xen/arch/x86/hvm/i8259.c87
-rw-r--r--xen/arch/x86/hvm/intercept.c111
-rw-r--r--xen/arch/x86/hvm/io.c38
-rw-r--r--xen/arch/x86/hvm/platform.c757
-rw-r--r--xen/arch/x86/hvm/rtc.c393
-rw-r--r--xen/arch/x86/hvm/svm/intr.c38
-rw-r--r--xen/arch/x86/hvm/svm/svm.c82
-rw-r--r--xen/arch/x86/hvm/svm/vmcb.c9
-rw-r--r--xen/arch/x86/hvm/svm/x86_32/exits.S2
-rw-r--r--xen/arch/x86/hvm/svm/x86_64/exits.S2
-rw-r--r--xen/arch/x86/hvm/vioapic.c51
-rw-r--r--xen/arch/x86/hvm/vlapic.c3
-rw-r--r--xen/arch/x86/hvm/vmx/io.c2
-rw-r--r--xen/arch/x86/hvm/vmx/vmx.c241
-rw-r--r--xen/arch/x86/i387.c9
-rw-r--r--xen/arch/x86/io_apic.c9
-rw-r--r--xen/arch/x86/irq.c2
-rw-r--r--xen/arch/x86/mm/shadow/common.c218
-rw-r--r--xen/arch/x86/mm/shadow/multi.c820
-rw-r--r--xen/arch/x86/mm/shadow/multi.h4
-rw-r--r--xen/arch/x86/mm/shadow/private.h75
-rw-r--r--xen/arch/x86/mm/shadow/types.h123
-rw-r--r--xen/arch/x86/oprofile/op_model_athlon.c30
-rw-r--r--xen/arch/x86/oprofile/op_model_p4.c10
-rw-r--r--xen/arch/x86/oprofile/op_model_ppro.c10
-rw-r--r--xen/arch/x86/oprofile/xenoprof.c121
-rw-r--r--xen/arch/x86/setup.c45
-rw-r--r--xen/arch/x86/time.c7
-rw-r--r--xen/common/Makefile3
-rw-r--r--xen/common/domain.c2
-rw-r--r--xen/common/grant_table.c2
-rw-r--r--xen/common/keyhandler.c1
-rw-r--r--xen/common/page_alloc.c2
-rw-r--r--xen/common/schedule.c2
-rw-r--r--xen/common/time.c77
-rw-r--r--xen/common/trace.c2
-rw-r--r--xen/common/vsprintf.c2
-rw-r--r--xen/drivers/char/console.c4
-rw-r--r--xen/drivers/char/serial.c4
-rw-r--r--xen/include/acm/acm_hooks.h14
-rw-r--r--xen/include/acpi/platform/acenv.h2
-rw-r--r--xen/include/asm-ia64/linux-xen/asm/spinlock.h6
-rw-r--r--xen/include/asm-powerpc/spinlock.h12
-rw-r--r--xen/include/asm-x86/domain.h17
-rw-r--r--xen/include/asm-x86/hvm/io.h42
-rw-r--r--xen/include/asm-x86/hvm/support.h6
-rw-r--r--xen/include/asm-x86/hvm/svm/vmcb.h1
-rw-r--r--xen/include/asm-x86/hvm/vcpu.h5
-rw-r--r--xen/include/asm-x86/hvm/vpic.h2
-rw-r--r--xen/include/asm-x86/hvm/vpit.h56
-rw-r--r--xen/include/asm-x86/mm.h17
-rw-r--r--xen/include/asm-x86/perfc_defn.h2
-rw-r--r--xen/include/asm-x86/shadow.h7
-rw-r--r--xen/include/asm-x86/spinlock.h8
-rw-r--r--xen/include/asm-x86/x86_64/asm_defns.h6
-rw-r--r--xen/include/public/io/ring.h22
-rw-r--r--xen/include/public/trace.h13
-rw-r--r--xen/include/xen/cpumask.h8
-rw-r--r--xen/include/xen/domain.h2
-rw-r--r--xen/include/xen/lib.h2
-rw-r--r--xen/include/xen/spinlock.h8
-rw-r--r--xen/include/xen/stdarg.h5
-rw-r--r--xen/include/xen/time.h14
238 files changed, 5027 insertions, 6558 deletions
diff --git a/.hgignore b/.hgignore
index dcd9012357..c84fae9f98 100644
--- a/.hgignore
+++ b/.hgignore
@@ -15,8 +15,11 @@
.*\.rej$
.*/a\.out$
.*/cscope\..*$
+^cscope.*$
^[^/]*\.bz2$
+^\.config$
^TAGS$
+^tags$
^dist/.*$
^docs/.*\.aux$
^docs/.*\.dvi$
diff --git a/.hgtags b/.hgtags
index b097c216b9..43265aa8dc 100644
--- a/.hgtags
+++ b/.hgtags
@@ -15,3 +15,4 @@ fb875591fd72e15c31879c0e9034d99b80225595 RELEASE-2.0.4
c8fdb0caa77b429cf47f9707926e83947778cb48 RELEASE-3.0.0
af0573e9e5258db0a9d28aa954dd302ddd2c2d23 3.0.2-rc
d0d3fef37685be264a7f52201f8ef44c030daad3 3.0.2-branched
+6ed4368b4a9e1924c983774c4b1a2b6baf8e98a6 3.0.3-branched
diff --git a/Config.mk b/Config.mk
index 74bd8ec80c..4cd113d905 100644
--- a/Config.mk
+++ b/Config.mk
@@ -4,43 +4,21 @@
debug ?= n
XEN_COMPILE_ARCH ?= $(shell uname -m | sed -e s/i.86/x86_32/ \
- -e s/ppc/powerpc/)
+ -e s/ppc/powerpc/ -e s/i86pc/x86_32/)
XEN_TARGET_ARCH ?= $(XEN_COMPILE_ARCH)
XEN_TARGET_X86_PAE ?= n
+XEN_OS ?= $(shell uname -s)
+
+CONFIG_$(XEN_OS) := y
# Tools to run on system hosting the build
HOSTCC = gcc
HOSTCFLAGS = -Wall -Werror -Wstrict-prototypes -O2 -fomit-frame-pointer
-AS = $(CROSS_COMPILE)as
-LD = $(CROSS_COMPILE)ld
-CC = $(CROSS_COMPILE)gcc
-CPP = $(CROSS_COMPILE)gcc -E
-AR = $(CROSS_COMPILE)ar
-RANLIB = $(CROSS_COMPILE)ranlib
-NM = $(CROSS_COMPILE)nm
-STRIP = $(CROSS_COMPILE)strip
-OBJCOPY = $(CROSS_COMPILE)objcopy
-OBJDUMP = $(CROSS_COMPILE)objdump
-
DISTDIR ?= $(XEN_ROOT)/dist
DESTDIR ?= /
-INSTALL = install
-INSTALL_DIR = $(INSTALL) -d -m0755
-INSTALL_DATA = $(INSTALL) -m0644
-INSTALL_PROG = $(INSTALL) -m0755
-
-ifneq ($(debug),y)
-# Optimisation flags are overridable
-CFLAGS ?= -O2 -fomit-frame-pointer
-CFLAGS += -DNDEBUG
-else
-# Less than -O1 produces bad code and large stack frames
-CFLAGS ?= -O1 -fno-omit-frame-pointer
-CFLAGS += -g
-endif
-
+include $(XEN_ROOT)/config/$(XEN_OS).mk
include $(XEN_ROOT)/config/$(XEN_TARGET_ARCH).mk
ifneq ($(EXTRA_PREFIX),)
@@ -48,19 +26,31 @@ EXTRA_INCLUDES += $(EXTRA_PREFIX)/include
EXTRA_LIB += $(EXTRA_PREFIX)/$(LIBDIR)
endif
-test-gcc-flag = $(shell $(1) -v --help 2>&1 | grep -q " $(2) " && echo $(2))
+# cc-option
+# Usage: cflags-y += $(call cc-option,$(CC),-march=winchip-c6,-march=i586)
+cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc \
+ /dev/null 2>&1`"; then echo "$(2)"; else echo "$(3)"; fi ;)
+
+ifneq ($(debug),y)
+CFLAGS += -DNDEBUG
+else
+CFLAGS += -g
+endif
+
+CFLAGS += -std=gnu99
CFLAGS += -Wall -Wstrict-prototypes
-HOSTCFLAGS += $(call test-gcc-flag,$(HOSTCC),-Wdeclaration-after-statement)
-CFLAGS += $(call test-gcc-flag,$(CC),-Wdeclaration-after-statement)
+# -Wunused-value makes GCC 4.x too aggressive for my taste: ignoring the
+# result of any casted expression causes a warning.
+CFLAGS += -Wno-unused-value
+
+HOSTCFLAGS += $(call cc-option,$(HOSTCC),-Wdeclaration-after-statement,)
+CFLAGS += $(call cc-option,$(CC),-Wdeclaration-after-statement,)
LDFLAGS += $(foreach i, $(EXTRA_LIB), -L$(i))
CFLAGS += $(foreach i, $(EXTRA_INCLUDES), -I$(i))
-# Choose the best mirror to download linux kernel
-KERNEL_REPO = http://www.kernel.org
-
# If ACM_SECURITY = y, then the access control module is compiled
# into Xen and the policy type can be set by the boot policy file
# y - Build the Xen ACM framework
diff --git a/Makefile b/Makefile
index 186b756765..c7004c0ae2 100644
--- a/Makefile
+++ b/Makefile
@@ -2,11 +2,6 @@
# Grand Unified Makefile for Xen.
#
-KERNELS ?= linux-2.6-xen
-# You may use wildcards in the above e.g. KERNELS=*2.6*
-
-XKERNELS := $(foreach kernel, $(KERNELS), $(patsubst buildconfigs/mk.%,%,$(wildcard buildconfigs/mk.$(kernel))) )
-
# Export target architecture overrides to Xen and Linux sub-trees.
ifneq ($(XEN_TARGET_ARCH),)
SUBARCH := $(subst x86_32,i386,$(XEN_TARGET_ARCH))
diff --git a/buildconfigs/Rules.mk b/buildconfigs/Rules.mk
index 6eca30ef0a..ae61ea0095 100644
--- a/buildconfigs/Rules.mk
+++ b/buildconfigs/Rules.mk
@@ -3,6 +3,9 @@ include Config.mk
export DESTDIR
+# Choose the best mirror to download linux kernel
+KERNEL_REPO = http://www.kernel.org
+
ALLKERNELS = $(patsubst buildconfigs/mk.%,%,$(wildcard buildconfigs/mk.*))
ALLSPARSETREES = $(patsubst %-xen-sparse,%,$(wildcard *-xen-sparse))
diff --git a/config/Linux.mk b/config/Linux.mk
new file mode 100644
index 0000000000..52c2227996
--- /dev/null
+++ b/config/Linux.mk
@@ -0,0 +1,8 @@
+include $(XEN_ROOT)/config/StdGNU.mk
+
+# You may use wildcards, e.g. KERNELS=*2.6*
+KERNELS ?= linux-2.6-xen
+
+XKERNELS := $(foreach kernel, $(KERNELS), \
+ $(patsubst buildconfigs/mk.%,%, \
+ $(wildcard buildconfigs/mk.$(kernel))) )
diff --git a/config/OpenBSD.mk b/config/OpenBSD.mk
new file mode 100644
index 0000000000..b421a1c840
--- /dev/null
+++ b/config/OpenBSD.mk
@@ -0,0 +1 @@
+include $(XEN_ROOT)/config/StdGNU.mk
diff --git a/config/StdGNU.mk b/config/StdGNU.mk
new file mode 100644
index 0000000000..2b767517b8
--- /dev/null
+++ b/config/StdGNU.mk
@@ -0,0 +1,30 @@
+AS = $(CROSS_COMPILE)as
+LD = $(CROSS_COMPILE)ld
+CC = $(CROSS_COMPILE)gcc
+CPP = $(CROSS_COMPILE)gcc -E
+AR = $(CROSS_COMPILE)ar
+RANLIB = $(CROSS_COMPILE)ranlib
+NM = $(CROSS_COMPILE)nm
+STRIP = $(CROSS_COMPILE)strip
+OBJCOPY = $(CROSS_COMPILE)objcopy
+OBJDUMP = $(CROSS_COMPILE)objdump
+
+INSTALL = install
+INSTALL_DIR = $(INSTALL) -d -m0755
+INSTALL_DATA = $(INSTALL) -m0644
+INSTALL_PROG = $(INSTALL) -m0755
+
+LIB64DIR = lib64
+
+SOCKET_LIBS =
+CURSES_LIBS = -lncurses
+SONAME_LDFLAG = -soname
+SHLIB_CFLAGS = -shared
+
+ifneq ($(debug),y)
+# Optimisation flags are overridable
+CFLAGS ?= -O2 -fomit-frame-pointer
+else
+# Less than -O1 produces bad code and large stack frames
+CFLAGS ?= -O1 -fno-omit-frame-pointer
+endif
diff --git a/config/SunOS.mk b/config/SunOS.mk
new file mode 100644
index 0000000000..21568304fc
--- /dev/null
+++ b/config/SunOS.mk
@@ -0,0 +1,35 @@
+AS = $(CROSS_COMPILE)gas
+LD = $(CROSS_COMPILE)gld
+CC = $(CROSS_COMPILE)gcc
+CPP = $(CROSS_COMPILE)gcc -E
+AR = $(CROSS_COMPILE)gar
+RANLIB = $(CROSS_COMPILE)granlib
+NM = $(CROSS_COMPILE)gnm
+STRIP = $(CROSS_COMPILE)gstrip
+OBJCOPY = $(CROSS_COMPILE)gobjcopy
+OBJDUMP = $(CROSS_COMPILE)gobjdump
+
+SHELL = bash
+
+INSTALL = ginstall
+INSTALL_DIR = $(INSTALL) -d -m0755
+INSTALL_DATA = $(INSTALL) -m0644
+INSTALL_PROG = $(INSTALL) -m0755
+
+LIB64DIR = lib/amd64
+
+SOCKET_LIBS = -lsocket
+CURSES_LIBS = -lcurses
+SONAME_LDFLAG = -h
+SHLIB_CFLAGS = -static-libgcc -shared
+
+ifneq ($(debug),y)
+# Optimisation flags are overridable
+CFLAGS ?= -O2 -fno-omit-frame-pointer
+else
+# Less than -O1 produces bad code and large stack frames
+CFLAGS ?= -O1 -fno-omit-frame-pointer
+endif
+
+CFLAGS += -Wa,--divide -D_POSIX_C_SOURCE=200112L -D__EXTENSIONS__
+
diff --git a/config/ia64.mk b/config/ia64.mk
index 4fab1118be..7cf99d9b69 100644
--- a/config/ia64.mk
+++ b/config/ia64.mk
@@ -1,4 +1,6 @@
CONFIG_IA64 := y
+CONFIG_IA64_$(XEN_OS) := y
+
CONFIG_IOEMU := y
CONFIG_XCUTILS := y
diff --git a/config/powerpc64.mk b/config/powerpc64.mk
index ee717ecd64..9773b24a6c 100644
--- a/config/powerpc64.mk
+++ b/config/powerpc64.mk
@@ -1,4 +1,5 @@
CONFIG_POWERPC := y
+CONFIG_POWERPC_$(XEN_OS) := y
CFLAGS += -DELFSIZE=64
LIBDIR := lib
diff --git a/config/x86_32.mk b/config/x86_32.mk
index 2d460a720a..4a0490afa8 100644
--- a/config/x86_32.mk
+++ b/config/x86_32.mk
@@ -1,9 +1,17 @@
CONFIG_X86 := y
+CONFIG_X86_$(XEN_OS) := y
+
CONFIG_HVM := y
CONFIG_MIGRATE := y
CONFIG_XCUTILS := y
CONFIG_IOEMU := y
-CONFIG_MBOOTPACK := y
CFLAGS += -m32 -march=i686
LIBDIR := lib
+
+# Use only if calling $(LD) directly.
+ifeq ($(XEN_OS),OpenBSD)
+LDFLAGS_DIRECT += -melf_i386_obsd
+else
+LDFLAGS_DIRECT += -melf_i386
+endif
diff --git a/config/x86_64.mk b/config/x86_64.mk
index bd43c04a6c..e85b37ff91 100644
--- a/config/x86_64.mk
+++ b/config/x86_64.mk
@@ -1,9 +1,17 @@
CONFIG_X86 := y
+CONFIG_X86_$(XEN_OS) := y
+
CONFIG_HVM := y
CONFIG_MIGRATE := y
CONFIG_XCUTILS := y
CONFIG_IOEMU := y
-CONFIG_MBOOTPACK := y
CFLAGS += -m64
-LIBDIR = lib64
+LIBDIR = $(LIB64DIR)
+
+# Use only if calling $(LD) directly.
+ifeq ($(XEN_OS),OpenBSD)
+LDFLAGS_DIRECT += -melf_x86_64_obsd
+else
+LDFLAGS_DIRECT += -melf_x86_64
+endif
diff --git a/docs/Makefile b/docs/Makefile
index 59e9fa69d7..0432855384 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -1,8 +1,9 @@
#!/usr/bin/make -f
+XEN_ROOT=..
+include $(XEN_ROOT)/Config.mk
+
VERSION = xen-unstable
-INSTALL = install
-INSTALL_DIR = $(INSTALL) -d -m0755
PS2PDF := ps2pdf
DVIPS := dvips
diff --git a/docs/man/xm.pod.1 b/docs/man/xm.pod.1
index e7dbbb90f6..b0ba7f8fb2 100644
--- a/docs/man/xm.pod.1
+++ b/docs/man/xm.pod.1
@@ -810,13 +810,13 @@ global policy root directory.
Loads the binary representation of the I<policy> into Xen. The binary
representation can be created with the B<makepolicy> subcommand.
-=item B<cfgbootpolicy> I<policy> [I<kernelversion>]
+=item B<cfgbootpolicy> I<policy> [I<boot title>]
Configures I<policy> as the boot policy for Xen. It copies the binary
policy representation into the /boot directory and adds a module line
specifying the binary policy to the /boot/grub/menu.lst file. If your
boot configuration includes multiple Xen boot titles, then use the
-I<kernelversion> parameter to select the proper title.
+I<boot title> parameter to specify a unique part of the proper title.
=item B<dumppolicy>
diff --git a/docs/src/interface.tex b/docs/src/interface.tex
index 9a598406a1..a77d4e81c2 100644
--- a/docs/src/interface.tex
+++ b/docs/src/interface.tex
@@ -955,7 +955,6 @@ This information doesn't change and is indexed by the domain's UUID.
A {\bf /vm} entry contains the following information:
\begin{description}
-\item[ssidref] ssid reference for domain
\item[uuid] uuid of the domain (somewhat redundant)
\item[on\_reboot] the action to take on a domain reboot request (destroy or restart)
\item[on\_poweroff] the action to take on a domain halt request (destroy or restart)
@@ -1125,6 +1124,16 @@ This path contains:
\end{description}
\end{description}
+ \item[security/] access control information for the domain
+ \begin{description}
+ \item[ssidref] security reference identifier used inside the hypervisor
+ \item[access\_control/] security label used by management tools
+ \begin{description}
+ \item[label] security label name
+ \item[policy] security policy name
+ \end{description}
+ \end{description}
+
\item[store/] per-domain information for the store
\begin{description}
\item[port] the event channel used for the store ring queue
@@ -2168,19 +2177,46 @@ Most of the above are best understood by looking at the code
implementing them (in {\tt xen/common/dom0\_ops.c}) and in
the user-space tools that use them (mostly in {\tt tools/libxc}).
+\section{Access Control Module Hypercalls}
+\label{s:acmops}
+
Hypercalls relating to the management of the Access Control Module are
-also restricted to domain 0 access for now:
+also restricted to domain 0 access for now. For more details on any or
+all of these, please see {\tt xen/include/public/acm\_ops.h}. A
+complete list is given below:
\begin{quote}
-\hypercall{acm\_op(struct acm\_op * u\_acm\_op)}
+\hypercall{acm\_op(int cmd, void *args)}
This hypercall can be used to configure the state of the ACM, query
that state, request access control decisions and dump additional
information.
+\begin{description}
+
+\item [ACMOP\_SETPOLICY:] set the access control policy
+
+\item [ACMOP\_GETPOLICY:] get the current access control policy and
+ status
+
+\item [ACMOP\_DUMPSTATS:] get current access control hook invocation
+ statistics
+
+\item [ACMOP\_GETSSID:] get security access control information for a
+ domain
+
+\item [ACMOP\_GETDECISION:] get access decision based on the currently
+ enforced access control policy
+
+\end{description}
\end{quote}
+Most of the above are best understood by looking at the code
+implementing them (in {\tt xen/common/acm\_ops.c}) and in the
+user-space tools that use them (mostly in {\tt tools/security} and
+{\tt tools/python/xen/lowlevel/acm}).
+
\section{Debugging Hypercalls}
diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/fixup.c b/linux-2.6-xen-sparse/arch/i386/kernel/fixup.c
index 20535e8fd4..2bf16fb732 100644
--- a/linux-2.6-xen-sparse/arch/i386/kernel/fixup.c
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/fixup.c
@@ -46,6 +46,9 @@ fastcall void do_fixup_4gb_segment(struct pt_regs *regs, long error_code)
if (test_and_set_bit(0, &printed))
return;
+ if (current->tgid == 1) /* Ignore statically linked init */
+ return;
+
HYPERVISOR_vm_assist(
VMASST_CMD_disable, VMASST_TYPE_4gb_segments_notify);
diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c
index 65d6ff995e..926ba175c3 100644
--- a/linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c
@@ -50,9 +50,6 @@ MODULE_LICENSE("GPL");
/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
static DECLARE_MUTEX(microcode_sem);
-
-static void __user *user_buffer; /* user area microcode data buffer */
-static unsigned int user_buffer_size; /* it's size */
static int microcode_open (struct inode *unused1, struct file *unused2)
{
@@ -60,21 +57,26 @@ static int microcode_open (struct inode *unused1, struct file *unused2)
}
-static int do_microcode_update (void)
+static int do_microcode_update (const void __user *ubuf, size_t len)
{
int err;
- dom0_op_t op;
+ void *kbuf;
+
+ kbuf = vmalloc(len);
+ if (!kbuf)
+ return -ENOMEM;
- err = sys_mlock((unsigned long)user_buffer, user_buffer_size);
- if (err != 0)
- return err;
+ if (copy_from_user(kbuf, ubuf, len) == 0) {
+ dom0_op_t op;
- op.cmd = DOM0_MICROCODE;
- set_xen_guest_handle(op.u.microcode.data, user_buffer);
- op.u.microcode.length = user_buffer_size;
- err = HYPERVISOR_dom0_op(&op);
+ op.cmd = DOM0_MICROCODE;
+ set_xen_guest_handle(op.u.microcode.data, kbuf);
+ op.u.microcode.length = len;
+ err = HYPERVISOR_dom0_op(&op);
+ } else
+ err = -EFAULT;
- (void)sys_munlock((unsigned long)user_buffer, user_buffer_size);
+ vfree(kbuf);
return err;
}
@@ -88,17 +90,9 @@ static ssize_t microcode_write (struct file *file, const char __user *buf, size_
return -EINVAL;
}
- if ((len >> PAGE_SHIFT) > num_physpages) {
- printk(KERN_ERR "microcode: too much data (max %ld pages)\n", num_physpages);
- return -EINVAL;
- }
-
down(&microcode_sem);
- user_buffer = (void __user *) buf;
- user_buffer_size = (int) len;
-
- ret = do_microcode_update();
+ ret = do_microcode_update(buf, len);
if (!ret)
ret = (ssize_t)len;
diff --git a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c
index 71c7dd3a00..75a5a6d03e 100644
--- a/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c
+++ b/linux-2.6-xen-sparse/drivers/char/tpm/tpm_xen.c
@@ -343,6 +343,7 @@ static void backend_changed(struct xenbus_device *dev,
case XenbusStateInitialising:
case XenbusStateInitWait:
case XenbusStateInitialised:
+ case XenbusStateUnknown:
break;
case XenbusStateConnected:
@@ -351,13 +352,14 @@ static void backend_changed(struct xenbus_device *dev,
case XenbusStateClosing:
tpmif_set_connected_state(tp, 0);
+ xenbus_frontend_closed(dev);
break;
- case XenbusStateUnknown:
case XenbusStateClosed:
+ tpmif_set_connected_state(tp, 0);
if (tp->is_suspended == 0)
device_unregister(&dev->dev);
- xenbus_switch_state(dev, XenbusStateClosed);
+ xenbus_frontend_closed(dev);
break;
}
}
@@ -419,9 +421,10 @@ static int tpmfront_suspend(struct xenbus_device *dev)
mutex_lock(&suspend_lock);
tp->is_suspended = 1;
- for (ctr = 0; atomic_read(&tp->tx_busy) && ctr <= 25; ctr++) {
+ for (ctr = 0; atomic_read(&tp->tx_busy) && ctr <= 300; ctr++) {
if ((ctr % 10) == 0)
- printk("TPM-FE [INFO]: Waiting for outstanding request.\n");
+ printk("TPM-FE [INFO]: Waiting for outstanding "
+ "request.\n");
/*
* Wait for a request to be responded to.
*/
diff --git a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c b/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c
index 0a0d31fe27..1fcf56fc41 100644
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c
@@ -845,28 +845,29 @@ static void fast_flush_area(pending_req_t *req, int k_idx, int u_idx, int
uvaddr = MMAP_VADDR(info->user_vstart, u_idx, i);
khandle = &pending_handle(mmap_idx, k_idx, i);
- if (BLKTAP_INVALID_HANDLE(khandle)) {
- WPRINTK("BLKTAP_INVALID_HANDLE\n");
- continue;
+
+ if (khandle->kernel != 0xFFFF) {
+ gnttab_set_unmap_op(&unmap[invcount],
+ idx_to_kaddr(mmap_idx, k_idx, i),
+ GNTMAP_host_map, khandle->kernel);
+ invcount++;
}
- gnttab_set_unmap_op(&unmap[invcount],
- idx_to_kaddr(mmap_idx, k_idx, i),
- GNTMAP_host_map, khandle->kernel);
- invcount++;
-
- if (create_lookup_pte_addr(
- info->vma->vm_mm,
- MMAP_VADDR(info->user_vstart, u_idx, i),
- &ptep) !=0) {
- WPRINTK("Couldn't get a pte addr!\n");
- return;
+
+ if (khandle->user != 0xFFFF) {
+ if (create_lookup_pte_addr(
+ info->vma->vm_mm,
+ MMAP_VADDR(info->user_vstart, u_idx, i),
+ &ptep) !=0) {
+ WPRINTK("Couldn't get a pte addr!\n");
+ return;
+ }
+
+ gnttab_set_unmap_op(&unmap[invcount],
+ ptep, GNTMAP_host_map,
+ khandle->user);
+ invcount++;
}
- gnttab_set_unmap_op(&unmap[invcount],
- ptep, GNTMAP_host_map,
- khandle->user);
- invcount++;
-
BLKTAP_INVALIDATE_HANDLE(khandle);
}
ret = HYPERVISOR_grant_table_op(
@@ -1030,7 +1031,7 @@ static int print_dbug = 1;
static int do_block_io_op(blkif_t *blkif)
{
blkif_back_ring_t *blk_ring = &blkif->blk_ring;
- blkif_request_t *req;
+ blkif_request_t req;
pending_req_t *pending_req;
RING_IDX rc, rp;
int more_to_do = 0;
@@ -1082,24 +1083,24 @@ static int do_block_io_op(blkif_t *blkif)
break;
}
- req = RING_GET_REQUEST(blk_ring, rc);
+ memcpy(&req, RING_GET_REQUEST(blk_ring, rc), sizeof(req));
blk_ring->req_cons = ++rc; /* before make_response() */
- switch (req->operation) {
+ switch (req.operation) {
case BLKIF_OP_READ:
blkif->st_rd_req++;
- dispatch_rw_block_io(blkif, req, pending_req);
+ dispatch_rw_block_io(blkif, &req, pending_req);
break;
case BLKIF_OP_WRITE:
blkif->st_wr_req++;
- dispatch_rw_block_io(blkif, req, pending_req);
+ dispatch_rw_block_io(blkif, &req, pending_req);
break;
default:
WPRINTK("unknown operation [%d]\n",
- req->operation);
- make_response(blkif, req->id, req->operation,
+ req.operation);
+ make_response(blkif, req.id, req.operation,
BLKIF_RSP_ERROR);
free_req(pending_req);
break;
@@ -1128,9 +1129,10 @@ static void dispatch_rw_block_io(blkif_t *blkif,
int usr_idx = GET_NEXT_REQ(info->idx_map);
uint16_t mmap_idx = pending_req->mem_idx;
- /*Check we have space on user ring - should never fail*/
- if(usr_idx == INVALID_REQ) goto fail_flush;
-
+ /* Check we have space on user ring - should never fail. */
+ if (usr_idx == INVALID_REQ)
+ goto fail_response;
+
/* Check that number of segments is sane. */
nseg = req->nr_segments;
if ( unlikely(nseg == 0) ||
@@ -1195,8 +1197,6 @@ static void dispatch_rw_block_io(blkif_t *blkif,
uvaddr, &ptep);
if (ret) {
WPRINTK("Couldn't get a pte addr!\n");
- fast_flush_area(pending_req, pending_idx, usr_idx,
- blkif->dev_num);
goto fail_flush;
}
@@ -1224,19 +1224,25 @@ static void dispatch_rw_block_io(blkif_t *blkif,
if (unlikely(map[i].status != 0)) {
WPRINTK("invalid kernel buffer -- "
"could not remap it\n");
- goto fail_flush;
+ ret |= 1;
+ map[i].handle = 0xFFFF;
}
if (unlikely(map[i+1].status != 0)) {
WPRINTK("invalid user buffer -- "
"could not remap it\n");
- goto fail_flush;
+ ret |= 1;
+ map[i+1].handle = 0xFFFF;
}
pending_handle(mmap_idx, pending_idx, i/2).kernel
= map[i].handle;
pending_handle(mmap_idx, pending_idx, i/2).user
= map[i+1].handle;
+
+ if (ret)
+ continue;
+
set_phys_to_machine(__pa(kvaddr) >> PAGE_SHIFT,
FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT));
offset = (uvaddr - info->vma->vm_start) >> PAGE_SHIFT;
@@ -1244,6 +1250,10 @@ static void dispatch_rw_block_io(blkif_t *blkif,
((struct page **)info->vma->vm_private_data)[offset] =
pg;
}
+
+ if (ret)
+ goto fail_flush;
+
/* Mark mapped pages as reserved: */
for (i = 0; i < req->nr_segments; i++) {
unsigned long kvaddr;
diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c
index a698ccc77b..78aa4cd8c5 100644
--- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c
@@ -128,7 +128,7 @@ static struct ethtool_ops network_ethtool_ops =
netif_t *netif_alloc(domid_t domid, unsigned int handle)
{
- int err = 0, i;
+ int err = 0;
struct net_device *dev;
netif_t *netif;
char name[IFNAMSIZ] = {};
diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c
index 11fbf9503a..08c075ac27 100644
--- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c
@@ -187,7 +187,7 @@ static struct sk_buff *netbk_copy_skb(struct sk_buff *skb)
if (unlikely(!nskb))
goto err;
- skb_reserve(nskb, 16);
+ skb_reserve(nskb, 16 + NET_IP_ALIGN);
headlen = nskb->end - nskb->data;
if (headlen > skb_headlen(skb))
headlen = skb_headlen(skb);
@@ -1210,7 +1210,7 @@ static void net_tx_action(unsigned long unused)
ret < MAX_SKB_FRAGS) ?
PKT_PROT_LEN : txreq.size;
- skb = alloc_skb(data_len+16, GFP_ATOMIC);
+ skb = alloc_skb(data_len + 16 + NET_IP_ALIGN, GFP_ATOMIC);
if (unlikely(skb == NULL)) {
DPRINTK("Can't allocate a skb in start_xmit.\n");
netbk_tx_err(netif, &txreq, i);
@@ -1218,7 +1218,7 @@ static void net_tx_action(unsigned long unused)
}
/* Packets passed to netif_rx() must have some headroom. */
- skb_reserve(skb, 16);
+ skb_reserve(skb, 16 + NET_IP_ALIGN);
if (extras[XEN_NETIF_EXTRA_TYPE_GSO - 1].type) {
struct netif_extra_info *gso;
diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
index 55101210d2..26e0610d15 100644
--- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
+++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
@@ -684,7 +684,7 @@ static void network_alloc_rx_buffers(struct net_device *dev)
* necessary here.
* 16 bytes added as necessary headroom for netif_receive_skb.
*/
- skb = alloc_skb(RX_COPY_THRESHOLD + 16,
+ skb = alloc_skb(RX_COPY_THRESHOLD + 16 + NET_IP_ALIGN,
GFP_ATOMIC | __GFP_NOWARN);
if (unlikely(!skb))
goto no_skb;
@@ -702,7 +702,7 @@ no_skb:
break;
}
- skb_reserve(skb, 16); /* mimic dev_alloc_skb() */
+ skb_reserve(skb, 16 + NET_IP_ALIGN); /* mimic dev_alloc_skb() */
skb_shinfo(skb)->frags[0].page = page;
skb_shinfo(skb)->nr_frags = 1;
__skb_queue_tail(&np->rx_batch, skb);
@@ -2129,6 +2129,9 @@ module_init(netif_init);
static void __exit netif_exit(void)
{
+ if (is_initial_xendomain())
+ return;
+
unregister_inetaddr_notifier(&notifier_inetdev);
return xenbus_unregister_driver(&netfront);
diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c
index 4ee5c5bbfe..f48b0e3726 100644
--- a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c
@@ -157,10 +157,12 @@ static void frontend_changed(struct xenbus_device *dev,
case XenbusStateClosing:
be->instance = -1;
+ xenbus_switch_state(dev, XenbusStateClosing);
break;
- case XenbusStateUnknown:
+ case XenbusStateUnknown: /* keep it here */
case XenbusStateClosed:
+ xenbus_switch_state(dev, XenbusStateClosed);
device_unregister(&be->dev->dev);
tpmback_remove(dev);
break;
diff --git a/patches/linux-2.6.16.29/net-gso-5-rcv-mss.patch b/patches/linux-2.6.16.29/net-gso-5-rcv-mss.patch
new file mode 100644
index 0000000000..a711d0ee5f
--- /dev/null
+++ b/patches/linux-2.6.16.29/net-gso-5-rcv-mss.patch
@@ -0,0 +1,13 @@
+diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
+index 104af5d..1fa1536 100644
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -127,7 +127,7 @@ static void tcp_measure_rcv_mss(struct s
+ /* skb->len may jitter because of SACKs, even if peer
+ * sends good full-sized frames.
+ */
+- len = skb->len;
++ len = skb_shinfo(skb)->gso_size ?: skb->len;
+ if (len >= icsk->icsk_ack.rcv_mss) {
+ icsk->icsk_ack.rcv_mss = len;
+ } else {
diff --git a/tools/Makefile b/tools/Makefile
index d16b590fe7..f1f25f19bf 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -60,7 +60,7 @@ check_clean:
$(MAKE) -C check clean
.PHONY: ioemu ioemuinstall ioemuclean
-ifdef CONFIG_IOEMU
+ifeq ($(CONFIG_IOEMU),y)
export IOEMU_DIR ?= ioemu
ioemu ioemuinstall:
[ -f $(IOEMU_DIR)/config-host.mak ] || \
diff --git a/tools/Rules.mk b/tools/Rules.mk
index bb6cdaf286..6a5036b3f6 100644
--- a/tools/Rules.mk
+++ b/tools/Rules.mk
@@ -5,8 +5,6 @@ all:
include $(XEN_ROOT)/Config.mk
-CONFIG_$(shell uname -s) := y
-
XEN_XC = $(XEN_ROOT)/tools/python/xen/lowlevel/xc
XEN_LIBXC = $(XEN_ROOT)/tools/libxc
XEN_XENSTORE = $(XEN_ROOT)/tools/xenstore
@@ -25,9 +23,9 @@ CFLAGS += -D__XEN_TOOLS__
%.o: %.cc
$(CC) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $<
-OS = $(shell uname -s)
+.PHONY: mk-symlinks mk-symlinks-xen mk-symlinks-$(XEN_OS)
-.PHONY: mk-symlinks mk-symlinks-xen mk-symlinks-$(OS)
+mk-symlinks-SunOS:
mk-symlinks-Linux: LINUX_ROOT=$(XEN_ROOT)/linux-2.6-xen-sparse
mk-symlinks-Linux:
@@ -44,4 +42,4 @@ mk-symlinks-xen:
mkdir -p xen/io
( cd xen/io && ln -sf ../../$(XEN_ROOT)/xen/include/public/io/*.h . )
-mk-symlinks: mk-symlinks-xen mk-symlinks-$(OS)
+mk-symlinks: mk-symlinks-xen mk-symlinks-$(XEN_OS)
diff --git a/tools/blktap/drivers/Makefile b/tools/blktap/drivers/Makefile
index 80b0ad1dbe..e1324063e6 100644
--- a/tools/blktap/drivers/Makefile
+++ b/tools/blktap/drivers/Makefile
@@ -3,11 +3,9 @@ include $(XEN_ROOT)/tools/Rules.mk
INCLUDES += -I.. -I../lib
-INSTALL = install
-INSTALL_PROG = $(INSTALL) -m0755
IBIN = blktapctrl tapdisk
QCOW_UTIL = img2qcow qcow2raw qcow-create
-INSTALL_DIR = /usr/sbin
+INST_DIR = /usr/sbin
LIBAIO_DIR = ../../libaio/src
CFLAGS += -Werror
@@ -58,7 +56,7 @@ img2qcow qcow2raw qcow-create: %: $(BLK-OBJS)
$(CC) $(CFLAGS) -o $* $(BLK-OBJS) $*.c $(AIOLIBS) $(LIBS)
install: all
- $(INSTALL_PROG) $(IBIN) $(QCOW_UTIL) $(DESTDIR)$(INSTALL_DIR)
+ $(INSTALL_PROG) $(IBIN) $(QCOW_UTIL) $(DESTDIR)$(INST_DIR)
clean:
rm -rf *.o *~ $(DEPS) xen TAGS $(IBIN) $(LIB) $(QCOW_UTIL)
diff --git a/tools/blktap/lib/Makefile b/tools/blktap/lib/Makefile
index 38f8ac686c..5596410f96 100644
--- a/tools/blktap/lib/Makefile
+++ b/tools/blktap/lib/Makefile
@@ -7,10 +7,6 @@ SONAME = libblktap.so.$(MAJOR)
BLKTAP_INSTALL_DIR = /usr/sbin
-INSTALL = install
-INSTALL_PROG = $(INSTALL) -m0755
-INSTALL_DIR = $(INSTALL) -d -m0755
-
INCLUDES += -I. -I.. -I $(XEN_LIBXC) -I $(XEN_XENSTORE)
LIBS := -lz
@@ -56,8 +52,8 @@ clean:
rm -rf *.a *.so* *.o *.rpm $(LIB) *~ $(DEPS) xen TAGS
libblktap.a: $(OBJS)
- $(CC) $(CFLAGS) -Wl,-soname -Wl,$(SONAME) -shared \
- -L$(XEN_XENSTORE) -l xenstore \
+ $(CC) $(CFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,$(SONAME) $(SHLIB_CFLAGS) \
+ -L$(XEN_XENSTORE) -l xenstore \
-o libblktap.so.$(MAJOR).$(MINOR) $^ $(LIBS)
ln -sf libblktap.so.$(MAJOR).$(MINOR) libblktap.so.$(MAJOR)
ln -sf libblktap.so.$(MAJOR) libblktap.so
diff --git a/tools/check/check_brctl b/tools/check/check_brctl
index 6b8250f5cc..e926120235 100755
--- a/tools/check/check_brctl
+++ b/tools/check/check_brctl
@@ -1,10 +1,27 @@
-#!/bin/bash
+#!/bin/sh
# CHECK-INSTALL
-function error {
- echo
- echo ' *** Check for the bridge control utils (brctl) FAILED'
- exit 1
-}
+RC=0
-which brctl 1>/dev/null 2>&1 || error
+case ${OS} in
+OpenBSD|NetBSD|FreeBSD)
+ # These systems have a bridge builtin
+ TOOL="brconfig"
+ which ${TOOL} 1>/dev/null 2>&1 || RC=1
+ ;;
+Linux)
+ TOOL="brctl"
+ which ${TOOL} 1>/dev/null 2>&1 || RC=1
+ ;;
+*)
+ TOOL=""
+ echo "Unknown OS" && RC=1
+ ;;
+esac
+
+if test ${RC} -ne 0; then
+ echo
+ echo " *** Check for the bridge control utils (${TOOL}) FAILED"
+fi
+
+exit ${RC}
diff --git a/tools/check/check_iproute b/tools/check/check_iproute
index c990349a9b..35af9a4c4b 100755
--- a/tools/check/check_iproute
+++ b/tools/check/check_iproute
@@ -1,11 +1,26 @@
-#!/bin/bash
+#!/bin/sh
# CHECK-INSTALL
-function error {
- echo
- echo ' *** Check for iproute (ip addr) FAILED'
- exit 1
-}
+RC=0
-ip addr list 1>/dev/null 2>&1 || error
+case ${OS} in
+OpenBSD|NetBSD|FreeBSD)
+ TOOL="ifconfig"
+ eval ${TOOL} -a 1>/dev/null 2>&1 || RC=1
+ ;;
+Linux)
+ TOOL="ip addr"
+ eval ${TOOL} list 1>/dev/null 2>&1 || RC=1
+ ;;
+*)
+ TOOL=""
+ echo "Unknown OS" && RC=1
+ ;;
+esac
+if test ${RC} -ne 0; then
+ echo
+ echo " *** Check for iproute (${TOOL}) FAILED"
+fi
+
+exit ${RC}
diff --git a/tools/check/check_python b/tools/check/check_python
index a30b0690a2..e56f5a9684 100755
--- a/tools/check/check_python
+++ b/tools/check/check_python
@@ -1,10 +1,13 @@
-#!/bin/bash
+#!/bin/sh
# CHECK-BUILD CHECK-INSTALL
-function error {
- echo
- echo " *** Check for Python version >= 2.2 FAILED"
- exit 1
-}
+RC=0
-python -V 2>&1 | cut -d ' ' -f 2 | grep -q '^2.[2345]' || error
+python -V 2>&1 | cut -d ' ' -f 2 | grep -q '^2.[2345]' || RC=1
+
+if test ${RC} -ne 0; then
+ echo
+ echo " *** Check for Python version >= 2.2 FAILED"
+fi
+
+exit ${RC}
diff --git a/tools/check/check_zlib_devel b/tools/check/check_zlib_devel
index 4986b4403e..108e06a616 100755
--- a/tools/check/check_zlib_devel
+++ b/tools/check/check_zlib_devel
@@ -1,11 +1,14 @@
-#!/bin/bash
+#!/bin/sh
# CHECK-BUILD
-function error {
- echo
- echo " *** Check for zlib headers FAILED"
- exit 1
-}
+RC=0
set -e
-[ -e /usr/include/zlib.h ] || error
+test -r /usr/include/zlib.h || RC=1
+
+if test ${RC} -ne 0; then
+ echo
+ echo " *** Check for zlib headers FAILED"
+fi
+
+exit ${RC}
diff --git a/tools/check/check_zlib_lib b/tools/check/check_zlib_lib
index 8820a30371..92d879ceda 100755
--- a/tools/check/check_zlib_lib
+++ b/tools/check/check_zlib_lib
@@ -1,11 +1,14 @@
-#!/bin/bash
+#!/bin/sh
# CHECK-BUILD CHECK-INSTALL
-function error {
- echo
- echo " *** Check for zlib library FAILED"
- exit 1
-}
+RC=0
set -e
-ldconfig -p | grep -q libz.so || error
+ldconfig -v 2>&1 | grep -q libz.so || RC=1
+
+if test ${RC} -ne 0; then
+ echo
+ echo " *** Check for zlib library FAILED"
+fi
+
+exit ${RC}
diff --git a/tools/check/chk b/tools/check/chk
index 7859760bd7..d8eb2f17e3 100755
--- a/tools/check/chk
+++ b/tools/check/chk
@@ -1,8 +1,9 @@
-#!/bin/bash
+#!/bin/sh
-function usage {
+func_usage ()
+{
echo "Usage:"
- echo "\t$0 [build|install|clean]"
+ echo " $0 [build|install|clean]"
echo
echo "Check suitability for Xen build or install."
echo "Exit with 0 if OK, 1 if not."
@@ -12,7 +13,13 @@ function usage {
exit 1
}
-export PATH=${PATH}:/sbin:/usr/sbin
+PATH=${PATH}:/sbin:/usr/sbin
+OS=`uname -s`
+export PATH OS
+
+if test "${OS}" = "SunOS"; then
+ exit 0
+fi
case $1 in
build)
@@ -25,7 +32,7 @@ case $1 in
exit 0
;;
*)
- usage
+ func_usage
;;
esac
@@ -54,4 +61,4 @@ for f in check_* ; do
fi
done
-exit $failed
+exit ${failed}
diff --git a/tools/console/Makefile b/tools/console/Makefile
index cbef956c5f..55e08e8f2d 100644
--- a/tools/console/Makefile
+++ b/tools/console/Makefile
@@ -5,10 +5,6 @@ include $(XEN_ROOT)/tools/Rules.mk
DAEMON_INSTALL_DIR = /usr/sbin
CLIENT_INSTALL_DIR = /usr/$(LIBDIR)/xen/bin
-INSTALL = install
-INSTALL_PROG = $(INSTALL) -m0755
-INSTALL_DIR = $(INSTALL) -d -m0755
-
CFLAGS += -Werror -g
CFLAGS += -I $(XEN_LIBXC)
@@ -26,11 +22,11 @@ clean:
xenconsoled: $(patsubst %.c,%.o,$(wildcard daemon/*.c))
$(CC) $(CFLAGS) $^ -o $@ -L$(XEN_LIBXC) -L$(XEN_XENSTORE) \
- -lxenctrl -lxenstore
+ $(SOCKET_LIBS) -lxenctrl -lxenstore
xenconsole: $(patsubst %.c,%.o,$(wildcard client/*.c))
$(CC) $(CFLAGS) $^ -o $@ -L$(XEN_LIBXC) -L$(XEN_XENSTORE) \
- -lxenctrl -lxenstore
+ $(SOCKET_LIBS) -lxenctrl -lxenstore
.PHONY: install
install: $(BIN)
diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
index 8bb18cafab..25ca40372f 100644
--- a/tools/console/daemon/io.c
+++ b/tools/console/daemon/io.c
@@ -147,7 +147,7 @@ static int domain_create_tty(struct domain *dom)
int master;
bool success;
- if ((master = getpt()) == -1 ||
+ if ((master = open("/dev/ptmx",O_RDWR|O_NOCTTY)) == -1 ||
grantpt(master) == -1 || unlockpt(master) == -1) {
dolog(LOG_ERR, "Failed to create tty for domain-%d",
dom->domid);
diff --git a/tools/console/daemon/utils.c b/tools/console/daemon/utils.c
index 40c64211d2..0801a6ccd6 100644
--- a/tools/console/daemon/utils.c
+++ b/tools/console/daemon/utils.c
@@ -95,7 +95,7 @@ void daemonize(const char *pidfile)
exit(1);
}
- len = sprintf(buf, "%d\n", getpid());
+ len = sprintf(buf, "%ld\n", (long)getpid());
if (write(fd, buf, len) < 0)
exit(1);
diff --git a/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c b/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c
index c87096d1c4..8b0b6d944a 100644
--- a/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c
+++ b/tools/debugger/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/linux-xen-low.c
@@ -36,8 +36,6 @@
#include <unistd.h>
#include <errno.h>
#include <xenctrl.h>
-#include <thread_db.h>
-#include <xc_ptrace.h>
#define TRACE_ENTER /* printf("enter %s\n", __FUNCTION__) */
diff --git a/tools/examples/Makefile b/tools/examples/Makefile
index cc5525c2a3..14f34135c8 100644
--- a/tools/examples/Makefile
+++ b/tools/examples/Makefile
@@ -1,11 +1,6 @@
XEN_ROOT = ../../
include $(XEN_ROOT)/tools/Rules.mk
-INSTALL = install
-INSTALL_DIR = $(INSTALL) -d -m0755
-INSTALL_PROG = $(INSTALL) -m0755
-INSTALL_DATA = $(INSTALL) -m0644
-
# Init scripts.
XEND_INITD = init.d/xend
XENDOMAINS_INITD = init.d/xendomains
diff --git a/tools/examples/vtpm-common.sh b/tools/examples/vtpm-common.sh
index e5e8ddbbf5..bf50f323e3 100644
--- a/tools/examples/vtpm-common.sh
+++ b/tools/examples/vtpm-common.sh
@@ -226,7 +226,7 @@ function vtpmdb_remove_entry () {
# Returns 'resume' or 'create'
function vtpm_get_create_reason () {
local resume
- resume=$(xenstore-read $XENBUS_PATH/resume)
+ resume=$(xenstore_read $XENBUS_PATH/resume)
if [ "$resume" == "True" ]; then
echo "resume"
else
@@ -287,6 +287,8 @@ function vtpm_create_instance () {
#entry is kept in the VTPMDB file.
function vtpm_remove_instance () {
local instance reason domname
+ #Stop script execution quietly if path does not exist (anymore)
+ xenstore-exists "$XENBUS_PATH"/domain
domname=$(xenstore_read "$XENBUS_PATH"/domain)
if [ "$domname" != "" ]; then
@@ -383,7 +385,7 @@ function vtpm_domid_from_name () {
local id name ids
ids=$(xenstore-list /local/domain)
for id in $ids; do
- name=$(xenstore-read /local/domain/$id/name)
+ name=$(xenstore_read /local/domain/$id/name)
if [ "$name" == "$1" ]; then
echo "$id"
return
diff --git a/tools/examples/xend-config.sxp b/tools/examples/xend-config.sxp
index ec88a9fb09..294d8e08de 100644
--- a/tools/examples/xend-config.sxp
+++ b/tools/examples/xend-config.sxp
@@ -135,3 +135,7 @@
# to 127.0.0.1 To restore old 'listen everywhere' behaviour
# set this to 0.0.0.0
#(vnc-listen '127.0.0.1')
+
+# The default password for VNC console on HVM domain.
+# Empty string is no authentication.
+(vncpasswd '')
diff --git a/tools/examples/xmexample.hvm b/tools/examples/xmexample.hvm
index cc683d42c2..20b58af44b 100644
--- a/tools/examples/xmexample.hvm
+++ b/tools/examples/xmexample.hvm
@@ -150,6 +150,11 @@ vnc=1
#vncconsole=0
#----------------------------------------------------------------------------
+# set password for domain's VNC console
+# default is depents on vncpasswd in xend-config.sxp
+vncpasswd=''
+
+#----------------------------------------------------------------------------
# no graphics, use serial port
#nographic=0
diff --git a/tools/examples/xmexample.vti b/tools/examples/xmexample.vti
index 3a0d8e1a3a..15efca7a0c 100644
--- a/tools/examples/xmexample.vti
+++ b/tools/examples/xmexample.vti
@@ -95,6 +95,11 @@ vnc=0
#vncconsole=0
#----------------------------------------------------------------------------
+# set password for domain's VNC console
+# default is depents on vncpasswd in xend-config.sxp
+vncpasswd=''
+
+#----------------------------------------------------------------------------
# no graphics, use serial port
#nographic=0
diff --git a/tools/firmware/Makefile b/tools/firmware/Makefile
index 63ccb7b17e..a024e1249e 100644
--- a/tools/firmware/Makefile
+++ b/tools/firmware/Makefile
@@ -4,7 +4,7 @@ include $(XEN_ROOT)/tools/Rules.mk
# hvmloader is a 32-bit protected mode binary.
# It belongs in /usr/lib, not /usr/lib64.
TARGET := hvmloader/hvmloader
-INSTALL_DIR := $(DESTDIR)/usr/lib/xen/boot
+INST_DIR := $(DESTDIR)/usr/lib/xen/boot
SUBDIRS :=
SUBDIRS += rombios
@@ -29,8 +29,8 @@ all:
.PHONY: install
install: all
- [ -d $(INSTALL_DIR) ] || install -d -m0755 $(INSTALL_DIR)
- [ ! -e $(TARGET) ] || install -m0644 $(TARGET) $(INSTALL_DIR)
+ [ -d $(INST_DIR) ] || $(INSTALL_DIR) $(INST_DIR)
+ [ ! -e $(TARGET) ] || $(INSTALL_DATA) $(TARGET) $(INST_DIR)
.PHONY: clean
clean:
diff --git a/tools/firmware/acpi/Makefile b/tools/firmware/acpi/Makefile
index b87cb79a33..3b4bb99b49 100644
--- a/tools/firmware/acpi/Makefile
+++ b/tools/firmware/acpi/Makefile
@@ -53,7 +53,7 @@ iasl:
wget $(IASL_URL)
tar xzf $(IASL_VER).tar.gz
make -C $(IASL_VER)/compiler
- install $(IASL_VER)/compiler/iasl /usr/bin/iasl
+ $(INSTALL_PROG) $(IASL_VER)/compiler/iasl /usr/bin/iasl
$(ACPI_GEN):$(C_SRC) $(H_SRC) acpi_dsdt.c
$(HOSTCC) -o $(ACPI_GEN) $(HOSTCFLAGS) $(shell ls *.c)
diff --git a/tools/firmware/hvmloader/Makefile b/tools/firmware/hvmloader/Makefile
index 3f9b7a95bb..cb740a7d55 100644
--- a/tools/firmware/hvmloader/Makefile
+++ b/tools/firmware/hvmloader/Makefile
@@ -32,13 +32,13 @@ DEFINES =-DDEBUG
XENINC =-I$(XEN_ROOT)/tools/libxc
# Disable PIE/SSP if GCC supports them. They can break us.
-CFLAGS += $(call test-gcc-flag,$(CC),-nopie)
-CFLAGS += $(call test-gcc-flag,$(CC),-fno-stack-protector)
-CFLAGS += $(call test-gcc-flag,$(CC),-fno-stack-protector-all)
+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 += $(DEFINES) -I. $(XENINC) -fno-builtin -O2 -msoft-float
-LDFLAGS = -m32 -nostdlib -Wl,-N -Wl,-Ttext -Wl,$(LOADADDR)
+LDFLAGS = -nostdlib -Wl,-N -Wl,-Ttext -Wl,$(LOADADDR)
SRCS = hvmloader.c acpi_madt.c mp_tables.c util.c smbios.c
OBJS = $(patsubst %.c,%.o,$(SRCS))
@@ -48,7 +48,7 @@ all: hvmloader
hvmloader: roms.h $(SRCS)
$(CC) $(CFLAGS) -c $(SRCS)
- $(CC) $(LDFLAGS) -o hvmloader.tmp $(OBJS)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o hvmloader.tmp $(OBJS)
$(OBJCOPY) hvmloader.tmp hvmloader
rm -f hvmloader.tmp
diff --git a/tools/firmware/vmxassist/Makefile b/tools/firmware/vmxassist/Makefile
index 08fea45781..70f7a0e0a3 100644
--- a/tools/firmware/vmxassist/Makefile
+++ b/tools/firmware/vmxassist/Makefile
@@ -32,14 +32,13 @@ DEFINES=-DDEBUG -DTEXTADDR=$(TEXTADDR)
XENINC=-I$(XEN_ROOT)/tools/libxc
# Disable PIE/SSP if GCC supports them. They can break us.
-CFLAGS += $(call test-gcc-flag,$(CC),-nopie)
-CFLAGS += $(call test-gcc-flag,$(CC),-fno-stack-protector)
-CFLAGS += $(call test-gcc-flag,$(CC),-fno-stack-protector-all)
+CFLAGS += $(call cc-option,$(CC),-nopie,)
+CFLAGS += $(call cc-option,$(CC),-fno-stack-protector,)
+CFLAGS += $(call cc-option,$(CC),-fno-stack-protector-all,)
CPP = cpp -P
OBJCOPY = objcopy -p -O binary -R .note -R .comment -R .bss -S --gap-fill=0
CFLAGS += $(DEFINES) -I. $(XENINC) -fno-builtin -O2 -msoft-float
-LDFLAGS = -m elf_i386
OBJECTS = head.o trap.o vm86.o setup.o util.o
@@ -48,7 +47,7 @@ all: vmxassist.bin
vmxassist.bin: vmxassist.ld $(OBJECTS)
$(CPP) $(DEFINES) vmxassist.ld > vmxassist.tmp
- $(LD) -o vmxassist $(LDFLAGS) -nostdlib --fatal-warnings -N -T vmxassist.tmp $(OBJECTS)
+ $(LD) -o vmxassist $(LDFLAGS_DIRECT) -nostdlib --fatal-warnings -N -T vmxassist.tmp $(OBJECTS)
nm -n vmxassist > vmxassist.sym
$(OBJCOPY) vmxassist vmxassist.tmp
dd if=vmxassist.tmp of=vmxassist.bin ibs=512 conv=sync
diff --git a/tools/firmware/vmxassist/head.S b/tools/firmware/vmxassist/head.S
index b183fac54e..a4cb614c68 100644
--- a/tools/firmware/vmxassist/head.S
+++ b/tools/firmware/vmxassist/head.S
@@ -59,7 +59,7 @@ _start16:
/* go to protected mode */
movl %cr0, %eax
- orl $CR0_PE, %eax
+ orl $(CR0_PE), %eax
movl %eax, %cr0
data32 ljmp $0x08, $1f
diff --git a/tools/firmware/vmxassist/trap.S b/tools/firmware/vmxassist/trap.S
index 468da0a5db..30e87adb85 100644
--- a/tools/firmware/vmxassist/trap.S
+++ b/tools/firmware/vmxassist/trap.S
@@ -106,7 +106,7 @@ common_trap: /* common trap handler */
pushl %es
pushal
- movl $DATA_SELECTOR, %eax /* make sure these are sane */
+ movl $(DATA_SELECTOR), %eax /* make sure these are sane */
movl %eax, %ds
movl %eax, %es
movl %eax, %fs
diff --git a/tools/firmware/vmxassist/util.c b/tools/firmware/vmxassist/util.c
index 0181fe702c..fbfc79a1a3 100644
--- a/tools/firmware/vmxassist/util.c
+++ b/tools/firmware/vmxassist/util.c
@@ -29,6 +29,31 @@ static void putchar(int);
static char *printnum(char *, unsigned long, int);
static void _doprint(void (*)(int), char const *, va_list);
+void
+cpuid_addr_value(uint64_t addr, uint64_t *value)
+{
+ uint32_t addr_low = (uint32_t)addr;
+ uint32_t addr_high = (uint32_t)(addr >> 32);
+ uint32_t value_low, value_high;
+ static unsigned int addr_leaf;
+
+ if (!addr_leaf) {
+ unsigned int eax, ebx, ecx, edx;
+ __asm__ __volatile__(
+ "cpuid"
+ : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
+ : "0" (0x40000000));
+ addr_leaf = eax + 1;
+ }
+
+ __asm__ __volatile__(
+ "cpuid"
+ : "=c" (value_low), "=d" (value_high)
+ : "a" (addr_leaf), "0" (addr_low), "1" (addr_high)
+ : "ebx");
+
+ *value = (uint64_t)value_high << 32 | value_low;
+}
void
dump_regs(struct regs *regs)
diff --git a/tools/firmware/vmxassist/util.h b/tools/firmware/vmxassist/util.h
index b2ace92b8f..c426f4e846 100644
--- a/tools/firmware/vmxassist/util.h
+++ b/tools/firmware/vmxassist/util.h
@@ -31,6 +31,7 @@
struct vmx_assist_context;
+extern void cpuid_addr_value(uint64_t addr, uint64_t *value);
extern void hexdump(unsigned char *, int);
extern void dump_regs(struct regs *);
extern void dump_vmx_context(struct vmx_assist_context *);
diff --git a/tools/firmware/vmxassist/vm86.c b/tools/firmware/vmxassist/vm86.c
index 8c620a4d5c..f997fc22ab 100644
--- a/tools/firmware/vmxassist/vm86.c
+++ b/tools/firmware/vmxassist/vm86.c
@@ -56,8 +56,8 @@ static char *rnames[] = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di" };
#define PT_ENTRY_PRESENT 0x1
/* We only support access to <=4G physical memory due to 1:1 mapping */
-static unsigned
-guest_linear_to_real(uint32_t base)
+static uint64_t
+guest_linear_to_phys(uint32_t base)
{
uint32_t gcr3 = oldctx.cr3;
uint64_t l2_mfn;
@@ -89,23 +89,32 @@ guest_linear_to_real(uint32_t base)
l2_mfn = ((uint64_t *)(long)gcr3)[(base >> 30) & 0x3];
if (!(l2_mfn & PT_ENTRY_PRESENT))
panic("l3 entry not present\n");
- l2_mfn &= 0x3fffff000ULL;
+ l2_mfn &= 0xffffff000ULL;
- l1_mfn = ((uint64_t *)(long)l2_mfn)[(base >> 21) & 0x1ff];
+ if (l2_mfn & 0xf00000000ULL) {
+ printf("l2 page above 4G\n");
+ cpuid_addr_value(l2_mfn + 8 * ((base >> 21) & 0x1ff), &l1_mfn);
+ } else
+ l1_mfn = ((uint64_t *)(long)l2_mfn)[(base >> 21) & 0x1ff];
if (!(l1_mfn & PT_ENTRY_PRESENT))
panic("l2 entry not present\n");
if (l1_mfn & PDE_PS) { /* CR4.PSE is ignored in PAE mode */
- l0_mfn = l1_mfn & 0x3ffe00000ULL;
+ l0_mfn = l1_mfn & 0xfffe00000ULL;
return l0_mfn + (base & 0x1fffff);
}
- l1_mfn &= 0x3fffff000ULL;
+ l1_mfn &= 0xffffff000ULL;
- l0_mfn = ((uint64_t *)(long)l1_mfn)[(base >> 12) & 0x1ff];
+ if (l1_mfn & 0xf00000000ULL) {
+ printf("l1 page above 4G\n");
+ cpuid_addr_value(l1_mfn + 8 * ((base >> 12) & 0x1ff), &l0_mfn);
+ } else
+ l0_mfn = ((uint64_t *)(long)l1_mfn)[(base >> 12) & 0x1ff];
if (!(l0_mfn & PT_ENTRY_PRESENT))
panic("l1 entry not present\n");
- l0_mfn &= 0x3fffff000ULL;
+
+ l0_mfn &= 0xffffff000ULL;
return l0_mfn + (base & 0xfff);
}
@@ -114,6 +123,7 @@ guest_linear_to_real(uint32_t base)
static unsigned
address(struct regs *regs, unsigned seg, unsigned off)
{
+ uint64_t gdt_phys_base;
unsigned long long entry;
unsigned seg_base, seg_limit;
unsigned entry_low, entry_high;
@@ -129,8 +139,13 @@ address(struct regs *regs, unsigned seg, unsigned off)
(mode == VM86_REAL_TO_PROTECTED && regs->cs == seg))
return ((seg & 0xFFFF) << 4) + off;
- entry = ((unsigned long long *)
- guest_linear_to_real(oldctx.gdtr_base))[seg >> 3];
+ gdt_phys_base = guest_linear_to_phys(oldctx.gdtr_base);
+ if (gdt_phys_base != (uint32_t)gdt_phys_base) {
+ printf("gdt base address above 4G\n");
+ cpuid_addr_value(gdt_phys_base + 8 * (seg >> 3), &entry);
+ } else
+ entry = ((unsigned long long *)(long)gdt_phys_base)[seg >> 3];
+
entry_high = entry >> 32;
entry_low = entry & 0xFFFFFFFF;
@@ -804,6 +819,7 @@ pop(struct regs *regs, unsigned prefix, unsigned opc)
static int
load_seg(unsigned long sel, uint32_t *base, uint32_t *limit, union vmcs_arbytes *arbytes)
{
+ uint64_t gdt_phys_base;
unsigned long long entry;
/* protected mode: use seg as index into gdt */
@@ -815,8 +831,12 @@ load_seg(unsigned long sel, uint32_t *base, uint32_t *limit, union vmcs_arbytes
return 1;
}
- entry = ((unsigned long long *)
- guest_linear_to_real(oldctx.gdtr_base))[sel >> 3];
+ gdt_phys_base = guest_linear_to_phys(oldctx.gdtr_base);
+ if (gdt_phys_base != (uint32_t)gdt_phys_base) {
+ printf("gdt base address above 4G\n");
+ cpuid_addr_value(gdt_phys_base + 8 * (sel >> 3), &entry);
+ } else
+ entry = ((unsigned long long *)(long)gdt_phys_base)[sel >> 3];
/* Check the P bit first */
if (!((entry >> (15+32)) & 0x1) && sel != 0)
diff --git a/tools/guest-headers/Makefile b/tools/guest-headers/Makefile
index dc1456667f..1c50599a4c 100644
--- a/tools/guest-headers/Makefile
+++ b/tools/guest-headers/Makefile
@@ -1,5 +1,6 @@
-
XEN_ROOT=../..
+include $(XEN_ROOT)/tools/Rules.mk
+
linuxsparsetree = $(XEN_ROOT)/linux-2.6-xen-sparse
.PHONY: all
@@ -8,10 +9,15 @@ all:
.PHONY: check
check:
-.PHONY: install
-install:
+.PHONY: install install-Linux install-SunOS
+
+install-Linux:
mkdir -p $(DESTDIR)/usr/include/xen/linux
install -m0644 $(linuxsparsetree)/include/xen/public/*.h $(DESTDIR)/usr/include/xen/linux
+install-SunOS:
+
+install: install-$(XEN_OS)
+
.PHONY: clean
clean:
diff --git a/tools/ioemu/Makefile.target b/tools/ioemu/Makefile.target
index c495abbf59..ca8dae4c4e 100644
--- a/tools/ioemu/Makefile.target
+++ b/tools/ioemu/Makefile.target
@@ -23,7 +23,7 @@ VPATH+=:$(SRC_PATH)/linux-user
DEFINES+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ARCH)
endif
CFLAGS+=-Wall -O2 -g -fno-strict-aliasing
-SSE2 := $(call test-gcc-flag,$(CC),-msse2)
+SSE2 := $(call cc-option,$(CC),-msse2,)
ifeq ($(SSE2),-msse2)
CFLAGS += -DUSE_SSE2=1 -msse2
endif
@@ -294,7 +294,11 @@ OBJS+=gdbstub.o
endif
# qemu-dm objects
+ifeq ($(ARCH),ia64)
LIBOBJS=helper2.o exec-dm.o i8259-dm.o
+else
+LIBOBJS=helper2.o exec-dm.o i8259-dm.o rtc-dm.o
+endif
all: $(PROGS)
@@ -354,7 +358,11 @@ VL_OBJS+= ne2000.o rtl8139.o pcnet.o
ifeq ($(TARGET_BASE_ARCH), i386)
# Hardware support
VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
+ifeq ($(ARCH),ia64)
VL_OBJS+= fdc.o mc146818rtc.o serial.o pc.o
+else
+VL_OBJS+= fdc.o serial.o pc.o
+endif
VL_OBJS+= cirrus_vga.o mixeng.o parallel.o acpi.o piix_pci.o
VL_OBJS+= usb-uhci.o
VL_OBJS+= piix4acpi.o
@@ -398,6 +406,7 @@ ifdef CONFIG_SDL
VL_OBJS+=sdl.o
endif
VL_OBJS+=vnc.o
+VL_OBJS+=d3des.o
ifdef CONFIG_COCOA
VL_OBJS+=cocoa.o
COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa -framework IOKit
@@ -458,6 +467,9 @@ sdl.o: sdl.c keymaps.c sdl_keysym.h
vnc.o: vnc.c keymaps.c sdl_keysym.h vnchextile.h
$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
+d3des.o: d3des.c d3des.h
+ $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
+
sdlaudio.o: sdlaudio.c
$(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $<
@@ -555,10 +567,10 @@ distclean: clean
install: all
mkdir -p "$(DESTDIR)$(bindir)" "$(DESTDIR)$(configdir)"
ifneq ($(PROGS),)
- $(INSTALL) -m 755 -s $(PROGS) "$(DESTDIR)$(bindir)"
+ $(INSTALL_PROG) $(PROGS) "$(DESTDIR)$(bindir)"
endif
- install -m 755 $(TARGET_PATH)/qemu-dm.debug "$(DESTDIR)$(bindir)"
- install -m 755 $(TARGET_PATH)/qemu-ifup "$(DESTDIR)$(configdir)"
+ $(INSTALL_PROG) $(TARGET_PATH)/qemu-dm.debug "$(DESTDIR)$(bindir)"
+ $(INSTALL_PROG) $(TARGET_PATH)/qemu-ifup "$(DESTDIR)$(configdir)"
ifneq ($(wildcard .depend),)
include .depend
diff --git a/tools/ioemu/d3des.c b/tools/ioemu/d3des.c
new file mode 100644
index 0000000000..eaca581653
--- /dev/null
+++ b/tools/ioemu/d3des.c
@@ -0,0 +1,434 @@
+/*
+ * This is D3DES (V5.09) by Richard Outerbridge with the double and
+ * triple-length support removed for use in VNC. Also the bytebit[] array
+ * has been reversed so that the most significant bit in each byte of the
+ * key is ignored, not the least significant.
+ *
+ * These changes are:
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This software 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.
+ */
+
+/* D3DES (V5.09) -
+ *
+ * A portable, public domain, version of the Data Encryption Standard.
+ *
+ * Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge.
+ * Thanks to: Dan Hoey for his excellent Initial and Inverse permutation
+ * code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis
+ * Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau,
+ * for humouring me on.
+ *
+ * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge.
+ * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.
+ */
+
+#include "d3des.h"
+
+static void scrunch(unsigned char *, unsigned long *);
+static void unscrun(unsigned long *, unsigned char *);
+static void desfunc(unsigned long *, unsigned long *);
+static void cookey(unsigned long *);
+
+static unsigned long KnL[32] = { 0L };
+
+static unsigned short bytebit[8] = {
+ 01, 02, 04, 010, 020, 040, 0100, 0200 };
+
+static unsigned long bigbyte[24] = {
+ 0x800000L, 0x400000L, 0x200000L, 0x100000L,
+ 0x80000L, 0x40000L, 0x20000L, 0x10000L,
+ 0x8000L, 0x4000L, 0x2000L, 0x1000L,
+ 0x800L, 0x400L, 0x200L, 0x100L,
+ 0x80L, 0x40L, 0x20L, 0x10L,
+ 0x8L, 0x4L, 0x2L, 0x1L };
+
+/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */
+
+static unsigned char pc1[56] = {
+ 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
+ 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
+ 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
+ 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 };
+
+static unsigned char totrot[16] = {
+ 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 };
+
+static unsigned char pc2[48] = {
+ 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
+ 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
+ 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
+ 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };
+
+void deskey(key, edf) /* Thanks to James Gillogly & Phil Karn! */
+unsigned char *key;
+int edf;
+{
+ register int i, j, l, m, n;
+ unsigned char pc1m[56], pcr[56];
+ unsigned long kn[32];
+
+ for ( j = 0; j < 56; j++ ) {
+ l = pc1[j];
+ m = l & 07;
+ pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0;
+ }
+ for( i = 0; i < 16; i++ ) {
+ if( edf == DE1 ) m = (15 - i) << 1;
+ else m = i << 1;
+ n = m + 1;
+ kn[m] = kn[n] = 0L;
+ for( j = 0; j < 28; j++ ) {
+ l = j + totrot[i];
+ if( l < 28 ) pcr[j] = pc1m[l];
+ else pcr[j] = pc1m[l - 28];
+ }
+ for( j = 28; j < 56; j++ ) {
+ l = j + totrot[i];
+ if( l < 56 ) pcr[j] = pc1m[l];
+ else pcr[j] = pc1m[l - 28];
+ }
+ for( j = 0; j < 24; j++ ) {
+ if( pcr[pc2[j]] ) kn[m] |= bigbyte[j];
+ if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j];
+ }
+ }
+ cookey(kn);
+ return;
+ }
+
+static void cookey(raw1)
+register unsigned long *raw1;
+{
+ register unsigned long *cook, *raw0;
+ unsigned long dough[32];
+ register int i;
+
+ cook = dough;
+ for( i = 0; i < 16; i++, raw1++ ) {
+ raw0 = raw1++;
+ *cook = (*raw0 & 0x00fc0000L) << 6;
+ *cook |= (*raw0 & 0x00000fc0L) << 10;
+ *cook |= (*raw1 & 0x00fc0000L) >> 10;
+ *cook++ |= (*raw1 & 0x00000fc0L) >> 6;
+ *cook = (*raw0 & 0x0003f000L) << 12;
+ *cook |= (*raw0 & 0x0000003fL) << 16;
+ *cook |= (*raw1 & 0x0003f000L) >> 4;
+ *cook++ |= (*raw1 & 0x0000003fL);
+ }
+ usekey(dough);
+ return;
+ }
+
+void cpkey(into)
+register unsigned long *into;
+{
+ register unsigned long *from, *endp;
+
+ from = KnL, endp = &KnL[32];
+ while( from < endp ) *into++ = *from++;
+ return;
+ }
+
+void usekey(from)
+register unsigned long *from;
+{
+ register unsigned long *to, *endp;
+
+ to = KnL, endp = &KnL[32];
+ while( to < endp ) *to++ = *from++;
+ return;
+ }
+
+void des(inblock, outblock)
+unsigned char *inblock, *outblock;
+{
+ unsigned long work[2];
+
+ scrunch(inblock, work);
+ desfunc(work, KnL);
+ unscrun(work, outblock);
+ return;
+ }
+
+static void scrunch(outof, into)
+register unsigned char *outof;
+register unsigned long *into;
+{
+ *into = (*outof++ & 0xffL) << 24;
+ *into |= (*outof++ & 0xffL) << 16;
+ *into |= (*outof++ & 0xffL) << 8;
+ *into++ |= (*outof++ & 0xffL);
+ *into = (*outof++ & 0xffL) << 24;
+ *into |= (*outof++ & 0xffL) << 16;
+ *into |= (*outof++ & 0xffL) << 8;
+ *into |= (*outof & 0xffL);
+ return;
+ }
+
+static void unscrun(outof, into)
+register unsigned long *outof;
+register unsigned char *into;
+{
+ *into++ = (unsigned char)((*outof >> 24) & 0xffL);
+ *into++ = (unsigned char)((*outof >> 16) & 0xffL);
+ *into++ = (unsigned char)((*outof >> 8) & 0xffL);
+ *into++ = (unsigned char)(*outof++ & 0xffL);
+ *into++ = (unsigned char)((*outof >> 24) & 0xffL);
+ *into++ = (unsigned char)((*outof >> 16) & 0xffL);
+ *into++ = (unsigned char)((*outof >> 8) & 0xffL);
+ *into = (unsigned char)(*outof & 0xffL);
+ return;
+ }
+
+static unsigned long SP1[64] = {
+ 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
+ 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
+ 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
+ 0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
+ 0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
+ 0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
+ 0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
+ 0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
+ 0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
+ 0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
+ 0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
+ 0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
+ 0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
+ 0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
+ 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,
+ 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L };
+
+static unsigned long SP2[64] = {
+ 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L,
+ 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L,
+ 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L,
+ 0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L,
+ 0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L,
+ 0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L,
+ 0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L,
+ 0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L,
+ 0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L,
+ 0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L,
+ 0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L,
+ 0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L,
+ 0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L,
+ 0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,
+ 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L,
+ 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L };
+
+static unsigned long SP3[64] = {
+ 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L,
+ 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L,
+ 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L,
+ 0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L,
+ 0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L,
+ 0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L,
+ 0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L,
+ 0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L,
+ 0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L,
+ 0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L,
+ 0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,
+ 0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L,
+ 0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,
+ 0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,
+ 0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,
+ 0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L };
+
+static unsigned long SP4[64] = {
+ 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
+ 0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,
+ 0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L,
+ 0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L,
+ 0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L,
+ 0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,
+ 0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L,
+ 0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,
+ 0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,
+ 0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L,
+ 0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L,
+ 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
+ 0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L,
+ 0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,
+ 0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,
+ 0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L };
+
+static unsigned long SP5[64] = {
+ 0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L,
+ 0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L,
+ 0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,
+ 0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,
+ 0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L,
+ 0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,
+ 0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L,
+ 0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,
+ 0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L,
+ 0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,
+ 0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,
+ 0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L,
+ 0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,
+ 0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L,
+ 0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,
+ 0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L };
+
+static unsigned long SP6[64] = {
+ 0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L,
+ 0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L,
+ 0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L,
+ 0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L,
+ 0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L,
+ 0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L,
+ 0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L,
+ 0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L,
+ 0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L,
+ 0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L,
+ 0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L,
+ 0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L,
+ 0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L,
+ 0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L,
+ 0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L,
+ 0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L };
+
+static unsigned long SP7[64] = {
+ 0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,
+ 0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,
+ 0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,
+ 0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,
+ 0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,
+ 0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,
+ 0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,
+ 0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,
+ 0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,
+ 0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,
+ 0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,
+ 0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,
+ 0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,
+ 0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,
+ 0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,
+ 0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L };
+
+static unsigned long SP8[64] = {
+ 0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,
+ 0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,
+ 0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,
+ 0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,
+ 0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,
+ 0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,
+ 0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,
+ 0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,
+ 0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,
+ 0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,
+ 0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,
+ 0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,
+ 0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,
+ 0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,
+ 0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,
+ 0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L };
+
+static void desfunc(block, keys)
+register unsigned long *block, *keys;
+{
+ register unsigned long fval, work, right, leftt;
+ register int round;
+
+ leftt = block[0];
+ right = block[1];
+ work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
+ right ^= work;
+ leftt ^= (work << 4);
+ work = ((leftt >> 16) ^ right) & 0x0000ffffL;
+ right ^= work;
+ leftt ^= (work << 16);
+ work = ((right >> 2) ^ leftt) & 0x33333333L;
+ leftt ^= work;
+ right ^= (work << 2);
+ work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
+ leftt ^= work;
+ right ^= (work << 8);
+ right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL;
+ work = (leftt ^ right) & 0xaaaaaaaaL;
+ leftt ^= work;
+ right ^= work;
+ leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL;
+
+ for( round = 0; round < 8; round++ ) {
+ work = (right << 28) | (right >> 4);
+ work ^= *keys++;
+ fval = SP7[ work & 0x3fL];
+ fval |= SP5[(work >> 8) & 0x3fL];
+ fval |= SP3[(work >> 16) & 0x3fL];
+ fval |= SP1[(work >> 24) & 0x3fL];
+ work = right ^ *keys++;
+ fval |= SP8[ work & 0x3fL];
+ fval |= SP6[(work >> 8) & 0x3fL];
+ fval |= SP4[(work >> 16) & 0x3fL];
+ fval |= SP2[(work >> 24) & 0x3fL];
+ leftt ^= fval;
+ work = (leftt << 28) | (leftt >> 4);
+ work ^= *keys++;
+ fval = SP7[ work & 0x3fL];
+ fval |= SP5[(work >> 8) & 0x3fL];
+ fval |= SP3[(work >> 16) & 0x3fL];
+ fval |= SP1[(work >> 24) & 0x3fL];
+ work = leftt ^ *keys++;
+ fval |= SP8[ work & 0x3fL];
+ fval |= SP6[(work >> 8) & 0x3fL];
+ fval |= SP4[(work >> 16) & 0x3fL];
+ fval |= SP2[(work >> 24) & 0x3fL];
+ right ^= fval;
+ }
+
+ right = (right << 31) | (right >> 1);
+ work = (leftt ^ right) & 0xaaaaaaaaL;
+ leftt ^= work;
+ right ^= work;
+ leftt = (leftt << 31) | (leftt >> 1);
+ work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
+ right ^= work;
+ leftt ^= (work << 8);
+ work = ((leftt >> 2) ^ right) & 0x33333333L;
+ right ^= work;
+ leftt ^= (work << 2);
+ work = ((right >> 16) ^ leftt) & 0x0000ffffL;
+ leftt ^= work;
+ right ^= (work << 16);
+ work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
+ leftt ^= work;
+ right ^= (work << 4);
+ *block++ = right;
+ *block = leftt;
+ return;
+ }
+
+/* Validation sets:
+ *
+ * Single-length key, single-length plaintext -
+ * Key : 0123 4567 89ab cdef
+ * Plain : 0123 4567 89ab cde7
+ * Cipher : c957 4425 6a5e d31d
+ *
+ * Double-length key, single-length plaintext -
+ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210
+ * Plain : 0123 4567 89ab cde7
+ * Cipher : 7f1d 0a77 826b 8aff
+ *
+ * Double-length key, double-length plaintext -
+ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210
+ * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff
+ * Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7
+ *
+ * Triple-length key, single-length plaintext -
+ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
+ * Plain : 0123 4567 89ab cde7
+ * Cipher : de0b 7c06 ae5e 0ed5
+ *
+ * Triple-length key, double-length plaintext -
+ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
+ * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff
+ * Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5
+ *
+ * d3des V5.0a rwo 9208.07 18:44 Graven Imagery
+ **********************************************************************/
diff --git a/tools/ioemu/d3des.h b/tools/ioemu/d3des.h
new file mode 100644
index 0000000000..ea3da44ce9
--- /dev/null
+++ b/tools/ioemu/d3des.h
@@ -0,0 +1,51 @@
+/*
+ * This is D3DES (V5.09) by Richard Outerbridge with the double and
+ * triple-length support removed for use in VNC.
+ *
+ * These changes are:
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This software 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.
+ */
+
+/* d3des.h -
+ *
+ * Headers and defines for d3des.c
+ * Graven Imagery, 1992.
+ *
+ * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge
+ * (GEnie : OUTER; CIS : [71755,204])
+ */
+
+#define EN0 0 /* MODE == encrypt */
+#define DE1 1 /* MODE == decrypt */
+
+extern void deskey(unsigned char *, int);
+/* hexkey[8] MODE
+ * Sets the internal key register according to the hexadecimal
+ * key contained in the 8 bytes of hexkey, according to the DES,
+ * for encryption or decryption according to MODE.
+ */
+
+extern void usekey(unsigned long *);
+/* cookedkey[32]
+ * Loads the internal key register with the data in cookedkey.
+ */
+
+extern void cpkey(unsigned long *);
+/* cookedkey[32]
+ * Copies the contents of the internal key register into the storage
+ * located at &cookedkey[0].
+ */
+
+extern void des(unsigned char *, unsigned char *);
+/* from[8] to[8]
+ * Encrypts/Decrypts (according to the key currently loaded in the
+ * internal key register) one block of eight bytes at address 'from'
+ * into the block at address 'to'. They can be the same.
+ */
+
+/* d3des.h V5.09 rwo 9208.04 15:06 Graven Imagery
+ ********************************************************************/
diff --git a/tools/ioemu/hw/ide.c b/tools/ioemu/hw/ide.c
index 8b070cc0cc..94d5beaad5 100644
--- a/tools/ioemu/hw/ide.c
+++ b/tools/ioemu/hw/ide.c
@@ -557,9 +557,9 @@ static void ide_atapi_identify(IDEState *s)
padstr((uint8_t *)(p + 23), QEMU_VERSION, 8); /* firmware version */
padstr((uint8_t *)(p + 27), "QEMU CD-ROM", 40); /* model */
put_le16(p + 48, 1); /* dword I/O (XXX: should not be set on CDROM) */
- put_le16(p + 49, 1 << 9); /* LBA supported, no DMA */
+ put_le16(p + 49, (1 << 11) | (1 << 9) | (1 << 8)); /* DMA and LBA supported */
put_le16(p + 53, 3); /* words 64-70, 54-58 valid */
- put_le16(p + 63, 0x103); /* DMA modes XXX: may be incorrect */
+ put_le16(p + 63, 0x07); /* mdma0-2 supported */
put_le16(p + 64, 1); /* PIO modes */
put_le16(p + 65, 0xb4); /* minimum DMA multiword tx cycle time */
put_le16(p + 66, 0xb4); /* recommended DMA multiword tx cycle time */
diff --git a/tools/ioemu/hw/xen_platform.c b/tools/ioemu/hw/xen_platform.c
index 89072925c2..a0e9f1e397 100644
--- a/tools/ioemu/hw/xen_platform.c
+++ b/tools/ioemu/hw/xen_platform.c
@@ -97,7 +97,8 @@ struct pci_config_header {
uint8_t bist; /* Built in self test */
uint32_t base_address_regs[6];
uint32_t reserved1;
- uint32_t reserved2;
+ uint16_t subsystem_vendor_id;
+ uint16_t subsystem_id;
uint32_t rom_addr;
uint32_t reserved3;
uint32_t reserved4;
@@ -126,6 +127,11 @@ void pci_xen_platform_init(PCIBus *bus)
pch->header_type = 0;
pch->interrupt_pin = 1;
+ /* Microsoft WHQL requires non-zero subsystem IDs. */
+ /* http://www.pcisig.com/reflector/msg02205.html. */
+ pch->subsystem_vendor_id = pch->vendor_id; /* Duplicate vendor id. */
+ pch->subsystem_id = 0x0001; /* Hardcode sub-id as 1. */
+
pci_register_io_region(d, 0, 0x100, PCI_ADDRESS_SPACE_IO,
platform_ioport_map);
diff --git a/tools/ioemu/target-i386-dm/rtc-dm.c b/tools/ioemu/target-i386-dm/rtc-dm.c
new file mode 100644
index 0000000000..e8be999dba
--- /dev/null
+++ b/tools/ioemu/target-i386-dm/rtc-dm.c
@@ -0,0 +1,107 @@
+/*
+ * QEMU MC146818 RTC emulation
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "vl.h"
+
+//#define DEBUG_CMOS
+
+struct RTCState {
+ uint8_t cmos_data[128];
+ uint8_t cmos_index;
+};
+
+void rtc_set_memory(RTCState *s, int addr, int val)
+{
+ if (addr >= 0 && addr <= 127)
+ s->cmos_data[addr] = val;
+}
+
+static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
+{
+ RTCState *s = opaque;
+
+ if ((addr & 1) == 0) {
+ s->cmos_index = data & 0x7f;
+ } else {
+#ifdef DEBUG_CMOS
+ printf("cmos: write index=0x%02x val=0x%02x\n",
+ s->cmos_index, data);
+#endif
+ s->cmos_data[s->cmos_index] = data;
+ }
+}
+
+static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
+{
+ RTCState *s = opaque;
+ int ret;
+ if ((addr & 1) == 0) {
+ return 0xff;
+ } else {
+ ret = s->cmos_data[s->cmos_index];
+#ifdef DEBUG_CMOS
+ printf("cmos: read index=0x%02x val=0x%02x\n",
+ s->cmos_index, ret);
+#endif
+ return ret;
+ }
+}
+
+static void rtc_save(QEMUFile *f, void *opaque)
+{
+ RTCState *s = opaque;
+
+ qemu_put_buffer(f, s->cmos_data, 128);
+ qemu_put_8s(f, &s->cmos_index);
+}
+
+static int rtc_load(QEMUFile *f, void *opaque, int version_id)
+{
+ RTCState *s = opaque;
+
+ if (version_id != 1)
+ return -EINVAL;
+
+ qemu_get_buffer(f, s->cmos_data, 128);
+ qemu_get_8s(f, &s->cmos_index);
+
+ return 0;
+}
+
+RTCState *rtc_init(int base, int irq)
+{
+ RTCState *s;
+
+ s = qemu_mallocz(sizeof(RTCState));
+ if (!s)
+ return NULL;
+
+ register_ioport_write(base, 2, 1, cmos_ioport_write, s);
+ register_ioport_read(base, 2, 1, cmos_ioport_read, s);
+
+ register_savevm("mc146818rtc", base, 1, rtc_save, rtc_load, s);
+ return s;
+}
+
+void rtc_set_date(RTCState *s, const struct tm *tm) {}
diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c
index f5ce725a72..185547743a 100644
--- a/tools/ioemu/vl.c
+++ b/tools/ioemu/vl.c
@@ -171,6 +171,9 @@ time_t timeoffset = 0;
char domain_name[1024] = { 'H','V', 'M', 'X', 'E', 'N', '-'};
extern int domid;
+char vncpasswd[64];
+unsigned char challenge[AUTHCHALLENGESIZE];
+
/***********************************************************/
/* x86 ISA bus support */
@@ -3028,7 +3031,7 @@ void net_slirp_smb(const char *exported_dir)
}
/* XXX: better tmp dir construction */
- snprintf(smb_dir, sizeof(smb_dir), "/tmp/qemu-smb.%d", getpid());
+ snprintf(smb_dir, sizeof(smb_dir), "/tmp/qemu-smb.%ld", (long)getpid());
if (mkdir(smb_dir, 0700) < 0) {
fprintf(stderr, "qemu: could not create samba server dir '%s'\n", smb_dir);
exit(1);
@@ -3995,7 +3998,7 @@ static void create_pidfile(const char *filename)
perror("Opening pidfile");
exit(1);
}
- fprintf(f, "%d\n", getpid());
+ fprintf(f, "%ld\n", (long)getpid());
fclose(f);
pid_filename = qemu_strdup(filename);
if (!pid_filename) {
@@ -5911,6 +5914,7 @@ int main(int argc, char **argv)
vncunused = 0;
kernel_filename = NULL;
kernel_cmdline = "";
+ *vncpasswd = '\0';
#ifndef CONFIG_DM
#ifdef TARGET_PPC
cdrom_index = 1;
@@ -5942,7 +5946,7 @@ int main(int argc, char **argv)
memset(&vnclisten_addr.sin_addr, 0, sizeof(vnclisten_addr.sin_addr));
/* init debug */
- sprintf(qemu_dm_logfilename, "/var/log/xen/qemu-dm.%d.log", getpid());
+ sprintf(qemu_dm_logfilename, "/var/log/xen/qemu-dm.%ld.log", (long)getpid());
cpu_set_log_filename(qemu_dm_logfilename);
cpu_set_log(0);
@@ -6559,6 +6563,10 @@ int main(int argc, char **argv)
init_ioports();
+ /* read vncpasswd from xenstore */
+ if (0 > xenstore_read_vncpasswd(domid))
+ exit(1);
+
/* terminal init */
if (nographic) {
dumb_display_init(ds);
diff --git a/tools/ioemu/vl.h b/tools/ioemu/vl.h
index 2cf874c054..864079f682 100644
--- a/tools/ioemu/vl.h
+++ b/tools/ioemu/vl.h
@@ -1211,6 +1211,7 @@ int xenstore_fd(void);
void xenstore_process_event(void *opaque);
void xenstore_check_new_media_present(int timeout);
void xenstore_write_vncport(int vnc_display);
+int xenstore_read_vncpasswd(int domid);
/* xen_platform.c */
void pci_xen_platform_init(PCIBus *bus);
@@ -1222,4 +1223,7 @@ extern char domain_name[];
void destroy_hvm_domain(void);
+/* VNC Authentication */
+#define AUTHCHALLENGESIZE 16
+
#endif /* VL_H */
diff --git a/tools/ioemu/vnc.c b/tools/ioemu/vnc.c
index 60d0449272..9b8bcffa37 100644
--- a/tools/ioemu/vnc.c
+++ b/tools/ioemu/vnc.c
@@ -44,6 +44,7 @@
#include "vnc_keysym.h"
#include "keymaps.c"
+#include "d3des.h"
#define XK_MISCELLANY
#define XK_LATIN1
@@ -137,6 +138,9 @@ static void _vnc_update_client(void *opaque);
static void vnc_update_client(void *opaque);
static void vnc_client_read(void *opaque);
static void framebuffer_set_updated(VncState *vs, int x, int y, int w, int h);
+static int make_challenge(char *random, int size);
+static void set_seed(unsigned int *seedp);
+static void get_random(int len, unsigned char *buf);
#if 0
static inline void vnc_set_bit(uint32_t *d, int k)
@@ -1208,23 +1212,92 @@ static int protocol_client_init(VncState *vs, char *data, size_t len)
return 0;
}
+static int protocol_response(VncState *vs, char *client_response, size_t len)
+{
+ extern char vncpasswd[64];
+ extern unsigned char challenge[AUTHCHALLENGESIZE];
+ unsigned char cryptchallenge[AUTHCHALLENGESIZE];
+ unsigned char key[8];
+ int passwdlen, i, j;
+
+ memcpy(cryptchallenge, challenge, AUTHCHALLENGESIZE);
+
+ /* Calculate the sent challenge */
+ passwdlen = strlen(vncpasswd);
+ for (i=0; i<8; i++)
+ key[i] = i<passwdlen ? vncpasswd[i] : 0;
+ deskey(key, EN0);
+ for (j = 0; j < AUTHCHALLENGESIZE; j += 8)
+ des(cryptchallenge+j, cryptchallenge+j);
+
+ /* Check the actual response */
+ if (memcmp(cryptchallenge, client_response, AUTHCHALLENGESIZE) != 0) {
+ /* password error */
+ vnc_write_u32(vs, 1);
+ vnc_write_u32(vs, 22);
+ vnc_write(vs, "Authentication failure", 22);
+ vnc_flush(vs);
+ fprintf(stderr, "VNC Password error.\n");
+ vnc_client_error(vs);
+ return 0;
+ }
+
+ vnc_write_u32(vs, 0);
+ vnc_flush(vs);
+
+ vnc_read_when(vs, protocol_client_init, 1);
+
+ return 0;
+}
+
static int protocol_version(VncState *vs, char *version, size_t len)
{
+ extern char vncpasswd[64];
+ extern unsigned char challenge[AUTHCHALLENGESIZE];
char local[13];
- int maj, min;
+ int support, maj, min;
memcpy(local, version, 12);
local[12] = 0;
+ /* protocol version check */
if (sscanf(local, "RFB %03d.%03d\n", &maj, &min) != 2) {
+ fprintf(stderr, "Protocol version error.\n");
vnc_client_error(vs);
return 0;
}
- vnc_write_u32(vs, 1); /* None */
- vnc_flush(vs);
- vnc_read_when(vs, protocol_client_init, 1);
+ support = 0;
+ if (maj = 3) {
+ if (min == 3 || min ==4) {
+ support = 1;
+ }
+ }
+
+ if (! support) {
+ fprintf(stderr, "Client uses unsupported protocol version %d.%d.\n",
+ maj, min);
+ vnc_client_error(vs);
+ return 0;
+ }
+
+ if (*vncpasswd == '\0') {
+ /* AuthType is None */
+ vnc_write_u32(vs, 1);
+ vnc_flush(vs);
+ vnc_read_when(vs, protocol_client_init, 1);
+ } else {
+ /* AuthType is VncAuth */
+ vnc_write_u32(vs, 2);
+
+ /* Challenge-Responce authentication */
+ /* Send Challenge */
+ make_challenge(challenge, AUTHCHALLENGESIZE);
+ vnc_write(vs, challenge, AUTHCHALLENGESIZE);
+ vnc_flush(vs);
+ vnc_read_when(vs, protocol_response, AUTHCHALLENGESIZE);
+ }
return 0;
}
@@ -1342,3 +1415,32 @@ int vnc_start_viewer(int port)
return pid;
}
}
+
+unsigned int seed;
+
+static int make_challenge(char *random, int size)
+{
+
+ set_seed(&seed);
+ get_random(size, random);
+
+ return 0;
+}
+
+static void set_seed(unsigned int *seedp)
+{
+ *seedp += (unsigned int)(time(NULL)+getpid()+getpid()*987654+rand());
+ srand(*seedp);
+
+ return;
+}
+
+static void get_random(int len, unsigned char *buf)
+{
+ int i;
+
+ for (i=0; i<len; i++)
+ buf[i] = (int) (256.0*rand()/(RAND_MAX+1.0));
+
+ return;
+}
diff --git a/tools/ioemu/xenstore.c b/tools/ioemu/xenstore.c
index fde469305a..ed978366b8 100644
--- a/tools/ioemu/xenstore.c
+++ b/tools/ioemu/xenstore.c
@@ -213,3 +213,54 @@ void xenstore_write_vncport(int display)
free(portstr);
free(buf);
}
+
+int xenstore_read_vncpasswd(int domid)
+{
+ extern char vncpasswd[64];
+ char *buf = NULL, *path, *uuid = NULL, *passwd = NULL;
+ unsigned int i, len, rc = 0;
+
+ if (xsh == NULL) {
+ return -1;
+ }
+
+ path = xs_get_domain_path(xsh, domid);
+ if (path == NULL) {
+ fprintf(logfile, "xs_get_domain_path() error. domid %d.\n", domid);
+ return -1;
+ }
+
+ pasprintf(&buf, "%s/vm", path);
+ uuid = xs_read(xsh, XBT_NULL, buf, &len);
+ if (uuid == NULL) {
+ fprintf(logfile, "xs_read(): uuid get error. %s.\n", buf);
+ free(path);
+ return -1;
+ }
+
+ pasprintf(&buf, "%s/vncpasswd", uuid);
+ passwd = xs_read(xsh, XBT_NULL, buf, &len);
+ if (passwd == NULL) {
+ fprintf(logfile, "xs_read(): vncpasswd get error. %s.\n", buf);
+ free(uuid);
+ free(path);
+ return rc;
+ }
+
+ for (i=0; i<len && i<63; i++) {
+ vncpasswd[i] = passwd[i];
+ passwd[i] = '\0';
+ }
+ vncpasswd[len] = '\0';
+ pasprintf(&buf, "%s/vncpasswd", uuid);
+ if (xs_write(xsh, XBT_NULL, buf, passwd, len) == 0) {
+ fprintf(logfile, "xs_write() vncpasswd failed.\n");
+ rc = -1;
+ }
+
+ free(passwd);
+ free(uuid);
+ free(path);
+
+ return rc;
+}
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
index caec7ec38a..b5e61af64d 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -1,15 +1,9 @@
-
-INSTALL = install
-INSTALL_PROG = $(INSTALL) -m0755
-INSTALL_DATA = $(INSTALL) -m0644
-INSTALL_DIR = $(INSTALL) -d -m0755
+XEN_ROOT = ../..
+include $(XEN_ROOT)/tools/Rules.mk
MAJOR = 3.0
MINOR = 0
-XEN_ROOT = ../..
-include $(XEN_ROOT)/tools/Rules.mk
-
CTRL_SRCS-y :=
CTRL_SRCS-y += xc_core.c
CTRL_SRCS-y += xc_domain.c
@@ -21,8 +15,10 @@ CTRL_SRCS-y += xc_private.c
CTRL_SRCS-y += xc_sedf.c
CTRL_SRCS-y += xc_csched.c
CTRL_SRCS-y += xc_tbuf.c
-CTRL_SRCS-$(CONFIG_X86) += xc_ptrace.c xc_ptrace_core.c xc_pagetab.c
+CTRL_SRCS-$(CONFIG_X86) += xc_pagetab.c
CTRL_SRCS-$(CONFIG_Linux) += xc_linux.c
+CTRL_SRCS-$(CONFIG_SunOS) += xc_solaris.c
+CTRL_SRCS-$(CONFIG_X86_Linux) += xc_ptrace.c xc_ptrace_core.c
GUEST_SRCS-y :=
GUEST_SRCS-y += xc_load_bin.c
@@ -123,7 +119,7 @@ libxenctrl.so.$(MAJOR): libxenctrl.so.$(MAJOR).$(MINOR)
ln -sf $< $@
libxenctrl.so.$(MAJOR).$(MINOR): $(CTRL_PIC_OBJS)
- $(CC) $(CFLAGS) $(LDFLAGS) -Wl,-soname -Wl,libxenctrl.so.$(MAJOR) -shared -o $@ $^
+ $(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenctrl.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $^
# libxenguest
@@ -136,7 +132,7 @@ libxenguest.so.$(MAJOR): libxenguest.so.$(MAJOR).$(MINOR)
ln -sf $< $@
libxenguest.so.$(MAJOR).$(MINOR): $(GUEST_PIC_OBJS) libxenctrl.so
- $(CC) $(CFLAGS) $(LDFLAGS) -Wl,-soname -Wl,libxenguest.so.$(MAJOR) -shared -o $@ $^ -lz -lxenctrl
+ $(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenguest.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $(GUEST_PIC_OBJS) -lz -lxenctrl
-include $(DEPS)
diff --git a/tools/libxc/ia64/xc_ia64_linux_restore.c b/tools/libxc/ia64/xc_ia64_linux_restore.c
index 0dadb96c78..e6aed35ead 100644
--- a/tools/libxc/ia64/xc_ia64_linux_restore.c
+++ b/tools/libxc/ia64/xc_ia64_linux_restore.c
@@ -44,11 +44,11 @@ read_page(int xc_handle, int io_fd, uint32_t dom, unsigned long pfn)
mem = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
PROT_READ|PROT_WRITE, pfn);
if (mem == NULL) {
- ERR("cannot map page");
+ ERROR("cannot map page");
return -1;
}
if (!read_exact(io_fd, mem, PAGE_SIZE)) {
- ERR("Error when reading from state file (5)");
+ ERROR("Error when reading from state file (5)");
return -1;
}
munmap(mem, PAGE_SIZE);
@@ -85,17 +85,17 @@ xc_linux_restore(int xc_handle, int io_fd, uint32_t dom,
if (!read_exact(io_fd, &ver, sizeof(unsigned long))) {
- ERR("Error when reading version");
+ ERROR("Error when reading version");
goto out;
}
if (ver != 1) {
- ERR("version of save doesn't match");
+ ERROR("version of save doesn't match");
goto out;
}
if (mlock(&ctxt, sizeof(ctxt))) {
/* needed for build domctl, but might as well do early */
- ERR("Unable to mlock ctxt");
+ ERROR("Unable to mlock ctxt");
return 1;
}
@@ -103,7 +103,7 @@ xc_linux_restore(int xc_handle, int io_fd, uint32_t dom,
domctl.cmd = XEN_DOMCTL_getdomaininfo;
domctl.domain = (domid_t)dom;
if (xc_domctl(xc_handle, &domctl) < 0) {
- ERR("Could not get information on new domain");
+ ERROR("Could not get information on new domain");
goto out;
}
shared_info_frame = domctl.u.getdomaininfo.shared_info_frame;
@@ -115,7 +115,7 @@ xc_linux_restore(int xc_handle, int io_fd, uint32_t dom,
if (xc_domain_memory_increase_reservation(xc_handle, dom, max_pfn,
0, 0, NULL) != 0) {
- ERR("Failed to increase reservation by %ld KB", PFN_TO_KB(max_pfn));
+ ERROR("Failed to increase reservation by %ld KB", PFN_TO_KB(max_pfn));
errno = ENOMEM;
goto out;
}
@@ -123,7 +123,7 @@ xc_linux_restore(int xc_handle, int io_fd, uint32_t dom,
DPRINTF("Increased domain reservation by %ld KB\n", PFN_TO_KB(max_pfn));
if (!read_exact(io_fd, &domctl.u.arch_setup, sizeof(domctl.u.arch_setup))) {
- ERR("read: domain setup");
+ ERROR("read: domain setup");
goto out;
}
@@ -141,13 +141,13 @@ xc_linux_restore(int xc_handle, int io_fd, uint32_t dom,
/* Get pages. */
page_array = malloc(max_pfn * sizeof(unsigned long));
if (page_array == NULL ) {
- ERR("Could not allocate memory");
+ ERROR("Could not allocate memory");
goto out;
}
if (xc_ia64_get_pfn_list(xc_handle, dom, page_array,
0, max_pfn) != max_pfn) {
- ERR("Could not get the page frame list");
+ ERROR("Could not get the page frame list");
goto out;
}
@@ -155,7 +155,7 @@ xc_linux_restore(int xc_handle, int io_fd, uint32_t dom,
while (1) {
if (!read_exact(io_fd, &mfn, sizeof(unsigned long))) {
- ERR("Error when reading batch size");
+ ERROR("Error when reading batch size");
goto out;
}
if (mfn == INVALID_MFN)
@@ -178,18 +178,18 @@ xc_linux_restore(int xc_handle, int io_fd, uint32_t dom,
int rc;
if (!read_exact(io_fd, &count, sizeof(count))) {
- ERR("Error when reading pfn count");
+ ERROR("Error when reading pfn count");
goto out;
}
pfntab = malloc(sizeof(unsigned long) * count);
if (!pfntab) {
- ERR("Out of memory");
+ ERROR("Out of memory");
goto out;
}
if (!read_exact(io_fd, pfntab, sizeof(unsigned long)*count)) {
- ERR("Error when reading pfntab");
+ ERROR("Error when reading pfntab");
goto out;
}
@@ -211,7 +211,7 @@ xc_linux_restore(int xc_handle, int io_fd, uint32_t dom,
rc = xc_memory_op(xc_handle, XENMEM_decrease_reservation,
&reservation);
if (rc != 1) {
- ERR("Could not decrease reservation : %d", rc);
+ ERROR("Could not decrease reservation : %d", rc);
goto out;
}
}
@@ -221,7 +221,7 @@ xc_linux_restore(int xc_handle, int io_fd, uint32_t dom,
if (!read_exact(io_fd, &ctxt, sizeof(ctxt))) {
- ERR("Error when reading ctxt");
+ ERROR("Error when reading ctxt");
goto out;
}
@@ -234,7 +234,7 @@ xc_linux_restore(int xc_handle, int io_fd, uint32_t dom,
domctl.u.vcpucontext.vcpu = 0;
set_xen_guest_handle(domctl.u.vcpucontext.ctxt, &ctxt);
if (xc_domctl(xc_handle, &domctl) != 0) {
- ERR("Couldn't set vcpu context");
+ ERROR("Couldn't set vcpu context");
goto out;
}
@@ -245,19 +245,19 @@ xc_linux_restore(int xc_handle, int io_fd, uint32_t dom,
domctl.u.vcpucontext.vcpu = 0;
set_xen_guest_handle(domctl.u.vcpucontext.ctxt, &ctxt);
if (xc_domctl(xc_handle, &domctl) != 0) {
- ERR("Couldn't set vcpu context");
+ ERROR("Couldn't set vcpu context");
goto out;
}
/* Just a check. */
if (xc_vcpu_getcontext(xc_handle, dom, 0 /* XXX */, &ctxt)) {
- ERR("Could not get vcpu context");
+ ERROR("Could not get vcpu context");
goto out;
}
/* Then get privreg page. */
if (read_page(xc_handle, io_fd, dom, ctxt.privregs_pfn) < 0) {
- ERR("Could not read vcpu privregs");
+ ERROR("Could not read vcpu privregs");
goto out;
}
@@ -265,11 +265,11 @@ xc_linux_restore(int xc_handle, int io_fd, uint32_t dom,
shared_info = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
PROT_READ|PROT_WRITE, shared_info_frame);
if (shared_info == NULL) {
- ERR("cannot map page");
+ ERROR("cannot map page");
goto out;
}
if (!read_exact(io_fd, shared_info, PAGE_SIZE)) {
- ERR("Error when reading shared_info page");
+ ERROR("Error when reading shared_info page");
goto out;
}
diff --git a/tools/libxc/ia64/xc_ia64_linux_save.c b/tools/libxc/ia64/xc_ia64_linux_save.c
index e280444054..42ec21c802 100644
--- a/tools/libxc/ia64/xc_ia64_linux_save.c
+++ b/tools/libxc/ia64/xc_ia64_linux_save.c
@@ -97,14 +97,14 @@ suspend_and_state(int (*suspend)(int), int xc_handle, int io_fd,
int i = 0;
if (!(*suspend)(dom)) {
- ERR("Suspend request failed");
+ ERROR("Suspend request failed");
return -1;
}
retry:
if (xc_domain_getinfo(xc_handle, dom, 1, info) != 1) {
- ERR("Could not get domain info");
+ ERROR("Could not get domain info");
return -1;
}
@@ -115,7 +115,7 @@ retry:
// try unpausing domain, wait, and retest
xc_domain_unpause(xc_handle, dom);
- ERR("Domain was paused. Wait and re-test.");
+ ERROR("Domain was paused. Wait and re-test.");
usleep(10000); // 10ms
goto retry;
@@ -123,12 +123,12 @@ retry:
if(++i < 100) {
- ERR("Retry suspend domain.");
+ ERROR("Retry suspend domain.");
usleep(10000); // 10ms
goto retry;
}
- ERR("Unable to suspend domain.");
+ ERROR("Unable to suspend domain.");
return -1;
}
@@ -191,7 +191,7 @@ xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
//initialize_mbit_rate();
if (xc_domain_getinfo(xc_handle, dom, 1, &info) != 1) {
- ERR("Could not get domain info");
+ ERROR("Could not get domain info");
return 1;
}
@@ -200,7 +200,7 @@ xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
#if 0
/* cheesy sanity check */
if ((info.max_memkb >> (PAGE_SHIFT - 10)) > max_mfn) {
- ERR("Invalid state record -- pfn count out of range: %lu",
+ ERROR("Invalid state record -- pfn count out of range: %lu",
(info.max_memkb >> (PAGE_SHIFT - 10)));
goto out;
}
@@ -210,7 +210,7 @@ xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
live_shinfo = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
PROT_READ, shared_info_frame);
if (!live_shinfo) {
- ERR("Couldn't map live_shinfo");
+ ERROR("Couldn't map live_shinfo");
goto out;
}
@@ -218,13 +218,13 @@ xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
page_array = malloc(max_pfn * sizeof(unsigned long));
if (page_array == NULL) {
- ERR("Could not allocate memory");
+ ERROR("Could not allocate memory");
goto out;
}
/* This is expected by xm restore. */
if (!write_exact(io_fd, &max_pfn, sizeof(unsigned long))) {
- ERR("write: max_pfn");
+ ERROR("write: max_pfn");
goto out;
}
@@ -237,7 +237,7 @@ xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
unsigned long version = 1;
if (!write_exact(io_fd, &version, sizeof(unsigned long))) {
- ERR("write: version");
+ ERROR("write: version");
goto out;
}
}
@@ -246,12 +246,12 @@ xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
domctl.domain = (domid_t)dom;
domctl.u.arch_setup.flags = XEN_DOMAINSETUP_query;
if (xc_domctl(xc_handle, &domctl) < 0) {
- ERR("Could not get domain setup");
+ ERROR("Could not get domain setup");
goto out;
}
if (!write_exact(io_fd, &domctl.u.arch_setup,
sizeof(domctl.u.arch_setup))) {
- ERR("write: domain setup");
+ ERROR("write: domain setup");
goto out;
}
@@ -261,7 +261,7 @@ xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
if (xc_ia64_shadow_control(xc_handle, dom,
XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY,
NULL, 0, NULL ) < 0) {
- ERR("Couldn't enable shadow mode");
+ ERROR("Couldn't enable shadow mode");
goto out;
}
@@ -272,7 +272,7 @@ xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
to_skip = malloc(bitmap_size);
if (!to_send || !to_skip) {
- ERR("Couldn't allocate bitmap array");
+ ERROR("Couldn't allocate bitmap array");
goto out;
}
@@ -280,11 +280,11 @@ xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
memset(to_send, 0xff, bitmap_size);
if (mlock(to_send, bitmap_size)) {
- ERR("Unable to mlock to_send");
+ ERROR("Unable to mlock to_send");
goto out;
}
if (mlock(to_skip, bitmap_size)) {
- ERR("Unable to mlock to_skip");
+ ERROR("Unable to mlock to_skip");
goto out;
}
@@ -296,7 +296,7 @@ xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
last_iter = 1;
if (suspend_and_state(suspend, xc_handle, io_fd, dom, &info)) {
- ERR("Domain appears not to have suspended");
+ ERROR("Domain appears not to have suspended");
goto out;
}
@@ -315,7 +315,7 @@ xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
/* Get the pfn list, as it may change. */
if (xc_ia64_get_pfn_list(xc_handle, dom, page_array,
0, max_pfn) != max_pfn) {
- ERR("Could not get the page frame list");
+ ERROR("Could not get the page frame list");
goto out;
}
@@ -326,7 +326,7 @@ xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
if (xc_ia64_shadow_control(xc_handle, dom,
XEN_DOMCTL_SHADOW_OP_PEEK,
to_skip, max_pfn, NULL) != max_pfn) {
- ERR("Error peeking shadow bitmap");
+ ERROR("Error peeking shadow bitmap");
goto out;
}
}
@@ -358,12 +358,12 @@ xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
}
if (!write_exact(io_fd, &N, sizeof(N))) {
- ERR("write: max_pfn");
+ ERROR("write: max_pfn");
goto out;
}
if (write(io_fd, mem, PAGE_SIZE) != PAGE_SIZE) {
- ERR("Error when writing to state file (5)");
+ ERROR("Error when writing to state file (5)");
goto out;
}
munmap(mem, PAGE_SIZE);
@@ -385,7 +385,7 @@ xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
last_iter = 1;
if (suspend_and_state(suspend, xc_handle, io_fd, dom, &info)) {
- ERR("Domain appears not to have suspended");
+ ERROR("Domain appears not to have suspended");
goto out;
}
}
@@ -394,7 +394,7 @@ xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
if (xc_ia64_shadow_control(xc_handle, dom,
XEN_DOMCTL_SHADOW_OP_CLEAN,
to_send, max_pfn, NULL ) != max_pfn) {
- ERR("Error flushing shadow PT");
+ ERROR("Error flushing shadow PT");
goto out;
}
@@ -411,7 +411,7 @@ xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
{
unsigned long pfn = INVALID_MFN;
if (!write_exact(io_fd, &pfn, sizeof(pfn))) {
- ERR("Error when writing to state file (6)");
+ ERROR("Error when writing to state file (6)");
goto out;
}
}
@@ -427,7 +427,7 @@ xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
}
if (!write_exact(io_fd, &j, sizeof(unsigned int))) {
- ERR("Error when writing to state file (6a)");
+ ERROR("Error when writing to state file (6a)");
goto out;
}
@@ -439,7 +439,7 @@ xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
i++;
if (j == 1024 || i == max_pfn) {
if (!write_exact(io_fd, &pfntab, sizeof(unsigned long)*j)) {
- ERR("Error when writing to state file (6b)");
+ ERROR("Error when writing to state file (6b)");
goto out;
}
j = 0;
@@ -449,12 +449,12 @@ xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
}
if (xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt)) {
- ERR("Could not get vcpu context");
+ ERROR("Could not get vcpu context");
goto out;
}
if (!write_exact(io_fd, &ctxt, sizeof(ctxt))) {
- ERR("Error when writing to state file (1)");
+ ERROR("Error when writing to state file (1)");
goto out;
}
@@ -464,17 +464,17 @@ xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
mem = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
PROT_READ|PROT_WRITE, ctxt.privregs_pfn);
if (mem == NULL) {
- ERR("cannot map privreg page");
+ ERROR("cannot map privreg page");
goto out;
}
if (write(io_fd, mem, PAGE_SIZE) != PAGE_SIZE) {
- ERR("Error when writing privreg to state file (5)");
+ ERROR("Error when writing privreg to state file (5)");
goto out;
}
munmap(mem, PAGE_SIZE);
if (!write_exact(io_fd, live_shinfo, PAGE_SIZE)) {
- ERR("Error when writing to state file (1)");
+ ERROR("Error when writing to state file (1)");
goto out;
}
diff --git a/tools/libxc/xc_hvm_build.c b/tools/libxc/xc_hvm_build.c
index dce154d7b7..31fd2577a7 100644
--- a/tools/libxc/xc_hvm_build.c
+++ b/tools/libxc/xc_hvm_build.c
@@ -17,7 +17,6 @@
#include <xen/hvm/e820.h>
#define HVM_LOADER_ENTR_ADDR 0x00100000
-
static int
parseelfimage(
char *elfbase, unsigned long elfsize, struct domain_setup_info *dsi);
@@ -82,15 +81,16 @@ static void build_e820map(void *e820_page, unsigned long long mem_size)
e820entry[nr_map].type = E820_IO;
nr_map++;
+ e820entry[nr_map].addr = 0xEA000;
+ e820entry[nr_map].size = 0x01000;
+ e820entry[nr_map].type = E820_ACPI;
+ nr_map++;
+
e820entry[nr_map].addr = 0xF0000;
e820entry[nr_map].size = 0x10000;
e820entry[nr_map].type = E820_RESERVED;
nr_map++;
-/* ACPI data: 10 pages. */
-#define ACPI_DATA_PAGES 10
-/* ACPI NVS: 3 pages. */
-#define ACPI_NVS_PAGES 3
/* buffered io page. */
#define BUFFERED_IO_PAGES 1
/* xenstore page. */
@@ -102,9 +102,7 @@ static void build_e820map(void *e820_page, unsigned long long mem_size)
/* Most of the ram goes here */
e820entry[nr_map].addr = 0x100000;
e820entry[nr_map].size = mem_size - 0x100000 - PAGE_SIZE *
- (ACPI_DATA_PAGES +
- ACPI_NVS_PAGES +
- BUFFERED_IO_PAGES +
+ (BUFFERED_IO_PAGES +
XENSTORE_PAGES +
SHARED_IO_PAGES);
e820entry[nr_map].type = E820_RAM;
@@ -112,27 +110,6 @@ static void build_e820map(void *e820_page, unsigned long long mem_size)
/* Statically allocated special pages */
- /* For ACPI data */
- e820entry[nr_map].addr = mem_size - PAGE_SIZE *
- (ACPI_DATA_PAGES +
- ACPI_NVS_PAGES +
- BUFFERED_IO_PAGES +
- XENSTORE_PAGES +
- SHARED_IO_PAGES);
- e820entry[nr_map].size = PAGE_SIZE * ACPI_DATA_PAGES;
- e820entry[nr_map].type = E820_ACPI;
- nr_map++;
-
- /* For ACPI NVS */
- e820entry[nr_map].addr = mem_size - PAGE_SIZE *
- (ACPI_NVS_PAGES +
- BUFFERED_IO_PAGES +
- XENSTORE_PAGES +
- SHARED_IO_PAGES);
- e820entry[nr_map].size = PAGE_SIZE * ACPI_NVS_PAGES;
- e820entry[nr_map].type = E820_NVS;
- nr_map++;
-
/* For buffered IO requests */
e820entry[nr_map].addr = mem_size - PAGE_SIZE *
(BUFFERED_IO_PAGES +
diff --git a/tools/libxc/xc_linux_restore.c b/tools/libxc/xc_linux_restore.c
index 6243701911..2bb7e92a6d 100644
--- a/tools/libxc/xc_linux_restore.c
+++ b/tools/libxc/xc_linux_restore.c
@@ -79,7 +79,7 @@ int uncanonicalize_pagetable(unsigned long type, void *page)
if(pfn >= max_pfn) {
/* This "page table page" is probably not one; bail. */
- ERR("Frame number in type %lu page table is out of range: "
+ 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;
@@ -158,24 +158,24 @@ int xc_linux_restore(int xc_handle, int io_fd,
if(!get_platform_info(xc_handle, dom,
&max_mfn, &hvirt_start, &pt_levels)) {
- ERR("Unable to get platform info.");
+ ERROR("Unable to get platform info.");
return 1;
}
if (mlock(&ctxt, sizeof(ctxt))) {
/* needed for build domctl, but might as well do early */
- ERR("Unable to mlock ctxt");
+ ERROR("Unable to mlock ctxt");
return 1;
}
if (!(p2m_frame_list = malloc(P2M_FL_SIZE))) {
- ERR("Couldn't allocate p2m_frame_list array");
+ ERROR("Couldn't allocate p2m_frame_list array");
goto out;
}
/* Read first entry of P2M list, or extended-info signature (~0UL). */
if (!read_exact(io_fd, p2m_frame_list, sizeof(long))) {
- ERR("read extended-info signature failed");
+ ERROR("read extended-info signature failed");
goto out;
}
@@ -184,7 +184,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
/* Next 4 bytes: total size of following extended info. */
if (!read_exact(io_fd, &tot_bytes, sizeof(tot_bytes))) {
- ERR("read extended-info size failed");
+ ERROR("read extended-info size failed");
goto out;
}
@@ -195,7 +195,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
/* 4-character chunk signature + 4-byte remaining chunk size. */
if (!read_exact(io_fd, chunk_sig, sizeof(chunk_sig)) ||
!read_exact(io_fd, &chunk_bytes, sizeof(chunk_bytes))) {
- ERR("read extended-info chunk signature failed");
+ ERROR("read extended-info chunk signature failed");
goto out;
}
tot_bytes -= 8;
@@ -203,7 +203,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
/* VCPU context structure? */
if (!strncmp(chunk_sig, "vcpu", 4)) {
if (!read_exact(io_fd, &ctxt, sizeof(ctxt))) {
- ERR("read extended-info vcpu context failed");
+ ERROR("read extended-info vcpu context failed");
goto out;
}
tot_bytes -= sizeof(struct vcpu_guest_context);
@@ -219,7 +219,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
if ( sz > P2M_FL_SIZE )
sz = P2M_FL_SIZE;
if (!read_exact(io_fd, p2m_frame_list, sz)) {
- ERR("read-and-discard extended-info chunk bytes failed");
+ ERROR("read-and-discard extended-info chunk bytes failed");
goto out;
}
chunk_bytes -= sz;
@@ -229,14 +229,14 @@ int xc_linux_restore(int xc_handle, int io_fd,
/* Now read the real first entry of P2M list. */
if (!read_exact(io_fd, p2m_frame_list, sizeof(long))) {
- ERR("read first entry of p2m_frame_list failed");
+ ERROR("read first entry of p2m_frame_list failed");
goto out;
}
}
/* First entry is already read into the p2m array. */
if (!read_exact(io_fd, &p2m_frame_list[1], P2M_FL_SIZE - sizeof(long))) {
- ERR("read p2m_frame_list failed");
+ ERROR("read p2m_frame_list failed");
goto out;
}
@@ -246,13 +246,13 @@ int xc_linux_restore(int xc_handle, int io_fd,
region_mfn = calloc(MAX_BATCH_SIZE, sizeof(xen_pfn_t));
if ((p2m == NULL) || (pfn_type == NULL) || (region_mfn == NULL)) {
- ERR("memory alloc failed");
+ ERROR("memory alloc failed");
errno = ENOMEM;
goto out;
}
if (mlock(region_mfn, sizeof(xen_pfn_t) * MAX_BATCH_SIZE)) {
- ERR("Could not mlock region_mfn");
+ ERROR("Could not mlock region_mfn");
goto out;
}
@@ -260,7 +260,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
domctl.cmd = XEN_DOMCTL_getdomaininfo;
domctl.domain = (domid_t)dom;
if (xc_domctl(xc_handle, &domctl) < 0) {
- ERR("Could not get information on new domain");
+ ERROR("Could not get information on new domain");
goto out;
}
shared_info_frame = domctl.u.getdomaininfo.shared_info_frame;
@@ -272,7 +272,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
if(xc_domain_memory_increase_reservation(
xc_handle, dom, max_pfn, 0, 0, NULL) != 0) {
- ERR("Failed to increase reservation by %lx KB", PFN_TO_KB(max_pfn));
+ ERROR("Failed to increase reservation by %lx KB", PFN_TO_KB(max_pfn));
errno = ENOMEM;
goto out;
}
@@ -281,12 +281,12 @@ int xc_linux_restore(int xc_handle, int io_fd,
/* Build the pfn-to-mfn table. We choose MFN ordering returned by Xen. */
if (xc_get_pfn_list(xc_handle, dom, p2m, max_pfn) != max_pfn) {
- ERR("Did not read correct number of frame numbers for new dom");
+ ERROR("Did not read correct number of frame numbers for new dom");
goto out;
}
if(!(mmu = xc_init_mmu_updates(xc_handle, dom))) {
- ERR("Could not initialise for MMU updates");
+ ERROR("Could not initialise for MMU updates");
goto out;
}
@@ -312,7 +312,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
}
if (!read_exact(io_fd, &j, sizeof(int))) {
- ERR("Error when reading batch size");
+ ERROR("Error when reading batch size");
goto out;
}
@@ -328,12 +328,12 @@ int xc_linux_restore(int xc_handle, int io_fd,
break; /* our work here is done */
if (j > MAX_BATCH_SIZE) {
- ERR("Max batch size exceeded. Giving up.");
+ ERROR("Max batch size exceeded. Giving up.");
goto out;
}
if (!read_exact(io_fd, region_pfn_type, j*sizeof(unsigned long))) {
- ERR("Error when reading region pfn types");
+ ERROR("Error when reading region pfn types");
goto out;
}
@@ -353,7 +353,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
xc_handle, dom, PROT_WRITE, region_mfn, j);
if ( region_base == NULL )
{
- ERR("map batch failed");
+ ERROR("map batch failed");
goto out;
}
@@ -371,7 +371,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
if ( pfn > max_pfn )
{
- ERR("pfn out of range");
+ ERROR("pfn out of range");
goto out;
}
@@ -383,7 +383,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
page = verify ? (void *)buf : (region_base + i*PAGE_SIZE);
if (!read_exact(io_fd, page, PAGE_SIZE)) {
- ERR("Error when reading page (type was %lx)", pagetype);
+ ERROR("Error when reading page (type was %lx)", pagetype);
goto out;
}
@@ -422,7 +422,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
}
else if ( pagetype != XEN_DOMCTL_PFINFO_NOTAB )
{
- ERR("Bogus page type %lx page table is out of range: "
+ ERROR("Bogus page type %lx page table is out of range: "
"i=%d max_pfn=%lu", pagetype, i, max_pfn);
goto out;
@@ -455,7 +455,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
if (xc_add_mmu_update(xc_handle, mmu,
(((unsigned long long)mfn) << PAGE_SHIFT)
| MMU_MACHPHYS_UPDATE, pfn)) {
- ERR("failed machpys update mfn=%lx pfn=%lx", mfn, pfn);
+ ERROR("failed machpys update mfn=%lx pfn=%lx", mfn, pfn);
goto out;
}
} /* end of 'batch' for loop */
@@ -469,7 +469,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
* reallocations below.
*/
if (xc_finish_mmu_updates(xc_handle, mmu)) {
- ERR("Error doing finish_mmu_updates()");
+ ERROR("Error doing finish_mmu_updates()");
goto out;
}
@@ -512,7 +512,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
munmap(l3tab, PAGE_SIZE);
if (!(new_mfn=xc_make_page_below_4G(xc_handle, dom, p2m[i]))) {
- ERR("Couldn't get a page below 4GB :-(");
+ ERROR("Couldn't get a page below 4GB :-(");
goto out;
}
@@ -521,7 +521,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
(((unsigned long long)new_mfn)
<< PAGE_SHIFT) |
MMU_MACHPHYS_UPDATE, i)) {
- ERR("Couldn't m2p on PAE root pgdir");
+ ERROR("Couldn't m2p on PAE root pgdir");
goto out;
}
@@ -554,14 +554,14 @@ int xc_linux_restore(int xc_handle, int io_fd,
if (!(region_base = xc_map_foreign_batch(
xc_handle, dom, PROT_READ | PROT_WRITE,
region_mfn, j))) {
- ERR("map batch failed");
+ ERROR("map batch failed");
goto out;
}
for(k = 0; k < j; k++) {
if(!uncanonicalize_pagetable(XEN_DOMCTL_PFINFO_L1TAB,
region_base + k*PAGE_SIZE)) {
- ERR("failed uncanonicalize pt!");
+ ERROR("failed uncanonicalize pt!");
goto out;
}
}
@@ -572,7 +572,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
}
if (xc_finish_mmu_updates(xc_handle, mmu)) {
- ERR("Error doing finish_mmu_updates()");
+ ERROR("Error doing finish_mmu_updates()");
goto out;
}
}
@@ -615,7 +615,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
/* Batch full? Then flush. */
if (nr_pins == MAX_PIN_BATCH) {
if (xc_mmuext_op(xc_handle, pin, nr_pins, dom) < 0) {
- ERR("Failed to pin batch of %d page tables", nr_pins);
+ ERROR("Failed to pin batch of %d page tables", nr_pins);
goto out;
}
nr_pins = 0;
@@ -624,7 +624,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
/* Flush final partial batch. */
if ((nr_pins != 0) && (xc_mmuext_op(xc_handle, pin, nr_pins, dom) < 0)) {
- ERR("Failed to pin batch of %d page tables", nr_pins);
+ ERROR("Failed to pin batch of %d page tables", nr_pins);
goto out;
}
@@ -638,17 +638,17 @@ int xc_linux_restore(int xc_handle, int io_fd,
int rc;
if (!read_exact(io_fd, &count, sizeof(count))) {
- ERR("Error when reading pfn count");
+ ERROR("Error when reading pfn count");
goto out;
}
if(!(pfntab = malloc(sizeof(unsigned long) * count))) {
- ERR("Out of memory");
+ ERROR("Out of memory");
goto out;
}
if (!read_exact(io_fd, pfntab, sizeof(unsigned long)*count)) {
- ERR("Error when reading pfntab");
+ ERROR("Error when reading pfntab");
goto out;
}
@@ -675,7 +675,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
if ((rc = xc_memory_op(xc_handle, XENMEM_decrease_reservation,
&reservation)) != count) {
- ERR("Could not decrease reservation : %d", rc);
+ ERROR("Could not decrease reservation : %d", rc);
goto out;
} else
DPRINTF("Decreased reservation by %d pages\n", count);
@@ -684,14 +684,14 @@ int xc_linux_restore(int xc_handle, int io_fd,
if (!read_exact(io_fd, &ctxt, sizeof(ctxt)) ||
!read_exact(io_fd, shared_info_page, PAGE_SIZE)) {
- ERR("Error when reading ctxt or shared info page");
+ ERROR("Error when reading ctxt or shared info page");
goto out;
}
/* Uncanonicalise the suspend-record frame number and poke resume rec. */
pfn = ctxt.user_regs.edx;
if ((pfn >= max_pfn) || (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB)) {
- ERR("Suspend record frame number is bad");
+ ERROR("Suspend record frame number is bad");
goto out;
}
ctxt.user_regs.edx = mfn = p2m[pfn];
@@ -709,14 +709,14 @@ int xc_linux_restore(int xc_handle, int io_fd,
/* Uncanonicalise each GDT frame number. */
if (ctxt.gdt_ents > 8192) {
- ERR("GDT entry count out of range");
+ ERROR("GDT entry count out of range");
goto out;
}
for (i = 0; i < ctxt.gdt_ents; i += 512) {
pfn = ctxt.gdt_frames[i];
if ((pfn >= max_pfn) || (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB)) {
- ERR("GDT frame number is bad");
+ ERROR("GDT frame number is bad");
goto out;
}
ctxt.gdt_frames[i] = p2m[pfn];
@@ -726,14 +726,14 @@ int xc_linux_restore(int xc_handle, int io_fd,
pfn = xen_cr3_to_pfn(ctxt.ctrlreg[3]);
if (pfn >= max_pfn) {
- ERR("PT base is bad: pfn=%lu max_pfn=%lu type=%08lx",
+ ERROR("PT base is bad: pfn=%lu max_pfn=%lu type=%08lx",
pfn, max_pfn, pfn_type[pfn]);
goto out;
}
if ( (pfn_type[pfn] & XEN_DOMCTL_PFINFO_LTABTYPE_MASK) !=
((unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT) ) {
- ERR("PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx",
+ ERROR("PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx",
pfn, max_pfn, pfn_type[pfn],
(unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT);
goto out;
@@ -757,7 +757,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
for (i = 0; i < P2M_FL_ENTRIES; i++) {
pfn = p2m_frame_list[i];
if ((pfn >= max_pfn) || (pfn_type[pfn] != XEN_DOMCTL_PFINFO_NOTAB)) {
- ERR("PFN-to-MFN frame number is bad");
+ ERROR("PFN-to-MFN frame number is bad");
goto out;
}
@@ -767,7 +767,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
/* Copy the P2M we've constructed to the 'live' P2M */
if (!(live_p2m = xc_map_foreign_batch(xc_handle, dom, PROT_WRITE,
p2m_frame_list, P2M_FL_ENTRIES))) {
- ERR("Couldn't map p2m table");
+ ERROR("Couldn't map p2m table");
goto out;
}
@@ -803,7 +803,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
(ctxt.ldt_ents > 8192) ||
(ctxt.ldt_base > hvirt_start) ||
((ctxt.ldt_base + ctxt.ldt_ents*8) > hvirt_start)) {
- ERR("Bad LDT base or size");
+ ERROR("Bad LDT base or size");
goto out;
}
@@ -816,7 +816,7 @@ int xc_linux_restore(int xc_handle, int io_fd,
rc = xc_domctl(xc_handle, &domctl);
if (rc != 0) {
- ERR("Couldn't build the domain");
+ ERROR("Couldn't build the domain");
goto out;
}
diff --git a/tools/libxc/xc_linux_save.c b/tools/libxc/xc_linux_save.c
index b5008a6cee..dfb2ee7664 100644
--- a/tools/libxc/xc_linux_save.c
+++ b/tools/libxc/xc_linux_save.c
@@ -363,19 +363,19 @@ static int suspend_and_state(int (*suspend)(int), int xc_handle, int io_fd,
int i = 0;
if (!(*suspend)(dom)) {
- ERR("Suspend request failed");
+ ERROR("Suspend request failed");
return -1;
}
retry:
if (xc_domain_getinfo(xc_handle, dom, 1, info) != 1) {
- ERR("Could not get domain info");
+ ERROR("Could not get domain info");
return -1;
}
if ( xc_vcpu_getcontext(xc_handle, dom, 0 /* XXX */, ctxt))
- ERR("Could not get vcpu context");
+ ERROR("Could not get vcpu context");
if (info->shutdown && info->shutdown_reason == SHUTDOWN_suspend)
@@ -385,7 +385,7 @@ static int suspend_and_state(int (*suspend)(int), int xc_handle, int io_fd,
// try unpausing domain, wait, and retest
xc_domain_unpause( xc_handle, dom );
- ERR("Domain was paused. Wait and re-test.");
+ ERROR("Domain was paused. Wait and re-test.");
usleep(10000); // 10ms
goto retry;
@@ -393,12 +393,12 @@ static int suspend_and_state(int (*suspend)(int), int xc_handle, int io_fd,
if( ++i < 100 ) {
- ERR("Retry suspend domain.");
+ ERROR("Retry suspend domain.");
usleep(10000); // 10ms
goto retry;
}
- ERR("Unable to suspend domain.");
+ ERROR("Unable to suspend domain.");
return -1;
}
@@ -516,25 +516,25 @@ static xen_pfn_t *xc_map_m2p(int xc_handle,
xmml.max_extents = m2p_chunks;
if (!(extent_start = malloc(m2p_chunks * sizeof(xen_pfn_t)))) {
- ERR("failed to allocate space for m2p mfns");
+ ERROR("failed to allocate space for m2p mfns");
return NULL;
}
set_xen_guest_handle(xmml.extent_start, extent_start);
if (xc_memory_op(xc_handle, XENMEM_machphys_mfn_list, &xmml) ||
(xmml.nr_extents != m2p_chunks)) {
- ERR("xc_get_m2p_mfns");
+ ERROR("xc_get_m2p_mfns");
return NULL;
}
if ((m2p = mmap(NULL, m2p_size, prot,
MAP_SHARED, xc_handle, 0)) == MAP_FAILED) {
- ERR("failed to mmap m2p");
+ ERROR("failed to mmap m2p");
return NULL;
}
if (!(entries = malloc(m2p_chunks * sizeof(privcmd_mmap_entry_t)))) {
- ERR("failed to allocate space for mmap entries");
+ ERROR("failed to allocate space for mmap entries");
return NULL;
}
@@ -546,7 +546,7 @@ static xen_pfn_t *xc_map_m2p(int xc_handle,
if ((rc = xc_map_foreign_ranges(xc_handle, DOMID_XEN,
entries, m2p_chunks)) < 0) {
- ERR("xc_mmap_foreign_ranges failed (rc = %d)", rc);
+ ERROR("xc_mmap_foreign_ranges failed (rc = %d)", rc);
return NULL;
}
@@ -619,23 +619,23 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
if(!get_platform_info(xc_handle, dom,
&max_mfn, &hvirt_start, &pt_levels)) {
- ERR("Unable to get platform info.");
+ ERROR("Unable to get platform info.");
return 1;
}
if (xc_domain_getinfo(xc_handle, dom, 1, &info) != 1) {
- ERR("Could not get domain info");
+ ERROR("Could not get domain info");
return 1;
}
if (mlock(&ctxt, sizeof(ctxt))) {
- ERR("Unable to mlock ctxt");
+ ERROR("Unable to mlock ctxt");
return 1;
}
/* Only have to worry about vcpu 0 even for SMP */
if (xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt)) {
- ERR("Could not get vcpu context");
+ ERROR("Could not get vcpu context");
goto out;
}
shared_info_frame = info.shared_info_frame;
@@ -643,13 +643,13 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
/* A cheesy test to see whether the domain contains valid state. */
if (ctxt.ctrlreg[3] == 0)
{
- ERR("Domain is not in a valid Linux guest OS state");
+ ERROR("Domain is not in a valid Linux guest OS state");
goto out;
}
/* cheesy sanity check */
if ((info.max_memkb >> (PAGE_SHIFT - 10)) > max_mfn) {
- ERR("Invalid state record -- pfn count out of range: %lu",
+ ERROR("Invalid state record -- pfn count out of range: %lu",
(info.max_memkb >> (PAGE_SHIFT - 10)));
goto out;
}
@@ -657,7 +657,7 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
/* Map the shared info frame */
if(!(live_shinfo = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
PROT_READ, shared_info_frame))) {
- ERR("Couldn't map live_shinfo");
+ ERROR("Couldn't map live_shinfo");
goto out;
}
@@ -668,7 +668,7 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
live_shinfo->arch.pfn_to_mfn_frame_list_list);
if (!live_p2m_frame_list_list) {
- ERR("Couldn't map p2m_frame_list_list (errno %d)", errno);
+ ERROR("Couldn't map p2m_frame_list_list (errno %d)", errno);
goto out;
}
@@ -678,7 +678,7 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
P2M_FLL_ENTRIES);
if (!live_p2m_frame_list) {
- ERR("Couldn't map p2m_frame_list");
+ ERROR("Couldn't map p2m_frame_list");
goto out;
}
@@ -692,20 +692,20 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
P2M_FL_ENTRIES);
if (!live_p2m) {
- ERR("Couldn't map p2m table");
+ ERROR("Couldn't map p2m table");
goto out;
}
/* Setup the mfn_to_pfn table mapping */
if(!(live_m2p = xc_map_m2p(xc_handle, max_mfn, PROT_READ))) {
- ERR("Failed to map live M2P table");
+ ERROR("Failed to map live M2P table");
goto out;
}
/* Get a local copy of the live_P2M_frame_list */
if(!(p2m_frame_list = malloc(P2M_FL_SIZE))) {
- ERR("Couldn't allocate p2m_frame_list array");
+ ERROR("Couldn't allocate p2m_frame_list array");
goto out;
}
memcpy(p2m_frame_list, live_p2m_frame_list, P2M_FL_SIZE);
@@ -713,8 +713,8 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
/* Canonicalise the pfn-to-mfn table frame-number list. */
for (i = 0; i < max_pfn; i += fpp) {
if (!translate_mfn_to_pfn(&p2m_frame_list[i/fpp])) {
- ERR("Frame# in pfn-to-mfn frame list is not in pseudophys");
- ERR("entry %d: p2m_frame_list[%ld] is 0x%"PRIx64, i, i/fpp,
+ ERROR("Frame# in pfn-to-mfn frame list is not in pseudophys");
+ ERROR("entry %d: p2m_frame_list[%ld] is 0x%"PRIx64, i, i/fpp,
(uint64_t)p2m_frame_list[i/fpp]);
goto out;
}
@@ -726,7 +726,7 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
if (xc_shadow_control(xc_handle, dom,
XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY,
NULL, 0, NULL, 0, NULL) < 0) {
- ERR("Couldn't enable shadow mode");
+ ERROR("Couldn't enable shadow mode");
goto out;
}
@@ -740,7 +740,7 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
last_iter = 1;
if (suspend_and_state(suspend, xc_handle, io_fd, dom, &info, &ctxt)) {
- ERR("Domain appears not to have suspended");
+ ERROR("Domain appears not to have suspended");
goto out;
}
@@ -761,20 +761,20 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
to_skip = malloc(BITMAP_SIZE);
if (!to_send || !to_fix || !to_skip) {
- ERR("Couldn't allocate to_send array");
+ ERROR("Couldn't allocate to_send array");
goto out;
}
memset(to_send, 0xff, BITMAP_SIZE);
if (mlock(to_send, BITMAP_SIZE)) {
- ERR("Unable to mlock to_send");
+ ERROR("Unable to mlock to_send");
return 1;
}
/* (to fix is local only) */
if (mlock(to_skip, BITMAP_SIZE)) {
- ERR("Unable to mlock to_skip");
+ ERROR("Unable to mlock to_skip");
return 1;
}
@@ -785,13 +785,13 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
pfn_batch = calloc(MAX_BATCH_SIZE, sizeof(*pfn_batch));
if ((pfn_type == NULL) || (pfn_batch == NULL)) {
- ERR("failed to alloc memory for pfn_type and/or pfn_batch arrays");
+ ERROR("failed to alloc memory for pfn_type and/or pfn_batch arrays");
errno = ENOMEM;
goto out;
}
if (mlock(pfn_type, MAX_BATCH_SIZE * sizeof(*pfn_type))) {
- ERR("Unable to mlock");
+ ERROR("Unable to mlock");
goto out;
}
@@ -817,7 +817,7 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
/* Start writing out the saved-domain record. */
if (!write_exact(io_fd, &max_pfn, sizeof(unsigned long))) {
- ERR("write: max_pfn");
+ ERROR("write: max_pfn");
goto out;
}
@@ -837,13 +837,13 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
!write_exact(io_fd, &chunk_sig, 4) ||
!write_exact(io_fd, &chunk_sz, sizeof(chunk_sz)) ||
!write_exact(io_fd, &ctxt, sizeof(ctxt))) {
- ERR("write: extended info");
+ ERROR("write: extended info");
goto out;
}
}
if (!write_exact(io_fd, p2m_frame_list, P2M_FL_SIZE)) {
- ERR("write: p2m_frame_list");
+ ERROR("write: p2m_frame_list");
goto out;
}
@@ -877,7 +877,7 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
if (!last_iter && xc_shadow_control(
xc_handle, dom, XEN_DOMCTL_SHADOW_OP_PEEK,
to_skip, max_pfn, NULL, 0, NULL) != max_pfn) {
- ERR("Error peeking shadow bitmap");
+ ERROR("Error peeking shadow bitmap");
goto out;
}
@@ -942,12 +942,12 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
if ((region_base = xc_map_foreign_batch(
xc_handle, dom, PROT_READ, pfn_type, batch)) == 0) {
- ERR("map batch failed");
+ ERROR("map batch failed");
goto out;
}
if (xc_get_pfn_type_batch(xc_handle, dom, batch, pfn_type)) {
- ERR("get_pfn_type_batch failed");
+ ERROR("get_pfn_type_batch failed");
goto out;
}
@@ -978,12 +978,12 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
}
if(!write_exact(io_fd, &batch, sizeof(unsigned int))) {
- ERR("Error when writing to state file (2)");
+ ERROR("Error when writing to state file (2)");
goto out;
}
if(!write_exact(io_fd, pfn_type, sizeof(unsigned long)*j)) {
- ERR("Error when writing to state file (3)");
+ ERROR("Error when writing to state file (3)");
goto out;
}
@@ -1013,7 +1013,7 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
goto out;
if (ratewrite(io_fd, page, PAGE_SIZE) != PAGE_SIZE) {
- ERR("Error when writing to state file (4)");
+ ERROR("Error when writing to state file (4)");
goto out;
}
@@ -1021,7 +1021,7 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
/* We have a normal page: just write it directly. */
if (ratewrite(io_fd, spage, PAGE_SIZE) != PAGE_SIZE) {
- ERR("Error when writing to state file (5)");
+ ERROR("Error when writing to state file (5)");
goto out;
}
}
@@ -1056,7 +1056,7 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
/* send "-1" to put receiver into debug mode */
if(!write_exact(io_fd, &minusone, sizeof(int))) {
- ERR("Error when writing to state file (6)");
+ ERROR("Error when writing to state file (6)");
goto out;
}
@@ -1079,7 +1079,7 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
if (suspend_and_state(suspend, xc_handle, io_fd, dom, &info,
&ctxt)) {
- ERR("Domain appears not to have suspended");
+ ERROR("Domain appears not to have suspended");
goto out;
}
@@ -1092,7 +1092,7 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
if (xc_shadow_control(xc_handle, dom,
XEN_DOMCTL_SHADOW_OP_CLEAN, to_send,
max_pfn, NULL, 0, &stats) != max_pfn) {
- ERR("Error flushing shadow PT");
+ ERROR("Error flushing shadow PT");
goto out;
}
@@ -1110,7 +1110,7 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
/* Zero terminate */
i = 0;
if (!write_exact(io_fd, &i, sizeof(int))) {
- ERR("Error when writing to state file (6)");
+ ERROR("Error when writing to state file (6)");
goto out;
}
@@ -1125,7 +1125,7 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
}
if(!write_exact(io_fd, &j, sizeof(unsigned int))) {
- ERR("Error when writing to state file (6a)");
+ ERROR("Error when writing to state file (6a)");
goto out;
}
@@ -1137,7 +1137,7 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
i++;
if (j == 1024 || i == max_pfn) {
if(!write_exact(io_fd, &pfntab, sizeof(unsigned long)*j)) {
- ERR("Error when writing to state file (6b)");
+ ERROR("Error when writing to state file (6b)");
goto out;
}
j = 0;
@@ -1148,21 +1148,21 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
/* Canonicalise the suspend-record frame number. */
if ( !translate_mfn_to_pfn(&ctxt.user_regs.edx) ){
- ERR("Suspend record is not in range of pseudophys map");
+ ERROR("Suspend record is not in range of pseudophys map");
goto out;
}
/* Canonicalise each GDT frame number. */
for ( i = 0; i < ctxt.gdt_ents; i += 512 ) {
if ( !translate_mfn_to_pfn(&ctxt.gdt_frames[i]) ) {
- ERR("GDT frame is not in range of pseudophys map");
+ ERROR("GDT frame is not in range of pseudophys map");
goto out;
}
}
/* Canonicalise the page table base pointer. */
if ( !MFN_IS_IN_PSEUDOPHYS_MAP(xen_cr3_to_pfn(ctxt.ctrlreg[3])) ) {
- ERR("PT base is not in range of pseudophys map");
+ ERROR("PT base is not in range of pseudophys map");
goto out;
}
ctxt.ctrlreg[3] =
@@ -1170,7 +1170,7 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
if (!write_exact(io_fd, &ctxt, sizeof(ctxt)) ||
!write_exact(io_fd, live_shinfo, PAGE_SIZE)) {
- ERR("Error when writing to state file (1)");
+ ERROR("Error when writing to state file (1)");
goto out;
}
diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h
index 513daed6f9..811a7eee21 100644
--- a/tools/libxc/xc_private.h
+++ b/tools/libxc/xc_private.h
@@ -30,6 +30,9 @@
#define DECLARE_SYSCTL struct xen_sysctl sysctl
#endif
+#undef PAGE_SHIFT
+#undef PAGE_SIZE
+#undef PAGE_MASK
#define PAGE_SHIFT XC_PAGE_SHIFT
#define PAGE_SIZE (1UL << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
@@ -56,11 +59,6 @@
#define PPRINTF(_f, _a...)
#endif
-#define ERR(_f, _a...) do { \
- DPRINTF(_f ": %d\n" , ## _a, errno); \
- fflush(stderr); } \
-while (0)
-
#define ERROR(_m, _a...) \
do { \
int __saved_errno = errno; \
diff --git a/tools/libxc/xc_ptrace.c b/tools/libxc/xc_ptrace.c
index d1a9f13580..2525417f16 100644
--- a/tools/libxc/xc_ptrace.c
+++ b/tools/libxc/xc_ptrace.c
@@ -1,5 +1,3 @@
-#define XC_PTRACE_PRIVATE
-
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <time.h>
diff --git a/tools/libxc/xc_ptrace.h b/tools/libxc/xc_ptrace.h
index 1c3f10b1d0..baaadb5b0b 100644
--- a/tools/libxc/xc_ptrace.h
+++ b/tools/libxc/xc_ptrace.h
@@ -1,9 +1,6 @@
#ifndef XC_PTRACE_
#define XC_PTRACE_
-#include <thread_db.h>
-
-#ifdef XC_PTRACE_PRIVATE
#define X86_CR0_PE 0x00000001 /* Enable Protected Mode (RW) */
#define X86_CR0_PG 0x80000000 /* Paging (RW) */
#define BSD_PAGE_MASK (PAGE_SIZE-1)
@@ -160,25 +157,4 @@ struct gdb_regs {
}
#endif
-#endif
-
-typedef void (*thr_ev_handler_t)(long);
-
-void xc_register_event_handler(
- thr_ev_handler_t h,
- td_event_e e);
-
-long xc_ptrace(
- int xc_handle,
- enum __ptrace_request request,
- uint32_t domid,
- long addr,
- long data);
-
-int xc_waitdomain(
- int xc_handle,
- int domain,
- int *status,
- int options);
-
#endif /* XC_PTRACE */
diff --git a/tools/libxc/xc_ptrace_core.c b/tools/libxc/xc_ptrace_core.c
index d57da3f172..03bbf318a3 100644
--- a/tools/libxc/xc_ptrace_core.c
+++ b/tools/libxc/xc_ptrace_core.c
@@ -1,5 +1,3 @@
-#define XC_PTRACE_PRIVATE
-
#include <sys/ptrace.h>
#include <sys/wait.h>
#include "xc_private.h"
diff --git a/tools/libxc/xc_solaris.c b/tools/libxc/xc_solaris.c
new file mode 100644
index 0000000000..902de64fa4
--- /dev/null
+++ b/tools/libxc/xc_solaris.c
@@ -0,0 +1,235 @@
+/******************************************************************************
+ *
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * 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, version 2 of the
+ * License.
+ */
+
+#include "xc_private.h"
+
+#include <xen/memory.h>
+#include <xen/sys/evtchn.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+int xc_interface_open(void)
+{
+ int flags, saved_errno;
+ int fd = open("/dev/xen/privcmd", O_RDWR);
+
+ if ( fd == -1 )
+ {
+ PERROR("Could not obtain handle on privileged command interface");
+ return -1;
+ }
+
+ /* Although we return the file handle as the 'xc handle' the API
+ does not specify / guarentee that this integer is in fact
+ a file handle. Thus we must take responsiblity to ensure
+ it doesn't propagate (ie leak) outside the process */
+ if ( (flags = fcntl(fd, F_GETFD)) < 0 )
+ {
+ PERROR("Could not get file handle flags");
+ goto error;
+ }
+ flags |= FD_CLOEXEC;
+ if ( fcntl(fd, F_SETFD, flags) < 0 )
+ {
+ PERROR("Could not set file handle flags");
+ goto error;
+ }
+
+ return fd;
+
+ error:
+ saved_errno = errno;
+ close(fd);
+ errno = saved_errno;
+ return -1;
+}
+
+int xc_interface_close(int xc_handle)
+{
+ return close(xc_handle);
+}
+
+void *xc_map_foreign_batch(int xc_handle, uint32_t dom, int prot,
+ xen_pfn_t *arr, int num)
+{
+ privcmd_mmapbatch_t ioctlx;
+ void *addr;
+ addr = mmap(NULL, num*PAGE_SIZE, prot, MAP_SHARED, xc_handle, 0);
+ if ( addr == MAP_FAILED )
+ return NULL;
+
+ ioctlx.num=num;
+ ioctlx.dom=dom;
+ ioctlx.addr=(unsigned long)addr;
+ ioctlx.arr=arr;
+ if ( ioctl(xc_handle, IOCTL_PRIVCMD_MMAPBATCH, &ioctlx) < 0 )
+ {
+ int saved_errno = errno;
+ perror("XXXXXXXX");
+ (void)munmap(addr, num*PAGE_SIZE);
+ errno = saved_errno;
+ return NULL;
+ }
+ return addr;
+
+}
+
+void *xc_map_foreign_range(int xc_handle, uint32_t dom,
+ int size, int prot,
+ unsigned long mfn)
+{
+ privcmd_mmap_t ioctlx;
+ privcmd_mmap_entry_t entry;
+ void *addr;
+ addr = mmap(NULL, size, prot, MAP_SHARED, xc_handle, 0);
+ if ( addr == MAP_FAILED )
+ return NULL;
+
+ ioctlx.num=1;
+ ioctlx.dom=dom;
+ ioctlx.entry=&entry;
+ entry.va=(unsigned long) addr;
+ entry.mfn=mfn;
+ entry.npages=(size+PAGE_SIZE-1)>>PAGE_SHIFT;
+ if ( ioctl(xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx) < 0 )
+ {
+ int saved_errno = errno;
+ (void)munmap(addr, size);
+ errno = saved_errno;
+ return NULL;
+ }
+ return addr;
+}
+
+int xc_map_foreign_ranges(int xc_handle, uint32_t dom,
+ privcmd_mmap_entry_t *entries, int nr)
+{
+ privcmd_mmap_t ioctlx;
+
+ ioctlx.num = nr;
+ ioctlx.dom = dom;
+ ioctlx.entry = entries;
+
+ return ioctl(xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx);
+}
+
+static int do_privcmd(int xc_handle, unsigned int cmd, unsigned long data)
+{
+ return ioctl(xc_handle, cmd, data);
+}
+
+int do_xen_hypercall(int xc_handle, privcmd_hypercall_t *hypercall)
+{
+ return do_privcmd(xc_handle,
+ IOCTL_PRIVCMD_HYPERCALL,
+ (unsigned long)hypercall);
+}
+
+int xc_evtchn_open(void)
+{
+ int fd;
+
+ if ( (fd = open("/dev/xen/evtchn", O_RDWR)) == -1 )
+ {
+ PERROR("Could not open event channel interface");
+ return -1;
+ }
+
+ return fd;
+}
+
+int xc_evtchn_close(int xce_handle)
+{
+ return close(xce_handle);
+}
+
+int xc_evtchn_fd(int xce_handle)
+{
+ return xce_handle;
+}
+
+int xc_evtchn_notify(int xce_handle, evtchn_port_t port)
+{
+ struct ioctl_evtchn_notify notify;
+
+ notify.port = port;
+
+ return ioctl(xce_handle, IOCTL_EVTCHN_NOTIFY, &notify);
+}
+
+evtchn_port_t xc_evtchn_bind_interdomain(int xce_handle, int domid,
+ evtchn_port_t remote_port)
+{
+ struct ioctl_evtchn_bind_interdomain bind;
+
+ bind.remote_domain = domid;
+ bind.remote_port = remote_port;
+
+ return ioctl(xce_handle, IOCTL_EVTCHN_BIND_INTERDOMAIN, &bind);
+}
+
+int xc_evtchn_unbind(int xce_handle, evtchn_port_t port)
+{
+ struct ioctl_evtchn_unbind unbind;
+
+ unbind.port = port;
+
+ return ioctl(xce_handle, IOCTL_EVTCHN_UNBIND, &unbind);
+}
+
+evtchn_port_t xc_evtchn_bind_virq(int xce_handle, unsigned int virq)
+{
+ struct ioctl_evtchn_bind_virq bind;
+
+ bind.virq = virq;
+
+ return ioctl(xce_handle, IOCTL_EVTCHN_BIND_VIRQ, &bind);
+}
+
+static int dorw(int fd, char *data, size_t size, int do_write)
+{
+ size_t offset = 0;
+ ssize_t len;
+
+ while ( offset < size )
+ {
+ if (do_write)
+ len = write(fd, data + offset, size - offset);
+ else
+ len = read(fd, data + offset, size - offset);
+
+ if ( len == -1 )
+ {
+ if ( errno == EINTR )
+ continue;
+ return -1;
+ }
+
+ offset += len;
+ }
+
+ return 0;
+}
+
+evtchn_port_t xc_evtchn_pending(int xce_handle)
+{
+ evtchn_port_t port;
+
+ if ( dorw(xce_handle, (char *)&port, sizeof(port), 0) == -1 )
+ return -1;
+
+ return port;
+}
+
+int xc_evtchn_unmask(int xce_handle, evtchn_port_t port)
+{
+ return dorw(xce_handle, (char *)&port, sizeof(port), 1);
+}
diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
index d74c1c8c27..8689b18cbd 100644
--- a/tools/libxc/xenctrl.h
+++ b/tools/libxc/xenctrl.h
@@ -16,7 +16,6 @@
#include <stddef.h>
#include <stdint.h>
-#include <sys/ptrace.h>
#include <xen/xen.h>
#include <xen/domctl.h>
#include <xen/sysctl.h>
@@ -116,18 +115,17 @@ typedef struct xc_core_header {
#define XC_CORE_MAGIC 0xF00FEBED
-long xc_ptrace_core(
- int xc_handle,
- enum __ptrace_request request,
- uint32_t domid,
- long addr,
- long data,
- vcpu_guest_context_t *ctxt);
+#ifdef __linux__
+
+#include <sys/ptrace.h>
+#include <thread_db.h>
+
void * map_domain_va_core(
unsigned long domfd,
int cpu,
void *guest_va,
vcpu_guest_context_t *ctxt);
+
int xc_waitdomain_core(
int xc_handle,
int domain,
@@ -135,6 +133,27 @@ int xc_waitdomain_core(
int options,
vcpu_guest_context_t *ctxt);
+typedef void (*thr_ev_handler_t)(long);
+
+void xc_register_event_handler(
+ thr_ev_handler_t h,
+ td_event_e e);
+
+long xc_ptrace(
+ int xc_handle,
+ enum __ptrace_request request,
+ uint32_t domid,
+ long addr,
+ long data);
+
+int xc_waitdomain(
+ int xc_handle,
+ int domain,
+ int *status,
+ int options);
+
+#endif /* __linux__ */
+
/*
* DOMAIN MANAGEMENT FUNCTIONS
*/
diff --git a/tools/libxc/xg_private.c b/tools/libxc/xg_private.c
index 083aafa7e6..a23d05de51 100644
--- a/tools/libxc/xg_private.c
+++ b/tools/libxc/xg_private.c
@@ -7,6 +7,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <zlib.h>
+#include <strings.h>
#include "xg_private.h"
diff --git a/tools/libxc/xg_private.h b/tools/libxc/xg_private.h
index c471e94cb6..63ad2bcfdc 100644
--- a/tools/libxc/xg_private.h
+++ b/tools/libxc/xg_private.h
@@ -79,10 +79,6 @@ unsigned long csum_page (void * page);
#define L4_PAGETABLE_ENTRIES 512
#endif
-#define PAGE_SHIFT XC_PAGE_SHIFT
-#define PAGE_SIZE (1UL << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE-1))
-
typedef uint32_t l1_pgentry_32_t;
typedef uint32_t l2_pgentry_32_t;
typedef uint64_t l1_pgentry_64_t;
diff --git a/tools/misc/Makefile b/tools/misc/Makefile
index eb6529f12d..13c95b56f7 100644
--- a/tools/misc/Makefile
+++ b/tools/misc/Makefile
@@ -1,7 +1,3 @@
-INSTALL = install
-INSTALL_PROG = $(INSTALL) -m0755
-INSTALL_DIR = $(INSTALL) -d -m0755
-
XEN_ROOT=../..
include $(XEN_ROOT)/tools/Rules.mk
@@ -24,9 +20,6 @@ all: build
.PHONY: build
build: $(TARGETS)
$(MAKE) -C miniterm
-ifeq ($(CONFIG_MBOOTPACK),y)
- $(MAKE) -C mbootpack
-endif
$(MAKE) -C lomount
.PHONY: install
@@ -38,14 +31,11 @@ install: build
$(MAKE) -C lomount install
# No sense in installing miniterm on the Xen box.
# $(MAKE) -C miniterm install
-# Likewise mbootpack
-# $(MAKE) -C mbootpack install
.PHONY: clean
clean:
$(RM) *.o $(TARGETS) *~
$(MAKE) -C miniterm clean
- $(MAKE) -C mbootpack clean
$(MAKE) -C lomount clean
%.o: %.c $(HDRS) Makefile
diff --git a/tools/misc/lomount/Makefile b/tools/misc/lomount/Makefile
index 0ed470b1d3..04c928d66f 100644
--- a/tools/misc/lomount/Makefile
+++ b/tools/misc/lomount/Makefile
@@ -1,8 +1,3 @@
-INSTALL = install
-INSTALL_PROG = $(INSTALL) -m0755
-INSTALL_DIR = $(INSTALL) -d -m0755
-INSTALL_DATA = $(INSTALL) -m0644
-
XEN_ROOT=../../..
include $(XEN_ROOT)/tools/Rules.mk
diff --git a/tools/misc/mbootpack/GPL b/tools/misc/mbootpack/GPL
deleted file mode 100644
index 5b6e7c66c2..0000000000
--- a/tools/misc/mbootpack/GPL
+++ /dev/null
@@ -1,340 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- 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
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/tools/misc/mbootpack/Makefile b/tools/misc/mbootpack/Makefile
deleted file mode 100644
index d4ac73d954..0000000000
--- a/tools/misc/mbootpack/Makefile
+++ /dev/null
@@ -1,68 +0,0 @@
-#
-# Makefile for mbootpack
-#
-INSTALL = install
-INSTALL_PROG = $(INSTALL) -m0755
-INSTALL_DIR = $(INSTALL) -d -m0755
-
-XEN_ROOT=../../..
-include $(XEN_ROOT)/tools/Rules.mk
-
-.PHONY: all
-all: build
-
-.PHONY: build
-build: mbootpack
-
-.PHONY: install
-install: build
- $(INSTALL_PROG) mbootpack $(DESTDIR)/usr/bin
-
-# Tools etc.
-RM := rm -f
-INCS := -I. -I-
-DEFS :=
-
-# What object files need building for the program
-OBJS := mbootpack.o buildimage.o
-
-# Get gcc to generate the dependencies for us.
-DEPFLAGS = -Wp,-MD,.$(@F).d
-DEPS = .*.d
-
-mbootpack: $(OBJS)
- $(HOSTCC) $(HOSTCFLAGS) -o $@ $(filter-out %.a, $^)
-
-.PHONY: clean
-clean:
- $(RM) mbootpack *.o $(DEPS) bootsect setup bzimage_header.c bin2c
-
-bootsect: bootsect.S
- $(CC) -m32 $(INCS) $(DEFS) -D__MB_ASM -c bootsect.S -o bootsect.o
- $(LD) -m elf_i386 -Ttext 0x0 -s --oformat binary bootsect.o -o $@
-
-setup: setup.S
- $(CC) -m32 $(INCS) $(DEFS) -D__MB_ASM -c setup.S -o setup.o
- $(LD) -m elf_i386 -Ttext 0x0 -s --oformat binary setup.o -o $@
-
-bin2c: bin2c.o
- $(HOSTCC) $(HOSTCFLAGS) -o $@ $^
-
-bzimage_header.c: bootsect setup bin2c
- ./bin2c -n 8 -b1 -a bzimage_bootsect bootsect > bzimage_header.c
- ./bin2c -n 8 -b1 -a bzimage_setup setup >> bzimage_header.c
-
-buildimage.c: bzimage_header.c
- @
-
-%.o: %.c
- $(HOSTCC) $(DEPFLAGS) $(HOSTCFLAGS) $(INCS) $(DEFS) -c $< -o $@
-
-.PRECIOUS: $(OBJS) $(OBJS:.o=.c) $(DEPS)
-.SUFFIXES:
-
--include $(DEPS)
-
-#
-# EOF
-#
diff --git a/tools/misc/mbootpack/README b/tools/misc/mbootpack/README
deleted file mode 100644
index 07516529b4..0000000000
--- a/tools/misc/mbootpack/README
+++ /dev/null
@@ -1,77 +0,0 @@
-
-mbootpack
----------
-
-This is a utility to take a multiboot kernel and modules and repackage
-them in a form that a standard linux bootloader will be able to load them.
-It statically allocates memory addresses based on a 'standard' PC memory
-layout, and then saves the image of the loaded system, along with an
-almost-standard linux bzImage header which takes care of the start-of-day
-requirements of a multiboot kernel (setting up 32-bit protected mode, etc.)
-
-Example invocation, to package a xen VMM and xenlinux guest and initrd:
-
- mbootpack -o bzImage -m ./xenlinux -m ./initrd.img ./xen-image
-
-You can now boot the 'bzImage' file using your favourite linux bootloader.
-
-The kernel command line will be provided at boot time by the bootloader
-(you can specify a kernel command-line using the '-c' flag, but it will
-be overridden at boot time unledd the bootloder provides an entirely
-empty command line). If you wan to override the command line for the
-first module (i.e. domain 0 kernel in Xen) at boot time, append ' -- '
-and the module commadn line to the bootloader command line, e.g.:
-
- boot: bzImage com1=9600,8n1 console=com1 dom0_mem=49152 -- root=/dev/sda3 ro console=ttyS0,9600n8
-
-Everything before the '--' is passed to the kernel (xen) as its command
-line; everything after is passed to the first module (xenlinux).
-
-This is ALPHA code: there are execution paths which have *not* been
-tested, though it works for loading the Xen hypervisor using GrUB, LILO
-or SYSLINUX. Bug reports and patches are very welcome.
-
-Possible features for future versions (all look possible, if there's any
-demand for them):
-
- - support for kernels that load below 1MB
- - zImage-style compressed images
- - sane error messgaes for insane load addresses
- - support for the MULTIBOOT_VIDEO_MODE bit
- - proper support for passing E820h memory-maps from bzImage
-
-
-Tim Deegan <tjd21@cl.cam.ac.uk>, March 2005
-
-
-
-License and attributions
-------------------------
-
-The bzImage header block was originally taken from the Linux kernel.
-http://www.kernel.org/
-
-Some parts of the Multiboot loader code are based on GNU GRUB.
-mb_info.h and mb_header.h are taken from GNU GRUB.
-http://www.gnu.org/software/grub/
-
-Bin2C was written by Nicolas Doualot; I tidied it a bit for a clean compile.
-http://slubman.celeonet.fr/program.php?style=Default&project=bin2c
-
-All other code is copyright (C) 2003-2005 Tim Deegan (tjd21@cl.cam.ac.uk)
-
-mbootpack is distributed under the GNU General Public License: see "GPL"
-
-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
diff --git a/tools/misc/mbootpack/bin2c.c b/tools/misc/mbootpack/bin2c.c
deleted file mode 100644
index 609335da7d..0000000000
--- a/tools/misc/mbootpack/bin2c.c
+++ /dev/null
@@ -1,356 +0,0 @@
-/***************************************************************************************
- Project informations:
- Project: bin2c
- Version: 1.00
- Plateforme: PC
- Copyright: DNDD.INC
- Date: 28/03/2004
-
- File informations:
- Name: bin2c.c
- Description:Convert any file to a C array
-
- Author informations:
- Author: DOUALOT Nicolas
- E-Mail: slubman@laposte.net
- site: http://membres.lycos.fr/slubman/gp32
-***************************************************************************************/
-
-
-#include <stdio.h> /*perror */
-#include <sys/mman.h> /*PROT_READ,MAP_xxx */
-#include <fcntl.h> /*O_RDONLY */
-#include <sys/stat.h> /*stat */
-#include <stdlib.h> /*atoi */
-#include <string.h> /*strcmp */
-#include <ctype.h> /*toupper */
-
-#define VERSION "1.10"
-
-
-static void help(void)
-{
- fprintf(stdout, "\nbin2c v"VERSION"\n");
- fprintf(stdout, "Slubman DevSoft (c)2003-2004 slubman.dndd@laposte.net \n\n");
-
- fprintf(stdout, "Usage: bin2c [flags] <infile>\n\n");
-
- //fprintf(stdout, "\t-quiet :\tdon't output standard messages\n");
- //fprintf(stdout, "\t-slash :\tappend backslash at end of line\n");
- fprintf(stdout, "\t-n <count> :\tnumber of items per line\n");
- fprintf(stdout, "\t-b1 :\tgenerate unsigned char array\n");
- fprintf(stdout, "\t-b2 :\tgenerate unsigned short array\n");
- fprintf(stdout, "\t-b4 :\tgenerate unsigned long array\n");
- fprintf(stdout, "\t-a <name> :\tgenerate an array with given name\n");
- fprintf(stdout, "\t-ss <nr> :\tskip number of bytes at begin of inputfile\n");
- fprintf(stdout, "\t-se <nr> :\tskip number of bytes at end of inputfile\n");
- fprintf(stdout, "\t-lb <nr> :\tinsert an additionally linebreak every nr line\n");
- fprintf(stdout, "\t-h :\tproduce an header\n");
- fprintf(stdout, "\tinfile :\tname of infile\n");
- fprintf(stdout, "\toutfile :\tname of outfile (use \"-\" for stdout)\n\n");
-
- fprintf(stdout, " \tconverts binary file to C array data\n");
-}
-
-static void UnknownFlag(char *flag)
-{
- fprintf(stderr, "Error: unknown flag %s\n", flag);
- help();
- exit(EXIT_FAILURE);
-}
-
-static void WriteHeader(FILE * outFile, char *oFileName, char *iFileName)
-{
- // File Header
- fprintf(outFile, "/***************************************************************************************\n");
- fprintf(outFile, "* File Name:\n");
- fprintf(outFile, "* Name: %s\n", oFileName);
- fprintf(outFile, "* From: %s\n", iFileName);
- fprintf(outFile, "* Created by :bin2c v"VERSION"\n*\n");
- fprintf(outFile, "* bin2c v"VERSION":\n");
- fprintf(outFile, "* Author: DOUALOT Nicolas\n");
- fprintf(outFile, "* E-Mail: slubman.dndd@laposte.net\n");
- fprintf(outFile, "* site: http://www.slubman.linux-fan.com/\n");
- fprintf(outFile, "***************************************************************************************/\n\n");
-}
-
-int main(int argc, char *argv[])
-{
- FILE *inFile = stdin, *outFile = stdout;
- int a, i, nbLine = 0;
- unsigned char *memory;
- struct stat st;
-
- // Options
- char arrayName[255] = "array"; // Array name
- char *iFileName = NULL; // File to convert
- char *oFileName = NULL; // File to write
- int bpd = 1; // Array item length
- int lb = 0; // Array blank line each lb line(s)
- int nbCol = 15; // Nuber of items per line
- int SkeepStart = 0; // Number of byte to skip at file begining
- int SkeepEnd = 0; // Number of byte to skip at file end
- int header = 0; // Produce an header
-
- // Is there the good number of arguments
- if (argc < 2)
- {
- help();
- return 0;
- }
-
- // On récupère les arguments (Ready for more options)
- for (a = 1; a < argc; a++)
- {
- // An option
- if (argv[a][0] == '-')
- {
- // Wich flag is it ?
- switch (argv[a][1])
- {
- // Writting on stdout
- case 0:
- printf("%s\n", argv[a]);
- outFile = stdout;
- break;
-
- // ArrayName flag
- case 'a':
- strcpy(arrayName, argv[++a]);
- break;
-
- // Data type
- case 'b':
- switch (argv[a][2])
- {
- case '1':
- bpd = 1;
- break;
-
- case '2':
- bpd = 2;
- break;
-
- case '4':
- bpd = 4;
- break;
-
- default:
- UnknownFlag(argv[a]);
- }
- break;
-
- // Produce an header
- case 'h':
- header = 1;
- break;
-
- // New line each n line
- case 'l':
- switch (argv[a][2])
- {
- case 'b':
- lb = atoi(argv[++a]);
- break;
-
- default:
- UnknownFlag(argv[a]);
- }
-
- // Number of bit per line
- case 'n':
- nbCol = atoi(argv[++a]);
- break;
-
- // Skip bytes
- case 's':
- switch (argv[a][2])
- {
- // Beginig of file
- case 's':
- SkeepStart = atoi(argv[++a]);
- break;
-
- // End of file
- case 'e':
- SkeepEnd = atoi(argv[++a]);
- break;
-
- // Flag inconnu
- default:
- UnknownFlag(argv[a]);
- }
-
- // Flag inconnu
- default:
- UnknownFlag(argv[a]);
- }
- }
- // A filename
- else
- {
- if (iFileName == NULL)
- {
- iFileName = argv[a];
- if ((inFile = fopen(iFileName, "rb")) == NULL)
- {
- fprintf(stderr, "Error: can't open %s\n", iFileName);
- exit(EXIT_FAILURE);
- }
- }
- else
- {
- if (oFileName == NULL)
- {
- oFileName = argv[a];
- if ((outFile = fopen(oFileName, "wb")) == NULL)
- {
- fprintf(stderr, "Error: can't open %s\n", oFileName);
- exit(EXIT_FAILURE);
- }
- }
- else
- {
- fprintf(stderr, "Error: Too many filesnames given!\n");
- help();
- exit(EXIT_FAILURE);
- }
- }
- }
- }
-
- if (!iFileName)
- exit(EXIT_FAILURE);
-
- // Get file informations
- if (stat(iFileName, &st) != 0)
- {
- fprintf(stderr, "Error: when scanning file %s\n", argv[1]);
- exit(EXIT_FAILURE);
- }
-
- // Allocating memory
- if (!(memory = malloc(st.st_size + 3)))
- {
- memset(memory, 0, st.st_size + 3);
- fprintf(stderr, "Error: not enought memory\n");
- exit(EXIT_FAILURE);
- }
-
- // Reading the file
- if (fread(memory, 1, st.st_size, inFile) != (size_t)st.st_size)
- {
- fprintf(stderr, "Error: when reading file %s\n", argv[1]);
- fclose(inFile);
- exit(EXIT_FAILURE);
- }
- fclose(inFile);
-
- // Must produce an header
- if (header)
- {
- unsigned int i;
- char hFileName[256], *def = NULL;
- FILE *hFile = stdout;
-
- if (oFileName)
- {
- strcpy(hFileName, oFileName);
- hFileName[strlen(hFileName) - 1] = 'h';
- hFile = fopen(hFileName, "wt");
- }
-
- WriteHeader(hFile, hFileName, iFileName);
-
- // Replace all '.' by '_'
- for (i = 0; i < strlen(hFileName); i++)
- if (hFileName[i] == '.')
- hFileName[i] = '_';
- else
- hFileName[i] = toupper(hFileName[i]);
-
- // the #ifdef at the begining
- def = strrchr(hFileName, '/');
- def = def ? def + 1 : hFileName;
- fprintf(hFile, "#ifndef __%s__\n#define __%s__\n\n", def, def);
-
- // Define array size
- fprintf(hFile, "#define _%s_size_ %u\n\n", arrayName, (unsigned int) (st.st_size - SkeepStart - SkeepEnd) / bpd);
-
- // Begin the array
- fprintf(hFile, "extern unsigned ");
- fprintf(hFile, "%s ", bpd == 1 ? "char" : bpd == 2 ? "short" : "long");
- fprintf(hFile, "%s[", arrayName);
- fprintf(hFile, "%u];\n\n", (unsigned int) (st.st_size - SkeepStart - SkeepEnd) / bpd);
-
- // the #endif at the end
- fprintf(hFile, "#endif\n\n");
-
- if (oFileName)
- fclose(hFile);
- }
-
- WriteHeader(outFile, oFileName, iFileName);
-
- // Define array size
- if (!header)
- fprintf(outFile, "#define _%s_size_ %u\n\n", arrayName, (unsigned int) (st.st_size - SkeepStart - SkeepEnd) / bpd);
-
- // Begin the array
- fprintf(outFile, "unsigned ");
- fprintf(outFile, "%s ", bpd == 1 ? "char" : bpd == 2 ? "short" : "long");
- fprintf(outFile, "%s[", arrayName);
- fprintf(outFile, "%u] = {\n\t", (unsigned int) (st.st_size - SkeepStart - SkeepEnd) / bpd);
-
- // Writing file elements
- for (i = 0; i < (st.st_size - SkeepEnd - SkeepStart) / bpd; /*i+=bpd */ i++)
- {
- // We write an item of bpd byte(s)
- switch (bpd)
- {
- case 1:
- fprintf(outFile, "0x%02x", *(unsigned char *) &memory[SkeepStart + i]);
- break;
-
- case 2:
- fprintf(outFile, "0x%04x", *(unsigned short *) &memory[SkeepStart + i]);
- break;
-
- case 4:
- fprintf(outFile, "0x%08lx", *(unsigned long *) &memory[SkeepStart + i]);
- break;
- }
-
- // Must put a coma ?
- if (i != st.st_size - 1)
- fprintf(outFile, ",");
-
- // End of a line ?
- if (i && !((i + 1) % nbCol))
- {
- // -lb option
- if (lb && !((++nbLine) % lb))
- fprintf(outFile, "\n");
- fprintf(outFile, "\n\t");
- }
- // Add a space
- else
- fprintf(outFile, " ");
- }
-
- // The last line as nbCol elements
- if (((st.st_size - SkeepStart - SkeepEnd) / bpd) % nbCol)
- fprintf(outFile, "\n");
-
- // Close the array
- fprintf(outFile, "};\n");
-
- // CLose the output file
- if (outFile != stdout)
- fclose(outFile);
-
- // Free allocated memory
- free(memory);
-
- exit(EXIT_SUCCESS);
-}
diff --git a/tools/misc/mbootpack/bootsect.S b/tools/misc/mbootpack/bootsect.S
deleted file mode 100644
index 2cc9ee106c..0000000000
--- a/tools/misc/mbootpack/bootsect.S
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * bootsect.S
- *
- * This is bootsect.S from the linux 2.6.9 sources,
- * with minor changes for mbootpack.
- *
- *
- * 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.
- *
- * $Id: bootsect.S,v 1.2 2005/03/23 10:39:11 tjd21 Exp $
- *
- */
-
-#include "mbootpack.h"
-
-/*
- * bootsect.S Copyright (C) 1991, 1992 Linus Torvalds
- *
- * modified by Drew Eckhardt
- * modified by Bruce Evans (bde)
- * modified by Chris Noe (May 1999) (as86 -> gas)
- * gutted by H. Peter Anvin (Jan 2003)
- *
- * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment
- * addresses must be multiplied by 16 to obtain their respective linear
- * addresses. To avoid confusion, linear addresses are written using leading
- * hex while segment addresses are written as segment:offset.
- *
- */
-
-/* #include <asm/boot.h> */
-/* Definitions we should have got from there */
-#define DEF_INITSEG 0x9000
-#define DEF_SYSSEG 0x1000
-#define DEF_SETUPSEG 0x9020
-#define DEF_SYSSIZE 0x7F00
-#define NORMAL_VGA 0xffff
-#define EXTENDED_VGA 0xfffe
-#define ASK_VGA 0xfffd
-
-
-/* SETUPSECTS = 4 */ /* default nr of setup-sectors */
-BOOTSEG = 0x07C0 /* original address of boot-sector */
-INITSEG = DEF_INITSEG /* we move boot here - out of the way */
-SETUPSEG = DEF_SETUPSEG /* setup starts here */
-SYSSEG = DEF_SYSSEG /* system loaded at 0x10000 (65536) */
-SYSSIZE = DEF_SYSSIZE /* system size: # of 16-byte clicks */
- /* to be loaded */
-ROOT_DEV = 0 /* ROOT_DEV is now written by "build" */
-SWAP_DEV = 0 /* SWAP_DEV is now written by "build" */
-
-#ifndef SVGA_MODE
-/* #define SVGA_MODE ASK_VGA */
-#define SVGA_MODE NORMAL_VGA
-#endif
-
-#ifndef RAMDISK
-#define RAMDISK 0
-#endif
-
-#ifndef ROOT_RDONLY
-#define ROOT_RDONLY 1
-#endif
-
-.code16
-.text
-
-.global _start
-_start:
-
- # Normalize the start address
- jmpl $BOOTSEG, $start2
-
-start2:
- movw %cs, %ax
- movw %ax, %ds
- movw %ax, %es
- movw %ax, %ss
- movw $0x7c00, %sp
- sti
- cld
-
- movw $bugger_off_msg, %si
-
-msg_loop:
- lodsb
- andb %al, %al
- jz die
- movb $0xe, %ah
- movw $7, %bx
- int $0x10
- jmp msg_loop
-
-die:
- # Allow the user to press a key, then reboot
- xorw %ax, %ax
- int $0x16
- int $0x19
-
- # int 0x19 should never return. In case it does anyway,
- # invoke the BIOS reset code...
- ljmp $0xf000,$0xfff0
-
-
-bugger_off_msg:
- .ascii "Direct booting from floppy is no longer supported.\r\n"
- .ascii "Please use a boot loader program instead.\r\n"
- .ascii "\n"
- .ascii "Remove disk and press any key to reboot . . .\r\n"
- .byte 0
-
-
- # Kernel attributes; used by setupbegtext
-
- .org 497
-setup_sects: .byte SETUPSECTS
-root_flags: .word ROOT_RDONLY
-syssize: .word SYSSIZE
-swap_dev: .word SWAP_DEV
-ram_size: .word RAMDISK
-vid_mode: .word SVGA_MODE
-root_dev: .word ROOT_DEV
-boot_flag: .word 0xAA55
diff --git a/tools/misc/mbootpack/buildimage.c b/tools/misc/mbootpack/buildimage.c
deleted file mode 100644
index bcf8303557..0000000000
--- a/tools/misc/mbootpack/buildimage.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * buildimage.c
- *
- * Takes the memory image of a loaded kernel and modules and repackages
- * it as a linux bzImage
- *
- * Copyright (C) 2003-2004 Tim Deegan (tjd21@cl.cam.ac.uk)
- *
- * 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.
- *
- * $Id: buildimage.c,v 1.2 2005/03/23 10:39:19 tjd21 Exp $
- *
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <getopt.h>
-#include <elf.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <asm/page.h>
-
-#include "mbootpack.h"
-#include "mb_header.h"
-
-
-/* We will build an image that a bzImage-capable bootloader will load like
- * this:
- *
- * ============== (0)
- * (BIOS memory)
- * --------------
- * (Bootloader)
- * --------------
- * bzImage startup code
- * MBI, command-lines, module info
- * ============== (0xa0000)
- * (memory hole)
- * ============== (0x100000)
- * Kernel and modules
- * ==============
- *
- * The bzImage startup code is mostly taken straight from the linux kernel
- * (see bootsect.S, startup.S). It does the usual unpleasant start-of-day
- * tasks to get to 32-bit protected mode, then sets registers appropriately
- * and jumps to the kernel's entry address.
- *
- * It also does some relocation to make sure the MBI is where we expect it,
- * and parses the linux command line.
- */
-
-#define BZ_SETUP_OFFSET (512 * (1 + SETUPSECTS))
-#define BZ_ENTRY_OFFSET 0x30
-#define BZ_MBI_OFFSET 0x34
-/* These *MUST* fit the offsets of entry_address and mbi_address in setup.S */
-
-/* Bring in the bzImage boot sector and setup code */
-#include "bzimage_header.c"
-
-#define _p(x) ((void *)(unsigned long)(x))
-
-address_t place_mbi(long int size)
-/* Find space at the top of *low* memory for the MBI and associated red tape */
-{
- address_t start;
- start = 0xa000 - size;
- if (start < 0x9000 + sizeof(bzimage_bootsect) + sizeof(bzimage_setup)) {
- printf("Fatal: command-lines too long: need %ld, have %ld bytes\n",
- size,
- 0x1000L - (sizeof(bzimage_bootsect) + sizeof(bzimage_setup)));
- exit(1);
- }
- if (!quiet) {
- printf("Placed MBI and strings (%p+%p)\n",
- _p(start), _p(size));
- }
- return start;
-}
-
-void make_bzImage(section_t *sections,
- address_t entry,
- address_t mbi,
- FILE *fp)
-/* Rework this list of sections into a bzImage and write it out to fp */
-{
- int i;
- size_t offset;
- section_t *s;
-
- /* Patch the kernel and mbi addresses into the setup code */
- *(address_t *)(bzimage_setup + BZ_ENTRY_OFFSET) = eswap(entry);
- *(address_t *)(bzimage_setup + BZ_MBI_OFFSET) = eswap(mbi);
- if (!quiet) printf("Kernel entry is %p, MBI is %p.\n",_p(entry), _p(mbi));
-
- /* Write out header and trampoline */
- if (fseek(fp, 0, SEEK_SET) < 0) {
- printf("Fatal: error seeking in output file: %s\n",
- strerror(errno));
- exit(1);
- }
- if (fwrite(bzimage_bootsect, sizeof(bzimage_bootsect), 1, fp) != 1) {
- printf("Fatal: error writing to output file: %s\n",
- strerror(errno));
- exit(1);
- }
- if (fwrite(bzimage_setup, sizeof(bzimage_setup), 1, fp) != 1) {
- printf("Fatal: error writing to output file: %s\n",
- strerror(errno));
- exit(1);
- }
-
- if (!quiet) printf("Wrote bzImage header: %ld + %ld bytes.\n",
- (long)sizeof(bzimage_bootsect),
- (long)sizeof(bzimage_setup));
-
- /* Sorted list of sections below 1MB: write them out */
- for (s = sections, i = 0; s; s = s->next) {
- if (s->start >= HIGHMEM_START) continue;
- offset = (s->start - 0x9000);
- if (fseek(fp, offset, SEEK_SET) < 0) {
- printf("Fatal: error seeking in output file: %s\n",
- strerror(errno));
- exit(1);
- }
- if (fwrite(s->buffer, s->size, 1, fp) != 1) {
- printf("Fatal: error writing to output file: %s\n",
- strerror(errno));
- exit(1);
- }
- i++;
- }
-
- if (!quiet) printf("Wrote %i low-memory sections.\n", i);
-
- /* Sorted list of sections higher than 1MB: write them out */
- for (s = sections, i = 0; s; s = s->next) {
- if (s->start < HIGHMEM_START) continue;
- offset = (s->start - HIGHMEM_START) + BZ_SETUP_OFFSET;
- if (fseek(fp, offset, SEEK_SET) < 0) {
- printf("Fatal: error seeking in output file: %s\n",
- strerror(errno));
- exit(1);
- }
- if (fwrite(s->buffer, s->size, 1, fp) != 1) {
- printf("Fatal: error writing to output file: %s\n",
- strerror(errno));
- exit(1);
- }
- i++;
- }
-
- if (!quiet) printf("Wrote %i high-memory sections.\n", i);
-}
-
-
-/*
- * EOF(buildimage.c)
- */
diff --git a/tools/misc/mbootpack/mb_header.h b/tools/misc/mbootpack/mb_header.h
deleted file mode 100644
index 21934574f3..0000000000
--- a/tools/misc/mbootpack/mb_header.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2000 Free Software Foundation, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*
- * MultiBoot Header description
- */
-
-struct multiboot_header
-{
- /* Must be MULTIBOOT_MAGIC - see below. */
- unsigned magic;
-
- /* Feature flags - see below. */
- unsigned flags;
-
- /*
- * Checksum
- *
- * The above fields plus this one must equal 0 mod 2^32.
- */
- unsigned checksum;
-
- /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */
- unsigned header_addr;
- unsigned load_addr;
- unsigned load_end_addr;
- unsigned bss_end_addr;
- unsigned entry_addr;
-
- /* These are only valid if MULTIBOOT_VIDEO_MODE is set. */
- unsigned mode_type;
- unsigned width;
- unsigned height;
- unsigned depth;
-};
-
-/*
- * The entire multiboot_header must be contained
- * within the first MULTIBOOT_SEARCH bytes of the kernel image.
- */
-#define MULTIBOOT_SEARCH 8192
-#define MULTIBOOT_FOUND(addr, len) \
- (! ((addr) & 0x3) \
- && (len) >= 12 \
- && *((int *) (addr)) == MULTIBOOT_MAGIC \
- && ! (*((unsigned *) (addr)) + *((unsigned *) (addr + 4)) \
- + *((unsigned *) (addr + 8))) \
- && (! (MULTIBOOT_AOUT_KLUDGE & *((int *) (addr + 4))) || (len) >= 32) \
- && (! (MULTIBOOT_VIDEO_MODE & *((int *) (addr + 4))) || (len) >= 48))
-
-/* Magic value identifying the multiboot_header. */
-#define MULTIBOOT_MAGIC 0x1BADB002
-
-/*
- * Features flags for 'flags'.
- * If a boot loader sees a flag in MULTIBOOT_MUSTKNOW set
- * and it doesn't understand it, it must fail.
- */
-#define MULTIBOOT_MUSTKNOW 0x0000FFFF
-
-/* currently unsupported flags... this is a kind of version number. */
-#define MULTIBOOT_UNSUPPORTED 0x0000FFF8
-
-/* Align all boot modules on i386 page (4KB) boundaries. */
-#define MULTIBOOT_PAGE_ALIGN 0x00000001
-
-/* Must pass memory information to OS. */
-#define MULTIBOOT_MEMORY_INFO 0x00000002
-
-/* Must pass video information to OS. */
-#define MULTIBOOT_VIDEO_MODE 0x00000004
-
-/* This flag indicates the use of the address fields in the header. */
-#define MULTIBOOT_AOUT_KLUDGE 0x00010000
diff --git a/tools/misc/mbootpack/mb_info.h b/tools/misc/mbootpack/mb_info.h
deleted file mode 100644
index fb37f10ff0..0000000000
--- a/tools/misc/mbootpack/mb_info.h
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2000 Free Software Foundation, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*
- * The structure type "mod_list" is used by the "multiboot_info" structure.
- */
-
-struct mod_list
-{
- /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */
- unsigned long mod_start;
- unsigned long mod_end;
-
- /* Module command line */
- unsigned long cmdline;
-
- /* padding to take it to 16 bytes (must be zero) */
- unsigned long pad;
-};
-
-
-/*
- * INT-15, AX=E820 style "AddressRangeDescriptor"
- * ...with a "size" parameter on the front which is the structure size - 4,
- * pointing to the next one, up until the full buffer length of the memory
- * map has been reached.
- */
-
-struct AddrRangeDesc
-{
- unsigned long size;
- unsigned long long BaseAddr;
- unsigned long long Length;
- unsigned long Type;
-
- /* unspecified optional padding... */
-};
-
-/* usable memory "Type", all others are reserved. */
-#define MB_ARD_MEMORY 1
-
-
-/* Drive Info structure. */
-struct drive_info
-{
- /* The size of this structure. */
- unsigned long size;
-
- /* The BIOS drive number. */
- unsigned char drive_number;
-
- /* The access mode (see below). */
- unsigned char drive_mode;
-
- /* The BIOS geometry. */
- unsigned short drive_cylinders;
- unsigned char drive_heads;
- unsigned char drive_sectors;
-
- /* The array of I/O ports used for the drive. */
- unsigned short drive_ports[0];
-};
-
-/* Drive Mode. */
-#define MB_DI_CHS_MODE 0
-#define MB_DI_LBA_MODE 1
-
-
-/* APM BIOS info. */
-struct apm_info
-{
- unsigned short version;
- unsigned short cseg;
- unsigned long offset;
- unsigned short cseg_16;
- unsigned short dseg_16;
- unsigned short cseg_len;
- unsigned short cseg_16_len;
- unsigned short dseg_16_len;
-};
-
-
-/*
- * MultiBoot Info description
- *
- * This is the struct passed to the boot image. This is done by placing
- * its address in the EAX register.
- */
-
-struct multiboot_info
-{
- /* MultiBoot info version number */
- unsigned long flags;
-
- /* Available memory from BIOS */
- unsigned long mem_lower;
- unsigned long mem_upper;
-
- /* "root" partition */
- unsigned long boot_device;
-
- /* Kernel command line */
- unsigned long cmdline;
-
- /* Boot-Module list */
- unsigned long mods_count;
- unsigned long mods_addr;
-
- union
- {
- struct
- {
- /* (a.out) Kernel symbol table info */
- unsigned long tabsize;
- unsigned long strsize;
- unsigned long addr;
- unsigned long pad;
- }
- a;
-
- struct
- {
- /* (ELF) Kernel section header table */
- unsigned long num;
- unsigned long size;
- unsigned long addr;
- unsigned long shndx;
- }
- e;
- }
- syms;
-
- /* Memory Mapping buffer */
- unsigned long mmap_length;
- unsigned long mmap_addr;
-
- /* Drive Info buffer */
- unsigned long drives_length;
- unsigned long drives_addr;
-
- /* ROM configuration table */
- unsigned long config_table;
-
- /* Boot Loader Name */
- unsigned long boot_loader_name;
-
- /* APM table */
- unsigned long apm_table;
-
- /* Video */
- unsigned long vbe_control_info;
- unsigned long vbe_mode_info;
- unsigned short vbe_mode;
- unsigned short vbe_interface_seg;
- unsigned short vbe_interface_off;
- unsigned short vbe_interface_len;
-};
-
-/*
- * Flags to be set in the 'flags' parameter above
- */
-
-/* is there basic lower/upper memory information? */
-#define MB_INFO_MEMORY 0x00000001
-/* is there a boot device set? */
-#define MB_INFO_BOOTDEV 0x00000002
-/* is the command-line defined? */
-#define MB_INFO_CMDLINE 0x00000004
-/* are there modules to do something with? */
-#define MB_INFO_MODS 0x00000008
-
-/* These next two are mutually exclusive */
-
-/* is there a symbol table loaded? */
-#define MB_INFO_AOUT_SYMS 0x00000010
-/* is there an ELF section header table? */
-#define MB_INFO_ELF_SHDR 0x00000020
-
-/* is there a full memory map? */
-#define MB_INFO_MEM_MAP 0x00000040
-
-/* Is there drive info? */
-#define MB_INFO_DRIVE_INFO 0x00000080
-
-/* Is there a config table? */
-#define MB_INFO_CONFIG_TABLE 0x00000100
-
-/* Is there a boot loader name? */
-#define MB_INFO_BOOT_LOADER_NAME 0x00000200
-
-/* Is there a APM table? */
-#define MB_INFO_APM_TABLE 0x00000400
-
-/* Is there video information? */
-#define MB_INFO_VIDEO_INFO 0x00000800
-
-/*
- * The following value must be present in the EAX register.
- */
-
-#define MULTIBOOT_VALID 0x2BADB002
diff --git a/tools/misc/mbootpack/mbootpack.c b/tools/misc/mbootpack/mbootpack.c
deleted file mode 100644
index c80fdeb975..0000000000
--- a/tools/misc/mbootpack/mbootpack.c
+++ /dev/null
@@ -1,704 +0,0 @@
-/*
- * mbootpack.c
- *
- * Takes a multiboot image, command-line and modules, and repackages
- * them as if they were a linux kernel. Only supports a subset of
- * the multiboot info page options (enough to boot the Xen hypervisor).
- *
- * Copyright (C) 2003-2004 Tim Deegan (tjd21@cl.cam.ac.uk)
- *
- * Parts based on GNU GRUB, Copyright (C) 2000 Free Software Foundation, Inc
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- *
- * $Id: mbootpack.c,v 1.3 2005/03/23 10:38:36 tjd21 Exp tjd21 $
- *
- */
-
-#define _GNU_SOURCE
-#include "mbootpack.h"
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <getopt.h>
-#include <elf.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <asm/page.h>
-
-/* From GNU GRUB */
-#include "mb_header.h"
-#include "mb_info.h"
-
-
-/*
- * The plan: Marshal up the multiboot modules and strings as if we
- * were loading them into memory on a fresh ix86 PC. Attach
- * a linux bzImage header to the front, which sets up the machine
- * appropriately and then jumps to the kernel entry address.
- *
- * The memory map will be made up roughly like so:
- *
- * =============
- * multiboot information (mbi) struct
- * -------
- * kernel command line
- * -------
- * bootloader name
- * -------
- * module command lines
- * -------
- * module information structs
- * =============
- * (memory hole)
- * =============
- * kernel
- * -------------
- * module 1
- * -------------
- * module 2
- * -------------
- * .
- * .
- * .
- *
- * ==============
- *
- *
- * For allocation of memory we assume that the target machine has 'low'
- * memory from 0 to 640K and 'high' memory starting at 1M. We allocate
- * the kernel first, wherever it wants to be. After that, sections
- * are added at the next available aligned address, always in the order
- * given above, and skipping the memory hole at 640K. Allocated sections
- * are stored in a linked list of buffers.
- *
- * Re-packaging as a bzImage file happens in buildimage.c
- *
- */
-
-/* Version */
-static const char version_string[] = "mbootpack " MBOOTPACK_VERSION_STRING;
-
-/* Flags */
-int quiet = 0;
-
-/* How much of the start of a kernel we read looking for headers.
- * Must be >= MULTIBOOT_SEARCH */
-#define HEADERBUF_SIZE MULTIBOOT_SEARCH
-
-
-/* Linked list of loaded sections, and a pointer to the next
- * available space (i.e. just above the highest allocation so far). */
-static section_t *sections = NULL;
-static section_t *last_section = NULL;
-static address_t next_free_space = 0;
-
-static void usage(void)
-/* If we don't understand the command-line options */
-{
- printf(
-"Usage: mbpack [OPTIONS] kernel-image\n\n"
-" -h --help Print this text.\n"
-" -q --quiet Only output errors and warnings.\n"
-" -o --output=filename Output to filename (default \"bzImage\").\n"
-" -M --multiboot-output Produce a multiboot kernel, not a bzImage\n"
-" (sets default output file to \"mbImage\").\n"
-" -c --command-line=STRING Set the kernel command line (DEPRECATED!).\n"
-" -m --module=\"MOD arg1 arg2...\" Load module MOD with arguments \"arg1...\"\n"
-" (can be used multiple times).\n"
-"\n");
- exit(1);
-}
-
-#define _p(x) ((void *)(unsigned long)(x))
-
-static void place_kernel_section(address_t start, long int size)
-/* Place the kernel in memory, checking for the memory hole. */
-{
- if (start >= MEM_HOLE_END) {
- /* Above the memory hole: easy */
- next_free_space = MAX(next_free_space, start + size);
- if (!quiet) {
- printf("Placed kernel section (%p+%p)\n",
- _p(start), _p(size));
- }
- return;
- }
-
- if (start >= MEM_HOLE_START) {
- /* In the memory hole. Not so good */
- printf("Fatal: kernel load address (%p) is in the memory hole.\n",
- _p(start));
- exit(1);
- }
-
- if (start + size > MEM_HOLE_START) {
- /* Too big for low memory */
- printf("Fatal: kernel (%p+%p) runs into the memory hole.\n",
- _p(start), _p(size));
- exit(1);
- }
-
- /* Kernel loads below the memory hole */
- next_free_space = MAX(next_free_space, start + size);
-
- if (!quiet) {
- printf("Placed kernel section (%p+%p)\n", _p(start), _p(size));
- }
-}
-
-
-static address_t place_section(long int size, int align)
-/* Find the next available place for this section.
- * "align" must be a power of 2 */
-{
- address_t start;
- assert(next_free_space != 0);
- assert(((~align + 1) & align) == align);
-
- start = ROUNDUP_P2(next_free_space, align);
-
- /* Check that we don't hit the memory hole */
- if (start < MEM_HOLE_END && (start + size) > MEM_HOLE_START)
- start = ROUNDUP_P2(MEM_HOLE_END, align);
-
- next_free_space = start + size;
-
- if (!quiet) {
- printf("Placed section (%p+%p), align=%p\n",
- _p(start), _p(size), _p(align));
- }
- return start;
-}
-
-
-static address_t load_kernel(const char *filename)
-/* Load an elf32/multiboot kernel from this file
- * Returns the entry address for the kernel. */
-{
- unsigned int i;
- address_t start;
- size_t len;
- long int size, loadsize;
- FILE *fp;
- char *buffer;
- section_t *sec, *s;
- Elf32_Ehdr *ehdr;
- Elf32_Phdr *phdr;
- struct multiboot_header *mbh;
- struct stat sb;
-
- static char headerbuf[HEADERBUF_SIZE];
-
- /* Stat and open the file */
- if (stat(filename, &sb) != 0) {
- printf("Fatal: cannot stat %s: %s\n", filename, strerror(errno));
- exit(1);
- }
- if ((fp = fopen(filename, "r")) == NULL) {
- printf("Fatal: cannot open %s: %s\n", filename, strerror(errno));
- exit(1);
- }
-
- /* Load the first 8k of the file */
- if (fseek(fp, 0, SEEK_SET) < 0) {
- printf("Fatal: seek error in %s: %s\n", filename, strerror(errno));
- exit(1);
- }
- if ((len = fread(headerbuf, 1, HEADERBUF_SIZE, fp))
- < HEADERBUF_SIZE)
- {
- if (feof(fp)) /* Short file */
- {
- if (len < 12) {
- printf("Fatal: %s is too short to be a multiboot file.",
- filename);
- exit(1);
- }
- } else {
- printf("Fatal: read error in %s: %s\n", filename, strerror(errno));
- exit(1);
- }
- }
-
- /* Sanity-check: is this file compressed? */
- if ((headerbuf[0] == '\037' &&
- (headerbuf[1] == '\235' /* .Z */ ||
- headerbuf[1] == '\213' /* .gz */)) ||
- (headerbuf[0] == 'B' && headerbuf[1] == 'Z') /* .bz[2] */) {
- printf("Warning: %s looks like a compressed file.\n"
- " You should uncompress it first!\n", filename);
- }
-
- /* Now look for a multiboot header */
- for (i = 0; i <= MIN(len - 12, MULTIBOOT_SEARCH - 12); i += 4)
- {
- mbh = (struct multiboot_header *)(headerbuf + i);
- if (eswap(mbh->magic) != MULTIBOOT_MAGIC
- || ((eswap(mbh->magic)+eswap(mbh->flags)+eswap(mbh->checksum))
- & 0xffffffff))
- {
- /* Not a multiboot header */
- continue;
- }
- if (eswap(mbh->flags) & MULTIBOOT_UNSUPPORTED) {
- /* Requires options we don't support */
- printf("Fatal: found a multiboot header, but it "
- "requires multiboot options that I\n"
- "don't understand. Sorry.\n");
- exit(1);
- }
- if (eswap(mbh->flags) & MULTIBOOT_VIDEO_MODE) {
- /* Asked for screen mode information */
- /* XXX carry on regardless */
- printf("Warning: found a multiboot header which asks "
- "for screen mode information.\n"
- " This kernel will NOT be given valid"
- "screen mode information at boot time.\n");
- }
- /* This kernel will do: place and load it */
-
- if (eswap(mbh->flags) & MULTIBOOT_AOUT_KLUDGE) {
-
- /* Load using the offsets in the multiboot header */
- if(!quiet)
- printf("Loading %s using multiboot header.\n", filename);
-
- /* How much is there? */
- start = eswap(mbh->load_addr);
- if (eswap(mbh->load_end_addr) != 0)
- loadsize = eswap(mbh->load_end_addr) - eswap(mbh->load_addr);
- else
- loadsize = sb.st_size;
-
- /* How much memory will it take up? */
- if (eswap(mbh->bss_end_addr) != 0)
- size = eswap(mbh->bss_end_addr) - eswap(mbh->load_addr);
- else
- size = loadsize;
-
- if (loadsize > size) {
- printf("Fatal: can't load %ld bytes of kernel into %ld bytes "
- "of memory.\n", loadsize, size);
- exit(1);
- }
-
- /* Does it fit where it wants to be? */
- place_kernel_section(start, size);
-
- /* Load the kernel */
- if ((buffer = malloc(size)) == NULL) {
- printf("Fatal: malloc() for kernel load failed: %s\n",
- strerror(errno));
- exit(1);
- }
- if ((fread(buffer, loadsize, 1, fp)) != 1) {
- printf("Fatal: cannot read %s: %s\n",
- filename, strerror(errno));
- exit(1);
- }
- fclose(fp);
-
- /* Clear the kernel BSS */
- memset(buffer + loadsize, 0, size - loadsize);
-
- /* Start off the linked list of sections */
- if ((sec = (section_t *)malloc(sizeof (section_t))) == NULL) {
- printf("Fatal: malloc() for section_t failed: %s\n",
- strerror(errno));
- exit(1);
- }
- sec->buffer = buffer;
- sec->start = start;
- sec->size = size;
- sec->next = NULL;
- sec->prev = NULL;
- sections = sec;
- last_section = sec;
-
- /* Done. */
- if (!quiet) printf("Loaded kernel from %s\n", filename);
- return eswap(mbh->entry_addr);
-
- } else {
-
- /* Now look for an ELF32 header */
- ehdr = (Elf32_Ehdr *)headerbuf;
- if (*(unsigned long *)ehdr != eswap(0x464c457f)
- || ehdr->e_ident[EI_DATA] != ELFDATA2LSB
- || ehdr->e_ident[EI_CLASS] != ELFCLASS32
- || eswap(ehdr->e_machine) != EM_386)
- {
- printf("Fatal: kernel has neither ELF32/x86 nor multiboot load"
- " headers.\n");
- exit(1);
- }
- if (eswap(ehdr->e_phoff) + eswap(ehdr->e_phnum)*sizeof(*phdr)
- > HEADERBUF_SIZE) {
- /* Don't expect this will happen with sane kernels */
- printf("Fatal: too much ELF for me. Try increasing "
- "HEADERBUF_SIZE in mbootpack.\n");
- exit(1);
- }
- if (eswap(ehdr->e_phoff) + eswap(ehdr->e_phnum)*sizeof (*phdr)
- > len) {
- printf("Fatal: malformed ELF header overruns EOF.\n");
- exit(1);
- }
- if (eswap(ehdr->e_phnum) <= 0) {
- printf("Fatal: ELF kernel has no program headers.\n");
- exit(1);
- }
-
- if(!quiet)
- printf("Loading %s using ELF header.\n", filename);
-
- if (eswap(ehdr->e_type) != ET_EXEC
- || eswap(ehdr->e_version) != EV_CURRENT
- || eswap(ehdr->e_phentsize) != sizeof (Elf32_Phdr)) {
- printf("Warning: funny-looking ELF header.\n");
- }
- phdr = (Elf32_Phdr *)(headerbuf + eswap(ehdr->e_phoff));
-
- /* Obey the program headers to load the kernel */
- for(i = 0; i < eswap(ehdr->e_phnum); i++) {
-
- start = eswap(phdr[i].p_paddr);
- size = eswap(phdr[i].p_memsz);
- if (eswap(phdr[i].p_type) != PT_LOAD)
- loadsize = 0;
- else
- loadsize = MIN((long int)eswap(phdr[i].p_filesz), size);
-
- if ((buffer = malloc(size)) == NULL) {
- printf("Fatal: malloc() for kernel load failed: %s\n",
- strerror(errno));
- exit(1);
- }
-
- /* Place the section where it wants to be */
- place_kernel_section(start, size);
-
- /* Load section from file */
- if (loadsize > 0) {
- if (fseek(fp, eswap(phdr[i].p_offset), SEEK_SET) != 0) {
- printf("Fatal: seek failed in %s\n",
- strerror(errno));
- exit(1);
- }
- if ((fread(buffer, loadsize, 1, fp)) != 1) {
- printf("Fatal: cannot read %s: %s\n",
- filename, strerror(errno));
- exit(1);
- }
- }
-
- /* Clear the rest of the buffer */
- memset(buffer + loadsize, 0, size - loadsize);
-
- /* Add this section to the list (keeping it ordered) */
- if ((sec = (section_t *)malloc(sizeof (section_t))) == NULL) {
- printf("Fatal: malloc() for section_t failed: %s\n",
- strerror(errno));
- exit(1);
- }
- sec->buffer = buffer;
- sec->start = start;
- sec->size = size;
-
- for(s = sections; s; s = s->next) {
- if (s->start > start) {
- sec->next = s;
- if (s->prev == NULL) {
- /* sec becomes the new first item */
- s->prev = sec;
- sections = sec;
- } else {
- /* sec goes between s->prev and s */
- sec->prev = s->prev;
- sec->prev->next = sec;
- s->prev = sec;
- }
- break;
- }
- }
- if (s == NULL) {
- /* sec becomes the new last item */
- sec->next = NULL;
- sec->prev = last_section;
- if (last_section) {
- last_section->next = sec;
- } else {
- sections = sec;
- }
- last_section = sec;
- }
- }
-
- /* Done! */
- if (!quiet) printf("Loaded kernel from %s\n", filename);
- return eswap(ehdr->e_entry);
- }
-
- }
-
- /* This is not a multiboot kernel */
- printf("Fatal: %s is not a multiboot kernel.\n", filename);
- exit(1);
-}
-
-
-int main(int argc, char **argv)
-{
- char *buffer, *imagename, *command_line, *p;
- char *mod_filename, *mod_command_line, *mod_clp;
- char *out_filename;
- section_t *sec;
- FILE *fp;
- struct stat sb;
- struct multiboot_info *mbi;
- struct mod_list *modp;
- address_t start, kernel_entry;
- long int size, mod_command_line_space, command_line_len;
- int modules, opt, mbi_reloc_offset;
-
- static const char short_options[] = "hc:m:o:qM";
- static const struct option options[] = {
- { "help", 0, 0, 'h' },
- { "command-line", 1, 0, 'c' },
- { "append", 1, 0, 'c' },
- { "module", 1, 0, 'm' },
- { "output", 1, 0, 'o' },
- { "quiet", 0, 0, 'q' },
- { 0, 0, 0, 0 },
- };
-
- /* Parse the command line */
- out_filename = NULL;
- command_line = "";
- command_line_len = 0;
- modules = 0;
- mod_command_line_space = 0;
- while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1)
- {
- switch(opt) {
- case 'c':
- command_line = optarg;
- break;
- case 'm':
- modules++;
- mod_command_line_space += strlen(optarg) + 1;
- break;
- case 'o':
- out_filename = optarg;
- break;
- case 'q':
- quiet = 1;
- break;
- case 'h':
- case '?':
- default:
- usage();
- }
- }
- imagename = argv[optind];
- if (!imagename || strlen(imagename) == 0) usage();
- command_line_len = strlen(command_line) + strlen(imagename) + 2;
- /* Leave space to overwritethe command-line at boot time */
- command_line_len = MAX(command_line_len, CMD_LINE_SPACE);
- if (!out_filename) out_filename = "bzImage";
-
- /* Place and load the kernel */
- kernel_entry = load_kernel(imagename);
- assert(sections != NULL);
- assert(last_section != NULL);
- assert(next_free_space != 0);
-
- /* Next section is all the metadata between kernel and modules */
- size = ((((sizeof (struct multiboot_info)
- + command_line_len
- + strlen(version_string) + 1
- + mod_command_line_space)
- + 3 ) & ~3)
- + modules * sizeof (struct mod_list));
- /* Locate this section after the setup sectors, in *low* memory */
- start = place_mbi(size);
-
- if ((buffer = malloc(size)) == NULL) {
- printf("Fatal: malloc() for boot metadata failed: %s\n",
- strerror(errno));
- exit(1);
- }
-
- if ((sec = (section_t *)malloc(sizeof (section_t))) == NULL) {
- printf("Fatal: malloc() for section_t failed: %s\n",
- strerror(errno));
- exit(1);
- }
- sec->buffer = buffer;
- sec->start = start;
- sec->size = size;
- sec->next = NULL;
- sec->prev = last_section;
- last_section->next = sec;
- last_section = sec;
-
- /* Multiboot info struct */
- mbi = (struct multiboot_info *)buffer;
- memset(buffer, 0, sizeof (struct multiboot_info));
- mbi_reloc_offset = start - (address_t)buffer;
-
- /* Command line */
- p = (char *)(mbi + 1);
- sprintf(p, "%s %s", imagename, command_line);
- mbi->cmdline = eswap(((address_t)p) + mbi_reloc_offset);
- p += command_line_len;
-
- /* Bootloader ID */
- sprintf(p, version_string);
- mbi->boot_loader_name = eswap(((address_t)p) + mbi_reloc_offset);
- p += strlen(version_string) + 1;
-
- /* Next is space for the module command lines */
- mod_clp = p;
-
- /* Last come the module info structs */
- modp = (struct mod_list *)
- ((((address_t)p + mod_command_line_space) + 3) & ~3);
- mbi->mods_count = eswap(modules);
- mbi->mods_addr = eswap(((address_t)modp) + mbi_reloc_offset);
-
- /* Memory information will be added at boot time, by setup.S
- * or trampoline.S. */
- mbi->flags = eswap(MB_INFO_CMDLINE | MB_INFO_BOOT_LOADER_NAME);
-
-
- /* Load the modules */
- if (modules) {
- mbi->flags = eswap(eswap(mbi->flags) | MB_INFO_MODS);
-
- /* Go back and parse the module command lines */
- optind = opterr = 1;
- while((opt = getopt_long(argc, argv,
- short_options, options, 0)) != -1)
- {
- if (opt != 'm') continue;
-
- /* Split module filename from command line */
- mod_command_line = mod_filename = optarg;
- if ((p = strchr(mod_filename, ' ')) != NULL) {
- /* See as I discard the 'const' modifier */
- *p = '\0';
- }
-
- /* Find space for it */
- if (stat(mod_filename, &sb) != 0) {
- printf("Fatal: cannot stat %s: %s\n",
- mod_filename, strerror(errno));
- exit(1);
- }
- size = sb.st_size;
- start = place_section(size, X86_PAGE_SIZE);
- /* XXX should be place_section(size, 4) if the MBH hasn't got
- * XXX MULTIBOOT_PAGE_ALIGN set, but that breaks Xen */
-
- /* Load it */
- if ((buffer = malloc(sb.st_size)) == NULL) {
- printf("Fatal: malloc failed for module load: %s\n",
- strerror(errno));
- exit(1);
- }
- if ((fp = fopen(mod_filename, "r")) == NULL) {
- printf("Fatal: cannot open %s: %s\n",
- mod_filename, strerror(errno));
- exit(1);
- }
- if ((fread(buffer, sb.st_size, 1, fp)) != 1) {
- printf("Fatal: cannot read %s: %s\n",
- mod_filename, strerror(errno));
- exit(1);
- }
- fclose(fp);
-
- /* Sanity-check: is this file compressed? */
- if ((buffer[0] == '\037' &&
- (buffer[1] == '\235' /* .Z */ ||
- buffer[1] == '\213' /* .gz */)) ||
- (buffer[0] == 'B' && buffer[1] == 'Z') /* .bz[2] */) {
- printf("Warning: %s looks like a compressed file.\n",
- mod_filename);
- }
-
- if (!quiet) printf("Loaded module from %s\n", mod_filename);
-
- /* Restore the command line to its former glory */
- if (p != NULL) *p = ' ';
-
- /* Fill in the module info struct */
- modp->mod_start = eswap(start);
- modp->mod_end = eswap(start + size);
- modp->cmdline = eswap((address_t)mod_clp + mbi_reloc_offset);
- modp->pad = eswap(0);
- modp++;
-
- /* Store the module command line */
- sprintf(mod_clp, "%s", mod_command_line);
- mod_clp += strlen(mod_clp) + 1;
-
- /* Add the section to the list */
- if ((sec = (section_t *)malloc(sizeof (section_t))) == NULL) {
- printf("Fatal: malloc() for section_t failed: %s\n",
- strerror(errno));
- exit(1);
- }
- sec->buffer = buffer;
- sec->start = start;
- sec->size = size;
- sec->next = NULL;
- sec->prev = last_section;
- last_section->next = sec;
- last_section = sec;
-
- }
-
- }
-
- /* Everything is placed and loaded. Now we package it all up
- * as a bzImage */
- if ((fp = fopen(out_filename, "w")) == NULL) {
- printf("Fatal: cannot open %s: %s\n", out_filename, strerror(errno));
- exit(1);
- }
- make_bzImage(sections,
- kernel_entry,
- ((address_t)mbi) + mbi_reloc_offset,
- fp);
- fclose(fp);
-
- /* Success! */
- if(!quiet) printf("Finished.\n");
- return 0;
-}
-
-/*
- * EOF (mbootpack.c)
- */
-
diff --git a/tools/misc/mbootpack/mbootpack.h b/tools/misc/mbootpack/mbootpack.h
deleted file mode 100644
index 20fe82a403..0000000000
--- a/tools/misc/mbootpack/mbootpack.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * mbootpack.h
- *
- * Common definitions for mbootpack
- *
- * Copyright (C) 2003-2004 Tim Deegan (tjd21@cl.cam.ac.uk)
- *
- * 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.
- *
- * $Id: mbootpack.h,v 1.2 2005/03/23 10:38:37 tjd21 Exp $
- *
- */
-
-#ifndef __MBOOTPACK__H__
-#define __MBOOTPACK__H__
-
-#ifndef __MB_ASM
-
-#undef NDEBUG
-#include <stdio.h>
-
-#include <endian.h>
-#include <byteswap.h>
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define eswap(x) (x)
-#else
-#define eswap(x) \
- ({ \
- typeof(x) y = (x); \
- switch(sizeof(y)) \
- { \
- case 2: y = __bswap_16(y); break; \
- case 4: y = __bswap_32(y); break; \
- case 8: y = __bswap_64(y); break; \
- } \
- y; \
- })
-#endif
-
-/* Flags */
-extern int quiet;
-
-/* Types */
-typedef unsigned long address_t;
-
-typedef struct section_t {
- char *buffer;
- address_t start;
- long int size;
- struct section_t *prev;
- struct section_t *next;
-} section_t;
-
-/* buildimage.c */
-extern void make_bzImage(section_t *sections,
- address_t entry,
- address_t mbi,
- FILE *fp);
-
-address_t place_mbi(long int size);
-
-
-/* trampoline.S */
-extern unsigned char mb_trampoline[];
-extern unsigned char mb_trampoline_end[];
-extern volatile address_t mb_mbi_address, mb_entry_address;
-
-/* Macros */
-#define MIN(_x,_y) (((_x)<=(_y))?(_x):(_y))
-#define MAX(_x,_y) (((_x)<=(_y))?(_y):(_x))
-#define ROUNDUP_P2(_x, _a) (((_x)+((_a)-1))&(~((_a)-1)))
-
-#endif
-
-/* x86 memory: such fun */
-#define MEM_HOLE_START 0xa0000
-#define MEM_HOLE_END 0x100000
-#define HIGHMEM_START MEM_HOLE_END
-#define X86_PAGE_SIZE 0x1000
-
-/* How much command line we'll take from the bootloader. */
-#define CMD_LINE_SPACE 0x300
-
-/* Number of 512-byte sectors to load in low memory (max 7) */
-#define SETUPSECTS 7
-
-
-/* Who are we? */
-#define MBOOTPACK_VERSION_STRING "v0.2 (alpha)"
-
-#endif /* __MBOOTPACK__H__ */
-
-/*
- * EOF (mbootpack.h)
- */
-
diff --git a/tools/misc/mbootpack/setup.S b/tools/misc/mbootpack/setup.S
deleted file mode 100644
index f429312df6..0000000000
--- a/tools/misc/mbootpack/setup.S
+++ /dev/null
@@ -1,1064 +0,0 @@
-/*
- * bootsect.S
- *
- * This is setup.S from the linux 2.6.9 source code,
- * with heavy cuts and changes for mbootpack
- * November 2004 Tim Deegan <tjd21@cl.cam.ac.uk>
- *
- *
- * 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.
- *
- * $Id: setup.S,v 1.4 2005/03/23 10:39:03 tjd21 Exp $
- *
- */
-
-#include "mbootpack.h"
-
-/*
- * setup.S Copyright (C) 1991, 1992 Linus Torvalds
- *
- * setup.s is responsible for getting the system data from the BIOS,
- * and putting them into the appropriate places in system memory.
- * both setup.s and system has been loaded by the bootblock.
- *
- * This code asks the bios for memory/disk/other parameters, and
- * puts them in a "safe" place: 0x90000-0x901FF, ie where the
- * boot-block used to be. It is then up to the protected mode
- * system to read them from there before the area is overwritten
- * for buffer-blocks.
- *
- * Move PS/2 aux init code to psaux.c
- * (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92
- *
- * some changes and additional features by Christoph Niemann,
- * March 1993/June 1994 (Christoph.Niemann@linux.org)
- *
- * add APM BIOS checking by Stephen Rothwell, May 1994
- * (sfr@canb.auug.org.au)
- *
- * High load stuff, initrd support and position independency
- * by Hans Lermen & Werner Almesberger, February 1996
- * <lermen@elserv.ffm.fgan.de>, <almesber@lrc.epfl.ch>
- *
- * Video handling moved to video.S by Martin Mares, March 1996
- * <mj@k332.feld.cvut.cz>
- *
- * Extended memory detection scheme retwiddled by orc@pell.chi.il.us (david
- * parsons) to avoid loadlin confusion, July 1997
- *
- * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999.
- * <stiker@northlink.com>
- *
- * Fix to work around buggy BIOSes which dont use carry bit correctly
- * and/or report extended memory in CX/DX for e801h memory size detection
- * call. As a result the kernel got wrong figures. The int15/e801h docs
- * from Ralf Brown interrupt list seem to indicate AX/BX should be used
- * anyway. So to avoid breaking many machines (presumably there was a reason
- * to orginally use CX/DX instead of AX/BX), we do a kludge to see
- * if CX/DX have been changed in the e801 call and if so use AX/BX .
- * Michael Miller, April 2001 <michaelm@mjmm.org>
- *
- * New A20 code ported from SYSLINUX by H. Peter Anvin. AMD Elan bugfixes
- * by Robert Schwebel, December 2001 <robert@schwebel.de>
- */
-
-/*
-#include <linux/config.h>
-#include <asm/segment.h>
-#include <linux/version.h>
-#include <linux/compile.h>
-#include <asm/boot.h>
-#include <asm/e820.h>
-#include <asm/page.h>
-*/
-
-/* Definitions that should have come from these includes */
-#define DEF_INITSEG 0x9000
-#define DEF_SYSSEG 0x1000
-#define DEF_SETUPSEG 0x9020
-#define DEF_SYSSIZE 0x7F00
-#define NORMAL_VGA 0xffff
-#define EXTENDED_VGA 0xfffe
-#define ASK_VGA 0xfffd
-#define GDT_ENTRY_BOOT_CS 2
-#define __BOOT_CS (GDT_ENTRY_BOOT_CS * 8)
-#define GDT_ENTRY_BOOT_DS (GDT_ENTRY_BOOT_CS + 1)
-#define __BOOT_DS (GDT_ENTRY_BOOT_DS * 8)
-#define __PAGE_OFFSET (0xC0000000)
-#define E820MAP 0x2d0 /* our map */
-#define E820MAX 32 /* number of entries in E820MAP */
-#define E820NR 0x1e8 /* # entries in E820MAP */
-#define E820_RAM 1
-#define E820_RESERVED 2
-#define E820_ACPI 3 /* usable as RAM once ACPI tables have been read */
-#define E820_NVS 4
-#define __BIG_KERNEL__
-
-
-/* Signature words to ensure LILO loaded us right */
-#define SIG1 0xAA55
-#define SIG2 0x5A5A
-
-INITSEG = DEF_INITSEG # 0x9000, we move boot here, out of the way
-SYSSEG = DEF_SYSSEG # 0x1000, system loaded at 0x10000 (65536).
-SETUPSEG = DEF_SETUPSEG # 0x9020, this is the current segment
- # ... and the former contents of CS
-
-DELTA_INITSEG = SETUPSEG - INITSEG # 0x0020
-
-.code16
-.globl _start, begtext, begdata, begbss, endtext, enddata, endbss
-
-.text
-begtext:
-.data
-begdata:
-.bss
-begbss:
-.text
-
-_start:
-start:
- jmp trampoline
-
-# This is the setup header, and it must start at %cs:2 (old 0x9020:2)
-
- .ascii "HdrS" # header signature
- .word 0x0203 # header version number (>= 0x0105)
- # or else old loadlin-1.5 will fail)
-realmode_swtch: .word 0, 0 # default_switch, SETUPSEG
-start_sys_seg: .word SYSSEG
- .word kernel_version # pointing to kernel version string
- # above section of header is compatible
- # with loadlin-1.5 (header v1.5). Don't
- # change it.
-
-type_of_loader: .byte 0 # = 0, old one (LILO, Loadlin,
- # Bootlin, SYSLX, bootsect...)
- # See Documentation/i386/boot.txt for
- # assigned ids
-
-# flags, unused bits must be zero (RFU) bit within loadflags
-loadflags:
-LOADED_HIGH = 1 # If set, the kernel is loaded high
-CAN_USE_HEAP = 0x80 # If set, the loader also has set
- # heap_end_ptr to tell how much
- # space behind setup.S can be used for
- # heap purposes.
- # Only the loader knows what is free
-#ifndef __BIG_KERNEL__
- .byte 0
-#else
- .byte LOADED_HIGH
-#endif
-
-setup_move_size: .word 0x8000 # size to move, when setup is not
- # loaded at 0x90000. We will move setup
- # to 0x90000 then just before jumping
- # into the kernel. However, only the
- # loader knows how much data behind
- # us also needs to be loaded.
-
-/* N.B. these next addresses are entirely ignored by this code -- it
- * assumes it was loaded with the 32bit code at 0x100000, and doesn't
- * touch the ramdisk. */
-code32_start: # here loaders can put a different
- # start address for 32-bit code.
-#ifndef __BIG_KERNEL__
- .long 0x1000 # 0x1000 = default for zImage
-#else
- .long 0x100000 # 0x100000 = default for big kernel
-#endif
-
-ramdisk_image: .long 0 # address of loaded ramdisk image
- # Here the loader puts the 32-bit
- # address where it loaded the image.
- # This only will be read by the kernel.
-
-ramdisk_size: .long 0 # its size in bytes
-
-bootsect_kludge:
- .long 0 # obsolete
-
-heap_end_ptr: .word modelist+1024 # (Header version 0x0201 or later)
- # space from here (exclusive) down to
- # end of setup code can be used by setup
- # for local heap purposes.
-
-pad1: .word 0
-cmd_line_ptr: .long 0 # (Header version 0x0202 or later)
- # If nonzero, a 32-bit pointer
- # to the kernel command line.
- # The command line should be
- # located between the start of
- # setup and the end of low
- # memory (0xa0000), or it may
- # get overwritten before it
- # gets read. If this field is
- # used, there is no longer
- # anything magical about the
- # 0x90000 segment; the setup
- # can be located anywhere in
- # low memory 0x10000 or higher.
-
-ramdisk_max: .long (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff
- # (Header version 0x0203 or later)
- # The highest safe address for
- # the contents of an initrd
-
-/* Add more known locations: the image builder will overwrite
- * these with the entry point and MBI location for the multiboot kernel.
- * These offsets *must* match the definitions in buildimage.c */
-
-entry_address: .long 0 # This will be offset 0x30 (0x230 from b'sect)
-mbi_address: .long 0 # This will be offset 0x34
-
-/* Storage space for the size of memory */
-highmem_size: .long 0
-
-trampoline: call start_of_setup
- .space 1024
-# End of setup header #####################################################
-
-start_of_setup:
-# Bootlin depends on this being done early
- movw $0x01500, %ax
- movb $0x81, %dl
- int $0x13
-
-#ifdef SAFE_RESET_DISK_CONTROLLER
-# Reset the disk controller.
- movw $0x0000, %ax
- movb $0x80, %dl
- int $0x13
-#endif
-
-# Set %ds = %cs, we know that SETUPSEG = %cs at this point
- movw %cs, %ax # aka SETUPSEG
- movw %ax, %ds
-
-# Check signature at end of setup
- cmpw $SIG1, setup_sig1
- jne bad_sig
-
- cmpw $SIG2, setup_sig2
- jne bad_sig
-
- jmp good_sig1
-
-# Routine to print asciiz string at ds:si
-prtstr:
- lodsb
- andb %al, %al
- jz fin
-
- call prtchr
- jmp prtstr
-
-fin: ret
-
-# Space printing
-prtsp2: call prtspc # Print double space
-prtspc: movb $0x20, %al # Print single space (note: fall-thru)
-
-# Part of above routine, this one just prints ascii al
-prtchr: pushw %ax
- pushw %cx
- movw $7,%bx
- movw $0x01, %cx
- movb $0x0e, %ah
- int $0x10
- popw %cx
- popw %ax
- ret
-
-beep: movb $0x07, %al
- jmp prtchr
-
-no_sig_mess: .string "No setup signature found ..."
-
-good_sig1:
- jmp good_sig
-
-# We now have to find the rest of the setup code/data
-bad_sig:
- movw %cs, %ax # SETUPSEG
- subw $DELTA_INITSEG, %ax # INITSEG
- movw %ax, %ds
- xorb %bh, %bh
- movb (497), %bl # get setup sect from bootsect
- subw $4, %bx # LILO loads 4 sectors of setup
- shlw $8, %bx # convert to words (1sect=2^8 words)
- movw %bx, %cx
- shrw $3, %bx # convert to segment
- addw $SYSSEG, %bx
- movw %bx, %cs:start_sys_seg
-# Move rest of setup code/data to here
- movw $2048, %di # four sectors loaded by LILO
- subw %si, %si
- pushw %cs
- popw %es
- movw $SYSSEG, %ax
- movw %ax, %ds
- rep
- movsw
- movw %cs, %ax # aka SETUPSEG
- movw %ax, %ds
- cmpw $SIG1, setup_sig1
- jne no_sig
-
- cmpw $SIG2, setup_sig2
- jne no_sig
-
- jmp good_sig
-
-no_sig:
- lea no_sig_mess, %si
- call prtstr
-
-no_sig_loop:
- hlt
- jmp no_sig_loop
-
-mb_hello_mess1:
- .string "mboot"
-
-good_sig:
- lea mb_hello_mess1, %si
- call prtstr
-
- movw %cs, %ax # aka SETUPSEG
- subw $DELTA_INITSEG, %ax # aka INITSEG
- movw %ax, %ds
-# Check if an old loader tries to load a big-kernel
- testb $LOADED_HIGH, %cs:loadflags # Do we have a big kernel?
- jz loader_ok # No, no danger for old loaders.
-
- cmpb $0, %cs:type_of_loader # Do we have a loader that
- # can deal with us?
- jnz loader_ok # Yes, continue.
-
- pushw %cs # No, we have an old loader,
- popw %ds # die.
- lea loader_panic_mess, %si
- call prtstr
-
- jmp no_sig_loop
-
-loader_panic_mess: .string "Wrong loader, giving up..."
-
-loader_ok:
-
-# Get memory size (extended mem, kB)
-
-/* We'll be storing this in highmem_size, to be copied to the mbi */
-
-# Try three different memory detection schemes. First, try
-# e820h, which lets us assemble a memory map, then try e801h,
-# which returns a 32-bit memory size, and finally 88h, which
-# returns 0-64m
-
- xorl %edx, %edx
- xorl %eax, %eax
- movl %eax, (0x1e0)
- movl %eax, highmem_size
- movb %al, (E820NR)
-
-# method E820H:
-# the memory map from hell. e820h returns memory classified into
-# a whole bunch of different types, and allows memory holes and
-# everything. We scan through this memory map and build a list
-# of the first 32 memory areas, which we return at [E820MAP].
-# This is documented at http://www.acpi.info/, in the ACPI 2.0 specification.
-
-#define SMAP 0x534d4150
-
-meme820:
- xorl %ebx, %ebx # continuation counter
- movw $E820MAP, %di # point into the whitelist
- # so we can have the bios
- # directly write into it.
-
-jmpe820:
- movl $0x0000e820, %eax # e820, upper word zeroed
- movl $SMAP, %edx # ascii 'SMAP'
- movl $20, %ecx # size of the e820rec
- pushw %ds # data record.
- popw %es
- int $0x15 # make the call
- jc bail820 # fall to e801 if it fails
-
- cmpl $SMAP, %eax # check the return is `SMAP'
- jne bail820 # fall to e801 if it fails
-
-# cmpl $1, 16(%di) # is this usable memory?
-# jne again820
-
- # If this is usable memory, we save it by simply advancing %di by
- # sizeof(e820rec).
- #
-good820:
- movb (E820NR), %al # up to 32 entries
- cmpb $E820MAX, %al
- jnl bail820
-
- incb (E820NR)
- movw %di, %ax
- addw $20, %ax
- movw %ax, %di
-again820:
- cmpl $0, %ebx # check to see if
- jne jmpe820 # %ebx is set to EOF
-
-/* Multiboot spec says high mem should be the address of the first
- * upper memory hole, minus 1 MB */
- xorl %ebx, %ebx
- xorl %ecx, %ecx
- xorl %edx, %edx
- movw $E820MAP, %di # Start at the beginning
-calc_highmem_loop:
- cmpl $1, 16(%di) # is it usable memory?
- jnz calc_highmem_next
- cmpl $0, 4(%di) # is base < 4GB?
- jnz calc_highmem_next
- cmpl $0x100000, 0(%di) # is base <= 1MB?
- jg calc_highmem_next
- movl 8(%di), %ecx # Calculate base+length
- shrl $10, %ecx # in kilobytes
- movl 12(%di), %edx
- shll $22, %edx
- orl %edx, %ecx
- movl 0(%di), %edx
- shrl $10, %edx
- addl %edx, %ecx
- subl $1024, %ecx # - 1 MB
- cmpl %cs:highmem_size, %ecx
- jl calc_highmem_next
- movl %ecx, %cs:highmem_size
-calc_highmem_next:
- add $1, %bl
- add $20, %di
- cmp %bl, (E820NR)
- je calc_highmem_done
- jmp calc_highmem_loop
-calc_highmem_done:
-
-bail820:
-
-# method E801H:
-# memory size is in 1k chunksizes, to avoid confusing loadlin.
-
-meme801:
- stc # fix to work around buggy
- xorw %cx,%cx # BIOSes which dont clear/set
- xorw %dx,%dx # carry on pass/error of
- # e801h memory size call
- # or merely pass cx,dx though
- # without changing them.
- movw $0xe801, %ax
- int $0x15
- jc mem88
-
- cmpw $0x0, %cx # Kludge to handle BIOSes
- jne e801usecxdx # which report their extended
- cmpw $0x0, %dx # memory in AX/BX rather than
- jne e801usecxdx # CX/DX. The spec I have read
- movw %ax, %cx # seems to indicate AX/BX
- movw %bx, %dx # are more reasonable anyway...
-
-e801usecxdx:
- andl $0xffff, %edx # clear sign extend
- shll $6, %edx # and go from 64k to 1k chunks
- andl $0xffff, %ecx # clear sign extend
- addl %ecx, %edx
-
- cmpl %cs:highmem_size, %edx # store extended mem size
- jl mem88 # if it's bigger than
- movl %edx, %cs:highmem_size # what we already have
-
-# Ye Olde Traditional Methode. Returns the memory size (up to 16mb or
-# 64mb, depending on the bios) in ax.
-mem88:
- movb $0x88, %ah
- int $0x15
-
- andl $0xffff, %eax # clear sign extend
- cmpl %cs:highmem_size, %eax # store extended mem size
- jl have_memsize # if it's bigger than
- movl %eax, %cs:highmem_size # what we already have
-
-have_memsize:
-
-/* Culled: HDD probes, APM, speedstep */
-
-# Now we want to move to protected mode ...
- cmpw $0, %cs:realmode_swtch
- jz rmodeswtch_normal
-
- lcall *%cs:realmode_swtch
-
- jmp rmodeswtch_end
-
-rmodeswtch_normal:
- pushw %cs
- call default_switch
-
-rmodeswtch_end:
-
-/* Culled: code to take the 32bit entry address from the loader */
-/* Culled: code to relocate non-bzImage kernels */
-
- # then we load the segment descriptors
- movw %cs, %ax # aka SETUPSEG
- movw %ax, %ds
-
-# Check whether we need to be downward compatible with version <=201
- cmpl $0, cmd_line_ptr
- jne end_move_self # loader uses version >=202 features
- cmpb $0x20, type_of_loader
- je end_move_self # bootsect loader, we know of it
-
-# Boot loader doesnt support boot protocol version 2.02.
-# If we have our code not at 0x90000, we need to move it there now.
-# We also then need to move the params behind it (commandline)
-# Because we would overwrite the code on the current IP, we move
-# it in two steps, jumping high after the first one.
- movw %cs, %ax
- cmpw $SETUPSEG, %ax
- je end_move_self
-
- cli # make sure we really have
- # interrupts disabled !
- # because after this the stack
- # should not be used
- subw $DELTA_INITSEG, %ax # aka INITSEG
- movw %ss, %dx
- cmpw %ax, %dx
- jb move_self_1
-
- addw $INITSEG, %dx
- subw %ax, %dx # this will go into %ss after
- # the move
-move_self_1:
- movw %ax, %ds
- movw $INITSEG, %ax # real INITSEG
- movw %ax, %es
- movw %cs:setup_move_size, %cx
- std # we have to move up, so we use
- # direction down because the
- # areas may overlap
- movw %cx, %di
- decw %di
- movw %di, %si
- subw $move_self_here+0x200, %cx
- rep
- movsb
- ljmp $SETUPSEG, $move_self_here
-
-move_self_here:
- movw $move_self_here+0x200, %cx
- rep
- movsb
- movw $SETUPSEG, %ax
- movw %ax, %ds
- movw %dx, %ss
-end_move_self: # now we are at the right place
-
-#
-# Enable A20. This is at the very best an annoying procedure.
-# A20 code ported from SYSLINUX 1.52-1.63 by H. Peter Anvin.
-# AMD Elan bug fix by Robert Schwebel.
-#
-
-#if defined(CONFIG_X86_ELAN)
- movb $0x02, %al # alternate A20 gate
- outb %al, $0x92 # this works on SC410/SC520
-a20_elan_wait:
- call a20_test
- jz a20_elan_wait
- jmp a20_done
-#endif
-
-
-A20_TEST_LOOPS = 32 # Iterations per wait
-A20_ENABLE_LOOPS = 255 # Total loops to try
-
-
-#ifndef CONFIG_X86_VOYAGER
-a20_try_loop:
-
- # First, see if we are on a system with no A20 gate.
-a20_none:
- call a20_test
- jnz a20_done
-
- # Next, try the BIOS (INT 0x15, AX=0x2401)
-a20_bios:
- movw $0x2401, %ax
- pushfl # Be paranoid about flags
- int $0x15
- popfl
-
- call a20_test
- jnz a20_done
-
- # Try enabling A20 through the keyboard controller
-#endif /* CONFIG_X86_VOYAGER */
-a20_kbc:
- call empty_8042
-
-#ifndef CONFIG_X86_VOYAGER
- call a20_test # Just in case the BIOS worked
- jnz a20_done # but had a delayed reaction.
-#endif
-
- movb $0xD1, %al # command write
- outb %al, $0x64
- call empty_8042
-
- movb $0xDF, %al # A20 on
- outb %al, $0x60
- call empty_8042
-
-#ifndef CONFIG_X86_VOYAGER
- # Wait until a20 really *is* enabled; it can take a fair amount of
- # time on certain systems; Toshiba Tecras are known to have this
- # problem.
-a20_kbc_wait:
- xorw %cx, %cx
-a20_kbc_wait_loop:
- call a20_test
- jnz a20_done
- loop a20_kbc_wait_loop
-
- # Final attempt: use "configuration port A"
-a20_fast:
- inb $0x92, %al # Configuration Port A
- orb $0x02, %al # "fast A20" version
- andb $0xFE, %al # don't accidentally reset
- outb %al, $0x92
-
- # Wait for configuration port A to take effect
-a20_fast_wait:
- xorw %cx, %cx
-a20_fast_wait_loop:
- call a20_test
- jnz a20_done
- loop a20_fast_wait_loop
-
- # A20 is still not responding. Try frobbing it again.
- #
- decb (a20_tries)
- jnz a20_try_loop
-
- movw $a20_err_msg, %si
- call prtstr
-
-a20_die:
- hlt
- jmp a20_die
-
-a20_tries:
- .byte A20_ENABLE_LOOPS
-
-a20_err_msg:
- .ascii "linux: fatal error: A20 gate not responding!"
- .byte 13, 10, 0
-
- # If we get here, all is good
-a20_done:
-
-
-#endif /* CONFIG_X86_VOYAGER */
-
-/* Another print, to show protected mode and A20 are OK */
-
- jmp mb_hello_mess2_end
-mb_hello_mess2:
- .string "pack "
-mb_hello_mess2_end:
- lea mb_hello_mess2, %si
- call prtstr
-
-# set up gdt and idt
-/* lidt idt_48 # load idt with 0,0 */
-/* Multiboot kernels must set up their own IDT: leave this for now,
- * so we can print diagnostics */
-
- xorl %eax, %eax # Compute gdt_base
- movw %ds, %ax # (Convert %ds:gdt to a linear ptr)
- shll $4, %eax
- addl $gdt, %eax
- movl %eax, (gdt_48+2)
- lgdt gdt_48 # load gdt with whatever is
- # appropriate
-
-# make sure any possible coprocessor is properly reset..
- xorw %ax, %ax
- outb %al, $0xf0
- call delay
-
- outb %al, $0xf1
- call delay
-
-
-# well, that went ok, I hope. Now we mask all interrupts - the rest
-# is done in init_IRQ().
- movb $0xFF, %al # mask all interrupts for now
- outb %al, $0xA1
- call delay
-
- movb $0xFB, %al # mask all irq's but irq2 which
- outb %al, $0x21 # is cascaded
-
-# Well, that certainly wasn't fun :-(. Hopefully it works, and we don't
-# need no steenking BIOS anyway (except for the initial loading :-).
-# The BIOS-routine wants lots of unnecessary data, and it's less
-# "interesting" anyway. This is how REAL programmers do it.
-
-/* Tailor the jump below so the target is the 32bit trampoline code */
-
- xorl %eax, %eax # Calculate
- movw %cs, %ax # the linear
- shll $4, %eax # address of
- addl $trampoline32, %eax # %cs:trampoline32
- movl %eax, %cs:code32 # Stick it into the jmpi
-
- /* Load a 32-bit pointer to the entry address into %ecx */
- xorl %ecx, %ecx # Calculate
- movw %cs, %cx # the linear
- shll $4, %ecx # address of
- addl $entry_address, %ecx # %cs:entry_address
-
-# Well, now's the time to actually move into protected mode.
-
- lea mb_ready_mess, %si
- call prtstr
-
-/* May as well load this IDT now */
- lidt idt_48
-
- xorl %eax, %eax
- movw $1, %ax # protected mode (PE) bit
- lmsw %ax # This is it!
- jmp flush_instr
-flush_instr:
-
- /* Set up segment registers */
- movw $__BOOT_DS, %dx
- movw %dx, %ds
- movw %dx, %es
- movw %dx, %fs
- movw %dx, %gs
- movw %dx, %ss
-
- /* Trampoline expects this in %eax */
- movl %ecx, %eax
-
- /* Jump to the 32-bit trampoline */
-
-# NOTE: For high loaded big kernels we need a
-# jmpi 0x100000,__BOOT_CS
-#
-# but we yet haven't reloaded the CS register, so the default size
-# of the target offset still is 16 bit.
-# However, using an operand prefix (0x66), the CPU will properly
-# take our 48 bit far pointer. (INTeL 80386 Programmer's Reference
-# Manual, Mixing 16-bit and 32-bit code, page 16-6)
-
- .byte 0x66, 0xea # prefix + jmpi-opcode
-code32: .long 0x1000 # will be set to trampoline32
- # by code above.
- .word __BOOT_CS
-
-# Here's a bunch of information about your current kernel..
-
-kernel_version: .string "mbootpack changeling bzImage"
-mb_ready_mess:
- .ascii MBOOTPACK_VERSION_STRING
- .ascii "\r\n"
- .byte 0
-
-# This is the default real mode switch routine.
-# to be called just before protected mode transition
-default_switch:
- cli # no interrupts allowed !
- movb $0x80, %al # disable NMI for bootup
- # sequence
- outb %al, $0x70
- lret
-
-
-#ifndef CONFIG_X86_VOYAGER
-# This routine tests whether or not A20 is enabled. If so, it
-# exits with zf = 0.
-#
-# The memory address used, 0x200, is the int $0x80 vector, which
-# should be safe.
-
-A20_TEST_ADDR = 4*0x80
-
-a20_test:
- pushw %cx
- pushw %ax
- xorw %cx, %cx
- movw %cx, %fs # Low memory
- decw %cx
- movw %cx, %gs # High memory area
- movw $A20_TEST_LOOPS, %cx
- movw %fs:(A20_TEST_ADDR), %ax
- pushw %ax
-a20_test_wait:
- incw %ax
- movw %ax, %fs:(A20_TEST_ADDR)
- call delay # Serialize and make delay constant
- cmpw %gs:(A20_TEST_ADDR+0x10), %ax
- loope a20_test_wait
-
- popw %fs:(A20_TEST_ADDR)
- popw %ax
- popw %cx
- ret
-
-#endif /* CONFIG_X86_VOYAGER */
-
-# This routine checks that the keyboard command queue is empty
-# (after emptying the output buffers)
-#
-# Some machines have delusions that the keyboard buffer is always full
-# with no keyboard attached...
-#
-# If there is no keyboard controller, we will usually get 0xff
-# to all the reads. With each IO taking a microsecond and
-# a timeout of 100,000 iterations, this can take about half a
-# second ("delay" == outb to port 0x80). That should be ok,
-# and should also be plenty of time for a real keyboard controller
-# to empty.
-#
-
-empty_8042:
- pushl %ecx
- movl $100000, %ecx
-
-empty_8042_loop:
- decl %ecx
- jz empty_8042_end_loop
-
- call delay
-
- inb $0x64, %al # 8042 status port
- testb $1, %al # output buffer?
- jz no_output
-
- call delay
- inb $0x60, %al # read it
- jmp empty_8042_loop
-
-no_output:
- testb $2, %al # is input buffer full?
- jnz empty_8042_loop # yes - loop
-empty_8042_end_loop:
- popl %ecx
- ret
-
-# Read the cmos clock. Return the seconds in al
-gettime:
- pushw %cx
- movb $0x02, %ah
- int $0x1a
- movb %dh, %al # %dh contains the seconds
- andb $0x0f, %al
- movb %dh, %ah
- movb $0x04, %cl
- shrb %cl, %ah
- aad
- popw %cx
- ret
-
-# Delay is needed after doing I/O
-delay:
- outb %al,$0x80
- ret
-
-# Descriptor tables
-#
-# NOTE: The intel manual says gdt should be sixteen bytes aligned for
-# efficiency reasons. However, there are machines which are known not
-# to boot with misaligned GDTs, so alter this at your peril! If you alter
-# GDT_ENTRY_BOOT_CS (in asm/segment.h) remember to leave at least two
-# empty GDT entries (one for NULL and one reserved).
-#
-# NOTE: On some CPUs, the GDT must be 8 byte aligned. This is
-# true for the Voyager Quad CPU card which will not boot without
-# This directive. 16 byte aligment is recommended by intel.
-#
-
-
-/* The boot-time code segment is set at the jmpi above */
-/* Dont change this without checking everything still matches */
-
- .align 16
-gdt:
- .fill GDT_ENTRY_BOOT_CS,8,0
-
- .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
- .word 0 # base address = 0
- .word 0x9A00 # code read/exec
- .word 0x00CF # granularity = 4096, 386
- # (+5th nibble of limit)
-
- .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
- .word 0 # base address = 0
- .word 0x9200 # data read/write
- .word 0x00CF # granularity = 4096, 386
- # (+5th nibble of limit)
-gdt_end:
- .align 4
-
- .word 0 # alignment byte
-idt_48:
- .word 0 # idt limit = 0
- .word 0, 0 # idt base = 0L
-
- .word 0 # alignment byte
-gdt_48:
- .word gdt_end - gdt - 1 # gdt limit
- .word 0, 0 # gdt base (filled in later)
-
-# Include video setup & detection code
-
-/* #include "video.S" */
-
-.code32
-trampoline32:
- /* Here, %eax = 32-bit pointer to entry_address */
-
- /* Check if the bootloader gave us a (non-empty) command line */
- movl -8(%eax), %ebx # cmd_line_ptr
- cmpl $0, %ebx
- je no_cmd_line
- cmpb $0, 0(%ebx)
- je no_cmd_line
-
- /* Find the MBI command line */
- movl %eax, %ecx # &entry_address
- addl $(begtext-entry_address), %ecx # --> start of setup
- subl $0x9200, %ecx # --> reloc offset
- movl %ecx, %esi # (copy offset)
- movl %ecx, %ebx # (copy offset)
- addl 4(%eax), %ecx # --> current addr of MBI
- addl 16(%ecx), %ebx # --> cur. addr of MB cmdline
-
- /* Overwrite the built-in MBI kernel command line */
- movl -8(%eax), %ecx
- movl $0, %edi
-
- /* Give the kernel a 'self' word, that linux doesn't get */
- movw $0x202E, 0(%ebx) # '. '
- addl $0x2, %ebx
-
-cmd_line_copy:
- movb (%ecx, %edi), %dl
- movb %dl, (%ebx, %edi)
- inc %edi
- cmp $CMD_LINE_SPACE-3, %edi
- je cmd_line_copy_end
-
- cmpb $0x0, %dl
- jne cmd_line_copy
-cmd_line_copy_end:
- movb $0x0, (%ebx, %edi)
- subl $0x2, %ebx
-
- /* Look for '--' in the kernel command line */
-cmd_line_scan:
- inc %ebx
- cmpb $0x0, 0(%ebx)
- je no_cmd_line
- cmpl $0x202D2D20, 0(%ebx) # ' -- '
- jne cmd_line_scan
-
- /* Found it: terminate kernel's command line */
- movb $0x0, 0(%ebx)
- inc %ebx
- /* Relocate address to where it will be moved to */
- subl %esi, %ebx
-
- /* Is there a module 0? */
- movl %esi, %ecx # Reloc offset
- addl 4(%eax), %ecx # --> current addr of MBI
- cmpl $0x0, 20(%ecx) # (check module count)
- je no_cmd_line
- /* Overwrite module 0's command line */
- movl %esi, %edx # Reloc offset
- addl 24(%ecx), %edx # --> cur. add. of Module 0
- movl %ebx, 8(%edx) # --> blat mod. 0's cmdline
-no_cmd_line:
-
-
- /* Relocate the MBI from after the setup code to its proper home
- * between the MBI pointer and 0xa000 */
- movl %eax, %ecx # &entry_address
- addl $(begtext-entry_address), %ecx # --> start of setup
- subl $0x9200, %ecx # --> reloc offset
- addl 4(%eax), %ecx # --> current addr of MBI
-
- movl $0xa000, %ebx # End of MBI
- subl 4(%eax), %ebx # --> size of MBI
- movl %ebx, %edi
-
- movl 4(%eax), %ebx # Destination of MBI
-
-mbi_copy:
- dec %edi
- movb (%ecx, %edi), %dl
- movb %dl, (%ebx, %edi)
- cmp $0x0, %edi
- jne mbi_copy
-
- /* Copy memory size into MBI structure */
- movl 4(%eax), %ebx # MBI pointer
- movl 8(%eax), %ecx # highmem_size
- movl %ecx, 8(%ebx) # --> mbi.mem_upper
- movl $0x280, %ecx
- movl %ecx, 4(%ebx) # --> mbi.mem_lower
- /* Set the MB_INFO_MEMORY bit */
- orl $1, 0(%ebx)
-
- /* Recover the MBI pointer into %ebx */
- movl 4(%eax), %ebx # MBI pointer
- /* Extract the load address into %ecx */
- movl 0(%eax), %ecx
- /* Let the kernel know we're a multiboot loader */
- movl $0x2BADB002, %eax
- /* Jump to the kernel address supplied */
- jmp *%ecx
-
-# Setup signature -- must be last
-setup_sig1: .word SIG1
-setup_sig2: .word SIG2
-
-# After this point, there is some free space which is used by the video mode
-# handling code to store the temporary mode table (not used by the kernel).
-
-modelist:
-
-.text
-endtext:
-.data
-enddata:
-.bss
-endbss:
diff --git a/tools/misc/miniterm/Makefile b/tools/misc/miniterm/Makefile
index 5b596a5f9f..1fe35f810c 100644
--- a/tools/misc/miniterm/Makefile
+++ b/tools/misc/miniterm/Makefile
@@ -1,10 +1,6 @@
XEN_ROOT:=../../..
include $(XEN_ROOT)/tools/Rules.mk
-INSTALL = install
-INSTALL_PROG = $(INSTALL) -m0755
-INSTALL_DIR = $(INSTALL) -d -m0755
-
TARGET = miniterm
.PHONY: all
diff --git a/tools/misc/xend b/tools/misc/xend
index ff58b30773..b0ee27f556 100644
--- a/tools/misc/xend
+++ b/tools/misc/xend
@@ -19,6 +19,9 @@
The daemon should reconnect to device control interfaces
and recover its state when restarted.
+
+ On Solaris, the daemons are SMF managed, and you should not attempt
+ to start xend by hand.
"""
import os
import os.path
@@ -108,9 +111,10 @@ def main():
if not sys.argv[1:]:
print 'usage: %s {start|stop|restart}' % sys.argv[0]
elif sys.argv[1] == 'start':
- start_xenstored()
- start_consoled()
- start_blktapctrl()
+ if os.uname()[0] != "SunOS":
+ start_xenstored()
+ start_consoled()
+ start_blktapctrl()
return daemon.start()
elif sys.argv[1] == 'trace_start':
start_xenstored()
diff --git a/tools/pygrub/Makefile b/tools/pygrub/Makefile
index de240f401f..da75bda4b0 100644
--- a/tools/pygrub/Makefile
+++ b/tools/pygrub/Makefile
@@ -6,16 +6,16 @@ include $(XEN_ROOT)/tools/Rules.mk
all: build
.PHONY: build
build:
- CFLAGS="$(CFLAGS)" python setup.py build
+ CC="$(CC)" CFLAGS="$(CFLAGS)" python setup.py build
.PHONY: install
ifndef XEN_PYTHON_NATIVE_INSTALL
install: all
- CFLAGS="$(CFLAGS)" python setup.py install --home="$(DESTDIR)/usr" --prefix=""
+ CC="$(CC)" CFLAGS="$(CFLAGS)" python setup.py install --home="$(DESTDIR)/usr" --prefix=""
$(INSTALL_DIR) -p $(DESTDIR)/var/lib/xen
else
install: all
- CFLAGS="$(CFLAGS)" python setup.py install --root="$(DESTDIR)"
+ CC="$(CC)" CFLAGS="$(CFLAGS)" python setup.py install --root="$(DESTDIR)"
$(INSTALL_DIR) -p $(DESTDIR)/var/lib/xen
endif
diff --git a/tools/python/Makefile b/tools/python/Makefile
index e73d624414..6b84446ee6 100644
--- a/tools/python/Makefile
+++ b/tools/python/Makefile
@@ -6,15 +6,15 @@ all: build
.PHONY: build
build:
- CFLAGS="$(CFLAGS)" python setup.py build
+ CC="$(CC)" CFLAGS="$(CFLAGS)" python setup.py build
.PHONY: install
ifndef XEN_PYTHON_NATIVE_INSTALL
install: all
- CFLAGS="$(CFLAGS)" python setup.py install --home="$(DESTDIR)/usr" --prefix="" --force
+ CC="$(CC)" CFLAGS="$(CFLAGS)" python setup.py install --home="$(DESTDIR)/usr" --prefix="" --force
else
install: all
- CFLAGS="$(CFLAGS)" python setup.py install --root="$(DESTDIR)" --force
+ CC="$(CC)" CFLAGS="$(CFLAGS)" python setup.py install --root="$(DESTDIR)" --force
endif
.PHONY: test
diff --git a/tools/python/xen/util/auxbin.py b/tools/python/xen/util/auxbin.py
index 50450773dd..5d2066157c 100644
--- a/tools/python/xen/util/auxbin.py
+++ b/tools/python/xen/util/auxbin.py
@@ -21,7 +21,7 @@ LIB_64 = "/usr/lib64"
LIB_BIN_SUFFIX = "xen/bin"
## The architectures on which the LIB_64 directory is used. This
-# deliberately excludes ia64 and ppc64.
+# deliberately excludes ia64 and ppc64, and Solaris.
LIB_64_ARCHS = [ 'x86_64', 's390x', 'sparc64']
diff --git a/tools/python/xen/util/security.py b/tools/python/xen/util/security.py
index 015de985b1..e617ddf894 100644
--- a/tools/python/xen/util/security.py
+++ b/tools/python/xen/util/security.py
@@ -31,6 +31,7 @@ from xen.util import dictio
policy_dir_prefix = "/etc/xen/acm-security/policies"
res_label_filename = policy_dir_prefix + "/resource_labels"
boot_filename = "/boot/grub/menu.lst"
+altboot_filename = "/boot/grub/grub.conf"
xensec_xml2bin = "/usr/sbin/xensec_xml2bin"
xensec_tool = "/usr/sbin/xensec_tool"
@@ -596,12 +597,34 @@ def get_res_security_details(resource):
return (label, ssidref, policy)
+def unify_resname(resource):
+ """Makes all resource locations absolute. In case of physical
+ resources, '/dev/' is added to local file names"""
+
+ # sanity check on resource name
+ (type, resfile) = resource.split(":")
+ if type == "phy":
+ if not resfile.startswith("/"):
+ resfile = "/dev/" + resfile
+
+ #file: resources must specified with absolute path
+ if (not resfile.startswith("/")) or (not os.path.exists(resfile)):
+ err("Invalid resource.")
+
+ # from here on absolute file names with resources
+ resource = type + ":" + resfile
+ return resource
+
+
def res_security_check(resource, domain_label):
"""Checks if the given resource can be used by the given domain
label. Returns 1 if the resource can be used, otherwise 0.
"""
rtnval = 1
+ #build canonical resource name
+ resource = unify_resname(resource)
+
# if security is on, ask the hypervisor for a decision
if on():
(label, ssidref, policy) = get_res_security_details(resource)
diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py
index 42e3a50dd7..748d7fe7f1 100644
--- a/tools/python/xen/xend/XendDomainInfo.py
+++ b/tools/python/xen/xend/XendDomainInfo.py
@@ -392,6 +392,8 @@ def parseConfig(config):
log.warn("Ignoring malformed and deprecated config option "
"restart = %s", restart)
+ result['start_time'] = get_cfg('start_time', float)
+
log.debug("parseConfig: result is %s", result)
return result
diff --git a/tools/python/xen/xend/XendRoot.py b/tools/python/xen/xend/XendRoot.py
index 4b81705b24..1ff9baf485 100644
--- a/tools/python/xen/xend/XendRoot.py
+++ b/tools/python/xen/xend/XendRoot.py
@@ -30,6 +30,7 @@ import os.path
import string
import sys
+import osdep
import XendLogging
from XendError import XendError
@@ -46,10 +47,10 @@ class XendRoot:
config_var = "XEND_CONFIG"
"""Where network control scripts live."""
- network_script_dir = "/etc/xen/scripts"
+ network_script_dir = osdep.scripts_dir
"""Where block control scripts live."""
- block_script_dir = "/etc/xen/scripts"
+ block_script_dir = osdep.scripts_dir
"""Default path to the log file. """
logfile_default = "/var/log/xen/xend.log"
@@ -96,6 +97,8 @@ class XendRoot:
dom0_vcpus_default = '0'
+ vncpasswd_default = None
+
"""Default interface to listen for VNC connections on"""
xend_vnc_listen_default = '127.0.0.1'
@@ -278,6 +281,10 @@ class XendRoot:
def get_vnclisten_address(self):
return self.get_config_value('vnc-listen', self.xend_vnc_listen_default)
+ def get_vncpasswd_default(self):
+ return self.get_config_value('vncpasswd',
+ self.vncpasswd_default)
+
def instance():
"""Get an instance of XendRoot.
Use this instead of the constructor.
diff --git a/tools/python/xen/xend/arch.py b/tools/python/xen/xend/arch.py
index 85e6547401..a556c0e6cf 100644
--- a/tools/python/xen/xend/arch.py
+++ b/tools/python/xen/xend/arch.py
@@ -25,6 +25,7 @@ _types = {
"i586": "x86",
"i686": "x86",
"x86_64": "x86",
+ "i86pc": "x86",
"ia64": "ia64",
"ppc": "powerpc",
"ppc64": "powerpc",
diff --git a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py
index 28a8952eec..88a8a169bc 100644
--- a/tools/python/xen/xend/image.py
+++ b/tools/python/xen/xend/image.py
@@ -20,6 +20,7 @@
import os, string
import re
import math
+import signal
import xen.lowlevel.xc
from xen.xend import sxp
@@ -312,6 +313,11 @@ class HVMImageHandler(ImageHandler):
if v:
ret.append("-%s" % a)
ret.append("%s" % v)
+
+ if a in ['fda', 'fdb' ]:
+ if v:
+ if not os.path.isfile(v):
+ raise VmError("Floppy file %s does not exist." % v)
log.debug("args: %s, val: %s" % (a,v))
# Handle disk/network related options
@@ -349,23 +355,49 @@ class HVMImageHandler(ImageHandler):
sdl = sxp.child_value(config, 'sdl')
ret = []
nographic = sxp.child_value(config, 'nographic')
+
+ # get password from VM config (if password omitted, None)
+ vncpasswd_vmconfig = sxp.child_value(config, 'vncpasswd')
+
if nographic:
ret.append('-nographic')
+ # remove password
+ if vncpasswd_vmconfig:
+ config.remove(['vncpasswd', vncpasswd_vmconfig])
return ret
+
if vnc:
vncdisplay = sxp.child_value(config, 'vncdisplay',
int(self.vm.getDomid()))
+
vncunused = sxp.child_value(config, 'vncunused')
if vncunused:
ret += ['-vncunused']
else:
ret += ['-vnc', '%d' % vncdisplay]
+
ret += ['-k', 'en-us']
+
vnclisten = sxp.child_value(config, 'vnclisten')
if not(vnclisten):
- vnclisten = xen.xend.XendRoot.instance().get_vnclisten_address()
+ vnclisten = (xen.xend.XendRoot.instance().
+ get_vnclisten_address())
if vnclisten:
ret += ['-vnclisten', vnclisten]
+
+ vncpasswd = vncpasswd_vmconfig
+ if vncpasswd is None:
+ vncpasswd = (xen.xend.XendRoot.instance().
+ get_vncpasswd_default())
+ if vncpasswd is None:
+ raise VmError('vncpasswd is not set up in ' +
+ 'VMconfig and xend-config.')
+ if vncpasswd != '':
+ self.vm.storeVm("vncpasswd", vncpasswd)
+
+ # remove password
+ config.remove(['vncpasswd', vncpasswd_vmconfig])
+
return ret
def createDeviceModel(self):
@@ -390,7 +422,6 @@ class HVMImageHandler(ImageHandler):
def destroy(self):
self.unregister_shutdown_watch();
- import signal
if not self.pid:
return
os.kill(self.pid, signal.SIGKILL)
diff --git a/tools/python/xen/xend/osdep.py b/tools/python/xen/xend/osdep.py
new file mode 100644
index 0000000000..35af7c55af
--- /dev/null
+++ b/tools/python/xen/xend/osdep.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of version 2.1 of the GNU Lesser General Public
+# License as published by the Free Software Foundation.
+#
+# 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
+#
+
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+
+import os
+
+_scripts_dir = {
+ "Linux": "/etc/xen/scripts",
+ "SunOS": "/usr/lib/xen/scripts",
+}
+
+_xend_autorestart = {
+ "Linux": True,
+ "SunOS": False,
+}
+
+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)
diff --git a/tools/python/xen/xend/server/SrvDaemon.py b/tools/python/xen/xend/server/SrvDaemon.py
index 3f3a90d15a..f883e7da85 100644
--- a/tools/python/xen/xend/server/SrvDaemon.py
+++ b/tools/python/xen/xend/server/SrvDaemon.py
@@ -17,6 +17,7 @@ import traceback
import xen.lowlevel.xc
from xen.xend.XendLogging import log
+from xen.xend import osdep
import relocate
import SrvServer
@@ -168,8 +169,14 @@ class Daemon:
# ready to receive requests. All subsequent restarts we don't
# want this behaviour, or the pipe will eventually fill up, so
# we just pass None into run in subsequent cases (by clearing w
- # in the parent of the first fork).
+ # in the parent of the first fork). On some operating systems,
+ # restart is managed externally, so we won't fork, and just exit.
while True:
+
+ if not osdep.xend_autorestart:
+ self.run(os.fdopen(w, 'w'))
+ break
+
pid = self.fork_pid()
if pid:
if w is not None:
diff --git a/tools/python/xen/xend/server/blkif.py b/tools/python/xen/xend/server/blkif.py
index 927e062e11..9726b43868 100644
--- a/tools/python/xen/xend/server/blkif.py
+++ b/tools/python/xen/xend/server/blkif.py
@@ -81,6 +81,9 @@ class BlkifController(DevController):
'acm_policy' : policy})
devid = blkif.blkdev_name_to_number(dev)
+ if not devid:
+ raise VmError('Unable to find number for device (%s)' % (dev))
+
front = { 'virtual-device' : "%i" % devid,
'device-type' : dev_type
}
diff --git a/tools/python/xen/xm/addlabel.py b/tools/python/xen/xm/addlabel.py
index 86e4ff7b74..af176da433 100644
--- a/tools/python/xen/xm/addlabel.py
+++ b/tools/python/xen/xm/addlabel.py
@@ -72,13 +72,8 @@ def add_resource_label(label, resource, policyref):
# sanity check: make sure this label can be instantiated later on
ssidref = security.label2ssidref(label, policyref, 'res')
- # sanity check on resource name
- (type, file) = resource.split(":")
- if type == "phy":
- file = "/dev/" + file
- if not os.path.exists(file):
- print "Invalid resource '"+resource+"'"
- return
+ #build canonical resource name
+ resource = security.unify_resname(resource)
# see if this resource is already in the file
access_control = {}
diff --git a/tools/python/xen/xm/cfgbootpolicy.py b/tools/python/xen/xm/cfgbootpolicy.py
index 5cb8e83793..c7043dfbc5 100644
--- a/tools/python/xen/xm/cfgbootpolicy.py
+++ b/tools/python/xen/xm/cfgbootpolicy.py
@@ -14,6 +14,7 @@
#============================================================================
# Copyright (C) 2006 International Business Machines Corp.
# Author: Reiner Sailer <sailer@us.ibm.com>
+# Contributions: Stefan Berger <stefanb@us.ibm.com>
#============================================================================
"""Configuring a security policy into the boot configuration
"""
@@ -24,67 +25,60 @@ import tempfile
import os, stat
import shutil
import string
-from xen.util.security import ACMError, err
-from xen.util.security import policy_dir_prefix, boot_filename, xen_title_re
-from xen.util.security import any_title_re, xen_kernel_re, kernel_ver_re, any_module_re
+import re
+from xen.util.security import err
+from xen.util.security import policy_dir_prefix, xen_title_re
+from xen.util.security import boot_filename, altboot_filename
+from xen.util.security import any_title_re, xen_kernel_re, any_module_re
from xen.util.security import empty_line_re, binary_name_re, policy_name_re
from xen.xm.opts import OptionError
def help():
return """
- Adds a 'module' line to the Xen grub.conf entry
- so that xen boots into a specific access control
- policy. If kernelversion is not given, then this
- script tries to determine it by looking for a grub
- entry with a line kernel xen.* If there are multiple
- Xen entries, then it must be called with an explicit
- version (it will fail otherwise).\n"""
+ Adds a 'module' line to the Xen grub configuration file entry
+ so that Xen boots with a specific access control policy. If
+ kernelversion is not given, then this script tries to determine
+ it by looking for a title starting with \"XEN\". If there are
+ multiple entries matching, then it must be called with the unique
+ beginning of the title's name.\n"""
-def determine_kernelversion(user_specified):
- within_xen_title = 0
- within_xen_entry = 0
- version_list = []
- guess_version = None
-
- grub_fd = open(boot_filename)
- for line in grub_fd:
- if xen_title_re.match(line):
- within_xen_title = 1
- elif within_xen_title and xen_kernel_re.match(line):
- within_xen_entry = 1
- elif within_xen_title and within_xen_entry and kernel_ver_re.match(line):
- for i in line.split():
- if (i.find("vmlinuz-") >= 0):
- # skip start until "vmlinuz-"
- guess_version = i[i.find("vmlinuz-") + len("vmlinuz-"):]
- if user_specified:
- if (guess_version == user_specified):
- version_list.append(guess_version)
- else:
- version_list.append(guess_version)
- elif len(line.split()) > 0:
- if line.split()[0] == "title":
- within_xen_title = 0
- within_xen_entry = 0
- if len(version_list) > 1:
- err("Cannot decide between entries for kernels %s" % version_list)
- elif len(version_list) == 0:
- err("Cannot find a boot entry candidate (please create a Xen boot entry first).")
+def strip_title(line):
+ """
+ strips whitespace left and right and cuts 'title'
+ """
+ s_title = string.strip(line)
+ pos = string.index(s_title, "title")
+ if pos >= 0:
+ return s_title[pos+6:]
else:
- return version_list[0]
-
+ return s_title
-def insert_policy(boot_file, kernel_version, policy_name):
+def insert_policy(boot_file, alt_boot_file, user_title, policy_name):
"""
inserts policy binary file as last line of the grub entry
matching the kernel_version version
"""
+ if user_title:
+ #replace "(" by "\(" and ")" by "\)" for matching
+ user_title = string.replace(user_title, "(", "\(")
+ user_title = string.replace(user_title, ")", "\)")
+ user_title_re = re.compile("\s*title\s+.*%s" \
+ % user_title, re.IGNORECASE)
+ else:
+ user_title_re = xen_title_re
+
within_xen_title = 0
within_xen_entry = 0
insert_at_end_of_entry = 0
path_prefix = ''
+ this_title = ''
+ extended_titles = []
(tmp_fd, tmp_grub) = tempfile.mkstemp()
+ #First check whether menu.lst exists
+ if not os.path.isfile(boot_file):
+ #take alternate boot file (grub.conf) instead
+ boot_file = alt_boot_file
#follow symlink since menue.lst might be linked to grub.conf
if stat.S_ISLNK(os.lstat(boot_file)[stat.ST_MODE]):
new_name = os.readlink(boot_file)
@@ -95,30 +89,33 @@ def insert_policy(boot_file, kernel_version, policy_name):
path[len(path)-1] = new_name
boot_file = '/'.join(path)
if not os.path.exists(boot_file):
- err("Boot file \'" + boot_file + "\' not found.")
+ err("Boot file \'%s\' not found." % boot_file)
grub_fd = open(boot_file)
for line in grub_fd:
- if xen_title_re.match(line):
+ if user_title_re.match(line):
+ this_title = strip_title(line)
within_xen_title = 1
elif within_xen_title and xen_kernel_re.match(line):
- within_xen_entry = 1
- elif within_xen_title and within_xen_entry and kernel_ver_re.match(line):
- for i in line.split():
- if (i.find("vmlinuz-") >= 0):
- if kernel_version == i[i.find("vmlinuz-") + len("vmlinuz-"):]:
- insert_at_end_of_entry = 1
- path_prefix = i[0:i.find("vmlinuz-")]
+ insert_at_end_of_entry = 1
+ #use prefix from xen.gz path for policy
+ path_prefix = line.split()[1]
+ idx = path_prefix.rfind('/')
+ if idx >= 0:
+ path_prefix = path_prefix[0:idx+1]
+ else:
+ path_prefix = ''
elif any_module_re.match(line) and insert_at_end_of_entry:
if binary_name_re.match(line):
#delete existing policy module line
line=''
elif any_title_re.match(line):
within_xen_title = 0
- within_xen_entry = 0
- if (empty_line_re.match(line) or any_title_re.match(line)) and insert_at_end_of_entry:
+ if (empty_line_re.match(line) or any_title_re.match(line)) and \
+ insert_at_end_of_entry:
#newline or new title: we insert the policy module line here
os.write(tmp_fd, "\tmodule " + path_prefix + policy_name + ".bin\n")
+ extended_titles.append(this_title)
insert_at_end_of_entry = 0
#write the line that was read (except potential existing policy entry)
os.write(tmp_fd, line)
@@ -126,27 +123,36 @@ def insert_policy(boot_file, kernel_version, policy_name):
if insert_at_end_of_entry:
#last entry, no empty line at end of file
os.write(tmp_fd, "\tmodule " + path_prefix + policy_name + ".bin\n")
+ extended_titles.append(this_title)
+
+ #if more than one entry was changed, abort
+ if len(extended_titles) > 1:
+ err("Following boot entries matched: %s. \nPlease specify "
+ "unique part of the boot title." % extended_titles)
+ if len(extended_titles) == 0:
+ err("Boot entry not found. Please specify unique part "
+ "of the boot title.")
- #temp file might be destroyed when closing it, first copy ...
+ #temp file might be destroyed when closing it, first copy it
shutil.move(boot_file, boot_file+"_save")
shutil.copyfile(tmp_grub, boot_file)
os.close(tmp_fd)
- #temp file did not disappear on my system ...
+ #sometimes the temp file does not disappear
try:
os.remove(tmp_grub)
except:
pass
-
+ return extended_titles[0]
def main(argv):
user_kver = None
- policy = None
+ user_title = None
if len(argv) == 2:
policy = argv[1]
elif len(argv) == 3:
policy = argv[1]
- user_kver = argv[2]
+ user_title = argv[2]
else:
raise OptionError('Invalid number of arguments')
@@ -167,9 +173,10 @@ def main(argv):
dst_binary_policy_file = "/boot/" + policy + ".bin"
shutil.copyfile(src_binary_policy_file, dst_binary_policy_file)
- kernel_version = determine_kernelversion(user_kver)
- insert_policy(boot_filename, kernel_version, policy)
- print "Boot entry created and \'%s\' copied to /boot" % (policy + ".bin")
+ entryname = insert_policy(boot_filename, altboot_filename,
+ user_title, policy)
+ print "Boot entry '%s' extended and \'%s\' copied to /boot" \
+ % (entryname, policy + ".bin")
if __name__ == '__main__':
try:
@@ -177,4 +184,3 @@ if __name__ == '__main__':
except Exception, e:
sys.stderr.write('Error: ' + str(e) + '\n')
sys.exit(-1)
-
diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py
index 6772840096..4b5cd3db7c 100644
--- a/tools/python/xen/xm/create.py
+++ b/tools/python/xen/xm/create.py
@@ -104,6 +104,10 @@ gopts.opt('console_autoconnect', short='c',
fn=set_true, default=0,
use="Connect to the console after the domain is created.")
+gopts.var('vncpasswd', val='NAME',
+ fn=set_value, default=None,
+ use="Password for VNC console on HVM domain.")
+
gopts.var('vncviewer', val='no|yes',
fn=set_bool, default=None,
use="Spawn a vncviewer listening for a vnc server in the domain.\n"
@@ -643,6 +647,7 @@ def configure_hvm(config_image, vals):
for a in args:
if (vals.__dict__[a]):
config_image.append([a, vals.__dict__[a]])
+ config_image.append(['vncpasswd', vals.vncpasswd])
def run_bootloader(vals, config_image):
if not os.access(vals.bootloader, os.X_OK):
diff --git a/tools/python/xen/xm/getlabel.py b/tools/python/xen/xm/getlabel.py
index f86b798771..3be98e82c3 100644
--- a/tools/python/xen/xm/getlabel.py
+++ b/tools/python/xen/xm/getlabel.py
@@ -33,6 +33,9 @@ def help():
def get_resource_label(resource):
"""Gets the resource label
"""
+ #build canonical resource name
+ resource = security.unify_resname(resource)
+
# read in the resource file
file = security.res_label_filename
try:
diff --git a/tools/python/xen/xm/rmlabel.py b/tools/python/xen/xm/rmlabel.py
index 997a4f04f3..0869c6c874 100644
--- a/tools/python/xen/xm/rmlabel.py
+++ b/tools/python/xen/xm/rmlabel.py
@@ -37,6 +37,9 @@ def help():
def rm_resource_label(resource):
"""Removes a resource label from the global resource label file.
"""
+ #build canonical resource name
+ resource = security.unify_resname(resource)
+
# read in the resource file
file = security.res_label_filename
try:
diff --git a/tools/security/example.txt b/tools/security/example.txt
deleted file mode 100644
index c9afe88714..0000000000
--- a/tools/security/example.txt
+++ /dev/null
@@ -1,376 +0,0 @@
-##
-# example.txt <description to the xen access control architecture>
-#
-# Author:
-# Reiner Sailer 08/15/2005 <sailer@watson.ibm.com>
-# 04/07/2006 update to using labels instead of ssidref
-#
-#
-# This file introduces into the tools to manage policies
-# and to label domains and resources.
-##
-
-We will show how to install and use the example one of the client_v1
-policies. Other policies work similarly. Feedback welcome!
-
-
-
-1. Using xm tools to translate example.chwall_ste.client_v1 policy:
-===================================================================
-
-#xm makepolicy example.chwall_ste.client_v1
-
-By default, the tool looks in directory /etc/xen/acm-security/policies
-for a directory that matches the policy name
-(here:example/chwall_ste/client_v1-security_policy.xml) to find the
-policy files. The '-d' option can be used to override the default
-/etc/xen/acm-security/policies policy-root directory.
-
-The default policy directory structure under /etc/xen/acm-security (and
-the Xen security tool build directory - tools/security) looks like:
-
-policies
-|-- security_policy.xsd
-|-- example
- |-- chwall
- | |-- client_v1-security_policy.xml
- |
- |-- chwall_ste
- | |-- client_v1-security_policy.xml
- |
- |-- ste
- |-- client_v1-security_policy.xml
-
-The security_policy.xsd file contains the schema against which the
-policy files must validate during translation.
-
-The policy files, ending in -security_policy.xml, define the policies,
-the types known to the policies, and the label definitions that group
-types together and make them easier to use for users.
-
-After executing the above 'xm makepolicy' command, you will find 2 new
-files in the /etc/xen/acm-security/policies/example/chwall_ste
-sub-directory:
-
- client_v1.map ... this file includes the mapping
- of names from the xml files into their binary code representation.
-
- client_v1.bin ... this is the binary policy file, the result of
- parsing the xml files and using the mapping to create a binary
- version that can be loaded into the hypervisor.
-
-
-
-2. Loading and activating the policy:
-=====================================
-
-We assume that xen is already configured for security;
-please refer to install.txt for instructions.
-
-To activate the policy from the command line:
-
-# xm loadpolicy example.chwall_ste.client_v1
-
-See install.txt for how to install a policy at boot time. This the
-recommended default. You can only load a policy if the currently
-enforced policy is "DEFAULT", a minimal startup policy, or if the
-currently enforced policy has the same name as the new one. Support
-for dynamic policy changes at run-time are a current working item.
-
-
-3. Labeling domains:
-====================
-
-a) Labeling Domain0:
-
-The chwall_ste-security_label_template.xml file includes an attribute
-"bootstrap", which is set to the label name that will be assigned to
-Dom0 (this label will be mapped to ssidref 1/1, the default for Dom0).
-
-b) Labeling User Domains (domains started from dom0 using xm commands):
-
-We distinguish two kinds of labels: a) VM labels (for domains) and RES
-Labels (for resources). We focus here on VM labels. Resource labels
-will be supported later.
-
-To list all available domain labels of a policy, use:
- #xm labels example.chwall_ste.client_v1
-
-To list all available labels including resource labels (their support
-is current work), use:
-
- #xm labels example.chwall_ste.client_v1 type=any
-
-The policy parameter is optional. The currently enforced hypervisor
-policy is used by default.
-
-If you would like to assign the dom_HomeBanking label to one of your user domains,
-look at the hypothetical domain configuration contained in /etc/xen/homebanking.xm:
-
- #------FOR HOME/ONLINE BANKING---------
- kernel = "/boot/vmlinuz-2.6.16-xen"
- ramdisk="/boot/U1_ramdisk.img"
- memory = 164
- name = "homebanking"
- vif=['']
- dhcp = "dhcp"
- #-------------------------
-
-Now we label this domain (policy name is optional, see above):
-
- # xm addlabel homebanking.xm dom_HomeBanking example.chwall_ste.client_v1
-
-The domain configuration should look now like:
-
- # cat homebanking.xm
- #------FOR HOME/ONLINE BANKING---------
- kernel = "/boot/vmlinuz-2.6.16-xen"
- ramdisk="/boot/U1_ramdisk.img"
- memory = 164
- name = "homebanking"
- vif=['']
- dhcp = "dhcp"
- access_control = ['policy=example.chwall_ste.client_v1, label=dom_HomeBanking']
-
-You can see the access_control line that was added to the
-configuration. This label will be translated into a local ssidref when
-a domain is created or resumed (also after migration and
-live-migration). The ssidref is a local security reference that is
-used inside the hypervisor instead of the security label for
-efficiency reasons. Since the same label can be mapped onto different
-ssidrefs in different policy translations (e.g., if the position of
-the label definition is changed in the policy file) or on different
-systems, the ssidref is re-calculated from the label each time a
-domain is instantiated or re-instantiated.
-
-Currently, the labels are not held in the hypervisor but only in
-.map files in the /etc/xen/acm-security/policies subdirectories. Only
-ssidrefs are known inside the hypervisr. This of course can change in
-the future.
-
-
-4. Starting a labeled domain
-============================
-
-Now, start the domain:
-
- #xm create homebanking.xm
- Using config file "homebanking.xm".
- Started domain fun
-
-
-[root@941e-4 VMconfigs]# xm list --label
-
-Name ID Mem(MiB) VCPUs State Time(s) Label
-fun 1 64 1 -b---- 5.9 dom_HomeBanking
-Domain-0 0 1954 1 r----- 1321.4 dom_SystemManagement
-
-
-
-If you label another domain configuration as dom_Fun and if
-you try to start it afterwards, this create will fail.
-
-Why? -- Because the running 'homebanking' domain has the chinese
-wall type "cw_Sensitive". The new domain 'fun' has the chinese wall
-label "cw_Distrusted". These domains are not allowed to run simultaneously
-on the same system because of the defined conflict set
-
- <conflictset name="Protection1">
- <type>cw_Sensitive</type>
- <type>cw_Distrusted</type>
- </conflictset>
-
-(in client_v1-security_policy.xml), which says that only one of the
-types cw_Sensitive and cw_Distrusted can run at a time.
-
-If you save or shutdown the 'homebanking' domain, you will be able to
-start the 'fun' domain. You can look into the Xen log to see if a
-domain was denied to start because of the access control framework
-with the command 'xm dmesg'.
-
-It is important (and usually non-trivial) to define the labels in a
-way that the semantics of the labels are enforced and supported by the
-types and the conflict sets. Usually, a workload abstraction seems
-helpful on the hypervisor level.
-
-Note: While the chinese wall policy enforcement is complete, the type
-enforcement is currently enforced inside the Xen hypervisor
-only. Therefore, only point-to-point sharing with regard to the type
-enforcement is currently controlled. Enforcing the STE policy while
-sharing virtual resources is ongoing work and assumed to be complete
-by year end as well as enforcing the STE policy for network traffic
-routed through dom0.
-
-
-5. Adding your own policies
-===========================
-
-Writing your own policy (e.g. "mypolicy.chwall.test") requires the policy
-definition (types etc.) and the label definitions. Any policy name
-must have chwall, ste, or chwall_ste in its name. This is used by the
-configuration tool to identify existing binary policy entries in the
-boot configuration file (menu.lst, grub.con). This part should, of
-course, be consistent with policy type that is defined.
-
-First, you create
-/etc/xen/acm-security/policies/mypolicy/chwall/test-security_policy.xml.
-
-You need to keep to the schema as defined in
-/etc/xen/acm-security/security_policy.xsd since the translation tools
-are written against this schema.
-
-You can hand-edit the xml files to create your policy or you can use the
-xensec_gen utility.
-
-
-6. Generating policy files using xensec_gen:
-============================================
-
-The xensec_gen utility starts a web-server that can be used to generate the
-XML policy files needed to create a policy.
-
-By default, xensec_gen runs as a daemon and listens on port 7777 for HTTP
-requests. The xensec_gen command supports command line options to change the
-listen port, run in the foreground, and a few others. Type 'xensec_gen -h'
-to see the full list of options available.
-
-Once the xensec_gen utility is running, point a browser at the host and port
-on which the utility is running (e.g. http://localhost:7777/). You will be
-presented with a web page that allows you to create or modify the XML policy
-file:
-
- - The Security Policy types section allows you to create or modify
- the policy types and conflict set definitions
-
- - The Security Policy Labeling section allows you to create or modify a
- label definitions
-
-The policy generation tool allows you to modify an existing policy
-definition or create a new policy definition file. To modify an
-existing policy definition, enter the full path to the existing file
-(the "Browse" button can be used to aid in this) in the Policy File
-entry field. To create a new policy definition file leave the Policy
-File entry field blank. At this point click the "Create" button to
-begin modifying or creating your policy definition.
-
- Security Policy Types Section
- -----------------------------
-
-You will then be presented with a web page. The upper part of it will
-allow you to create either Simple Type Enforcement types or Chinese
-Wall types or both, as well as Chinese Wall conflict type sets.
-
- As an example:
- - To add a Simple Type Enforcement type:
- - Enter the name of a new type under the Simple Type Enforcement Types
- section in the entry field above the "New" button.
- - Click the "New" button and the type will be added to the list of defined
- Simple Type Enforcement types.
- - To remove a Simple Type Enforcement type:
- - Click on the type to be removed in the list of defined Simple Type
- Enforcement types.
- - Click the "Delete" button to remove the type.
-
- Follow the same process to add Chinese Wall types. If you define Chinese Wall
- types you need to define at least one Chinese Wall Conflict Set. The Chinese
- Wall Conflict Set will allow you to add Chinese Wall types from the list of
- defined Chinese Wall types.
-
- Security Policy Labeling:
- -------------------------
-
- The security policy label section of the web page allows you to create labels
- for classes of virtual machines. The input policy type definitions on the upper
- part of the web page will provide the available types (Simple Type Enforcement
- and/or Chinese Wall) that can be assigned to a virtual machine class.
-
- As an example:
- - To add a Virtual Machine class (the name entered will become the label
- that will be used to identify the class):
- - Enter the name of a new class under the Virtual Machine Classes section
- in the entry field above the "New" button.
- - Click the "New" button and the class will be added to the table of defined
- Virtual Machine classes.
- - To remove a Virtual Machine class:
- - Click the "Delete" link associated with the class in the table of Virtual
- Machine classes.
-
- Once you have defined one or more Virtual Machine classes, you will be able to
- add any of the defined Simple Type Enforcement types or Chinese Wall types to a
- particular Virtual Machine.
-
- You must also define which Virtual Machine class is to be associated with the
- bootstrap domain (or Dom0 domain). By default, the first Virtual Machine class
- created will be associated as the bootstrap domain.
-
- To save your policy definition file, click on the "Generate XML" button
- on the top of the page. This will present you with a dialog box to save the
- generated XML file on your system. The default name will be
- security_policy.xml which you should change to follow the policy file
- naming conventions based on the policy name that you choose to use.
-
- To get a feel for the tool, you could use one of the example policy definitions
- files from /etc/xen/acm-security/policies/example as input.
-
-
-7. Hypervisor - OS Security Interface
-=====================================
-
-We currently provide 2 hypercalls through which user operating systems
-can interact with the hypervisor Access Control Module. Examples of
-using them are under "xen_root"/tools/security/python/xensec_tools:
-
-
-I) acm_getdecision -i domainid -l labelname
- Call this example script without arguments to show its usage
- information.
-
- This script enables a domain to retrieve an access control decision
- regarding the STE policy from the hypervisor. It will be used to
- control access to virtual/real resources in hosting domains.
-
- The script can be provided with any combination of domain ids or
- labelnames. Before calling into the hypervisor, labels are translated
- into ssidrefs. The hypervisor then retrieves for any domain id
- paramter the ssidref before deciding access.
-
- Example:
- #/etc/xen/acm-security/scripts/acm_getdecision -l dom_Fun
- -l dom_SystemManagement
- PERMITTED
-
- #/etc/xen/acm-security/scripts/acm_getdecision -i 0 -i 1
- PERMITTED
-
- #/etc/xen/acm-security/scripts/acm_getdecision -i 0 -l dom_Fun
- PERMITTED
-
- #/etc/xen/acm-security/scripts/acm_getdecision -i 0 -l no_label
- ACMError: Label 'nolabel' not found.
-
- Now, assume domain 123454 does not exist:
- #/etc/xen/acm-security/scripts/acm_getdecision -i 123454 -l dom_Fun
- ACMError: Cannot determine decision (Invalid parameter).
-
- Return values:
- * DENIED: access is denied based on the current hypervisor
- policy
-
- * PERMITTED: access is permitted based on the current
-
- * Exception ACMError: one of the parameters was illegal,
- i.e. an unknown label or a
- non-existing domain id
-
-I) acm_getlabel -i domainid
- Retrieves the label of a runing domain. This function can be used
- by domains to determine their own label or (if authorized) the label
- other domains.
-
- Example (result is broken up into different lines to simplify description):
- # /etc/xen/acm-security/scripts/acm_getlabel -i 0
- ('example.chwall.client_v1', <--- policy describing labels etc.
- 'dom_SystemManagement', <--- label name of the domain
- 'CHINESE WALL', <--- policy type
- 65537) <--- hypervisor internal ssidref
-
diff --git a/tools/security/install.txt b/tools/security/install.txt
deleted file mode 100644
index ebdf84f7d4..0000000000
--- a/tools/security/install.txt
+++ /dev/null
@@ -1,87 +0,0 @@
-##
-# install.txt <description to the xen access control architecture>
-#
-# Author:
-# Reiner Sailer 08/15/2005 <sailer@watson.ibm.com>
-# 03/18/2006 update: new labeling
-#
-#
-# This file shows how to activate and install the access control
-# framework for Xen.
-##
-
-
-INSTALLING A SECURITY POLICY IN XEN
-===================================
-
-By default, the access control architecture is disabled in Xen. To
-enable the access control architecture in Xen follow the steps below.
-This description assumes that you want to install the Chinese Wall and
-Simple Type Enforcement policy. Some file names need to be replaced
-below to activate the Chinese Wall OR the Type Enforcement policy
-exclusively (chwall_ste --> {chwall, ste}).
-
-0. build and install the xm man page. It includes the description of
- available management commands for the security policy for Xen and
- the labeling of domains. If not installed by default, you can make
- and install the xm man page as follows:
- # cd "xen_root"/doc
- # make install
- Then, use man xm to read it:
- # man xm
-
-1. enable access control in Xen
- # cd "xen_root"
- # edit/xemacs/vi Config.mk
-
- change the lines:
- ACM_SECURITY ?= n
- to:
- ACM_SECURITY ?= y
-
- Now the hypervisor will boot into the policy that is specified
- in the grub configuration. If you would like to boot into a
- specific policy (even if you can't specify a boot policy but
- need to set the policy later using the 'xensec_tool
- loadpolicy'), then use the other config parameter to change
- from NULL to any other default policy, e.g.:
- ACM_DEFAULT_SECURITY_POLICY ?= ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY
-
- # make dist
- # ./install.sh
-
-2. Build acm and policy tools and create boot-able policy:
- # cd tools/security
- # make install
-
- For description of the following commands, please see the xm
- man page (docs/man1/xm.1). If it is not built, then you can
- create it manually: cd "xen_root"/docs; make; man man1/xm.1
-
- Step1: Building binary version of an example policy:
- # xm makepolicy example.chwall_ste.client_v1
- # xm cfgbootpolicy example.chwall_ste.client_v1
-
- Please verify boot entry in /boot/grub/grub.conf (or menu.lst):
- title Xen (2.6.16)
- root (hd0,0)
- kernel /xen.gz dom0_mem=2000000 console=vga
- module /vmlinuz-2.6.16-xen ro root=/dev/VolGroup00/LogVol00 rhgb
- module /initrd-2.6.165-xen-U.img
- module /example.chwall_ste.client_v1.bin
-
-3. reboot into the newly compiled hypervisor
-
- after boot
- # xm dmesg should show an entry about the policy being loaded
- during the boot process
-
- # xm dumppolicy
- should print the new binary policy representation
- including the policy name example.chwall_ste.client_v1
-
- # xm list --label
- should show security label names behind the running domains
-
-For more information about how to use the security-enabled Xen, see
-the examples.txt file in this directory.
diff --git a/tools/security/policy.txt b/tools/security/policy.txt
index 4888577a1a..493d1f2e55 100644
--- a/tools/security/policy.txt
+++ b/tools/security/policy.txt
@@ -1,131 +1,13 @@
##
-# policy.txt <description to the Xen access control architecture>
+# policy.txt <description to the sHype/Xen access control architecture>
#
# Author:
-# Reiner Sailer 08/15/2005 <sailer@watson.ibm.com>
+# Reiner Sailer 08/30/2006 <sailer@watson.ibm.com>
#
#
-# This file gives an overview of the security policies currently
-# provided and also gives some reasoning about how to assign
-# labels to domains.
+# This file gives an overview of the example security policies.
##
-Xen access control policies
-
-
-General explanation of supported security policies:
-=====================================================
-
-We have implemented the mandatory access control architecture of our
-hypervisor security architecture (sHype) for the Xen hypervisor. It
-controls communication (in Xen: event channels, grant tables) between
-Virtual Machines (from here on called domains) and through this the
-virtual block devices, networking, and shared memory are implemented
-on top of these communication means. While we have implemented the
-described policies and access control architecture for other
-hypervisor systems, we will describe below specifically its
-implementation and use in the Xen hypervisor. The policy enforcement
-is called mandatory regarding user domains since the policy it is
-given by the security administration and enforced independently of the
-user domains by the Xen hypervisor in cooperation with the domain
-management.
-
-The access control architecture consists of three parts:
-
-i) The access control policy determines the "command set" of the ACM
-and the hooks with which they can be configured to constrain the
-sharing of virtual resources. The current access control architecture
-implemented for Xen supports two policies: Chinese Wall and Simple
-Type Enforcement, which we describe in turn below.
-
-
-ii) The actually enforced policy instantiation uses the policy
-language (i) to configure the Xen access control in a way that suits
-the specific application (home desktop environment, company desktop,
-Web server system, etc.). We have defined an exemplary policy
-instantiation for Chinese Wall (chwall policy) and Simple Type
-Enforcement (ste policy) for a desktop system. We offer these policies
-in combination since they are controlling orthogonal events.
-
-
-iii) The access control module (ACM) and related hooks are part of the
-core hypervisor and their controls cannot be bypassed by domains. The
-ACM and hooks are the active security components. We refer to
-publications that describe how access control is enforced in the Xen
-hypervisor using the ACM (access decision) and the hooks (decision
-enforcement) inserted into the setup of event channels and grant
-tables, and into domain operations (create, destroy, save, restore,
-migrate). These controls decide based on the active policy
-configuration (see i. and ii.) if the operation proceeds of if the
-operation is aborted (denied).
-
-In general, security policy instantiations in the Xen access control
-framework are defined by XML policy files. Each security policy has
-exactly one file including all the information the hypervisor needs to
-enforce the policy.
-
-The name of a policy is unique and consists of a colon-separated list
-of names, which can be translated into the location (subtree) where
-this policy must be located. The last part of the name is the file
-name pre-fix for the policy xml file. The preceding name parts are
-translated into the local path relative to the global policy root
-(/etc/xen/acm-security/policies) pointing to the policy xml file. For
-example: example.chwall_ste.client_v1 denotes the policy file
-example/chwall_ste/client_v1-security_policy.xml relative to the
-global policy root directory.
-
-Every security policy has its own sub-directory under the global
-policy root directory /etc/xen/acm-security/policies, which is
-installed during the Xen installation or can be manually installed
-(when switching from a "security disabled" Xen to a "security enabled"
-Xen AFTER configuring security, see install.txt) by the command
-sequence:
-
- cd "Xen-root"/tools/security/policies; make install
-
-We will describe those files for our example policy (Chinese Wall and
-Simple Type Enforcement) in more detail as we go along. Eventually, we
-will move towards a system installation where the policies will reside
-under /etc.
-
-
-CHINESE WALL
-============
-
-The Chinese Wall policy enables the user to define "which workloads
-(domain payloads) cannot run on a single physical system at the same
-time". Why would we want to prevent workloads from running at the same
-time on the same system? This supports requirements that can (but
-don't have to) be rooted in the measure of trust into the isolation of
-different domains that share the same hardware. Since the access
-control architecture aims at high performance and non-intrusive
-implementation, it currently does not address covert (timing) channels
-and aims at medium assurance. Users can apply the Chinese Wall policy
-to guarantee an air-gap between very sensitive payloads both regarding
-covert information channels and regarding resource starvation.
-
-To enable the CW control, each domain is labeled with a set of Chinese
-Wall types and CW Conflict Sets are defined which include those CW
-types that cannot run simultaneously on the same hardware. This
-interpretation of conflict sets is the only policy rule for the Chines
-Wall policy.
-
-This is enforced by controlling the start of domains according to
-their assigned CW worload types. Domains with Chinese Wall types that
-appear in a common conflict set are running mutually exclusive on a
-platform, i.e., once a domain with one of the cw-types of a conflict
-set is running, no domain with another cw-type of the same conflict
-set can start until the first domain is destroyed, paused, or migrated
-away from the physical system (this assumes that such a partition can
-no longer be observed). The idea is to assign cw-types according to
-the type of payload that a domain runs and to use the Chinese Wall
-policy to ensure that payload types can be differentiated by the
-hypervisor and can be prevented from being executed on the same system
-at the same time. Using the flexible CW policy maintains system
-consolidation and workload-balancing while introducing guaranteed
-constraints where necessary.
-
-
Example of a Chinese Wall Policy Instantiation
----------------------------------------------
@@ -233,13 +115,12 @@ Currently in Xen, Dom0 controls all hardware, needs to communicate
with all domains during their setup, and intercepts all communication
between domains. Consequently, Dom0 needs to be assigned all types
used and must be completely trusted to maintain the separation of
-informatio ncoming from domains with different STE types. Thus a
+information coming from domains with different STE types. Thus a
refactoring of Dom0 is recommended for stronger confinement
guarantees.
Domain --> RESOURCES Access
'''''''''''''''''''''''''''
-(current work)
We define for each resource that we want to distinguish a separate STE
type. Each STE type is assigned to the respective resource and to
@@ -266,8 +147,7 @@ maximum security benefit from sHype.
Example of a Simple Type Enforcement Policy Instantiation
---------------------------------------------------------
-
-We define the following types:
+The example policies define the following types:
* ste_SystemManagement identifies workloads (and domains that runs
them) that must share information to accomplish the management of the
@@ -384,19 +264,18 @@ Xen components and these components use a single consistent policy to
co-operatively enforce the policy. In the storage domain example, we
have three components that co-operate:
-1. The ACM module inside the hypervisor enforces: communication between
-user domains and the storage domain (only domains including types
-ste_PersonalFinances or ste_InternetInsecure can communicate with the
-storage domain and request access to logical resource). This confines
-the sharing to the types assigned to the storage domain.
+1. The ACM module inside the hypervisor enforces: communication
+between user domains and the storage domain (only domains including
+types ste_PersonalFinances or ste_InternetInsecure can communicate
+with the storage domain and request access to logical resource). This
+confines the sharing to the types assigned to the storage domain.
-2. The domain management will enforce (work in progress): assignment of
-real resources (hda) to domains (storage domain) that share a
-type with the resource.
+2. The domain management enforces: assignment of real resources (hda)
+to domains (storage domain) that share a type with the resource.
-3. If the storage domain serves multiple STE types (as in our example),
-it enforces (work in progress): that domains can access (mount)
-logical resources only if they share an STE type with the respective
+3. If the storage domain serves multiple STE types (as in our
+example), it enforces: that domains can access (mount) logical
+resources only if they share an STE type with the respective
resource. In our example, domains with the STE type
ste_PersonalFinances can request access (mount) to logical resource
hda1 from the storage domain.
@@ -406,8 +285,8 @@ see the minimal set of types assigned to our domain manageing disk
drive hda for serving logical disk partitions exclusively to
dom_HomeBanking and dom_Fun.
-Similary, network domains can confine access to the network or
-network communication between user domains.
+Similary, network domains can confine access to the network or network
+communication between user domains.
As a result, device domains (e.g., storage domain, network domain)
must be simple and small to ensure their correct co-operation in the
diff --git a/tools/security/policytools.txt b/tools/security/policytools.txt
new file mode 100644
index 0000000000..fb863f4722
--- /dev/null
+++ b/tools/security/policytools.txt
@@ -0,0 +1,148 @@
+##
+# policytools.txt
+# <description to the sHype/Xen policy management tools>
+#
+# Author:
+# Reiner Sailer 08/31/2006 <sailer@watson.ibm.com>
+#
+#
+##
+
+This file describes the Xen-tools to create and maintain security
+policies for the sHype/Xen access control module.
+
+A security policy (e.g. "example.chwall_ste.test") is defined in
+XML. Read in the user manual about the naming of policies. The policy
+name is used by the Xen management tools to identify existing
+policies. Creating the security policy means creating a policy
+description in XML:
+/etc/xen/acm-security/policies/example/chwall_ste/test-security_policy.xml.
+
+The policy XML description must follow the XML schema definition in
+/etc/xen/acm-security/policies/security_policy.xsd. The policy tools
+are written against this schema; they will create and refine policies
+that conform to this scheme.
+
+Two tools are provided to help creating security policies:
+
+
+1. xensec_ezpolicy: The starting point for writing security policies.
+===================
+
+This wxPython-based GUI tool is meant to create very quickly a
+starting point for a workload protection security policy. Please start
+the tool (xensec_ezpolicy) and press <CTRL-h> for usage explanations.
+The Xen User guide explains its usage at an example in chapter
+"sHype/Xen Access Control".
+
+The output of the tool is a security policy that is fully operable. It
+is sufficient to create policies that demonstrate how sHype/ACM works.
+
+However, it defines only a basic set of security labels assuming that
+Domain0 hosts and virtualizes all hardware (storage etc.). Use
+xensec_gen to refine this policy and tailor it to your requirements.
+
+
+2. xensec_gen: The tool to refine a basic security policy:
+==============
+
+The xensec_gen utility starts a web-server that can be used to
+generate the XML policy files needed to create or maintain a
+policy. It can be pre-loaded with a policy file created by
+xensec_ezpolicy.
+
+By default, xensec_gen runs as a daemon and listens on port 7777 for
+HTTP requests. The xensec_gen command supports command line options
+to change the listen port, run in the foreground, and a few others.
+Type 'xensec_gen -h' to see the full list of options available.
+
+Once the xensec_gen utility is running, point a browser at the host
+and port on which the utility is running (e.g. http://localhost:7777).
+You will be presented with a web page that allows you to create or
+modify the XML policy file:
+
+ - The Security Policy types section allows you to create or modify
+the policy types and conflict set definitions
+
+ - The Security Policy Labeling section allows you to create or
+modify label definitions
+
+The policy generation tool allows you to modify an existing policy
+definition or create a new policy definition file. To modify an
+existing policy definition, enter the full path to the existing file
+(the "Browse" button can be used to aid in this) in the Policy File
+entry field. To create a new policy definition file leave the Policy
+File entry field blank. At this point click the "Create" button to
+begin modifying or creating your policy definition.
+
+ Security Policy Types Section
+ -----------------------------
+
+You will then be presented with a web page. The upper part of it will
+allow you to create either Simple Type Enforcement types or Chinese
+Wall types or both, as well as Chinese Wall conflict sets.
+
+As an example, to add a Simple Type Enforcement type:
+
+- Enter the name of a new type under the Simple Type Enforcement Types
+section in the entry field above the "New" button.
+
+- Click the "New" button and the type will be added to the list of
+defined Simple Type Enforcement types.
+
+To remove a Simple Type Enforcement type:
+
+- Click on the type to be removed in the list of defined Simple Type
+Enforcement types.
+
+- Click the "Delete" button to remove the type.
+
+Follow the same process to add Chinese Wall types. The Chinese Wall
+Conflict Set allows you to add Chinese Wall types from the list of
+defined Chinese Wall types.
+
+
+ Security Policy Labels:
+ -------------------------
+
+The security policy label section of the web page allows you to create
+labels for classes of virtual machines and resources. The input
+policy type definitions on the upper part of the web page will provide
+the available types (Simple Type Enforcement and/or Chinese Wall) that
+can be assigned to a virtual machine class. Resource classes only
+include simple type enforcement types; the Chinese Wall policy does
+apply only to virtual machines.
+
+As an example, to add a Virtual Machine class (the name entered will
+become the label that will be used to identify the class):
+
+- Enter the name of a new class under the Virtual Machine Classes
+section in the entry field above the "New" button.
+
+- Click the "New" button and the class will be added to the table of
+defined Virtual Machine classes.
+
+To remove a Virtual Machine class:
+
+- Click the "Delete" link associated with the class in the table of
+Virtual Machine classes.
+
+Once you have defined one or more Virtual Machine classes, you will
+be able to add any of the defined Simple Type Enforcement types or
+Chinese Wall types to a particular Virtual Machine.
+
+If you create a new policy, you must also define which Virtual Machine
+class is to be associated with the bootstrap domain (or Dom0 domain).
+By default, the first Virtual Machine class created will be associated
+as the bootstrap domain.
+
+To save your policy definition file, click on the "Generate XML"
+button on the top of the page. This will present you with a dialog
+box to save the generated XML file on your system. The default name
+will be security_policy.xml which you should change to follow the
+policy file naming conventions based on the policy name that you
+choose to use.
+
+To get a feel for the tool, you could use one of the example policy
+definitions files from /etc/xen/acm-security/policies/example as
+input or a policy created by the xensec_ezpolicy tool.
diff --git a/tools/security/readme.txt b/tools/security/readme.txt
index 9d8e18a4ec..991359a53a 100644
--- a/tools/security/readme.txt
+++ b/tools/security/readme.txt
@@ -1,34 +1,33 @@
##
-# readme.txt <description to the xen access control architecture>
+# readme.txt <description to the sHype/Xen access control architecture>
#
# Author:
-# Reiner Sailer 08/15/2005 <sailer@watson.ibm.com>
+# Reiner Sailer 08/30/2006 <sailer@watson.ibm.com>
#
#
# This file is a toc for information regarding
# the access control policy and tools in Xen.
##
-1. 'xm' man page
+1. Xen User Guide
- describes the commands related to Xen management, including the
- commands to manage security policies and labels. Read the access
- control subcommand section of the xm manual first. If it is not
- built by default, check install.txt.
+ describes how to configure, install, and deploy the sHype Access
+ Control Module in Xen. See chapter "sHype/Xen Access Control".
-2. policy.txt:
+2. 'xm' man page
- describes the general reasoning and examples for access
- control policies in Xen
+ describes the commands related to Xen management, including the
+ commands to manage security policies and labels. Read the access
+ control subcommand section of the xm manual first.
+3. policy.txt
-3. install.txt
+ describes examples for access control policies in Xen. First read
+ the policy description in the Xen User Guide.
- describes the activation of the access control framework
- in Xen
-4. example.txt
+4. policytools.txt
- describes the available tools for managing security policies
- in Xen and the tools to label domains
+ describes the available tools for creating and managing security
+ policies in Xen.
diff --git a/tools/security/secpol_tool.c b/tools/security/secpol_tool.c
index 901beae9d5..470de4f25b 100644
--- a/tools/security/secpol_tool.c
+++ b/tools/security/secpol_tool.c
@@ -43,6 +43,8 @@
fprintf(stderr, "ERROR: " _m " (%d = %s)\n" , ## _a , \
errno, strerror(errno))
+#define ALIGN8(x) (void *)(((long)(x) + 7) & ~7)
+
void usage(char *progname)
{
printf("Usage: %s ACTION\n"
@@ -182,14 +184,14 @@ void acm_dump_policy_buffer(void *buf, int buflen)
ntohl(pol->secondary_buffer_offset));
switch (ntohl(pol->primary_policy_code)) {
case ACM_CHINESE_WALL_POLICY:
- acm_dump_chinesewall_buffer(buf +
- ntohl(pol->primary_buffer_offset),
+ acm_dump_chinesewall_buffer(ALIGN8(buf +
+ ntohl(pol->primary_buffer_offset)),
ntohl(pol->len) -
ntohl(pol->primary_buffer_offset));
break;
case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
- acm_dump_ste_buffer(buf + ntohl(pol->primary_buffer_offset),
+ acm_dump_ste_buffer(ALIGN8(buf + ntohl(pol->primary_buffer_offset)),
ntohl(pol->len) -
ntohl(pol->primary_buffer_offset));
break;
@@ -204,14 +206,14 @@ void acm_dump_policy_buffer(void *buf, int buflen)
switch (ntohl(pol->secondary_policy_code)) {
case ACM_CHINESE_WALL_POLICY:
- acm_dump_chinesewall_buffer(buf +
- ntohl(pol->secondary_buffer_offset),
+ acm_dump_chinesewall_buffer(ALIGN8(buf +
+ ntohl(pol->secondary_buffer_offset)),
ntohl(pol->len) -
ntohl(pol->secondary_buffer_offset));
break;
case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
- acm_dump_ste_buffer(buf + ntohl(pol->secondary_buffer_offset),
+ acm_dump_ste_buffer(ALIGN8(buf + ntohl(pol->secondary_buffer_offset)),
ntohl(pol->len) -
ntohl(pol->secondary_buffer_offset));
break;
diff --git a/tools/security/secpol_xml2bin.c b/tools/security/secpol_xml2bin.c
index 477991f28c..c316250e41 100644
--- a/tools/security/secpol_xml2bin.c
+++ b/tools/security/secpol_xml2bin.c
@@ -979,13 +979,15 @@ unsigned char *write_policy_reference_binary(u_int32_t * len_pr)
unsigned char *buf, *ptr;
struct acm_policy_reference_buffer *pr_header;
u_int32_t len;
+ u_int32_t name_len;
if (policy_reference_name == NULL) {
printf("ERROR: No policy reference name found.\n");
exit(EXIT_FAILURE);
}
- len = (sizeof(struct acm_policy_reference_buffer) +
- strlen(policy_reference_name) + 1);
+ name_len = strlen(policy_reference_name) + 1; /* strend '\0' */
+ len = sizeof(struct acm_policy_reference_buffer) + name_len;
+ len = (len + 7) & ~7; /* Alignment. */
buf = malloc(len);
ptr = buf;
@@ -994,9 +996,9 @@ unsigned char *write_policy_reference_binary(u_int32_t * len_pr)
("ERROR: out of memory allocating label reference buffer.\n");
exit(EXIT_FAILURE);
}
+ memset (buf, 0, len);
pr_header = (struct acm_policy_reference_buffer *) buf;
- pr_header->len =
- htonl(strlen(policy_reference_name) + 1 /* strend \'0' */ );
+ pr_header->len = htonl(name_len);
ptr += sizeof(struct acm_policy_reference_buffer);
strcpy((char *) ptr, policy_reference_name);
diff --git a/tools/vnet/doc/Makefile b/tools/vnet/doc/Makefile
index 67f70ab68d..38accfa7f6 100644
--- a/tools/vnet/doc/Makefile
+++ b/tools/vnet/doc/Makefile
@@ -1,12 +1,11 @@
#!/usr/bin/make -f
# -*- mode: Makefile; -*-
+XEN_ROOT = ../../..
+include $(XEN_ROOT)/tools/Rules.mk
VERSION = 1.0
HEADER = Vnet
-INSTALL = install
-INSTALL_DIR = $(INSTALL) -d -m0755
-
PS2PDF := ps2pdf
DVIPS := dvips
LATEX := latex
diff --git a/tools/vnet/examples/Makefile b/tools/vnet/examples/Makefile
index ba605ca318..c3aab0c70e 100644
--- a/tools/vnet/examples/Makefile
+++ b/tools/vnet/examples/Makefile
@@ -1,9 +1,7 @@
# -*- mode: Makefile; -*-
#============================================================================
-
-INSTALL = install
-INSTALL_PROG = $(INSTALL) -m0755
-INSTALL_DIR = $(INSTALL) -d -m0755
+XEN_ROOT = ../../..
+include $(XEN_ROOT)/tools/Rules.mk
XEN_SCRIPT_DIR = $(DESTDIR)/etc/xen/scripts
diff --git a/tools/vnet/libxutil/Makefile b/tools/vnet/libxutil/Makefile
index b8661276d8..80cbe4443e 100644
--- a/tools/vnet/libxutil/Makefile
+++ b/tools/vnet/libxutil/Makefile
@@ -3,11 +3,6 @@ export VNET_ROOT = $(shell cd .. && pwd)
include $(VNET_ROOT)/Make.env
endif
-INSTALL = install
-INSTALL_DATA = $(INSTALL) -m0644
-INSTALL_PROG = $(INSTALL) -m0755
-INSTALL_DIR = $(INSTALL) -d -m0755
-
include $(XEN_ROOT)/tools/Rules.mk
LIB_SRCS :=
@@ -60,7 +55,7 @@ libxutil.so.$(MAJOR): libxutil.so.$(MAJOR).$(MINOR)
ln -sf $^ $@
libxutil.so.$(MAJOR).$(MINOR): $(PIC_OBJS)
- $(CC) $(CFLAGS) -Wl,-soname -Wl,libxutil.so.$(MAJOR) -shared -o $@ $^
+ $(CC) $(CFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxutil.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $^
libxutil.a: $(LIB_OBJS)
$(AR) rc $@ $^
diff --git a/tools/vnet/scripts/Makefile b/tools/vnet/scripts/Makefile
index 077d6b6224..24f6f35880 100644
--- a/tools/vnet/scripts/Makefile
+++ b/tools/vnet/scripts/Makefile
@@ -1,9 +1,7 @@
# -*- mode: Makefile; -*-
#============================================================================
-
-INSTALL = install
-INSTALL_PROG = $(INSTALL) -m0755
-INSTALL_DIR = $(INSTALL) -d -m0755
+XEN_ROOT = ../../..
+include $(XEN_ROOT)/tools/Rules.mk
SBIN_DIR = $(DESTDIR)/usr/sbin
diff --git a/tools/vnet/vnetd/Makefile b/tools/vnet/vnetd/Makefile
index 93e6dbce43..530284c218 100644
--- a/tools/vnet/vnetd/Makefile
+++ b/tools/vnet/vnetd/Makefile
@@ -110,7 +110,7 @@ vnetd: $(VNETD_OBJ)
.PHONY: install
install: vnetd
mkdir -p $(DESTDIR)$(VNETD_INSTALL_DIR)
- install -m 0755 vnetd $(DESTDIR)$(VNETD_INSTALL_DIR)
+ $(INSTALL_PROG) vnetd $(DESTDIR)$(VNETD_INSTALL_DIR)
.PHONY: clean
clean:
diff --git a/tools/vtpm/Rules.mk b/tools/vtpm/Rules.mk
index 9ce85dc316..8eb1a3c343 100644
--- a/tools/vtpm/Rules.mk
+++ b/tools/vtpm/Rules.mk
@@ -5,11 +5,6 @@ include $(XEN_ROOT)/tools/Rules.mk
# Tool definitions
#
-# Installation program and options
-INSTALL = install
-INSTALL_PROG = $(INSTALL) -m0755
-INSTALL_DIR = $(INSTALL) -d -m0755
-
# Xen tools installation directory
TOOLS_INSTALL_DIR = $(DESTDIR)/usr/bin
diff --git a/tools/vtpm_manager/Rules.mk b/tools/vtpm_manager/Rules.mk
index 3435afed38..68c2a26ff7 100644
--- a/tools/vtpm_manager/Rules.mk
+++ b/tools/vtpm_manager/Rules.mk
@@ -5,11 +5,6 @@ include $(XEN_ROOT)/tools/Rules.mk
# Tool definitions
#
-# Installation program and options
-INSTALL = install
-INSTALL_PROG = $(INSTALL) -m0755
-INSTALL_DIR = $(INSTALL) -d -m0755
-
# Xen tools installation directory
TOOLS_INSTALL_DIR = $(DESTDIR)/usr/bin
diff --git a/tools/xcutils/Makefile b/tools/xcutils/Makefile
index 24031a1688..6022505577 100644
--- a/tools/xcutils/Makefile
+++ b/tools/xcutils/Makefile
@@ -8,10 +8,6 @@
# Copyright (C) 2005 by Christian Limpach
#
-INSTALL = install
-INSTALL_PROG = $(INSTALL) -m0755
-INSTALL_DIR = $(INSTALL) -d -m0755
-
XEN_ROOT = ../..
include $(XEN_ROOT)/tools/Rules.mk
@@ -37,7 +33,7 @@ all: build
build: $(PROGRAMS)
$(PROGRAMS): %: %.o
- $(LINK.o) $^ $(LDLIBS) -o $@
+ $(CC) $(CFLAGS) $^ $(LDLIBS) -o $@
.PHONY: install
install: build
diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c
index af4162a558..cbd177a88f 100644
--- a/tools/xcutils/readnotes.c
+++ b/tools/xcutils/readnotes.c
@@ -56,7 +56,8 @@ static void print_numeric_note(const char *prefix,Elf_Nhdr *note)
prefix, *(uint64_t *)ELFNOTE_DESC(note));
break;
default:
- printf("%s: unknown data size %#x\n", prefix, note->n_descsz);
+ printf("%s: unknown data size %#lx\n", prefix,
+ (unsigned long)note->n_descsz);
break;
}
}
@@ -301,7 +302,8 @@ int main(int argc, char **argv)
print_string_note("FEATURES", note);
break;
default:
- printf("unknown note type %#x\n", note->n_type);
+ printf("unknown note type %#lx\n",
+ (unsigned long)note->n_type);
break;
}
}
diff --git a/tools/xenmon/Makefile b/tools/xenmon/Makefile
index 3d46dbe548..725567d619 100644
--- a/tools/xenmon/Makefile
+++ b/tools/xenmon/Makefile
@@ -10,16 +10,11 @@
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-INSTALL = install
-INSTALL_PROG = $(INSTALL) -m0755
-INSTALL_DIR = $(INSTALL) -d -m0755
-INSTALL_DATA = $(INSTALL) -m0644
-
-sbindir=/usr/sbin
-
XEN_ROOT=../..
include $(XEN_ROOT)/tools/Rules.mk
+sbindir=/usr/sbin
+
CFLAGS += -Werror -g
CFLAGS += -I $(XEN_XC)
CFLAGS += -I $(XEN_LIBXC)
diff --git a/tools/xenstat/libxenstat/Makefile b/tools/xenstat/libxenstat/Makefile
index 7eea316133..8cb77f17bc 100644
--- a/tools/xenstat/libxenstat/Makefile
+++ b/tools/xenstat/libxenstat/Makefile
@@ -16,10 +16,6 @@ XEN_ROOT=../../..
include $(XEN_ROOT)/tools/Rules.mk
LINUX_ROOT := $(XEN_ROOT)/linux-2.6-xen-sparse
-INSTALL = install
-INSTALL_PROG = $(INSTALL) -m0755 -D
-INSTALL_DATA = $(INSTALL) -m0644 -D
-
prefix=/usr
includedir=$(prefix)/include
libdir=$(prefix)/lib
@@ -34,7 +30,7 @@ LIB=src/libxenstat.a
SHLIB=src/libxenstat.so.$(MAJOR).$(MINOR)
SHLIB_LINKS=src/libxenstat.so.$(MAJOR) src/libxenstat.so
OBJECTS=src/xenstat.o
-SONAME_FLAGS=-Wl,-soname -Wl,libxenstat.so.$(MAJOR)
+SONAME_FLAGS=-Wl,$(SONAME_LDFLAG) -Wl,libxenstat.so.$(MAJOR)
WARN_FLAGS=-Wall -Werror
@@ -49,7 +45,7 @@ $(LIB): $(OBJECTS)
$(RANLIB) $@
$(SHLIB): $(OBJECTS)
- $(CC) $(CFLAGS) $(LDFLAGS) $(SONAME_FLAGS) -shared -o $@ $(OBJECTS) \
+ $(CC) $(CFLAGS) $(LDFLAGS) $(SONAME_FLAGS) $(SHLIB_CFLAGS) -o $@ $(OBJECTS) \
-lxenstore -lxenctrl
src/xenstat.o: src/xenstat.c src/xenstat.h
@@ -101,7 +97,7 @@ $(PYSRC) $(PYMOD): bindings/swig/xenstat.i
swig -python $(SWIG_FLAGS) -outdir $(@D) -o $(PYSRC) $<
$(PYLIB): $(PYSRC)
- $(CC) $(CFLAGS) $(LDFLAGS) $(PYTHON_FLAGS) -shared -lxenstat -o $@ $<
+ $(CC) $(CFLAGS) $(LDFLAGS) $(PYTHON_FLAGS) $(SHLIB_CFLAGS) -lxenstat -o $@ $<
python-bindings: $(PYLIB) $(PYMOD)
@@ -122,7 +118,7 @@ $(PERLSRC) $(PERLMOD): bindings/swig/xenstat.i
swig -perl $(SWIG_FLAGS) -outdir $(@D) -o $(PERLSRC) $<
$(PERLLIB): $(PERLSRC)
- $(CC) $(CFLAGS) $(LDFLAGS) $(PERL_FLAGS) -shared -lxenstat -o $@ $<
+ $(CC) $(CFLAGS) $(LDFLAGS) $(PERL_FLAGS) $(SHLIB_CFLAGS) -lxenstat -o $@ $<
.PHONY: perl-bindings
perl-bindings: $(PERLLIB) $(PERLMOD)
diff --git a/tools/xenstat/xentop/Makefile b/tools/xenstat/xentop/Makefile
index 273cb31e4e..2248bfb3c3 100644
--- a/tools/xenstat/xentop/Makefile
+++ b/tools/xenstat/xentop/Makefile
@@ -18,10 +18,6 @@ ifneq ($(XENSTAT_XENTOP),y)
all install xentop:
else
-INSTALL = install
-INSTALL_PROG = $(INSTALL) -m0755 -D
-INSTALL_DATA = $(INSTALL) -m0644 -D
-
prefix=/usr
mandir=$(prefix)/share/man
man1dir=$(mandir)/man1
@@ -29,7 +25,7 @@ sbindir=$(prefix)/sbin
CFLAGS += -DGCC_PRINTF -Wall -Werror -I$(XEN_LIBXENSTAT)
LDFLAGS += -L$(XEN_LIBXENSTAT)
-LDLIBS += -lxenstat -lncurses
+LDLIBS += -lxenstat $(CURSES_LIBS) $(SOCKET_LIBS)
.PHONY: all
all: xentop
@@ -37,6 +33,7 @@ all: xentop
.PHONY: install
install: xentop xentop.1
$(INSTALL_PROG) xentop $(DESTDIR)$(sbindir)/xentop
+ $(INSTALL_DIR) $(DESTDIR)$(man1dir)
$(INSTALL_DATA) xentop.1 $(DESTDIR)$(man1dir)/xentop.1
endif
diff --git a/tools/xenstat/xentop/xentop.c b/tools/xenstat/xentop/xentop.c
index b808bfa497..7d3ec59d2e 100644
--- a/tools/xenstat/xentop/xentop.c
+++ b/tools/xenstat/xentop/xentop.c
@@ -23,6 +23,7 @@
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
+#include <stdarg.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
@@ -186,6 +187,8 @@ char prompt_val[PROMPT_VAL_LEN];
int prompt_val_len = 0;
void (*prompt_complete_func)(char *);
+static WINDOW *cwin;
+
/*
* Function definitions
*/
@@ -222,7 +225,7 @@ static void version(void)
/* Clean up any open resources */
static void cleanup(void)
{
- if(!isendwin())
+ if(cwin != NULL && !isendwin())
endwin();
if(prev_node != NULL)
xenstat_free_node(prev_node);
@@ -235,7 +238,7 @@ static void cleanup(void)
/* Display the given message and gracefully exit */
static void fail(const char *str)
{
- if(!isendwin())
+ if(cwin != NULL && !isendwin())
endwin();
fprintf(stderr, str);
exit(1);
@@ -266,7 +269,7 @@ static void print(const char *fmt, ...)
if (!batch) {
if((current_row() < lines()-1)) {
va_start(args, fmt);
- vw_printw(stdscr, fmt, args);
+ vwprintw(stdscr, (char *)fmt, args);
va_end(args);
}
} else {
@@ -280,7 +283,7 @@ static void print(const char *fmt, ...)
static void attr_addstr(int attr, const char *str)
{
attron(attr);
- addstr(str);
+ addstr((char *)str);
attroff(attr);
}
@@ -1028,14 +1031,16 @@ int main(int argc, char **argv)
if (!batch) {
/* Begin curses stuff */
- initscr();
+ cwin = initscr();
start_color();
cbreak();
noecho();
nonl();
keypad(stdscr, TRUE);
halfdelay(5);
+#ifndef __sun__
use_default_colors();
+#endif
init_pair(1, -1, COLOR_YELLOW);
do {
diff --git a/tools/xenstore/Makefile b/tools/xenstore/Makefile
index 279a5a5354..d4d35c7c8c 100644
--- a/tools/xenstore/Makefile
+++ b/tools/xenstore/Makefile
@@ -5,11 +5,6 @@ XEN_LIBXC = $(XEN_ROOT)/tools/libxc
MAJOR = 3.0
MINOR = 0
-INSTALL = install
-INSTALL_DATA = $(INSTALL) -m0644
-INSTALL_PROG = $(INSTALL) -m0755
-INSTALL_DIR = $(INSTALL) -d -m0755
-
PROFILE=#-pg
BASECFLAGS=-Wall -g -Werror
# Make gcc generate dependencies.
@@ -32,39 +27,40 @@ CLIENTS_OBJS := $(patsubst xenstore-%,xenstore_%.o,$(CLIENTS))
XENSTORED_OBJS = xenstored_core.o xenstored_watch.o xenstored_domain.o xenstored_transaction.o xs_lib.o talloc.o utils.o tdb.o hashtable.o
-XENSTORED_Linux = xenstored_linux.o
+XENSTORED_OBJS_$(CONFIG_Linux) = xenstored_linux.o
+XENSTORED_OBJS_$(CONFIG_SunOS) = xenstored_solaris.o
-XENSTORED_OBJS += $(XENSTORED_$(OS))
+XENSTORED_OBJS += $(XENSTORED_OBJS_y)
.PHONY: all
all: libxenstore.so libxenstore.a xenstored $(CLIENTS) xs_tdb_dump xenstore-control xenstore-ls
test_interleaved_transactions: test_interleaved_transactions.o
- $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -L. -lxenstore -o $@
+ $(CC) $(CFLAGS) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -L. -lxenstore -o $@
.PHONY: testcode
testcode: xs_test xenstored_test xs_random
xenstored: $(XENSTORED_OBJS)
- $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -lxenctrl -o $@
+ $(CC) $(CFLAGS) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -lxenctrl $(SOCKET_LIBS) -o $@
$(CLIENTS): xenstore-%: xenstore_%.o libxenstore.so
- $(LINK.o) $< $(LOADLIBES) $(LDLIBS) -L. -lxenstore -o $@
+ $(CC) $(CFLAGS) $(LDFLAGS) $< $(LOADLIBES) $(LDLIBS) -L. -lxenstore $(SOCKET_LIBS) -o $@
$(CLIENTS_OBJS): xenstore_%.o: xenstore_client.c
$(COMPILE.c) -DCLIENT_$(*F) -o $@ $<
xenstore-control: xenstore_control.o libxenstore.so
- $(LINK.o) $< $(LOADLIBES) $(LDLIBS) -L. -lxenstore -o $@
+ $(CC) $(CFLAGS) $(LDFLAGS) $< $(LOADLIBES) $(LDLIBS) -L. -lxenstore $(SOCKET_LIBS) -o $@
xenstore-ls: xsls.o libxenstore.so
- $(LINK.o) $< $(LOADLIBES) $(LDLIBS) -L. -lxenstore -o $@
+ $(CC) $(CFLAGS) $(LDFLAGS) $< $(LOADLIBES) $(LDLIBS) -L. -lxenstore $(SOCKET_LIBS) -o $@
xenstored_test: xenstored_core_test.o xenstored_watch_test.o xenstored_domain_test.o xenstored_transaction_test.o xs_lib.o talloc_test.o fake_libxc.o utils.o tdb.o
- $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
+ $(CC) $(CFLAGS) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
xs_tdb_dump: xs_tdb_dump.o utils.o tdb.o talloc.o
- $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
+ $(CC) $(CFLAGS) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@
xs_test xs_random xs_stress xs_crashme: LDFLAGS+=-lpthread
xs_test: xs_test.o xs_lib.o utils.o
@@ -95,7 +91,7 @@ libxenstore.so.$(MAJOR): libxenstore.so.$(MAJOR).$(MINOR)
ln -sf $< $@
libxenstore.so.$(MAJOR).$(MINOR): xs.opic xs_lib.opic
- $(CC) $(CFLAGS) $(LDFLAGS) -Wl,-soname -Wl,libxenstore.so.$(MAJOR) -shared -o $@ $^ -lpthread
+ $(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenstore.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $^ -lpthread
libxenstore.a: xs.o xs_lib.o
$(AR) rcs libxenstore.a $^
diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c
index 2511e4a5fc..890f852d73 100644
--- a/tools/xenstore/xenstored_core.c
+++ b/tools/xenstore/xenstored_core.c
@@ -1688,7 +1688,7 @@ static void write_pidfile(const char *pidfile)
if (lockf(fd, F_TLOCK, 0) == -1)
exit(0);
- len = sprintf(buf, "%d\n", getpid());
+ len = sprintf(buf, "%ld\n", (long)getpid());
if (write(fd, buf, len) != len)
barf_perror("Writing pid file %s", pidfile);
}
@@ -1901,7 +1901,7 @@ int main(int argc, char *argv[])
restore_existing_connections();
if (outputpid) {
- printf("%i\n", getpid());
+ printf("%ld\n", (long)getpid());
fflush(stdout);
}
@@ -1924,6 +1924,9 @@ int main(int argc, char *argv[])
/* Get ready to listen to the tools. */
max = initialize_set(&inset, &outset, *sock, *ro_sock);
+ /* Tell the kernel we're up and running. */
+ xenbus_notify_running();
+
/* Main loop. */
/* FIXME: Rewrite so noone can starve. */
for (;;) {
diff --git a/tools/xenstore/xenstored_core.h b/tools/xenstore/xenstored_core.h
index 0849e7ba78..d46d77f026 100644
--- a/tools/xenstore/xenstored_core.h
+++ b/tools/xenstore/xenstored_core.h
@@ -172,6 +172,9 @@ void *xenbus_map(void);
/* Return the event channel used by xenbus. */
evtchn_port_t xenbus_evtchn(void);
+/* Tell the kernel xenstored is running. */
+void xenbus_notify_running(void);
+
#endif /* _XENSTORED_CORE_H */
/*
diff --git a/tools/xenstore/xenstored_linux.c b/tools/xenstore/xenstored_linux.c
index dabc5ff1a4..5460ca5573 100644
--- a/tools/xenstore/xenstored_linux.c
+++ b/tools/xenstore/xenstored_linux.c
@@ -67,3 +67,7 @@ void *xenbus_map(void)
return addr;
}
+
+void xenbus_notify_running(void)
+{
+}
diff --git a/tools/xenstore/xenstored_solaris.c b/tools/xenstore/xenstored_solaris.c
new file mode 100644
index 0000000000..376a00081b
--- /dev/null
+++ b/tools/xenstore/xenstored_solaris.c
@@ -0,0 +1,66 @@
+/******************************************************************************
+ *
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright (C) 2005 Rusty Russell IBM Corporation
+ *
+ * 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, version 2 of the
+ * License.
+ */
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <xen/sys/xenbus.h>
+
+#include "xenstored_core.h"
+
+evtchn_port_t xenbus_evtchn(void)
+{
+ int fd;
+ evtchn_port_t port;
+
+ fd = open("/dev/xen/xenbus", O_RDONLY);
+ if (fd == -1)
+ return -1;
+
+ port = ioctl(fd, IOCTL_XENBUS_XENSTORE_EVTCHN);
+
+ close(fd);
+ return port;
+}
+
+void *xenbus_map(void)
+{
+ int fd;
+ void *addr;
+
+ fd = open("/dev/xen/xenbus", O_RDWR);
+ if (fd == -1)
+ return NULL;
+
+ addr = mmap(NULL, getpagesize(), PROT_READ|PROT_WRITE,
+ MAP_SHARED, fd, 0);
+
+ if (addr == MAP_FAILED)
+ addr = NULL;
+
+ close(fd);
+
+ return addr;
+}
+
+void xenbus_notify_running(void)
+{
+ int fd;
+
+ fd = open("/dev/xen/xenbus", O_RDONLY);
+
+ (void) ioctl(fd, IOCTL_XENBUS_NOTIFY_UP);
+
+ close(fd);
+}
diff --git a/tools/xenstore/xs_lib.c b/tools/xenstore/xs_lib.c
index 750d1823cf..0afe87d325 100644
--- a/tools/xenstore/xs_lib.c
+++ b/tools/xenstore/xs_lib.c
@@ -76,7 +76,14 @@ const char *xs_daemon_socket_ro(void)
const char *xs_domain_dev(void)
{
char *s = getenv("XENSTORED_PATH");
- return (s ? s : "/proc/xen/xenbus");
+ if (s)
+ return s;
+
+#ifdef __linux__
+ return "/proc/xen/xenbus";
+#else
+ return "/dev/xen/xenbus";
+#endif
}
/* Simple routines for writing to sockets, etc. */
diff --git a/tools/xenstore/xsls.c b/tools/xenstore/xsls.c
index 4d3b1aa1af..7667752546 100644
--- a/tools/xenstore/xsls.c
+++ b/tools/xenstore/xsls.c
@@ -6,6 +6,7 @@
#include <getopt.h>
#include <unistd.h>
#include <sys/ioctl.h>
+#include <termios.h>
static int max_width = 80;
static int desired_width = 60;
diff --git a/tools/xentrace/Makefile b/tools/xentrace/Makefile
index 0ab5e4c060..eafc5bba85 100644
--- a/tools/xentrace/Makefile
+++ b/tools/xentrace/Makefile
@@ -1,8 +1,3 @@
-INSTALL = install
-INSTALL_PROG = $(INSTALL) -m0755
-INSTALL_DIR = $(INSTALL) -d -m0755
-INSTALL_DATA = $(INSTALL) -m0644
-
XEN_ROOT=../..
include $(XEN_ROOT)/tools/Rules.mk
diff --git a/tools/xentrace/formats b/tools/xentrace/formats
index 96ba53212c..45be9d231e 100644
--- a/tools/xentrace/formats
+++ b/tools/xentrace/formats
@@ -12,10 +12,29 @@
0x0002f00c CPU%(cpu)d %(tsc)d t_timer_fn
0x0002f00d CPU%(cpu)d %(tsc)d dom_timer_fn
-0x00080001 CPU%(cpu)d %(tsc)d VMX_VMEXIT [ domid = 0x%(1)08x, eip = 0x%(2)08x, reason = 0x%(3)08x ]
-0x00080002 CPU%(cpu)d %(tsc)d VMX_VECTOR [ domid = 0x%(1)08x, eip = 0x%(2)08x, vector = 0x%(3)08x ]
-0x00080003 CPU%(cpu)d %(tsc)d VMX_INT [ domid = 0x%(1)08x, trap = 0x%(2)08x, va = 0x%(3)08x ]
+0x00080001 CPU%(cpu)d %(tsc)d VMX_VMEXIT [ domid = 0x%(1)08x, eip = 0x%(2)08x, reason = 0x%(3)08x ]
+0x00084001 CPU%(cpu)d %(tsc)d VMX_INTR [ domid = 0x%(1)08x, trap = 0x%(2)08x, va = 0x%(3)08x ]
-0x00081001 CPU%(cpu)d %(tsc)d VMEXIT 0x%(1)08x 0x%(2)08x 0x%(3)08x
-0x00081002 CPU%(cpu)d %(tsc)d VMENTRY 0x%(1)08x 0x%(2)08x 0x%(3)08x 0x%(4)08x 0x%(5)08x
+0x00081001 CPU%(cpu)d %(tsc)d VMEXIT_0 0x%(1)08x 0x%(2)08x 0x%(3)08x
+0x00082001 CPU%(cpu)d %(tsc)d VMENTRY_0 0x%(1)08x 0x%(2)08x 0x%(3)08x 0x%(4)08x 0x%(5)08x
+0x00081002 CPU%(cpu)d %(tsc)d VMEXIT_1 0x%(1)08x 0x%(2)08x 0x%(3)08x
+0x00082002 CPU%(cpu)d %(tsc)d VMENTRY_1 0x%(1)08x 0x%(2)08x 0x%(3)08x 0x%(4)08x 0x%(5)08x
+
+0x00081003 CPU%(cpu)d %(tsc)d VMEXIT_2 0x%(1)08x 0x%(2)08x 0x%(3)08x
+0x00082003 CPU%(cpu)d %(tsc)d VMENTRY_2 0x%(1)08x 0x%(2)08x 0x%(3)08x 0x%(4)08x 0x%(5)08x
+
+0x00081004 CPU%(cpu)d %(tsc)d VMEXIT_3 0x%(1)08x 0x%(2)08x 0x%(3)08x
+0x00082004 CPU%(cpu)d %(tsc)d VMENTRY_3 0x%(1)08x 0x%(2)08x 0x%(3)08x 0x%(4)08x 0x%(5)08x
+
+0x00081005 CPU%(cpu)d %(tsc)d VMEXIT_4 0x%(1)08x 0x%(2)08x 0x%(3)08x
+0x00082005 CPU%(cpu)d %(tsc)d VMENTRY_4 0x%(1)08x 0x%(2)08x 0x%(3)08x 0x%(4)08x 0x%(5)08x
+
+0x00081006 CPU%(cpu)d %(tsc)d VMEXIT_5 0x%(1)08x 0x%(2)08x 0x%(3)08x
+0x00082006 CPU%(cpu)d %(tsc)d VMENTRY_5 0x%(1)08x 0x%(2)08x 0x%(3)08x 0x%(4)08x 0x%(5)08x
+
+0x00081007 CPU%(cpu)d %(tsc)d VMEXIT_6 0x%(1)08x 0x%(2)08x 0x%(3)08x
+0x00082007 CPU%(cpu)d %(tsc)d VMENTRY_6 0x%(1)08x 0x%(2)08x 0x%(3)08x 0x%(4)08x 0x%(5)08x
+
+0x00081008 CPU%(cpu)d %(tsc)d VMEXIT_7 0x%(1)08x 0x%(2)08x 0x%(3)08x
+0x00082008 CPU%(cpu)d %(tsc)d VMENTRY_7 0x%(1)08x 0x%(2)08x 0x%(3)08x 0x%(4)08x 0x%(5)08x
diff --git a/tools/xm-test/README b/tools/xm-test/README
index 62897748d8..22a07c4012 100644
--- a/tools/xm-test/README
+++ b/tools/xm-test/README
@@ -112,6 +112,38 @@ Xm-test will look for disk.img in the ramdisk directory when run by
default.
+BUILDING for ACM Security Testing
+=================================
+
+A number of tests have been added to test the access control module (ACM)
+in the Xen hypervisor and the tools for supporting ACM. Those tests are
+located in the security-acm directory. If ACM support is compiled into Xen
+(see the user guide for how to do this) those tests can be run with the
+following command from the xm-test directory
+
+./runtest.sh [...] -g security <report>
+
+Some of these tests will work even without support of ACM by Xen.
+
+The xm test suite has been extended to support labeling of resources
+as required by the existing tests. However, by default the test suite
+is not allowed to automatically label resources since this may affect
+existing labels. To enable this, the test suite must be configured with
+the following parameter passed to the configure scripts (in addition to
+any other desired parameters)
+
+./configure --enable-full-labeling
+
+To revoke the privilege at a later time run the configure scripts without
+this parameter:
+
+./configure
+
+If a 'make' has previously been run for building the test suite, it is not
+necessary to run 'make' again just for enabling or disabling the automatic
+labeling of resources.
+
+
Running
=======
diff --git a/tools/xm-test/configure.ac b/tools/xm-test/configure.ac
index 5183162f82..10091cc964 100644
--- a/tools/xm-test/configure.ac
+++ b/tools/xm-test/configure.ac
@@ -38,6 +38,20 @@ fi
AM_CONDITIONAL(HVM, test x$ENABLE_HVM = xTrue)
AC_SUBST(ENABLE_HVM)
+AC_ARG_ENABLE(full-labeling,
+ [[ --enable-full-labeling allows the test suite to label all resources]],
+ [
+ ENABLE_LABELING=True
+ ],[
+ ENABLE_LABELING=False
+ ])
+
+if test "x$ENABLE_LABELING" = "xTrue"; then
+ echo "ACM_LABEL_RESOURCES = True" > lib/XmTestLib/acm_config.py
+else
+ rm -f lib/XmTestLib/acm_config.py*
+fi
+
# Network needs to know ips to use: dhcp or a range of IPs in the form
# of: 192.168.1.1-192.168.1.100
# If not dhcp, a netmask and network address must be supplied. Defaults to
@@ -127,6 +141,7 @@ AC_CONFIG_FILES([
tests/restore/Makefile
tests/save/Makefile
tests/sched-credit/Makefile
+ tests/security-acm/Makefile
tests/sedf/Makefile
tests/shutdown/Makefile
tests/sysrq/Makefile
diff --git a/tools/xm-test/grouptest/default b/tools/xm-test/grouptest/default
index d4af74057d..d82ca73d21 100644
--- a/tools/xm-test/grouptest/default
+++ b/tools/xm-test/grouptest/default
@@ -22,6 +22,7 @@ reboot
restore
save
sched-credit
+security-acm
shutdown
sysrq
unpause
diff --git a/tools/xm-test/grouptest/security b/tools/xm-test/grouptest/security
new file mode 100644
index 0000000000..4d5c8b941d
--- /dev/null
+++ b/tools/xm-test/grouptest/security
@@ -0,0 +1 @@
+security-acm
diff --git a/tools/xm-test/lib/XmTestLib/XenDomain.py b/tools/xm-test/lib/XmTestLib/XenDomain.py
index cbe93f805d..e78fd7f6c4 100644
--- a/tools/xm-test/lib/XmTestLib/XenDomain.py
+++ b/tools/xm-test/lib/XmTestLib/XenDomain.py
@@ -29,6 +29,7 @@ from Test import *
from config import *
from Console import *
from XenDevice import *
+from acm import *
BLOCK_ROOT_DEV = "hda"
@@ -102,6 +103,9 @@ class XenConfig:
self.defaultOpts["disk"] = []
self.defaultOpts["vif"] = []
self.defaultOpts["vtpm"] = []
+ if isACMEnabled():
+ #A default so every VM can start with ACM enabled
+ self.defaultOpts["access_control"] = ['policy=xm-test,label=red']
self.opts = self.defaultOpts
@@ -129,6 +133,7 @@ class XenConfig:
output = file(filename, "w")
output.write(self.toString())
output.close()
+ ACMPrepareSystem(self.opts)
def __str__(self):
"""When used as a string, we represent ourself by a config
diff --git a/tools/xm-test/lib/XmTestLib/acm.py b/tools/xm-test/lib/XmTestLib/acm.py
new file mode 100644
index 0000000000..dd1e67646d
--- /dev/null
+++ b/tools/xm-test/lib/XmTestLib/acm.py
@@ -0,0 +1,91 @@
+#!/usr/bin/python
+"""
+ Copyright (C) International Business Machines Corp., 2006
+ Author: Stefan Berger <stefanb@us.ibm.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; under version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+"""
+from Test import *
+from xen.util import security
+
+try:
+ from acm_config import *
+except:
+ ACM_LABEL_RESOURCES = False
+
+labeled_resources = {}
+acm_verbose = True
+
+def isACMEnabled():
+ return security.on()
+
+
+def ACMLoadPolicy(policy='xm-test'):
+ s, o = traceCommand("xm makepolicy %s" % (policy))
+ if s != 0:
+ FAIL("Need to be able to do 'xm makepolicy %s' but could not" %
+ (policy))
+ s, o = traceCommand("xm loadpolicy %s" % (policy))
+ if s != 0:
+ FAIL("Could not load the required policy '%s'.\n"
+ "Start the system without any policy.\n%s" %
+ (policy, o))
+
+def ACMPrepareSystem(resources):
+ if isACMEnabled():
+ ACMLoadPolicy()
+ ACMLabelResources(resources)
+
+def ACMLabelResources(resources):
+ for k, v in resources.items():
+ if k == "disk":
+ for vv in v:
+ res = vv.split(',')[0]
+ ACMLabelResource(res)
+
+# Applications may label resources explicitly by calling this function
+def ACMLabelResource(resource, label='red'):
+ if acm_verbose:
+ print "labeling resource %s with label %s" % (resource, label)
+ if not ACM_LABEL_RESOURCES:
+ SKIP("Skipping test since not allowed to label resources in "
+ "test suite")
+ if not isACMResourceLabeled(resource):
+ ACMUnlabelResource(resource)
+ s, o = traceCommand("xm addlabel %s res %s" % (label, resource))
+ if s != 0:
+ FAIL("Could not add label to resource")
+ else:
+ labeled_resources["%s" % resource] = 1
+
+
+# Application may remove a label from a resource. It has to call this
+# function and must do so once a resource for re-labeling a resource
+def ACMUnlabelResource(resource):
+ s, o = traceCommand("xm rmlabel res %s" % (resource))
+ labeled_resources["%s" % resource] = 0
+
+
+def isACMResourceLabeled(resource):
+ """ Check whether a resource has been labeled using this API
+ and while running the application """
+ try:
+ if labeled_resources["%s" % resource] == 1:
+ if acm_verbose:
+ print "resource %s already labeled!" % resource
+ return True
+ except:
+ return False
+ return False
diff --git a/tools/xm-test/lib/XmTestLib/block_utils.py b/tools/xm-test/lib/XmTestLib/block_utils.py
index 38c5d20d5f..c315c17bd1 100644
--- a/tools/xm-test/lib/XmTestLib/block_utils.py
+++ b/tools/xm-test/lib/XmTestLib/block_utils.py
@@ -6,6 +6,7 @@
import time
from XmTestLib import *
+from acm import *
import xen.util.blkif
@@ -26,6 +27,7 @@ def get_state(domain, devname):
def block_attach(domain, phy, virt):
+ ACMLabelResource(phy)
status, output = traceCommand("xm block-attach %s %s %s w" %
(domain.getName(), phy, virt))
if status != 0:
diff --git a/tools/xm-test/runtest.sh b/tools/xm-test/runtest.sh
index 9e11824b80..2bcc46110f 100755
--- a/tools/xm-test/runtest.sh
+++ b/tools/xm-test/runtest.sh
@@ -197,6 +197,8 @@ run=yes
unsafe=no
GROUPENTERED=default
+cp -f tests/security-acm/xm-test-security_policy.xml /etc/xen/acm-security/policies
+
# Resolve options
while [ $# -gt 0 ]
do
diff --git a/tools/xm-test/tests/Makefile.am b/tools/xm-test/tests/Makefile.am
index c01cdd244d..0ba9076a1d 100644
--- a/tools/xm-test/tests/Makefile.am
+++ b/tools/xm-test/tests/Makefile.am
@@ -19,6 +19,7 @@ SUBDIRS = \
pause \
reboot \
sched-credit \
+ security-acm \
sedf \
shutdown \
sysrq \
diff --git a/tools/xm-test/tests/security-acm/01_security-acm_basic.py b/tools/xm-test/tests/security-acm/01_security-acm_basic.py
new file mode 100644
index 0000000000..6459bb9fd8
--- /dev/null
+++ b/tools/xm-test/tests/security-acm/01_security-acm_basic.py
@@ -0,0 +1,121 @@
+#!/usr/bin/python
+
+# Copyright (C) International Business Machines Corp., 2006
+# Author: Stefan Berger <stefanb@us.ibm.com>
+#
+# A couple of simple tests that test ACM security extensions
+# for the xm tool. The following xm subcommands are tested:
+#
+# - makepolicy
+# - labels
+# - rmlabel
+# - addlabel
+# - getlabel
+# - resources
+
+from XmTestLib import *
+from xen.util import security
+import commands
+import os
+import re
+
+testpolicy = "xm-test"
+testlabel = "blue"
+vmconfigfile = "/tmp/xm-test.conf"
+testresource = "phy:ram0"
+
+if not isACMEnabled():
+ SKIP("Not running this test since ACM not enabled.")
+
+status, output = traceCommand("xm makepolicy %s" % (testpolicy))
+if status != 0 or output != "":
+ FAIL("'xm makepolicy' failed with status %d and output\n%s" %
+ (status,output));
+
+status, output = traceCommand("xm labels %s" % (testpolicy))
+if status != 0:
+ FAIL("'xm labels' failed with status %d.\n" % status)
+
+#Need to get a vm config file - just have it written to a file
+domain = XmTestDomain()
+domain.config.write(vmconfigfile)
+
+#Whatever label it might have - remove it
+status, output = traceCommand("xm rmlabel dom %s" %
+ (vmconfigfile))
+
+status, output = traceCommand("xm addlabel %s dom %s %s" %
+ (testlabel, vmconfigfile, testpolicy))
+if status != 0:
+ FAIL("'xm addlabel' failed with status %d.\n" % status)
+
+status, output = traceCommand("xm getlabel dom %s" %
+ (vmconfigfile))
+
+if status != 0:
+ FAIL("'xm getlabel' failed with status %d, output:\n%s" %
+ (status, output))
+if output != "policy=%s,label=%s" % (testpolicy,testlabel):
+ FAIL("Received unexpected output from 'xm getlabel': \n%s" %
+ (output))
+
+
+status, output = traceCommand("xm rmlabel dom %s" %
+ (vmconfigfile))
+
+if status != 0:
+ FAIL("'xm rmlabel' failed with status %d, output: \n%s" %
+ (status,output))
+if output != "":
+ FAIL("Received unexpected output from 'xm rmlabel': \n%s" %
+ (output))
+
+status, output = traceCommand("xm getlabel dom %s" %
+ (vmconfigfile))
+
+if output != "Error: 'Domain not labeled'":
+ FAIL("Received unexpected output from 'xm getlabel': \n%s" %
+ (output))
+
+#Whatever label the resource might have, remove it
+status, output = traceCommand("xm rmlabel res %s" %
+ (testresource))
+
+status, output = traceCommand("xm addlabel %s res %s %s" %
+ (testlabel, testresource, testpolicy))
+if status != 0:
+ FAIL("'xm addlabel' on resource failed with status %d.\n" % status)
+
+status, output = traceCommand("xm getlabel res %s" % (testresource))
+
+if status != 0:
+ FAIL("'xm getlabel' on resource failed with status %d, output:\n%s" %
+ (status, output))
+if output != "policy=%s,label=%s" % (testpolicy,testlabel):
+ FAIL("Received unexpected output from 'xm getlabel': \n%s" %
+ (output))
+
+status, output = traceCommand("xm resources")
+
+if status != 0:
+ FAIL("'xm resources' did not run properly")
+if not re.search(security.unify_resname(testresource), output):
+ FAIL("'xm resources' did not show the tested resource '%s'." %
+ testresource)
+
+status, output = traceCommand("xm rmlabel res %s" %
+ (testresource))
+
+if status != 0:
+ FAIL("'xm rmlabel' on resource failed with status %d, output: \n%s" %
+ (status,output))
+if output != "":
+ FAIL("Received unexpected output from 'xm rmlabel': \n%s" %
+ (output))
+
+status, output = traceCommand("xm getlabel res %s" %
+ (testresource))
+
+if output != "Error: 'Resource not labeled'":
+ FAIL("Received unexpected output from 'xm getlabel': \n%s" %
+ (output))
diff --git a/tools/xm-test/tests/security-acm/02_security-acm_dom_start.py b/tools/xm-test/tests/security-acm/02_security-acm_dom_start.py
new file mode 100644
index 0000000000..4aac09d2fc
--- /dev/null
+++ b/tools/xm-test/tests/security-acm/02_security-acm_dom_start.py
@@ -0,0 +1,64 @@
+#!/usr/bin/python
+
+# Copyright (C) International Business Machines Corp., 2006
+# Author: Stefan Berger <stefanb@us.ibm.com>
+#
+# Simple test that starts two labeled domains; both domains should start
+#
+# The following xm subcommands are tested:
+# - dumppolicy
+# - labels
+
+from XmTestLib import *
+from acm_utils import *
+import commands
+import os
+
+testlabel1 = "green"
+testlabel2 = "red"
+
+status, output = traceCommand("xm labels")
+
+labels = ["SystemManagement", "blue", "red", "green"]
+for l in labels:
+ if not re.search(l, output):
+ FAIL("Label '%s' not found in current policy!", l)
+
+status, output = traceCommand("xm dumppolicy")
+if status != 0:
+ FAIL("'xm dumppolicy' returned an error code.")
+lines = ["ssidref 0: 00 00 00 00",
+ "ssidref 1: 01 00 00 00",
+ "ssidref 2: 00 01 00 00",
+ "ssidref 3: 00 00 01 00",
+ "ssidref 4: 00 00 00 01"]
+for l in lines:
+ if not re.search(l, output):
+ FAIL("Could not find '%s' in output of 'xm dumppolicy'" % l)
+
+config = {"access_control":"policy=%s,label=%s" % (testpolicy,testlabel1)}
+verbose = True
+domain1 = XmTestDomain(name="domain-%s" % testlabel1,
+ extraConfig=config)
+
+try:
+ domain1.start(noConsole=True)
+except DomainError, e:
+ if verbose:
+ print e.extra
+ FAIL("Unable to start 1st labeled test domain.")
+
+config = {"access_control":"policy=%s,label=%s" % (testpolicy,testlabel2)}
+
+domain2 = XmTestDomain(name="domain-%s" % testlabel2,
+ extraConfig=config)
+
+try:
+ domain2.start(noConsole=True)
+except DomainError, e:
+ if verbose:
+ print e.extra
+ FAIL("Unable to start 2nd labeled test domain.")
+
+domain2.destroy()
+domain1.destroy()
diff --git a/tools/xm-test/tests/security-acm/03_security-acm_dom_conflict.py b/tools/xm-test/tests/security-acm/03_security-acm_dom_conflict.py
new file mode 100644
index 0000000000..4aef380de5
--- /dev/null
+++ b/tools/xm-test/tests/security-acm/03_security-acm_dom_conflict.py
@@ -0,0 +1,60 @@
+#!/usr/bin/python
+
+# Copyright (C) International Business Machines Corp., 2006
+# Author: Stefan Berger <stefanb@us.ibm.com>
+#
+# A test that exercises the conflict set of the chinese wall policy.
+# Start a first domain and then a second one. The second one is
+# expected NOT to be starteable.
+
+from XmTestLib import *
+from acm_utils import *
+import commands
+import os
+
+testlabel1 = "blue"
+testlabel2 = "red"
+
+config = {"access_control":"policy=%s,label=%s" % (testpolicy,testlabel1)}
+
+domain1 = XmTestDomain(name="domain-%s" % testlabel1,
+ extraConfig=config)
+
+try:
+ domain1.start(noConsole=True)
+except DomainError, e:
+ if verbose:
+ print e.extra
+ FAIL("Unable to start 1st labeled test domain")
+
+# Verify with xm dry-run
+status, output = traceCommand("xm dry-run /tmp/xm-test.conf | "
+ "grep -v \"Dry Run\"")
+if status != 0:
+ FAIL("'xm dry-run' failed")
+if not re.search("PERMITTED", output):
+ FAIL("'xm dry-run' did not succeed.")
+
+config = {"access_control":"policy=%s,label=%s" % (testpolicy,testlabel2)}
+
+domain2 = XmTestDomain(name="domain-%s" % testlabel2,
+ extraConfig=config)
+
+try:
+ domain2.start(noConsole=True)
+ # Should never get here!
+ FAIL("Could start a domain in a conflict set - "
+ "this should not be possible")
+except DomainError, e:
+ #This is exactly what we want in this case
+ status = 0
+
+# Verify with xm dry-run
+status, output = traceCommand("xm dry-run /tmp/xm-test.conf | "
+ "grep -v \"Dry Run\"")
+if status != 0:
+ FAIL("'xm dry-run' failed.")
+if not re.search("PERMITTED", output):
+ FAIL("'xm dry-run' did not show that operation was permitted.")
+
+domain1.destroy()
diff --git a/tools/xm-test/tests/security-acm/04_security-acm_dom_res.py b/tools/xm-test/tests/security-acm/04_security-acm_dom_res.py
new file mode 100644
index 0000000000..367016339f
--- /dev/null
+++ b/tools/xm-test/tests/security-acm/04_security-acm_dom_res.py
@@ -0,0 +1,69 @@
+#!/usr/bin/python
+
+# Copyright (C) International Business Machines Corp., 2006
+# Author: Stefan Berger <stefanb@us.ibm.com>
+#
+# Simple test that starts two labeled domains using labeled resources each
+#
+
+from XmTestLib import *
+from acm_utils import *
+import commands
+import os
+
+testlabel1 = "green"
+resource1 = "phy:ram0"
+testlabel2 = "red"
+resource2 = "phy:/dev/ram1"
+
+config = {"access_control":"policy=%s,label=%s" % (testpolicy,testlabel1),
+ "disk" :"%s,hda1,w" % (resource1)}
+domain1 = XmTestDomain(name="domain-%s" % testlabel1,
+ extraConfig=config)
+
+# Explicity label the resource
+ACMLabelResource(resource1, testlabel1)
+
+try:
+ domain1.start(noConsole=True)
+except DomainError, e:
+ if verbose:
+ print e.extra
+ FAIL("Unable to start 1st labeled test domain.")
+
+# Verify with xm dry-run
+status, output = traceCommand("xm dry-run /tmp/xm-test.conf | "
+ "grep -v \"Dry Run\"")
+
+if status != 0:
+ FAIL("'xm dry-run' failed")
+if not re.search("%s: PERMITTED" % resource1, output):
+ FAIL("'xm dry-run' did not succeed.")
+
+config = {"access_control":"policy=%s,label=%s" % (testpolicy,testlabel2),
+ "disk" :"%s,hda1,w" % (resource2)}
+
+domain2 = XmTestDomain(name="domain-%s" % testlabel2,
+ extraConfig=config)
+
+# Explicity label the resource
+ACMLabelResource(resource2, testlabel2)
+
+try:
+ domain2.start(noConsole=True)
+except DomainError, e:
+ if verbose:
+ print e.extra
+ FAIL("Unable to start 2nd labeled test domain.")
+
+# Verify with xm dry-run
+status, output = traceCommand("xm dry-run /tmp/xm-test.conf | "
+ "grep -v \"Dry Run\"")
+
+if status != 0:
+ FAIL("'xm dry-run' failed")
+if not re.search("%s: PERMITTED" % resource2, output):
+ FAIL("'xm dry-run' did not succeed.")
+
+domain2.destroy()
+domain1.destroy()
diff --git a/tools/xm-test/tests/security-acm/05_security-acm_dom_res_conf.py b/tools/xm-test/tests/security-acm/05_security-acm_dom_res_conf.py
new file mode 100644
index 0000000000..89c6b5974c
--- /dev/null
+++ b/tools/xm-test/tests/security-acm/05_security-acm_dom_res_conf.py
@@ -0,0 +1,38 @@
+#!/usr/bin/python
+
+# Copyright (C) International Business Machines Corp., 2006
+# Author: Stefan Berger <stefanb@us.ibm.com>
+#
+# A test that tries to start a domain using a resource that it is
+# not supposed to be able to use due to its labeling
+
+from XmTestLib import *
+from acm_utils import *
+import commands
+import os
+
+testlabel1 = "blue"
+resource1 = "phy:ram0"
+
+config = {"access_control":"policy=%s,label=%s" % (testpolicy,testlabel1),
+ "disk" :"%s,hda1,w" % (resource1)}
+
+domain1 = XmTestDomain(name="domain-%s" % testlabel1,
+ extraConfig=config)
+
+ACMLabelResource(resource1,"red")
+
+try:
+ domain1.start(noConsole=True)
+ # Should never get here
+ FAIL("Could start domain with resource that it is not supposed to access.")
+except DomainError, e:
+ #That's exactly what we want to have in this case
+ dummy = 0
+
+# Verify via dry-run
+status, output = traceCommand("xm dry-run /tmp/xm-test.conf | "
+ "grep -v \"Dry Run\"")
+if not re.search("%s: DENIED" %resource1, output):
+ FAIL("'xm dry-run' did not show expected result that operation was NOT "
+ "permitted: \n%s" % output)
diff --git a/tools/xm-test/tests/security-acm/06_security-acm_dom_block_attach.py b/tools/xm-test/tests/security-acm/06_security-acm_dom_block_attach.py
new file mode 100644
index 0000000000..f3908f7820
--- /dev/null
+++ b/tools/xm-test/tests/security-acm/06_security-acm_dom_block_attach.py
@@ -0,0 +1,82 @@
+#!/usr/bin/python
+
+# Copyright (C) International Business Machines Corp., 2005
+# Author: Stefan Berger <stefanb@us.ibm.com>
+# Based on block-create/01_block_attach_device_pos.py
+#
+# Create a domain and attach 2 resources to it. The first resource
+# should be attacheable, the 2nd one should not be due to the label it has.
+
+import re
+from XmTestLib import *
+from XmTestLib import block_utils
+from acm_utils import *
+
+testlabel1 = "blue"
+resource1 = "phy:ram1"
+resourcelabel1 = "blue"
+resource2 = "phy:/dev/ram0"
+resourcelabel2 = "red"
+
+if ENABLE_HVM_SUPPORT:
+ SKIP("Block-attach not supported for HVM domains")
+
+# Create a domain (default XmTestDomain, with our ramdisk)
+config = {"access_control":"policy=%s,label=%s" % (testpolicy,testlabel1)}
+
+domain = XmTestDomain(extraConfig=config)
+
+try:
+ console = domain.start()
+except DomainError, e:
+ FAIL(str(e))
+
+# Attach a console to it
+try:
+ console.setHistorySaveCmds(value=True)
+ # Run 'ls'
+ run = console.runCmd("ls")
+except ConsoleError, e:
+ saveLog(console.getHistory())
+ FAIL(str(e))
+
+
+# Explicitly label the 1st resource
+ACMLabelResource(resource1, resourcelabel1)
+block_utils.block_attach(domain, resource1, "sdb1")
+
+try:
+ run1 = console.runCmd("cat /proc/partitions")
+except ConsoleError, e:
+ FAIL(str(e))
+
+#Explicitly label the 2nd resource
+ACMLabelResource(resource2, resourcelabel2)
+#Cannot call block_attach here since we legally may fail the command
+status, output = traceCommand("xm block-attach %s %s %s w" %
+ (domain.getName(), resource2, "sdb2" ))
+
+for i in range(10):
+ if block_utils.get_state(domain, "sdb2") == 4:
+ break
+ time.sleep(1)
+
+try:
+ run2 = console.runCmd("cat /proc/partitions")
+except ConsoleError, e:
+ FAIL(str(e))
+
+# Close the console
+domain.closeConsole()
+
+# Stop the domain (nice shutdown)
+domain.stop()
+
+if not re.search("sdb1",run1["output"]):
+ FAIL("Labeled device 'sdb1' is not actually connected to the domU")
+
+if not re.search("sdb1",run2["output"]):
+ FAIL("Labeled device 'sdb1' has disappeared?!")
+
+if re.search("sdb2",run2["output"]):
+ FAIL("Labeled device 'sdb2' is connected to the domU but should not be")
diff --git a/tools/xm-test/tests/security-acm/Makefile.am b/tools/xm-test/tests/security-acm/Makefile.am
new file mode 100644
index 0000000000..7b691712f2
--- /dev/null
+++ b/tools/xm-test/tests/security-acm/Makefile.am
@@ -0,0 +1,28 @@
+SUBDIRS =
+
+TESTS = 01_security-acm_basic.test \
+ 02_security-acm_dom_start.test \
+ 03_security-acm_dom_conflict.test \
+ 04_security-acm_dom_res.test \
+ 05_security-acm_dom_res_conf.test \
+ 06_security-acm_dom_block_attach.test
+
+XFAIL_TESTS =
+
+EXTRA_DIST = $(TESTS) $(XFAIL_TESTS) acm_utils.py
+TESTS_ENVIRONMENT=@TENV@
+
+%.test: %.py
+ cp $< $@
+ chmod +x $@
+ @if [ -d /etc/xen/acm-security/policies ]; then \
+ cp -f xm-test-security_policy.xml \
+ /etc/xen/acm-security/policies; \
+ fi;
+
+clean-local: am_config_clean-local
+
+am_config_clean-local:
+ rm -f *test
+ rm -f *log
+ rm -f *~
diff --git a/tools/xm-test/tests/security-acm/acm_utils.py b/tools/xm-test/tests/security-acm/acm_utils.py
new file mode 100644
index 0000000000..29608a38a4
--- /dev/null
+++ b/tools/xm-test/tests/security-acm/acm_utils.py
@@ -0,0 +1,15 @@
+#!/usr/bin/python
+
+# Copyright (C) International Business Machines Corp., 2006
+# Author: Stefan Berger <stefanb@us.ibm.com>
+
+from XmTestLib import *
+from XmTestLib.acm import *
+
+testpolicy = "xm-test"
+vmconfigfile = "/tmp/xm-test.conf"
+
+if not isACMEnabled():
+ SKIP("Not running this test since ACM not enabled.")
+
+ACMLoadPolicy(testpolicy)
diff --git a/tools/xm-test/tests/security-acm/xm-test-security_policy.xml b/tools/xm-test/tests/security-acm/xm-test-security_policy.xml
new file mode 100644
index 0000000000..b1736dbdf2
--- /dev/null
+++ b/tools/xm-test/tests/security-acm/xm-test-security_policy.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Auto-generated by ezPolicy -->
+<SecurityPolicyDefinition xmlns="http://www.ibm.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.ibm.com ../../security_policy.xsd ">
+ <PolicyHeader>
+ <PolicyName>xm-test</PolicyName>
+ <Date>Fri Sep 29 14:44:38 2006</Date>
+ </PolicyHeader>
+
+ <SimpleTypeEnforcement>
+ <SimpleTypeEnforcementTypes>
+ <Type>SystemManagement</Type>
+ <Type>green</Type>
+ <Type>red</Type>
+ <Type>blue</Type>
+ </SimpleTypeEnforcementTypes>
+ </SimpleTypeEnforcement>
+
+ <ChineseWall priority="PrimaryPolicyComponent">
+ <ChineseWallTypes>
+ <Type>SystemManagement</Type>
+ <Type>green</Type>
+ <Type>red</Type>
+ <Type>blue</Type>
+ </ChineseWallTypes>
+
+ <ConflictSets>
+ <Conflict name="RER">
+ <Type>blue</Type>
+ <Type>red</Type>
+ </Conflict>
+ </ConflictSets>
+ </ChineseWall>
+
+ <SecurityLabelTemplate>
+ <SubjectLabels bootstrap="SystemManagement">
+ <VirtualMachineLabel>
+ <Name>SystemManagement</Name>
+ <SimpleTypeEnforcementTypes>
+ <Type>SystemManagement</Type>
+ <Type>green</Type>
+ <Type>red</Type>
+ <Type>blue</Type>
+ </SimpleTypeEnforcementTypes>
+ <ChineseWallTypes>
+ <Type>SystemManagement</Type>
+ </ChineseWallTypes>
+ </VirtualMachineLabel>
+
+ <VirtualMachineLabel>
+ <Name>green</Name>
+ <SimpleTypeEnforcementTypes>
+ <Type>green</Type>
+ </SimpleTypeEnforcementTypes>
+ <ChineseWallTypes>
+ <Type>green</Type>
+ </ChineseWallTypes>
+ </VirtualMachineLabel>
+
+ <VirtualMachineLabel>
+ <Name>red</Name>
+ <SimpleTypeEnforcementTypes>
+ <Type>red</Type>
+ </SimpleTypeEnforcementTypes>
+ <ChineseWallTypes>
+ <Type>red</Type>
+ </ChineseWallTypes>
+ </VirtualMachineLabel>
+
+ <VirtualMachineLabel>
+ <Name>blue</Name>
+ <SimpleTypeEnforcementTypes>
+ <Type>blue</Type>
+ </SimpleTypeEnforcementTypes>
+ <ChineseWallTypes>
+ <Type>blue</Type>
+ </ChineseWallTypes>
+ </VirtualMachineLabel>
+ </SubjectLabels>
+
+ <ObjectLabels>
+ <ResourceLabel>
+ <Name>SystemManagement</Name>
+ <SimpleTypeEnforcementTypes>
+ <Type>SystemManagement</Type>
+ </SimpleTypeEnforcementTypes>
+ </ResourceLabel>
+
+ <ResourceLabel>
+ <Name>green</Name>
+ <SimpleTypeEnforcementTypes>
+ <Type>green</Type>
+ </SimpleTypeEnforcementTypes>
+ </ResourceLabel>
+
+ <ResourceLabel>
+ <Name>red</Name>
+ <SimpleTypeEnforcementTypes>
+ <Type>red</Type>
+ </SimpleTypeEnforcementTypes>
+ </ResourceLabel>
+
+ <ResourceLabel>
+ <Name>blue</Name>
+ <SimpleTypeEnforcementTypes>
+ <Type>blue</Type>
+ </SimpleTypeEnforcementTypes>
+ </ResourceLabel>
+ </ObjectLabels>
+ </SecurityLabelTemplate>
+</SecurityPolicyDefinition>
diff --git a/unmodified_drivers/linux-2.6/mkbuildtree b/unmodified_drivers/linux-2.6/mkbuildtree
index 9e2803cd77..ce0a142447 100644
--- a/unmodified_drivers/linux-2.6/mkbuildtree
+++ b/unmodified_drivers/linux-2.6/mkbuildtree
@@ -1,5 +1,13 @@
#! /bin/sh
+if [ $1 ]; then
+ uname="$1"
+else
+ uname=`uname -m`
+ echo "Defaulting to this machine's architecture, $uname, for linking."
+ echo "This may be overridden on the command line (i386,x86_64,ia64)."
+fi
+
C=$PWD
XEN=$C/../../xen
@@ -27,34 +35,33 @@ ln -sf ${XEN}/include/public include/xen/interface
# Need to be quite careful here: we don't want the files we link in to
# risk overriding the native Linux ones (in particular, system.h must
# be native and not xenolinux).
-uname=`uname -m`
case "$uname"
in
"x86_64")
- ln -sf ${XL}/include/asm-x86_64/mach-xen/asm/hypervisor.h include/asm
- ln -sf ${XL}/include/asm-x86_64/mach-xen/asm/hypercall.h include/asm
- ln -sf ${XL}/include/asm-x86_64/mach-xen/asm/synch_bitops.h include/asm
- ln -sf ${XL}/include/asm-x86_64/mach-xen/asm/maddr.h include/asm
- ln -sf ${XL}/include/asm-i386 include/asm-i386
- ;;
+ ln -sf ${XL}/include/asm-x86_64/mach-xen/asm/hypervisor.h include/asm
+ ln -sf ${XL}/include/asm-x86_64/mach-xen/asm/hypercall.h include/asm
+ ln -sf ${XL}/include/asm-x86_64/mach-xen/asm/synch_bitops.h include/asm
+ ln -sf ${XL}/include/asm-x86_64/mach-xen/asm/maddr.h include/asm
+ ln -sf ${XL}/include/asm-i386 include/asm-i386
+ ;;
i[34567]86)
- ln -sf ${XL}/include/asm-i386/mach-xen/asm/hypervisor.h include/asm
- ln -sf ${XL}/include/asm-i386/mach-xen/asm/hypercall.h include/asm
- ln -sf ${XL}/include/asm-i386/mach-xen/asm/synch_bitops.h include/asm
- ln -sf ${XL}/include/asm-i386/mach-xen/asm/maddr.h include/asm
- ;;
+ ln -sf ${XL}/include/asm-i386/mach-xen/asm/hypervisor.h include/asm
+ ln -sf ${XL}/include/asm-i386/mach-xen/asm/hypercall.h include/asm
+ ln -sf ${XL}/include/asm-i386/mach-xen/asm/synch_bitops.h include/asm
+ ln -sf ${XL}/include/asm-i386/mach-xen/asm/maddr.h include/asm
+ ;;
"ia64")
- ln -sf ${XL}/include/asm-ia64/hypervisor.h include/asm
- ln -sf ${XL}/include/asm-ia64/hypercall.h include/asm
- ln -sf ${XL}/include/asm-ia64/synch_bitops.h include/asm
- ln -sf ${XL}/include/asm-ia64/maddr.h include/asm
- ln -sf ${XL}/include/asm-ia64/xen/xcom_hcall.h include/asm/xen
- ln -sf ${XL}/include/asm-ia64/xen/xencomm.h include/asm/xen
- ln -sf ${XL}/arch/ia64/xen/xcom_mini.c platform-pci
- ln -sf ${XL}/arch/ia64/xen/xencomm.c platform-pci
- ;;
+ ln -sf ${XL}/include/asm-ia64/hypervisor.h include/asm
+ ln -sf ${XL}/include/asm-ia64/hypercall.h include/asm
+ ln -sf ${XL}/include/asm-ia64/synch_bitops.h include/asm
+ ln -sf ${XL}/include/asm-ia64/maddr.h include/asm
+ ln -sf ${XL}/include/asm-ia64/xen/xcom_hcall.h include/asm/xen
+ ln -sf ${XL}/include/asm-ia64/xen/xencomm.h include/asm/xen
+ ln -sf ${XL}/arch/ia64/xen/xcom_mini.c platform-pci
+ ln -sf ${XL}/arch/ia64/xen/xencomm.c platform-pci
+ ;;
*)
- echo unknown architecture $uname
- exit 1
- ;;
+ echo unknown architecture $uname
+ exit 1
+ ;;
esac
diff --git a/xen/Makefile b/xen/Makefile
index 4485a8e931..0c06e081fe 100644
--- a/xen/Makefile
+++ b/xen/Makefile
@@ -2,7 +2,7 @@
# All other places this is stored (eg. compile.h) should be autogenerated.
export XEN_VERSION = 3
export XEN_SUBVERSION = 0
-export XEN_EXTRAVERSION ?= -unstable
+export XEN_EXTRAVERSION ?= -unstable$(XEN_VENDORVERSION)
export XEN_FULLVERSION = $(XEN_VERSION).$(XEN_SUBVERSION)$(XEN_EXTRAVERSION)
-include xen-version
@@ -93,14 +93,14 @@ include/xen/acm_policy.h:
include/xen/compile.h: include/xen/compile.h.in
@sed -e 's/@@date@@/$(shell LC_ALL=C date)/g' \
-e 's/@@time@@/$(shell LC_ALL=C date +%T)/g' \
- -e 's/@@whoami@@/$(shell whoami)/g' \
+ -e 's/@@whoami@@/$(USER)/g' \
-e 's/@@domain@@/$(shell ([ -x /bin/dnsdomainname ] && /bin/dnsdomainname) || ([ -x /bin/domainname ] && /bin/domainname || echo [unknown]))/g' \
-e 's/@@hostname@@/$(shell hostname)/g' \
- -e 's|@@compiler@@|$(shell $(CC) $(CFLAGS) -v 2>&1 | tail -n 1 | sed -e "s;|;/;")|g' \
+ -e 's!@@compiler@@!$(shell $(CC) $(CFLAGS) -v 2>&1 | grep -i "gcc.*version")!g' \
-e 's/@@version@@/$(XEN_VERSION)/g' \
-e 's/@@subversion@@/$(XEN_SUBVERSION)/g' \
-e 's/@@extraversion@@/$(XEN_EXTRAVERSION)/g' \
- -e 's!@@changeset@@!$(shell ((hg parents || head -n 7 ../ChangeLog || echo date: unavailable) | awk '{FS="changeset:[ ]+"}/^changeset/{CS=$$2};{FS="date:[ ]+"}/^date/{D=$$2}; END {print D, CS}') 2>/dev/null)!g' \
+ -e 's!@@changeset@@!$(shell ((hg parents --template "{date|date} {rev}:{node|short}" >/dev/null && hg parents --template "{date|date} {rev}:{node|short}") || echo "unavailable") 2>/dev/null)!g' \
< include/xen/compile.h.in > $@.new
tools/figlet/figlet -d tools/figlet Xen $(XEN_FULLVERSION) >> $@.new
@mv -f $@.new $@
@@ -154,7 +154,7 @@ _cscope:
.PHONY: MAP
MAP:
- $(NM) $(TARGET) | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map
+ $(NM) -n $(TARGET) | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' > System.map
.PHONY: FORCE
FORCE:
diff --git a/xen/Rules.mk b/xen/Rules.mk
index e319ffb619..08c26aca44 100644
--- a/xen/Rules.mk
+++ b/xen/Rules.mk
@@ -24,9 +24,11 @@ endif
override COMPILE_SUBARCH := $(XEN_COMPILE_ARCH)
override TARGET_SUBARCH := $(XEN_TARGET_ARCH)
override COMPILE_ARCH := $(shell echo $(XEN_COMPILE_ARCH) | \
- sed -e 's/\(x86\|powerpc\).*/\1/')
+ sed -e 's/x86.*/x86/' \
+ -e 's/powerpc.*/powerpc/')
override TARGET_ARCH := $(shell echo $(XEN_TARGET_ARCH) | \
- sed -e 's/\(x86\|powerpc\).*/\1/')
+ sed -e 's/x86.*/x86/' \
+ -e 's/powerpc.*/powerpc/')
TARGET := $(BASEDIR)/xen
@@ -35,10 +37,6 @@ HDRS += $(wildcard $(BASEDIR)/include/public/*.h)
HDRS += $(wildcard $(BASEDIR)/include/asm-$(TARGET_ARCH)/*.h)
HDRS += $(wildcard $(BASEDIR)/include/asm-$(TARGET_ARCH)/$(TARGET_SUBARCH)/*.h)
-INSTALL := install
-INSTALL_DATA := $(INSTALL) -m0644
-INSTALL_DIR := $(INSTALL) -d -m0755
-
include $(BASEDIR)/arch/$(TARGET_ARCH)/Rules.mk
# Do not depend on auto-generated header files.
@@ -65,8 +63,16 @@ endif
AFLAGS-y += -D__ASSEMBLY__
ALL_OBJS := $(ALL_OBJS-y)
+
CFLAGS := $(strip $(CFLAGS) $(CFLAGS-y))
+
+# Most CFLAGS are safe for assembly files:
+# -std=gnu{89,99} gets confused by #-prefixed end-of-line comments
AFLAGS := $(strip $(AFLAGS) $(AFLAGS-y))
+AFLAGS += $(patsubst -std=gnu%,,$(CFLAGS))
+
+# LDFLAGS are only passed directly to $(LD)
+LDFLAGS := $(strip $(LDFLAGS) $(LDFLAGS_DIRECT))
include Makefile
@@ -104,10 +110,11 @@ _clean_%/: FORCE
$(CC) $(CFLAGS) -c $< -o $@
%.o: %.S $(HDRS) Makefile
- $(CC) $(CFLAGS) $(AFLAGS) -c $< -o $@
+ $(CC) $(AFLAGS) -c $< -o $@
%.i: %.c $(HDRS) Makefile
$(CPP) $(CFLAGS) $< -o $@
+# -std=gnu{89,99} gets confused by # as an end-of-line comment marker
%.s: %.S $(HDRS) Makefile
- $(CPP) $(CFLAGS) $(AFLAGS) $< -o $@
+ $(CPP) $(AFLAGS) $< -o $@
diff --git a/xen/acm/acm_chinesewall_hooks.c b/xen/acm/acm_chinesewall_hooks.c
index 8071cec1be..98aea6e428 100644
--- a/xen/acm/acm_chinesewall_hooks.c
+++ b/xen/acm/acm_chinesewall_hooks.c
@@ -154,6 +154,8 @@ static int chwall_dump_policy(u8 * buf, u32 buf_size)
ret = ntohl(chwall_buf->chwall_conflict_aggregate_offset) +
sizeof(domaintype_t) * chwall_bin_pol.max_types;
+ ret = (ret + 7) & ~7;
+
if (buf_size < ret)
return -EINVAL;
diff --git a/xen/acm/acm_core.c b/xen/acm/acm_core.c
index bafb177c3d..fdac3dd3e5 100644
--- a/xen/acm/acm_core.c
+++ b/xen/acm/acm_core.c
@@ -60,7 +60,7 @@ struct acm_operations *acm_secondary_ops = NULL;
/* acm global binary policy (points to 'local' primary and secondary policies */
struct acm_binary_policy acm_bin_pol;
/* acm binary policy lock */
-rwlock_t acm_bin_pol_rwlock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(acm_bin_pol_rwlock);
/* until we have endian support in Xen, we discover it at runtime */
u8 little_endian = 1;
@@ -100,9 +100,11 @@ acm_dump_policy_reference(u8 *buf, u32 buf_size)
struct acm_policy_reference_buffer *pr_buf = (struct acm_policy_reference_buffer *)buf;
int ret = sizeof(struct acm_policy_reference_buffer) + strlen(acm_bin_pol.policy_reference_name) + 1;
+ ret = (ret + 7) & ~7;
if (buf_size < ret)
return -EINVAL;
+ memset(buf, 0, ret);
pr_buf->len = htonl(strlen(acm_bin_pol.policy_reference_name) + 1); /* including stringend '\0' */
strcpy((char *)(buf + sizeof(struct acm_policy_reference_buffer)),
acm_bin_pol.policy_reference_name);
@@ -187,85 +189,58 @@ acm_init_binary_policy(u32 policy_code)
return ret;
}
+int
+acm_is_policy(char *buf, unsigned long len)
+{
+ struct acm_policy_buffer *pol;
+
+ if (buf == NULL || len < sizeof(struct acm_policy_buffer))
+ return 0;
+
+ pol = (struct acm_policy_buffer *)buf;
+ return ntohl(pol->magic) == ACM_MAGIC;
+}
+
+
static int
-acm_setup(unsigned int *initrdidx,
- const multiboot_info_t *mbi,
- unsigned long initial_images_start)
+acm_setup(char *policy_start,
+ unsigned long policy_len)
{
- int i;
- module_t *mod = (module_t *)__va(mbi->mods_addr);
int rc = ACM_OK;
+ struct acm_policy_buffer *pol;
+
+ if (policy_start == NULL || policy_len < sizeof(struct acm_policy_buffer))
+ return rc;
- if (mbi->mods_count > 1)
- *initrdidx = 1;
+ pol = (struct acm_policy_buffer *)policy_start;
+ if (ntohl(pol->magic) != ACM_MAGIC)
+ return rc;
- /*
- * Try all modules and see whichever could be the binary policy.
- * Adjust the initrdidx if module[1] is the binary policy.
- */
- for (i = mbi->mods_count-1; i >= 1; i--)
+ rc = do_acm_set_policy((void *)policy_start, (u32)policy_len);
+ if (rc == ACM_OK)
+ {
+ printkd("Policy len 0x%lx, start at %p.\n",policy_len,policy_start);
+ }
+ else
{
- struct acm_policy_buffer *pol;
- char *_policy_start;
- unsigned long _policy_len;
-#if defined(__i386__)
- _policy_start = (char *)(initial_images_start + (mod[i].mod_start-mod[0].mod_start));
-#elif defined(__x86_64__)
- _policy_start = __va(initial_images_start + (mod[i].mod_start-mod[0].mod_start));
-#else
-#error Architecture unsupported by sHype
-#endif
- _policy_len = mod[i].mod_end - mod[i].mod_start;
- if (_policy_len < sizeof(struct acm_policy_buffer))
- continue; /* not a policy */
-
- pol = (struct acm_policy_buffer *)_policy_start;
- if (ntohl(pol->magic) == ACM_MAGIC)
- {
- rc = do_acm_set_policy((void *)_policy_start,
- (u32)_policy_len);
- if (rc == ACM_OK)
- {
- printkd("Policy len 0x%lx, start at %p.\n",_policy_len,_policy_start);
- if (i == 1)
- {
- if (mbi->mods_count > 2)
- {
- *initrdidx = 2;
- }
- else {
- *initrdidx = 0;
- }
- }
- else
- {
- *initrdidx = 1;
- }
- break;
- }
- else
- {
- printk("Invalid policy. %d.th module line.\n", i+1);
- /* load default policy later */
- acm_active_security_policy = ACM_POLICY_UNDEFINED;
- }
- } /* end if a binary policy definition, i.e., (ntohl(pol->magic) == ACM_MAGIC ) */
+ printk("Invalid policy.\n");
+ /* load default policy later */
+ acm_active_security_policy = ACM_POLICY_UNDEFINED;
}
return rc;
}
int
-acm_init(unsigned int *initrdidx,
- const multiboot_info_t *mbi,
- unsigned long initial_images_start)
+acm_init(char *policy_start,
+ unsigned long policy_len)
{
int ret = ACM_OK;
acm_set_endian();
/* first try to load the boot policy (uses its own locks) */
- acm_setup(initrdidx, mbi, initial_images_start);
+ acm_setup(policy_start, policy_len);
if (acm_active_security_policy != ACM_POLICY_UNDEFINED)
{
diff --git a/xen/acm/acm_simple_type_enforcement_hooks.c b/xen/acm/acm_simple_type_enforcement_hooks.c
index 0f8c8c3818..77e1062408 100644
--- a/xen/acm/acm_simple_type_enforcement_hooks.c
+++ b/xen/acm/acm_simple_type_enforcement_hooks.c
@@ -150,6 +150,8 @@ ste_dump_policy(u8 *buf, u32 buf_size) {
ret = ntohl(ste_buf->ste_ssid_offset) +
sizeof(domaintype_t)*ste_bin_pol.max_ssidrefs*ste_bin_pol.max_types;
+ ret = (ret + 7) & ~7;
+
if (buf_size < ret)
return -EINVAL;
diff --git a/xen/arch/ia64/Rules.mk b/xen/arch/ia64/Rules.mk
index fc11c5e5f8..8f69704d7d 100644
--- a/xen/arch/ia64/Rules.mk
+++ b/xen/arch/ia64/Rules.mk
@@ -18,8 +18,6 @@ endif
# Used only by linux/Makefile.
AFLAGS_KERNEL += -mconstant-gp -nostdinc $(CPPFLAGS)
-# Note: .S -> .o rule uses AFLAGS and CFLAGS.
-
CFLAGS += -nostdinc -fno-builtin -fno-common -fno-strict-aliasing
CFLAGS += -mconstant-gp
#CFLAGS += -O3 # -O3 over-inlines making debugging tough!
diff --git a/xen/arch/ia64/linux-xen/smpboot.c b/xen/arch/ia64/linux-xen/smpboot.c
index ac96fb8cc9..4450ce9260 100644
--- a/xen/arch/ia64/linux-xen/smpboot.c
+++ b/xen/arch/ia64/linux-xen/smpboot.c
@@ -650,7 +650,8 @@ clear_cpu_sibling_map(int cpu)
for_each_cpu_mask(i, cpu_core_map[cpu])
cpu_clear(cpu, cpu_core_map[i]);
- cpu_sibling_map[cpu] = cpu_core_map[cpu] = CPU_MASK_NONE;
+ cpus_clear(cpu_sibling_map[cpu]);
+ cpus_clear(cpu_core_map[cpu]);
}
static void
diff --git a/xen/arch/ia64/xen/xenmisc.c b/xen/arch/ia64/xen/xenmisc.c
index e9bb00c480..fceb2bfe29 100644
--- a/xen/arch/ia64/xen/xenmisc.c
+++ b/xen/arch/ia64/xen/xenmisc.c
@@ -165,6 +165,10 @@ void arch_dump_domain_info(struct domain *d)
{
}
+void arch_dump_vcpu_info(struct vcpu *v)
+{
+}
+
void audit_domains_key(unsigned char key)
{
}
diff --git a/xen/arch/powerpc/Makefile b/xen/arch/powerpc/Makefile
index 837364acc1..5db65c2c7c 100644
--- a/xen/arch/powerpc/Makefile
+++ b/xen/arch/powerpc/Makefile
@@ -141,7 +141,7 @@ asm-offsets.s: $(TARGET_SUBARCH)/asm-offsets.c $(HDRS)
$(CC) $(CFLAGS) -S -o $@ $<
xen.lds: xen.lds.S $(HDRS)
- $(CC) $(CFLAGS) -P -E $(AFLAGS) -o $@ $<
+ $(CC) -P -E $(AFLAGS) -o $@ $<
dom0.bin: $(DOM0_IMAGE)
cp $< $@
diff --git a/xen/arch/powerpc/domain.c b/xen/arch/powerpc/domain.c
index 29bdd54ba8..ed52491f19 100644
--- a/xen/arch/powerpc/domain.c
+++ b/xen/arch/powerpc/domain.c
@@ -286,6 +286,10 @@ void arch_dump_domain_info(struct domain *d)
{
}
+void arch_dump_vcpu_info(struct vcpu *v)
+{
+}
+
extern void sleep(void);
static void safe_halt(void)
{
diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
index e303ec7b59..31f2793fb9 100644
--- a/xen/arch/x86/Makefile
+++ b/xen/arch/x86/Makefile
@@ -46,8 +46,7 @@ obj-$(crash_debug) += gdbstub.o
$(TARGET): $(TARGET)-syms boot/mkelf32
./boot/mkelf32 $(TARGET)-syms $(TARGET) 0x100000 \
- `$(NM) $(TARGET)-syms | sort | tail -n 1 | \
- sed -e 's/^\([^ ]*\).*/0x\1/'`
+ `$(NM) -nr $(TARGET)-syms | head -n 1 | sed -e 's/^\([^ ]*\).*/0x\1/'`
$(TARGET)-syms: boot/$(TARGET_SUBARCH).o $(ALL_OBJS) xen.lds
$(MAKE) -f $(BASEDIR)/Rules.mk $(BASEDIR)/common/symbols-dummy.o
@@ -70,7 +69,7 @@ asm-offsets.s: $(TARGET_SUBARCH)/asm-offsets.c $(HDRS)
$(CC) $(CFLAGS) -S -o $@ $<
xen.lds: $(TARGET_SUBARCH)/xen.lds.S $(HDRS)
- $(CC) $(CFLAGS) -P -E -Ui386 $(AFLAGS) -o $@ $<
+ $(CC) -P -E -Ui386 $(AFLAGS) -o $@ $<
boot/mkelf32: boot/mkelf32.c
$(HOSTCC) $(HOSTCFLAGS) -o $@ $<
diff --git a/xen/arch/x86/Rules.mk b/xen/arch/x86/Rules.mk
index 176d6aebf4..fc4241fafb 100644
--- a/xen/arch/x86/Rules.mk
+++ b/xen/arch/x86/Rules.mk
@@ -11,41 +11,44 @@ HAS_VGA := y
pae ?= n
supervisor_mode_kernel ?= n
-CFLAGS += -nostdinc -fno-builtin -fno-common -fno-strict-aliasing
-CFLAGS += -iwithprefix include -Werror -Wno-pointer-arith -pipe
-CFLAGS += -I$(BASEDIR)/include
-CFLAGS += -I$(BASEDIR)/include/asm-x86/mach-generic
-CFLAGS += -I$(BASEDIR)/include/asm-x86/mach-default
+# Solaris grabs stdarg.h and friends from the system include directory.
+ifneq ($(XEN_OS),SunOS)
+CFLAGS += -nostdinc
+endif
+
+CFLAGS += -fno-builtin -fno-common -fno-strict-aliasing
+CFLAGS += -iwithprefix include -Werror -Wno-pointer-arith -pipe
+CFLAGS += -I$(BASEDIR)/include
+CFLAGS += -I$(BASEDIR)/include/asm-x86/mach-generic
+CFLAGS += -I$(BASEDIR)/include/asm-x86/mach-default
# Prevent floating-point variables from creeping into Xen.
-CFLAGS += -msoft-float
+CFLAGS += -msoft-float
# Disable PIE/SSP if GCC supports them. They can break us.
-CFLAGS += $(call test-gcc-flag,$(CC),-nopie)
-CFLAGS += $(call test-gcc-flag,$(CC),-fno-stack-protector)
-CFLAGS += $(call test-gcc-flag,$(CC),-fno-stack-protector-all)
+CFLAGS += $(call cc-option,$(CC),-nopie,)
+CFLAGS += $(call cc-option,$(CC),-fno-stack-protector,)
+CFLAGS += $(call cc-option,$(CC),-fno-stack-protector-all,)
ifeq ($(TARGET_SUBARCH)$(pae),x86_32y)
-CFLAGS += -DCONFIG_X86_PAE=1
+CFLAGS += -DCONFIG_X86_PAE=1
endif
ifeq ($(supervisor_mode_kernel),y)
-CFLAGS += -DCONFIG_X86_SUPERVISOR_MODE_KERNEL=1
+CFLAGS += -DCONFIG_X86_SUPERVISOR_MODE_KERNEL=1
endif
ifeq ($(XEN_TARGET_ARCH),x86_32)
-LDFLAGS += -m elf_i386
x86_32 := y
x86_64 := n
endif
ifeq ($(TARGET_SUBARCH),x86_64)
-CFLAGS += -mno-red-zone -fpic -fno-reorder-blocks
-CFLAGS += -fno-asynchronous-unwind-tables
+CFLAGS += -mno-red-zone -fpic -fno-reorder-blocks
+CFLAGS += -fno-asynchronous-unwind-tables
# -fvisibility=hidden reduces -fpic cost, if it's available
-CFLAGS += $(shell $(CC) -v --help 2>&1 | grep " -fvisibility=" | \
- grep -q hidden && echo "-DGCC_HAS_VISIBILITY_ATTRIBUTE")
-LDFLAGS += -m elf_x86_64
+CFLAGS += $(call cc-option,$(CC),-fvisibility=hidden,)
+CFLAGS := $(subst -fvisibility=hidden,-DGCC_HAS_VISIBILITY_ATTRIBUTE,$(CFLAGS))
x86_32 := n
x86_64 := y
endif
diff --git a/xen/arch/x86/boot/mkelf32.c b/xen/arch/x86/boot/mkelf32.c
index 53cc514295..18e52b5836 100644
--- a/xen/arch/x86/boot/mkelf32.c
+++ b/xen/arch/x86/boot/mkelf32.c
@@ -90,6 +90,11 @@ static Elf32_Shdr out_shdr[] = {
}
};
+/* Some system header files define these macros and pollute our namespace. */
+#undef swap16
+#undef swap32
+#undef swap64
+
#define swap16(_v) ((((u16)(_v)>>8)&0xff)|(((u16)(_v)&0xff)<<8))
#define swap32(_v) (((u32)swap16((u16)(_v))<<16)|(u32)swap16((u32)((_v)>>16)))
#define swap64(_v) (((u64)swap32((u32)(_v))<<32)|(u64)swap32((u32)((_v)>>32)))
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index be19507d59..53d22417dc 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -1003,6 +1003,20 @@ void arch_dump_domain_info(struct domain *d)
}
}
+void arch_dump_vcpu_info(struct vcpu *v)
+{
+ if ( shadow_mode_enabled(v->domain) )
+ {
+ if ( v->arch.shadow.mode )
+ printk(" shadowed %u-on-%u, %stranslated\n",
+ v->arch.shadow.mode->guest_levels,
+ v->arch.shadow.mode->shadow_levels,
+ shadow_vcpu_mode_translate(v) ? "" : "not ");
+ else
+ printk(" not shadowed\n");
+ }
+}
+
/*
* Local variables:
* mode: C
diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c
index f858adab51..b8765be263 100644
--- a/xen/arch/x86/domain_build.c
+++ b/xen/arch/x86/domain_build.c
@@ -286,7 +286,8 @@ int construct_dom0(struct domain *d,
nr_pages = avail_domheap_pages() + initial_images_nrpages() +
dom0_nrpages;
else
- nr_pages = dom0_nrpages;
+ nr_pages = min(avail_domheap_pages() + initial_images_nrpages(),
+ (unsigned long)dom0_nrpages);
if ( (rc = parseelfimage(&dsi)) != 0 )
return rc;
@@ -668,6 +669,8 @@ int construct_dom0(struct domain *d,
if ( opt_dom0_max_vcpus == 0 )
opt_dom0_max_vcpus = num_online_cpus();
+ if ( opt_dom0_max_vcpus > num_online_cpus() )
+ opt_dom0_max_vcpus = num_online_cpus();
if ( opt_dom0_max_vcpus > MAX_VIRT_CPUS )
opt_dom0_max_vcpus = MAX_VIRT_CPUS;
printk("Dom0 has maximum %u VCPUs\n", opt_dom0_max_vcpus);
diff --git a/xen/arch/x86/hvm/Makefile b/xen/arch/x86/hvm/Makefile
index 0f6e80f644..37623ff5eb 100644
--- a/xen/arch/x86/hvm/Makefile
+++ b/xen/arch/x86/hvm/Makefile
@@ -4,6 +4,7 @@ subdir-y += vmx
obj-y += hvm.o
obj-y += i8254.o
obj-y += i8259.o
+obj-y += rtc.o
obj-y += instrlen.o
obj-y += intercept.o
obj-y += io.o
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 06b8de63d9..34afeb46e6 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -40,8 +40,10 @@
#include <asm/processor.h>
#include <asm/types.h>
#include <asm/msr.h>
+#include <asm/mc146818rtc.h>
#include <asm/spinlock.h>
#include <asm/hvm/hvm.h>
+#include <asm/hvm/vpit.h>
#include <asm/hvm/support.h>
#include <public/sched.h>
#include <public/hvm/ioreq.h>
@@ -277,6 +279,7 @@ void hvm_setup_platform(struct domain* d)
init_timer(&platform->pl_time.periodic_tm.timer,
pt_timer_fn, v, v->processor);
pit_init(v, cpu_khz);
+ rtc_init(v, RTC_PORT(0), RTC_IRQ);
}
void pic_irq_request(void *data, int level)
@@ -368,7 +371,7 @@ void hvm_hlt(unsigned long rflags)
{
struct vcpu *v = current;
struct periodic_time *pt = &v->domain->arch.hvm_domain.pl_time.periodic_tm;
- s_time_t next_pit = -1, next_wakeup;
+ s_time_t next_pt = -1, next_wakeup;
/*
* If we halt with interrupts disabled, that's a pretty sure sign that we
@@ -379,10 +382,10 @@ void hvm_hlt(unsigned long rflags)
return hvm_vcpu_down();
if ( !v->vcpu_id )
- next_pit = get_scheduled(v, pt->irq, pt);
+ next_pt = get_scheduled(v, pt->irq, pt);
next_wakeup = get_apictime_scheduled(v);
- if ( (next_pit != -1 && next_pit < next_wakeup) || next_wakeup == -1 )
- next_wakeup = next_pit;
+ if ( (next_pt != -1 && next_pt < next_wakeup) || next_wakeup == -1 )
+ next_wakeup = next_pt;
if ( next_wakeup != - 1 )
set_timer(&current->arch.hvm_vcpu.hlt_timer, next_wakeup);
do_sched_op_compat(SCHEDOP_block, 0);
diff --git a/xen/arch/x86/hvm/i8254.c b/xen/arch/x86/hvm/i8254.c
index 6b817293b9..5f27ee25b2 100644
--- a/xen/arch/x86/hvm/i8254.c
+++ b/xen/arch/x86/hvm/i8254.c
@@ -49,7 +49,6 @@
#define RW_STATE_WORD0 3
#define RW_STATE_WORD1 4
-#define ticks_per_sec(v) (v->domain->arch.hvm_domain.tsc_frequency)
static int handle_pit_io(ioreq_t *p);
static int handle_speaker_io(ioreq_t *p);
@@ -77,17 +76,6 @@ uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
return res.ll;
}
-/*
- * get processor time.
- * unit: TSC
- */
-int64_t hvm_get_clock(struct vcpu *v)
-{
- uint64_t gtsc;
- gtsc = hvm_get_guest_time(v);
- return gtsc;
-}
-
static int pit_get_count(PITChannelState *s)
{
uint64_t d;
@@ -215,11 +203,11 @@ static inline void pit_load_count(PITChannelState *s, int val)
switch (s->mode) {
case 2:
/* create periodic time */
- s->pt = create_periodic_time (s, period, 0, 0);
+ s->pt = create_periodic_time (period, 0, 0, pit_time_fired, s);
break;
case 1:
/* create one shot time */
- s->pt = create_periodic_time (s, period, 0, 1);
+ s->pt = create_periodic_time (period, 0, 1, pit_time_fired, s);
#ifdef DEBUG_PIT
printk("HVM_PIT: create one shot time.\n");
#endif
diff --git a/xen/arch/x86/hvm/i8259.c b/xen/arch/x86/hvm/i8259.c
index e90f365044..64689e4a8d 100644
--- a/xen/arch/x86/hvm/i8259.c
+++ b/xen/arch/x86/hvm/i8259.c
@@ -498,19 +498,19 @@ void pic_init(struct hvm_virpic *s, void (*irq_request)(void *, int),
static int intercept_pic_io(ioreq_t *p)
{
- struct hvm_virpic *pic;
- struct vcpu *v = current;
+ struct hvm_virpic *pic;
uint32_t data;
unsigned long flags;
-
- if ( p->size != 1 || p->count != 1) {
+
+ if ( p->size != 1 || p->count != 1 ) {
printk("PIC_IO wrong access size %d!\n", (int)p->size);
return 1;
}
- pic = &v->domain->arch.hvm_domain.vpic;
- if ( p->dir == 0 ) {
- if (p->pdata_valid)
- (void)hvm_copy_from_guest_virt(
+
+ pic = &current->domain->arch.hvm_domain.vpic;
+ if ( p->dir == IOREQ_WRITE ) {
+ if ( p->pdata_valid )
+ (void)hvm_copy_from_guest_phys(
&data, (unsigned long)p->u.pdata, p->size);
else
data = p->u.data;
@@ -524,10 +524,10 @@ static int intercept_pic_io(ioreq_t *p)
data = pic_ioport_read(
(void*)&pic->pics[p->addr>>7], (uint32_t) p->addr);
spin_unlock_irqrestore(&pic->lock, flags);
- if (p->pdata_valid)
- (void)hvm_copy_to_guest_virt(
+ if ( p->pdata_valid )
+ (void)hvm_copy_to_guest_phys(
(unsigned long)p->u.pdata, &data, p->size);
- else
+ else
p->u.data = (u64)data;
}
return 1;
@@ -535,42 +535,41 @@ static int intercept_pic_io(ioreq_t *p)
static int intercept_elcr_io(ioreq_t *p)
{
- struct hvm_virpic *s;
- struct vcpu *v = current;
+ struct hvm_virpic *s;
uint32_t data;
unsigned long flags;
-
+
if ( p->size != 1 || p->count != 1 ) {
printk("PIC_IO wrong access size %d!\n", (int)p->size);
return 1;
}
- s = &v->domain->arch.hvm_domain.vpic;
- if ( p->dir == 0 ) {
- if (p->pdata_valid)
- (void)hvm_copy_from_guest_virt(
+ s = &current->domain->arch.hvm_domain.vpic;
+ if ( p->dir == IOREQ_WRITE ) {
+ if ( p->pdata_valid )
+ (void)hvm_copy_from_guest_phys(
&data, (unsigned long)p->u.pdata, p->size);
else
data = p->u.data;
spin_lock_irqsave(&s->lock, flags);
elcr_ioport_write((void*)&s->pics[p->addr&1],
(uint32_t) p->addr, (uint32_t)( data & 0xff));
- get_sp(current->domain)->sp_global.pic_elcr =
+ get_sp(current->domain)->sp_global.pic_elcr =
s->pics[0].elcr | ((u16)s->pics[1].elcr << 8);
spin_unlock_irqrestore(&s->lock, flags);
}
else {
data = (u64) elcr_ioport_read(
(void*)&s->pics[p->addr&1], (uint32_t) p->addr);
- if (p->pdata_valid)
- (void)hvm_copy_to_guest_virt(
+ if ( p->pdata_valid )
+ (void)hvm_copy_to_guest_phys(
(unsigned long)p->u.pdata, &data, p->size);
- else
+ else
p->u.data = (u64)data;
-
}
return 1;
}
+
void register_pic_io_hook (void)
{
register_portio_handler(0x20, 2, intercept_pic_io);
@@ -599,23 +598,47 @@ int cpu_get_pic_interrupt(struct vcpu *v, int *type)
return intno;
}
-int is_pit_irq(struct vcpu *v, int irq, int type)
+int is_periodic_irq(struct vcpu *v, int irq, int type)
{
- int pit_vec;
+ int vec;
+ struct periodic_time *pt =
+ &(v->domain->arch.hvm_domain.pl_time.periodic_tm);
+ struct RTCState *vrtc =
+ &(v->domain->arch.hvm_domain.pl_time.vrtc);
+
+ if (pt->irq == 0) { /* Is it pit irq? */
+ if (type == APIC_DM_EXTINT)
+ vec = v->domain->arch.hvm_domain.vpic.pics[0].irq_base;
+ else
+ vec =
+ v->domain->arch.hvm_domain.vioapic.redirtbl[0].RedirForm.vector;
- if (type == APIC_DM_EXTINT)
- pit_vec = v->domain->arch.hvm_domain.vpic.pics[0].irq_base;
- else
- pit_vec =
- v->domain->arch.hvm_domain.vioapic.redirtbl[0].RedirForm.vector;
+ if (irq == vec)
+ return 1;
+ }
- return (irq == pit_vec);
+ if (pt->irq == 8) { /* Or rtc irq? */
+ if (type == APIC_DM_EXTINT)
+ vec = v->domain->arch.hvm_domain.vpic.pics[1].irq_base;
+ else
+ vec =
+ v->domain->arch.hvm_domain.vioapic.redirtbl[8].RedirForm.vector;
+
+ if (irq == vec)
+ return is_rtc_periodic_irq(vrtc);
+ }
+
+ return 0;
}
int is_irq_enabled(struct vcpu *v, int irq)
{
+ struct hvm_vioapic *vioapic = &v->domain->arch.hvm_domain.vioapic;
struct hvm_virpic *vpic=&v->domain->arch.hvm_domain.vpic;
-
+
+ if (vioapic->redirtbl[irq].RedirForm.mask == 0)
+ return 1;
+
if ( irq & 8 ) {
return !( (1 << (irq&7)) & vpic->pics[1].imr);
}
diff --git a/xen/arch/x86/hvm/intercept.c b/xen/arch/x86/hvm/intercept.c
index 300f283825..288cf2724d 100644
--- a/xen/arch/x86/hvm/intercept.c
+++ b/xen/arch/x86/hvm/intercept.c
@@ -61,49 +61,39 @@ static inline void hvm_mmio_access(struct vcpu *v,
hvm_mmio_read_t read_handler,
hvm_mmio_write_t write_handler)
{
- ioreq_t *req;
- vcpu_iodata_t *vio = get_vio(v->domain, v->vcpu_id);
unsigned int tmp1, tmp2;
unsigned long data;
- if (vio == NULL) {
- printk("vlapic_access: bad shared page\n");
- domain_crash_synchronous();
- }
-
- req = &vio->vp_ioreq;
-
- switch (req->type) {
+ switch ( p->type ) {
case IOREQ_TYPE_COPY:
{
- int sign = (req->df) ? -1 : 1, i;
-
- if (!req->pdata_valid) {
- if (req->dir == IOREQ_READ){
- req->u.data = read_handler(v, req->addr, req->size);
- } else { /* req->dir != IOREQ_READ */
- write_handler(v, req->addr, req->size, req->u.data);
- }
- } else { /* !req->pdata_valid */
- if (req->dir == IOREQ_READ) {
- for (i = 0; i < req->count; i++) {
+ if ( !p->pdata_valid ) {
+ if ( p->dir == IOREQ_READ )
+ p->u.data = read_handler(v, p->addr, p->size);
+ else /* p->dir == IOREQ_WRITE */
+ write_handler(v, p->addr, p->size, p->u.data);
+ } else { /* !p->pdata_valid */
+ int i, sign = (p->df) ? -1 : 1;
+
+ if ( p->dir == IOREQ_READ ) {
+ for ( i = 0; i < p->count; i++ ) {
data = read_handler(v,
- req->addr + (sign * i * req->size),
- req->size);
- (void)hvm_copy_to_guest_virt(
- (unsigned long)p->u.pdata + (sign * i * req->size),
+ p->addr + (sign * i * p->size),
+ p->size);
+ (void)hvm_copy_to_guest_phys(
+ (unsigned long)p->u.pdata + (sign * i * p->size),
&data,
p->size);
}
- } else { /* !req->dir == IOREQ_READ */
- for (i = 0; i < req->count; i++) {
- (void)hvm_copy_from_guest_virt(
+ } else {/* p->dir == IOREQ_WRITE */
+ for ( i = 0; i < p->count; i++ ) {
+ (void)hvm_copy_from_guest_phys(
&data,
- (unsigned long)p->u.pdata + (sign * i * req->size),
+ (unsigned long)p->u.pdata + (sign * i * p->size),
p->size);
write_handler(v,
- req->addr + (sign * i * req->size),
- req->size, data);
+ p->addr + (sign * i * p->size),
+ p->size, data);
}
}
}
@@ -111,44 +101,44 @@ static inline void hvm_mmio_access(struct vcpu *v,
}
case IOREQ_TYPE_AND:
- tmp1 = read_handler(v, req->addr, req->size);
- if (req->dir == IOREQ_WRITE) {
- tmp2 = tmp1 & (unsigned long) req->u.data;
- write_handler(v, req->addr, req->size, tmp2);
+ tmp1 = read_handler(v, p->addr, p->size);
+ if ( p->dir == IOREQ_WRITE ) {
+ tmp2 = tmp1 & (unsigned long) p->u.data;
+ write_handler(v, p->addr, p->size, tmp2);
}
- req->u.data = tmp1;
+ p->u.data = tmp1;
break;
case IOREQ_TYPE_OR:
- tmp1 = read_handler(v, req->addr, req->size);
- if (req->dir == IOREQ_WRITE) {
- tmp2 = tmp1 | (unsigned long) req->u.data;
- write_handler(v, req->addr, req->size, tmp2);
+ tmp1 = read_handler(v, p->addr, p->size);
+ if ( p->dir == IOREQ_WRITE ) {
+ tmp2 = tmp1 | (unsigned long) p->u.data;
+ write_handler(v, p->addr, p->size, tmp2);
}
- req->u.data = tmp1;
+ p->u.data = tmp1;
break;
case IOREQ_TYPE_XOR:
- tmp1 = read_handler(v, req->addr, req->size);
- if (req->dir == IOREQ_WRITE) {
- tmp2 = tmp1 ^ (unsigned long) req->u.data;
- write_handler(v, req->addr, req->size, tmp2);
+ tmp1 = read_handler(v, p->addr, p->size);
+ if ( p->dir == IOREQ_WRITE ) {
+ tmp2 = tmp1 ^ (unsigned long) p->u.data;
+ write_handler(v, p->addr, p->size, tmp2);
}
- req->u.data = tmp1;
+ p->u.data = tmp1;
break;
case IOREQ_TYPE_XCHG:
- /*
+ /*
* Note that we don't need to be atomic here since VCPU is accessing
* its own local APIC.
*/
- tmp1 = read_handler(v, req->addr, req->size);
- write_handler(v, req->addr, req->size, (unsigned long) req->u.data);
- req->u.data = tmp1;
+ tmp1 = read_handler(v, p->addr, p->size);
+ write_handler(v, p->addr, p->size, (unsigned long) p->u.data);
+ p->u.data = tmp1;
break;
default:
- printk("error ioreq type for local APIC %x\n", req->type);
+ printk("hvm_mmio_access: error ioreq type %x\n", p->type);
domain_crash_synchronous();
break;
}
@@ -270,12 +260,11 @@ int register_io_handler(unsigned long addr, unsigned long size,
return 1;
}
-/* hooks function for the HLT instruction emulation wakeup */
+/* Hook function for the HLT instruction emulation wakeup. */
void hlt_timer_fn(void *data)
{
struct vcpu *v = data;
-
- hvm_prod_vcpu(v);
+ vcpu_kick(v);
}
static __inline__ void missed_ticks(struct periodic_time *pt)
@@ -325,17 +314,14 @@ void pickup_deactive_ticks(struct periodic_time *pt)
* period: fire frequency in ns.
*/
struct periodic_time * create_periodic_time(
- PITChannelState *s,
u32 period,
char irq,
- char one_shot)
+ char one_shot,
+ time_cb *cb,
+ void *data)
{
- struct vcpu *v = s->vcpu;
- struct periodic_time *pt = &(v->domain->arch.hvm_domain.pl_time.periodic_tm);
+ struct periodic_time *pt = &(current->domain->arch.hvm_domain.pl_time.periodic_tm);
if ( pt->enabled ) {
- if ( v->vcpu_id != 0 ) {
- printk("HVM_PIT: start 2nd periodic time on non BSP!\n");
- }
stop_timer (&pt->timer);
pt->enabled = 0;
}
@@ -355,7 +341,8 @@ struct periodic_time * create_periodic_time(
pt->scheduled = NOW() + period;
set_timer (&pt->timer,pt->scheduled);
pt->enabled = 1;
- pt->priv = s;
+ pt->cb = cb;
+ pt->priv = data;
return pt;
}
diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c
index f91f37f95d..da6224e938 100644
--- a/xen/arch/x86/hvm/io.c
+++ b/xen/arch/x86/hvm/io.c
@@ -369,18 +369,18 @@ static void hvm_pio_assist(struct cpu_user_regs *regs, ioreq_t *p,
{
if ( pio_opp->flags & REPZ )
regs->ecx -= p->count;
+
if ( p->dir == IOREQ_READ )
{
- regs->edi += sign * p->count * p->size;
if ( pio_opp->flags & OVERLAP )
{
- unsigned long addr = regs->edi;
- if (hvm_realmode(current))
- addr += regs->es << 4;
- if (sign > 0)
- addr -= p->size;
- (void)hvm_copy_to_guest_virt(addr, &p->u.data, p->size);
+ unsigned long addr = pio_opp->addr;
+ if ( hvm_paging_enabled(current) )
+ (void)hvm_copy_to_guest_virt(addr, &p->u.data, p->size);
+ else
+ (void)hvm_copy_to_guest_phys(addr, &p->u.data, p->size);
}
+ regs->edi += sign * p->count * p->size;
}
else /* p->dir == IOREQ_WRITE */
{
@@ -485,19 +485,22 @@ static void hvm_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
case INSTR_MOVS:
sign = p->df ? -1 : 1;
- regs->esi += sign * p->count * p->size;
- regs->edi += sign * p->count * p->size;
+
+ if (mmio_opp->flags & REPZ)
+ regs->ecx -= p->count;
if ((mmio_opp->flags & OVERLAP) && p->dir == IOREQ_READ) {
- unsigned long addr = regs->edi;
+ unsigned long addr = mmio_opp->addr;
- if (sign > 0)
- addr -= p->size;
- (void)hvm_copy_to_guest_virt(addr, &p->u.data, p->size);
+ if (hvm_paging_enabled(current))
+ (void)hvm_copy_to_guest_virt(addr, &p->u.data, p->size);
+ else
+ (void)hvm_copy_to_guest_phys(addr, &p->u.data, p->size);
}
- if (mmio_opp->flags & REPZ)
- regs->ecx -= p->count;
+ regs->esi += sign * p->count * p->size;
+ regs->edi += sign * p->count * p->size;
+
break;
case INSTR_STOS:
@@ -680,7 +683,7 @@ void hvm_interrupt_post(struct vcpu *v, int vector, int type)
struct periodic_time *pt =
&(v->domain->arch.hvm_domain.pl_time.periodic_tm);
- if ( is_pit_irq(v, vector, type) ) {
+ if ( pt->enabled && is_periodic_irq(v, vector, type) ) {
if ( !pt->first_injected ) {
pt->pending_intr_nr = 0;
pt->last_plt_gtime = hvm_get_guest_time(v);
@@ -691,8 +694,9 @@ void hvm_interrupt_post(struct vcpu *v, int vector, int type)
pt->pending_intr_nr--;
pt->last_plt_gtime += pt->period_cycles;
hvm_set_guest_time(v, pt->last_plt_gtime);
- pit_time_fired(v, pt->priv);
}
+ if (pt->cb)
+ pt->cb(v, pt->priv);
}
switch(type) {
diff --git a/xen/arch/x86/hvm/platform.c b/xen/arch/x86/hvm/platform.c
index 3440765269..e52464c0dc 100644
--- a/xen/arch/x86/hvm/platform.c
+++ b/xen/arch/x86/hvm/platform.c
@@ -30,6 +30,7 @@
#include <asm/regs.h>
#include <asm/hvm/hvm.h>
#include <asm/hvm/support.h>
+#include <asm/hvm/io.h>
#include <public/hvm/ioreq.h>
#include <xen/lib.h>
@@ -39,10 +40,13 @@
#define DECODE_success 1
#define DECODE_failure 0
+#define mk_operand(size_reg, index, seg, flag) \
+ (((size_reg) << 24) | ((index) << 16) | ((seg) << 8) | (flag))
+
#if defined (__x86_64__)
static inline long __get_reg_value(unsigned long reg, int size)
{
- switch(size) {
+ switch ( size ) {
case BYTE_64:
return (char)(reg & 0xFF);
case WORD:
@@ -59,8 +63,8 @@ static inline long __get_reg_value(unsigned long reg, int size)
long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs)
{
- if (size == BYTE) {
- switch (index) {
+ if ( size == BYTE ) {
+ switch ( index ) {
case 0: /* %al */
return (char)(regs->rax & 0xFF);
case 1: /* %cl */
@@ -84,7 +88,7 @@ long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs)
/* NOTREACHED */
}
- switch (index) {
+ switch ( index ) {
case 0: return __get_reg_value(regs->rax, size);
case 1: return __get_reg_value(regs->rcx, size);
case 2: return __get_reg_value(regs->rdx, size);
@@ -109,7 +113,7 @@ long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs)
#elif defined (__i386__)
static inline long __get_reg_value(unsigned long reg, int size)
{
- switch(size) {
+ switch ( size ) {
case WORD:
return (short)(reg & 0xFFFF);
case LONG:
@@ -122,8 +126,8 @@ static inline long __get_reg_value(unsigned long reg, int size)
long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs)
{
- if (size == BYTE) {
- switch (index) {
+ if ( size == BYTE ) {
+ switch ( index ) {
case 0: /* %al */
return (char)(regs->eax & 0xFF);
case 1: /* %cl */
@@ -146,7 +150,7 @@ long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs)
}
}
- switch (index) {
+ switch ( index ) {
case 0: return __get_reg_value(regs->eax, size);
case 1: return __get_reg_value(regs->ecx, size);
case 2: return __get_reg_value(regs->edx, size);
@@ -163,19 +167,21 @@ long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs)
#endif
static inline unsigned char *check_prefix(unsigned char *inst,
- struct instruction *thread_inst, unsigned char *rex_p)
+ struct hvm_io_op *mmio_op,
+ unsigned char *op_size,
+ unsigned char *rex_p)
{
- while (1) {
- switch (*inst) {
+ while ( 1 ) {
+ switch ( *inst ) {
/* rex prefix for em64t instructions */
case 0x40 ... 0x4e:
*rex_p = *inst;
break;
case 0xf3: /* REPZ */
- thread_inst->flags = REPZ;
+ mmio_op->flags = REPZ;
break;
case 0xf2: /* REPNZ */
- thread_inst->flags = REPNZ;
+ mmio_op->flags = REPNZ;
break;
case 0xf0: /* LOCK */
break;
@@ -185,10 +191,10 @@ static inline unsigned char *check_prefix(unsigned char *inst,
case 0x26: /* ES */
case 0x64: /* FS */
case 0x65: /* GS */
- thread_inst->seg_sel = *inst;
+ //mmio_op->seg_sel = *inst;
break;
case 0x66: /* 32bit->16bit */
- thread_inst->op_size = WORD;
+ *op_size = WORD;
break;
case 0x67:
break;
@@ -199,7 +205,7 @@ static inline unsigned char *check_prefix(unsigned char *inst,
}
}
-static inline unsigned long get_immediate(int op16,const unsigned char *inst, int op_size)
+static inline unsigned long get_immediate(int op16, const unsigned char *inst, int op_size)
{
int mod, reg, rm;
unsigned long val = 0;
@@ -210,14 +216,14 @@ static inline unsigned long get_immediate(int op16,const unsigned char *inst, in
rm = *inst & 7;
inst++; //skip ModR/M byte
- if (mod != 3 && rm == 4) {
+ if ( mod != 3 && rm == 4 ) {
inst++; //skip SIB byte
}
- switch(mod) {
+ switch ( mod ) {
case 0:
- if (rm == 5 || rm == 4) {
- if (op16)
+ if ( rm == 5 || rm == 4 ) {
+ if ( op16 )
inst = inst + 2; //disp16, skip 2 bytes
else
inst = inst + 4; //disp32, skip 4 bytes
@@ -227,17 +233,17 @@ static inline unsigned long get_immediate(int op16,const unsigned char *inst, in
inst++; //disp8, skip 1 byte
break;
case 2:
- if (op16)
+ if ( op16 )
inst = inst + 2; //disp16, skip 2 bytes
else
inst = inst + 4; //disp32, skip 4 bytes
break;
}
- if (op_size == QUAD)
+ if ( op_size == QUAD )
op_size = LONG;
- for (i = 0; i < op_size; i++) {
+ for ( i = 0; i < op_size; i++ ) {
val |= (*inst++ & 0xff) << (8 * i);
}
@@ -257,7 +263,7 @@ static inline int get_index(const unsigned char *inst, unsigned char rex)
rex_b = rex & 1;
//Only one operand in the instruction is register
- if (mod == 3) {
+ if ( mod == 3 ) {
return (rm + (rex_b << 3));
} else {
return (reg + (rex_r << 3));
@@ -265,53 +271,52 @@ static inline int get_index(const unsigned char *inst, unsigned char rex)
return 0;
}
-static void init_instruction(struct instruction *mmio_inst)
+static void init_instruction(struct hvm_io_op *mmio_op)
{
- mmio_inst->instr = 0;
- mmio_inst->op_size = 0;
- mmio_inst->immediate = 0;
- mmio_inst->seg_sel = 0;
+ mmio_op->instr = 0;
- mmio_inst->operand[0] = 0;
- mmio_inst->operand[1] = 0;
+ mmio_op->flags = 0;
+ //mmio_op->seg_sel = 0;
- mmio_inst->flags = 0;
+ mmio_op->operand[0] = 0;
+ mmio_op->operand[1] = 0;
+ mmio_op->immediate = 0;
}
-#define GET_OP_SIZE_FOR_BYTE(op_size) \
+#define GET_OP_SIZE_FOR_BYTE(size_reg) \
do { \
- if (rex) \
- op_size = BYTE_64; \
+ if ( rex ) \
+ (size_reg) = BYTE_64; \
else \
- op_size = BYTE; \
- } while(0)
+ (size_reg) = BYTE; \
+ } while( 0 )
#define GET_OP_SIZE_FOR_NONEBYTE(op_size) \
do { \
- if (rex & 0x8) \
- op_size = QUAD; \
- else if (op_size != WORD) \
- op_size = LONG; \
- } while(0)
+ if ( rex & 0x8 ) \
+ (op_size) = QUAD; \
+ else if ( (op_size) != WORD ) \
+ (op_size) = LONG; \
+ } while( 0 )
/*
* Decode mem,accumulator operands (as in <opcode> m8/m16/m32, al,ax,eax)
*/
-static int mem_acc(unsigned char size, struct instruction *instr)
+static inline int mem_acc(unsigned char size, struct hvm_io_op *mmio)
{
- instr->operand[0] = mk_operand(size, 0, 0, MEMORY);
- instr->operand[1] = mk_operand(size, 0, 0, REGISTER);
+ mmio->operand[0] = mk_operand(size, 0, 0, MEMORY);
+ mmio->operand[1] = mk_operand(size, 0, 0, REGISTER);
return DECODE_success;
}
/*
* Decode accumulator,mem operands (as in <opcode> al,ax,eax, m8/m16/m32)
*/
-static int acc_mem(unsigned char size, struct instruction *instr)
+static inline int acc_mem(unsigned char size, struct hvm_io_op *mmio)
{
- instr->operand[0] = mk_operand(size, 0, 0, REGISTER);
- instr->operand[1] = mk_operand(size, 0, 0, MEMORY);
+ mmio->operand[0] = mk_operand(size, 0, 0, REGISTER);
+ mmio->operand[1] = mk_operand(size, 0, 0, MEMORY);
return DECODE_success;
}
@@ -319,12 +324,12 @@ static int acc_mem(unsigned char size, struct instruction *instr)
* Decode mem,reg operands (as in <opcode> r32/16, m32/16)
*/
static int mem_reg(unsigned char size, unsigned char *opcode,
- struct instruction *instr, unsigned char rex)
+ struct hvm_io_op *mmio_op, unsigned char rex)
{
int index = get_index(opcode + 1, rex);
- instr->operand[0] = mk_operand(size, 0, 0, MEMORY);
- instr->operand[1] = mk_operand(size, index, 0, REGISTER);
+ mmio_op->operand[0] = mk_operand(size, 0, 0, MEMORY);
+ mmio_op->operand[1] = mk_operand(size, index, 0, REGISTER);
return DECODE_success;
}
@@ -332,263 +337,273 @@ static int mem_reg(unsigned char size, unsigned char *opcode,
* Decode reg,mem operands (as in <opcode> m32/16, r32/16)
*/
static int reg_mem(unsigned char size, unsigned char *opcode,
- struct instruction *instr, unsigned char rex)
+ struct hvm_io_op *mmio_op, unsigned char rex)
{
int index = get_index(opcode + 1, rex);
- instr->operand[0] = mk_operand(size, index, 0, REGISTER);
- instr->operand[1] = mk_operand(size, 0, 0, MEMORY);
+ mmio_op->operand[0] = mk_operand(size, index, 0, REGISTER);
+ mmio_op->operand[1] = mk_operand(size, 0, 0, MEMORY);
return DECODE_success;
}
-static int hvm_decode(int realmode, unsigned char *opcode, struct instruction *instr)
+static int hvm_decode(int realmode, unsigned char *opcode,
+ struct hvm_io_op *mmio_op, unsigned char *op_size)
{
unsigned char size_reg = 0;
unsigned char rex = 0;
int index;
- init_instruction(instr);
+ *op_size = 0;
+ init_instruction(mmio_op);
- opcode = check_prefix(opcode, instr, &rex);
+ opcode = check_prefix(opcode, mmio_op, op_size, &rex);
- if (realmode) { /* meaning is reversed */
- if (instr->op_size == WORD)
- instr->op_size = LONG;
- else if (instr->op_size == LONG)
- instr->op_size = WORD;
- else if (instr->op_size == 0)
- instr->op_size = WORD;
+ if ( realmode ) { /* meaning is reversed */
+ if ( *op_size == WORD )
+ *op_size = LONG;
+ else if ( *op_size == LONG )
+ *op_size = WORD;
+ else if ( *op_size == 0 )
+ *op_size = WORD;
}
- switch (*opcode) {
- case 0x0A: /* or r8, m8 */
- instr->instr = INSTR_OR;
- instr->op_size = BYTE;
+ /* the operands order in comments conforms to AT&T convention */
+
+ switch ( *opcode ) {
+ case 0x0A: /* or m8, r8 */
+ mmio_op->instr = INSTR_OR;
+ *op_size = BYTE;
GET_OP_SIZE_FOR_BYTE(size_reg);
- return mem_reg(size_reg, opcode, instr, rex);
+ return mem_reg(size_reg, opcode, mmio_op, rex);
case 0x0B: /* or m32/16, r32/16 */
- instr->instr = INSTR_OR;
- GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
- return mem_reg(instr->op_size, opcode, instr, rex);
+ mmio_op->instr = INSTR_OR;
+ GET_OP_SIZE_FOR_NONEBYTE(*op_size);
+ return mem_reg(*op_size, opcode, mmio_op, rex);
case 0x20: /* and r8, m8 */
- instr->instr = INSTR_AND;
- instr->op_size = BYTE;
+ mmio_op->instr = INSTR_AND;
+ *op_size = BYTE;
GET_OP_SIZE_FOR_BYTE(size_reg);
- return reg_mem(size_reg, opcode, instr, rex);
+ return reg_mem(size_reg, opcode, mmio_op, rex);
case 0x21: /* and r32/16, m32/16 */
- instr->instr = INSTR_AND;
- GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
- return reg_mem(instr->op_size, opcode, instr, rex);
+ mmio_op->instr = INSTR_AND;
+ GET_OP_SIZE_FOR_NONEBYTE(*op_size);
+ return reg_mem(*op_size, opcode, mmio_op, rex);
case 0x22: /* and m8, r8 */
- instr->instr = INSTR_AND;
- instr->op_size = BYTE;
+ mmio_op->instr = INSTR_AND;
+ *op_size = BYTE;
GET_OP_SIZE_FOR_BYTE(size_reg);
- return mem_reg(size_reg, opcode, instr, rex);
+ return mem_reg(size_reg, opcode, mmio_op, rex);
case 0x23: /* and m32/16, r32/16 */
- instr->instr = INSTR_AND;
- GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
- return mem_reg(instr->op_size, opcode, instr, rex);
+ mmio_op->instr = INSTR_AND;
+ GET_OP_SIZE_FOR_NONEBYTE(*op_size);
+ return mem_reg(*op_size, opcode, mmio_op, rex);
case 0x2B: /* sub m32/16, r32/16 */
- instr->instr = INSTR_SUB;
- GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
- return mem_reg(instr->op_size, opcode, instr, rex);
+ mmio_op->instr = INSTR_SUB;
+ GET_OP_SIZE_FOR_NONEBYTE(*op_size);
+ return mem_reg(*op_size, opcode, mmio_op, rex);
case 0x30: /* xor r8, m8 */
- instr->instr = INSTR_XOR;
- instr->op_size = BYTE;
+ mmio_op->instr = INSTR_XOR;
+ *op_size = BYTE;
GET_OP_SIZE_FOR_BYTE(size_reg);
- return reg_mem(size_reg, opcode, instr, rex);
+ return reg_mem(size_reg, opcode, mmio_op, rex);
case 0x31: /* xor r32/16, m32/16 */
- instr->instr = INSTR_XOR;
- GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
- return reg_mem(instr->op_size, opcode, instr, rex);
+ mmio_op->instr = INSTR_XOR;
+ GET_OP_SIZE_FOR_NONEBYTE(*op_size);
+ return reg_mem(*op_size, opcode, mmio_op, rex);
+
+ case 0x32: /* xor m8, r8 */
+ mmio_op->instr = INSTR_XOR;
+ *op_size = BYTE;
+ GET_OP_SIZE_FOR_BYTE(size_reg);
+ return mem_reg(size_reg, opcode, mmio_op, rex);
- case 0x32: /* xor m8, r8*/
- instr->instr = INSTR_XOR;
- instr->op_size = BYTE;
+ case 0x38: /* cmp r8, m8 */
+ mmio_op->instr = INSTR_CMP;
+ *op_size = BYTE;
GET_OP_SIZE_FOR_BYTE(size_reg);
- return mem_reg(size_reg, opcode, instr, rex);
+ return reg_mem(size_reg, opcode, mmio_op, rex);
case 0x39: /* cmp r32/16, m32/16 */
- instr->instr = INSTR_CMP;
- GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
- return reg_mem(instr->op_size, opcode, instr, rex);
+ mmio_op->instr = INSTR_CMP;
+ GET_OP_SIZE_FOR_NONEBYTE(*op_size);
+ return reg_mem(*op_size, opcode, mmio_op, rex);
- case 0x3A: /* cmp r8, r8/m8 */
- instr->instr = INSTR_CMP;
- GET_OP_SIZE_FOR_BYTE(instr->op_size);
- return reg_mem(instr->op_size, opcode, instr, rex);
+ case 0x3A: /* cmp m8, r8 */
+ mmio_op->instr = INSTR_CMP;
+ *op_size = BYTE;
+ GET_OP_SIZE_FOR_BYTE(size_reg);
+ return mem_reg(size_reg, opcode, mmio_op, rex);
case 0x3B: /* cmp m32/16, r32/16 */
- instr->instr = INSTR_CMP;
- GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
- return mem_reg(instr->op_size, opcode, instr, rex);
+ mmio_op->instr = INSTR_CMP;
+ GET_OP_SIZE_FOR_NONEBYTE(*op_size);
+ return mem_reg(*op_size, opcode, mmio_op, rex);
case 0x80:
case 0x81:
case 0x83:
- {
- unsigned char ins_subtype = (opcode[1] >> 3) & 7;
+ {
+ unsigned char ins_subtype = (opcode[1] >> 3) & 7;
- if (opcode[0] == 0x80) {
- GET_OP_SIZE_FOR_BYTE(size_reg);
- instr->op_size = BYTE;
- } else if (opcode[0] == 0x81) {
- GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
- size_reg = instr->op_size;
- } else if (opcode[0] == 0x83) {
- GET_OP_SIZE_FOR_NONEBYTE(size_reg);
- instr->op_size = size_reg;
- }
-
- /* opcode 0x83 always has a single byte operand */
- if (opcode[0] == 0x83)
- instr->immediate =
- (signed char)get_immediate(realmode, opcode+1, BYTE);
- else
- instr->immediate =
- get_immediate(realmode, opcode+1, instr->op_size);
+ if ( opcode[0] == 0x80 ) {
+ *op_size = BYTE;
+ GET_OP_SIZE_FOR_BYTE(size_reg);
+ } else {
+ GET_OP_SIZE_FOR_NONEBYTE(*op_size);
+ size_reg = *op_size;
+ }
- instr->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE);
- instr->operand[1] = mk_operand(size_reg, 0, 0, MEMORY);
+ /* opcode 0x83 always has a single byte operand */
+ if ( opcode[0] == 0x83 )
+ mmio_op->immediate =
+ (signed char)get_immediate(realmode, opcode + 1, BYTE);
+ else
+ mmio_op->immediate =
+ get_immediate(realmode, opcode + 1, *op_size);
- switch (ins_subtype) {
- case 7: /* cmp $imm, m32/16 */
- instr->instr = INSTR_CMP;
- return DECODE_success;
+ mmio_op->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE);
+ mmio_op->operand[1] = mk_operand(size_reg, 0, 0, MEMORY);
- case 1: /* or $imm, m32/16 */
- instr->instr = INSTR_OR;
- return DECODE_success;
+ switch ( ins_subtype ) {
+ case 7: /* cmp $imm, m32/16 */
+ mmio_op->instr = INSTR_CMP;
+ return DECODE_success;
- default:
- printk("%x/%x, This opcode isn't handled yet!\n",
- *opcode, ins_subtype);
- return DECODE_failure;
- }
+ case 1: /* or $imm, m32/16 */
+ mmio_op->instr = INSTR_OR;
+ return DECODE_success;
+
+ default:
+ printk("%x/%x, This opcode isn't handled yet!\n",
+ *opcode, ins_subtype);
+ return DECODE_failure;
}
+ }
- case 0x84: /* test m8, r8 */
- instr->instr = INSTR_TEST;
- instr->op_size = BYTE;
+ case 0x84: /* test r8, m8 */
+ mmio_op->instr = INSTR_TEST;
+ *op_size = BYTE;
GET_OP_SIZE_FOR_BYTE(size_reg);
- return mem_reg(size_reg, opcode, instr, rex);
+ return reg_mem(size_reg, opcode, mmio_op, rex);
- case 0x85: /* text m16/32, r16/32 */
- instr->instr = INSTR_TEST;
- GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
- return mem_reg(instr->op_size, opcode, instr, rex);
+ case 0x85: /* test r16/32, m16/32 */
+ mmio_op->instr = INSTR_TEST;
+ GET_OP_SIZE_FOR_NONEBYTE(*op_size);
+ return reg_mem(*op_size, opcode, mmio_op, rex);
case 0x87: /* xchg {r/m16|r/m32}, {m/r16|m/r32} */
- instr->instr = INSTR_XCHG;
- GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
- if (((*(opcode+1)) & 0xc7) == 5)
- return reg_mem(instr->op_size, opcode, instr, rex);
+ mmio_op->instr = INSTR_XCHG;
+ GET_OP_SIZE_FOR_NONEBYTE(*op_size);
+ if ( ((*(opcode+1)) & 0xc7) == 5 )
+ return reg_mem(*op_size, opcode, mmio_op, rex);
else
- return mem_reg(instr->op_size, opcode, instr, rex);
+ return mem_reg(*op_size, opcode, mmio_op, rex);
case 0x88: /* mov r8, m8 */
- instr->instr = INSTR_MOV;
- instr->op_size = BYTE;
+ mmio_op->instr = INSTR_MOV;
+ *op_size = BYTE;
GET_OP_SIZE_FOR_BYTE(size_reg);
- return reg_mem(size_reg, opcode, instr, rex);
+ return reg_mem(size_reg, opcode, mmio_op, rex);
case 0x89: /* mov r32/16, m32/16 */
- instr->instr = INSTR_MOV;
- GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
- return reg_mem(instr->op_size, opcode, instr, rex);
+ mmio_op->instr = INSTR_MOV;
+ GET_OP_SIZE_FOR_NONEBYTE(*op_size);
+ return reg_mem(*op_size, opcode, mmio_op, rex);
case 0x8A: /* mov m8, r8 */
- instr->instr = INSTR_MOV;
- instr->op_size = BYTE;
+ mmio_op->instr = INSTR_MOV;
+ *op_size = BYTE;
GET_OP_SIZE_FOR_BYTE(size_reg);
- return mem_reg(size_reg, opcode, instr, rex);
+ return mem_reg(size_reg, opcode, mmio_op, rex);
case 0x8B: /* mov m32/16, r32/16 */
- instr->instr = INSTR_MOV;
- GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
- return mem_reg(instr->op_size, opcode, instr, rex);
+ mmio_op->instr = INSTR_MOV;
+ GET_OP_SIZE_FOR_NONEBYTE(*op_size);
+ return mem_reg(*op_size, opcode, mmio_op, rex);
case 0xA0: /* mov <addr>, al */
- instr->instr = INSTR_MOV;
- instr->op_size = BYTE;
+ mmio_op->instr = INSTR_MOV;
+ *op_size = BYTE;
GET_OP_SIZE_FOR_BYTE(size_reg);
- return mem_acc(size_reg, instr);
+ return mem_acc(size_reg, mmio_op);
case 0xA1: /* mov <addr>, ax/eax */
- instr->instr = INSTR_MOV;
- GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
- return mem_acc(instr->op_size, instr);
+ mmio_op->instr = INSTR_MOV;
+ GET_OP_SIZE_FOR_NONEBYTE(*op_size);
+ return mem_acc(*op_size, mmio_op);
case 0xA2: /* mov al, <addr> */
- instr->instr = INSTR_MOV;
- instr->op_size = BYTE;
+ mmio_op->instr = INSTR_MOV;
+ *op_size = BYTE;
GET_OP_SIZE_FOR_BYTE(size_reg);
- return acc_mem(size_reg, instr);
+ return acc_mem(size_reg, mmio_op);
case 0xA3: /* mov ax/eax, <addr> */
- instr->instr = INSTR_MOV;
- GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
- return acc_mem(instr->op_size, instr);
+ mmio_op->instr = INSTR_MOV;
+ GET_OP_SIZE_FOR_NONEBYTE(*op_size);
+ return acc_mem(*op_size, mmio_op);
case 0xA4: /* movsb */
- instr->instr = INSTR_MOVS;
- instr->op_size = BYTE;
+ mmio_op->instr = INSTR_MOVS;
+ *op_size = BYTE;
return DECODE_success;
case 0xA5: /* movsw/movsl */
- instr->instr = INSTR_MOVS;
- GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+ mmio_op->instr = INSTR_MOVS;
+ GET_OP_SIZE_FOR_NONEBYTE(*op_size);
return DECODE_success;
case 0xAA: /* stosb */
- instr->instr = INSTR_STOS;
- instr->op_size = BYTE;
+ mmio_op->instr = INSTR_STOS;
+ *op_size = BYTE;
return DECODE_success;
case 0xAB: /* stosw/stosl */
- instr->instr = INSTR_STOS;
- GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+ mmio_op->instr = INSTR_STOS;
+ GET_OP_SIZE_FOR_NONEBYTE(*op_size);
return DECODE_success;
case 0xAC: /* lodsb */
- instr->instr = INSTR_LODS;
- instr->op_size = BYTE;
+ mmio_op->instr = INSTR_LODS;
+ *op_size = BYTE;
return DECODE_success;
case 0xAD: /* lodsw/lodsl */
- instr->instr = INSTR_LODS;
- GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+ mmio_op->instr = INSTR_LODS;
+ GET_OP_SIZE_FOR_NONEBYTE(*op_size);
return DECODE_success;
case 0xC6:
- if (((opcode[1] >> 3) & 7) == 0) { /* mov $imm8, m8 */
- instr->instr = INSTR_MOV;
- instr->op_size = BYTE;
+ if ( ((opcode[1] >> 3) & 7) == 0 ) { /* mov $imm8, m8 */
+ mmio_op->instr = INSTR_MOV;
+ *op_size = BYTE;
- instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE);
- instr->immediate = get_immediate(realmode, opcode+1, instr->op_size);
- instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
+ mmio_op->operand[0] = mk_operand(*op_size, 0, 0, IMMEDIATE);
+ mmio_op->immediate =
+ get_immediate(realmode, opcode + 1, *op_size);
+ mmio_op->operand[1] = mk_operand(*op_size, 0, 0, MEMORY);
return DECODE_success;
} else
return DECODE_failure;
case 0xC7:
- if (((opcode[1] >> 3) & 7) == 0) { /* mov $imm16/32, m16/32 */
- instr->instr = INSTR_MOV;
- GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+ if ( ((opcode[1] >> 3) & 7) == 0 ) { /* mov $imm16/32, m16/32 */
+ mmio_op->instr = INSTR_MOV;
+ GET_OP_SIZE_FOR_NONEBYTE(*op_size);
- instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE);
- instr->immediate = get_immediate(realmode, opcode+1, instr->op_size);
- instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
+ mmio_op->operand[0] = mk_operand(*op_size, 0, 0, IMMEDIATE);
+ mmio_op->immediate =
+ get_immediate(realmode, opcode + 1, *op_size);
+ mmio_op->operand[1] = mk_operand(*op_size, 0, 0, MEMORY);
return DECODE_success;
} else
@@ -596,20 +611,21 @@ static int hvm_decode(int realmode, unsigned char *opcode, struct instruction *i
case 0xF6:
case 0xF7:
- if (((opcode[1] >> 3) & 7) == 0) { /* test $imm8/16/32, m8/16/32 */
- instr->instr = INSTR_TEST;
+ if ( ((opcode[1] >> 3) & 7) == 0 ) { /* test $imm8/16/32, m8/16/32 */
+ mmio_op->instr = INSTR_TEST;
- if (opcode[0] == 0xF6) {
+ if ( opcode[0] == 0xF6 ) {
+ *op_size = BYTE;
GET_OP_SIZE_FOR_BYTE(size_reg);
- instr->op_size = BYTE;
} else {
- GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
- size_reg = instr->op_size;
+ GET_OP_SIZE_FOR_NONEBYTE(*op_size);
+ size_reg = *op_size;
}
- instr->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE);
- instr->immediate = get_immediate(realmode, opcode+1, instr->op_size);
- instr->operand[1] = mk_operand(size_reg, 0, 0, MEMORY);
+ mmio_op->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE);
+ mmio_op->immediate =
+ get_immediate(realmode, opcode + 1, *op_size);
+ mmio_op->operand[1] = mk_operand(size_reg, 0, 0, MEMORY);
return DECODE_success;
} else
@@ -623,59 +639,59 @@ static int hvm_decode(int realmode, unsigned char *opcode, struct instruction *i
return DECODE_failure;
}
- switch (*++opcode) {
+ switch ( *++opcode ) {
case 0xB6: /* movzx m8, r16/r32/r64 */
- instr->instr = INSTR_MOVZX;
- GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+ mmio_op->instr = INSTR_MOVZX;
+ GET_OP_SIZE_FOR_NONEBYTE(*op_size);
index = get_index(opcode + 1, rex);
- instr->operand[0] = mk_operand(BYTE, 0, 0, MEMORY);
- instr->operand[1] = mk_operand(instr->op_size, index, 0, REGISTER);
+ mmio_op->operand[0] = mk_operand(BYTE, 0, 0, MEMORY);
+ mmio_op->operand[1] = mk_operand(*op_size, index, 0, REGISTER);
return DECODE_success;
case 0xB7: /* movzx m16/m32, r32/r64 */
- instr->instr = INSTR_MOVZX;
- GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+ mmio_op->instr = INSTR_MOVZX;
+ GET_OP_SIZE_FOR_NONEBYTE(*op_size);
index = get_index(opcode + 1, rex);
- if (rex & 0x8)
- instr->operand[0] = mk_operand(LONG, 0, 0, MEMORY);
+ if ( rex & 0x8 )
+ mmio_op->operand[0] = mk_operand(LONG, 0, 0, MEMORY);
else
- instr->operand[0] = mk_operand(WORD, 0, 0, MEMORY);
- instr->operand[1] = mk_operand(instr->op_size, index, 0, REGISTER);
+ mmio_op->operand[0] = mk_operand(WORD, 0, 0, MEMORY);
+ mmio_op->operand[1] = mk_operand(*op_size, index, 0, REGISTER);
return DECODE_success;
case 0xBE: /* movsx m8, r16/r32/r64 */
- instr->instr = INSTR_MOVSX;
- GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+ mmio_op->instr = INSTR_MOVSX;
+ GET_OP_SIZE_FOR_NONEBYTE(*op_size);
index = get_index(opcode + 1, rex);
- instr->operand[0] = mk_operand(BYTE, 0, 0, MEMORY);
- instr->operand[1] = mk_operand(instr->op_size, index, 0, REGISTER);
+ mmio_op->operand[0] = mk_operand(BYTE, 0, 0, MEMORY);
+ mmio_op->operand[1] = mk_operand(*op_size, index, 0, REGISTER);
return DECODE_success;
case 0xBF: /* movsx m16, r32/r64 */
- instr->instr = INSTR_MOVSX;
- GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+ mmio_op->instr = INSTR_MOVSX;
+ GET_OP_SIZE_FOR_NONEBYTE(*op_size);
index = get_index(opcode + 1, rex);
- instr->operand[0] = mk_operand(WORD, 0, 0, MEMORY);
- instr->operand[1] = mk_operand(instr->op_size, index, 0, REGISTER);
+ mmio_op->operand[0] = mk_operand(WORD, 0, 0, MEMORY);
+ mmio_op->operand[1] = mk_operand(*op_size, index, 0, REGISTER);
return DECODE_success;
case 0xA3: /* bt r32, m32 */
- instr->instr = INSTR_BT;
+ mmio_op->instr = INSTR_BT;
index = get_index(opcode + 1, rex);
- instr->op_size = LONG;
- instr->operand[0] = mk_operand(instr->op_size, index, 0, REGISTER);
- instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
+ *op_size = LONG;
+ mmio_op->operand[0] = mk_operand(*op_size, index, 0, REGISTER);
+ mmio_op->operand[1] = mk_operand(*op_size, 0, 0, MEMORY);
return DECODE_success;
case 0xBA:
- if (((opcode[1] >> 3) & 7) == 4) /* BT $imm8, m16/32/64 */
+ if ( ((opcode[1] >> 3) & 7) == 4 ) /* BT $imm8, m16/32/64 */
{
- instr->instr = INSTR_BT;
- GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
- instr->immediate =
- (signed char)get_immediate(realmode, opcode+1, BYTE);
- instr->operand[0] = mk_operand(BYTE, 0, 0, IMMEDIATE);
- instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
+ mmio_op->instr = INSTR_BT;
+ GET_OP_SIZE_FOR_NONEBYTE(*op_size);
+ mmio_op->operand[0] = mk_operand(BYTE, 0, 0, IMMEDIATE);
+ mmio_op->immediate =
+ (signed char)get_immediate(realmode, opcode + 1, BYTE);
+ mmio_op->operand[1] = mk_operand(*op_size, 0, 0, MEMORY);
return DECODE_success;
}
else
@@ -692,9 +708,9 @@ static int hvm_decode(int realmode, unsigned char *opcode, struct instruction *i
int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip, int inst_len)
{
- if (inst_len > MAX_INST_LEN || inst_len <= 0)
+ if ( inst_len > MAX_INST_LEN || inst_len <= 0 )
return 0;
- if (hvm_copy_from_guest_virt(buf, guest_eip, inst_len))
+ if ( hvm_copy_from_guest_virt(buf, guest_eip, inst_len) )
return 0;
return inst_len;
}
@@ -716,27 +732,20 @@ static void hvm_send_assist_req(struct vcpu *v)
notify_via_xen_event_channel(v->arch.hvm_vcpu.xen_port);
}
-
-/* Wake up a vcpu whihc is waiting for interrupts to come in */
-void hvm_prod_vcpu(struct vcpu *v)
-{
- vcpu_unblock(v);
-}
-
-void send_pio_req(struct cpu_user_regs *regs, unsigned long port,
- unsigned long count, int size, long value, int dir, int pvalid)
+void send_pio_req(unsigned long port, unsigned long count, int size,
+ long value, int dir, int df, int pvalid)
{
struct vcpu *v = current;
vcpu_iodata_t *vio;
ioreq_t *p;
- if (size == 0 || count == 0) {
+ if ( size == 0 || count == 0 ) {
printf("null pio request? port %lx, count %lx, size %d, value %lx, dir %d, pvalid %d.\n",
port, count, size, value, dir, pvalid);
}
vio = get_vio(v->domain, v->vcpu_id);
- if (vio == NULL) {
+ if ( vio == NULL ) {
printk("bad shared page: %lx\n", (unsigned long) vio);
domain_crash_synchronous();
}
@@ -745,6 +754,7 @@ void send_pio_req(struct cpu_user_regs *regs, unsigned long port,
if ( p->state != STATE_INVALID )
printk("WARNING: send pio with something already pending (%d)?\n",
p->state);
+
p->dir = dir;
p->pdata_valid = pvalid;
@@ -752,19 +762,20 @@ void send_pio_req(struct cpu_user_regs *regs, unsigned long port,
p->size = size;
p->addr = port;
p->count = count;
- p->df = regs->eflags & EF_DF ? 1 : 0;
+ p->df = df;
p->io_count++;
- if (pvalid) {
- if (hvm_paging_enabled(current))
- p->u.data = shadow_gva_to_gpa(current, value);
+ if ( pvalid ) /* get physical address of data */
+ {
+ if ( hvm_paging_enabled(current) )
+ p->u.pdata = (void *)shadow_gva_to_gpa(current, value);
else
- p->u.pdata = (void *) value; /* guest VA == guest PA */
- } else
+ p->u.pdata = (void *)value; /* guest VA == guest PA */
+ } else if ( dir == IOREQ_WRITE )
p->u.data = value;
- if (hvm_portio_intercept(p)) {
+ if ( hvm_portio_intercept(p) ) {
p->state = STATE_IORESP_READY;
hvm_io_assist(v);
return;
@@ -773,22 +784,19 @@ void send_pio_req(struct cpu_user_regs *regs, unsigned long port,
hvm_send_assist_req(v);
}
-static void send_mmio_req(
- unsigned char type, unsigned long gpa,
- unsigned long count, int size, long value, int dir, int pvalid)
+static void send_mmio_req(unsigned char type, unsigned long gpa,
+ unsigned long count, int size, long value,
+ int dir, int df, int pvalid)
{
struct vcpu *v = current;
vcpu_iodata_t *vio;
ioreq_t *p;
- struct cpu_user_regs *regs;
- if (size == 0 || count == 0) {
+ if ( size == 0 || count == 0 ) {
printf("null mmio request? type %d, gpa %lx, count %lx, size %d, value %lx, dir %d, pvalid %d.\n",
type, gpa, count, size, value, dir, pvalid);
}
- regs = &current->arch.hvm_vcpu.io_op.io_context;
-
vio = get_vio(v->domain, v->vcpu_id);
if (vio == NULL) {
printk("bad shared page\n");
@@ -807,7 +815,7 @@ static void send_mmio_req(
p->size = size;
p->addr = gpa;
p->count = count;
- p->df = regs->eflags & EF_DF ? 1 : 0;
+ p->df = df;
p->io_count++;
@@ -828,59 +836,59 @@ static void send_mmio_req(
hvm_send_assist_req(v);
}
-static void mmio_operands(int type, unsigned long gpa, struct instruction *inst,
- struct hvm_io_op *mmio_opp, struct cpu_user_regs *regs)
+static void mmio_operands(int type, unsigned long gpa,
+ struct hvm_io_op *mmio_op,
+ unsigned char op_size)
{
unsigned long value = 0;
- int index, size_reg;
+ int df, index, size_reg;
+ struct cpu_user_regs *regs = &mmio_op->io_context;
- size_reg = operand_size(inst->operand[0]);
+ df = regs->eflags & X86_EFLAGS_DF ? 1 : 0;
- mmio_opp->flags = inst->flags;
- mmio_opp->instr = inst->instr;
- mmio_opp->operand[0] = inst->operand[0]; /* source */
- mmio_opp->operand[1] = inst->operand[1]; /* destination */
- mmio_opp->immediate = inst->immediate;
+ size_reg = operand_size(mmio_op->operand[0]);
- if (inst->operand[0] & REGISTER) { /* dest is memory */
- index = operand_index(inst->operand[0]);
+ if ( mmio_op->operand[0] & REGISTER ) { /* dest is memory */
+ index = operand_index(mmio_op->operand[0]);
value = get_reg_value(size_reg, index, 0, regs);
- send_mmio_req(type, gpa, 1, inst->op_size, value, IOREQ_WRITE, 0);
- } else if (inst->operand[0] & IMMEDIATE) { /* dest is memory */
- value = inst->immediate;
- send_mmio_req(type, gpa, 1, inst->op_size, value, IOREQ_WRITE, 0);
- } else if (inst->operand[0] & MEMORY) { /* dest is register */
+ send_mmio_req(type, gpa, 1, op_size, value, IOREQ_WRITE, df, 0);
+ } else if ( mmio_op->operand[0] & IMMEDIATE ) { /* dest is memory */
+ value = mmio_op->immediate;
+ send_mmio_req(type, gpa, 1, op_size, value, IOREQ_WRITE, df, 0);
+ } else if ( mmio_op->operand[0] & MEMORY ) { /* dest is register */
/* send the request and wait for the value */
- if ( (inst->instr == INSTR_MOVZX) || (inst->instr == INSTR_MOVSX) )
- send_mmio_req(type, gpa, 1, size_reg, 0, IOREQ_READ, 0);
+ if ( (mmio_op->instr == INSTR_MOVZX) ||
+ (mmio_op->instr == INSTR_MOVSX) )
+ send_mmio_req(type, gpa, 1, size_reg, 0, IOREQ_READ, df, 0);
else
- send_mmio_req(type, gpa, 1, inst->op_size, 0, IOREQ_READ, 0);
+ send_mmio_req(type, gpa, 1, op_size, 0, IOREQ_READ, df, 0);
} else {
- printk("mmio_operands: invalid operand\n");
+ printk("%s: invalid dest mode.\n", __func__);
domain_crash_synchronous();
}
}
#define GET_REPEAT_COUNT() \
- (mmio_inst.flags & REPZ ? (realmode ? regs->ecx & 0xFFFF : regs->ecx) : 1)
+ (mmio_op->flags & REPZ ? (realmode ? regs->ecx & 0xFFFF : regs->ecx) : 1)
-void handle_mmio(unsigned long va, unsigned long gpa)
+void handle_mmio(unsigned long gpa)
{
unsigned long inst_addr;
- struct hvm_io_op *mmio_opp;
+ struct hvm_io_op *mmio_op;
struct cpu_user_regs *regs;
- struct instruction mmio_inst;
- unsigned char inst[MAX_INST_LEN];
- int i, realmode, ret, inst_len;
+ unsigned char inst[MAX_INST_LEN], op_size;
+ int i, realmode, df, inst_len;
struct vcpu *v = current;
- mmio_opp = &v->arch.hvm_vcpu.io_op;
- regs = &mmio_opp->io_context;
+ mmio_op = &v->arch.hvm_vcpu.io_op;
+ regs = &mmio_op->io_context;
/* Copy current guest state into io instruction state structure. */
memcpy(regs, guest_cpu_user_regs(), HVM_CONTEXT_STACK_BYTES);
hvm_store_cpu_guest_regs(v, regs, NULL);
+ df = regs->eflags & X86_EFLAGS_DF ? 1 : 0;
+
inst_len = hvm_instruction_length(regs, hvm_guest_x86_mode(v));
if ( inst_len <= 0 )
{
@@ -889,25 +897,21 @@ void handle_mmio(unsigned long va, unsigned long gpa)
}
realmode = hvm_realmode(v);
- if (realmode)
+ if ( realmode )
inst_addr = (regs->cs << 4) + regs->eip;
else
inst_addr = regs->eip;
memset(inst, 0, MAX_INST_LEN);
- ret = inst_copy_from_guest(inst, inst_addr, inst_len);
- if (ret != inst_len) {
+ if ( inst_copy_from_guest(inst, inst_addr, inst_len) != inst_len ) {
printk("handle_mmio: failed to copy instruction\n");
domain_crash_synchronous();
}
- init_instruction(&mmio_inst);
-
- if (hvm_decode(realmode, inst, &mmio_inst) == DECODE_failure) {
+ if ( hvm_decode(realmode, inst, mmio_op, &op_size) == DECODE_failure ) {
printk("handle_mmio: failed to decode instruction\n");
- printk("mmio opcode: va 0x%lx, gpa 0x%lx, len %d:",
- va, gpa, inst_len);
- for (i = 0; i < inst_len; i++)
+ printk("mmio opcode: gpa 0x%lx, len %d:", gpa, inst_len);
+ for ( i = 0; i < inst_len; i++ )
printk(" %02x", inst[i] & 0xFF);
printk("\n");
domain_crash_synchronous();
@@ -915,24 +919,23 @@ void handle_mmio(unsigned long va, unsigned long gpa)
regs->eip += inst_len; /* advance %eip */
- switch (mmio_inst.instr) {
+ switch ( mmio_op->instr ) {
case INSTR_MOV:
- mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mmio_opp, regs);
+ mmio_operands(IOREQ_TYPE_COPY, gpa, mmio_op, op_size);
break;
case INSTR_MOVS:
{
unsigned long count = GET_REPEAT_COUNT();
- unsigned long size = mmio_inst.op_size;
- int sign = regs->eflags & EF_DF ? -1 : 1;
+ int sign = regs->eflags & X86_EFLAGS_DF ? -1 : 1;
unsigned long addr = 0;
- int dir;
+ int dir, size = op_size;
ASSERT(count);
/* determine non-MMIO address */
- if (realmode) {
- if (((regs->es << 4) + (regs->edi & 0xFFFF)) == va) {
+ if ( realmode ) {
+ if ( ((regs->es << 4) + (regs->edi & 0xFFFF)) == gpa ) {
dir = IOREQ_WRITE;
addr = (regs->ds << 4) + (regs->esi & 0xFFFF);
} else {
@@ -940,7 +943,7 @@ void handle_mmio(unsigned long va, unsigned long gpa)
addr = (regs->es << 4) + (regs->edi & 0xFFFF);
}
} else {
- if (va == regs->edi) {
+ if ( gpa == regs->edi ) {
dir = IOREQ_WRITE;
addr = regs->esi;
} else {
@@ -949,58 +952,61 @@ void handle_mmio(unsigned long va, unsigned long gpa)
}
}
- mmio_opp->flags = mmio_inst.flags;
- mmio_opp->instr = mmio_inst.instr;
-
- if (addr & (size - 1))
- DPRINTK("Unaligned ioport access: %lx, %ld\n", addr, size);
+ if ( addr & (size - 1) )
+ DPRINTK("Unaligned ioport access: %lx, %d\n", addr, size);
/*
* In case of a movs spanning multiple pages, we break the accesses
* up into multiple pages (the device model works with non-continguous
* physical guest pages). To copy just one page, we adjust %ecx and
- * do not advance %eip so that the next "rep movs" copies the next page.
+ * do not advance %eip so that the next rep;movs copies the next page.
* Unaligned accesses, for example movsl starting at PGSZ-2, are
* turned into a single copy where we handle the overlapping memory
* copy ourself. After this copy succeeds, "rep movs" is executed
* again.
*/
- if ((addr & PAGE_MASK) != ((addr + sign * (size - 1)) & PAGE_MASK)) {
+ if ( (addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK) ) {
unsigned long value = 0;
DPRINTK("Single io request in a movs crossing page boundary.\n");
- mmio_opp->flags |= OVERLAP;
+ mmio_op->flags |= OVERLAP;
+
+ if ( dir == IOREQ_WRITE ) {
+ if ( hvm_paging_enabled(v) )
+ (void)hvm_copy_from_guest_virt(&value, addr, size);
+ else
+ (void)hvm_copy_from_guest_phys(&value, addr, size);
+ } else
+ mmio_op->addr = addr;
- regs->eip -= inst_len; /* do not advance %eip */
+ if ( count != 1 )
+ regs->eip -= inst_len; /* do not advance %eip */
- if (dir == IOREQ_WRITE)
- (void)hvm_copy_from_guest_virt(&value, addr, size);
- send_mmio_req(IOREQ_TYPE_COPY, gpa, 1, size, value, dir, 0);
+ send_mmio_req(IOREQ_TYPE_COPY, gpa, 1, size, value, dir, df, 0);
} else {
- if ((addr & PAGE_MASK) != ((addr + sign * (count * size - 1)) & PAGE_MASK)) {
+ unsigned long last_addr = sign > 0 ? addr + count * size - 1
+ : addr - (count - 1) * size;
+
+ if ( (addr & PAGE_MASK) != (last_addr & PAGE_MASK) )
+ {
regs->eip -= inst_len; /* do not advance %eip */
- if (sign > 0) {
+ if ( sign > 0 )
count = (PAGE_SIZE - (addr & ~PAGE_MASK)) / size;
- } else {
- /* We need to make sure we advance to the point
- where the next request will be on a different
- page. If we're going down, that means
- advancing until one byte before the start of
- the page, hence +1. */
- count = ((addr + 1) & ~PAGE_MASK) / size;
- }
+ else
+ count = (addr & ~PAGE_MASK) / size + 1;
}
ASSERT(count);
- send_mmio_req(IOREQ_TYPE_COPY, gpa, count, size, addr, dir, 1);
+
+ send_mmio_req(IOREQ_TYPE_COPY, gpa, count, size, addr, dir, df, 1);
}
break;
}
case INSTR_MOVZX:
case INSTR_MOVSX:
- mmio_operands(IOREQ_TYPE_COPY, gpa, &mmio_inst, mmio_opp, regs);
+ mmio_operands(IOREQ_TYPE_COPY, gpa, mmio_op, op_size);
break;
case INSTR_STOS:
@@ -1008,10 +1014,8 @@ void handle_mmio(unsigned long va, unsigned long gpa)
* Since the destination is always in (contiguous) mmio space we don't
* need to break it up into pages.
*/
- mmio_opp->flags = mmio_inst.flags;
- mmio_opp->instr = mmio_inst.instr;
send_mmio_req(IOREQ_TYPE_COPY, gpa,
- GET_REPEAT_COUNT(), mmio_inst.op_size, regs->eax, IOREQ_WRITE, 0);
+ GET_REPEAT_COUNT(), op_size, regs->eax, IOREQ_WRITE, df, 0);
break;
case INSTR_LODS:
@@ -1019,87 +1023,70 @@ void handle_mmio(unsigned long va, unsigned long gpa)
* Since the source is always in (contiguous) mmio space we don't
* need to break it up into pages.
*/
- mmio_opp->flags = mmio_inst.flags;
- mmio_opp->instr = mmio_inst.instr;
send_mmio_req(IOREQ_TYPE_COPY, gpa,
- GET_REPEAT_COUNT(), mmio_inst.op_size, 0, IOREQ_READ, 0);
+ GET_REPEAT_COUNT(), op_size, 0, IOREQ_READ, df, 0);
break;
case INSTR_OR:
- mmio_operands(IOREQ_TYPE_OR, gpa, &mmio_inst, mmio_opp, regs);
+ mmio_operands(IOREQ_TYPE_OR, gpa, mmio_op, op_size);
break;
case INSTR_AND:
- mmio_operands(IOREQ_TYPE_AND, gpa, &mmio_inst, mmio_opp, regs);
+ mmio_operands(IOREQ_TYPE_AND, gpa, mmio_op, op_size);
break;
case INSTR_XOR:
- mmio_operands(IOREQ_TYPE_XOR, gpa, &mmio_inst, mmio_opp, regs);
+ mmio_operands(IOREQ_TYPE_XOR, gpa, mmio_op, op_size);
break;
case INSTR_CMP: /* Pass through */
case INSTR_TEST:
case INSTR_SUB:
- mmio_opp->flags = mmio_inst.flags;
- mmio_opp->instr = mmio_inst.instr;
- mmio_opp->operand[0] = mmio_inst.operand[0]; /* source */
- mmio_opp->operand[1] = mmio_inst.operand[1]; /* destination */
- mmio_opp->immediate = mmio_inst.immediate;
-
/* send the request and wait for the value */
- send_mmio_req(IOREQ_TYPE_COPY, gpa, 1,
- mmio_inst.op_size, 0, IOREQ_READ, 0);
+ send_mmio_req(IOREQ_TYPE_COPY, gpa, 1, op_size, 0, IOREQ_READ, df, 0);
break;
case INSTR_BT:
- {
- unsigned long value = 0;
- int index, size;
-
- mmio_opp->instr = mmio_inst.instr;
- mmio_opp->operand[0] = mmio_inst.operand[0]; /* bit offset */
- mmio_opp->operand[1] = mmio_inst.operand[1]; /* bit base */
+ {
+ unsigned long value = 0;
+ int index, size;
- if ( mmio_inst.operand[0] & REGISTER )
- {
- index = operand_index(mmio_inst.operand[0]);
- size = operand_size(mmio_inst.operand[0]);
- value = get_reg_value(size, index, 0, regs);
- }
- else if ( mmio_inst.operand[0] & IMMEDIATE )
- {
- mmio_opp->immediate = mmio_inst.immediate;
- value = mmio_inst.immediate;
- }
- send_mmio_req(IOREQ_TYPE_COPY, gpa + (value >> 5), 1,
- mmio_inst.op_size, 0, IOREQ_READ, 0);
- break;
+ if ( mmio_op->operand[0] & REGISTER )
+ {
+ index = operand_index(mmio_op->operand[0]);
+ size = operand_size(mmio_op->operand[0]);
+ value = get_reg_value(size, index, 0, regs);
+ }
+ else if ( mmio_op->operand[0] & IMMEDIATE )
+ {
+ mmio_op->immediate = mmio_op->immediate;
+ value = mmio_op->immediate;
}
+ send_mmio_req(IOREQ_TYPE_COPY, gpa + (value >> 5), 1,
+ op_size, 0, IOREQ_READ, df, 0);
+ break;
+ }
case INSTR_XCHG:
- mmio_opp->flags = mmio_inst.flags;
- mmio_opp->instr = mmio_inst.instr;
- mmio_opp->operand[0] = mmio_inst.operand[0]; /* source */
- mmio_opp->operand[1] = mmio_inst.operand[1]; /* destination */
- if ( mmio_inst.operand[0] & REGISTER ) {
+ if ( mmio_op->operand[0] & REGISTER ) {
long value;
- unsigned long operand = mmio_inst.operand[0];
+ unsigned long operand = mmio_op->operand[0];
value = get_reg_value(operand_size(operand),
operand_index(operand), 0,
regs);
/* send the request and wait for the value */
send_mmio_req(IOREQ_TYPE_XCHG, gpa, 1,
- mmio_inst.op_size, value, IOREQ_WRITE, 0);
+ op_size, value, IOREQ_WRITE, df, 0);
} else {
/* the destination is a register */
long value;
- unsigned long operand = mmio_inst.operand[1];
+ unsigned long operand = mmio_op->operand[1];
value = get_reg_value(operand_size(operand),
operand_index(operand), 0,
regs);
/* send the request and wait for the value */
send_mmio_req(IOREQ_TYPE_XCHG, gpa, 1,
- mmio_inst.op_size, value, IOREQ_WRITE, 0);
+ op_size, value, IOREQ_WRITE, df, 0);
}
break;
diff --git a/xen/arch/x86/hvm/rtc.c b/xen/arch/x86/hvm/rtc.c
new file mode 100644
index 0000000000..210168c26b
--- /dev/null
+++ b/xen/arch/x86/hvm/rtc.c
@@ -0,0 +1,393 @@
+/*
+ * QEMU MC146818 RTC emulation
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <asm/mc146818rtc.h>
+#include <asm/hvm/vpit.h>
+#include <asm/hvm/io.h>
+#include <asm/hvm/support.h>
+#include <asm/current.h>
+
+/* #define DEBUG_RTC */
+
+void rtc_periodic_cb(struct vcpu *v, void *opaque)
+{
+ RTCState *s = opaque;
+ s->cmos_data[RTC_REG_C] |= 0xc0;
+}
+
+int is_rtc_periodic_irq(void *opaque)
+{
+ RTCState *s = opaque;
+ return !(s->cmos_data[RTC_REG_C] & RTC_AF ||
+ s->cmos_data[RTC_REG_C] & RTC_UF);
+}
+
+static void rtc_timer_update(RTCState *s, int64_t current_time)
+{
+ int period_code;
+ int period;
+
+ period_code = s->cmos_data[RTC_REG_A] & 0x0f;
+ if (period_code != 0 && (s->cmos_data[RTC_REG_B] & RTC_PIE)) {
+ if (period_code <= 2)
+ period_code += 7;
+
+ period = 1 << (period_code - 1); /* period in 32 Khz cycles */
+ period = DIV_ROUND((period * 1000000000ULL), 32768); /* period in ns */
+
+#ifdef DEBUG_RTC
+ printk("HVM_RTC: period = %uns\n", period);
+#endif
+
+ s->pt = create_periodic_time(period, RTC_IRQ, 0, rtc_periodic_cb, s);
+ } else if (s->pt) {
+ destroy_periodic_time(s->pt);
+ s->pt = NULL;
+ }
+}
+
+static void rtc_set_time(RTCState *s);
+
+static int rtc_ioport_write(void *opaque, uint32_t addr, uint32_t data)
+{
+ RTCState *s = opaque;
+
+ if ((addr & 1) == 0) {
+ s->cmos_index = data & 0x7f;
+ if (s->cmos_index < RTC_SIZE)
+ return 1;
+ } else if (s->cmos_index < RTC_SIZE) {
+#ifdef DEBUG_RTC
+ printk("HVM_RTC: write index=0x%02x val=0x%02x\n",
+ s->cmos_index, data);
+#endif
+ switch(s->cmos_index) {
+ case RTC_SECONDS_ALARM:
+ case RTC_MINUTES_ALARM:
+ case RTC_HOURS_ALARM:
+ s->cmos_data[s->cmos_index] = data;
+ break;
+ case RTC_SECONDS:
+ case RTC_MINUTES:
+ case RTC_HOURS:
+ case RTC_DAY_OF_WEEK:
+ case RTC_DAY_OF_MONTH:
+ case RTC_MONTH:
+ case RTC_YEAR:
+ s->cmos_data[s->cmos_index] = data;
+ /* if in set mode, do not update the time */
+ if (!(s->cmos_data[RTC_REG_B] & RTC_SET)) {
+ rtc_set_time(s);
+ }
+ break;
+ case RTC_REG_A:
+ /* UIP bit is read only */
+ s->cmos_data[RTC_REG_A] = (data & ~RTC_UIP) |
+ (s->cmos_data[RTC_REG_A] & RTC_UIP);
+ rtc_timer_update(s, hvm_get_clock(s->vcpu));
+ break;
+ case RTC_REG_B:
+ if (data & RTC_SET) {
+ /* set mode: reset UIP mode */
+ s->cmos_data[RTC_REG_A] &= ~RTC_UIP;
+ data &= ~RTC_UIE;
+ } else {
+ /* if disabling set mode, update the time */
+ if (s->cmos_data[RTC_REG_B] & RTC_SET) {
+ rtc_set_time(s);
+ }
+ }
+ s->cmos_data[RTC_REG_B] = data;
+ rtc_timer_update(s, hvm_get_clock(s->vcpu));
+ break;
+ case RTC_REG_C:
+ case RTC_REG_D:
+ /* cannot write to them */
+ break;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static inline int to_bcd(RTCState *s, int a)
+{
+ if (s->cmos_data[RTC_REG_B] & 0x04) {
+ return a;
+ } else {
+ return ((a / 10) << 4) | (a % 10);
+ }
+}
+
+static inline int from_bcd(RTCState *s, int a)
+{
+ if (s->cmos_data[RTC_REG_B] & 0x04) {
+ return a;
+ } else {
+ return ((a >> 4) * 10) + (a & 0x0f);
+ }
+}
+
+static void rtc_set_time(RTCState *s)
+{
+ struct tm *tm = &s->current_tm;
+
+ tm->tm_sec = from_bcd(s, s->cmos_data[RTC_SECONDS]);
+ tm->tm_min = from_bcd(s, s->cmos_data[RTC_MINUTES]);
+ tm->tm_hour = from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
+ if (!(s->cmos_data[RTC_REG_B] & 0x02) &&
+ (s->cmos_data[RTC_HOURS] & 0x80)) {
+ tm->tm_hour += 12;
+ }
+ tm->tm_wday = from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]);
+ tm->tm_mday = from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
+ tm->tm_mon = from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
+ tm->tm_year = from_bcd(s, s->cmos_data[RTC_YEAR]) + 100;
+}
+
+static void rtc_copy_date(RTCState *s)
+{
+ const struct tm *tm = &s->current_tm;
+
+ s->cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec);
+ s->cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min);
+ if (s->cmos_data[RTC_REG_B] & 0x02) {
+ /* 24 hour format */
+ s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour);
+ } else {
+ /* 12 hour format */
+ s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour % 12);
+ if (tm->tm_hour >= 12)
+ s->cmos_data[RTC_HOURS] |= 0x80;
+ }
+ s->cmos_data[RTC_DAY_OF_WEEK] = to_bcd(s, tm->tm_wday);
+ s->cmos_data[RTC_DAY_OF_MONTH] = to_bcd(s, tm->tm_mday);
+ s->cmos_data[RTC_MONTH] = to_bcd(s, tm->tm_mon + 1);
+ s->cmos_data[RTC_YEAR] = to_bcd(s, tm->tm_year % 100);
+}
+
+/* month is between 0 and 11. */
+static int get_days_in_month(int month, int year)
+{
+ static const int days_tab[12] = {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+ };
+ int d;
+ if ((unsigned )month >= 12)
+ return 31;
+ d = days_tab[month];
+ if (month == 1) {
+ if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0))
+ d++;
+ }
+ return d;
+}
+
+/* update 'tm' to the next second */
+static void rtc_next_second(struct tm *tm)
+{
+ int days_in_month;
+
+ tm->tm_sec++;
+ if ((unsigned)tm->tm_sec >= 60) {
+ tm->tm_sec = 0;
+ tm->tm_min++;
+ if ((unsigned)tm->tm_min >= 60) {
+ tm->tm_min = 0;
+ tm->tm_hour++;
+ if ((unsigned)tm->tm_hour >= 24) {
+ tm->tm_hour = 0;
+ /* next day */
+ tm->tm_wday++;
+ if ((unsigned)tm->tm_wday >= 7)
+ tm->tm_wday = 0;
+ days_in_month = get_days_in_month(tm->tm_mon,
+ tm->tm_year + 1900);
+ tm->tm_mday++;
+ if (tm->tm_mday < 1) {
+ tm->tm_mday = 1;
+ } else if (tm->tm_mday > days_in_month) {
+ tm->tm_mday = 1;
+ tm->tm_mon++;
+ if (tm->tm_mon >= 12) {
+ tm->tm_mon = 0;
+ tm->tm_year++;
+ }
+ }
+ }
+ }
+ }
+}
+
+static void rtc_update_second(void *opaque)
+{
+ RTCState *s = opaque;
+
+ /* if the oscillator is not in normal operation, we do not update */
+ if ((s->cmos_data[RTC_REG_A] & 0x70) != 0x20) {
+ s->next_second_time += 1000000000ULL;
+ set_timer(&s->second_timer, s->next_second_time);
+ } else {
+ rtc_next_second(&s->current_tm);
+
+ if (!(s->cmos_data[RTC_REG_B] & RTC_SET)) {
+ /* update in progress bit */
+ s->cmos_data[RTC_REG_A] |= RTC_UIP;
+ }
+ /* Delay time before update cycle */
+ set_timer(&s->second_timer2, s->next_second_time + 244000);
+ }
+}
+
+static void rtc_update_second2(void *opaque)
+{
+ RTCState *s = opaque;
+ struct hvm_domain *plat=&s->vcpu->domain->arch.hvm_domain;
+ struct hvm_virpic *pic= &plat->vpic;
+
+ if (!(s->cmos_data[RTC_REG_B] & RTC_SET)) {
+ rtc_copy_date(s);
+ }
+
+ /* check alarm */
+ if (s->cmos_data[RTC_REG_B] & RTC_AIE) {
+ if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 ||
+ s->cmos_data[RTC_SECONDS_ALARM] == s->current_tm.tm_sec) &&
+ ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 ||
+ s->cmos_data[RTC_MINUTES_ALARM] == s->current_tm.tm_mon) &&
+ ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 ||
+ s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) {
+
+ s->cmos_data[RTC_REG_C] |= 0xa0;
+ pic_set_irq(pic, s->irq, 0);
+ pic_set_irq(pic, s->irq, 1);
+ }
+ }
+
+ /* update ended interrupt */
+ if (s->cmos_data[RTC_REG_B] & RTC_UIE) {
+ s->cmos_data[RTC_REG_C] |= 0x90;
+ pic_set_irq(pic, s->irq, 0);
+ pic_set_irq(pic, s->irq, 1);
+ }
+
+ /* clear update in progress bit */
+ s->cmos_data[RTC_REG_A] &= ~RTC_UIP;
+
+ s->next_second_time += 1000000000ULL;
+ set_timer(&s->second_timer, s->next_second_time);
+}
+
+static uint32_t rtc_ioport_read(void *opaque, uint32_t addr)
+{
+ RTCState *s = opaque;
+ struct hvm_domain *plat=&s->vcpu->domain->arch.hvm_domain;
+ struct hvm_virpic *pic= &plat->vpic;
+ int ret;
+
+ if ((addr & 1) == 0) {
+ return 0xff;
+ } else {
+ switch(s->cmos_index) {
+ case RTC_SECONDS:
+ case RTC_MINUTES:
+ case RTC_HOURS:
+ case RTC_DAY_OF_WEEK:
+ case RTC_DAY_OF_MONTH:
+ case RTC_MONTH:
+ case RTC_YEAR:
+ ret = s->cmos_data[s->cmos_index];
+ break;
+ case RTC_REG_A:
+ ret = s->cmos_data[s->cmos_index];
+ break;
+ case RTC_REG_C:
+ ret = s->cmos_data[s->cmos_index];
+ pic_set_irq(pic, s->irq, 0);
+ s->cmos_data[RTC_REG_C] = 0x00;
+ break;
+ default:
+ ret = s->cmos_data[s->cmos_index];
+ break;
+ }
+#ifdef DEBUG_RTC
+ printk("HVM_RTC: read index=0x%02x val=0x%02x\n",
+ s->cmos_index, ret);
+#endif
+ return ret;
+ }
+}
+
+static int handle_rtc_io(ioreq_t *p)
+{
+ struct vcpu *v = current;
+ struct RTCState *vrtc = &v->domain->arch.hvm_domain.pl_time.vrtc;
+
+ if (p->size != 1 ||
+ p->pdata_valid ||
+ p->type != IOREQ_TYPE_PIO){
+ printk("HVM_RTC: wrong RTC IO!\n");
+ return 1;
+ }
+
+ if (p->dir == 0) { /* write */
+ if (rtc_ioport_write(vrtc, p->addr, p->u.data & 0xFF))
+ return 1;
+ } else if (p->dir == 1 && vrtc->cmos_index < RTC_SIZE) { /* read */
+ p->u.data = rtc_ioport_read(vrtc, p->addr);
+ return 1;
+ }
+ return 0;
+}
+
+void rtc_init(struct vcpu *v, int base, int irq)
+{
+ RTCState *s = &v->domain->arch.hvm_domain.pl_time.vrtc;
+
+ s->vcpu = v;
+ s->irq = irq;
+ s->cmos_data[RTC_REG_A] = 0x26;
+ s->cmos_data[RTC_REG_B] = 0x02;
+ s->cmos_data[RTC_REG_C] = 0x00;
+ s->cmos_data[RTC_REG_D] = 0x80;
+
+ s->current_tm = gmtime(get_localtime(v->domain));
+ rtc_copy_date(s);
+
+ init_timer(&s->second_timer, rtc_update_second, s, v->processor);
+ init_timer(&s->second_timer2, rtc_update_second2, s, v->processor);
+
+ s->next_second_time = NOW() + 1000000000ULL;
+ set_timer(&s->second_timer2, s->next_second_time);
+
+ register_portio_handler(base, 2, handle_rtc_io);
+}
+
+void rtc_deinit(struct domain *d)
+{
+ RTCState *s = &d->arch.hvm_domain.pl_time.vrtc;
+
+ kill_timer(&s->second_timer);
+ kill_timer(&s->second_timer2);
+}
diff --git a/xen/arch/x86/hvm/svm/intr.c b/xen/arch/x86/hvm/svm/intr.c
index 0f30bd5478..9989105fca 100644
--- a/xen/arch/x86/hvm/svm/intr.c
+++ b/xen/arch/x86/hvm/svm/intr.c
@@ -43,7 +43,7 @@
* to be suitable for SVM.
*/
-static inline int svm_inject_extint(struct vcpu *v, int trap, int error_code)
+static inline int svm_inject_extint(struct vcpu *v, int trap)
{
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
vintr_t intr;
@@ -62,7 +62,7 @@ static inline int svm_inject_extint(struct vcpu *v, int trap, int error_code)
// printf( "IRQ = %d\n", trap );
return 0;
}
-
+
asmlinkage void svm_intr_assist(void)
{
struct vcpu *v = current;
@@ -74,7 +74,6 @@ asmlinkage void svm_intr_assist(void)
int intr_type = APIC_DM_EXTINT;
int intr_vector = -1;
int re_injecting = 0;
- unsigned long rflags;
ASSERT(vmcb);
@@ -82,19 +81,28 @@ asmlinkage void svm_intr_assist(void)
/* Previous Interrupt delivery caused this Intercept? */
if (vmcb->exitintinfo.fields.v && (vmcb->exitintinfo.fields.type == 0)) {
v->arch.hvm_svm.saved_irq_vector = vmcb->exitintinfo.fields.vector;
-// printk("Injecting PF#: saving IRQ from ExitInfo\n");
vmcb->exitintinfo.bytes = 0;
re_injecting = 1;
}
- /* Guest's interrputs masked? */
- rflags = vmcb->rflags;
- if (irq_masked(rflags)) {
- HVM_DBG_LOG(DBG_LEVEL_1, "Guest IRQs masked: rflags: %lx", rflags);
- /* bail out, we won't be injecting an interrupt this time */
+ /*
+ * If event requires injecting then do not inject int.
+ */
+ if (unlikely(v->arch.hvm_svm.inject_event)) {
+ v->arch.hvm_svm.inject_event = 0;
return;
}
-
+
+ /*
+ * create a 'fake' virtual interrupt on to intercept as soon
+ * as the guest _can_ take interrupts
+ */
+ if (irq_masked(vmcb->rflags) || vmcb->interrupt_shadow) {
+ vmcb->general1_intercepts |= GENERAL1_INTERCEPT_VINTR;
+ svm_inject_extint(v, 0x0); /* actual vector doesn't really matter */
+ return;
+ }
+
/* Previous interrupt still pending? */
if (vmcb->vintr.fields.irq) {
// printk("Re-injecting IRQ from Vintr\n");
@@ -140,14 +148,13 @@ asmlinkage void svm_intr_assist(void)
case APIC_DM_FIXED:
case APIC_DM_LOWEST:
/* Re-injecting a PIT interruptt? */
- if (re_injecting &&
- is_pit_irq(v, intr_vector, intr_type)) {
+ if (re_injecting && pt->enabled &&
+ is_periodic_irq(v, intr_vector, intr_type)) {
++pt->pending_intr_nr;
}
/* let's inject this interrupt */
- TRACE_3D(TRC_VMX_INT, v->domain->domain_id, intr_vector, 0);
- svm_inject_extint(v, intr_vector, VMX_DELIVER_NO_ERROR_CODE);
- hvm_interrupt_post(v, intr_vector, intr_type);
+ TRACE_3D(TRC_VMX_INTR, v->domain->domain_id, intr_vector, 0);
+ svm_inject_extint(v, intr_vector);
break;
case APIC_DM_SMI:
case APIC_DM_NMI:
@@ -158,6 +165,7 @@ asmlinkage void svm_intr_assist(void)
BUG();
break;
}
+ hvm_interrupt_post(v, intr_vector, intr_type);
}
}
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index ffefba24fc..0ba59591c0 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -54,13 +54,10 @@
/* External functions. We should move these to some suitable header file(s) */
-extern void do_nmi(struct cpu_user_regs *, unsigned long);
extern int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip,
int inst_len);
extern uint32_t vlapic_update_ppr(struct vlapic *vlapic);
extern asmlinkage void do_IRQ(struct cpu_user_regs *);
-extern void send_pio_req(struct cpu_user_regs *regs, unsigned long port,
- unsigned long count, int size, long value, int dir, int pvalid);
extern void svm_dump_inst(unsigned long eip);
extern int svm_dbg_on;
void svm_dump_regs(const char *from, struct cpu_user_regs *regs);
@@ -196,6 +193,7 @@ static inline void svm_inject_exception(struct vcpu *v, int trap,
ASSERT(vmcb->eventinj.fields.v == 0);
vmcb->eventinj = event;
+ v->arch.hvm_svm.inject_event=1;
}
static void stop_svm(void)
@@ -923,6 +921,7 @@ static void svm_relinquish_guest_resources(struct domain *d)
}
kill_timer(&d->arch.hvm_domain.pl_time.periodic_tm.timer);
+ rtc_deinit(d);
if ( d->arch.hvm_domain.shared_page_va )
unmap_domain_page_global(
@@ -937,6 +936,7 @@ static void svm_migrate_timers(struct vcpu *v)
{
struct periodic_time *pt =
&(v->domain->arch.hvm_domain.pl_time.periodic_tm);
+ struct RTCState *vrtc = &v->domain->arch.hvm_domain.pl_time.vrtc;
if ( pt->enabled )
{
@@ -945,6 +945,8 @@ static void svm_migrate_timers(struct vcpu *v)
}
if ( VLAPIC(v) != NULL )
migrate_timer(&VLAPIC(v)->vlapic_timer, v->processor);
+ migrate_timer(&vrtc->second_timer, v->processor);
+ migrate_timer(&vrtc->second_timer2, v->processor);
}
@@ -1410,7 +1412,7 @@ static void svm_io_instruction(struct vcpu *v)
struct cpu_user_regs *regs;
struct hvm_io_op *pio_opp;
unsigned int port;
- unsigned int size, dir;
+ unsigned int size, dir, df;
ioio_info_t info;
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
@@ -1429,6 +1431,8 @@ static void svm_io_instruction(struct vcpu *v)
port = info.fields.port; /* port used to be addr */
dir = info.fields.type; /* direction */
+ df = regs->eflags & X86_EFLAGS_DF ? 1 : 0;
+
if (info.fields.sz32)
size = 4;
else if (info.fields.sz16)
@@ -1445,7 +1449,7 @@ static void svm_io_instruction(struct vcpu *v)
if (info.fields.str)
{
unsigned long addr, count;
- int sign = regs->eflags & EF_DF ? -1 : 1;
+ int sign = regs->eflags & X86_EFLAGS_DF ? -1 : 1;
if (!svm_get_io_address(v, regs, dir, &count, &addr))
{
@@ -1475,25 +1479,37 @@ static void svm_io_instruction(struct vcpu *v)
unsigned long value = 0;
pio_opp->flags |= OVERLAP;
+ pio_opp->addr = addr;
+
+ if (dir == IOREQ_WRITE) /* OUTS */
+ {
+ if (hvm_paging_enabled(current))
+ (void)hvm_copy_from_guest_virt(&value, addr, size);
+ else
+ (void)hvm_copy_from_guest_phys(&value, addr, size);
+ }
- if (dir == IOREQ_WRITE)
- (void)hvm_copy_from_guest_virt(&value, addr, size);
+ if (count == 1)
+ regs->eip = vmcb->exitinfo2;
- send_pio_req(regs, port, 1, size, value, dir, 0);
+ send_pio_req(port, 1, size, value, dir, df, 0);
}
else
{
- if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK))
+ unsigned long last_addr = sign > 0 ? addr + count * size - 1
+ : addr - (count - 1) * size;
+
+ if ((addr & PAGE_MASK) != (last_addr & PAGE_MASK))
{
if (sign > 0)
count = (PAGE_SIZE - (addr & ~PAGE_MASK)) / size;
else
- count = (addr & ~PAGE_MASK) / size;
+ count = (addr & ~PAGE_MASK) / size + 1;
}
else
regs->eip = vmcb->exitinfo2;
- send_pio_req(regs, port, count, size, addr, dir, 1);
+ send_pio_req(port, count, size, addr, dir, df, 1);
}
}
else
@@ -1507,7 +1523,7 @@ static void svm_io_instruction(struct vcpu *v)
if (port == 0xe9 && dir == IOREQ_WRITE && size == 1)
hvm_print_line(v, regs->eax); /* guest debug output */
- send_pio_req(regs, port, 1, size, regs->eax, dir, 0);
+ send_pio_req(port, 1, size, regs->eax, dir, df, 0);
}
}
@@ -1539,9 +1555,8 @@ static int svm_set_cr0(unsigned long value)
if ((value & X86_CR0_PE) && (value & X86_CR0_PG) && !paging_enabled)
{
/* The guest CR3 must be pointing to the guest physical. */
- if (!VALID_MFN(mfn =
- get_mfn_from_gpfn(v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT))
- || !get_page(mfn_to_page(mfn), v->domain))
+ mfn = get_mfn_from_gpfn(v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT);
+ if ( !VALID_MFN(mfn) || !get_page(mfn_to_page(mfn), v->domain))
{
printk("Invalid CR3 value = %lx\n", v->arch.hvm_svm.cpu_cr3);
domain_crash_synchronous(); /* need to take a clean path */
@@ -1725,9 +1740,8 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
* first.
*/
HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 value = %lx", value);
- if (((value >> PAGE_SHIFT) > v->domain->max_pages)
- || !VALID_MFN(mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT))
- || !get_page(mfn_to_page(mfn), v->domain))
+ mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT);
+ if ( !VALID_MFN(mfn) || !get_page(mfn_to_page(mfn), v->domain))
{
printk("Invalid CR3 value=%lx\n", value);
domain_crash_synchronous(); /* need to take a clean path */
@@ -1739,9 +1753,6 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
if (old_base_mfn)
put_page(mfn_to_page(old_base_mfn));
- /*
- * arch.shadow_table should now hold the next CR3 for shadow
- */
v->arch.hvm_svm.cpu_cr3 = value;
update_cr3(v);
vmcb->cr3 = v->arch.hvm_vcpu.hw_cr3;
@@ -1764,9 +1775,8 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
/* The guest is a 32-bit PAE guest. */
#if CONFIG_PAGING_LEVELS >= 3
unsigned long mfn, old_base_mfn;
-
- if ( !VALID_MFN(mfn = get_mfn_from_gpfn(
- v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT)) ||
+ mfn = get_mfn_from_gpfn(v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT);
+ if ( !VALID_MFN(mfn) ||
!get_page(mfn_to_page(mfn), v->domain) )
{
printk("Invalid CR3 value = %lx", v->arch.hvm_svm.cpu_cr3);
@@ -1788,10 +1798,6 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
vmcb->cr3 = v->arch.hvm_vcpu.hw_cr3;
- /*
- * arch->shadow_table should hold the next CR3 for shadow
- */
-
HVM_DBG_LOG(DBG_LEVEL_VMMU,
"Update CR3 value = %lx, mfn = %lx",
v->arch.hvm_svm.cpu_cr3, mfn);
@@ -2355,7 +2361,7 @@ void svm_dump_regs(const char *from, struct cpu_user_regs *regs)
{
struct vcpu *v = current;
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
- unsigned long pt = pagetable_get_paddr(v->arch.shadow_table);
+ unsigned long pt = v->arch.hvm_vcpu.hw_cr3;
printf("%s: guest registers from %s:\n", __func__, from);
#if defined (__x86_64__)
@@ -2589,7 +2595,7 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)
save_svm_cpu_user_regs(v, regs);
vmcb->tlb_control = 1;
-
+ v->arch.hvm_svm.inject_event = 0;
if (exit_reason == VMEXIT_INVALID)
{
@@ -2681,11 +2687,11 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)
if (do_debug)
{
printk("%s:+ guest_table = 0x%08x, monitor_table = 0x%08x, "
- "shadow_table = 0x%08x\n",
+ "hw_cr3 = 0x%16lx\n",
__func__,
(int) v->arch.guest_table.pfn,
(int) v->arch.monitor_table.pfn,
- (int) v->arch.shadow_table.pfn);
+ (long unsigned int) v->arch.hvm_vcpu.hw_cr3);
svm_dump_vmcb(__func__, vmcb);
svm_dump_regs(__func__, regs);
@@ -2729,7 +2735,6 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)
break;
case VMEXIT_NMI:
- do_nmi(regs, 0);
break;
case VMEXIT_SMI:
@@ -2788,7 +2793,7 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)
v->arch.hvm_svm.cpu_cr2 = va;
vmcb->cr2 = va;
- TRACE_3D(TRC_VMX_INT, v->domain->domain_id,
+ TRACE_3D(TRC_VMX_INTR, v->domain->domain_id,
VMEXIT_EXCEPTION_PF, va);
}
break;
@@ -2802,6 +2807,11 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)
svm_inject_exception(v, TRAP_double_fault, 1, 0);
break;
+ case VMEXIT_VINTR:
+ vmcb->vintr.fields.irq = 0;
+ vmcb->general1_intercepts &= ~GENERAL1_INTERCEPT_VINTR;
+ break;
+
case VMEXIT_INTR:
break;
@@ -2913,10 +2923,10 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)
if (do_debug)
{
printk("vmexit_handler():- guest_table = 0x%08x, "
- "monitor_table = 0x%08x, shadow_table = 0x%08x\n",
+ "monitor_table = 0x%08x, hw_cr3 = 0x%16x\n",
(int)v->arch.guest_table.pfn,
(int)v->arch.monitor_table.pfn,
- (int)v->arch.shadow_table.pfn);
+ (int)v->arch.hvm_vcpu.hw_cr3);
printk("svm_vmexit_handler: Returning\n");
}
#endif
diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c
index b3e3cd13c9..93fced8753 100644
--- a/xen/arch/x86/hvm/svm/vmcb.c
+++ b/xen/arch/x86/hvm/svm/vmcb.c
@@ -372,8 +372,8 @@ void svm_do_launch(struct vcpu *v)
if (svm_dbg_on)
{
unsigned long pt;
- pt = pagetable_get_paddr(v->arch.shadow_table);
- printk("%s: shadow_table = %lx\n", __func__, pt);
+ printk("%s: hw_cr3 = %llx\n", __func__,
+ (unsigned long long) v->arch.hvm_vcpu.hw_cr3);
pt = pagetable_get_paddr(v->arch.guest_table);
printk("%s: guest_table = %lx\n", __func__, pt);
pt = pagetable_get_paddr(v->domain->arch.phys_table);
@@ -387,8 +387,9 @@ void svm_do_launch(struct vcpu *v)
{
printk("%s: cr3 = %lx ", __func__, (unsigned long)vmcb->cr3);
printk("init_guest_table: guest_table = 0x%08x, monitor_table = 0x%08x,"
- " shadow_table = 0x%08x\n", (int)v->arch.guest_table.pfn,
- (int)v->arch.monitor_table.pfn, (int)v->arch.shadow_table.pfn);
+ " hw_cr3 = 0x%16llx\n", (int)v->arch.guest_table.pfn,
+ (int)v->arch.monitor_table.pfn,
+ (unsigned long long) v->arch.hvm_vcpu.hw_cr3);
}
v->arch.schedule_tail = arch_svm_do_resume;
diff --git a/xen/arch/x86/hvm/svm/x86_32/exits.S b/xen/arch/x86/hvm/svm/x86_32/exits.S
index 99a08cd483..a2714030fd 100644
--- a/xen/arch/x86/hvm/svm/x86_32/exits.S
+++ b/xen/arch/x86/hvm/svm/x86_32/exits.S
@@ -126,6 +126,8 @@ ENTRY(svm_asm_do_launch)
HVM_SAVE_ALL_NOSEGREGS
STGI
+.globl svm_stgi_label;
+svm_stgi_label:
movl %esp,%eax
push %eax
call svm_vmexit_handler
diff --git a/xen/arch/x86/hvm/svm/x86_64/exits.S b/xen/arch/x86/hvm/svm/x86_64/exits.S
index 1e36baf53d..11c62f9d9e 100644
--- a/xen/arch/x86/hvm/svm/x86_64/exits.S
+++ b/xen/arch/x86/hvm/svm/x86_64/exits.S
@@ -144,6 +144,8 @@ ENTRY(svm_asm_do_launch)
VMLOAD
STGI
+.globl svm_stgi_label;
+svm_stgi_label:
movq %rsp,%rdi
call svm_vmexit_handler
jmp svm_asm_do_resume
diff --git a/xen/arch/x86/hvm/vioapic.c b/xen/arch/x86/hvm/vioapic.c
index daa812a6f3..e608b24fbf 100644
--- a/xen/arch/x86/hvm/vioapic.c
+++ b/xen/arch/x86/hvm/vioapic.c
@@ -42,6 +42,9 @@
/* HACK: Route IRQ0 only to VCPU0 to prevent time jumps. */
#define IRQ0_SPECIAL_ROUTING 1
+#ifdef IRQ0_SPECIAL_ROUTING
+static int redir_warning_done = 0;
+#endif
#if defined(__ia64__)
#define opt_hvm_debug_level opt_vmx_debug_level
@@ -155,6 +158,7 @@ static void hvm_vioapic_update_imr(struct hvm_vioapic *s, int index)
clear_bit(index, &s->imr);
}
+
static void hvm_vioapic_write_indirect(struct hvm_vioapic *s,
unsigned long addr,
unsigned long length,
@@ -179,21 +183,35 @@ static void hvm_vioapic_write_indirect(struct hvm_vioapic *s,
{
uint32_t redir_index = 0;
+ redir_index = (s->ioregsel - 0x10) >> 1;
+
HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "hvm_vioapic_write_indirect "
"change redir index %x val %lx\n",
redir_index, val);
- redir_index = (s->ioregsel - 0x10) >> 1;
-
if (redir_index >= 0 && redir_index < IOAPIC_NUM_PINS) {
uint64_t redir_content;
redir_content = s->redirtbl[redir_index].value;
- if (s->ioregsel & 0x1)
+ if (s->ioregsel & 0x1) {
+#ifdef IRQ0_SPECIAL_ROUTING
+ if ( !redir_warning_done && (redir_index == 0) &&
+ ((val >> 24) != 0) ) {
+ /*
+ * Cannot yet handle delivering PIT interrupts to
+ * any VCPU != 0. Needs proper fixing, but for now
+ * simply spit a warning that we're going to ignore
+ * the target in practice & always deliver to VCPU 0
+ */
+ printk("IO-APIC: PIT (IRQ0) redirect to VCPU %lx "
+ "will be ignored.\n", val >> 24);
+ redir_warning_done = 1;
+ }
+#endif
redir_content = (((uint64_t)val & 0xffffffff) << 32) |
(redir_content & 0xffffffff);
- else
+ } else
redir_content = ((redir_content >> 32) << 32) |
(val & 0xffffffff);
s->redirtbl[redir_index].value = redir_content;
@@ -409,6 +427,8 @@ static void ioapic_deliver(hvm_vioapic_t *s, int irqno)
uint8_t vector = s->redirtbl[irqno].RedirForm.vector;
uint8_t trig_mode = s->redirtbl[irqno].RedirForm.trigmod;
uint32_t deliver_bitmask;
+ struct vlapic *target;
+
HVM_DBG_LOG(DBG_LEVEL_IOAPIC,
"dest %x dest_mode %x delivery_mode %x vector %x trig_mode %x\n",
@@ -427,9 +447,8 @@ static void ioapic_deliver(hvm_vioapic_t *s, int irqno)
switch (delivery_mode) {
case dest_LowestPrio:
{
- struct vlapic* target;
-
#ifdef IRQ0_SPECIAL_ROUTING
+ /* Force round-robin to pick VCPU 0 */
if (irqno == 0)
target = s->lapic_info[0];
else
@@ -450,19 +469,17 @@ static void ioapic_deliver(hvm_vioapic_t *s, int irqno)
{
uint8_t bit;
for (bit = 0; bit < s->lapic_count; bit++) {
- if (deliver_bitmask & (1 << bit)) {
+ if ( !(deliver_bitmask & (1 << bit)) )
+ continue;
#ifdef IRQ0_SPECIAL_ROUTING
- if ( (irqno == 0) && (bit !=0) )
- {
- printk("PIT irq to bit %x\n", bit);
- domain_crash_synchronous();
- }
+ /* Do not deliver timer interrupts to VCPU != 0 */
+ if ( (irqno == 0) && (bit !=0 ) )
+ target = s->lapic_info[0];
+ else
#endif
- if (s->lapic_info[bit]) {
- ioapic_inj_irq(s, s->lapic_info[bit],
- vector, trig_mode, delivery_mode);
- }
- }
+ target = s->lapic_info[bit];
+ if (target)
+ ioapic_inj_irq(s, target, vector, trig_mode, delivery_mode);
}
break;
}
diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c
index 533b6c8237..8c121ee2c3 100644
--- a/xen/arch/x86/hvm/vlapic.c
+++ b/xen/arch/x86/hvm/vlapic.c
@@ -231,7 +231,8 @@ static int vlapic_accept_irq(struct vcpu *v, int delivery_mode,
"level trig mode for vector %d\n", vector);
vlapic_set_vector(vector, vlapic->regs + APIC_TMR);
}
- hvm_prod_vcpu(v);
+
+ vcpu_kick(v);
result = 1;
break;
diff --git a/xen/arch/x86/hvm/vmx/io.c b/xen/arch/x86/hvm/vmx/io.c
index cc7fdcb1b0..07731ad251 100644
--- a/xen/arch/x86/hvm/vmx/io.c
+++ b/xen/arch/x86/hvm/vmx/io.c
@@ -153,7 +153,7 @@ asmlinkage void vmx_intr_assist(void)
case APIC_DM_FIXED:
case APIC_DM_LOWEST:
vmx_inject_extint(v, highest_vector, VMX_DELIVER_NO_ERROR_CODE);
- TRACE_3D(TRC_VMX_INT, v->domain->domain_id, highest_vector, 0);
+ TRACE_3D(TRC_VMX_INTR, v->domain->domain_id, highest_vector, 0);
break;
case APIC_DM_SMI:
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index db83ffe9f9..6d98a858ec 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -146,6 +146,7 @@ static void vmx_relinquish_guest_resources(struct domain *d)
}
kill_timer(&d->arch.hvm_domain.pl_time.periodic_tm.timer);
+ rtc_deinit(d);
if ( d->arch.hvm_domain.shared_page_va )
unmap_domain_page_global(
@@ -487,6 +488,7 @@ static void stop_vmx(void)
void vmx_migrate_timers(struct vcpu *v)
{
struct periodic_time *pt = &(v->domain->arch.hvm_domain.pl_time.periodic_tm);
+ struct RTCState *vrtc = &v->domain->arch.hvm_domain.pl_time.vrtc;
if ( pt->enabled )
{
@@ -495,6 +497,8 @@ void vmx_migrate_timers(struct vcpu *v)
}
if ( VLAPIC(v) != NULL )
migrate_timer(&VLAPIC(v)->vlapic_timer, v->processor);
+ migrate_timer(&vrtc->second_timer, v->processor);
+ migrate_timer(&vrtc->second_timer2, v->processor);
}
static void vmx_store_cpu_guest_regs(
@@ -867,7 +871,7 @@ static int vmx_do_page_fault(unsigned long va, struct cpu_user_regs *regs)
result = shadow_fault(va, regs);
- TRACE_VMEXIT (2,result);
+ TRACE_VMEXIT(2, result);
#if 0
if ( !result )
{
@@ -898,7 +902,7 @@ static void vmx_do_no_device_fault(void)
}
#define bitmaskof(idx) (1U << ((idx)&31))
-static void vmx_vmexit_do_cpuid(struct cpu_user_regs *regs)
+static void vmx_do_cpuid(struct cpu_user_regs *regs)
{
unsigned int input = (unsigned int)regs->eax;
unsigned int count = (unsigned int)regs->ecx;
@@ -917,7 +921,32 @@ static void vmx_vmexit_do_cpuid(struct cpu_user_regs *regs)
if ( input == CPUID_LEAF_0x4 )
{
cpuid_count(input, count, &eax, &ebx, &ecx, &edx);
- eax &= NUM_CORES_RESET_MASK;
+ eax &= NUM_CORES_RESET_MASK;
+ }
+ else if ( input == 0x40000003 )
+ {
+ /*
+ * NB. Unsupported interface for private use of VMXASSIST only.
+ * Note that this leaf lives at <max-hypervisor-leaf> + 1.
+ */
+ u64 value = ((u64)regs->edx << 32) | (u32)regs->ecx;
+ unsigned long mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT);
+ char *p;
+
+ DPRINTK("Input address is 0x%"PRIx64".\n", value);
+
+ /* 8-byte aligned valid pseudophys address from vmxassist, please. */
+ if ( (value & 7) || (mfn == INVALID_MFN) ||
+ !v->arch.hvm_vmx.vmxassist_enabled )
+ domain_crash_synchronous();
+
+ p = map_domain_page(mfn);
+ value = *((uint64_t *)(p + (value & (PAGE_SIZE - 1))));
+ unmap_domain_page(p);
+
+ DPRINTK("Output value is 0x%"PRIx64".\n", value);
+ ecx = (u32)(value >> 0);
+ edx = (u32)(value >> 32);
}
else if ( !cpuid_hypervisor_leaves(input, &eax, &ebx, &ecx, &edx) )
{
@@ -1023,14 +1052,14 @@ static void vmx_dr_access(unsigned long exit_qualification,
* Invalidate the TLB for va. Invalidate the shadow page corresponding
* the address va.
*/
-static void vmx_vmexit_do_invlpg(unsigned long va)
+static void vmx_do_invlpg(unsigned long va)
{
unsigned long eip;
struct vcpu *v = current;
__vmread(GUEST_RIP, &eip);
- HVM_DBG_LOG(DBG_LEVEL_VMMU, "vmx_vmexit_do_invlpg: eip=%lx, va=%lx",
+ HVM_DBG_LOG(DBG_LEVEL_VMMU, "eip=%lx, va=%lx",
eip, va);
/*
@@ -1041,14 +1070,20 @@ static void vmx_vmexit_do_invlpg(unsigned long va)
}
-static int check_for_null_selector(unsigned long eip)
+static int check_for_null_selector(unsigned long eip, int inst_len, int dir)
{
unsigned char inst[MAX_INST_LEN];
unsigned long sel;
- int i, inst_len;
+ int i;
int inst_copy_from_guest(unsigned char *, unsigned long, int);
- inst_len = __get_instruction_length(); /* Safe: INS/OUTS */
+ /* INS can only use ES segment register, and it can't be overridden */
+ if ( dir == IOREQ_READ )
+ {
+ __vmread(GUEST_ES_SELECTOR, &sel);
+ return sel == 0 ? 1 : 0;
+ }
+
memset(inst, 0, MAX_INST_LEN);
if ( inst_copy_from_guest(inst, eip, inst_len) != inst_len )
{
@@ -1093,18 +1128,13 @@ static int check_for_null_selector(unsigned long eip)
return 0;
}
-extern void send_pio_req(struct cpu_user_regs *regs, unsigned long port,
- unsigned long count, int size, long value,
- int dir, int pvalid);
-
static void vmx_io_instruction(unsigned long exit_qualification,
unsigned long inst_len)
{
struct cpu_user_regs *regs;
struct hvm_io_op *pio_opp;
- unsigned long eip, cs, eflags;
- unsigned long port, size, dir;
- int vm86;
+ unsigned long port, size;
+ int dir, df, vm86;
pio_opp = &current->arch.hvm_vcpu.io_op;
pio_opp->instr = INSTR_PIO;
@@ -1116,28 +1146,26 @@ static void vmx_io_instruction(unsigned long exit_qualification,
memcpy(regs, guest_cpu_user_regs(), HVM_CONTEXT_STACK_BYTES);
hvm_store_cpu_guest_regs(current, regs, NULL);
- eip = regs->eip;
- cs = regs->cs;
- eflags = regs->eflags;
-
- vm86 = eflags & X86_EFLAGS_VM ? 1 : 0;
+ vm86 = regs->eflags & X86_EFLAGS_VM ? 1 : 0;
+ df = regs->eflags & X86_EFLAGS_DF ? 1 : 0;
- HVM_DBG_LOG(DBG_LEVEL_IO,
- "vmx_io_instruction: vm86 %d, eip=%lx:%lx, "
+ HVM_DBG_LOG(DBG_LEVEL_IO, "vm86 %d, eip=%x:%lx, "
"exit_qualification = %lx",
- vm86, cs, eip, exit_qualification);
+ vm86, regs->cs, (unsigned long)regs->eip, exit_qualification);
- if (test_bit(6, &exit_qualification))
+ if ( test_bit(6, &exit_qualification) )
port = (exit_qualification >> 16) & 0xFFFF;
else
port = regs->edx & 0xffff;
- TRACE_VMEXIT(1, port);
+
+ TRACE_VMEXIT(1,port);
+
size = (exit_qualification & 7) + 1;
dir = test_bit(3, &exit_qualification); /* direction */
- if (test_bit(4, &exit_qualification)) { /* string instruction */
+ if ( test_bit(4, &exit_qualification) ) { /* string instruction */
unsigned long addr, count = 1;
- int sign = regs->eflags & EF_DF ? -1 : 1;
+ int sign = regs->eflags & X86_EFLAGS_DF ? -1 : 1;
__vmread(GUEST_LINEAR_ADDRESS, &addr);
@@ -1145,10 +1173,10 @@ static void vmx_io_instruction(unsigned long exit_qualification,
* In protected mode, guest linear address is invalid if the
* selector is null.
*/
- if (!vm86 && check_for_null_selector(eip))
+ if ( !vm86 && check_for_null_selector(regs->eip, inst_len, dir) )
addr = dir == IOREQ_WRITE ? regs->esi : regs->edi;
- if (test_bit(5, &exit_qualification)) { /* "rep" prefix */
+ if ( test_bit(5, &exit_qualification) ) { /* "rep" prefix */
pio_opp->flags |= REPZ;
count = vm86 ? regs->ecx & 0xFFFF : regs->ecx;
}
@@ -1157,30 +1185,45 @@ static void vmx_io_instruction(unsigned long exit_qualification,
* Handle string pio instructions that cross pages or that
* are unaligned. See the comments in hvm_domain.c/handle_mmio()
*/
- if ((addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK)) {
+ if ( (addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK) ) {
unsigned long value = 0;
pio_opp->flags |= OVERLAP;
- if (dir == IOREQ_WRITE)
- (void)hvm_copy_from_guest_virt(&value, addr, size);
- send_pio_req(regs, port, 1, size, value, dir, 0);
+
+ if ( dir == IOREQ_WRITE ) /* OUTS */
+ {
+ if ( hvm_paging_enabled(current) )
+ (void)hvm_copy_from_guest_virt(&value, addr, size);
+ else
+ (void)hvm_copy_from_guest_phys(&value, addr, size);
+ } else
+ pio_opp->addr = addr;
+
+ if ( count == 1 )
+ regs->eip += inst_len;
+
+ send_pio_req(port, 1, size, value, dir, df, 0);
} else {
- if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK)) {
- if (sign > 0)
+ unsigned long last_addr = sign > 0 ? addr + count * size - 1
+ : addr - (count - 1) * size;
+
+ if ( (addr & PAGE_MASK) != (last_addr & PAGE_MASK) )
+ {
+ if ( sign > 0 )
count = (PAGE_SIZE - (addr & ~PAGE_MASK)) / size;
else
- count = (addr & ~PAGE_MASK) / size;
+ count = (addr & ~PAGE_MASK) / size + 1;
} else
regs->eip += inst_len;
- send_pio_req(regs, port, count, size, addr, dir, 1);
+ send_pio_req(port, count, size, addr, dir, df, 1);
}
} else {
- if (port == 0xe9 && dir == IOREQ_WRITE && size == 1)
+ if ( port == 0xe9 && dir == IOREQ_WRITE && size == 1 )
hvm_print_line(current, regs->eax); /* guest debug output */
regs->eip += inst_len;
- send_pio_req(regs, port, 1, size, regs->eax, dir, 0);
+ send_pio_req(port, 1, size, regs->eax, dir, df, 0);
}
}
@@ -1280,12 +1323,13 @@ static int vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c)
* first.
*/
HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 c->cr3 = %x", c->cr3);
- if ((c->cr3 >> PAGE_SHIFT) > v->domain->max_pages) {
+ mfn = get_mfn_from_gpfn(c->cr3 >> PAGE_SHIFT);
+ if ( !VALID_MFN(mfn) )
+ {
printk("Invalid CR3 value=%x", c->cr3);
domain_crash_synchronous();
return 0;
}
- mfn = get_mfn_from_gpfn(c->cr3 >> PAGE_SHIFT);
if(!get_page(mfn_to_page(mfn), v->domain))
return 0;
old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
@@ -1465,9 +1509,8 @@ static int vmx_set_cr0(unsigned long value)
* Trying to enable guest paging.
* The guest CR3 must be pointing to the guest physical.
*/
- if ( !VALID_MFN(mfn = get_mfn_from_gpfn(
- v->arch.hvm_vmx.cpu_cr3 >> PAGE_SHIFT)) ||
- !get_page(mfn_to_page(mfn), v->domain) )
+ mfn = get_mfn_from_gpfn(v->arch.hvm_vmx.cpu_cr3 >> PAGE_SHIFT);
+ if ( !VALID_MFN(mfn) || !get_page(mfn_to_page(mfn), v->domain) )
{
printk("Invalid CR3 value = %lx (mfn=%lx)\n",
v->arch.hvm_vmx.cpu_cr3, mfn);
@@ -1629,6 +1672,10 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs)
__hvm_bug(regs);
}
+ TRACE_VMEXIT(1, TYPE_MOV_TO_CR);
+ TRACE_VMEXIT(2, cr);
+ TRACE_VMEXIT(3, value);
+
HVM_DBG_LOG(DBG_LEVEL_1, "CR%d, value = %lx", cr, value);
switch ( cr ) {
@@ -1665,11 +1712,10 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs)
* first.
*/
HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 value = %lx", value);
- if ( ((value >> PAGE_SHIFT) > v->domain->max_pages ) ||
- !VALID_MFN(mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT)) ||
- !get_page(mfn_to_page(mfn), v->domain) )
+ mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT);
+ if ( !VALID_MFN(mfn) || !get_page(mfn_to_page(mfn), v->domain) )
{
- printk("Invalid CR3 value=%lx", value);
+ printk("Invalid CR3 value=%lx\n", value);
domain_crash_synchronous(); /* need to take a clean path */
}
old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
@@ -1698,16 +1744,14 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs)
/* The guest is a 32-bit PAE guest. */
#if CONFIG_PAGING_LEVELS >= 3
unsigned long mfn, old_base_mfn;
-
- if ( !VALID_MFN(mfn = get_mfn_from_gpfn(
- v->arch.hvm_vmx.cpu_cr3 >> PAGE_SHIFT)) ||
+ mfn = get_mfn_from_gpfn(v->arch.hvm_vmx.cpu_cr3 >> PAGE_SHIFT);
+ if ( !VALID_MFN(mfn) ||
!get_page(mfn_to_page(mfn), v->domain) )
{
printk("Invalid CR3 value = %lx", v->arch.hvm_vmx.cpu_cr3);
domain_crash_synchronous(); /* need to take a clean path */
}
-
/*
* Now arch.guest_table points to machine physical.
*/
@@ -1810,6 +1854,10 @@ static void mov_from_cr(int cr, int gp, struct cpu_user_regs *regs)
__hvm_bug(regs);
}
+ TRACE_VMEXIT(1, TYPE_MOV_FROM_CR);
+ TRACE_VMEXIT(2, cr);
+ TRACE_VMEXIT(3, value);
+
HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR%d, value = %lx", cr, value);
}
@@ -1824,20 +1872,14 @@ static int vmx_cr_access(unsigned long exit_qualification,
case TYPE_MOV_TO_CR:
gp = exit_qualification & CONTROL_REG_ACCESS_REG;
cr = exit_qualification & CONTROL_REG_ACCESS_NUM;
- TRACE_VMEXIT(1,TYPE_MOV_TO_CR);
- TRACE_VMEXIT(2,cr);
- TRACE_VMEXIT(3,gp);
return mov_to_cr(gp, cr, regs);
case TYPE_MOV_FROM_CR:
gp = exit_qualification & CONTROL_REG_ACCESS_REG;
cr = exit_qualification & CONTROL_REG_ACCESS_NUM;
- TRACE_VMEXIT(1,TYPE_MOV_FROM_CR);
- TRACE_VMEXIT(2,cr);
- TRACE_VMEXIT(3,gp);
mov_from_cr(cr, gp, regs);
break;
case TYPE_CLTS:
- TRACE_VMEXIT(1,TYPE_CLTS);
+ TRACE_VMEXIT(1, TYPE_CLTS);
/* We initialise the FPU now, to avoid needing another vmexit. */
setup_fpu(v);
@@ -1852,10 +1894,11 @@ static int vmx_cr_access(unsigned long exit_qualification,
__vmwrite(CR0_READ_SHADOW, value);
break;
case TYPE_LMSW:
- TRACE_VMEXIT(1,TYPE_LMSW);
__vmread_vcpu(v, CR0_READ_SHADOW, &value);
value = (value & ~0xF) |
(((exit_qualification & LMSW_SOURCE_DATA) >> 16) & 0xF);
+ TRACE_VMEXIT(1, TYPE_LMSW);
+ TRACE_VMEXIT(2, value);
return vmx_set_cr0(value);
break;
default:
@@ -1871,7 +1914,7 @@ static inline void vmx_do_msr_read(struct cpu_user_regs *regs)
u32 eax, edx;
struct vcpu *v = current;
- HVM_DBG_LOG(DBG_LEVEL_1, "vmx_do_msr_read: ecx=%lx, eax=%lx, edx=%lx",
+ HVM_DBG_LOG(DBG_LEVEL_1, "ecx=%lx, eax=%lx, edx=%lx",
(unsigned long)regs->ecx, (unsigned long)regs->eax,
(unsigned long)regs->edx);
switch (regs->ecx) {
@@ -1908,8 +1951,7 @@ static inline void vmx_do_msr_read(struct cpu_user_regs *regs)
regs->eax = msr_content & 0xFFFFFFFF;
regs->edx = msr_content >> 32;
- HVM_DBG_LOG(DBG_LEVEL_1, "vmx_do_msr_read returns: "
- "ecx=%lx, eax=%lx, edx=%lx",
+ HVM_DBG_LOG(DBG_LEVEL_1, "returns: ecx=%lx, eax=%lx, edx=%lx",
(unsigned long)regs->ecx, (unsigned long)regs->eax,
(unsigned long)regs->edx);
}
@@ -1919,7 +1961,7 @@ static inline void vmx_do_msr_write(struct cpu_user_regs *regs)
u64 msr_content;
struct vcpu *v = current;
- HVM_DBG_LOG(DBG_LEVEL_1, "vmx_do_msr_write: ecx=%lx, eax=%lx, edx=%lx",
+ HVM_DBG_LOG(DBG_LEVEL_1, "ecx=%lx, eax=%lx, edx=%lx",
(unsigned long)regs->ecx, (unsigned long)regs->eax,
(unsigned long)regs->edx);
@@ -1947,20 +1989,19 @@ static inline void vmx_do_msr_write(struct cpu_user_regs *regs)
break;
}
- HVM_DBG_LOG(DBG_LEVEL_1, "vmx_do_msr_write returns: "
- "ecx=%lx, eax=%lx, edx=%lx",
+ HVM_DBG_LOG(DBG_LEVEL_1, "returns: ecx=%lx, eax=%lx, edx=%lx",
(unsigned long)regs->ecx, (unsigned long)regs->eax,
(unsigned long)regs->edx);
}
-void vmx_vmexit_do_hlt(void)
+static void vmx_do_hlt(void)
{
unsigned long rflags;
__vmread(GUEST_RFLAGS, &rflags);
hvm_hlt(rflags);
}
-static inline void vmx_vmexit_do_extint(struct cpu_user_regs *regs)
+static inline void vmx_do_extint(struct cpu_user_regs *regs)
{
unsigned int vector;
int error;
@@ -1981,7 +2022,7 @@ static inline void vmx_vmexit_do_extint(struct cpu_user_regs *regs)
__hvm_bug(regs);
vector &= INTR_INFO_VECTOR_MASK;
- TRACE_VMEXIT(1,vector);
+ TRACE_VMEXIT(1, vector);
switch(vector) {
case LOCAL_TIMER_VECTOR:
@@ -2112,7 +2153,7 @@ static void vmx_reflect_exception(struct vcpu *v)
asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
{
unsigned int exit_reason;
- unsigned long exit_qualification, rip, inst_len = 0;
+ unsigned long exit_qualification, inst_len = 0;
struct vcpu *v = current;
__vmread(VM_EXIT_REASON, &exit_reason);
@@ -2154,7 +2195,7 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
domain_crash_synchronous();
}
- TRACE_VMEXIT(0,exit_reason);
+ TRACE_VMEXIT(0, exit_reason);
switch ( exit_reason )
{
@@ -2166,14 +2207,13 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
* (2) NMI
*/
unsigned int vector;
- unsigned long va;
if ( __vmread(VM_EXIT_INTR_INFO, &vector) ||
!(vector & INTR_INFO_VALID_MASK) )
domain_crash_synchronous();
vector &= INTR_INFO_VECTOR_MASK;
- TRACE_VMEXIT(1,vector);
+ TRACE_VMEXIT(1, vector);
perfc_incra(cause_vector, vector);
switch ( vector ) {
@@ -2229,11 +2269,11 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
}
case TRAP_page_fault:
{
- __vmread(EXIT_QUALIFICATION, &va);
+ __vmread(EXIT_QUALIFICATION, &exit_qualification);
__vmread(VM_EXIT_INTR_ERROR_CODE, &regs->error_code);
TRACE_VMEXIT(3, regs->error_code);
- TRACE_VMEXIT(4, va);
+ TRACE_VMEXIT(4, exit_qualification);
HVM_DBG_LOG(DBG_LEVEL_VMMU,
"eax=%lx, ebx=%lx, ecx=%lx, edx=%lx, esi=%lx, edi=%lx",
@@ -2241,13 +2281,13 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
(unsigned long)regs->ecx, (unsigned long)regs->edx,
(unsigned long)regs->esi, (unsigned long)regs->edi);
- if ( !vmx_do_page_fault(va, regs) )
+ if ( !vmx_do_page_fault(exit_qualification, regs) )
{
/* Inject #PG using Interruption-Information Fields. */
vmx_inject_hw_exception(v, TRAP_page_fault, regs->error_code);
- v->arch.hvm_vmx.cpu_cr2 = va;
- TRACE_3D(TRC_VMX_INT, v->domain->domain_id,
- TRAP_page_fault, va);
+ v->arch.hvm_vmx.cpu_cr2 = exit_qualification;
+ TRACE_3D(TRC_VMX_INTR, v->domain->domain_id,
+ TRAP_page_fault, exit_qualification);
}
break;
}
@@ -2261,7 +2301,7 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
break;
}
case EXIT_REASON_EXTERNAL_INTERRUPT:
- vmx_vmexit_do_extint(regs);
+ vmx_do_extint(regs);
break;
case EXIT_REASON_TRIPLE_FAULT:
domain_crash_synchronous();
@@ -2278,39 +2318,35 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
case EXIT_REASON_CPUID:
inst_len = __get_instruction_length(); /* Safe: CPUID */
__update_guest_eip(inst_len);
- vmx_vmexit_do_cpuid(regs);
+ vmx_do_cpuid(regs);
break;
case EXIT_REASON_HLT:
inst_len = __get_instruction_length(); /* Safe: HLT */
__update_guest_eip(inst_len);
- vmx_vmexit_do_hlt();
+ vmx_do_hlt();
break;
case EXIT_REASON_INVLPG:
{
- unsigned long va;
inst_len = __get_instruction_length(); /* Safe: INVLPG */
__update_guest_eip(inst_len);
- __vmread(EXIT_QUALIFICATION, &va);
- vmx_vmexit_do_invlpg(va);
+ __vmread(EXIT_QUALIFICATION, &exit_qualification);
+ vmx_do_invlpg(exit_qualification);
+ TRACE_VMEXIT(4, exit_qualification);
break;
}
case EXIT_REASON_VMCALL:
{
inst_len = __get_instruction_length(); /* Safe: VMCALL */
__update_guest_eip(inst_len);
- __vmread(GUEST_RIP, &rip);
- __vmread(EXIT_QUALIFICATION, &exit_qualification);
hvm_do_hypercall(regs);
break;
}
case EXIT_REASON_CR_ACCESS:
{
- __vmread(GUEST_RIP, &rip);
__vmread(EXIT_QUALIFICATION, &exit_qualification);
inst_len = __get_instruction_length(); /* Safe: MOV Cn, LMSW, CLTS */
if ( vmx_cr_access(exit_qualification, regs) )
__update_guest_eip(inst_len);
- TRACE_VMEXIT(3, regs->error_code);
TRACE_VMEXIT(4, exit_qualification);
break;
}
@@ -2322,17 +2358,23 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
__vmread(EXIT_QUALIFICATION, &exit_qualification);
inst_len = __get_instruction_length(); /* Safe: IN, INS, OUT, OUTS */
vmx_io_instruction(exit_qualification, inst_len);
- TRACE_VMEXIT(4,exit_qualification);
+ TRACE_VMEXIT(4, exit_qualification);
break;
case EXIT_REASON_MSR_READ:
inst_len = __get_instruction_length(); /* Safe: RDMSR */
__update_guest_eip(inst_len);
vmx_do_msr_read(regs);
+ TRACE_VMEXIT(1, regs->ecx);
+ TRACE_VMEXIT(2, regs->eax);
+ TRACE_VMEXIT(3, regs->edx);
break;
case EXIT_REASON_MSR_WRITE:
inst_len = __get_instruction_length(); /* Safe: WRMSR */
__update_guest_eip(inst_len);
vmx_do_msr_write(regs);
+ TRACE_VMEXIT(1, regs->ecx);
+ TRACE_VMEXIT(2, regs->eax);
+ TRACE_VMEXIT(3, regs->edx);
break;
case EXIT_REASON_MWAIT_INSTRUCTION:
case EXIT_REASON_MONITOR_INSTRUCTION:
@@ -2366,26 +2408,25 @@ asmlinkage void vmx_load_cr2(void)
asm volatile("mov %0,%%cr2": :"r" (v->arch.hvm_vmx.cpu_cr2));
}
-asmlinkage void vmx_trace_vmentry (void)
+asmlinkage void vmx_trace_vmentry(void)
{
- TRACE_5D(TRC_VMX_VMENTRY,
+ TRACE_5D(TRC_VMX_VMENTRY + current->vcpu_id,
this_cpu(trace_values)[0],
this_cpu(trace_values)[1],
this_cpu(trace_values)[2],
this_cpu(trace_values)[3],
this_cpu(trace_values)[4]);
- TRACE_VMEXIT(0,9);
- TRACE_VMEXIT(1,9);
- TRACE_VMEXIT(2,9);
- TRACE_VMEXIT(3,9);
- TRACE_VMEXIT(4,9);
- return;
+
+ TRACE_VMEXIT(0, 0);
+ TRACE_VMEXIT(1, 0);
+ TRACE_VMEXIT(2, 0);
+ TRACE_VMEXIT(3, 0);
+ TRACE_VMEXIT(4, 0);
}
asmlinkage void vmx_trace_vmexit (void)
{
- TRACE_3D(TRC_VMX_VMEXIT,0,0,0);
- return;
+ TRACE_3D(TRC_VMX_VMEXIT + current->vcpu_id, 0, 0, 0);
}
/*
diff --git a/xen/arch/x86/i387.c b/xen/arch/x86/i387.c
index ebfc37fa7b..899f80da3b 100644
--- a/xen/arch/x86/i387.c
+++ b/xen/arch/x86/i387.c
@@ -14,6 +14,7 @@
#include <asm/processor.h>
#include <asm/hvm/support.h>
#include <asm/i387.h>
+#include <asm/asm_defns.h>
void init_fpu(void)
{
@@ -41,11 +42,11 @@ void save_init_fpu(struct vcpu *v)
#else /* __x86_64__ */
/*
* The only way to force fxsaveq on a wide range of gas versions. On
- * older versions the rex64 prefix works only if we force an addressing
- * mode that doesn't require extended registers.
+ * older versions the rex64 prefix works only if we force an
+ * addressing mode that doesn't require extended registers.
*/
__asm__ __volatile__ (
- "rex64/fxsave (%1)"
+ REX64_PREFIX "fxsave (%1)"
: "=m" (*fpu_ctxt) : "cdaSDb" (fpu_ctxt) );
#endif
@@ -95,7 +96,7 @@ void restore_fpu(struct vcpu *v)
"1: fxrstor %0 \n"
#else /* __x86_64__ */
/* See above for why the operands/constraints are this way. */
- "1: rex64/fxrstor (%2) \n"
+ "1: " REX64_PREFIX "fxrstor (%2)\n"
#endif
".section .fixup,\"ax\" \n"
"2: push %%"__OP"ax \n"
diff --git a/xen/arch/x86/io_apic.c b/xen/arch/x86/io_apic.c
index 9a86c040d0..4b30851276 100644
--- a/xen/arch/x86/io_apic.c
+++ b/xen/arch/x86/io_apic.c
@@ -269,13 +269,10 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask)
int pin;
struct irq_pin_list *entry = irq_2_pin + irq;
unsigned int apicid_value;
- cpumask_t tmp;
-
- cpus_and(tmp, cpumask, cpu_online_map);
- if (cpus_empty(tmp))
- tmp = TARGET_CPUS;
- cpus_and(cpumask, tmp, CPU_MASK_ALL);
+ cpus_and(cpumask, cpumask, cpu_online_map);
+ if (cpus_empty(cpumask))
+ cpumask = TARGET_CPUS;
apicid_value = cpu_mask_to_apicid(cpumask);
/* Prepare to do the io_apic_write */
diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c
index 4fa637ad01..4bad3ee23e 100644
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -450,7 +450,7 @@ int pirq_guest_bind(struct vcpu *v, int irq, int will_share)
action->in_flight = 0;
action->shareable = will_share;
action->ack_type = pirq_acktype(irq);
- action->cpu_eoi_map = CPU_MASK_NONE;
+ cpus_clear(action->cpu_eoi_map);
desc->depth = 0;
desc->status |= IRQ_GUEST;
diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c
index 40f8bfb4b2..c053e64ffb 100644
--- a/xen/arch/x86/mm/shadow/common.c
+++ b/xen/arch/x86/mm/shadow/common.c
@@ -283,11 +283,8 @@ __shadow_validate_guest_entry(struct vcpu *v, mfn_t gmfn,
if ( page->shadow_flags & SHF_L2H_PAE )
result |= SHADOW_INTERNAL_NAME(sh_map_and_validate_gl2he, 3, 3)
(v, gmfn, entry, size);
- if ( page->shadow_flags & SHF_L3_PAE )
- result |= SHADOW_INTERNAL_NAME(sh_map_and_validate_gl3e, 3, 3)
- (v, gmfn, entry, size);
#else /* 32-bit non-PAE hypervisor does not support PAE guests */
- ASSERT((page->shadow_flags & (SHF_L3_PAE|SHF_L2_PAE|SHF_L1_PAE)) == 0);
+ ASSERT((page->shadow_flags & (SHF_L2H_PAE|SHF_L2_PAE|SHF_L1_PAE)) == 0);
#endif
#if CONFIG_PAGING_LEVELS >= 4
@@ -343,8 +340,11 @@ shadow_validate_guest_pt_write(struct vcpu *v, mfn_t gmfn,
if ( rc & SHADOW_SET_ERROR )
{
/* This page is probably not a pagetable any more: tear it out of the
- * shadows, along with any tables that reference it */
- shadow_remove_all_shadows_and_parents(v, gmfn);
+ * shadows, along with any tables that reference it.
+ * Since the validate call above will have made a "safe" (i.e. zero)
+ * shadow entry, we can let the domain live even if we can't fully
+ * unshadow the page. */
+ sh_remove_shadows(v, gmfn, 0, 0);
}
}
@@ -424,22 +424,16 @@ shadow_validate_guest_pt_write(struct vcpu *v, mfn_t gmfn,
/* Allocating shadow pages
* -----------------------
*
- * Most shadow pages are allocated singly, but there are two cases where we
- * need to allocate multiple pages together.
- *
- * 1: Shadowing 32-bit guest tables on PAE or 64-bit shadows.
- * A 32-bit guest l1 table covers 4MB of virtuial address space,
- * and needs to be shadowed by two PAE/64-bit l1 tables (covering 2MB
- * of virtual address space each). Similarly, a 32-bit guest l2 table
- * (4GB va) needs to be shadowed by four PAE/64-bit l2 tables (1GB va
- * each). These multi-page shadows are contiguous and aligned;
- * functions for handling offsets into them are defined in shadow.c
- * (shadow_l1_index() etc.)
+ * Most shadow pages are allocated singly, but there is one case where
+ * we need to allocate multiple pages together: shadowing 32-bit guest
+ * tables on PAE or 64-bit shadows. A 32-bit guest l1 table covers 4MB
+ * of virtuial address space, and needs to be shadowed by two PAE/64-bit
+ * l1 tables (covering 2MB of virtual address space each). Similarly, a
+ * 32-bit guest l2 table (4GB va) needs to be shadowed by four
+ * PAE/64-bit l2 tables (1GB va each). These multi-page shadows are
+ * contiguous and aligned; functions for handling offsets into them are
+ * defined in shadow.c (shadow_l1_index() etc.)
*
- * 2: Shadowing PAE top-level pages. Each guest page that contains
- * any PAE top-level pages requires two shadow pages to shadow it.
- * They contain alternating l3 tables and pae_l3_bookkeeping structs.
- *
* This table shows the allocation behaviour of the different modes:
*
* Xen paging 32b pae pae 64b 64b 64b
@@ -449,7 +443,7 @@ shadow_validate_guest_pt_write(struct vcpu *v, mfn_t gmfn,
*
* sl1 size 4k 8k 4k 8k 4k 4k
* sl2 size 4k 16k 4k 16k 4k 4k
- * sl3 size - - 8k - 8k 4k
+ * sl3 size - - - - - 4k
* sl4 size - - - - - 4k
*
* We allocate memory from xen in four-page units and break them down
@@ -503,7 +497,6 @@ shadow_order(u32 shadow_type)
0, /* PGC_SH_fl1_pae_shadow */
0, /* PGC_SH_l2_pae_shadow */
0, /* PGC_SH_l2h_pae_shadow */
- 1, /* PGC_SH_l3_pae_shadow */
0, /* PGC_SH_l1_64_shadow */
0, /* PGC_SH_fl1_64_shadow */
0, /* PGC_SH_l2_64_shadow */
@@ -546,7 +539,8 @@ void shadow_unhook_mappings(struct vcpu *v, mfn_t smfn)
#endif
break;
#if CONFIG_PAGING_LEVELS >= 3
- case PGC_SH_l3_pae_shadow >> PGC_SH_type_shift:
+ case PGC_SH_l2_pae_shadow >> PGC_SH_type_shift:
+ case PGC_SH_l2h_pae_shadow >> PGC_SH_type_shift:
SHADOW_INTERNAL_NAME(sh_unhook_pae_mappings,3,3)(v,smfn);
break;
#endif
@@ -573,13 +567,18 @@ void shadow_prealloc(struct domain *d, unsigned int order)
{
/* Need a vpcu for calling unpins; for now, since we don't have
* per-vcpu shadows, any will do */
- struct vcpu *v = d->vcpu[0];
+ struct vcpu *v, *v2;
struct list_head *l, *t;
struct page_info *pg;
+ cpumask_t flushmask = CPU_MASK_NONE;
mfn_t smfn;
if ( chunk_is_available(d, order) ) return;
+ v = current;
+ if ( v->domain != d )
+ v = d->vcpu[0];
+
/* Stage one: walk the list of top-level pages, unpinning them */
perfc_incrc(shadow_prealloc_1);
list_for_each_backwards_safe(l, t, &d->arch.shadow.toplevel_shadows)
@@ -587,18 +586,8 @@ void shadow_prealloc(struct domain *d, unsigned int order)
pg = list_entry(l, struct page_info, list);
smfn = page_to_mfn(pg);
-#if CONFIG_PAGING_LEVELS >= 3
- if ( (pg->count_info & PGC_SH_type_mask) == PGC_SH_l3_pae_shadow )
- {
- /* For PAE, we need to unpin each subshadow on this shadow */
- SHADOW_INTERNAL_NAME(sh_unpin_all_l3_subshadows,3,3)(v, smfn);
- }
- else
-#endif /* 32-bit code always takes this branch */
- {
- /* Unpin this top-level shadow */
- sh_unpin(v, smfn);
- }
+ /* Unpin this top-level shadow */
+ sh_unpin(v, smfn);
/* See if that freed up a chunk of appropriate size */
if ( chunk_is_available(d, order) ) return;
@@ -608,24 +597,30 @@ void shadow_prealloc(struct domain *d, unsigned int order)
* loaded in cr3 on some vcpu. Walk them, unhooking the non-Xen
* mappings. */
perfc_incrc(shadow_prealloc_2);
- v = current;
- if ( v->domain != d )
- v = d->vcpu[0];
- /* Walk the list from the tail: recently used toplevels have been pulled
- * to the head */
list_for_each_backwards_safe(l, t, &d->arch.shadow.toplevel_shadows)
{
pg = list_entry(l, struct page_info, list);
smfn = page_to_mfn(pg);
shadow_unhook_mappings(v, smfn);
- /* Need to flush TLB if we've altered our own tables */
- if ( !shadow_mode_external(d)
- && pagetable_get_pfn(current->arch.shadow_table) == mfn_x(smfn) )
- local_flush_tlb();
-
+ /* Remember to flush TLBs: we have removed shadow entries that
+ * were in use by some vcpu(s). */
+ for_each_vcpu(d, v2)
+ {
+ if ( pagetable_get_pfn(v2->arch.shadow_table[0]) == mfn_x(smfn)
+ || pagetable_get_pfn(v2->arch.shadow_table[1]) == mfn_x(smfn)
+ || pagetable_get_pfn(v2->arch.shadow_table[2]) == mfn_x(smfn)
+ || pagetable_get_pfn(v2->arch.shadow_table[3]) == mfn_x(smfn)
+ )
+ cpus_or(flushmask, v2->vcpu_dirty_cpumask, flushmask);
+ }
+
/* See if that freed up a chunk of appropriate size */
- if ( chunk_is_available(d, order) ) return;
+ if ( chunk_is_available(d, order) )
+ {
+ flush_tlb_mask(flushmask);
+ return;
+ }
}
/* Nothing more we can do: all remaining shadows are of pages that
@@ -732,6 +727,15 @@ void shadow_free(struct domain *d, mfn_t smfn)
for ( i = 0; i < 1<<order; i++ )
{
+#if SHADOW_OPTIMIZATIONS & SHOPT_WRITABLE_HEURISTIC
+ struct vcpu *v;
+ for_each_vcpu(d, v)
+ {
+ /* No longer safe to look for a writeable mapping in this shadow */
+ if ( v->arch.shadow.last_writeable_pte_smfn == mfn_x(smfn) + i )
+ v->arch.shadow.last_writeable_pte_smfn = 0;
+ }
+#endif
/* Strip out the type: this is now a free shadow page */
pg[i].count_info = 0;
/* Remember the TLB timestamp so we will know whether to flush
@@ -920,9 +924,20 @@ p2m_next_level(struct domain *d, mfn_t *table_mfn, void **table,
#if CONFIG_PAGING_LEVELS == 3
if (type == PGT_l2_page_table)
{
+ struct vcpu *v;
/* We have written to the p2m l3: need to sync the per-vcpu
* copies of it in the monitor tables */
p2m_install_entry_in_monitors(d, (l3_pgentry_t *)p2m_entry);
+ /* Also, any vcpus running on shadows of the p2m need to
+ * reload their CR3s so the change propagates to the shadow */
+ ASSERT(shadow_lock_is_acquired(d));
+ for_each_vcpu(d, v)
+ {
+ if ( pagetable_get_pfn(v->arch.guest_table)
+ == pagetable_get_pfn(d->arch.phys_table)
+ && v->arch.shadow.mode != NULL )
+ v->arch.shadow.mode->update_cr3(v);
+ }
}
#endif
/* The P2M can be shadowed: keep the shadows synced */
@@ -1711,9 +1726,6 @@ void sh_destroy_shadow(struct vcpu *v, mfn_t smfn)
case PGC_SH_l2h_pae_shadow >> PGC_SH_type_shift:
SHADOW_INTERNAL_NAME(sh_destroy_l2_shadow, 3, 3)(v, smfn);
break;
- case PGC_SH_l3_pae_shadow >> PGC_SH_type_shift:
- SHADOW_INTERNAL_NAME(sh_destroy_l3_shadow, 3, 3)(v, smfn);
- break;
#endif
#if CONFIG_PAGING_LEVELS >= 4
@@ -1768,7 +1780,6 @@ int shadow_remove_write_access(struct vcpu *v, mfn_t gmfn,
#endif
NULL, /* l2_pae */
NULL, /* l2h_pae */
- NULL, /* l3_pae */
#if CONFIG_PAGING_LEVELS >= 4
SHADOW_INTERNAL_NAME(sh_remove_write_access,4,4), /* l1_64 */
SHADOW_INTERNAL_NAME(sh_remove_write_access,4,4), /* fl1_64 */
@@ -1825,12 +1836,11 @@ int shadow_remove_write_access(struct vcpu *v, mfn_t gmfn,
unsigned long gfn;
/* Heuristic: there is likely to be only one writeable mapping,
* and that mapping is likely to be in the current pagetable,
- * either in the guest's linear map (linux, windows) or in a
- * magic slot used to map high memory regions (linux HIGHTPTE) */
+ * in the guest's linear map (on non-HIGHPTE linux and windows)*/
#define GUESS(_a, _h) do { \
- if ( v->arch.shadow.mode->guess_wrmap(v, (_a), gmfn) ) \
- perfc_incrc(shadow_writeable_h_ ## _h); \
+ if ( v->arch.shadow.mode->guess_wrmap(v, (_a), gmfn) ) \
+ perfc_incrc(shadow_writeable_h_ ## _h); \
if ( (pg->u.inuse.type_info & PGT_count_mask) == 0 ) \
return 1; \
} while (0)
@@ -1880,9 +1890,35 @@ int shadow_remove_write_access(struct vcpu *v, mfn_t gmfn,
#endif /* CONFIG_PAGING_LEVELS >= 3 */
#undef GUESS
+ }
+
+ if ( (pg->u.inuse.type_info & PGT_count_mask) == 0 )
+ return 1;
+
+ /* Second heuristic: on HIGHPTE linux, there are two particular PTEs
+ * (entries in the fixmap) where linux maps its pagetables. Since
+ * we expect to hit them most of the time, we start the search for
+ * the writeable mapping by looking at the same MFN where the last
+ * brute-force search succeeded. */
+
+ if ( v->arch.shadow.last_writeable_pte_smfn != 0 )
+ {
+ unsigned long old_count = (pg->u.inuse.type_info & PGT_count_mask);
+ mfn_t last_smfn = _mfn(v->arch.shadow.last_writeable_pte_smfn);
+ int shtype = (mfn_to_page(last_smfn)->count_info & PGC_SH_type_mask)
+ >> PGC_SH_type_shift;
+
+ if ( callbacks[shtype] )
+ callbacks[shtype](v, last_smfn, gmfn);
+ if ( (pg->u.inuse.type_info & PGT_count_mask) != old_count )
+ perfc_incrc(shadow_writeable_h_5);
}
-#endif
+
+ if ( (pg->u.inuse.type_info & PGT_count_mask) == 0 )
+ return 1;
+
+#endif /* SHADOW_OPTIMIZATIONS & SHOPT_WRITABLE_HEURISTIC */
/* Brute-force search of all the shadows, by walking the hash */
perfc_incrc(shadow_writeable_bf);
@@ -1932,7 +1968,6 @@ int shadow_remove_all_mappings(struct vcpu *v, mfn_t gmfn)
#endif
NULL, /* l2_pae */
NULL, /* l2h_pae */
- NULL, /* l3_pae */
#if CONFIG_PAGING_LEVELS >= 4
SHADOW_INTERNAL_NAME(sh_remove_all_mappings,4,4), /* l1_64 */
SHADOW_INTERNAL_NAME(sh_remove_all_mappings,4,4), /* fl1_64 */
@@ -2005,7 +2040,8 @@ static int sh_remove_shadow_via_pointer(struct vcpu *v, mfn_t smfn)
ASSERT((pg->count_info & PGC_SH_type_mask) > 0);
ASSERT((pg->count_info & PGC_SH_type_mask) < PGC_SH_max_shadow);
ASSERT((pg->count_info & PGC_SH_type_mask) != PGC_SH_l2_32_shadow);
- ASSERT((pg->count_info & PGC_SH_type_mask) != PGC_SH_l3_pae_shadow);
+ ASSERT((pg->count_info & PGC_SH_type_mask) != PGC_SH_l2_pae_shadow);
+ ASSERT((pg->count_info & PGC_SH_type_mask) != PGC_SH_l2h_pae_shadow);
ASSERT((pg->count_info & PGC_SH_type_mask) != PGC_SH_l4_64_shadow);
if (pg->up == 0) return 0;
@@ -2034,7 +2070,6 @@ static int sh_remove_shadow_via_pointer(struct vcpu *v, mfn_t smfn)
case PGC_SH_l1_pae_shadow:
case PGC_SH_l2_pae_shadow:
case PGC_SH_l2h_pae_shadow:
- case PGC_SH_l3_pae_shadow:
SHADOW_INTERNAL_NAME(sh_clear_shadow_entry,3,3)(v, vaddr, pmfn);
break;
#if CONFIG_PAGING_LEVELS >= 4
@@ -2058,17 +2093,20 @@ static int sh_remove_shadow_via_pointer(struct vcpu *v, mfn_t smfn)
return rc;
}
-void sh_remove_shadows(struct vcpu *v, mfn_t gmfn, int all)
+void sh_remove_shadows(struct vcpu *v, mfn_t gmfn, int fast, int all)
/* Remove the shadows of this guest page.
- * If all != 0, find all shadows, if necessary by walking the tables.
- * Otherwise, just try the (much faster) heuristics, which will remove
- * at most one reference to each shadow of the page. */
+ * If fast != 0, just try the quick heuristic, which will remove
+ * at most one reference to each shadow of the page. Otherwise, walk
+ * all the shadow tables looking for refs to shadows of this gmfn.
+ * If all != 0, kill the domain if we can't find all the shadows.
+ * (all != 0 implies fast == 0)
+ */
{
struct page_info *pg;
mfn_t smfn;
u32 sh_flags;
unsigned char t;
-
+
/* Dispatch table for getting per-type functions: each level must
* be called with the function to remove a lower-level shadow. */
static hash_callback_t callbacks[16] = {
@@ -2085,11 +2123,9 @@ void sh_remove_shadows(struct vcpu *v, mfn_t gmfn, int all)
#if CONFIG_PAGING_LEVELS >= 3
SHADOW_INTERNAL_NAME(sh_remove_l1_shadow,3,3), /* l2_pae */
SHADOW_INTERNAL_NAME(sh_remove_l1_shadow,3,3), /* l2h_pae */
- SHADOW_INTERNAL_NAME(sh_remove_l2_shadow,3,3), /* l3_pae */
#else
NULL, /* l2_pae */
NULL, /* l2h_pae */
- NULL, /* l3_pae */
#endif
NULL, /* l1_64 */
NULL, /* fl1_64 */
@@ -2115,9 +2151,8 @@ void sh_remove_shadows(struct vcpu *v, mfn_t gmfn, int all)
((1 << (PGC_SH_l2h_pae_shadow >> PGC_SH_type_shift))
| (1 << (PGC_SH_l2_pae_shadow >> PGC_SH_type_shift))), /* l1_pae */
0, /* fl1_pae */
- 1 << (PGC_SH_l3_pae_shadow >> PGC_SH_type_shift), /* l2_pae */
- 1 << (PGC_SH_l3_pae_shadow >> PGC_SH_type_shift), /* l2h_pae */
- 0, /* l3_pae */
+ 0, /* l2_pae */
+ 0, /* l2h_pae */
1 << (PGC_SH_l2_64_shadow >> PGC_SH_type_shift), /* l1_64 */
0, /* fl1_64 */
1 << (PGC_SH_l3_64_shadow >> PGC_SH_type_shift), /* l2_64 */
@@ -2128,6 +2163,7 @@ void sh_remove_shadows(struct vcpu *v, mfn_t gmfn, int all)
};
ASSERT(shadow_lock_is_acquired(v->domain));
+ ASSERT(!(all && fast));
pg = mfn_to_page(gmfn);
@@ -2147,29 +2183,26 @@ void sh_remove_shadows(struct vcpu *v, mfn_t gmfn, int all)
* call will remove at most one shadow, and terminate immediately when
* it does remove it, so we never walk the hash after doing a deletion. */
#define DO_UNSHADOW(_type) do { \
- t = (_type) >> PGC_SH_type_shift; \
- smfn = shadow_hash_lookup(v, mfn_x(gmfn), t); \
- if ( !sh_remove_shadow_via_pointer(v, smfn) && all ) \
+ t = (_type) >> PGC_SH_type_shift; \
+ smfn = shadow_hash_lookup(v, mfn_x(gmfn), t); \
+ if ( !sh_remove_shadow_via_pointer(v, smfn) && !fast ) \
hash_foreach(v, masks[t], callbacks, smfn); \
} while (0)
/* Top-level shadows need to be unpinned */
-#define DO_UNPIN(_type) do { \
+#define DO_UNPIN(_type) do { \
t = (_type) >> PGC_SH_type_shift; \
smfn = shadow_hash_lookup(v, mfn_x(gmfn), t); \
if ( mfn_to_page(smfn)->count_info & PGC_SH_pinned ) \
sh_unpin(v, smfn); \
- if ( (_type) == PGC_SH_l3_pae_shadow ) \
- SHADOW_INTERNAL_NAME(sh_unpin_all_l3_subshadows,3,3)(v, smfn); \
} while (0)
if ( sh_flags & SHF_L1_32 ) DO_UNSHADOW(PGC_SH_l1_32_shadow);
if ( sh_flags & SHF_L2_32 ) DO_UNPIN(PGC_SH_l2_32_shadow);
#if CONFIG_PAGING_LEVELS >= 3
if ( sh_flags & SHF_L1_PAE ) DO_UNSHADOW(PGC_SH_l1_pae_shadow);
- if ( sh_flags & SHF_L2_PAE ) DO_UNSHADOW(PGC_SH_l2_pae_shadow);
- if ( sh_flags & SHF_L2H_PAE ) DO_UNSHADOW(PGC_SH_l2h_pae_shadow);
- if ( sh_flags & SHF_L3_PAE ) DO_UNPIN(PGC_SH_l3_pae_shadow);
+ if ( sh_flags & SHF_L2_PAE ) DO_UNPIN(PGC_SH_l2_pae_shadow);
+ if ( sh_flags & SHF_L2H_PAE ) DO_UNPIN(PGC_SH_l2h_pae_shadow);
#if CONFIG_PAGING_LEVELS >= 4
if ( sh_flags & SHF_L1_64 ) DO_UNSHADOW(PGC_SH_l1_64_shadow);
if ( sh_flags & SHF_L2_64 ) DO_UNSHADOW(PGC_SH_l2_64_shadow);
@@ -2181,21 +2214,19 @@ void sh_remove_shadows(struct vcpu *v, mfn_t gmfn, int all)
#undef DO_UNSHADOW
#undef DO_UNPIN
-
-#if CONFIG_PAGING_LEVELS > 2
- /* We may have caused some PAE l3 entries to change: need to
- * fix up the copies of them in various places */
- if ( sh_flags & (SHF_L2_PAE|SHF_L2H_PAE) )
- sh_pae_recopy(v->domain);
-#endif
-
/* If that didn't catch the shadows, something is wrong */
- if ( all && (pg->count_info & PGC_page_table) )
+ if ( !fast && (pg->count_info & PGC_page_table) )
{
- SHADOW_ERROR("can't find all shadows of mfn %05lx (shadow_flags=%08x)\n",
+ SHADOW_ERROR("can't find all shadows of mfn %05lx "
+ "(shadow_flags=%08x)\n",
mfn_x(gmfn), pg->shadow_flags);
- domain_crash(v->domain);
+ if ( all )
+ domain_crash(v->domain);
}
+
+ /* Need to flush TLBs now, so that linear maps are safe next time we
+ * take a fault. */
+ flush_tlb_mask(v->domain->domain_dirty_cpumask);
}
void
@@ -2681,7 +2712,7 @@ int shadow_test_enable(struct domain *d)
if ( shadow_mode_enabled(d) )
{
SHADOW_ERROR("Don't support enabling test mode"
- "on already shadowed doms\n");
+ " on already shadowed doms\n");
ret = -EINVAL;
goto out;
}
@@ -2754,7 +2785,7 @@ static int shadow_log_dirty_enable(struct domain *d)
if ( shadow_mode_enabled(d) )
{
SHADOW_ERROR("Don't (yet) support enabling log-dirty"
- "on already shadowed doms\n");
+ " on already shadowed doms\n");
ret = -EINVAL;
goto out;
}
@@ -3118,7 +3149,6 @@ void shadow_audit_tables(struct vcpu *v)
SHADOW_INTERNAL_NAME(sh_audit_fl1_table,3,3), /* fl1_pae */
SHADOW_INTERNAL_NAME(sh_audit_l2_table,3,3), /* l2_pae */
SHADOW_INTERNAL_NAME(sh_audit_l2_table,3,3), /* l2h_pae */
- SHADOW_INTERNAL_NAME(sh_audit_l3_table,3,3), /* l3_pae */
#if CONFIG_PAGING_LEVELS >= 4
SHADOW_INTERNAL_NAME(sh_audit_l1_table,4,4), /* l1_64 */
SHADOW_INTERNAL_NAME(sh_audit_fl1_table,4,4), /* fl1_64 */
@@ -3143,7 +3173,7 @@ void shadow_audit_tables(struct vcpu *v)
{
case 2: mask = (SHF_L1_32|SHF_FL1_32|SHF_L2_32); break;
case 3: mask = (SHF_L1_PAE|SHF_FL1_PAE|SHF_L2_PAE
- |SHF_L2H_PAE|SHF_L3_PAE); break;
+ |SHF_L2H_PAE); break;
case 4: mask = (SHF_L1_64|SHF_FL1_64|SHF_L2_64
|SHF_L3_64|SHF_L4_64); break;
default: BUG();
diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c
index 1df92df8e7..b70c979fbd 100644
--- a/xen/arch/x86/mm/shadow/multi.c
+++ b/xen/arch/x86/mm/shadow/multi.c
@@ -21,20 +21,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-// DESIGN QUESTIONS:
-// Why use subshadows for PAE guests?
-// - reduces pressure in the hash table
-// - reduces shadow size (64-vs-4096 bytes of shadow for 32 bytes of guest L3)
-// - would need to find space in the page_info to store 7 more bits of
-// backpointer
-// - independent shadows of 32 byte chunks makes it non-obvious how to quickly
-// figure out when to demote the guest page from l3 status
-//
-// PAE Xen HVM guests are restricted to 8GB of pseudo-physical address space.
-// - Want to map the P2M table into the 16MB RO_MPT hole in Xen's address
-// space for both PV and HVM guests.
-//
-
#include <xen/config.h>
#include <xen/types.h>
#include <xen/mm.h>
@@ -118,9 +104,6 @@ static char *fetch_type_names[] = {
#endif
/* XXX forward declarations */
-#if (GUEST_PAGING_LEVELS == 3) && (SHADOW_PAGING_LEVELS == 3)
-static unsigned long hvm_pae_copy_root(struct vcpu *v, l3_pgentry_t *l3tab, int clear_res);
-#endif
static inline void sh_update_linear_entries(struct vcpu *v);
/**************************************************************************/
@@ -129,8 +112,6 @@ static inline void sh_update_linear_entries(struct vcpu *v);
* Normal case: maps the mfn of a guest page to the mfn of its shadow page.
* FL1's: maps the *gfn* of the start of a superpage to the mfn of a
* shadow L1 which maps its "splinters".
- * PAE CR3s: maps the 32-byte aligned, 32-bit CR3 value to the mfn of the
- * PAE L3 info page for that CR3 value.
*/
static inline mfn_t
@@ -215,7 +196,6 @@ delete_fl1_shadow_status(struct vcpu *v, gfn_t gfn, mfn_t smfn)
{
SHADOW_PRINTK("gfn=%"SH_PRI_gfn", type=%08x, smfn=%05lx\n",
gfn_x(gfn), PGC_SH_fl1_shadow, mfn_x(smfn));
-
shadow_hash_delete(v, gfn_x(gfn),
PGC_SH_fl1_shadow >> PGC_SH_type_shift, smfn);
}
@@ -429,18 +409,16 @@ static void sh_audit_gw(struct vcpu *v, walk_t *gw)
if ( !(SHADOW_AUDIT_ENABLE) )
return;
-#if GUEST_PAGING_LEVELS >= 3 /* PAE or 64... */
#if GUEST_PAGING_LEVELS >= 4 /* 64-bit only... */
if ( valid_mfn(gw->l4mfn)
&& valid_mfn((smfn = get_shadow_status(v, gw->l4mfn,
PGC_SH_l4_shadow))) )
(void) sh_audit_l4_table(v, smfn, _mfn(INVALID_MFN));
-#endif /* PAE or 64... */
if ( valid_mfn(gw->l3mfn)
&& valid_mfn((smfn = get_shadow_status(v, gw->l3mfn,
PGC_SH_l3_shadow))) )
(void) sh_audit_l3_table(v, smfn, _mfn(INVALID_MFN));
-#endif /* All levels... */
+#endif /* PAE or 64... */
if ( valid_mfn(gw->l2mfn) )
{
if ( valid_mfn((smfn = get_shadow_status(v, gw->l2mfn,
@@ -498,8 +476,7 @@ static u32 guest_set_ad_bits(struct vcpu *v,
flags = guest_l1e_get_flags(*ep);
/* PAE l3s do not have A and D bits */
- if ( unlikely(GUEST_PAGING_LEVELS == 3 && level == 3) )
- return flags;
+ ASSERT(GUEST_PAGING_LEVELS > 3 || level != 3);
/* Need the D bit as well for writes, in L1es and PSE L2es. */
if ( ft == ft_demand_write
@@ -646,38 +623,14 @@ shadow_l2_index(mfn_t *smfn, u32 guest_index)
#endif
}
-#if GUEST_PAGING_LEVELS >= 3
+#if GUEST_PAGING_LEVELS >= 4
static inline u32
shadow_l3_index(mfn_t *smfn, u32 guest_index)
{
-#if GUEST_PAGING_LEVELS == 3
- u32 group_id;
-
- // Because we use twice the space in L3 shadows as was consumed in guest
- // L3s, the number of guest entries per shadow page is
- // SHADOW_L2_PAGETABLE_ENTRIES/2. (Note this is *not*
- // SHADOW_L3_PAGETABLE_ENTRIES, which in this case is 4...)
- //
- *smfn = _mfn(mfn_x(*smfn) +
- (guest_index / (SHADOW_L2_PAGETABLE_ENTRIES / 2)));
-
- // We store PAE L3 shadows in groups of 4, alternating shadows and
- // pae_l3_bookkeeping structs. So the effective shadow index is
- // the the group_id * 8 + the offset within the group.
- //
- guest_index %= (SHADOW_L2_PAGETABLE_ENTRIES / 2);
- group_id = guest_index / 4;
- return (group_id * 8) + (guest_index % 4);
-#else
return guest_index;
-#endif
}
-#endif // GUEST_PAGING_LEVELS >= 3
-
-#if GUEST_PAGING_LEVELS >= 4
-
static inline u32
shadow_l4_index(mfn_t *smfn, u32 guest_index)
{
@@ -722,6 +675,9 @@ do { \
u32 pass_thru_flags;
u32 sflags;
+ /* We don't shadow PAE l3s */
+ ASSERT(GUEST_PAGING_LEVELS > 3 || level != 3);
+
// XXX -- might want to think about PAT support for HVM guests...
#ifndef NDEBUG
@@ -757,29 +713,16 @@ do { \
if ( guest_entry_ptr && (ft & FETCH_TYPE_DEMAND) )
gflags = guest_set_ad_bits(v, gmfn, guest_entry_ptr, level, ft);
- // PAE does not allow NX, RW, USER, ACCESSED, or DIRTY bits in its L3e's...
- //
- if ( (SHADOW_PAGING_LEVELS == 3) && (level == 3) )
- pass_thru_flags = _PAGE_PRESENT;
- else
- {
- pass_thru_flags = (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_USER |
- _PAGE_RW | _PAGE_PRESENT);
- if ( guest_supports_nx(v) )
- pass_thru_flags |= _PAGE_NX_BIT;
- }
-
- // PAE guests can not put NX, RW, USER, ACCESSED, or DIRTY bits into their
- // L3e's; they are all implied. So we emulate them here.
- //
- if ( (GUEST_PAGING_LEVELS == 3) && (level == 3) )
- gflags = pass_thru_flags;
// Propagate bits from the guest to the shadow.
// Some of these may be overwritten, below.
// Since we know the guest's PRESENT bit is set, we also set the shadow's
// SHADOW_PRESENT bit.
//
+ pass_thru_flags = (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_USER |
+ _PAGE_RW | _PAGE_PRESENT);
+ if ( guest_supports_nx(v) )
+ pass_thru_flags |= _PAGE_NX_BIT;
sflags = (gflags & pass_thru_flags) | _PAGE_SHADOW_PRESENT;
// Copy the guest's RW bit into the SHADOW_RW bit.
@@ -800,8 +743,7 @@ do { \
// If the A or D bit has not yet been set in the guest, then we must
// prevent the corresponding kind of access.
//
- if ( unlikely(!((GUEST_PAGING_LEVELS == 3) && (level == 3)) &&
- !(gflags & _PAGE_ACCESSED)) )
+ if ( unlikely(!(gflags & _PAGE_ACCESSED)) )
sflags &= ~_PAGE_PRESENT;
/* D bits exist in L1es and PSE L2es */
@@ -890,9 +832,7 @@ l4e_propagate_from_guest(struct vcpu *v,
fetch_type_names[ft], gl4e->l4, sl4p->l4);
ASSERT(sflags != -1);
}
-#endif // GUEST_PAGING_LEVELS >= 4
-#if GUEST_PAGING_LEVELS >= 3
static void
l3e_propagate_from_guest(struct vcpu *v,
guest_l3e_t *gl3e,
@@ -912,7 +852,7 @@ l3e_propagate_from_guest(struct vcpu *v,
fetch_type_names[ft], gl3e->l3, sl3p->l3);
ASSERT(sflags != -1);
}
-#endif // GUEST_PAGING_LEVELS >= 3
+#endif // GUEST_PAGING_LEVELS >= 4
static void
l2e_propagate_from_guest(struct vcpu *v,
@@ -1081,9 +1021,6 @@ shadow_write_entries(void *d, void *s, int entries, mfn_t mfn)
safe_write_entry(dst++, src++);
if ( map != NULL ) sh_unmap_domain_page(map);
-
- /* XXX TODO:
- * Update min/max field in page_info struct of this mfn */
}
static inline int
@@ -1195,9 +1132,7 @@ static int shadow_set_l4e(struct vcpu *v,
}
return flags;
}
-#endif /* GUEST_PAGING_LEVELS >= 4 */
-#if GUEST_PAGING_LEVELS >= 3
static int shadow_set_l3e(struct vcpu *v,
shadow_l3e_t *sl3e,
shadow_l3e_t new_sl3e,
@@ -1224,28 +1159,6 @@ static int shadow_set_l3e(struct vcpu *v,
shadow_write_entries(sl3e, &new_sl3e, 1, sl3mfn);
flags |= SHADOW_SET_CHANGED;
-#if GUEST_PAGING_LEVELS == 3
- /* We wrote a guest l3e in a PAE pagetable. This table is copied in
- * the linear pagetable entries of its l2s, and may also be copied
- * to a low memory location to make it fit in CR3. Report that we
- * need to resync those copies (we can't wait for the guest to flush
- * the TLB because it might be an increase in rights). */
- {
- struct vcpu *vcpu;
-
- struct pae_l3_bookkeeping *info = sl3p_to_info(sl3e);
- for_each_vcpu(v->domain, vcpu)
- {
- if (info->vcpus & (1 << vcpu->vcpu_id))
- {
- // Remember that this flip/update needs to occur.
- vcpu->arch.shadow.pae_flip_pending = 1;
- flags |= SHADOW_SET_L3PAE_RECOPY;
- }
- }
- }
-#endif
-
if ( shadow_l3e_get_flags(old_sl3e) & _PAGE_PRESENT )
{
/* We lost a reference to an old mfn. */
@@ -1260,7 +1173,7 @@ static int shadow_set_l3e(struct vcpu *v,
}
return flags;
}
-#endif /* GUEST_PAGING_LEVELS >= 3 */
+#endif /* GUEST_PAGING_LEVELS >= 4 */
static int shadow_set_l2e(struct vcpu *v,
shadow_l2e_t *sl2e,
@@ -1535,51 +1448,7 @@ do { \
#endif /* different kinds of l2 */
-#if GUEST_PAGING_LEVELS == 3
-
-/* PAE l3 subshadow: touch all entries (FOREACH_L2E will find Xen l2es). */
-#define SHADOW_FOREACH_L3E_SUB(_sl3e, _gl3p, _done, _code) \
-do { \
- int _i; \
- for ( _i = 0; _i < 4; _i++ ) \
- { \
- if ( shadow_l3e_get_flags(*(_sl3e)) & _PAGE_PRESENT ) \
- {_code} \
- if ( _done ) break; \
- _sl3e++; \
- increment_ptr_to_guest_entry(_gl3p); \
- } \
-} while (0)
-
-/* PAE l3 full shadow: call subshadow walk on all valid l3 subshadows */
-#define SHADOW_FOREACH_L3E(_sl3mfn, _sl3e, _gl3p, _done, _code) \
-do { \
- int _i, _j, _k, __done = 0; \
- ASSERT((mfn_to_page(_sl3mfn)->count_info & PGC_SH_type_mask) \
- == PGC_SH_l3_pae_shadow); \
- /* The subshadows are split, 64 on each page of the shadow */ \
- for ( _j = 0; _j < 2 && !__done; _j++ ) \
- { \
- void *_sp = sh_map_domain_page(_sl3mfn); \
- for ( _i = 0; _i < 64; _i++ ) \
- { \
- /* Every second 32-byte region is a bookkeeping entry */ \
- _sl3e = (shadow_l3e_t *)(_sp + (64 * _i)); \
- if ( (sl3p_to_info(_sl3e))->refcount > 0 ) \
- SHADOW_FOREACH_L3E_SUB(_sl3e, _gl3p, \
- ({ __done = (_done); __done; }), \
- _code); \
- else \
- for ( _k = 0 ; _k < 4 ; _k++ ) \
- increment_ptr_to_guest_entry(_gl3p); \
- if ( __done ) break; \
- } \
- sh_unmap_domain_page(_sp); \
- _sl3mfn = _mfn(mfn_x(_sl3mfn) + 1); \
- } \
-} while (0)
-
-#elif GUEST_PAGING_LEVELS == 4
+#if GUEST_PAGING_LEVELS == 4
/* 64-bit l3: touch all entries */
#define SHADOW_FOREACH_L3E(_sl3mfn, _sl3e, _gl3p, _done, _code) \
@@ -1711,8 +1580,8 @@ void sh_install_xen_entries_in_l2h(struct vcpu *v,
/* We don't set up a linear mapping here because we can't until this
* l2h is installed in an l3e. sh_update_linear_entries() handles
- * the linear mappings when the l3 is loaded. We zero them here, just as
- * a safety measure.
+ * the linear mappings when CR3 (and so the fourth l3e) is loaded.
+ * We zero them here, just as a safety measure.
*/
for ( i = 0; i < SHADOW_L3_PAGETABLE_ENTRIES; i++ )
sl2e[shadow_l2_table_offset(LINEAR_PT_VIRT_START) + i] =
@@ -1740,37 +1609,6 @@ void sh_install_xen_entries_in_l2h(struct vcpu *v,
sh_unmap_domain_page(sl2e);
}
-
-void sh_install_xen_entries_in_l3(struct vcpu *v, mfn_t gl3mfn, mfn_t sl3mfn)
-{
- shadow_l3e_t *sl3e;
- guest_l3e_t *gl3e = v->arch.guest_vtable;
- shadow_l3e_t new_sl3e;
- gfn_t l2gfn;
- mfn_t l2gmfn, l2smfn;
- int r;
-
- ASSERT(!shadow_mode_external(v->domain));
- ASSERT(guest_l3e_get_flags(gl3e[3]) & _PAGE_PRESENT);
- l2gfn = guest_l3e_get_gfn(gl3e[3]);
- l2gmfn = sh_gfn_to_mfn(v->domain, gfn_x(l2gfn));
- l2smfn = get_shadow_status(v, l2gmfn, PGC_SH_l2h_shadow);
- if ( !valid_mfn(l2smfn) )
- {
- /* must remove write access to this page before shadowing it */
- // XXX -- should check to see whether this is better with level==0 or
- // level==2...
- if ( shadow_remove_write_access(v, l2gmfn, 2, 0xc0000000ul) != 0 )
- flush_tlb_mask(v->domain->domain_dirty_cpumask);
-
- l2smfn = sh_make_shadow(v, l2gmfn, PGC_SH_l2h_shadow);
- }
- l3e_propagate_from_guest(v, &gl3e[3], gl3mfn, l2smfn, &new_sl3e,
- ft_prefetch);
- sl3e = sh_map_domain_page(sl3mfn);
- r = shadow_set_l3e(v, &sl3e[3], new_sl3e, sl3mfn);
- sh_unmap_domain_page(sl3e);
-}
#endif
@@ -1827,8 +1665,6 @@ void sh_install_xen_entries_in_l2(struct vcpu *v, mfn_t gl2mfn, mfn_t sl2mfn)
-
-
/**************************************************************************/
/* Create a shadow of a given guest page.
*/
@@ -1839,7 +1675,10 @@ sh_make_shadow(struct vcpu *v, mfn_t gmfn, u32 shadow_type)
SHADOW_DEBUG(MAKE_SHADOW, "(%05lx, %u)=>%05lx\n",
mfn_x(gmfn), shadow_type, mfn_x(smfn));
- if ( shadow_type != PGC_SH_guest_root_type )
+ if ( shadow_type != PGC_SH_l2_32_shadow
+ && shadow_type != PGC_SH_l2_pae_shadow
+ && shadow_type != PGC_SH_l2h_pae_shadow
+ && shadow_type != PGC_SH_l4_64_shadow )
/* Lower-level shadow, not yet linked form a higher level */
mfn_to_page(smfn)->up = 0;
@@ -1853,8 +1692,6 @@ sh_make_shadow(struct vcpu *v, mfn_t gmfn, u32 shadow_type)
sh_install_xen_entries_in_l4(v, gmfn, smfn); break;
#endif
#if CONFIG_PAGING_LEVELS == 3 && GUEST_PAGING_LEVELS == 3
- case PGC_SH_l3_shadow:
- sh_install_xen_entries_in_l3(v, gmfn, smfn); break;
case PGC_SH_l2h_shadow:
sh_install_xen_entries_in_l2h(v, smfn); break;
#endif
@@ -1988,20 +1825,16 @@ static shadow_l4e_t * shadow_get_and_create_l4e(struct vcpu *v,
mfn_t *sl4mfn)
{
/* There is always a shadow of the top level table. Get it. */
- *sl4mfn = pagetable_get_mfn(v->arch.shadow_table);
+ *sl4mfn = pagetable_get_mfn(v->arch.shadow_table[0]);
/* Reading the top level table is always valid. */
return sh_linear_l4_table(v) + shadow_l4_linear_offset(gw->va);
}
-#endif /* GUEST_PAGING_LEVELS >= 4 */
-
-#if GUEST_PAGING_LEVELS >= 3
static shadow_l3e_t * shadow_get_and_create_l3e(struct vcpu *v,
walk_t *gw,
mfn_t *sl3mfn,
fetch_type_t ft)
{
-#if GUEST_PAGING_LEVELS >= 4 /* 64bit... */
mfn_t sl4mfn;
shadow_l4e_t *sl4e;
if ( !valid_mfn(gw->l3mfn) ) return NULL; /* No guest page. */
@@ -2032,19 +1865,8 @@ static shadow_l3e_t * shadow_get_and_create_l3e(struct vcpu *v,
}
/* Now follow it down a level. Guaranteed to succeed. */
return sh_linear_l3_table(v) + shadow_l3_linear_offset(gw->va);
-#else /* PAE... */
- /* There is always a shadow of the top level table. Get it. */
- *sl3mfn = pagetable_get_mfn(v->arch.shadow_table);
- /* This next line is important: the shadow l3 table is in an 8k
- * shadow and we need to return the right mfn of the pair. This call
- * will set it for us as a side-effect. */
- (void) shadow_l3_index(sl3mfn, guest_index(gw->l3e));
- ASSERT(v->arch.shadow_vtable);
- return ((shadow_l3e_t *)v->arch.shadow_vtable)
- + shadow_l3_table_offset(gw->va);
-#endif /* GUEST_PAGING_LEVELS >= 4 */
}
-#endif /* GUEST_PAGING_LEVELS >= 3 */
+#endif /* GUEST_PAGING_LEVELS >= 4 */
static shadow_l2e_t * shadow_get_and_create_l2e(struct vcpu *v,
@@ -2052,7 +1874,7 @@ static shadow_l2e_t * shadow_get_and_create_l2e(struct vcpu *v,
mfn_t *sl2mfn,
fetch_type_t ft)
{
-#if GUEST_PAGING_LEVELS >= 3 /* PAE or 64bit... */
+#if GUEST_PAGING_LEVELS >= 4 /* 64bit... */
mfn_t sl3mfn = _mfn(INVALID_MFN);
shadow_l3e_t *sl3e;
if ( !valid_mfn(gw->l2mfn) ) return NULL; /* No guest page. */
@@ -2080,17 +1902,22 @@ static shadow_l2e_t * shadow_get_and_create_l2e(struct vcpu *v,
*sl2mfn, &new_sl3e, ft);
r = shadow_set_l3e(v, sl3e, new_sl3e, sl3mfn);
ASSERT((r & SHADOW_SET_FLUSH) == 0);
-#if GUEST_PAGING_LEVELS == 3
- /* Need to sync up the linear maps, as we are about to use them */
- ASSERT( r & SHADOW_SET_L3PAE_RECOPY );
- sh_pae_recopy(v->domain);
-#endif
}
/* Now follow it down a level. Guaranteed to succeed. */
return sh_linear_l2_table(v) + shadow_l2_linear_offset(gw->va);
+#elif GUEST_PAGING_LEVELS == 3 /* PAE... */
+ /* We never demand-shadow PAE l3es: they are only created in
+ * sh_update_cr3(). Check if the relevant sl3e is present. */
+ shadow_l3e_t *sl3e = ((shadow_l3e_t *)&v->arch.shadow.l3table)
+ + shadow_l3_linear_offset(gw->va);
+ if ( !(shadow_l3e_get_flags(*sl3e) & _PAGE_PRESENT) )
+ return NULL;
+ *sl2mfn = shadow_l3e_get_mfn(*sl3e);
+ ASSERT(valid_mfn(*sl2mfn));
+ return sh_linear_l2_table(v) + shadow_l2_linear_offset(gw->va);
#else /* 32bit... */
/* There is always a shadow of the top level table. Get it. */
- *sl2mfn = pagetable_get_mfn(v->arch.shadow_table);
+ *sl2mfn = pagetable_get_mfn(v->arch.shadow_table[0]);
/* This next line is important: the guest l2 has a 16k
* shadow, we need to return the right mfn of the four. This
* call will set it for us as a side-effect. */
@@ -2213,9 +2040,7 @@ void sh_destroy_l4_shadow(struct vcpu *v, mfn_t smfn)
/* Put the memory back in the pool */
shadow_free(v->domain, smfn);
}
-#endif
-#if GUEST_PAGING_LEVELS >= 3
void sh_destroy_l3_shadow(struct vcpu *v, mfn_t smfn)
{
shadow_l3e_t *sl3e;
@@ -2230,10 +2055,6 @@ void sh_destroy_l3_shadow(struct vcpu *v, mfn_t smfn)
gmfn = _mfn(mfn_to_page(smfn)->u.inuse.type_info);
delete_shadow_status(v, gmfn, t, smfn);
shadow_demote(v, gmfn, t);
-#if GUEST_PAGING_LEVELS == 3
- /* Take this shadow off the list of root shadows */
- list_del_init(&mfn_to_page(smfn)->list);
-#endif
/* Decrement refcounts of all the old entries */
sl3mfn = smfn;
@@ -2247,53 +2068,8 @@ void sh_destroy_l3_shadow(struct vcpu *v, mfn_t smfn)
/* Put the memory back in the pool */
shadow_free(v->domain, smfn);
}
-#endif
-
+#endif /* GUEST_PAGING_LEVELS >= 4 */
-#if GUEST_PAGING_LEVELS == 3
-static void sh_destroy_l3_subshadow(struct vcpu *v,
- shadow_l3e_t *sl3e)
-/* Tear down just a single 4-entry l3 on a 2-page l3 shadow. */
-{
- int i;
- mfn_t sl3mfn = _mfn(maddr_from_mapped_domain_page(sl3e) >> PAGE_SHIFT);
- ASSERT((unsigned long)sl3e % (4 * sizeof (shadow_l3e_t)) == 0);
- for ( i = 0; i < GUEST_L3_PAGETABLE_ENTRIES; i++ )
- if ( shadow_l3e_get_flags(sl3e[i]) & _PAGE_PRESENT )
- shadow_set_l3e(v, &sl3e[i], shadow_l3e_empty(), sl3mfn);
-}
-#endif
-
-#if (GUEST_PAGING_LEVELS == 3) && (SHADOW_PAGING_LEVELS == 3)
-void sh_unpin_all_l3_subshadows(struct vcpu *v, mfn_t smfn)
-/* Walk a full PAE l3 shadow, unpinning all of the subshadows on it */
-{
- int i, j;
- struct pae_l3_bookkeeping *bk;
-
- ASSERT((mfn_to_page(smfn)->count_info & PGC_SH_type_mask)
- == PGC_SH_l3_pae_shadow);
- /* The subshadows are split, 64 on each page of the shadow */
- for ( i = 0; i < 2; i++ )
- {
- void *p = sh_map_domain_page(_mfn(mfn_x(smfn) + i));
- for ( j = 0; j < 64; j++ )
- {
- /* Every second 32-byte region is a bookkeeping entry */
- bk = (struct pae_l3_bookkeeping *)(p + (64 * j) + 32);
- if ( bk->pinned )
- sh_unpin_l3_subshadow(v, (shadow_l3e_t *)(p + (64*j)), smfn);
- /* Check whether we've just freed the whole shadow */
- if ( (mfn_to_page(smfn)->count_info & PGC_SH_count_mask) == 0 )
- {
- sh_unmap_domain_page(p);
- return;
- }
- }
- sh_unmap_domain_page(p);
- }
-}
-#endif
void sh_destroy_l2_shadow(struct vcpu *v, mfn_t smfn)
{
@@ -2311,7 +2087,7 @@ void sh_destroy_l2_shadow(struct vcpu *v, mfn_t smfn)
gmfn = _mfn(mfn_to_page(smfn)->u.inuse.type_info);
delete_shadow_status(v, gmfn, t, smfn);
shadow_demote(v, gmfn, t);
-#if GUEST_PAGING_LEVELS == 2
+#if (GUEST_PAGING_LEVELS == 2) || (GUEST_PAGING_LEVELS == 3)
/* Take this shadow off the list of root shadows */
list_del_init(&mfn_to_page(smfn)->list);
#endif
@@ -2421,31 +2197,14 @@ void sh_unhook_32b_mappings(struct vcpu *v, mfn_t sl2mfn)
#elif GUEST_PAGING_LEVELS == 3
-void sh_unhook_pae_mappings(struct vcpu *v, mfn_t sl3mfn)
-/* Walk a full PAE l3 shadow, unhooking entries from all the subshadows */
+void sh_unhook_pae_mappings(struct vcpu *v, mfn_t sl2mfn)
+/* Walk a PAE l2 shadow, unhooking entries from all the subshadows */
{
- shadow_l3e_t *sl3e;
- SHADOW_FOREACH_L3E(sl3mfn, sl3e, 0, 0, {
- if ( (shadow_l3e_get_flags(*sl3e) & _PAGE_PRESENT) ) {
- mfn_t sl2mfn = shadow_l3e_get_mfn(*sl3e);
- if ( (mfn_to_page(sl2mfn)->count_info & PGC_SH_type_mask)
- == PGC_SH_l2h_pae_shadow )
- {
- /* High l2: need to pick particular l2es to unhook */
- shadow_l2e_t *sl2e;
- SHADOW_FOREACH_L2E(sl2mfn, sl2e, 0, 0, 1, {
- (void) shadow_set_l2e(v, sl2e, shadow_l2e_empty(), sl2mfn);
- });
- }
- else
- {
- /* Normal l2: can safely unhook the whole l3e */
- (void) shadow_set_l3e(v, sl3e, shadow_l3e_empty(), sl3mfn);
- }
- }
+ shadow_l2e_t *sl2e;
+ int xen_mappings = !shadow_mode_external(v->domain);
+ SHADOW_FOREACH_L2E(sl2mfn, sl2e, 0, 0, xen_mappings, {
+ (void) shadow_set_l2e(v, sl2e, shadow_l2e_empty(), sl2mfn);
});
- /* We've changed PAE L3 entries: must sync up various copies of them */
- sh_pae_recopy(v->domain);
}
#elif GUEST_PAGING_LEVELS == 4
@@ -2523,9 +2282,8 @@ static int validate_gl4e(struct vcpu *v, void *new_ge, mfn_t sl4mfn, void *se)
result |= shadow_set_l4e(v, sl4p, new_sl4e, sl4mfn);
return result;
}
-#endif // GUEST_PAGING_LEVELS >= 4
-#if GUEST_PAGING_LEVELS >= 3
+
static int validate_gl3e(struct vcpu *v, void *new_ge, mfn_t sl3mfn, void *se)
{
shadow_l3e_t new_sl3e;
@@ -2536,16 +2294,6 @@ static int validate_gl3e(struct vcpu *v, void *new_ge, mfn_t sl3mfn, void *se)
perfc_incrc(shadow_validate_gl3e_calls);
-#if (SHADOW_PAGING_LEVELS == 3) && (GUEST_PAGING_LEVELS == 3)
- {
- /* If we've updated a subshadow which is unreferenced then
- we don't care what value is being written - bail. */
- struct pae_l3_bookkeeping *info = sl3p_to_info(se);
- if(!info->refcount)
- return result;
- }
-#endif
-
if ( guest_l3e_get_flags(*new_gl3e) & _PAGE_PRESENT )
{
gfn_t gl2gfn = guest_l3e_get_gfn(*new_gl3e);
@@ -2559,16 +2307,9 @@ static int validate_gl3e(struct vcpu *v, void *new_ge, mfn_t sl3mfn, void *se)
sl2mfn, &new_sl3e, ft_prefetch);
result |= shadow_set_l3e(v, sl3p, new_sl3e, sl3mfn);
-#if GUEST_PAGING_LEVELS == 3
- /* We have changed a PAE l3 entry: need to sync up the possible copies
- * of it */
- if ( result & SHADOW_SET_L3PAE_RECOPY )
- sh_pae_recopy(v->domain);
-#endif
-
return result;
}
-#endif // GUEST_PAGING_LEVELS >= 3
+#endif // GUEST_PAGING_LEVELS >= 4
static int validate_gl2e(struct vcpu *v, void *new_ge, mfn_t sl2mfn, void *se)
{
@@ -2755,12 +2496,12 @@ int
sh_map_and_validate_gl3e(struct vcpu *v, mfn_t gl3mfn,
void *new_gl3p, u32 size)
{
-#if GUEST_PAGING_LEVELS >= 3
+#if GUEST_PAGING_LEVELS >= 4
return sh_map_and_validate(v, gl3mfn, new_gl3p, size,
PGC_SH_l3_shadow,
shadow_l3_index,
validate_gl3e);
-#else // ! GUEST_PAGING_LEVELS >= 3
+#else // ! GUEST_PAGING_LEVELS >= 4
SHADOW_PRINTK("called in wrong paging mode!\n");
BUG();
return 0;
@@ -2821,36 +2562,11 @@ static inline void check_for_early_unshadow(struct vcpu *v, mfn_t gmfn)
sh_mfn_is_a_page_table(gmfn) )
{
u32 flags = mfn_to_page(gmfn)->shadow_flags;
- mfn_t smfn;
- if ( !(flags & (SHF_L2_32|SHF_L3_PAE|SHF_L4_64)) )
+ if ( !(flags & (SHF_L2_32|SHF_L2_PAE|SHF_L2H_PAE|SHF_L4_64)) )
{
perfc_incrc(shadow_early_unshadow);
- sh_remove_shadows(v, gmfn, 0 /* Can fail to unshadow */ );
- return;
- }
- /* SHF_unhooked_mappings is set to make sure we only unhook
- * once in a single batch of updates. It is reset when this
- * top-level page is loaded into CR3 again */
- if ( !(flags & SHF_unhooked_mappings) )
- {
- perfc_incrc(shadow_early_unshadow_top);
- mfn_to_page(gmfn)->shadow_flags |= SHF_unhooked_mappings;
- if ( flags & SHF_L2_32 )
- {
- smfn = get_shadow_status(v, gmfn, PGC_SH_l2_32_shadow);
- shadow_unhook_mappings(v, smfn);
- }
- if ( flags & SHF_L3_PAE )
- {
- smfn = get_shadow_status(v, gmfn, PGC_SH_l3_pae_shadow);
- shadow_unhook_mappings(v, smfn);
- }
- if ( flags & SHF_L4_64 )
- {
- smfn = get_shadow_status(v, gmfn, PGC_SH_l4_64_shadow);
- shadow_unhook_mappings(v, smfn);
- }
- }
+ sh_remove_shadows(v, gmfn, 1, 0 /* Fast, can fail to unshadow */ );
+ }
}
v->arch.shadow.last_emulated_mfn = mfn_x(gmfn);
#endif
@@ -3119,23 +2835,13 @@ static int sh_page_fault(struct vcpu *v,
mmio:
perfc_incrc(shadow_fault_mmio);
- if ( !hvm_apic_support(d) && (gpa >= 0xFEC00000) )
- {
- /* Need to deal with these disabled-APIC accesses, as
- * handle_mmio() apparently does not currently do that. */
- /* TJD: What about it, then? For now, I'm turning this BUG()
- * into a domain_crash() since we don't want to kill Xen. */
- SHADOW_ERROR("disabled-APIC access: not supported\n.");
- domain_crash(d);
- }
sh_audit_gw(v, &gw);
unmap_walk(v, &gw);
SHADOW_PRINTK("mmio\n");
shadow_audit_tables(v);
reset_early_unshadow(v);
shadow_unlock(d);
- sh_log_mmio(v, gpa);
- handle_mmio(va, gpa);
+ handle_mmio(gpa);
return EXCRET_fault_fixed;
not_a_shadow_fault:
@@ -3183,8 +2889,7 @@ sh_invlpg(struct vcpu *v, unsigned long va)
return 0;
}
#elif SHADOW_PAGING_LEVELS == 3
- if ( !(shadow_l3e_get_flags(
- ((shadow_l3e_t *)v->arch.shadow_vtable)[shadow_l3_linear_offset(va)])
+ if ( !(l3e_get_flags(v->arch.shadow.l3table[shadow_l3_linear_offset(va)])
& _PAGE_PRESENT) )
// no need to flush anything if there's no SL2...
return 0;
@@ -3249,34 +2954,6 @@ sh_gva_to_gpa(struct vcpu *v, unsigned long va)
}
-// XXX -- should this be in this file?
-// Or should it be moved to shadow-common.c?
-//
-/* returns a lowmem machine address of the copied HVM L3 root table
- * If clear_res != 0, then clear the PAE-l3 reserved bits in the copy,
- * otherwise blank out any entries with reserved bits in them. */
-#if (GUEST_PAGING_LEVELS == 3) && (SHADOW_PAGING_LEVELS == 3)
-static unsigned long
-hvm_pae_copy_root(struct vcpu *v, l3_pgentry_t *l3tab, int clear_res)
-{
- int i, f;
- int res = (_PAGE_RW|_PAGE_NX_BIT|_PAGE_USER|_PAGE_ACCESSED|_PAGE_DIRTY);
- l3_pgentry_t new_l3e, *copy = v->arch.hvm_vcpu.hvm_lowmem_l3tab;
- memcpy(copy, l3tab, 4 * sizeof(l3_pgentry_t));
- for ( i = 0; i < 4; i++ )
- {
- f = l3e_get_flags(l3tab[i]);
- if ( (f & _PAGE_PRESENT) && (!(f & res) || clear_res) )
- new_l3e = l3e_from_pfn(l3e_get_pfn(l3tab[i]), f & ~res);
- else
- new_l3e = l3e_empty();
- safe_write_entry(&copy[i], &new_l3e);
- }
- return __pa(copy);
-}
-#endif
-
-
static inline void
sh_update_linear_entries(struct vcpu *v)
/* Sync up all the linear mappings for this vcpu's pagetables */
@@ -3330,7 +3007,7 @@ sh_update_linear_entries(struct vcpu *v)
if ( v == current )
{
__linear_l4_table[l4_linear_offset(SH_LINEAR_PT_VIRT_START)] =
- l4e_from_pfn(pagetable_get_pfn(v->arch.shadow_table),
+ l4e_from_pfn(pagetable_get_pfn(v->arch.shadow_table[0]),
__PAGE_HYPERVISOR);
}
else
@@ -3338,7 +3015,7 @@ sh_update_linear_entries(struct vcpu *v)
l4_pgentry_t *ml4e;
ml4e = sh_map_domain_page(pagetable_get_mfn(v->arch.monitor_table));
ml4e[l4_table_offset(SH_LINEAR_PT_VIRT_START)] =
- l4e_from_pfn(pagetable_get_pfn(v->arch.shadow_table),
+ l4e_from_pfn(pagetable_get_pfn(v->arch.shadow_table[0]),
__PAGE_HYPERVISOR);
sh_unmap_domain_page(ml4e);
}
@@ -3379,13 +3056,8 @@ sh_update_linear_entries(struct vcpu *v)
sh_unmap_domain_page(ml4e);
}
-#if GUEST_PAGING_LEVELS == 2
/* Shadow l3 tables are made up by update_cr3 */
- sl3e = v->arch.hvm_vcpu.hvm_lowmem_l3tab;
-#else
- /* Always safe to use shadow_vtable, because it's globally mapped */
- sl3e = v->arch.shadow_vtable;
-#endif
+ sl3e = v->arch.shadow.l3table;
for ( i = 0; i < SHADOW_L3_PAGETABLE_ENTRIES; i++ )
{
@@ -3424,14 +3096,14 @@ sh_update_linear_entries(struct vcpu *v)
#if GUEST_PAGING_LEVELS == 2
/* Shadow l3 tables were built by update_cr3 */
if ( shadow_mode_external(d) )
- shadow_l3e = v->arch.hvm_vcpu.hvm_lowmem_l3tab;
+ shadow_l3e = (shadow_l3e_t *)&v->arch.shadow.l3table;
else
BUG(); /* PV 2-on-3 is not supported yet */
#else /* GUEST_PAGING_LEVELS == 3 */
- /* Always safe to use *_vtable, because they're globally mapped */
- shadow_l3e = v->arch.shadow_vtable;
+ shadow_l3e = (shadow_l3e_t *)&v->arch.shadow.l3table;
+ /* Always safe to use guest_vtable, because it's globally mapped */
guest_l3e = v->arch.guest_vtable;
#endif /* GUEST_PAGING_LEVELS */
@@ -3510,7 +3182,7 @@ sh_update_linear_entries(struct vcpu *v)
if ( v == current )
{
__linear_l2_table[l2_linear_offset(SH_LINEAR_PT_VIRT_START)] =
- l2e_from_pfn(pagetable_get_pfn(v->arch.shadow_table),
+ l2e_from_pfn(pagetable_get_pfn(v->arch.shadow_table[0]),
__PAGE_HYPERVISOR);
}
else
@@ -3518,7 +3190,7 @@ sh_update_linear_entries(struct vcpu *v)
l2_pgentry_t *ml2e;
ml2e = sh_map_domain_page(pagetable_get_mfn(v->arch.monitor_table));
ml2e[l2_table_offset(SH_LINEAR_PT_VIRT_START)] =
- l2e_from_pfn(pagetable_get_pfn(v->arch.shadow_table),
+ l2e_from_pfn(pagetable_get_pfn(v->arch.shadow_table[0]),
__PAGE_HYPERVISOR);
sh_unmap_domain_page(ml2e);
}
@@ -3530,69 +3202,7 @@ sh_update_linear_entries(struct vcpu *v)
}
-// XXX -- should this be in this file?
-// Or should it be moved to shadow-common.c?
-//
-#if (GUEST_PAGING_LEVELS == 3) && (SHADOW_PAGING_LEVELS == 3)
-void sh_pae_recopy(struct domain *d)
-/* Called whenever we write to the l3 entries of a PAE pagetable which
- * is currently in use. Each vcpu that is using the table needs to
- * resync its copies of the l3s in linear maps and any low-memory
- * copies it might have made for fitting into 32bit CR3.
- * Since linear maps are also resynced when we change CR3, we don't
- * need to worry about changes to PAE l3es that are not currently in use.*/
-{
- struct vcpu *v;
- cpumask_t flush_mask = CPU_MASK_NONE;
- ASSERT(shadow_lock_is_acquired(d));
-
- for_each_vcpu(d, v)
- {
- if ( !v->arch.shadow.pae_flip_pending )
- continue;
-
- cpu_set(v->processor, flush_mask);
-
- SHADOW_PRINTK("d=%u v=%u\n", v->domain->domain_id, v->vcpu_id);
-
- /* This vcpu has a copy in its linear maps */
- sh_update_linear_entries(v);
- if ( hvm_guest(v) )
- {
- /* This vcpu has a copy in its HVM PAE l3 */
- v->arch.hvm_vcpu.hw_cr3 =
- hvm_pae_copy_root(v, v->arch.shadow_vtable,
- !shadow_vcpu_mode_translate(v));
- }
-#if CONFIG_PAGING_LEVELS == 3
- else
- {
- /* This vcpu might have copied the l3 to below 4GB */
- if ( v->arch.cr3 >> PAGE_SHIFT
- != pagetable_get_pfn(v->arch.shadow_table) )
- {
- /* Recopy to where that copy is. */
- int i;
- l3_pgentry_t *dst, *src;
- dst = __va(v->arch.cr3 & ~0x1f); /* Mask cache control bits */
- src = v->arch.shadow_vtable;
- for ( i = 0 ; i < 4 ; i++ )
- safe_write_entry(dst + i, src + i);
- }
- }
-#endif
- v->arch.shadow.pae_flip_pending = 0;
- }
-
- flush_tlb_mask(flush_mask);
-}
-#endif /* (GUEST_PAGING_LEVELS == 3) && (SHADOW_PAGING_LEVELS == 3) */
-
-
-/* removes:
- * vcpu->arch.guest_vtable
- * vcpu->arch.shadow_table
- * vcpu->arch.shadow_vtable
+/* Removes vcpu->arch.guest_vtable and vcpu->arch.shadow_table[].
* Does all appropriate management/bookkeeping/refcounting/etc...
*/
static void
@@ -3600,6 +3210,7 @@ sh_detach_old_tables(struct vcpu *v)
{
struct domain *d = v->domain;
mfn_t smfn;
+ int i = 0;
////
//// vcpu->arch.guest_vtable
@@ -3620,56 +3231,80 @@ sh_detach_old_tables(struct vcpu *v)
}
////
- //// vcpu->arch.shadow_table
+ //// vcpu->arch.shadow_table[]
////
- smfn = pagetable_get_mfn(v->arch.shadow_table);
- if ( mfn_x(smfn) )
- {
- ASSERT(v->arch.shadow_vtable);
-#if GUEST_PAGING_LEVELS == 3
- // PAE guests do not (necessarily) use an entire page for their
- // 4-entry L3s, so we have to deal with them specially.
- //
- sh_put_ref_l3_subshadow(v, v->arch.shadow_vtable, smfn);
-#else
- sh_put_ref(v, smfn, 0);
-#endif
-#if (SHADOW_PAGING_LEVELS == 3) && (GUEST_PAGING_LEVELS == 3)
- {
- struct pae_l3_bookkeeping *info =
- sl3p_to_info(v->arch.shadow_vtable);
- ASSERT(test_bit(v->vcpu_id, &info->vcpus));
- clear_bit(v->vcpu_id, &info->vcpus);
- }
+#if GUEST_PAGING_LEVELS == 3
+ /* PAE guests have four shadow_table entries */
+ for ( i = 0 ; i < 4 ; i++ )
#endif
- v->arch.shadow_table = pagetable_null();
+ {
+ smfn = pagetable_get_mfn(v->arch.shadow_table[i]);
+ if ( mfn_x(smfn) )
+ sh_put_ref(v, smfn, 0);
+ v->arch.shadow_table[i] = pagetable_null();
}
+}
- ////
- //// vcpu->arch.shadow_vtable
- ////
- if ( (shadow_mode_external(v->domain) || (GUEST_PAGING_LEVELS == 3)) &&
- v->arch.shadow_vtable )
+/* Set up the top-level shadow and install it in slot 'slot' of shadow_table */
+static void
+sh_set_toplevel_shadow(struct vcpu *v,
+ int slot,
+ mfn_t gmfn,
+ unsigned int root_type)
+{
+ mfn_t smfn = get_shadow_status(v, gmfn, root_type);
+ struct domain *d = v->domain;
+ ASSERT(pagetable_is_null(v->arch.shadow_table[slot]));
+ if ( valid_mfn(smfn) )
{
- // Q: why does this need to use (un)map_domain_page_*global* ?
- /* A: so sh_update_linear_entries can operate on other vcpus */
- sh_unmap_domain_page_global(v->arch.shadow_vtable);
- v->arch.shadow_vtable = NULL;
+ /* Pull this root shadow to the front of the list of roots. */
+ list_del(&mfn_to_page(smfn)->list);
+ list_add(&mfn_to_page(smfn)->list, &d->arch.shadow.toplevel_shadows);
}
+ else
+ {
+ /* This guest MFN is a pagetable. Must revoke write access. */
+ if ( shadow_remove_write_access(v, gmfn, GUEST_PAGING_LEVELS, 0) != 0 )
+ flush_tlb_mask(v->domain->domain_dirty_cpumask);
+ /* Make sure there's enough free shadow memory. */
+ shadow_prealloc(d, SHADOW_MAX_ORDER);
+ /* Shadow the page. */
+ smfn = sh_make_shadow(v, gmfn, root_type);
+ list_add(&mfn_to_page(smfn)->list, &d->arch.shadow.toplevel_shadows);
+ }
+ ASSERT(valid_mfn(smfn));
+
+#if SHADOW_OPTIMIZATIONS & SHOPT_EARLY_UNSHADOW
+ /* Once again OK to unhook entries from this table if we see fork/exit */
+ ASSERT(sh_mfn_is_a_page_table(gmfn));
+ mfn_to_page(gmfn)->shadow_flags &= ~SHF_unhooked_mappings;
+#endif
+
+ /* Take a ref to this page: it will be released in sh_detach_old_tables. */
+ sh_get_ref(smfn, 0);
+ sh_pin(smfn);
+
+ /* Done. Install it */
+ SHADOW_PRINTK("%u/%u [%u] gmfn %#"SH_PRI_mfn" smfn %#"SH_PRI_mfn"\n",
+ GUEST_PAGING_LEVELS, SHADOW_PAGING_LEVELS, slot,
+ mfn_x(gmfn), mfn_x(smfn));
+ v->arch.shadow_table[slot] = pagetable_from_mfn(smfn);
}
+
static void
sh_update_cr3(struct vcpu *v)
-/* Updates vcpu->arch.shadow_table after the guest has changed CR3.
+/* Updates vcpu->arch.cr3 after the guest has changed CR3.
* Paravirtual guests should set v->arch.guest_table (and guest_table_user,
* if appropriate).
- * HVM guests should also set hvm_get_guest_cntl_reg(v, 3)...
+ * HVM guests should also make sure hvm_get_guest_cntl_reg(v, 3) works,
+ * and read vcpu->arch.hvm_vcpu.hw_cr3 afterwards.
*/
{
struct domain *d = v->domain;
- mfn_t gmfn, smfn;
+ mfn_t gmfn;
#if GUEST_PAGING_LEVELS == 3
u32 guest_idx=0;
#endif
@@ -3770,160 +3405,103 @@ sh_update_cr3(struct vcpu *v)
#endif
////
- //// vcpu->arch.shadow_table
+ //// vcpu->arch.shadow_table[]
////
- smfn = get_shadow_status(v, gmfn, PGC_SH_guest_root_type);
- if ( valid_mfn(smfn) )
- {
- /* Pull this root shadow to the front of the list of roots. */
- list_del(&mfn_to_page(smfn)->list);
- list_add(&mfn_to_page(smfn)->list, &d->arch.shadow.toplevel_shadows);
- }
- else
- {
- /* This guest MFN is a pagetable. Must revoke write access. */
- if ( shadow_remove_write_access(v, gmfn, GUEST_PAGING_LEVELS, 0)
- != 0 )
- flush_tlb_mask(d->domain_dirty_cpumask);
- /* Make sure there's enough free shadow memory. */
- shadow_prealloc(d, SHADOW_MAX_ORDER);
- /* Shadow the page. */
- smfn = sh_make_shadow(v, gmfn, PGC_SH_guest_root_type);
- list_add(&mfn_to_page(smfn)->list, &d->arch.shadow.toplevel_shadows);
- }
- ASSERT(valid_mfn(smfn));
- v->arch.shadow_table = pagetable_from_mfn(smfn);
-
-#if SHADOW_OPTIMIZATIONS & SHOPT_EARLY_UNSHADOW
- /* Once again OK to unhook entries from this table if we see fork/exit */
- ASSERT(sh_mfn_is_a_page_table(gmfn));
- mfn_to_page(gmfn)->shadow_flags &= ~SHF_unhooked_mappings;
-#endif
-
- ////
- //// vcpu->arch.shadow_vtable
- ////
- if ( shadow_mode_external(d) )
+#if GUEST_PAGING_LEVELS == 2
+ sh_set_toplevel_shadow(v, 0, gmfn, PGC_SH_l2_shadow);
+#elif GUEST_PAGING_LEVELS == 3
+ /* PAE guests have four shadow_table entries, based on the
+ * current values of the guest's four l3es. */
{
-#if (SHADOW_PAGING_LEVELS == 3) && (GUEST_PAGING_LEVELS == 3)
- mfn_t adjusted_smfn = smfn;
- u32 shadow_idx = shadow_l3_index(&adjusted_smfn, guest_idx);
- // Q: why does this need to use (un)map_domain_page_*global* ?
- v->arch.shadow_vtable =
- (shadow_l3e_t *)sh_map_domain_page_global(adjusted_smfn) +
- shadow_idx;
-#else
- // Q: why does this need to use (un)map_domain_page_*global* ?
- v->arch.shadow_vtable = sh_map_domain_page_global(smfn);
-#endif
+ int i;
+ guest_l3e_t *gl3e = (guest_l3e_t*)v->arch.guest_vtable;
+ for ( i = 0; i < 4; i++ )
+ {
+ ASSERT(pagetable_is_null(v->arch.shadow_table[i]));
+ if ( guest_l3e_get_flags(gl3e[i]) & _PAGE_PRESENT )
+ {
+ gfn_t gl2gfn = guest_l3e_get_gfn(gl3e[i]);
+ mfn_t gl2mfn = vcpu_gfn_to_mfn(v, gl2gfn);
+ if ( valid_mfn(gl2mfn) )
+ sh_set_toplevel_shadow(v, i, gl2mfn, (i == 3)
+ ? PGC_SH_l2h_shadow
+ : PGC_SH_l2_shadow);
+ }
+ }
}
- else
- {
-#if SHADOW_PAGING_LEVELS == 4
- v->arch.shadow_vtable = __sh_linear_l4_table;
-#elif GUEST_PAGING_LEVELS == 3
- // XXX - why does this need a global map?
- v->arch.shadow_vtable = sh_map_domain_page_global(smfn);
+#elif GUEST_PAGING_LEVELS == 4
+ sh_set_toplevel_shadow(v, 0, gmfn, PGC_SH_l4_shadow);
#else
- v->arch.shadow_vtable = __sh_linear_l2_table;
+#error This should never happen
#endif
- }
#if (CONFIG_PAGING_LEVELS == 3) && (GUEST_PAGING_LEVELS == 3)
- // Now that shadow_vtable is in place, check that the sl3e[3] is properly
- // shadowed and installed in PAE PV guests...
- if ( !shadow_mode_external(d) &&
- !(shadow_l3e_get_flags(((shadow_l3e_t *)v->arch.shadow_vtable)[3]) &
- _PAGE_PRESENT) )
- {
- sh_install_xen_entries_in_l3(v, gmfn, smfn);
- }
#endif
- ////
- //// Take a ref to the new shadow table, and pin it.
- ////
- //
- // This ref is logically "held" by v->arch.shadow_table entry itself.
- // Release the old ref.
- //
-#if GUEST_PAGING_LEVELS == 3
- // PAE guests do not (necessarily) use an entire page for their
- // 4-entry L3s, so we have to deal with them specially.
- //
- // XXX - might want to revisit this if/when we do multiple compilation for
- // HVM-vs-PV guests, as PAE PV guests could get away without doing
- // subshadows.
- //
- sh_get_ref_l3_subshadow(v->arch.shadow_vtable, smfn);
- sh_pin_l3_subshadow(v->arch.shadow_vtable, smfn);
+ ///
+ /// v->arch.shadow.l3table
+ ///
+#if SHADOW_PAGING_LEVELS == 3
+ {
+ mfn_t smfn;
+ int i;
+ for ( i = 0; i < 4; i++ )
+ {
+#if GUEST_PAGING_LEVELS == 2
+ /* 2-on-3: make a PAE l3 that points at the four-page l2 */
+ smfn = _mfn(pagetable_get_pfn(v->arch.shadow_table[0]) + i);
#else
- sh_get_ref(smfn, 0);
- sh_pin(smfn);
+ /* 3-on-3: make a PAE l3 that points at the four l2 pages */
+ smfn = pagetable_get_mfn(v->arch.shadow_table[i]);
#endif
+ v->arch.shadow.l3table[i] =
+ (mfn_x(smfn) == 0)
+ ? shadow_l3e_empty()
+ : shadow_l3e_from_mfn(smfn, _PAGE_PRESENT);
+ }
+ }
+#endif /* SHADOW_PAGING_LEVELS == 3 */
-#if (SHADOW_PAGING_LEVELS == 3) && (GUEST_PAGING_LEVELS == 3)
- // PAE 3-on-3 shadows have to keep track of which vcpu's are using
- // which l3 subshadow, in order handle the SHADOW_SET_L3PAE_RECOPY
- // case from validate_gl3e(). Search for SHADOW_SET_L3PAE_RECOPY
- // in the code for more info.
- //
+
+ ///
+ /// v->arch.cr3
+ ///
+ if ( shadow_mode_external(d) )
{
- struct pae_l3_bookkeeping *info =
- sl3p_to_info(v->arch.shadow_vtable);
- ASSERT(!test_bit(v->vcpu_id, &info->vcpus));
- set_bit(v->vcpu_id, &info->vcpus);
+ make_cr3(v, pagetable_get_pfn(v->arch.monitor_table));
}
+ else // not shadow_mode_external...
+ {
+ /* We don't support PV except guest == shadow == config levels */
+ BUG_ON(GUEST_PAGING_LEVELS != SHADOW_PAGING_LEVELS);
+#if SHADOW_PAGING_LEVELS == 3
+ /* 2-on-3 or 3-on-3: Use the PAE shadow l3 table we just fabricated.
+ * Don't use make_cr3 because (a) we know it's below 4GB, and
+ * (b) it's not necessarily page-aligned, and make_cr3 takes a pfn */
+ ASSERT(virt_to_maddr(&v->arch.shadow.l3table) <= 0xffffffe0ULL);
+ v->arch.cr3 = virt_to_maddr(&v->arch.shadow.l3table);
+#else
+ /* 2-on-2 or 4-on-4: Just use the shadow top-level directly */
+ make_cr3(v, pagetable_get_pfn(v->arch.shadow_table[0]));
#endif
+ }
- debugtrace_printk("%s cr3 gmfn=%05lx smfn=%05lx\n",
- __func__, gmfn, smfn);
///
- /// v->arch.cr3 and, if appropriate, v->arch.hvm_vcpu.hw_cr3
+ /// v->arch.hvm_vcpu.hw_cr3
///
if ( shadow_mode_external(d) )
{
ASSERT(hvm_guest(v));
- make_cr3(v, pagetable_get_pfn(v->arch.monitor_table));
-
-#if (GUEST_PAGING_LEVELS == 2) && (SHADOW_PAGING_LEVELS != 2)
-#if SHADOW_PAGING_LEVELS != 3
-#error unexpected combination of GUEST and SHADOW paging levels
-#endif
- /* 2-on-3: make a PAE l3 table that points at the four-page l2 */
- {
- mfn_t smfn = pagetable_get_mfn(v->arch.shadow_table);
- int i;
-
- ASSERT(v->arch.hvm_vcpu.hw_cr3 ==
- virt_to_maddr(v->arch.hvm_vcpu.hvm_lowmem_l3tab));
- for (i = 0; i < 4; i++)
- {
- v->arch.hvm_vcpu.hvm_lowmem_l3tab[i] =
- shadow_l3e_from_mfn(_mfn(mfn_x(smfn)+i), _PAGE_PRESENT);
- }
- }
-#elif (GUEST_PAGING_LEVELS == 3) && (SHADOW_PAGING_LEVELS == 3)
- /* 3-on-3: copy the shadow l3 to slots that are below 4GB.
- * If paging is disabled, clear l3e reserved bits; otherwise
- * remove entries that have reserved bits set. */
- v->arch.hvm_vcpu.hw_cr3 =
- hvm_pae_copy_root(v, v->arch.shadow_vtable,
- !shadow_vcpu_mode_translate(v));
+#if SHADOW_PAGING_LEVELS == 3
+ /* 2-on-3 or 3-on-3: Use the PAE shadow l3 table we just fabricated */
+ v->arch.hvm_vcpu.hw_cr3 = virt_to_maddr(&v->arch.shadow.l3table);
#else
- /* 2-on-2 or 4-on-4: just put the shadow top-level into cr3 */
- v->arch.hvm_vcpu.hw_cr3 =
- pagetable_get_paddr(v->arch.shadow_table);
+ /* 2-on-2 or 4-on-4: Just use the shadow top-level directly */
+ v->arch.hvm_vcpu.hw_cr3 = pagetable_get_paddr(v->arch.shadow_table[0]);
#endif
}
- else // not shadow_mode_external...
- {
- /* We don't support PV except guest == shadow == config levels */
- BUG_ON(GUEST_PAGING_LEVELS != SHADOW_PAGING_LEVELS);
- make_cr3(v, pagetable_get_pfn(v->arch.shadow_table));
- }
/* Fix up the linear pagetable mappings */
sh_update_linear_entries(v);
@@ -3950,7 +3528,6 @@ static int sh_guess_wrmap(struct vcpu *v, unsigned long vaddr, mfn_t gmfn)
/* Carefully look in the shadow linear map for the l1e we expect */
- if ( v->arch.shadow_vtable == NULL ) return 0;
#if GUEST_PAGING_LEVELS >= 4
sl4p = sh_linear_l4_table(v) + shadow_l4_linear_offset(vaddr);
if ( !(shadow_l4e_get_flags(*sl4p) & _PAGE_PRESENT) )
@@ -3959,7 +3536,7 @@ static int sh_guess_wrmap(struct vcpu *v, unsigned long vaddr, mfn_t gmfn)
if ( !(shadow_l3e_get_flags(*sl3p) & _PAGE_PRESENT) )
return 0;
#elif GUEST_PAGING_LEVELS == 3
- sl3p = ((shadow_l3e_t *) v->arch.shadow_vtable)
+ sl3p = ((shadow_l3e_t *) v->arch.shadow.l3table)
+ shadow_l3_linear_offset(vaddr);
if ( !(shadow_l3e_get_flags(*sl3p) & _PAGE_PRESENT) )
return 0;
@@ -3988,6 +3565,7 @@ int sh_remove_write_access(struct vcpu *v, mfn_t sl1mfn, mfn_t readonly_mfn)
shadow_l1e_t *sl1e;
int done = 0;
int flags;
+ mfn_t base_sl1mfn = sl1mfn; /* Because sl1mfn changes in the foreach */
SHADOW_FOREACH_L1E(sl1mfn, sl1e, 0, done,
{
@@ -3997,6 +3575,10 @@ int sh_remove_write_access(struct vcpu *v, mfn_t sl1mfn, mfn_t readonly_mfn)
&& (mfn_x(shadow_l1e_get_mfn(*sl1e)) == mfn_x(readonly_mfn)) )
{
shadow_set_l1e(v, sl1e, shadow_l1e_empty(), sl1mfn);
+#if SHADOW_OPTIMIZATIONS & SHOPT_WRITABLE_HEURISTIC
+ /* Remember the last shadow that we shot a writeable mapping in */
+ v->arch.shadow.last_writeable_pte_smfn = mfn_x(base_sl1mfn);
+#endif
if ( (mfn_to_page(readonly_mfn)->u.inuse.type_info
& PGT_count_mask) == 0 )
/* This breaks us cleanly out of the FOREACH macro */
@@ -4044,14 +3626,12 @@ void sh_clear_shadow_entry(struct vcpu *v, void *ep, mfn_t smfn)
case PGC_SH_l2h_shadow:
#endif
shadow_set_l2e(v, ep, shadow_l2e_empty(), smfn); break;
-#if GUEST_PAGING_LEVELS >= 3
+#if GUEST_PAGING_LEVELS >= 4
case PGC_SH_l3_shadow:
shadow_set_l3e(v, ep, shadow_l3e_empty(), smfn); break;
-#if GUEST_PAGING_LEVELS >= 4
case PGC_SH_l4_shadow:
shadow_set_l4e(v, ep, shadow_l4e_empty(), smfn); break;
#endif
-#endif
default: BUG(); /* Called with the wrong kind of shadow. */
}
}
@@ -4081,7 +3661,7 @@ int sh_remove_l1_shadow(struct vcpu *v, mfn_t sl2mfn, mfn_t sl1mfn)
return done;
}
-#if GUEST_PAGING_LEVELS >= 3
+#if GUEST_PAGING_LEVELS >= 4
int sh_remove_l2_shadow(struct vcpu *v, mfn_t sl3mfn, mfn_t sl2mfn)
/* Remove all mappings of this l2 shadow from this l3 shadow */
{
@@ -4104,7 +3684,6 @@ int sh_remove_l2_shadow(struct vcpu *v, mfn_t sl3mfn, mfn_t sl2mfn)
return done;
}
-#if GUEST_PAGING_LEVELS >= 4
int sh_remove_l3_shadow(struct vcpu *v, mfn_t sl4mfn, mfn_t sl3mfn)
/* Remove all mappings of this l3 shadow from this l4 shadow */
{
@@ -4127,7 +3706,6 @@ int sh_remove_l3_shadow(struct vcpu *v, mfn_t sl4mfn, mfn_t sl3mfn)
return done;
}
#endif /* 64bit guest */
-#endif /* PAE guest */
/**************************************************************************/
/* Handling HVM guest writes to pagetables */
@@ -4448,7 +4026,7 @@ int sh_audit_l2_table(struct vcpu *v, mfn_t sl2mfn, mfn_t x)
return 0;
}
-#if GUEST_PAGING_LEVELS >= 3
+#if GUEST_PAGING_LEVELS >= 4
int sh_audit_l3_table(struct vcpu *v, mfn_t sl3mfn, mfn_t x)
{
guest_l3e_t *gl3e, *gp;
@@ -4486,9 +4064,7 @@ int sh_audit_l3_table(struct vcpu *v, mfn_t sl3mfn, mfn_t x)
sh_unmap_domain_page(gp);
return 0;
}
-#endif /* GUEST_PAGING_LEVELS >= 3 */
-#if GUEST_PAGING_LEVELS >= 4
int sh_audit_l4_table(struct vcpu *v, mfn_t sl4mfn, mfn_t x)
{
guest_l4e_t *gl4e, *gp;
diff --git a/xen/arch/x86/mm/shadow/multi.h b/xen/arch/x86/mm/shadow/multi.h
index 732782cd62..2cc61b830f 100644
--- a/xen/arch/x86/mm/shadow/multi.h
+++ b/xen/arch/x86/mm/shadow/multi.h
@@ -50,10 +50,6 @@ extern void
SHADOW_INTERNAL_NAME(sh_destroy_l4_shadow, SHADOW_LEVELS, GUEST_LEVELS)(
struct vcpu *v, mfn_t smfn);
-extern void
-SHADOW_INTERNAL_NAME(sh_unpin_all_l3_subshadows, 3, 3)
- (struct vcpu *v, mfn_t smfn);
-
extern void
SHADOW_INTERNAL_NAME(sh_unhook_32b_mappings, SHADOW_LEVELS, GUEST_LEVELS)
(struct vcpu *v, mfn_t sl2mfn);
diff --git a/xen/arch/x86/mm/shadow/private.h b/xen/arch/x86/mm/shadow/private.h
index a357e189fb..ba56d2b809 100644
--- a/xen/arch/x86/mm/shadow/private.h
+++ b/xen/arch/x86/mm/shadow/private.h
@@ -178,77 +178,6 @@ extern void shadow_audit_p2m(struct domain *d);
/******************************************************************************
- * Mechanism for double-checking the optimized pagefault path: this
- * structure contains a record of actions taken by the fault handling
- * code. In paranoid mode, the fast-path code fills out one of these
- * structures (but doesn't take any actual action) and then the normal
- * path fills in another. When the fault handler finishes, the
- * two are compared */
-
-#ifdef SHADOW_OPTIMIZATION_PARANOIA
-
-typedef struct shadow_action_log sh_log_t;
-struct shadow_action_log {
- paddr_t ad[CONFIG_PAGING_LEVELS]; /* A & D bits propagated here */
- paddr_t mmio; /* Address of an mmio operation */
- int rv; /* Result of the fault handler */
-};
-
-/* There are two logs, one for the fast path, one for the normal path */
-enum sh_log_type { log_slow = 0, log_fast= 1 };
-
-/* Alloc and zero the logs */
-static inline void sh_init_log(struct vcpu *v)
-{
- if ( unlikely(!v->arch.shadow.action_log) )
- v->arch.shadow.action_log = xmalloc_array(sh_log_t, 2);
- ASSERT(v->arch.shadow.action_log);
- memset(v->arch.shadow.action_log, 0, 2 * sizeof (sh_log_t));
-}
-
-/* Log an A&D-bit update */
-static inline void sh_log_ad(struct vcpu *v, paddr_t e, unsigned int level)
-{
- v->arch.shadow.action_log[v->arch.shadow.action_index].ad[level] = e;
-}
-
-/* Log an MMIO address */
-static inline void sh_log_mmio(struct vcpu *v, paddr_t m)
-{
- v->arch.shadow.action_log[v->arch.shadow.action_index].mmio = m;
-}
-
-/* Log the result */
-static inline void sh_log_rv(struct vcpu *v, int rv)
-{
- v->arch.shadow.action_log[v->arch.shadow.action_index].rv = rv;
-}
-
-/* Set which mode we're in */
-static inline void sh_set_log_mode(struct vcpu *v, enum sh_log_type t)
-{
- v->arch.shadow.action_index = t;
-}
-
-/* Know not to take action, because we're only checking the mechanism */
-static inline int sh_take_no_action(struct vcpu *v)
-{
- return (v->arch.shadow.action_index == log_fast);
-}
-
-#else /* Non-paranoid mode: these logs do not exist */
-
-#define sh_init_log(_v) do { (void)(_v); } while(0)
-#define sh_set_log_mode(_v,_t) do { (void)(_v); } while(0)
-#define sh_log_ad(_v,_e,_l) do { (void)(_v),(void)(_e),(void)(_l); } while (0)
-#define sh_log_mmio(_v,_m) do { (void)(_v),(void)(_m); } while (0)
-#define sh_log_rv(_v,_r) do { (void)(_v),(void)(_r); } while (0)
-#define sh_take_no_action(_v) (((void)(_v)), 0)
-
-#endif /* SHADOW_OPTIMIZATION_PARANOIA */
-
-
-/******************************************************************************
* Macro for dealing with the naming of the internal names of the
* shadow code's external entry points.
*/
@@ -336,13 +265,9 @@ void shadow_convert_to_log_dirty(struct vcpu *v, mfn_t smfn);
* non-Xen mappings in this top-level shadow mfn */
void shadow_unhook_mappings(struct vcpu *v, mfn_t smfn);
-/* Re-sync copies of PAE shadow L3 tables if they have been changed */
-void sh_pae_recopy(struct domain *d);
-
/* Install the xen mappings in various flavours of shadow */
void sh_install_xen_entries_in_l4(struct vcpu *v, mfn_t gl4mfn, mfn_t sl4mfn);
void sh_install_xen_entries_in_l2h(struct vcpu *v, mfn_t sl2hmfn);
-void sh_install_xen_entries_in_l3(struct vcpu *v, mfn_t gl3mfn, mfn_t sl3mfn);
void sh_install_xen_entries_in_l2(struct vcpu *v, mfn_t gl2mfn, mfn_t sl2mfn);
diff --git a/xen/arch/x86/mm/shadow/types.h b/xen/arch/x86/mm/shadow/types.h
index 0faf217f06..69d077f561 100644
--- a/xen/arch/x86/mm/shadow/types.h
+++ b/xen/arch/x86/mm/shadow/types.h
@@ -215,8 +215,7 @@ static inline shadow_l4e_t shadow_l4e_from_mfn(mfn_t mfn, u32 flags)
shadow_l1_linear_offset(SH_LINEAR_PT_VIRT_START)); \
})
-// shadow linear L3 and L4 tables only exist in 4 level paging...
-#if SHADOW_PAGING_LEVELS == 4
+#if SHADOW_PAGING_LEVELS >= 4
#define sh_linear_l3_table(v) ({ \
ASSERT(current == (v)); \
((shadow_l3e_t *) \
@@ -386,7 +385,6 @@ static inline guest_l4e_t guest_l4e_from_gfn(gfn_t gfn, u32 flags)
#define PGC_SH_fl1_shadow PGC_SH_fl1_pae_shadow
#define PGC_SH_l2_shadow PGC_SH_l2_pae_shadow
#define PGC_SH_l2h_shadow PGC_SH_l2h_pae_shadow
-#define PGC_SH_l3_shadow PGC_SH_l3_pae_shadow
#else
#define PGC_SH_l1_shadow PGC_SH_l1_64_shadow
#define PGC_SH_fl1_shadow PGC_SH_fl1_64_shadow
@@ -405,14 +403,6 @@ valid_gfn(gfn_t m)
return VALID_GFN(gfn_x(m));
}
-#if GUEST_PAGING_LEVELS == 2
-#define PGC_SH_guest_root_type PGC_SH_l2_32_shadow
-#elif GUEST_PAGING_LEVELS == 3
-#define PGC_SH_guest_root_type PGC_SH_l3_pae_shadow
-#else
-#define PGC_SH_guest_root_type PGC_SH_l4_64_shadow
-#endif
-
/* Translation between mfns and gfns */
static inline mfn_t
vcpu_gfn_to_mfn(struct vcpu *v, gfn_t gfn)
@@ -490,8 +480,6 @@ struct shadow_walk_t
#define sh_map_and_validate_gl1e INTERNAL_NAME(sh_map_and_validate_gl1e)
#define sh_destroy_l4_shadow INTERNAL_NAME(sh_destroy_l4_shadow)
#define sh_destroy_l3_shadow INTERNAL_NAME(sh_destroy_l3_shadow)
-#define sh_destroy_l3_subshadow INTERNAL_NAME(sh_destroy_l3_subshadow)
-#define sh_unpin_all_l3_subshadows INTERNAL_NAME(sh_unpin_all_l3_subshadows)
#define sh_destroy_l2_shadow INTERNAL_NAME(sh_destroy_l2_shadow)
#define sh_destroy_l1_shadow INTERNAL_NAME(sh_destroy_l1_shadow)
#define sh_unhook_32b_mappings INTERNAL_NAME(sh_unhook_32b_mappings)
@@ -533,115 +521,6 @@ struct shadow_walk_t
SHADOW_PAGING_LEVELS)
-#if GUEST_PAGING_LEVELS == 3
-/*
- * Accounting information stored in the shadow of PAE Guest L3 pages.
- * Because these "L3 pages" are only 32-bytes, it is inconvenient to keep
- * various refcounts, etc., on the page_info of their page. We provide extra
- * bookkeeping space in the shadow itself, and this is the structure
- * definition for that bookkeeping information.
- */
-struct pae_l3_bookkeeping {
- u32 vcpus; /* bitmap of which vcpus are currently storing
- * copies of this 32-byte page */
- u32 refcount; /* refcount for this 32-byte page */
- u8 pinned; /* is this 32-byte page pinned or not? */
-};
-
-// Convert a shadow entry pointer into a pae_l3_bookkeeping pointer.
-#define sl3p_to_info(_ptr) ((struct pae_l3_bookkeeping *) \
- (((unsigned long)(_ptr) & ~31) + 32))
-
-static void sh_destroy_l3_subshadow(struct vcpu *v,
- shadow_l3e_t *sl3e);
-
-/* Increment a subshadow ref
- * Called with a pointer to the subshadow, and the mfn of the
- * *first* page of the overall shadow. */
-static inline void sh_get_ref_l3_subshadow(shadow_l3e_t *sl3e, mfn_t smfn)
-{
- struct pae_l3_bookkeeping *bk = sl3p_to_info(sl3e);
-
- /* First ref to the subshadow takes a ref to the full shadow */
- if ( bk->refcount == 0 )
- sh_get_ref(smfn, 0);
- if ( unlikely(++(bk->refcount) == 0) )
- {
- SHADOW_PRINTK("shadow l3 subshadow ref overflow, smfn=%" SH_PRI_mfn " sh=%p\n",
- mfn_x(smfn), sl3e);
- domain_crash_synchronous();
- }
-}
-
-/* Decrement a subshadow ref.
- * Called with a pointer to the subshadow, and the mfn of the
- * *first* page of the overall shadow. Calling this may cause the
- * entire shadow to disappear, so the caller must immediately unmap
- * the pointer after calling. */
-static inline void sh_put_ref_l3_subshadow(struct vcpu *v,
- shadow_l3e_t *sl3e,
- mfn_t smfn)
-{
- struct pae_l3_bookkeeping *bk;
-
- bk = sl3p_to_info(sl3e);
-
- ASSERT(bk->refcount > 0);
- if ( --(bk->refcount) == 0 )
- {
- /* Need to destroy this subshadow */
- sh_destroy_l3_subshadow(v, sl3e);
- /* Last ref to the subshadow had a ref to the full shadow */
- sh_put_ref(v, smfn, 0);
- }
-}
-
-/* Pin a subshadow
- * Called with a pointer to the subshadow, and the mfn of the
- * *first* page of the overall shadow. */
-static inline void sh_pin_l3_subshadow(shadow_l3e_t *sl3e, mfn_t smfn)
-{
- struct pae_l3_bookkeeping *bk = sl3p_to_info(sl3e);
-
-#if 0
- debugtrace_printk("%s smfn=%05lx offset=%ld\n",
- __func__, mfn_x(smfn),
- ((unsigned long)sl3e & ~PAGE_MASK) / 64);
-#endif
-
- if ( !bk->pinned )
- {
- bk->pinned = 1;
- sh_get_ref_l3_subshadow(sl3e, smfn);
- }
-}
-
-/* Unpin a sub-shadow.
- * Called with a pointer to the subshadow, and the mfn of the
- * *first* page of the overall shadow. Calling this may cause the
- * entire shadow to disappear, so the caller must immediately unmap
- * the pointer after calling. */
-static inline void sh_unpin_l3_subshadow(struct vcpu *v,
- shadow_l3e_t *sl3e,
- mfn_t smfn)
-{
- struct pae_l3_bookkeeping *bk = sl3p_to_info(sl3e);
-
-#if 0
- debugtrace_printk("%s smfn=%05lx offset=%ld\n",
- __func__, mfn_x(smfn),
- ((unsigned long)sl3e & ~PAGE_MASK) / 64);
-#endif
-
- if ( bk->pinned )
- {
- bk->pinned = 0;
- sh_put_ref_l3_subshadow(v, sl3e, smfn);
- }
-}
-
-#endif /* GUEST_PAGING_LEVELS == 3 */
-
#if SHADOW_PAGING_LEVELS == 3
#define MFN_FITS_IN_HVM_CR3(_MFN) !(mfn_x(_MFN) >> 20)
#endif
diff --git a/xen/arch/x86/oprofile/op_model_athlon.c b/xen/arch/x86/oprofile/op_model_athlon.c
index c946c1ea8e..1d8f9668f4 100644
--- a/xen/arch/x86/oprofile/op_model_athlon.c
+++ b/xen/arch/x86/oprofile/op_model_athlon.c
@@ -18,6 +18,7 @@
#include <xen/sched.h>
#include <asm/regs.h>
#include <asm/current.h>
+#include <asm/hvm/support.h>
#include "op_x86_model.h"
#include "op_counter.h"
@@ -44,7 +45,11 @@ static unsigned long reset_value[NUM_COUNTERS];
extern void xenoprof_log_event(struct vcpu *v, unsigned long eip,
int mode, int event);
-
+extern int xenoprofile_get_mode(struct vcpu *v,
+ struct cpu_user_regs * const regs);
+
+extern char svm_stgi_label[];
+
static void athlon_fill_in_addresses(struct op_msrs * const msrs)
{
msrs->counters[0].addr = MSR_K7_PERFCTR0;
@@ -97,10 +102,9 @@ static void athlon_setup_ctrs(struct op_msrs const * const msrs)
}
}
-
static int athlon_check_ctrs(unsigned int const cpu,
- struct op_msrs const * const msrs,
- struct cpu_user_regs * const regs)
+ struct op_msrs const * const msrs,
+ struct cpu_user_regs * const regs)
{
unsigned int low, high;
@@ -108,11 +112,19 @@ static int athlon_check_ctrs(unsigned int const cpu,
int ovf = 0;
unsigned long eip = regs->eip;
int mode = 0;
-
- if (guest_kernel_mode(current, regs))
- mode = 1;
- else if (ring_0(regs))
- mode = 2;
+ struct vcpu *v = current;
+ struct cpu_user_regs tmp_regs;
+
+ if (!guest_mode(regs) &&
+ (regs->eip == (unsigned long)svm_stgi_label)) {
+ /* SVM guest was running when NMI occurred */
+ hvm_store_cpu_guest_regs(v, &tmp_regs, NULL);
+ eip = tmp_regs.eip;
+ mode = xenoprofile_get_mode(v, &tmp_regs);
+ } else {
+ eip = regs->eip;
+ mode = xenoprofile_get_mode(v, regs);
+ }
for (i = 0 ; i < NUM_COUNTERS; ++i) {
CTR_READ(low, high, msrs, i);
diff --git a/xen/arch/x86/oprofile/op_model_p4.c b/xen/arch/x86/oprofile/op_model_p4.c
index 018124eaf9..c285ea1d41 100644
--- a/xen/arch/x86/oprofile/op_model_p4.c
+++ b/xen/arch/x86/oprofile/op_model_p4.c
@@ -620,9 +620,10 @@ static void p4_setup_ctrs(struct op_msrs const * const msrs)
}
}
-
extern void xenoprof_log_event(struct vcpu *v, unsigned long eip,
int mode, int event);
+extern int xenoprofile_get_mode(struct vcpu *v,
+ struct cpu_user_regs * const regs);
static int p4_check_ctrs(unsigned int const cpu,
struct op_msrs const * const msrs,
@@ -632,12 +633,7 @@ static int p4_check_ctrs(unsigned int const cpu,
int i;
int ovf = 0;
unsigned long eip = regs->eip;
- int mode = 0;
-
- if (guest_kernel_mode(current, regs))
- mode = 1;
- else if (ring_0(regs))
- mode = 2;
+ int mode = xenoprofile_get_mode(current, regs);
stag = get_stagger();
diff --git a/xen/arch/x86/oprofile/op_model_ppro.c b/xen/arch/x86/oprofile/op_model_ppro.c
index b982443928..139f4571bf 100644
--- a/xen/arch/x86/oprofile/op_model_ppro.c
+++ b/xen/arch/x86/oprofile/op_model_ppro.c
@@ -88,9 +88,10 @@ static void ppro_setup_ctrs(struct op_msrs const * const msrs)
}
}
-
extern void xenoprof_log_event(struct vcpu *v, unsigned long eip,
int mode, int event);
+extern int xenoprofile_get_mode(struct vcpu *v,
+ struct cpu_user_regs * const regs);
static int ppro_check_ctrs(unsigned int const cpu,
struct op_msrs const * const msrs,
@@ -100,13 +101,8 @@ static int ppro_check_ctrs(unsigned int const cpu,
int i;
int ovf = 0;
unsigned long eip = regs->eip;
- int mode = 0;
+ int mode = xenoprofile_get_mode(current, regs);
- if ( guest_kernel_mode(current, regs) )
- mode = 1;
- else if ( ring_0(regs) )
- mode = 2;
-
for (i = 0 ; i < NUM_COUNTERS; ++i) {
CTR_READ(low, high, msrs, i);
if (CTR_OVERFLOWED(low)) {
diff --git a/xen/arch/x86/oprofile/xenoprof.c b/xen/arch/x86/oprofile/xenoprof.c
index 4379d1223b..27c2a90297 100644
--- a/xen/arch/x86/oprofile/xenoprof.c
+++ b/xen/arch/x86/oprofile/xenoprof.c
@@ -7,12 +7,16 @@
#include <xen/guest_access.h>
#include <xen/sched.h>
#include <public/xenoprof.h>
+#include <asm/hvm/support.h>
#include "op_counter.h"
/* Limit amount of pages used for shared buffer (per domain) */
#define MAX_OPROF_SHARED_PAGES 32
+/* Lock protecting the following global state */
+static DEFINE_SPINLOCK(xenoprof_lock);
+
struct domain *active_domains[MAX_OPROF_DOMAINS];
int active_ready[MAX_OPROF_DOMAINS];
unsigned int adomains;
@@ -95,7 +99,7 @@ static void xenoprof_reset_buf(struct domain *d)
}
}
-char *alloc_xenoprof_buf(struct domain *d, int npages)
+static char *alloc_xenoprof_buf(struct domain *d, int npages)
{
char *rawbuf;
int i, order;
@@ -118,10 +122,12 @@ char *alloc_xenoprof_buf(struct domain *d, int npages)
return rawbuf;
}
-int alloc_xenoprof_struct(struct domain *d, int max_samples, int is_passive)
+static int alloc_xenoprof_struct(
+ struct domain *d, int max_samples, int is_passive)
{
struct vcpu *v;
int nvcpu, npages, bufsize, max_bufsize;
+ unsigned max_max_samples;
int i;
d->xenoprof = xmalloc(struct xenoprof);
@@ -139,17 +145,15 @@ int alloc_xenoprof_struct(struct domain *d, int max_samples, int is_passive)
for_each_vcpu ( d, v )
nvcpu++;
- /* reduce buffer size if necessary to limit pages allocated */
- bufsize = sizeof(struct xenoprof_buf) +
- (max_samples - 1) * sizeof(struct event_log);
+ /* reduce max_samples if necessary to limit pages allocated */
max_bufsize = (MAX_OPROF_SHARED_PAGES * PAGE_SIZE) / nvcpu;
- if ( bufsize > max_bufsize )
- {
- bufsize = max_bufsize;
- max_samples = ( (max_bufsize - sizeof(struct xenoprof_buf)) /
+ max_max_samples = ( (max_bufsize - sizeof(struct xenoprof_buf)) /
sizeof(struct event_log) ) + 1;
- }
+ if ( (unsigned)max_samples > max_max_samples )
+ max_samples = max_max_samples;
+ bufsize = sizeof(struct xenoprof_buf) +
+ (max_samples - 1) * sizeof(struct event_log);
npages = (nvcpu * bufsize - 1) / PAGE_SIZE + 1;
d->xenoprof->rawbuf = alloc_xenoprof_buf(is_passive ? dom0 : d, npages);
@@ -205,7 +209,7 @@ void free_xenoprof_pages(struct domain *d)
d->xenoprof = NULL;
}
-int active_index(struct domain *d)
+static int active_index(struct domain *d)
{
int i;
@@ -216,7 +220,7 @@ int active_index(struct domain *d)
return -1;
}
-int set_active(struct domain *d)
+static int set_active(struct domain *d)
{
int ind;
struct xenoprof *x;
@@ -237,7 +241,7 @@ int set_active(struct domain *d)
return 0;
}
-int reset_active(struct domain *d)
+static int reset_active(struct domain *d)
{
int ind;
struct xenoprof *x;
@@ -263,7 +267,7 @@ int reset_active(struct domain *d)
return 0;
}
-void reset_passive(struct domain *d)
+static void reset_passive(struct domain *d)
{
struct xenoprof *x;
@@ -279,7 +283,7 @@ void reset_passive(struct domain *d)
return;
}
-void reset_active_list(void)
+static void reset_active_list(void)
{
int i;
@@ -295,7 +299,7 @@ void reset_active_list(void)
activated = 0;
}
-void reset_passive_list(void)
+static void reset_passive_list(void)
{
int i;
@@ -309,7 +313,7 @@ void reset_passive_list(void)
pdomains = 0;
}
-int add_active_list (domid_t domid)
+static int add_active_list(domid_t domid)
{
struct domain *d;
@@ -327,7 +331,7 @@ int add_active_list (domid_t domid)
return 0;
}
-int add_passive_list(XEN_GUEST_HANDLE(void) arg)
+static int add_passive_list(XEN_GUEST_HANDLE(void) arg)
{
struct xenoprof_passive passive;
struct domain *d;
@@ -434,7 +438,7 @@ void xenoprof_log_event(
}
}
-int xenoprof_op_init(XEN_GUEST_HANDLE(void) arg)
+static int xenoprof_op_init(XEN_GUEST_HANDLE(void) arg)
{
struct xenoprof_init xenoprof_init;
int ret;
@@ -456,7 +460,7 @@ int xenoprof_op_init(XEN_GUEST_HANDLE(void) arg)
return 0;
}
-int xenoprof_op_get_buffer(XEN_GUEST_HANDLE(void) arg)
+static int xenoprof_op_get_buffer(XEN_GUEST_HANDLE(void) arg)
{
struct xenoprof_get_buffer xenoprof_get_buffer;
struct domain *d = current->domain;
@@ -515,6 +519,8 @@ int do_xenoprof_op(int op, XEN_GUEST_HANDLE(void) arg)
return -EPERM;
}
+ spin_lock(&xenoprof_lock);
+
switch ( op )
{
case XENOPROF_init:
@@ -540,23 +546,31 @@ int do_xenoprof_op(int op, XEN_GUEST_HANDLE(void) arg)
case XENOPROF_set_active:
{
domid_t domid;
- if ( xenoprof_state != XENOPROF_IDLE )
- return -EPERM;
- if ( copy_from_guest(&domid, arg, 1) )
- return -EFAULT;
+ if ( xenoprof_state != XENOPROF_IDLE ) {
+ ret = -EPERM;
+ break;
+ }
+ if ( copy_from_guest(&domid, arg, 1) ) {
+ ret = -EFAULT;
+ break;
+ }
ret = add_active_list(domid);
break;
}
case XENOPROF_set_passive:
{
- if ( xenoprof_state != XENOPROF_IDLE )
- return -EPERM;
+ if ( xenoprof_state != XENOPROF_IDLE ) {
+ ret = -EPERM;
+ break;
+ }
ret = add_passive_list(arg);
break;
}
case XENOPROF_reserve_counters:
- if ( xenoprof_state != XENOPROF_IDLE )
- return -EPERM;
+ if ( xenoprof_state != XENOPROF_IDLE ) {
+ ret = -EPERM;
+ break;
+ }
ret = nmi_reserve_counters();
if ( !ret )
xenoprof_state = XENOPROF_COUNTERS_RESERVED;
@@ -565,16 +579,20 @@ int do_xenoprof_op(int op, XEN_GUEST_HANDLE(void) arg)
case XENOPROF_counter:
{
struct xenoprof_counter counter;
- if ( xenoprof_state != XENOPROF_COUNTERS_RESERVED )
- return -EPERM;
- if ( adomains == 0 )
- return -EPERM;
+ if ( xenoprof_state != XENOPROF_COUNTERS_RESERVED || adomains == 0) {
+ ret = -EPERM;
+ break;
+ }
- if ( copy_from_guest(&counter, arg, 1) )
- return -EFAULT;
+ if ( copy_from_guest(&counter, arg, 1) ) {
+ ret = -EFAULT;
+ break;
+ }
- if ( counter.ind > OP_MAX_COUNTER )
- return -E2BIG;
+ if ( counter.ind > OP_MAX_COUNTER ) {
+ ret = -E2BIG;
+ break;
+ }
counter_config[counter.ind].count = (unsigned long) counter.count;
counter_config[counter.ind].enabled = (unsigned long) counter.enabled;
@@ -588,8 +606,10 @@ int do_xenoprof_op(int op, XEN_GUEST_HANDLE(void) arg)
}
case XENOPROF_setup_events:
- if ( xenoprof_state != XENOPROF_COUNTERS_RESERVED )
- return -EPERM;
+ if ( xenoprof_state != XENOPROF_COUNTERS_RESERVED ) {
+ ret = -EPERM;
+ break;
+ }
ret = nmi_setup_events();
if ( !ret )
xenoprof_state = XENOPROF_READY;
@@ -622,16 +642,20 @@ int do_xenoprof_op(int op, XEN_GUEST_HANDLE(void) arg)
break;
case XENOPROF_stop:
- if ( xenoprof_state != XENOPROF_PROFILING )
- return -EPERM;
+ if ( xenoprof_state != XENOPROF_PROFILING ) {
+ ret = -EPERM;
+ break;
+ }
nmi_stop();
xenoprof_state = XENOPROF_READY;
break;
case XENOPROF_disable_virq:
if ( (xenoprof_state == XENOPROF_PROFILING) &&
- (is_active(current->domain)) )
- return -EPERM;
+ (is_active(current->domain)) ) {
+ ret = -EPERM;
+ break;
+ }
ret = reset_active(current->domain);
break;
@@ -663,6 +687,8 @@ int do_xenoprof_op(int op, XEN_GUEST_HANDLE(void) arg)
ret = -EINVAL;
}
+ spin_unlock(&xenoprof_lock);
+
if ( ret < 0 )
printk("xenoprof: operation %d failed for dom %d (status : %d)\n",
op, current->domain->domain_id, ret);
@@ -670,6 +696,17 @@ int do_xenoprof_op(int op, XEN_GUEST_HANDLE(void) arg)
return ret;
}
+int xenoprofile_get_mode(struct vcpu *v, struct cpu_user_regs * const regs)
+{
+ if ( !guest_mode(regs) )
+ return 2;
+
+ if ( hvm_guest(v) )
+ return ((regs->cs & 3) != 3);
+
+ return guest_kernel_mode(v, regs);
+}
+
/*
* Local variables:
* mode: C
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index 8e69ca3220..9fb04ac6a2 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -202,6 +202,44 @@ static void __init percpu_free_unused_areas(void)
#endif
}
+/* Fetch acm policy module from multiboot modules. */
+static void extract_acm_policy(
+ multiboot_info_t *mbi,
+ unsigned int *initrdidx,
+ char **_policy_start,
+ unsigned long *_policy_len)
+{
+ int i;
+ module_t *mod = (module_t *)__va(mbi->mods_addr);
+ unsigned long start, policy_len;
+ char *policy_start;
+
+ /*
+ * Try all modules and see whichever could be the binary policy.
+ * Adjust the initrdidx if module[1] is the binary policy.
+ */
+ for ( i = mbi->mods_count-1; i >= 1; i-- )
+ {
+ start = initial_images_start + (mod[i].mod_start-mod[0].mod_start);
+#if defined(__i386__)
+ policy_start = (char *)start;
+#elif defined(__x86_64__)
+ policy_start = __va(start);
+#endif
+ policy_len = mod[i].mod_end - mod[i].mod_start;
+ if ( acm_is_policy(policy_start, policy_len) )
+ {
+ printk("Policy len 0x%lx, start at %p - module %d.\n",
+ policy_len, policy_start, i);
+ *_policy_start = policy_start;
+ *_policy_len = policy_len;
+ if ( i == 1 )
+ *initrdidx = (mbi->mods_count > 2) ? 2 : 0;
+ break;
+ }
+ }
+}
+
static void __init init_idle_domain(void)
{
struct domain *idle_domain;
@@ -224,6 +262,8 @@ void __init __start_xen(multiboot_info_t *mbi)
char __cmdline[] = "", *cmdline = __cmdline;
unsigned long _initrd_start = 0, _initrd_len = 0;
unsigned int initrdidx = 1;
+ char *_policy_start = NULL;
+ unsigned long _policy_len = 0;
module_t *mod = (module_t *)__va(mbi->mods_addr);
unsigned long nr_pages, modules_length;
paddr_t s, e;
@@ -565,8 +605,11 @@ void __init __start_xen(multiboot_info_t *mbi)
if ( opt_watchdog )
watchdog_enable();
+ /* Extract policy from multiboot. */
+ extract_acm_policy(mbi, &initrdidx, &_policy_start, &_policy_len);
+
/* initialize access control security module */
- acm_init(&initrdidx, mbi, initial_images_start);
+ acm_init(_policy_start, _policy_len);
/* Create initial domain 0. */
dom0 = domain_create(0);
diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c
index 6191af3ef3..970a742efc 100644
--- a/xen/arch/x86/time.c
+++ b/xen/arch/x86/time.c
@@ -919,6 +919,13 @@ void send_timer_event(struct vcpu *v)
send_guest_vcpu_virq(v, VIRQ_TIMER);
}
+/* Return secs after 00:00:00 localtime, 1 January, 1970. */
+unsigned long get_localtime(struct domain *d)
+{
+ return wc_sec + (wc_nsec + NOW()) / 1000000000ULL
+ + d->time_offset_seconds;
+}
+
/*
* Local variables:
* mode: C
diff --git a/xen/common/Makefile b/xen/common/Makefile
index 130e2b438b..b076e2a6a0 100644
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -20,8 +20,9 @@ obj-y += softirq.o
obj-y += string.o
obj-y += symbols.o
obj-y += sysctl.o
-obj-y += trace.o
+obj-y += time.o
obj-y += timer.o
+obj-y += trace.o
obj-y += version.o
obj-y += vsprintf.o
obj-y += xmalloc.o
diff --git a/xen/common/domain.c b/xen/common/domain.c
index 2dde26eb75..f96becc578 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -27,7 +27,7 @@
#include <public/vcpu.h>
/* Both these structures are protected by the domlist_lock. */
-rwlock_t domlist_lock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(domlist_lock);
struct domain *domain_hash[DOMAIN_HASH_SIZE];
struct domain *domain_list;
diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
index b09bc2b850..0e98628bd2 100644
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -1161,7 +1161,7 @@ grant_table_destroy(
return;
free_xenheap_pages(t->shared, ORDER_GRANT_FRAMES);
- free_xenheap_page(t->maptrack);
+ free_xenheap_pages(t->maptrack, t->maptrack_order);
xfree(t->active);
xfree(t);
diff --git a/xen/common/keyhandler.c b/xen/common/keyhandler.c
index e9e2b4d385..1486bdf7b5 100644
--- a/xen/common/keyhandler.c
+++ b/xen/common/keyhandler.c
@@ -173,6 +173,7 @@ static void dump_domains(unsigned char key)
printk("dirty_cpus=%s ", cpuset);
cpuset_print(cpuset, sizeof(cpuset), v->cpu_affinity);
printk("cpu_affinity=%s\n", cpuset);
+ arch_dump_vcpu_info(v);
printk(" Notifying guest (virq %d, port %d, stat %d/%d/%d)\n",
VIRQ_DEBUG, v->virq_to_evtchn[VIRQ_DEBUG],
test_bit(v->virq_to_evtchn[VIRQ_DEBUG],
diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c
index 70aab2799b..fbbe837780 100644
--- a/xen/common/page_alloc.c
+++ b/xen/common/page_alloc.c
@@ -704,7 +704,7 @@ void free_domheap_pages(struct page_info *pg, unsigned int order)
{
/* Freeing anonymous domain-heap pages. */
for ( i = 0; i < (1 << order); i++ )
- pg[i].u.free.cpumask = CPU_MASK_NONE;
+ cpus_clear(pg[i].u.free.cpumask);
free_heap_pages(pfn_dom_zone_type(page_to_mfn(pg)), pg, order);
drop_dom_ref = 0;
}
diff --git a/xen/common/schedule.c b/xen/common/schedule.c
index b7ed65aa4c..fc2a927e2b 100644
--- a/xen/common/schedule.c
+++ b/xen/common/schedule.c
@@ -113,7 +113,7 @@ int sched_init_vcpu(struct vcpu *v, unsigned int processor)
if ( is_idle_domain(d) || ((d->domain_id == 0) && opt_dom0_vcpus_pin) )
v->cpu_affinity = cpumask_of_cpu(processor);
else
- v->cpu_affinity = CPU_MASK_ALL;
+ cpus_setall(v->cpu_affinity);
/* Initialise the per-domain timers. */
init_timer(&v->timer, vcpu_timer_fn, v, v->processor);
diff --git a/xen/common/time.c b/xen/common/time.c
new file mode 100644
index 0000000000..65929d1c1f
--- /dev/null
+++ b/xen/common/time.c
@@ -0,0 +1,77 @@
+/******************************************************************************
+ * time.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <xen/config.h>
+#include <xen/time.h>
+
+/* Nonzero if YEAR is a leap year (every 4 years,
+ except every 100th isn't, and every 400th is). */
+#define __isleap(year) \
+ ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
+
+/* How many days are in each month. */
+const unsigned short int __mon_lengths[2][12] = {
+ /* Normal years. */
+ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
+ /* Leap years. */
+ {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
+};
+
+#define SECS_PER_HOUR (60 * 60)
+#define SECS_PER_DAY (SECS_PER_HOUR * 24)
+
+struct tm gmtime(unsigned long t)
+{
+ struct tm tbuf;
+ long days, rem;
+ int y;
+ unsigned short int *ip;
+
+ days = t / SECS_PER_DAY;
+ rem = t % SECS_PER_DAY;
+
+ tbuf.tm_hour = rem / SECS_PER_HOUR;
+ rem %= SECS_PER_HOUR;
+ tbuf.tm_min = rem / 60;
+ tbuf.tm_sec = rem % 60;
+ /* January 1, 1970 was a Thursday. */
+ tbuf.tm_wday = (4 + days) % 7;
+ if ( tbuf.tm_wday < 0 )
+ tbuf.tm_wday += 7;
+ y = 1970;
+ while ( days >= (rem = __isleap(y) ? 366 : 365) )
+ {
+ ++y;
+ days -= rem;
+ }
+ while ( days < 0 )
+ {
+ --y;
+ days += __isleap(y) ? 366 : 365;
+ }
+ tbuf.tm_year = y - 1900;
+ tbuf.tm_yday = days;
+ ip = (unsigned short int *)__mon_lengths[__isleap(y)];
+ for ( y = 0; days >= ip[y]; ++y )
+ days -= ip[y];
+ tbuf.tm_mon = y;
+ tbuf.tm_mday = days + 1;
+ tbuf.tm_isdst = -1;
+
+ return tbuf;
+}
diff --git a/xen/common/trace.c b/xen/common/trace.c
index fde88764eb..5f40a6b9d2 100644
--- a/xen/common/trace.c
+++ b/xen/common/trace.c
@@ -187,7 +187,7 @@ int tb_control(xen_sysctl_tbuf_op_t *tbc)
tbc->size = opt_tbuf_size * PAGE_SIZE;
break;
case XEN_SYSCTL_TBUFOP_set_cpu_mask:
- cpumask_to_xenctl_cpumap(&tbc->cpu_mask, &tb_cpu_mask);
+ xenctl_cpumap_to_cpumask(&tb_cpu_mask, &tbc->cpu_mask);
break;
case XEN_SYSCTL_TBUFOP_set_evt_mask:
tb_event_mask = tbc->evt_mask;
diff --git a/xen/common/vsprintf.c b/xen/common/vsprintf.c
index da82029195..7de43593fe 100644
--- a/xen/common/vsprintf.c
+++ b/xen/common/vsprintf.c
@@ -16,7 +16,7 @@
* - scnprintf and vscnprintf
*/
-#include <stdarg.h>
+#include <xen/stdarg.h>
#include <xen/ctype.h>
#include <xen/lib.h>
#include <asm/div64.h>
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index c3e17efe72..78034b2753 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -6,7 +6,7 @@
* Copyright (c) 2002-2004, K A Fraser.
*/
-#include <stdarg.h>
+#include <xen/stdarg.h>
#include <xen/config.h>
#include <xen/version.h>
#include <xen/init.h>
@@ -418,7 +418,7 @@ void console_endboot(void)
void console_force_unlock(void)
{
- console_lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(&console_lock);
serial_force_unlock(sercon_handle);
console_start_sync();
}
diff --git a/xen/drivers/char/serial.c b/xen/drivers/char/serial.c
index 024de30ae9..cd909a6cef 100644
--- a/xen/drivers/char/serial.c
+++ b/xen/drivers/char/serial.c
@@ -295,8 +295,8 @@ void serial_force_unlock(int handle)
if ( handle == -1 )
return;
- port->rx_lock = SPIN_LOCK_UNLOCKED;
- port->tx_lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(&port->rx_lock);
+ spin_lock_init(&port->tx_lock);
serial_start_sync(handle);
}
diff --git a/xen/include/acm/acm_hooks.h b/xen/include/acm/acm_hooks.h
index fb652bf041..4e956fca98 100644
--- a/xen/include/acm/acm_hooks.h
+++ b/xen/include/acm/acm_hooks.h
@@ -143,9 +143,9 @@ static inline int acm_pre_grant_map_ref(domid_t id)
{ return 0; }
static inline int acm_pre_grant_setup(domid_t id)
{ return 0; }
-static inline int acm_init(unsigned int *initrdidx,
- const multiboot_info_t *mbi,
- unsigned long start)
+static inline int acm_init(char *policy_start, unsigned long policy_len)
+{ return 0; }
+static inline int acm_is_policy(char *buf, unsigned long len)
{ return 0; }
static inline void acm_post_domain0_create(domid_t domid)
{ return; }
@@ -369,9 +369,11 @@ static inline int acm_sharing(ssidref_t ssidref1, ssidref_t ssidref2)
return ACM_ACCESS_PERMITTED;
}
-extern int acm_init(unsigned int *initrdidx,
- const multiboot_info_t *mbi,
- unsigned long start);
+
+extern int acm_init(char *policy_start, unsigned long policy_len);
+
+/* Return true iff buffer has an acm policy magic number. */
+extern int acm_is_policy(char *buf, unsigned long len);
#endif
diff --git a/xen/include/acpi/platform/acenv.h b/xen/include/acpi/platform/acenv.h
index 5a956b549b..c259c4afa7 100644
--- a/xen/include/acpi/platform/acenv.h
+++ b/xen/include/acpi/platform/acenv.h
@@ -119,7 +119,7 @@
/*! [Begin] no source code translation */
-#if defined(__linux__)
+#if 1 /*defined(__linux__)*/ /* XEN: suitable for all supported build OSes */
#include "aclinux.h"
#elif defined(_AED_EFI)
diff --git a/xen/include/asm-ia64/linux-xen/asm/spinlock.h b/xen/include/asm-ia64/linux-xen/asm/spinlock.h
index 1c2034c80d..129fbf5156 100644
--- a/xen/include/asm-ia64/linux-xen/asm/spinlock.h
+++ b/xen/include/asm-ia64/linux-xen/asm/spinlock.h
@@ -33,7 +33,7 @@ typedef struct {
#endif
} spinlock_t;
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
+#define SPIN_LOCK_UNLOCKED /*(spinlock_t)*/ { 0 }
#define spin_lock_init(x) ((x)->lock = 0)
#ifdef ASM_SUPPORTED
@@ -136,9 +136,9 @@ typedef struct {
unsigned int break_lock;
#endif
} rwlock_t;
-#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
+#define RW_LOCK_UNLOCKED /*(rwlock_t)*/ { 0, 0 }
-#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
+#define rwlock_init(x) do { *(x) = (rwlock_t) RW_LOCK_UNLOCKED; } while(0)
#define read_can_lock(rw) (*(volatile int *)(rw) >= 0)
#define write_can_lock(rw) (*(volatile int *)(rw) == 0)
diff --git a/xen/include/asm-powerpc/spinlock.h b/xen/include/asm-powerpc/spinlock.h
index f6574d6b76..e65e0f2bc0 100644
--- a/xen/include/asm-powerpc/spinlock.h
+++ b/xen/include/asm-powerpc/spinlock.h
@@ -81,10 +81,10 @@ typedef union {
#define __UNLOCKED (0U)
#define __LOCKED (~__UNLOCKED)
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { __UNLOCKED }
+#define SPIN_LOCK_UNLOCKED /*(spinlock_t)*/ { __UNLOCKED }
static inline void spin_lock_init(spinlock_t *lock)
{
- *lock = SPIN_LOCK_UNLOCKED;
+ *lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
}
static inline int spin_is_locked(spinlock_t *lock)
@@ -103,7 +103,7 @@ static inline void _raw_spin_lock(spinlock_t *lock)
static inline void _raw_spin_unlock(spinlock_t *lock)
{
sync_before_release();
- *lock = SPIN_LOCK_UNLOCKED;
+ *lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
}
static inline int _raw_spin_trylock(spinlock_t *lock)
@@ -121,10 +121,10 @@ typedef struct {
volatile unsigned int lock;
} rwlock_t;
-#define RW_LOCK_UNLOCKED (rwlock_t) { __UNLOCKED }
+#define RW_LOCK_UNLOCKED /*(rwlock_t)*/ { __UNLOCKED }
static inline void rwlock_init(rwlock_t *lock)
{
- *lock = RW_LOCK_UNLOCKED;
+ *lock = (rwlock_t) RW_LOCK_UNLOCKED;
}
static inline void _raw_read_lock(rwlock_t *lock)
@@ -152,7 +152,7 @@ static inline void _raw_write_lock(rwlock_t *lock)
static inline void _raw_write_unlock(rwlock_t *lock)
{
sync_before_release();
- *lock = RW_LOCK_UNLOCKED;
+ *lock = (rwlock_t) RW_LOCK_UNLOCKED;
}
static inline void _raw_read_unlock(rwlock_t *lock)
diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h
index 3486fb234c..71fd4dcd3b 100644
--- a/xen/include/asm-x86/domain.h
+++ b/xen/include/asm-x86/domain.h
@@ -134,18 +134,20 @@ struct pae_l3_cache { };
#endif
struct shadow_vcpu {
+#if CONFIG_PAGING_LEVELS >= 3
+ /* PAE guests: per-vcpu shadow top-level table */
+ l3_pgentry_t l3table[4] __attribute__((__aligned__(32)));
+#endif
/* Pointers to mode-specific entry points. */
struct shadow_paging_mode *mode;
/* Last MFN that we emulated a write to. */
unsigned long last_emulated_mfn;
+ /* MFN of the last shadow that we shot a writeable mapping in */
+ unsigned long last_writeable_pte_smfn;
/* HVM guest: paging enabled (CR0.PG)? */
unsigned int translate_enabled:1;
/* Emulated fault needs to be propagated to guest? */
unsigned int propagate_fault:1;
-#if CONFIG_PAGING_LEVELS >= 3
- /* Shadow update requires this PAE cpu to recopy/install its L3 table. */
- unsigned int pae_flip_pending:1;
-#endif
};
struct arch_vcpu
@@ -190,13 +192,12 @@ struct arch_vcpu
pagetable_t guest_table; /* (MFN) guest notion of cr3 */
/* guest_table holds a ref to the page, and also a type-count unless
* shadow refcounts are in use */
- pagetable_t shadow_table; /* (MFN) shadow of guest */
+ pagetable_t shadow_table[4]; /* (MFN) shadow(s) of guest */
pagetable_t monitor_table; /* (MFN) hypervisor PT (for HVM) */
unsigned long cr3; /* (MA) value to install in HW CR3 */
- void *guest_vtable; /* virtual address of pagetable */
- void *shadow_vtable; /* virtual address of shadow_table */
- root_pgentry_t *monitor_vtable; /* virtual address of monitor_table */
+ void *guest_vtable; /* virtual addr of pagetable */
+ root_pgentry_t *monitor_vtable; /* virtual addr of monitor_table */
/* Current LDT details. */
unsigned long shadow_ldt_mapcnt;
diff --git a/xen/include/asm-x86/hvm/io.h b/xen/include/asm-x86/hvm/io.h
index 8ec4747967..2e35ef79d9 100644
--- a/xen/include/asm-x86/hvm/io.h
+++ b/xen/include/asm-x86/hvm/io.h
@@ -25,11 +25,6 @@
#include <public/hvm/ioreq.h>
#include <public/event_channel.h>
-#define MAX_OPERAND_NUM 2
-
-#define mk_operand(size_reg, index, seg, flag) \
- (((size_reg) << 24) | ((index) << 16) | ((seg) << 8) | (flag))
-
#define operand_size(operand) \
((operand >> 24) & 0xFF)
@@ -70,29 +65,23 @@
#define INSTR_XCHG 14
#define INSTR_SUB 15
-struct instruction {
- __s8 instr; /* instruction type */
- __s16 op_size; /* the operand's bit size, e.g. 16-bit or 32-bit */
- __u64 immediate;
- __u16 seg_sel; /* segmentation selector */
- __u32 operand[MAX_OPERAND_NUM]; /* order is AT&T assembly */
- __u32 flags;
-};
-
#define MAX_INST_LEN 15 /* Maximum instruction length = 15 bytes */
struct hvm_io_op {
- int flags;
- int instr; /* instruction */
- unsigned long operand[2]; /* operands */
- unsigned long immediate; /* immediate portion */
- struct cpu_user_regs io_context; /* current context */
+ unsigned int instr; /* instruction */
+ unsigned int flags;
+ unsigned long addr; /* virt addr for overlap PIO/MMIO */
+ struct {
+ unsigned int operand[2]; /* operands */
+ unsigned long immediate; /* immediate portion */
+ };
+ struct cpu_user_regs io_context; /* current context */
};
#define MAX_IO_HANDLER 8
-#define VMX_PORTIO 0
-#define VMX_MMIO 1
+#define HVM_PORTIO 0
+#define HVM_MMIO 1
typedef int (*intercept_action_t)(ioreq_t *);
typedef unsigned long (*hvm_mmio_read_t)(struct vcpu *v,
@@ -131,16 +120,17 @@ extern int register_io_handler(unsigned long addr, unsigned long size,
static inline int hvm_portio_intercept(ioreq_t *p)
{
- return hvm_io_intercept(p, VMX_PORTIO);
+ return hvm_io_intercept(p, HVM_PORTIO);
}
-int hvm_mmio_intercept(ioreq_t *p);
+extern int hvm_mmio_intercept(ioreq_t *p);
+extern int hvm_buffered_io_intercept(ioreq_t *p);
static inline int register_portio_handler(unsigned long addr,
unsigned long size,
intercept_action_t action)
{
- return register_io_handler(addr, size, action, VMX_PORTIO);
+ return register_io_handler(addr, size, action, HVM_PORTIO);
}
#if defined(__i386__) || defined(__x86_64__)
@@ -150,7 +140,9 @@ static inline int irq_masked(unsigned long eflags)
}
#endif
-extern void handle_mmio(unsigned long, unsigned long);
+extern void send_pio_req(unsigned long port, unsigned long count, int size,
+ long value, int dir, int df, int pvalid);
+extern void handle_mmio(unsigned long gpa);
extern void hvm_interrupt_post(struct vcpu *v, int vector, int type);
extern void hvm_io_assist(struct vcpu *v);
extern void pic_irq_request(void *data, int level);
diff --git a/xen/include/asm-x86/hvm/support.h b/xen/include/asm-x86/hvm/support.h
index f68b046087..1c557c228f 100644
--- a/xen/include/asm-x86/hvm/support.h
+++ b/xen/include/asm-x86/hvm/support.h
@@ -142,17 +142,11 @@ int hvm_copy_to_guest_virt(unsigned long vaddr, void *buf, int size);
int hvm_copy_from_guest_virt(void *buf, unsigned long vaddr, int size);
void hvm_setup_platform(struct domain* d);
-int hvm_mmio_intercept(ioreq_t *p);
-int hvm_io_intercept(ioreq_t *p, int type);
-int hvm_buffered_io_intercept(ioreq_t *p);
-void hvm_hooks_assist(struct vcpu *v);
void hvm_print_line(struct vcpu *v, const char c);
void hlt_timer_fn(void *data);
void hvm_do_hypercall(struct cpu_user_regs *pregs);
-void hvm_prod_vcpu(struct vcpu *v);
-
void hvm_hlt(unsigned long rflags);
#endif /* __ASM_X86_HVM_SUPPORT_H__ */
diff --git a/xen/include/asm-x86/hvm/svm/vmcb.h b/xen/include/asm-x86/hvm/svm/vmcb.h
index 0f73f0c975..5ac5de3a9a 100644
--- a/xen/include/asm-x86/hvm/svm/vmcb.h
+++ b/xen/include/asm-x86/hvm/svm/vmcb.h
@@ -484,6 +484,7 @@ struct arch_svm_struct {
u32 *msrpm;
u64 vmexit_tsc; /* tsc read at #VMEXIT. for TSC_OFFSET */
int saved_irq_vector;
+ u32 inject_event;
u32 launch_core;
u32 asid_core;
diff --git a/xen/include/asm-x86/hvm/vcpu.h b/xen/include/asm-x86/hvm/vcpu.h
index b607a4578b..f613ae6a09 100644
--- a/xen/include/asm-x86/hvm/vcpu.h
+++ b/xen/include/asm-x86/hvm/vcpu.h
@@ -41,11 +41,6 @@ struct hvm_vcpu {
int xen_port;
-#if CONFIG_PAGING_LEVELS >= 3
- l3_pgentry_t hvm_lowmem_l3tab[4]
- __attribute__((__aligned__(32)));
-#endif
-
/* Flags */
int flag_dr_dirty;
diff --git a/xen/include/asm-x86/hvm/vpic.h b/xen/include/asm-x86/hvm/vpic.h
index f6a488e339..8e2d386e59 100644
--- a/xen/include/asm-x86/hvm/vpic.h
+++ b/xen/include/asm-x86/hvm/vpic.h
@@ -75,7 +75,7 @@ void pic_update_irq(struct hvm_virpic *s); /* Caller must hold s->lock */
uint32_t pic_intack_read(struct hvm_virpic *s);
void register_pic_io_hook (void);
int cpu_get_pic_interrupt(struct vcpu *v, int *type);
-int is_pit_irq(struct vcpu *v, int irq, int type);
+int is_periodic_irq(struct vcpu *v, int irq, int type);
int is_irq_enabled(struct vcpu *v, int irq);
void do_pic_irqs (struct hvm_virpic *s, uint16_t irqs);
void do_pic_irqs_clear (struct hvm_virpic *s, uint16_t irqs);
diff --git a/xen/include/asm-x86/hvm/vpit.h b/xen/include/asm-x86/hvm/vpit.h
index eb3ccd1207..83b1af2622 100644
--- a/xen/include/asm-x86/hvm/vpit.h
+++ b/xen/include/asm-x86/hvm/vpit.h
@@ -25,11 +25,12 @@
#include <xen/lib.h>
#include <xen/time.h>
#include <xen/errno.h>
+#include <xen/time.h>
#include <xen/timer.h>
#include <asm/hvm/vpic.h>
#define PIT_FREQ 1193181
-#define PIT_BASE 0x40
+#define PIT_BASE 0x40
typedef struct PITChannelState {
int count; /* can be 65536 */
@@ -49,10 +50,32 @@ typedef struct PITChannelState {
struct vcpu *vcpu;
struct periodic_time *pt;
} PITChannelState;
+
+typedef struct PITState {
+ PITChannelState channels[3];
+ int speaker_data_on;
+ int dummy_refresh_clock;
+} PITState;
+
+#define RTC_SIZE 14
+typedef struct RTCState {
+ uint8_t cmos_data[RTC_SIZE]; /* Only handle time/interrupt part in HV */
+ uint8_t cmos_index;
+ struct tm current_tm;
+ int irq;
+ /* second update */
+ int64_t next_second_time;
+ struct timer second_timer;
+ struct timer second_timer2;
+ struct vcpu *vcpu;
+ struct periodic_time *pt;
+} RTCState;
/*
* Abstract layer of periodic time, one short time.
*/
+typedef void time_cb(struct vcpu *v, void *opaque);
+
struct periodic_time {
char enabled; /* enabled */
char one_shot; /* one shot time */
@@ -64,19 +87,15 @@ struct periodic_time {
s_time_t scheduled; /* scheduled timer interrupt */
u64 last_plt_gtime; /* platform time when last IRQ is injected */
struct timer timer; /* ac_timer */
+ time_cb *cb;
void *priv; /* ponit back to platform time source */
};
-typedef struct PITState {
- PITChannelState channels[3];
- int speaker_data_on;
- int dummy_refresh_clock;
-} PITState;
-
struct pl_time { /* platform time */
struct periodic_time periodic_tm;
struct PITState vpit;
- /* TODO: RTC/ACPI time */
+ struct RTCState vrtc;
+ /* TODO: ACPI time */
};
static __inline__ s_time_t get_scheduled(
@@ -90,13 +109,30 @@ static __inline__ s_time_t get_scheduled(
return -1;
}
+extern u64 hvm_get_guest_time(struct vcpu *v);
+/*
+ * get processor time.
+ * unit: TSC
+ */
+static __inline__ int64_t hvm_get_clock(struct vcpu *v)
+{
+ uint64_t gtsc;
+
+ gtsc = hvm_get_guest_time(v);
+ return gtsc;
+}
+
+#define ticks_per_sec(v) (v->domain->arch.hvm_domain.tsc_frequency)
+
/* to hook the ioreq packet to get the PIT initialization info */
extern void hvm_hooks_assist(struct vcpu *v);
extern void pickup_deactive_ticks(struct periodic_time *vpit);
-extern u64 hvm_get_guest_time(struct vcpu *v);
-extern struct periodic_time *create_periodic_time(PITChannelState *v, u32 period, char irq, char one_shot);
+extern struct periodic_time *create_periodic_time(u32 period, char irq, char one_shot, time_cb *cb, void *data);
extern void destroy_periodic_time(struct periodic_time *pt);
void pit_init(struct vcpu *v, unsigned long cpu_khz);
+void rtc_init(struct vcpu *v, int base, int irq);
+void rtc_deinit(struct domain *d);
+int is_rtc_periodic_irq(void *opaque);
void pt_timer_fn(void *data);
void pit_time_fired(struct vcpu *v, void *priv);
diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h
index dd85519c12..389366a7ba 100644
--- a/xen/include/asm-x86/mm.h
+++ b/xen/include/asm-x86/mm.h
@@ -114,15 +114,14 @@ struct page_info
#define PGC_SH_fl1_pae_shadow (5U<<28) /* L1 shadow for pae 2M superpg */
#define PGC_SH_l2_pae_shadow (6U<<28) /* shadowing a pae L2-low page */
#define PGC_SH_l2h_pae_shadow (7U<<28) /* shadowing a pae L2-high page */
-#define PGC_SH_l3_pae_shadow (8U<<28) /* shadowing a pae L3 page */
-#define PGC_SH_l1_64_shadow (9U<<28) /* shadowing a 64-bit L1 page */
-#define PGC_SH_fl1_64_shadow (10U<<28) /* L1 shadow for 64-bit 2M superpg */
-#define PGC_SH_l2_64_shadow (11U<<28) /* shadowing a 64-bit L2 page */
-#define PGC_SH_l3_64_shadow (12U<<28) /* shadowing a 64-bit L3 page */
-#define PGC_SH_l4_64_shadow (13U<<28) /* shadowing a 64-bit L4 page */
-#define PGC_SH_max_shadow (13U<<28)
-#define PGC_SH_p2m_table (14U<<28) /* in use as the p2m table */
-#define PGC_SH_monitor_table (15U<<28) /* in use as a monitor table */
+#define PGC_SH_l1_64_shadow (8U<<28) /* shadowing a 64-bit L1 page */
+#define PGC_SH_fl1_64_shadow (9U<<28) /* L1 shadow for 64-bit 2M superpg */
+#define PGC_SH_l2_64_shadow (10U<<28) /* shadowing a 64-bit L2 page */
+#define PGC_SH_l3_64_shadow (11U<<28) /* shadowing a 64-bit L3 page */
+#define PGC_SH_l4_64_shadow (12U<<28) /* shadowing a 64-bit L4 page */
+#define PGC_SH_max_shadow (12U<<28)
+#define PGC_SH_p2m_table (13U<<28) /* in use as the p2m table */
+#define PGC_SH_monitor_table (14U<<28) /* in use as a monitor table */
#define PGC_SH_unused (15U<<28)
#define PGC_SH_type_mask (15U<<28)
diff --git a/xen/include/asm-x86/perfc_defn.h b/xen/include/asm-x86/perfc_defn.h
index 76801f5da5..7204348fca 100644
--- a/xen/include/asm-x86/perfc_defn.h
+++ b/xen/include/asm-x86/perfc_defn.h
@@ -71,11 +71,11 @@ PERFCOUNTER_CPU(shadow_writeable_h_1, "shadow writeable: 32b w2k3")
PERFCOUNTER_CPU(shadow_writeable_h_2, "shadow writeable: 32pae w2k3")
PERFCOUNTER_CPU(shadow_writeable_h_3, "shadow writeable: 64b w2k3")
PERFCOUNTER_CPU(shadow_writeable_h_4, "shadow writeable: 32b linux low")
+PERFCOUNTER_CPU(shadow_writeable_h_5, "shadow writeable: 32b linux high")
PERFCOUNTER_CPU(shadow_writeable_bf, "shadow writeable brute-force")
PERFCOUNTER_CPU(shadow_mappings, "shadow removes all mappings")
PERFCOUNTER_CPU(shadow_mappings_bf, "shadow rm-mappings brute-force")
PERFCOUNTER_CPU(shadow_early_unshadow, "shadow unshadows for fork/exit")
-PERFCOUNTER_CPU(shadow_early_unshadow_top, "shadow unhooks for fork/exit")
PERFCOUNTER_CPU(shadow_unshadow, "shadow unshadows a page")
PERFCOUNTER_CPU(shadow_up_pointer, "shadow unshadow by up-pointer")
PERFCOUNTER_CPU(shadow_unshadow_bf, "shadow unshadow brute-force")
diff --git a/xen/include/asm-x86/shadow.h b/xen/include/asm-x86/shadow.h
index 98dcc140b9..27cf6843eb 100644
--- a/xen/include/asm-x86/shadow.h
+++ b/xen/include/asm-x86/shadow.h
@@ -72,7 +72,6 @@
#define SHADOW_SET_CHANGED 0x1
#define SHADOW_SET_FLUSH 0x2
#define SHADOW_SET_ERROR 0x4
-#define SHADOW_SET_L3PAE_RECOPY 0x8
// How do we tell that we have a 32-bit PV guest in a 64-bit Xen?
#ifdef __x86_64__
@@ -406,7 +405,6 @@ shadow_update_cr3(struct vcpu *v)
* for HVM guests, arch.monitor_table and hvm's guest CR3.
*
* Update ref counts to shadow tables appropriately.
- * For PAE, relocate L3 entries, if necessary, into low memory.
*/
static inline void update_cr3(struct vcpu *v)
{
@@ -549,13 +547,13 @@ shadow_remove_all_shadows_and_parents(struct vcpu *v, mfn_t gmfn);
* Unshadow it, and recursively unshadow pages that reference it. */
/* Remove all shadows of the guest mfn. */
-extern void sh_remove_shadows(struct vcpu *v, mfn_t gmfn, int all);
+extern void sh_remove_shadows(struct vcpu *v, mfn_t gmfn, int fast, int all);
static inline void shadow_remove_all_shadows(struct vcpu *v, mfn_t gmfn)
{
int was_locked = shadow_lock_is_acquired(v->domain);
if ( !was_locked )
shadow_lock(v->domain);
- sh_remove_shadows(v, gmfn, 1);
+ sh_remove_shadows(v, gmfn, 0, 1);
if ( !was_locked )
shadow_unlock(v->domain);
}
@@ -587,7 +585,6 @@ shadow_guest_physmap_remove_page(struct domain *d, unsigned long gfn,
#define SHF_FL1_PAE (1u << PGC_SH_type_to_index(PGC_SH_fl1_pae_shadow))
#define SHF_L2_PAE (1u << PGC_SH_type_to_index(PGC_SH_l2_pae_shadow))
#define SHF_L2H_PAE (1u << PGC_SH_type_to_index(PGC_SH_l2h_pae_shadow))
-#define SHF_L3_PAE (1u << PGC_SH_type_to_index(PGC_SH_l3_pae_shadow))
#define SHF_L1_64 (1u << PGC_SH_type_to_index(PGC_SH_l1_64_shadow))
#define SHF_FL1_64 (1u << PGC_SH_type_to_index(PGC_SH_fl1_64_shadow))
#define SHF_L2_64 (1u << PGC_SH_type_to_index(PGC_SH_l2_64_shadow))
diff --git a/xen/include/asm-x86/spinlock.h b/xen/include/asm-x86/spinlock.h
index 1d864188da..8c148e0240 100644
--- a/xen/include/asm-x86/spinlock.h
+++ b/xen/include/asm-x86/spinlock.h
@@ -12,9 +12,9 @@ typedef struct {
u8 recurse_cnt;
} spinlock_t;
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { 1, -1, 0 }
+#define SPIN_LOCK_UNLOCKED /*(spinlock_t)*/ { 1, -1, 0 }
-#define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
+#define spin_lock_init(x) do { *(x) = (spinlock_t) SPIN_LOCK_UNLOCKED; } while(0)
#define spin_is_locked(x) (*(volatile char *)(&(x)->lock) <= 0)
static inline void _raw_spin_lock(spinlock_t *lock)
@@ -89,9 +89,9 @@ typedef struct {
volatile unsigned int lock;
} rwlock_t;
-#define RW_LOCK_UNLOCKED (rwlock_t) { RW_LOCK_BIAS }
+#define RW_LOCK_UNLOCKED /*(rwlock_t)*/ { RW_LOCK_BIAS }
-#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0)
+#define rwlock_init(x) do { *(x) = (rwlock_t) RW_LOCK_UNLOCKED; } while(0)
/*
* On x86, we implement read-write locks as a 32-bit counter
diff --git a/xen/include/asm-x86/x86_64/asm_defns.h b/xen/include/asm-x86/x86_64/asm_defns.h
index 699e81b4f0..05f708adaf 100644
--- a/xen/include/asm-x86/x86_64/asm_defns.h
+++ b/xen/include/asm-x86/x86_64/asm_defns.h
@@ -60,6 +60,12 @@
#define safe_swapgs \
"mfence; swapgs;"
+#ifdef __sun__
+#define REX64_PREFIX "rex64\\"
+#else
+#define REX64_PREFIX "rex64/"
+#endif
+
#define BUILD_SMP_INTERRUPT(x,v) XBUILD_SMP_INTERRUPT(x,v)
#define XBUILD_SMP_INTERRUPT(x,v) \
asmlinkage void x(void); \
diff --git a/xen/include/public/io/ring.h b/xen/include/public/io/ring.h
index 6b56dc3211..d427ba6679 100644
--- a/xen/include/public/io/ring.h
+++ b/xen/include/public/io/ring.h
@@ -152,7 +152,7 @@ typedef struct __name##_back_ring __name##_back_ring_t
((_r)->nr_ents)
/* Number of free requests (for use on front side only). */
-#define RING_FREE_REQUESTS(_r) \
+#define RING_FREE_REQUESTS(_r) \
(RING_SIZE(_r) - ((_r)->req_prod_pvt - (_r)->rsp_cons))
/* Test if there is an empty slot available on the front ring.
@@ -165,13 +165,21 @@ typedef struct __name##_back_ring __name##_back_ring_t
#define RING_HAS_UNCONSUMED_RESPONSES(_r) \
((_r)->sring->rsp_prod - (_r)->rsp_cons)
+#ifdef __GNUC__
+#define RING_HAS_UNCONSUMED_REQUESTS(_r) ({ \
+ unsigned int req = (_r)->sring->req_prod - (_r)->req_cons; \
+ unsigned int rsp = RING_SIZE(_r) - \
+ ((_r)->req_cons - (_r)->rsp_prod_pvt); \
+ req < rsp ? req : rsp; \
+})
+#else
+/* Same as above, but without the nice GCC ({ ... }) syntax. */
#define RING_HAS_UNCONSUMED_REQUESTS(_r) \
- ({ \
- unsigned int req = (_r)->sring->req_prod - (_r)->req_cons; \
- unsigned int rsp = RING_SIZE(_r) - \
- ((_r)->req_cons - (_r)->rsp_prod_pvt); \
- req < rsp ? req : rsp; \
- })
+ ((((_r)->sring->req_prod - (_r)->req_cons) < \
+ (RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt))) ? \
+ ((_r)->sring->req_prod - (_r)->req_cons) : \
+ (RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt)))
+#endif
/* Direct access to individual ring elements, by index. */
#define RING_GET_REQUEST(_r, _idx) \
diff --git a/xen/include/public/trace.h b/xen/include/public/trace.h
index 4cb73386c3..328160cb9e 100644
--- a/xen/include/public/trace.h
+++ b/xen/include/public/trace.h
@@ -19,11 +19,11 @@
/* Trace subclasses */
#define TRC_SUBCLS_SHIFT 12
+
/* trace subclasses for VMX */
#define TRC_VMXEXIT 0x00081000 /* VMX exit trace */
-#define TRC_VMXTIMER 0x00082000 /* VMX timer trace */
-#define TRC_VMXINT 0x00084000 /* VMX interrupt trace */
-#define TRC_VMXIO 0x00088000 /* VMX io emulation trace */
+#define TRC_VMXENTRY 0x00082000 /* VMX exit trace */
+#define TRC_VMXINTR 0x00084000 /* VMX interrupt trace */
/* Trace events per class */
#define TRC_LOST_RECORDS (TRC_GEN + 1)
@@ -50,11 +50,8 @@
/* trace events per subclass */
#define TRC_VMX_VMEXIT (TRC_VMXEXIT + 1)
-#define TRC_VMX_VMENTRY (TRC_VMXEXIT + 2)
-
-#define TRC_VMX_TIMER_INTR (TRC_VMXTIMER + 1)
-
-#define TRC_VMX_INT (TRC_VMXINT + 1)
+#define TRC_VMX_VMENTRY (TRC_VMXENTRY + 1)
+#define TRC_VMX_INTR (TRC_VMXINTR + 1)
/* This structure represents a single trace buffer record. */
diff --git a/xen/include/xen/cpumask.h b/xen/include/xen/cpumask.h
index 997efb1d45..d9296201cb 100644
--- a/xen/include/xen/cpumask.h
+++ b/xen/include/xen/cpumask.h
@@ -239,14 +239,14 @@ static inline int __next_cpu(int n, const cpumask_t *srcp, int nbits)
#if NR_CPUS <= BITS_PER_LONG
#define CPU_MASK_ALL \
-(cpumask_t) { { \
+/*(cpumask_t)*/ { { \
[BITS_TO_LONGS(NR_CPUS)-1] = CPU_MASK_LAST_WORD \
} }
#else
#define CPU_MASK_ALL \
-(cpumask_t) { { \
+/*(cpumask_t)*/ { { \
[0 ... BITS_TO_LONGS(NR_CPUS)-2] = ~0UL, \
[BITS_TO_LONGS(NR_CPUS)-1] = CPU_MASK_LAST_WORD \
} }
@@ -254,12 +254,12 @@ static inline int __next_cpu(int n, const cpumask_t *srcp, int nbits)
#endif
#define CPU_MASK_NONE \
-(cpumask_t) { { \
+/*(cpumask_t)*/ { { \
[0 ... BITS_TO_LONGS(NR_CPUS)-1] = 0UL \
} }
#define CPU_MASK_CPU0 \
-(cpumask_t) { { \
+/*(cpumask_t)*/ { { \
[0] = 1UL \
} }
diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h
index e421c8442d..40103e7df5 100644
--- a/xen/include/xen/domain.h
+++ b/xen/include/xen/domain.h
@@ -29,6 +29,8 @@ void domain_relinquish_resources(struct domain *d);
void dump_pageframe_info(struct domain *d);
+void arch_dump_vcpu_info(struct vcpu *v);
+
void arch_dump_domain_info(struct domain *d);
#endif /* __XEN_DOMAIN_H__ */
diff --git a/xen/include/xen/lib.h b/xen/include/xen/lib.h
index 00bb0830e9..52509addd4 100644
--- a/xen/include/xen/lib.h
+++ b/xen/include/xen/lib.h
@@ -2,7 +2,7 @@
#define __LIB_H__
#include <xen/inttypes.h>
-#include <stdarg.h>
+#include <xen/stdarg.h>
#include <xen/config.h>
#include <xen/types.h>
#include <xen/xmalloc.h>
diff --git a/xen/include/xen/spinlock.h b/xen/include/xen/spinlock.h
index 73184daad8..11f83119d4 100644
--- a/xen/include/xen/spinlock.h
+++ b/xen/include/xen/spinlock.h
@@ -42,10 +42,10 @@
#if (__GNUC__ > 2)
typedef struct { } spinlock_t;
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { }
+#define SPIN_LOCK_UNLOCKED /*(spinlock_t)*/ { }
#else
typedef struct { int gcc_is_buggy; } spinlock_t;
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
+#define SPIN_LOCK_UNLOCKED /*(spinlock_t)*/ { 0 }
#endif
#define spin_lock_init(lock) do { } while(0)
@@ -58,10 +58,10 @@ typedef struct { int gcc_is_buggy; } spinlock_t;
#if (__GNUC__ > 2)
typedef struct { } rwlock_t;
-#define RW_LOCK_UNLOCKED (rwlock_t) { }
+#define RW_LOCK_UNLOCKED /*(rwlock_t)*/ { }
#else
typedef struct { int gcc_is_buggy; } rwlock_t;
-#define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
+#define RW_LOCK_UNLOCKED /*(rwlock_t)*/ { 0 }
#endif
#define rwlock_init(lock) do { } while(0)
diff --git a/xen/include/xen/stdarg.h b/xen/include/xen/stdarg.h
new file mode 100644
index 0000000000..9508bc4df4
--- /dev/null
+++ b/xen/include/xen/stdarg.h
@@ -0,0 +1,5 @@
+#if defined(__OpenBSD__)
+# include "/usr/include/stdarg.h"
+#else
+# include <stdarg.h>
+#endif
diff --git a/xen/include/xen/time.h b/xen/include/xen/time.h
index 931401388e..33b12763ed 100644
--- a/xen/include/xen/time.h
+++ b/xen/include/xen/time.h
@@ -49,6 +49,20 @@ struct domain;
typedef s64 s_time_t;
s_time_t get_s_time(void);
+unsigned long get_localtime(struct domain *d);
+
+struct tm {
+ int tm_sec; /* seconds */
+ int tm_min; /* minutes */
+ int tm_hour; /* hours */
+ int tm_mday; /* day of the month */
+ int tm_mon; /* month */
+ int tm_year; /* year */
+ int tm_wday; /* day of the week */
+ int tm_yday; /* day in the year */
+ int tm_isdst; /* daylight saving time */
+};
+struct tm gmtime(unsigned long t);
#define NOW() ((s_time_t)get_s_time())
#define SECONDS(_s) ((s_time_t)((_s) * 1000000000ULL))