aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.hgignore11
-rw-r--r--buildconfigs/enable-xen-config10
-rw-r--r--buildconfigs/mk.linux-2.6-common26
-rwxr-xr-xbuildconfigs/select-linux-arch30
-rwxr-xr-xbuildconfigs/select-linux-image33
-rw-r--r--config/MiniOS.mk9
-rw-r--r--config/StdGNU.mk1
-rw-r--r--config/SunOS.mk1
-rw-r--r--docs/misc/xenstore.txt10
-rw-r--r--docs/xen-api/revision-history.tex7
-rw-r--r--docs/xen-api/xenapi-coversheet.tex2
-rw-r--r--docs/xen-api/xenapi.tex5
-rw-r--r--extras/mini-os/Config.mk76
-rw-r--r--extras/mini-os/Makefile81
-rw-r--r--extras/mini-os/arch/ia64/Makefile4
-rw-r--r--extras/mini-os/arch/ia64/minios-ia64.lds12
-rw-r--r--extras/mini-os/arch/ia64/mm.c8
-rw-r--r--extras/mini-os/arch/x86/Makefile3
-rw-r--r--extras/mini-os/arch/x86/arch.mk8
-rw-r--r--extras/mini-os/arch/x86/minios-x86_32.lds12
-rw-r--r--extras/mini-os/arch/x86/minios-x86_64.lds12
-rw-r--r--extras/mini-os/arch/x86/mm.c17
-rw-r--r--extras/mini-os/arch/x86/x86_32.S6
-rw-r--r--extras/mini-os/arch/x86/x86_64.S6
-rw-r--r--extras/mini-os/blkfront.c56
-rw-r--r--extras/mini-os/include/arch/cc.h7
-rw-r--r--extras/mini-os/include/byteswap.h22
-rw-r--r--extras/mini-os/include/console.h3
-rw-r--r--extras/mini-os/include/errno.h7
-rw-r--r--extras/mini-os/include/fcntl.h3
-rw-r--r--extras/mini-os/include/fs.h1
-rw-r--r--extras/mini-os/include/ia64/arch_limits.h12
-rw-r--r--extras/mini-os/include/ia64/arch_mm.h4
-rw-r--r--extras/mini-os/include/ia64/page.h6
-rw-r--r--extras/mini-os/include/lib.h59
-rw-r--r--extras/mini-os/include/linux/types.h5
-rw-r--r--extras/mini-os/include/mm.h8
-rw-r--r--extras/mini-os/include/netfront.h4
-rw-r--r--extras/mini-os/include/posix/dirent.h24
-rw-r--r--extras/mini-os/include/posix/limits.h9
-rw-r--r--extras/mini-os/include/posix/netdb.h9
-rw-r--r--extras/mini-os/include/posix/netinet/in.h7
-rw-r--r--extras/mini-os/include/posix/netinet/tcp.h6
-rw-r--r--extras/mini-os/include/posix/pthread.h19
-rw-r--r--extras/mini-os/include/posix/stdlib.h8
-rw-r--r--extras/mini-os/include/posix/strings.h8
-rw-r--r--extras/mini-os/include/posix/sys/ioctl.h16
-rw-r--r--extras/mini-os/include/posix/sys/mman.h19
-rw-r--r--extras/mini-os/include/posix/sys/select.h7
-rw-r--r--extras/mini-os/include/posix/sys/socket.h31
-rw-r--r--extras/mini-os/include/posix/termios.h87
-rw-r--r--extras/mini-os/include/posix/time.h10
-rw-r--r--extras/mini-os/include/posix/unistd.h12
-rw-r--r--extras/mini-os/include/sched.h3
-rw-r--r--extras/mini-os/include/sys/time.h4
-rw-r--r--extras/mini-os/include/time.h11
-rw-r--r--extras/mini-os/include/x86/arch_limits.h20
-rw-r--r--extras/mini-os/include/x86/arch_mm.h22
-rw-r--r--extras/mini-os/include/x86/arch_sched.h4
-rw-r--r--extras/mini-os/include/x86/arch_spinlock.h1
-rw-r--r--extras/mini-os/include/x86/os.h1
-rw-r--r--extras/mini-os/lib/sys.c1083
-rw-r--r--extras/mini-os/lib/xmalloc.c17
-rw-r--r--extras/mini-os/lib/xs.c187
-rw-r--r--extras/mini-os/main-caml.c42
-rw-r--r--extras/mini-os/main.c167
-rw-r--r--extras/mini-os/minios.mk13
-rw-r--r--extras/mini-os/mm.c23
-rw-r--r--extras/mini-os/netfront.c98
-rw-r--r--extras/mini-os/sched.c44
-rw-r--r--stubdom/Makefile259
-rw-r--r--stubdom/README41
-rw-r--r--stubdom/binutils.patch14
-rw-r--r--stubdom/caml/Makefile18
-rw-r--r--stubdom/caml/hello.ml4
-rw-r--r--stubdom/gcc.patch31
-rw-r--r--stubdom/libpci.config.h5
-rw-r--r--stubdom/libpci.config.mak2
-rw-r--r--stubdom/newlib.patch203
-rw-r--r--stubdom/stubdom-dm97
-rw-r--r--tools/blktap/drivers/tapdisk.c2
-rw-r--r--tools/console/daemon/io.c98
-rw-r--r--tools/console/daemon/main.c20
-rw-r--r--tools/firmware/hvmloader/acpi/build.c18
-rw-r--r--tools/firmware/hvmloader/acpi/dsdt.asl8
-rw-r--r--tools/firmware/hvmloader/acpi/dsdt.c896
-rw-r--r--tools/fs-back/fs-backend.c4
-rw-r--r--tools/ioemu/Makefile.target43
-rw-r--r--tools/ioemu/aes.c2
-rw-r--r--tools/ioemu/block-raw.c33
-rw-r--r--tools/ioemu/block-vbd.c345
-rw-r--r--tools/ioemu/block.c3
-rwxr-xr-xtools/ioemu/configure22
-rw-r--r--tools/ioemu/console.c6
-rw-r--r--tools/ioemu/cpu-all.h10
-rw-r--r--tools/ioemu/exec-all.h4
-rw-r--r--tools/ioemu/hw/fdc.c7
-rw-r--r--tools/ioemu/hw/ide.c4
-rw-r--r--tools/ioemu/hw/pc.c11
-rw-r--r--tools/ioemu/hw/scsi-disk.c8
-rw-r--r--tools/ioemu/hw/usb-hid.c68
-rw-r--r--tools/ioemu/hw/vga.c14
-rw-r--r--tools/ioemu/hw/xen_console.c8
-rw-r--r--tools/ioemu/hw/xen_machine_fv.c3
-rw-r--r--tools/ioemu/hw/xenfb.c8
-rw-r--r--tools/ioemu/osdep.c20
-rw-r--r--tools/ioemu/osdep.h1
-rw-r--r--tools/ioemu/sdl.c30
-rw-r--r--tools/ioemu/target-i386-dm/cpu.h4
-rw-r--r--tools/ioemu/target-i386-dm/helper2.c6
-rw-r--r--tools/ioemu/vl.c161
-rw-r--r--tools/ioemu/vl.h6
-rw-r--r--tools/ioemu/vnc.c360
-rw-r--r--tools/ioemu/vnchextile.h12
-rw-r--r--tools/ioemu/xenstore.c19
-rw-r--r--tools/libxc/Makefile17
-rw-r--r--tools/libxc/ia64/Makefile2
-rw-r--r--tools/libxc/xc_domain.c15
-rw-r--r--tools/libxc/xc_domain_restore.c12
-rw-r--r--tools/libxc/xc_domain_save.c48
-rw-r--r--tools/libxc/xc_minios.c313
-rw-r--r--tools/libxc/xenctrl.h28
-rw-r--r--tools/libxc/xg_private.h4
-rw-r--r--tools/libxc/xg_save_restore.h17
-rw-r--r--tools/python/xen/lowlevel/xc/xc.c28
-rw-r--r--tools/python/xen/xend/XendConfig.py12
-rw-r--r--tools/python/xen/xend/XendConstants.py1
-rw-r--r--tools/python/xen/xend/XendDomainInfo.py12
-rw-r--r--tools/python/xen/xend/XendPBD.py22
-rw-r--r--tools/python/xen/xend/image.py31
-rw-r--r--tools/python/xen/xm/create.py6
-rw-r--r--tools/python/xen/xm/xenapi_create.py3
-rw-r--r--tools/xenmon/xenbaked.c4
-rw-r--r--tools/xenstore/xenstored_domain.c8
-rw-r--r--tools/xentrace/xentrace.c157
-rw-r--r--unmodified_drivers/linux-2.6/platform-pci/Kbuild1
-rw-r--r--unmodified_drivers/linux-2.6/platform-pci/panic-handler.c54
-rw-r--r--unmodified_drivers/linux-2.6/platform-pci/platform-pci.c4
-rw-r--r--xen/arch/x86/boot/trampoline.S7
-rw-r--r--xen/arch/x86/cpu/mtrr/main.c2
-rw-r--r--xen/arch/x86/domain.c3
-rw-r--r--xen/arch/x86/domctl.c8
-rw-r--r--xen/arch/x86/hvm/Makefile1
-rw-r--r--xen/arch/x86/hvm/hpet.c3
-rw-r--r--xen/arch/x86/hvm/hvm.c146
-rw-r--r--xen/arch/x86/hvm/iommu.c135
-rw-r--r--xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-detect.c2
-rw-r--r--xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-map.c331
-rw-r--r--xen/arch/x86/hvm/svm/amd_iommu/pci-amd-iommu.c316
-rw-r--r--xen/arch/x86/hvm/svm/intr.c41
-rw-r--r--xen/arch/x86/hvm/svm/svm.c98
-rw-r--r--xen/arch/x86/hvm/vioapic.c2
-rw-r--r--xen/arch/x86/hvm/vmx/realmode.c71
-rw-r--r--xen/arch/x86/hvm/vmx/vmx.c118
-rw-r--r--xen/arch/x86/hvm/vmx/vtd/Makefile1
-rw-r--r--xen/arch/x86/hvm/vmx/vtd/extern.h7
-rw-r--r--xen/arch/x86/hvm/vmx/vtd/intel-iommu.c44
-rw-r--r--xen/arch/x86/hvm/vmx/vtd/intremap.c340
-rw-r--r--xen/arch/x86/hvm/vmx/vtd/io.c53
-rw-r--r--xen/arch/x86/mm/p2m.c24
-rw-r--r--xen/arch/x86/mm/shadow/multi.c122
-rw-r--r--xen/arch/x86/smpboot.c28
-rw-r--r--xen/arch/x86/trace.c18
-rw-r--r--xen/arch/x86/x86_emulate.c32
-rw-r--r--xen/common/Makefile1
-rw-r--r--xen/common/stop_machine.c158
-rw-r--r--xen/common/trace.c94
-rw-r--r--xen/include/asm-x86/hvm/iommu.h3
-rw-r--r--xen/include/asm-x86/hvm/svm/amd-iommu-defs.h5
-rw-r--r--xen/include/asm-x86/hvm/svm/amd-iommu-proto.h18
-rw-r--r--xen/include/asm-x86/hvm/trace.h66
-rw-r--r--xen/include/asm-x86/hvm/vmx/intel-iommu.h8
-rw-r--r--xen/include/asm-x86/io_apic.h5
-rw-r--r--xen/include/asm-x86/iommu.h20
-rw-r--r--xen/include/asm-x86/smp.h3
-rw-r--r--xen/include/asm-x86/trace.h10
-rw-r--r--xen/include/public/hvm/params.h5
-rw-r--r--xen/include/public/io/ring.h24
-rw-r--r--xen/include/public/trace.h8
-rw-r--r--xen/include/public/xen-compat.h2
-rw-r--r--xen/include/xen/smp.h55
-rw-r--r--xen/include/xen/softirq.h3
-rw-r--r--xen/include/xen/stop_machine.h19
-rw-r--r--xen/include/xen/trace.h73
184 files changed, 7103 insertions, 1766 deletions
diff --git a/.hgignore b/.hgignore
index 4063f19caa..78f33293fa 100644
--- a/.hgignore
+++ b/.hgignore
@@ -80,6 +80,17 @@
^pristine-.*$
^ref-.*$
^tmp-.*$
+^stubdom/binutils-.*$
+^stubdom/cross-root-.*$
+^stubdom/gcc-.*$
+^stubdom/include$
+^stubdom/ioemu$
+^stubdom/libxc$
+^stubdom/lwip-.*$
+^stubdom/mini-os$
+^stubdom/newlib-.*$
+^stubdom/pciutils-.*$
+^stubdom/zlib-.*$
^tools/.*/TAGS$
^tools/.*/build/lib.*/.*\.py$
^tools/blktap/Makefile\.smh$
diff --git a/buildconfigs/enable-xen-config b/buildconfigs/enable-xen-config
index 1f9945faef..75f648eab6 100644
--- a/buildconfigs/enable-xen-config
+++ b/buildconfigs/enable-xen-config
@@ -1,6 +1,6 @@
#!/bin/sh
-set -ex
+set -e
if [ $# -ne 1 ] ; then
echo "Usage $(basename $0) <config-file>" 1>&2
@@ -26,6 +26,7 @@ setopt()
}
setopt CONFIG_PARAVIRT y
+setopt CONFIG_PARAVIRT_GUEST y
setopt CONFIG_XEN y
setopt CONFIG_VMI y
setopt CONFIG_KVM y
@@ -36,5 +37,12 @@ setopt CONFIG_XEN_BLKDEV_FRONTEND y
setopt CONFIG_XEN_NETDEV_FRONTEND y
setopt CONFIG_HVC_XEN y
setopt CONFIG_NUMA n
+setopt CONFIG_LOCALVERSION_AUTO n
+
+case ${XEN_TARGET_ARCH} in
+ x86_32) setopt CONFIG_64BIT n ;;
+ x86_64) setopt CONFIG_64BIT y ;;
+ *) ;;
+esac
exit 0
diff --git a/buildconfigs/mk.linux-2.6-common b/buildconfigs/mk.linux-2.6-common
index 35150591b5..024d55f680 100644
--- a/buildconfigs/mk.linux-2.6-common
+++ b/buildconfigs/mk.linux-2.6-common
@@ -14,22 +14,15 @@ else
__XEN_LINUX_UPDATE =
endif
-# Let XEN_TARGET_ARCH override ARCH.
-ifeq ($(XEN_TARGET_ARCH),x86_32)
-LINUX_ARCH ?= i386
+ifeq ($(XEN_LINUX_NONINTERACTIVE_CONFIG),y)
+__NONINT_CONFIG = yes $$'\n' |
else
-LINUX_ARCH ?= $(XEN_TARGET_ARCH)
+__NONINT_CONFIG =
endif
LINUX_DIR = build-linux-$(LINUX_VER)$(EXTRAVERSION)_$(XEN_TARGET_ARCH)
IMAGE_TARGET ?= vmlinuz
-ifneq ($(XEN_TARGET_ARCH),ia64)
-IMAGE_PATH ?= arch/$(LINUX_ARCH)/boot/$(firstword $(IMAGE_TARGET))
-else
-IMAGE_PATH ?= arch/ia64/hp/sim/boot/vmlinux.gz
-endif
-INSTALL_BOOT_PATH := $(DESTDIR)/boot
LINUX_VER3 := $(LINUX_SERIES).$(word 3, $(subst ., ,$(LINUX_VER)))
@@ -38,6 +31,11 @@ _build: build
include buildconfigs/src.$(XEN_LINUX_SOURCE)
+LINUX_ARCH = $$(sh buildconfigs/select-linux-arch $(LINUX_SRCDIR))
+IMAGE_PATH = $$(sh buildconfigs/select-linux-image $(LINUX_DIR) $(LINUX_ARCH) $(IMAGE_TARGET))
+
+INSTALL_BOOT_PATH := $(DESTDIR)/boot
+
# Default to allowing interface mismatch
ifndef XEN_LINUX_ALLOW_INTERFACE_MISMATCH
XEN_LINUX_ALLOW_INTERFACE_MISMATCH := y
@@ -64,9 +62,9 @@ endif
fi
$(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) INSTALL_PATH=$(DESTDIR) $(IMAGE_TARGET)
mkdir -p $(INSTALL_BOOT_PATH)
- cp $(LINUX_DIR)/$(IMAGE_PATH) $(INSTALL_BOOT_PATH)/vmlinuz-$(KERNELRELEASE)
- cp $(LINUX_DIR)/.config $(INSTALL_BOOT_PATH)/config-$(KERNELRELEASE)
- cp $(LINUX_DIR)/System.map $(INSTALL_BOOT_PATH)/System.map-$(KERNELRELEASE)
+ @cp -v $(IMAGE_PATH) $(INSTALL_BOOT_PATH)/vmlinuz-$(KERNELRELEASE)
+ @cp -v $(LINUX_DIR)/.config $(INSTALL_BOOT_PATH)/config-$(KERNELRELEASE)
+ @cp -v $(LINUX_DIR)/System.map $(INSTALL_BOOT_PATH)/System.map-$(KERNELRELEASE)
$(LINUX_DIR)/include/linux/autoconf.h: CONFIG_FILE=$(CURDIR)/$(LINUX_DIR)/.config
$(LINUX_DIR)/include/linux/autoconf.h: $(LINUX_SRCDIR)/.valid-src
@@ -102,7 +100,7 @@ endif
ifneq ($(EXTRAVERSION),)
echo "$(EXTRAVERSION)" >$(LINUX_DIR)/localversion-xen
endif
- $(MAKE) -C $(LINUX_SRCDIR) ARCH=$(LINUX_ARCH) oldconfig O=$$(/bin/pwd)/$(LINUX_DIR)
+ $(__NONINT_CONFIG) $(MAKE) -C $(LINUX_SRCDIR) ARCH=$(LINUX_ARCH) oldconfig O=$$(/bin/pwd)/$(LINUX_DIR)
@set -e ; if [ ! -f $(LINUX_DIR)/Makefile ] ; then \
echo "***********************************"; \
echo "oldconfig did not create a Makefile"; \
diff --git a/buildconfigs/select-linux-arch b/buildconfigs/select-linux-arch
new file mode 100755
index 0000000000..a5d0856e12
--- /dev/null
+++ b/buildconfigs/select-linux-arch
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+ME=$(basename $0)
+
+if [ $# -lt 1 ] || [ $# -gt 2 ] ; then
+ echo "usage: $ME <linux-build-directory>" 1>&2
+ exit 1;
+fi
+
+LINUX_DIR=$1
+
+case ${XEN_TARGET_ARCH} in
+ x86_32|x86_64)
+ if [ -d ${LINUX_DIR}/arch/x86 ] ; then
+ ARCH=x86
+ elif [ "${XEN_TARGET_ARCH}" = "x86_32" ] ; then
+ ARCH=i386
+ else
+ ARCH=x86_64
+ fi
+ ;;
+ *)
+ ARCH=${XEN_TARGET_ARCH}
+ ;;
+esac
+
+echo "$ME: ${ARCH}" 1>&2
+echo ${ARCH}
+
+exit 0
diff --git a/buildconfigs/select-linux-image b/buildconfigs/select-linux-image
new file mode 100755
index 0000000000..07899f80e2
--- /dev/null
+++ b/buildconfigs/select-linux-image
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+ME=$(basename $0)
+
+if [ $# -lt 3 ] ; then
+ echo "usage: $ME <linux-build-directory> <linux-arch> <linux-targets...>" 1>&2
+ exit 1;
+fi
+
+LINUX_DIR=$1
+LINUX_ARCH=$2
+LINUX_TARGET=$3 # We don't care about second and subsequent targets
+
+case ${XEN_TARGET_ARCH} in
+ ia64)
+ IMAGE=${LINUX_DIR}/arch/ia64/hp/sim/boot/vmlinux.gz
+ ;;
+ *)
+ if [ -f ${LINUX_DIR}/arch/${LINUX_ARCH}/boot/${LINUX_TARGET} ] ; then
+ IMAGE=${LINUX_DIR}/arch/${LINUX_ARCH}/boot/${LINUX_TARGET}
+ elif [ -f ${LINUX_DIR}/${LINUX_TARGET} ] ; then
+ IMAGE=${LINUX_DIR}/${LINUX_TARGET}
+ else
+ echo "$ME: cannot determine Linux image to use for ${LINUX_ARCH} in ${LINUX_DIR}" 1>&2
+ exit 1
+ fi
+ ;;
+esac
+
+echo "$ME: ${IMAGE}" 1>&2
+echo ${IMAGE}
+
+exit 0
diff --git a/config/MiniOS.mk b/config/MiniOS.mk
new file mode 100644
index 0000000000..fc02b70fc4
--- /dev/null
+++ b/config/MiniOS.mk
@@ -0,0 +1,9 @@
+include $(XEN_ROOT)/config/StdGNU.mk
+include $(XEN_ROOT)/extras/mini-os/Config.mk
+CFLAGS += $(DEF_CFLAGS) $(ARCH_CFLAGS)
+CPPFLAGS += $(DEF_CPPFLAGS) $(ARCH_CPPFLAGS) $(extra_incl)
+ASFLAGS += $(DEF_ASFLAGS) $(ARCH_ASFLAGS)
+LDFLAGS += $(DEF_LDFLAGS) $(ARCH_LDFLAGS)
+
+# Override settings for this OS
+PTHREAD_LIBS =
diff --git a/config/StdGNU.mk b/config/StdGNU.mk
index dfbc7ece44..82a99d3f11 100644
--- a/config/StdGNU.mk
+++ b/config/StdGNU.mk
@@ -35,6 +35,7 @@ PRIVATE_BINDIR = $(PRIVATE_PREFIX)/bin
SOCKET_LIBS =
CURSES_LIBS = -lncurses
+PTHREAD_LIBS = -lpthread
UTIL_LIBS = -lutil
SONAME_LDFLAG = -soname
SHLIB_CFLAGS = -shared
diff --git a/config/SunOS.mk b/config/SunOS.mk
index e6035bf4ca..c2a5594000 100644
--- a/config/SunOS.mk
+++ b/config/SunOS.mk
@@ -39,6 +39,7 @@ SunOS_LIBDIR_x86_64 = /usr/sfw/lib/amd64
SOCKET_LIBS = -lsocket
CURSES_LIBS = -lcurses
+PTHREAD_LIBS = -lpthread
UTIL_LIBS =
SONAME_LDFLAG = -h
SHLIB_CFLAGS = -R $(SunOS_LIBDIR) -shared
diff --git a/docs/misc/xenstore.txt b/docs/misc/xenstore.txt
index 90632863df..baf2c42dc0 100644
--- a/docs/misc/xenstore.txt
+++ b/docs/misc/xenstore.txt
@@ -296,6 +296,16 @@ RESUME <domid>|
xenstored prevents the use of RESUME other than by dom0.
+SET_TARGET <domid>|<tdomid>|
+ Notifies xenstored that domain <domid> is targeting domain
+ <tdomid>. This grants domain <domid> full access to paths
+ owned by <tdomid>. Domain <domid> also inherits all
+ permissions granted to <tdomid> on all other paths. This
+ allows <domid> to behave as if it were dom0 when modifying
+ paths related to <tdomid>.
+
+ xenstored prevents the use of SET_TARGET other than by dom0.
+
---------- Miscellaneous ----------
DEBUG print|<string>|?? sends <string> to debug log
diff --git a/docs/xen-api/revision-history.tex b/docs/xen-api/revision-history.tex
index 70ac17390f..d282adb106 100644
--- a/docs/xen-api/revision-history.tex
+++ b/docs/xen-api/revision-history.tex
@@ -23,5 +23,12 @@
\end{flushleft}
\end{minipage}\\
\hline
+ 1.0.2 & 11th Feb. 08 & S. Berger &
+ \begin{minipage}[t]{7cm}
+ \begin{flushleft}
+ Added table of contents and hyperlink cross reference.
+ \end{flushleft}
+ \end{minipage}\\
+ \hline
\end{tabular}
\end{center} \ No newline at end of file
diff --git a/docs/xen-api/xenapi-coversheet.tex b/docs/xen-api/xenapi-coversheet.tex
index bf9371f073..c35190acfe 100644
--- a/docs/xen-api/xenapi-coversheet.tex
+++ b/docs/xen-api/xenapi-coversheet.tex
@@ -17,7 +17,7 @@
\newcommand{\coversheetlogo}{xen.eps}
%% Document date
-\newcommand{\datestring}{25th January 2008}
+\newcommand{\datestring}{11th February 2008}
\newcommand{\releasestatement}{Stable Release}
diff --git a/docs/xen-api/xenapi.tex b/docs/xen-api/xenapi.tex
index f71689e377..902d9b2daf 100644
--- a/docs/xen-api/xenapi.tex
+++ b/docs/xen-api/xenapi.tex
@@ -17,6 +17,7 @@
\usepackage{graphics}
\usepackage{longtable}
\usepackage{fancyhdr}
+\usepackage{hyperref}
\setlength\topskip{0cm}
\setlength\topmargin{0cm}
@@ -35,6 +36,10 @@
% The revision history
\include{revision-history}
+% Table of contents
+\tableofcontents
+
+
% ... and off we go!
\chapter{Introduction}
diff --git a/extras/mini-os/Config.mk b/extras/mini-os/Config.mk
new file mode 100644
index 0000000000..e38fae99cb
--- /dev/null
+++ b/extras/mini-os/Config.mk
@@ -0,0 +1,76 @@
+# Set mini-os root path, used in mini-os.mk.
+MINI-OS_ROOT=$(XEN_ROOT)/extras/mini-os
+export MINI-OS_ROOT
+
+ifeq ($(XEN_TARGET_ARCH),x86_32)
+export pae ?= y
+endif
+libc = $(stubdom)
+
+XEN_INTERFACE_VERSION := 0x00030205
+export XEN_INTERFACE_VERSION
+
+# Try to find out the architecture family TARGET_ARCH_FAM.
+# First check whether x86_... is contained (for x86_32, x86_32y, x86_64).
+# If not x86 then use $(XEN_TARGET_ARCH) -> for ia64, ...
+ifeq ($(findstring x86_,$(XEN_TARGET_ARCH)),x86_)
+TARGET_ARCH_FAM = x86
+else
+TARGET_ARCH_FAM = $(XEN_TARGET_ARCH)
+endif
+
+# The architecture family directory below mini-os.
+TARGET_ARCH_DIR := arch/$(TARGET_ARCH_FAM)
+
+# Export these variables for possible use in architecture dependent makefiles.
+export TARGET_ARCH_DIR
+export TARGET_ARCH_FAM
+export XEN_TARGET_X86_PAE
+
+# This is used for architecture specific links.
+# This can be overwritten from arch specific rules.
+ARCH_LINKS =
+
+# The path pointing to the architecture specific header files.
+ARCH_INC := $(TARGET_ARCH_FAM)
+
+# For possible special header directories.
+# This can be overwritten from arch specific rules.
+EXTRA_INC = $(ARCH_INC)
+
+# Include the architecture family's special makerules.
+# This must be before include minios.mk!
+include $(MINI-OS_ROOT)/$(TARGET_ARCH_DIR)/arch.mk
+
+extra_incl := $(foreach dir,$(EXTRA_INC),-I$(MINI-OS_ROOT)/include/$(dir))
+
+DEF_CPPFLAGS += -I$(MINI-OS_ROOT)/include
+
+ifeq ($(stubdom),y)
+DEF_CPPFLAGS += -DCONFIG_STUBDOM
+endif
+
+ifeq ($(libc),y)
+DEF_CPPFLAGS += -DHAVE_LIBC
+DEF_CPPFLAGS += -I$(MINI-OS_ROOT)/include/posix
+DEF_CPPFLAGS += -I$(XEN_ROOT)/tools/xenstore
+endif
+
+ifneq ($(LWIPDIR),)
+lwip=y
+DEF_CPPFLAGS += -DHAVE_LWIP
+DEF_CPPFLAGS += -I$(LWIPDIR)/src/include
+DEF_CPPFLAGS += -I$(LWIPDIR)/src/include/ipv4
+endif
+
+ifneq ($(QEMUDIR),)
+qemu=y
+endif
+
+ifneq ($(CAMLDIR),)
+caml=y
+endif
+
+ifeq ($(pae),y)
+DEF_CPPFLAGS += -DCONFIG_X86_PAE
+endif
diff --git a/extras/mini-os/Makefile b/extras/mini-os/Makefile
index a008143cf0..4811f0dbfd 100644
--- a/extras/mini-os/Makefile
+++ b/extras/mini-os/Makefile
@@ -4,54 +4,11 @@
# Makefile and a arch.mk.
#
-XEN_ROOT = ../..
+export XEN_ROOT = ../..
include $(XEN_ROOT)/Config.mk
-XEN_INTERFACE_VERSION := 0x00030205
-export XEN_INTERFACE_VERSION
-
-# Set TARGET_ARCH
-override TARGET_ARCH := $(XEN_TARGET_ARCH)
-
-# Set mini-os root path, used in mini-os.mk.
-MINI-OS_ROOT=$(PWD)
-export MINI-OS_ROOT
-
-# Try to find out the architecture family TARGET_ARCH_FAM.
-# First check whether x86_... is contained (for x86_32, x86_32y, x86_64).
-# If not x86 then use $(TARGET_ARCH) -> for ia64, ...
-ifeq ($(findstring x86_,$(TARGET_ARCH)),x86_)
-TARGET_ARCH_FAM = x86
-else
-TARGET_ARCH_FAM = $(TARGET_ARCH)
-endif
-
-# The architecture family directory below mini-os.
-TARGET_ARCH_DIR := arch/$(TARGET_ARCH_FAM)
-
-# Export these variables for possible use in architecture dependent makefiles.
-export TARGET_ARCH
-export TARGET_ARCH_DIR
-export TARGET_ARCH_FAM
-export XEN_TARGET_X86_PAE
-
-# This is used for architecture specific links.
-# This can be overwritten from arch specific rules.
-ARCH_LINKS =
-
-# For possible special header directories.
-# This can be overwritten from arch specific rules.
-EXTRA_INC =
-
-# Include the architecture family's special makerules.
-# This must be before include minios.mk!
-include $(TARGET_ARCH_DIR)/arch.mk
-
-ifneq ($(LWIPDIR),)
-lwip=y
-DEF_CFLAGS += -DHAVE_LWIP
-DEF_CFLAGS += -I$(LWIPDIR)/src/include
-DEF_CFLAGS += -I$(LWIPDIR)/src/include/ipv4
+ifneq ($(stubdom),y)
+include Config.mk
endif
# Include common mini-os makerules.
@@ -63,7 +20,7 @@ include minios.mk
# Define some default flags for linking.
LDLIBS :=
LDARCHLIB := -L$(TARGET_ARCH_DIR) -l$(ARCH_LIB_NAME)
-LDFLAGS_FINAL := -T $(TARGET_ARCH_DIR)/minios-$(TARGET_ARCH).lds
+LDFLAGS_FINAL := -T $(TARGET_ARCH_DIR)/minios-$(XEN_TARGET_ARCH).lds
# Prefix for global API names. All other symbols are localised before
# linking with EXTRA_OBJS.
@@ -112,14 +69,38 @@ lwip.a: $(LWO)
$(AR) cqs $@ $^
OBJS += lwip.a
+endif
+
+OBJS := $(filter-out lwip%.o $(LWO), $(OBJS))
-OBJS := $(filter-out $(LWO), $(OBJS))
+ifeq ($(caml),y)
+CAMLLIB = $(shell ocamlc -where)
+OBJS += $(CAMLDIR)/caml.o
+OBJS += $(CAMLLIB)/libasmrun.a
+CFLAGS += -I$(CAMLLIB)
+LDLIBS += -lm
else
-OBJS := $(filter-out daytime.o lwip%.o, $(OBJS))
+OBJS := $(filter-out main-caml.o, $(OBJS))
+endif
+
+ifeq ($(qemu),y)
+OBJS += $(QEMUDIR)/i386-dm-stubdom/qemu.a $(QEMUDIR)/i386-dm-stubdom/libqemu.a
+CFLAGS += -DCONFIG_QEMU
+endif
+
+ifeq ($(libc),y)
+LDLIBS += -L$(XEN_ROOT)/stubdom/libxc -lxenctrl -lxenguest
+LDLIBS += -lpci
+LDLIBS += -lz
+LDLIBS += -lc
+endif
+
+ifneq ($(caml)-$(qemu)-$(lwip),--y)
+OBJS := $(filter-out daytime.o, $(OBJS))
endif
$(TARGET): links $(OBJS) arch_lib
- $(LD) -r $(LDFLAGS) $(HEAD_OBJ) $(OBJS) $(LDARCHLIB) -o $@.o
+ $(LD) -r $(LDFLAGS) $(HEAD_OBJ) $(OBJS) $(LDARCHLIB) $(LDLIBS) -o $@.o
$(OBJCOPY) -w -G $(GLOBAL_PREFIX)* -G _start $@.o $@.o
$(LD) $(LDFLAGS) $(LDFLAGS_FINAL) $@.o $(EXTRA_OBJS) -o $@
gzip -f -9 -c $@ >$@.gz
diff --git a/extras/mini-os/arch/ia64/Makefile b/extras/mini-os/arch/ia64/Makefile
index fb5ca9fb72..6e46aa67ef 100644
--- a/extras/mini-os/arch/ia64/Makefile
+++ b/extras/mini-os/arch/ia64/Makefile
@@ -5,6 +5,8 @@
XEN_ROOT = ../../../..
include $(XEN_ROOT)/Config.mk
+include ../../Config.mk
+
include arch.mk
include ../../minios.mk
@@ -41,7 +43,7 @@ ARCH_OBJS += __divdi3.o
GEN_OFF_SRC := gen_off.c
GEN_OFF_ASM := gen_off.s
-GEN_OFF_H := $(ARCH_INC)/offsets.h
+GEN_OFF_H := $(MINI-OS_ROOT)/include/$(ARCH_INC)/offsets.h
all: $(ARCH_LIB)
diff --git a/extras/mini-os/arch/ia64/minios-ia64.lds b/extras/mini-os/arch/ia64/minios-ia64.lds
index 70435de11e..96911aa3fd 100644
--- a/extras/mini-os/arch/ia64/minios-ia64.lds
+++ b/extras/mini-os/arch/ia64/minios-ia64.lds
@@ -40,6 +40,18 @@ SECTIONS
.rodata.str1.8 : AT(ADDR(.rodata.str1.8) - (((5<<(61))+0x100000000) - (1 << 20)))
{ *(.rodata.str1.8) }
+ /* newlib initialization functions */
+ . = ALIGN(64 / 8);
+ PROVIDE (__preinit_array_start = .);
+ .preinit_array : { *(.preinit_array) }
+ PROVIDE (__preinit_array_end = .);
+ PROVIDE (__init_array_start = .);
+ .init_array : { *(.init_array) }
+ PROVIDE (__init_array_end = .);
+ PROVIDE (__fini_array_start = .);
+ .fini_array : { *(.fini_array) }
+ PROVIDE (__fini_array_end = .);
+
.IA_64.unwind_info : AT(ADDR(.IA_64.unwind_info) - (((5<<(61))+0x100000000) - (1 << 20)))
{ *(.IA_64.unwind_info) }
diff --git a/extras/mini-os/arch/ia64/mm.c b/extras/mini-os/arch/ia64/mm.c
index f557730257..f2291f918c 100644
--- a/extras/mini-os/arch/ia64/mm.c
+++ b/extras/mini-os/arch/ia64/mm.c
@@ -43,6 +43,14 @@ extern uint64_t _text[], _etext[], _end[], kstack[], phys_start[];
uint64_t kernstart, kernend, kernsize, kernpstart, kernpend;
+#ifdef HAVE_LIBC
+uint8_t _heap[512 * 1024];
+unsigned long heap = (unsigned long)_heap,
+ brk = (unsigned long)_heap,
+ heap_mapped = (unsigned long)_heap + sizeof(_heap),
+ heap_end = (unsigned long)_heap + sizeof(_heap);
+#endif
+
/* Print the available memory chunks. */
static void
print_phys_avail(void)
diff --git a/extras/mini-os/arch/x86/Makefile b/extras/mini-os/arch/x86/Makefile
index 22cfe82811..21f0958f6a 100644
--- a/extras/mini-os/arch/x86/Makefile
+++ b/extras/mini-os/arch/x86/Makefile
@@ -5,13 +5,14 @@
XEN_ROOT = ../../../..
include $(XEN_ROOT)/Config.mk
+include ../../Config.mk
# include arch.mk has to be before mini-os.mk!
include arch.mk
include ../../minios.mk
-# Sources here are all *.c *.S without $(TARGET_ARCH).S
+# Sources here are all *.c *.S without $(XEN_TARGET_ARCH).S
# This is handled in $(HEAD_ARCH_OBJ)
ARCH_SRCS := $(wildcard *.c)
diff --git a/extras/mini-os/arch/x86/arch.mk b/extras/mini-os/arch/x86/arch.mk
index dd6bfe0b8d..1680362789 100644
--- a/extras/mini-os/arch/x86/arch.mk
+++ b/extras/mini-os/arch/x86/arch.mk
@@ -3,11 +3,11 @@
# (including x86_32, x86_32y and x86_64).
#
-ifeq ($(TARGET_ARCH),x86_32)
+ifeq ($(XEN_TARGET_ARCH),x86_32)
ARCH_CFLAGS := -m32 -march=i686
ARCH_LDFLAGS := -m elf_i386
ARCH_ASFLAGS := -m32
-EXTRA_INC += $(TARGET_ARCH_FAM)/$(TARGET_ARCH)
+EXTRA_INC += $(TARGET_ARCH_FAM)/$(XEN_TARGET_ARCH)
EXTRA_SRC += arch/$(EXTRA_INC)
ifeq ($(XEN_TARGET_X86_PAE),y)
@@ -16,12 +16,12 @@ ARCH_ASFLAGS += -DCONFIG_X86_PAE=1
endif
endif
-ifeq ($(TARGET_ARCH),x86_64)
+ifeq ($(XEN_TARGET_ARCH),x86_64)
ARCH_CFLAGS := -m64 -mno-red-zone -fno-reorder-blocks
ARCH_CFLAGS += -fno-asynchronous-unwind-tables
ARCH_ASFLAGS := -m64
ARCH_LDFLAGS := -m elf_x86_64
-EXTRA_INC += $(TARGET_ARCH_FAM)/$(TARGET_ARCH)
+EXTRA_INC += $(TARGET_ARCH_FAM)/$(XEN_TARGET_ARCH)
EXTRA_SRC += arch/$(EXTRA_INC)
endif
diff --git a/extras/mini-os/arch/x86/minios-x86_32.lds b/extras/mini-os/arch/x86/minios-x86_32.lds
index 08ebe14328..df5301944f 100644
--- a/extras/mini-os/arch/x86/minios-x86_32.lds
+++ b/extras/mini-os/arch/x86/minios-x86_32.lds
@@ -16,6 +16,18 @@ SECTIONS
. = ALIGN(4096);
_erodata = .;
+ /* newlib initialization functions */
+ . = ALIGN(32 / 8);
+ PROVIDE (__preinit_array_start = .);
+ .preinit_array : { *(.preinit_array) }
+ PROVIDE (__preinit_array_end = .);
+ PROVIDE (__init_array_start = .);
+ .init_array : { *(.init_array) }
+ PROVIDE (__init_array_end = .);
+ PROVIDE (__fini_array_start = .);
+ .fini_array : { *(.fini_array) }
+ PROVIDE (__fini_array_end = .);
+
.data : { /* Data */
*(.data)
CONSTRUCTORS
diff --git a/extras/mini-os/arch/x86/minios-x86_64.lds b/extras/mini-os/arch/x86/minios-x86_64.lds
index 345c38640c..f93800236b 100644
--- a/extras/mini-os/arch/x86/minios-x86_64.lds
+++ b/extras/mini-os/arch/x86/minios-x86_64.lds
@@ -16,6 +16,18 @@ SECTIONS
. = ALIGN(4096);
_erodata = .;
+ /* newlib initialization functions */
+ . = ALIGN(64 / 8);
+ PROVIDE (__preinit_array_start = .);
+ .preinit_array : { *(.preinit_array) }
+ PROVIDE (__preinit_array_end = .);
+ PROVIDE (__init_array_start = .);
+ .init_array : { *(.init_array) }
+ PROVIDE (__init_array_end = .);
+ PROVIDE (__fini_array_start = .);
+ .fini_array : { *(.fini_array) }
+ PROVIDE (__fini_array_end = .);
+
.data : { /* Data */
*(.data)
CONSTRUCTORS
diff --git a/extras/mini-os/arch/x86/mm.c b/extras/mini-os/arch/x86/mm.c
index 082527d098..dd556e4741 100644
--- a/extras/mini-os/arch/x86/mm.c
+++ b/extras/mini-os/arch/x86/mm.c
@@ -448,6 +448,15 @@ static unsigned long demand_map_area_start;
#define DEMAND_MAP_PAGES ((2ULL << 30) / PAGE_SIZE)
#endif
+#ifdef HAVE_LIBC
+unsigned long heap, brk, heap_mapped, heap_end;
+#ifdef __x86_64__
+#define HEAP_PAGES ((128ULL << 30) / PAGE_SIZE)
+#else
+#define HEAP_PAGES ((1ULL << 30) / PAGE_SIZE)
+#endif
+#endif
+
void arch_init_demand_mapping_area(unsigned long cur_pfn)
{
cur_pfn++;
@@ -455,6 +464,14 @@ void arch_init_demand_mapping_area(unsigned long cur_pfn)
demand_map_area_start = (unsigned long) pfn_to_virt(cur_pfn);
cur_pfn += DEMAND_MAP_PAGES;
printk("Demand map pfns at %lx-%lx.\n", demand_map_area_start, pfn_to_virt(cur_pfn));
+
+#ifdef HAVE_LIBC
+ cur_pfn++;
+ heap_mapped = brk = heap = (unsigned long) pfn_to_virt(cur_pfn);
+ cur_pfn += HEAP_PAGES;
+ heap_end = (unsigned long) pfn_to_virt(cur_pfn);
+ printk("Heap resides at %lx-%lx.\n", brk, heap_end);
+#endif
}
#define MAP_BATCH ((STACK_SIZE / 2) / sizeof(mmu_update_t))
diff --git a/extras/mini-os/arch/x86/x86_32.S b/extras/mini-os/arch/x86/x86_32.S
index 4b9a337c08..7f01851f0c 100644
--- a/extras/mini-os/arch/x86/x86_32.S
+++ b/extras/mini-os/arch/x86/x86_32.S
@@ -1,5 +1,5 @@
#include <os.h>
-#include <arch_mm.h>
+#include <arch_limits.h>
#include <xen/arch-x86_32.h>
.section __xen_guest
@@ -22,12 +22,12 @@
_start:
cld
lss stack_start,%esp
- andl $(~(STACK_SIZE-1)), %esp
+ andl $(~(__STACK_SIZE-1)), %esp
push %esi
call start_kernel
stack_start:
- .long stack+(2*STACK_SIZE), __KERNEL_SS
+ .long stack+(2*__STACK_SIZE), __KERNEL_SS
/* Unpleasant -- the PTE that maps this page is actually overwritten */
/* to map the real shared-info page! :-) */
diff --git a/extras/mini-os/arch/x86/x86_64.S b/extras/mini-os/arch/x86/x86_64.S
index fae2ae4cf5..c7a797db90 100644
--- a/extras/mini-os/arch/x86/x86_64.S
+++ b/extras/mini-os/arch/x86/x86_64.S
@@ -1,5 +1,5 @@
#include <os.h>
-#include <arch_mm.h>
+#include <arch_limits.h>
#include <xen/features.h>
.section __xen_guest
@@ -19,12 +19,12 @@
_start:
cld
movq stack_start(%rip),%rsp
- andq $(~(STACK_SIZE-1)), %rsp
+ andq $(~(__STACK_SIZE-1)), %rsp
movq %rsi,%rdi
call start_kernel
stack_start:
- .quad stack+(2*STACK_SIZE)
+ .quad stack+(2*__STACK_SIZE)
/* Unpleasant -- the PTE that maps this page is actually overwritten */
/* to map the real shared-info page! :-) */
diff --git a/extras/mini-os/blkfront.c b/extras/mini-os/blkfront.c
index 881efd3055..3210396b7b 100644
--- a/extras/mini-os/blkfront.c
+++ b/extras/mini-os/blkfront.c
@@ -15,6 +15,10 @@
#include <lib.h>
#include <fcntl.h>
+#ifndef HAVE_LIBC
+#define strtoul simple_strtoul
+#endif
+
/* Note: we generally don't need to disable IRQs since we hardly do anything in
* the interrupt handler. */
@@ -49,15 +53,20 @@ struct blkfront_dev {
int mode;
int barrier;
int flush;
-};
-static inline int xenblk_rxidx(RING_IDX idx)
-{
- return idx & (BLK_RING_SIZE - 1);
-}
+#ifdef HAVE_LIBC
+ int fd;
+#endif
+};
void blkfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
{
+#ifdef HAVE_LIBC
+ struct blkfront_dev *dev = data;
+ int fd = dev->fd;
+
+ files[fd].read = 1;
+#endif
wake_up(&blkfront_queue);
}
@@ -148,7 +157,7 @@ done:
printk("backend at %s\n", dev->backend);
- dev->handle = simple_strtoul(strrchr(nodename, '/')+1, NULL, 0);
+ dev->handle = strtoul(strrchr(nodename, '/')+1, NULL, 0);
{
char path[strlen(dev->backend) + 1 + 19 + 1];
@@ -313,6 +322,11 @@ int blkfront_aio_poll(struct blkfront_dev *dev)
struct blkif_response *rsp;
moretodo:
+#ifdef HAVE_LIBC
+ files[dev->fd].read = 0;
+ mb(); /* Make sure to let the handler set read to 1 before we start looking at the ring */
+#endif
+
rp = dev->ring.sring->rsp_prod;
rmb(); /* Ensure we see queued responses up to 'rp'. */
cons = dev->ring.rsp_cons;
@@ -322,12 +336,16 @@ moretodo:
{
rsp = RING_GET_RESPONSE(&dev->ring, cons);
+ if (rsp->status != BLKIF_RSP_OKAY)
+ printk("block error %d for op %d\n", rsp->status, rsp->operation);
+
switch (rsp->operation) {
case BLKIF_OP_READ:
case BLKIF_OP_WRITE:
{
struct blkfront_aiocb *aiocbp = (void*) (uintptr_t) rsp->id;
int j;
+
for (j = 0; j < aiocbp->n; j++)
gnttab_end_access(aiocbp->gref[j]);
@@ -365,6 +383,12 @@ static void blkfront_push_operation(struct blkfront_dev *dev, uint8_t op)
i = dev->ring.req_prod_pvt;
req = RING_GET_REQUEST(&dev->ring, i);
req->operation = op;
+ req->nr_segments = 0;
+ req->handle = dev->handle;
+ /* Not used */
+ req->id = 0;
+ /* Not needed anyway, but the backend will check it */
+ req->sector_number = 0;
dev->ring.req_prod_pvt = i + 1;
wmb();
RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&dev->ring, notify);
@@ -375,11 +399,13 @@ void blkfront_sync(struct blkfront_dev *dev)
{
unsigned long flags;
- if (dev->barrier == 1)
- blkfront_push_operation(dev, BLKIF_OP_WRITE_BARRIER);
+ if (dev->mode == O_RDWR) {
+ if (dev->barrier == 1)
+ blkfront_push_operation(dev, BLKIF_OP_WRITE_BARRIER);
- if (dev->flush == 1)
- blkfront_push_operation(dev, BLKIF_OP_FLUSH_DISKCACHE);
+ if (dev->flush == 1)
+ blkfront_push_operation(dev, BLKIF_OP_FLUSH_DISKCACHE);
+ }
/* Note: This won't finish if another thread enqueues requests. */
local_irq_save(flags);
@@ -397,3 +423,13 @@ void blkfront_sync(struct blkfront_dev *dev)
remove_waiter(w);
local_irq_restore(flags);
}
+
+#ifdef HAVE_LIBC
+int blkfront_open(struct blkfront_dev *dev)
+{
+ dev->fd = alloc_fd(FTYPE_BLK);
+ printk("blk_open(%s) -> %d\n", dev->nodename, dev->fd);
+ files[dev->fd].blk.dev = dev;
+ return dev->fd;
+}
+#endif
diff --git a/extras/mini-os/include/arch/cc.h b/extras/mini-os/include/arch/cc.h
index 70191f0b30..e9a258d8bf 100644
--- a/extras/mini-os/include/arch/cc.h
+++ b/extras/mini-os/include/arch/cc.h
@@ -54,7 +54,14 @@ extern void lwip_die(char *fmt, ...);
#include <errno.h>
/* Not required by the docs, but needed for network-order calculations */
+#ifdef HAVE_LIBC
+#include <machine/endian.h>
+#ifndef BIG_ENDIAN
+#error endian.h does not define byte order
+#endif
+#else
#include <endian.h>
+#endif
#include <inttypes.h>
#define S16_F PRIi16
diff --git a/extras/mini-os/include/byteswap.h b/extras/mini-os/include/byteswap.h
new file mode 100644
index 0000000000..7c4ffe393c
--- /dev/null
+++ b/extras/mini-os/include/byteswap.h
@@ -0,0 +1,22 @@
+#ifndef _BYTESWAP_H_
+#define _BYTESWAP_H_
+
+/* Unfortunately not provided by newlib. */
+#define bswap_16(x) \
+ ((((x) & 0xff00) >> 8) | (((x) & 0xff) << 8))
+
+#define bswap_32(x) \
+ ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
+ (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
+
+#define bswap_64(x) \
+ ((((x) & 0xff00000000000000ULL) >> 56) | \
+ (((x) & 0x00ff000000000000ULL) >> 40) | \
+ (((x) & 0x0000ff0000000000ULL) >> 24) | \
+ (((x) & 0x000000ff00000000ULL) >> 8) | \
+ (((x) & 0x00000000ff000000ULL) << 8) | \
+ (((x) & 0x0000000000ff0000ULL) << 24) | \
+ (((x) & 0x000000000000ff00ULL) << 40) | \
+ (((x) & 0x00000000000000ffULL) << 56))
+
+#endif /* _BYTESWAP_H */
diff --git a/extras/mini-os/include/console.h b/extras/mini-os/include/console.h
index 6ee04f1316..9ace8dfcb1 100644
--- a/extras/mini-os/include/console.h
+++ b/extras/mini-os/include/console.h
@@ -36,7 +36,9 @@
#ifndef _LIB_CONSOLE_H_
#define _LIB_CONSOLE_H_
+#include<os.h>
#include<traps.h>
+#include<stdarg.h>
void print(int direct, const char *fmt, va_list args);
void printk(const char *fmt, ...);
@@ -48,5 +50,6 @@ void xencons_rx(char *buf, unsigned len, struct pt_regs *regs);
void xencons_tx(void);
void init_console(void);
+void console_print(char *data, int length);
#endif /* _LIB_CONSOLE_H_ */
diff --git a/extras/mini-os/include/errno.h b/extras/mini-os/include/errno.h
index 262ab3e0b4..2829420dd7 100644
--- a/extras/mini-os/include/errno.h
+++ b/extras/mini-os/include/errno.h
@@ -107,4 +107,11 @@
#define EOWNERDEAD 130 /* Owner died */
#define ENOTRECOVERABLE 131 /* State not recoverable */
+#ifdef HAVE_LIBC
+#include <sched.h>
+extern int errno;
+#define ERRNO
+#define errno (get_current()->reent._errno)
+#endif
+
#endif
diff --git a/extras/mini-os/include/fcntl.h b/extras/mini-os/include/fcntl.h
index 64020795ab..34a6484d35 100644
--- a/extras/mini-os/include/fcntl.h
+++ b/extras/mini-os/include/fcntl.h
@@ -86,4 +86,7 @@ struct flock64 {
#define F_LINUX_SPECIFIC_BASE 1024
*/
+
+int open(const char *path, int flags, ...);
+int fcntl(int fd, int cmd, ...);
#endif
diff --git a/extras/mini-os/include/fs.h b/extras/mini-os/include/fs.h
index 1555a5adcc..4c822dfb20 100644
--- a/extras/mini-os/include/fs.h
+++ b/extras/mini-os/include/fs.h
@@ -22,6 +22,7 @@ struct fs_import
struct semaphore reqs_sem; /* Accounts requests resource */
};
+extern struct fs_import *fs_import;
void init_fs_frontend(void);
diff --git a/extras/mini-os/include/ia64/arch_limits.h b/extras/mini-os/include/ia64/arch_limits.h
new file mode 100644
index 0000000000..c7bb9b6573
--- /dev/null
+++ b/extras/mini-os/include/ia64/arch_limits.h
@@ -0,0 +1,12 @@
+
+#ifndef __ARCH_LIMITS_H__
+#define __ARCH_LIMITS_H__
+
+/* Commonly 16K pages are used. */
+#define __PAGE_SHIFT 14 /* 16K pages */
+#define __PAGE_SIZE (1<<(__PAGE_SHIFT))
+
+#define __STACK_SIZE_PAGE_ORDER 2
+#define __STACK_SIZE (__PAGE_SIZE * (1 << __STACK_SIZE_PAGE_ORDER))
+
+#endif /* __ARCH_LIMITS_H__ */
diff --git a/extras/mini-os/include/ia64/arch_mm.h b/extras/mini-os/include/ia64/arch_mm.h
index 2a8e1c82a6..adc1da6d0f 100644
--- a/extras/mini-os/include/ia64/arch_mm.h
+++ b/extras/mini-os/include/ia64/arch_mm.h
@@ -35,11 +35,9 @@
#define virt_to_mfn(x) virt_to_pfn(x)
#define virtual_to_mfn(x) (ia64_tpa((uint64_t)(x)) >> PAGE_SHIFT)
-#define STACK_SIZE_PAGE_ORDER 1
-#define STACK_SIZE (PAGE_SIZE * (1 << STACK_SIZE_PAGE_ORDER))
-
#define map_frames(f, n) map_frames_ex(f, n, 1, 0, 1, DOMID_SELF, 0, 0)
/* TODO */
#define map_zero(n, a) map_frames_ex(NULL, n, 0, 0, a, DOMID_SELF, 0, 0)
+#define do_map_zero(start, n) ((void)0)
#endif /* __ARCH_MM_H__ */
diff --git a/extras/mini-os/include/ia64/page.h b/extras/mini-os/include/ia64/page.h
index 714227f172..67be0a555d 100644
--- a/extras/mini-os/include/ia64/page.h
+++ b/extras/mini-os/include/ia64/page.h
@@ -43,9 +43,9 @@
/* The efi-pal page size for text and data. */
#define PAL_TR_PAGE_SIZE PTE_PS_1M
-/* Commonly 16K pages are used. */
-#define PAGE_SHIFT 14 /* 16K pages */
-#define PAGE_SIZE (1<<(PAGE_SHIFT))
+#include "arch_limits.h"
+#define PAGE_SHIFT __PAGE_SHIFT
+#define PAGE_SIZE __PAGE_SIZE
#define PAGE_MASK (~(PAGE_SIZE-1))
#define KSTACK_PAGES 4 /* 4 pages for the kernel stack + bsp */
diff --git a/extras/mini-os/include/lib.h b/extras/mini-os/include/lib.h
index efe096bdba..2ddb8d07c8 100644
--- a/extras/mini-os/include/lib.h
+++ b/extras/mini-os/include/lib.h
@@ -57,6 +57,8 @@
#include <stdarg.h>
#include <stddef.h>
+#include <xen/xen.h>
+#include <xen/event_channel.h>
#ifdef HAVE_LIBC
#include <stdio.h>
@@ -103,6 +105,8 @@ char *strdup(const char *s);
int rand(void);
+#include <xenbus.h>
+
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
struct kvec {
@@ -126,4 +130,59 @@ do { \
/* Consistency check as much as possible. */
void sanity_check(void);
+#ifdef HAVE_LIBC
+enum fd_type {
+ FTYPE_NONE = 0,
+ FTYPE_CONSOLE,
+ FTYPE_FILE,
+ FTYPE_XENBUS,
+ FTYPE_EVTCHN,
+ FTYPE_SOCKET,
+ FTYPE_TAP,
+ FTYPE_BLK,
+};
+
+#define MAX_EVTCHN_PORTS 16
+
+extern struct file {
+ enum fd_type type;
+ union {
+ struct {
+ /* lwIP fd */
+ int fd;
+ } socket;
+ struct {
+ /* FS import fd */
+ int fd;
+ off_t offset;
+ } file;
+ struct {
+ /* To each event channel FD is associated a series of ports which
+ * wakes select for this FD. */
+ struct {
+ evtchn_port_t port;
+ volatile unsigned long pending;
+ int bound;
+ } ports[MAX_EVTCHN_PORTS];
+ } evtchn;
+ struct {
+ struct netfront_dev *dev;
+ } tap;
+ struct {
+ struct blkfront_dev *dev;
+ } blk;
+ struct {
+ /* To each xenbus FD is associated a queue of watch events for this
+ * FD. */
+ struct xenbus_event *volatile events;
+ } xenbus;
+ };
+ volatile int read; /* maybe available for read */
+} files[];
+
+int alloc_fd(enum fd_type type);
+void close_all_files(void);
+extern struct thread *main_thread;
+#endif
+
#endif /* _LIB_H_ */
diff --git a/extras/mini-os/include/linux/types.h b/extras/mini-os/include/linux/types.h
new file mode 100644
index 0000000000..f153ce8e42
--- /dev/null
+++ b/extras/mini-os/include/linux/types.h
@@ -0,0 +1,5 @@
+#ifndef _LINUX_TYPES_H_
+#define _LINUX_TYPES_H_
+#include <types.h>
+typedef u64 __u64;
+#endif /* _LINUX_TYPES_H_ */
diff --git a/extras/mini-os/include/mm.h b/extras/mini-os/include/mm.h
index 4319fa2640..8396ec6b31 100644
--- a/extras/mini-os/include/mm.h
+++ b/extras/mini-os/include/mm.h
@@ -36,8 +36,13 @@
#endif
#include <lib.h>
+
+#include <arch_limits.h>
#include <arch_mm.h>
+#define STACK_SIZE_PAGE_ORDER __STACK_SIZE_PAGE_ORDER
+#define STACK_SIZE __STACK_SIZE
+
void init_mm(void);
unsigned long alloc_pages(int order);
@@ -61,5 +66,8 @@ void arch_init_p2m(unsigned long max_pfn_p);
void *map_frames_ex(unsigned long *f, unsigned long n, unsigned long stride,
unsigned long increment, unsigned long alignment, domid_t id,
int may_fail, unsigned long prot);
+#ifdef HAVE_LIBC
+extern unsigned long heap, brk, heap_mapped, heap_end;
+#endif
#endif /* _MM_H_ */
diff --git a/extras/mini-os/include/netfront.h b/extras/mini-os/include/netfront.h
index 5c8ec9c4fa..acfc91944b 100644
--- a/extras/mini-os/include/netfront.h
+++ b/extras/mini-os/include/netfront.h
@@ -6,6 +6,10 @@ struct netfront_dev;
struct netfront_dev *init_netfront(char *nodename, void (*netif_rx)(unsigned char *data, int len), unsigned char rawmac[6]);
void netfront_xmit(struct netfront_dev *dev, unsigned char* data,int len);
void shutdown_netfront(struct netfront_dev *dev);
+#ifdef HAVE_LIBC
+int netfront_tap_open(char *nodename);
+ssize_t netfront_receive(struct netfront_dev *dev, unsigned char *data, size_t len);
+#endif
extern struct wait_queue_head netfront_queue;
diff --git a/extras/mini-os/include/posix/dirent.h b/extras/mini-os/include/posix/dirent.h
new file mode 100644
index 0000000000..56b1d67258
--- /dev/null
+++ b/extras/mini-os/include/posix/dirent.h
@@ -0,0 +1,24 @@
+#ifndef _POSIX_DIRENT_H
+#define _POSIX_DIRENT_H
+
+#include <sys/types.h>
+
+struct dirent {
+ char *d_name;
+};
+
+typedef struct {
+ struct dirent dirent;
+ char *name;
+ int32_t offset;
+ char **entries;
+ int32_t curentry;
+ int32_t nbentries;
+ int has_more;
+} DIR;
+
+DIR *opendir(const char *name);
+struct dirent *readdir(DIR *dir);
+int closedir(DIR *dir);
+
+#endif /* _POSIX_DIRENT_H */
diff --git a/extras/mini-os/include/posix/limits.h b/extras/mini-os/include/posix/limits.h
new file mode 100644
index 0000000000..ba800e33d2
--- /dev/null
+++ b/extras/mini-os/include/posix/limits.h
@@ -0,0 +1,9 @@
+#ifndef _POSIX_LIMITS_H
+#define _POSIX_LIMITS_H
+
+#include_next <limits.h>
+#include <arch_limits.h>
+
+#define PATH_MAX __PAGE_SIZE
+
+#endif /* _POSIX_LIMITS_H */
diff --git a/extras/mini-os/include/posix/netdb.h b/extras/mini-os/include/posix/netdb.h
new file mode 100644
index 0000000000..8f76a95b76
--- /dev/null
+++ b/extras/mini-os/include/posix/netdb.h
@@ -0,0 +1,9 @@
+#ifndef _POSIX_NETDB_H_
+#define _POSIX_NETDB_H_
+
+struct hostent {
+ char *h_addr;
+};
+#define gethostbyname(buf) NULL
+
+#endif /* _POSIX_NETDB_H_ */
diff --git a/extras/mini-os/include/posix/netinet/in.h b/extras/mini-os/include/posix/netinet/in.h
new file mode 100644
index 0000000000..cc1a91076d
--- /dev/null
+++ b/extras/mini-os/include/posix/netinet/in.h
@@ -0,0 +1,7 @@
+#ifndef _POSIX_SYS_IN_H_
+#define _POSIX_SYS_IN_H_
+
+#include <fcntl.h>
+#include <lwip/sockets.h>
+
+#endif /* _POSIX_SYS_IN_H_ */
diff --git a/extras/mini-os/include/posix/netinet/tcp.h b/extras/mini-os/include/posix/netinet/tcp.h
new file mode 100644
index 0000000000..3e3b060467
--- /dev/null
+++ b/extras/mini-os/include/posix/netinet/tcp.h
@@ -0,0 +1,6 @@
+#ifndef _POSIX_SYS_TCP_H_
+#define _POSIX_SYS_TCP_H_
+
+#include <lwip/tcp.h>
+
+#endif /* _POSIX_SYS_TCP_H_ */
diff --git a/extras/mini-os/include/posix/pthread.h b/extras/mini-os/include/posix/pthread.h
new file mode 100644
index 0000000000..7e62001e3a
--- /dev/null
+++ b/extras/mini-os/include/posix/pthread.h
@@ -0,0 +1,19 @@
+#ifndef _POSIX_PTHREAD_H
+#define _POSIX_PTHREAD_H
+
+/* Let's be single-threaded for now. */
+
+typedef void *pthread_key_t;
+typedef struct {} pthread_mutex_t, pthread_once_t;
+#define PTHREAD_MUTEX_INITIALIZER {}
+#define PTHREAD_ONCE_INIT {}
+static inline int pthread_mutex_lock(pthread_mutex_t *mutex) { return 0; }
+static inline int pthread_mutex_unlock(pthread_mutex_t *mutex) { return 0; }
+static inline int pthread_key_create(pthread_key_t *key, void (*destr_function)(void*)) { *key = NULL; return 0; }
+static inline int pthread_setspecific(pthread_key_t *key, const void *pointer) { *key = (void*) pointer; return 0; }
+static inline void *pthread_getspecific(pthread_key_t *key) { return *key; }
+static inline int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) { init_routine(); return 0; }
+
+#define __thread
+
+#endif /* _POSIX_PTHREAD_H */
diff --git a/extras/mini-os/include/posix/stdlib.h b/extras/mini-os/include/posix/stdlib.h
new file mode 100644
index 0000000000..53e6289635
--- /dev/null
+++ b/extras/mini-os/include/posix/stdlib.h
@@ -0,0 +1,8 @@
+#ifndef _POSIX_STDLIB_H
+#define _POSIX_STDLIB_H
+
+#include_next <stdlib.h>
+
+#define realpath(p,r) strcpy(r,p)
+
+#endif /* _POSIX_STDLIB_H */
diff --git a/extras/mini-os/include/posix/strings.h b/extras/mini-os/include/posix/strings.h
new file mode 100644
index 0000000000..8619ba2865
--- /dev/null
+++ b/extras/mini-os/include/posix/strings.h
@@ -0,0 +1,8 @@
+#ifndef _POSIX_STRINGS_H
+#define _POSIX_STRINGS_H
+
+#include <string.h>
+
+#define bzero(ptr, size) (memset((ptr), '\0', (size)), (void) 0)
+
+#endif /* _POSIX_STRINGS_H */
diff --git a/extras/mini-os/include/posix/sys/ioctl.h b/extras/mini-os/include/posix/sys/ioctl.h
new file mode 100644
index 0000000000..ecf3080d5a
--- /dev/null
+++ b/extras/mini-os/include/posix/sys/ioctl.h
@@ -0,0 +1,16 @@
+#ifndef _POSIX_SYS_IOCTL_H
+#define _POSIX_SYS_IOCTL_H
+
+int ioctl(int fd, int request, ...);
+
+#define _IOC_NONE 0
+#define _IOC_WRITE 1
+#define _IOC_READ 2
+
+#define _IOC(rw, class, n, size) \
+ (((rw ) << 30) | \
+ ((class) << 22) | \
+ ((n ) << 14) | \
+ ((size ) << 0))
+
+#endif /* _POSIX_SYS_IOCTL_H */
diff --git a/extras/mini-os/include/posix/sys/mman.h b/extras/mini-os/include/posix/sys/mman.h
new file mode 100644
index 0000000000..318d574877
--- /dev/null
+++ b/extras/mini-os/include/posix/sys/mman.h
@@ -0,0 +1,19 @@
+#ifndef _POSIX_SYS_MMAN_H
+#define _POSIX_SYS_MMAN_H
+
+#define PROT_READ 0x1
+#define PROT_WRITE 0x2
+#define PROT_EXEC 0x4
+
+#define MAP_SHARED 0x01
+#define MAP_PRIVATE 0x02
+#define MAP_ANON 0x20
+
+#define MAP_FAILED ((void*)0)
+
+void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
+int munmap(void *start, size_t length);
+#define munlock(addr, len) ((void)addr, (void)len, 0)
+#define mlock(addr, len) ((void)addr, (void)len, 0)
+
+#endif /* _POSIX_SYS_MMAN_H */
diff --git a/extras/mini-os/include/posix/sys/select.h b/extras/mini-os/include/posix/sys/select.h
new file mode 100644
index 0000000000..5132c51224
--- /dev/null
+++ b/extras/mini-os/include/posix/sys/select.h
@@ -0,0 +1,7 @@
+#ifndef _POSIX_SELECT_H
+#define _POSIX_SELECT_H
+
+#include <sys/time.h>
+int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
+
+#endif /* _POSIX_SELECT_H */
diff --git a/extras/mini-os/include/posix/sys/socket.h b/extras/mini-os/include/posix/sys/socket.h
new file mode 100644
index 0000000000..7c039a2f03
--- /dev/null
+++ b/extras/mini-os/include/posix/sys/socket.h
@@ -0,0 +1,31 @@
+#ifndef _POSIX_SYS_SOCKET_H_
+#define _POSIX_SYS_SOCKET_H_
+
+#include <fcntl.h>
+#include <lwip/sockets.h>
+
+int accept(int s, struct sockaddr *addr, socklen_t *addrlen);
+int bind(int s, struct sockaddr *name, socklen_t namelen);
+int shutdown(int s, int how);
+int getpeername (int s, struct sockaddr *name, socklen_t *namelen);
+int getsockname (int s, struct sockaddr *name, socklen_t *namelen);
+int getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen);
+int setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen);
+int close(int s);
+int connect(int s, struct sockaddr *name, socklen_t namelen);
+int listen(int s, int backlog);
+int recv(int s, void *mem, int len, unsigned int flags);
+//int read(int s, void *mem, int len);
+int recvfrom(int s, void *mem, int len, unsigned int flags,
+ struct sockaddr *from, socklen_t *fromlen);
+int send(int s, void *dataptr, int size, unsigned int flags);
+int sendto(int s, void *dataptr, int size, unsigned int flags,
+ struct sockaddr *to, socklen_t tolen);
+int socket(int domain, int type, int protocol);
+//int write(int s, void *dataptr, int size);
+int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
+ struct timeval *timeout);
+//int ioctl(int s, long cmd, void *argp);
+int getsockname(int s, struct sockaddr *name, socklen_t *namelen);
+
+#endif /* _POSIX_SYS_SOCKET_H_ */
diff --git a/extras/mini-os/include/posix/termios.h b/extras/mini-os/include/posix/termios.h
new file mode 100644
index 0000000000..a57aee4556
--- /dev/null
+++ b/extras/mini-os/include/posix/termios.h
@@ -0,0 +1,87 @@
+#ifndef _POSIX_TERMIOS_H
+#define _POSIX_TERMIOS_H
+
+#define NCC 32
+
+struct termios {
+ unsigned long c_iflag;
+ unsigned long c_oflag;
+ unsigned long c_lflag;
+ unsigned long c_cflag;
+ unsigned char c_cc[NCC];
+};
+
+/* modem lines */
+#define TIOCM_DTR 0x002
+#define TIOCM_RTS 0x004
+#define TIOCM_CTS 0x020
+#define TIOCM_CAR 0x040
+#define TIOCM_RI 0x080
+#define TIOCM_DSR 0x100
+
+/* c_iflag */
+#define IGNBRK 0x00000001
+#define BRKINT 0x00000002
+#define IGNPAR 0x00000004
+#define PARMRK 0x00000008
+#define INPCK 0x00000010
+#define ISTRIP 0x00000020
+#define INLCR 0x00000040
+#define IGNCR 0x00000080
+#define ICRNL 0x00000100
+#define IUCLC 0x00000200
+#define IXON 0x00000400
+#define IXANY 0x00000800
+#define IXOFF 0x00001000
+#define IMAXBEL 0x00002000
+#define IUTF8 0x00004000
+
+/* c_oflag */
+#define OPOST 0x00000001
+#define OLCUC 0x00000002
+#define ONLCR 0x00000004
+#define OCRNL 0x00000008
+#define ONOCR 0x00000010
+#define ONLRET 0x00000020
+#define OFILL 0x00000040
+#define OFDEL 0x00000080
+
+/* c_lflag */
+#define ISIG 0x00000001
+#define ICANON 0x00000002
+#define XCASE 0x00000004
+#define ECHO 0x00000008
+#define ECHOE 0x00000010
+#define ECHOK 0x00000020
+#define ECHONL 0x00000040
+#define NOFLSH 0x00000080
+#define TOSTOP 0x00000100
+#define ECHOCTL 0x00000200
+#define ECHOPRT 0x00000400
+#define ECHOKE 0x00000800
+#define FLUSHO 0x00002000
+#define PENDIN 0x00004000
+#define IEXTEN 0x00008000
+
+/* c_cflag */
+#define CSIZE 0x00000030
+#define CS8 0x00000030
+#define CSTOPB 0x00000040
+#define CREAD 0x00000080
+#define PARENB 0x00000100
+#define PARODD 0x00000200
+#define HUPCL 0x00000400
+#define CLOCAL 0x00000800
+
+/* c_cc */
+#define VTIME 5
+#define VMIN 6
+
+#define TCSANOW 0
+#define TCSADRAIN 1
+#define TCSAFLUSH 2
+
+int tcsetattr(int fildes, int action, const struct termios *tios);
+int tcgetattr(int fildes, struct termios *tios);
+
+#endif /* _POSIX_TERMIOS_H */
diff --git a/extras/mini-os/include/posix/time.h b/extras/mini-os/include/posix/time.h
new file mode 100644
index 0000000000..4f457cb5ad
--- /dev/null
+++ b/extras/mini-os/include/posix/time.h
@@ -0,0 +1,10 @@
+#ifndef _POSIX_TIME_H
+#define _POSIX_TIME_H
+
+#include <sys/time.h>
+#define CLOCK_MONOTONIC 2
+#include_next <time.h>
+
+int nanosleep(const struct timespec *req, struct timespec *rem);
+
+#endif /* _POSIX_TIME_H */
diff --git a/extras/mini-os/include/posix/unistd.h b/extras/mini-os/include/posix/unistd.h
new file mode 100644
index 0000000000..0cd9396ec9
--- /dev/null
+++ b/extras/mini-os/include/posix/unistd.h
@@ -0,0 +1,12 @@
+#ifndef _POSIX_UNISTD_H
+#define _POSIX_UNISTD_H
+
+#include_next <unistd.h>
+#include <sys/select.h>
+#include <arch_limits.h>
+
+#define getpagesize() __PAGE_SIZE
+
+int ftruncate(int fd, off_t length);
+
+#endif /* _POSIX_UNISTD_H */
diff --git a/extras/mini-os/include/sched.h b/extras/mini-os/include/sched.h
index a3d2022b8a..ba0d4e3df9 100644
--- a/extras/mini-os/include/sched.h
+++ b/extras/mini-os/include/sched.h
@@ -19,6 +19,9 @@ struct thread
struct list_head thread_list;
u32 flags;
s_time_t wakeup_time;
+#ifdef HAVE_LIBC
+ struct _reent reent;
+#endif
};
extern struct thread *idle_thread;
diff --git a/extras/mini-os/include/sys/time.h b/extras/mini-os/include/sys/time.h
index 87887c27d1..d6623a4e77 100644
--- a/extras/mini-os/include/sys/time.h
+++ b/extras/mini-os/include/sys/time.h
@@ -20,6 +20,9 @@
#ifndef _MINIOS_SYS_TIME_H_
#define _MINIOS_SYS_TIME_H_
+#ifdef HAVE_LIBC
+#include_next <sys/time.h>
+#else
struct timespec {
time_t tv_sec;
long tv_nsec;
@@ -34,5 +37,6 @@ struct timeval {
};
int gettimeofday(struct timeval *tv, void *tz);
+#endif
#endif /* _MINIOS_SYS_TIME_H_ */
diff --git a/extras/mini-os/include/time.h b/extras/mini-os/include/time.h
index 914f2fcff2..e28bf171d7 100644
--- a/extras/mini-os/include/time.h
+++ b/extras/mini-os/include/time.h
@@ -17,8 +17,9 @@
****************************************************************************
*/
-#ifndef _TIME_H_
-#define _TIME_H_
+#ifndef _MINIOS_TIME_H_
+#define _MINIOS_TIME_H_
+#include <types.h>
/*
* System Time
@@ -44,8 +45,12 @@ typedef s64 s_time_t;
/* wall clock time */
typedef long time_t;
typedef long suseconds_t;
+
#include <sys/time.h>
+#ifdef HAVE_LIBC
+#include_next <time.h>
+#endif
/* prototypes */
void init_time(void);
@@ -54,4 +59,4 @@ s_time_t get_v_time(void);
u64 monotonic_clock(void);
void block_domain(s_time_t until);
-#endif /* _TIME_H_ */
+#endif /* _MINIOS_TIME_H_ */
diff --git a/extras/mini-os/include/x86/arch_limits.h b/extras/mini-os/include/x86/arch_limits.h
new file mode 100644
index 0000000000..7f0351c67f
--- /dev/null
+++ b/extras/mini-os/include/x86/arch_limits.h
@@ -0,0 +1,20 @@
+
+#ifndef __ARCH_LIMITS_H__
+#define __ARCH_LIMITS_H__
+
+#define __PAGE_SHIFT 12
+
+#ifdef __ASSEMBLY__
+#define __PAGE_SIZE (1 << __PAGE_SHIFT)
+#else
+#ifndef CONFIG_X86_PAE
+#define __PAGE_SIZE (1UL << __PAGE_SHIFT)
+#else
+#define __PAGE_SIZE (1ULL << __PAGE_SHIFT)
+#endif
+#endif
+
+#define __STACK_SIZE_PAGE_ORDER 4
+#define __STACK_SIZE (__PAGE_SIZE * (1 << __STACK_SIZE_PAGE_ORDER))
+
+#endif /* __ARCH_LIMITS_H__ */
diff --git a/extras/mini-os/include/x86/arch_mm.h b/extras/mini-os/include/x86/arch_mm.h
index c5e106e6da..7ad8bc14be 100644
--- a/extras/mini-os/include/x86/arch_mm.h
+++ b/extras/mini-os/include/x86/arch_mm.h
@@ -157,16 +157,9 @@ typedef unsigned long pgentry_t;
#define L4_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
#endif /* __i386__ || __x86_64__ */
-#ifdef __ASSEMBLY__
-#define PAGE_SIZE (1 << L1_PAGETABLE_SHIFT)
-#else
-#ifndef CONFIG_X86_PAE
-#define PAGE_SIZE (1UL << L1_PAGETABLE_SHIFT)
-#else
-#define PAGE_SIZE (1ULL << L1_PAGETABLE_SHIFT)
-#endif
-#endif
-#define PAGE_SHIFT L1_PAGETABLE_SHIFT
+#include "arch_limits.h"
+#define PAGE_SIZE __PAGE_SIZE
+#define PAGE_SHIFT __PAGE_SHIFT
#define PAGE_MASK (~(PAGE_SIZE-1))
#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> L1_PAGETABLE_SHIFT)
@@ -177,9 +170,6 @@ typedef unsigned long pgentry_t;
/* to align the pointer to the (next) page boundary */
#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-#define STACK_SIZE_PAGE_ORDER 1
-#define STACK_SIZE (PAGE_SIZE * (1 << STACK_SIZE_PAGE_ORDER))
-
#ifndef __ASSEMBLY__
/* Definitions for machine and pseudophysical addresses. */
#ifdef CONFIG_X86_PAE
@@ -257,5 +247,11 @@ static __inline__ paddr_t machine_to_phys(maddr_t machine)
#define map_frames(f, n) map_frames_ex(f, n, 1, 0, 1, DOMID_SELF, 0, L1_PROT)
#define map_zero(n, a) map_frames_ex(&mfn_zero, n, 0, 0, a, DOMID_SELF, 0, L1_PROT_RO)
+#ifndef __ASSEMBLY__
+void do_map_frames(unsigned long addr,
+ unsigned long *f, unsigned long n, unsigned long stride,
+ unsigned long increment, domid_t id, int may_fail, unsigned long prot);
+#endif
+#define do_map_zero(start, n) do_map_frames(start, &mfn_zero, n, 0, 0, DOMID_SELF, 0, L1_PROT_RO)
#endif /* _ARCH_MM_H_ */
diff --git a/extras/mini-os/include/x86/arch_sched.h b/extras/mini-os/include/x86/arch_sched.h
index 877440762e..d80323cd37 100644
--- a/extras/mini-os/include/x86/arch_sched.h
+++ b/extras/mini-os/include/x86/arch_sched.h
@@ -2,7 +2,7 @@
#ifndef __ARCH_SCHED_H__
#define __ARCH_SCHED_H__
-#include <arch_mm.h>
+#include <arch_limits.h>
static inline struct thread* get_current(void)
{
@@ -12,7 +12,7 @@ static inline struct thread* get_current(void)
#else
register unsigned long sp asm("rsp");
#endif
- current = (void *)(unsigned long)(sp & ~(STACK_SIZE-1));
+ current = (void *)(unsigned long)(sp & ~(__STACK_SIZE-1));
return *current;
}
diff --git a/extras/mini-os/include/x86/arch_spinlock.h b/extras/mini-os/include/x86/arch_spinlock.h
index a181ed3c92..b711fe473c 100644
--- a/extras/mini-os/include/x86/arch_spinlock.h
+++ b/extras/mini-os/include/x86/arch_spinlock.h
@@ -4,6 +4,7 @@
#define __ARCH_ASM_SPINLOCK_H
#include <lib.h>
+#include "os.h"
#define ARCH_SPIN_LOCK_UNLOCKED (spinlock_t) { 1 }
diff --git a/extras/mini-os/include/x86/os.h b/extras/mini-os/include/x86/os.h
index 7a4433b3f9..7217d0b3ca 100644
--- a/extras/mini-os/include/x86/os.h
+++ b/extras/mini-os/include/x86/os.h
@@ -563,6 +563,7 @@ static __inline__ int synch_var_test_bit(int nr, volatile void * addr)
synch_var_test_bit((nr),(addr)))
+#undef ADDR
#endif /* not assembly */
#endif /* _OS_H_ */
diff --git a/extras/mini-os/lib/sys.c b/extras/mini-os/lib/sys.c
new file mode 100644
index 0000000000..f71e6966bd
--- /dev/null
+++ b/extras/mini-os/lib/sys.c
@@ -0,0 +1,1083 @@
+/*
+ * POSIX-compatible libc layer
+ *
+ * Samuel Thibault <Samuel.Thibault@eu.citrix.net>, October 2007
+ *
+ * Provides the UNIXish part of the standard libc function.
+ *
+ * Relatively straight-forward: just multiplex the file descriptor operations
+ * among the various file types (console, FS, network, ...)
+ */
+
+//#define LIBC_VERBOSE
+//#define LIBC_DEBUG
+
+#ifdef LIBC_DEBUG
+#define DEBUG(fmt,...) printk(fmt, ##__VA_ARGS__)
+#else
+#define DEBUG(fmt,...)
+#endif
+
+#ifdef HAVE_LIBC
+#include <os.h>
+#include <console.h>
+#include <sched.h>
+#include <events.h>
+#include <wait.h>
+#include <netfront.h>
+#include <blkfront.h>
+#include <xenbus.h>
+#include <xs.h>
+
+#include <sys/types.h>
+#include <sys/unistd.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <time.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <assert.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include <lwip/sockets.h>
+#include <fs.h>
+
+#define debug(fmt, ...) \
+
+#define print_unsupported(fmt, ...) \
+ printk("Unsupported function "fmt" called in Mini-OS kernel\n", ## __VA_ARGS__);
+
+/* Crash on function call */
+#define unsupported_function_crash(function) \
+ int __unsup_##function(void) asm(#function); \
+ int __unsup_##function(void) \
+ { \
+ print_unsupported(#function); \
+ do_exit(); \
+ }
+
+/* Log and err out on function call */
+#define unsupported_function_log(type, function, ret) \
+ type __unsup_##function(void) asm(#function); \
+ type __unsup_##function(void) \
+ { \
+ print_unsupported(#function); \
+ errno = ENOSYS; \
+ return ret; \
+ }
+
+/* Err out on function call */
+#define unsupported_function(type, function, ret) \
+ type __unsup_##function(void) asm(#function); \
+ type __unsup_##function(void) \
+ { \
+ errno = ENOSYS; \
+ return ret; \
+ }
+
+#define NOFILE 32
+extern int xc_evtchn_close(int fd);
+
+pthread_mutex_t fd_lock = PTHREAD_MUTEX_INITIALIZER;
+struct file files[NOFILE] = {
+ { .type = FTYPE_CONSOLE }, /* stdin */
+ { .type = FTYPE_CONSOLE }, /* stdout */
+ { .type = FTYPE_CONSOLE }, /* stderr */
+};
+
+DECLARE_WAIT_QUEUE_HEAD(event_queue);
+
+int alloc_fd(enum fd_type type)
+{
+ int i;
+ pthread_mutex_lock(&fd_lock);
+ for (i=0; i<NOFILE; i++) {
+ if (files[i].type == FTYPE_NONE) {
+ files[i].type = type;
+ pthread_mutex_unlock(&fd_lock);
+ return i;
+ }
+ }
+ pthread_mutex_unlock(&fd_lock);
+ printk("Too many opened files\n");
+ do_exit();
+}
+
+void close_all_files(void)
+{
+ int i;
+ pthread_mutex_lock(&fd_lock);
+ for (i=NOFILE - 1; i > 0; i--)
+ if (files[i].type != FTYPE_NONE)
+ close(i);
+ pthread_mutex_unlock(&fd_lock);
+}
+
+int dup2(int oldfd, int newfd)
+{
+ pthread_mutex_lock(&fd_lock);
+ if (files[newfd].type != FTYPE_NONE)
+ close(newfd);
+ // XXX: this is a bit bogus, as we are supposed to share the offset etc
+ files[newfd] = files[oldfd];
+ pthread_mutex_unlock(&fd_lock);
+ return 0;
+}
+
+pid_t getpid(void)
+{
+ return 1;
+}
+
+pid_t getppid(void)
+{
+ return 1;
+}
+
+pid_t setsid(void)
+{
+ return 1;
+}
+
+char *getcwd(char *buf, size_t size)
+{
+ snprintf(buf, size, "/");
+ return buf;
+}
+
+#define LOG_PATH "/var/log/"
+
+int mkdir(const char *pathname, mode_t mode)
+{
+ int ret;
+ ret = fs_create(fs_import, (char *) pathname, 1, mode);
+ if (ret < 0) {
+ errno = EIO;
+ return -1;
+ }
+ return 0;
+}
+
+int open(const char *pathname, int flags, ...)
+{
+ int fs_fd, fd;
+ /* Ugly, but fine. */
+ if (!strncmp(pathname,LOG_PATH,strlen(LOG_PATH))) {
+ fd = alloc_fd(FTYPE_CONSOLE);
+ printk("open(%s) -> %d\n", pathname, fd);
+ return fd;
+ }
+ printk("open(%s)", pathname);
+ fs_fd = fs_open(fs_import, (void *) pathname);
+ if (fs_fd < 0) {
+ errno = EIO;
+ return -1;
+ }
+ fd = alloc_fd(FTYPE_FILE);
+ printk("-> %d\n", fd);
+ files[fd].file.fd = fs_fd;
+ files[fd].file.offset = 0;
+ return fd;
+}
+#if defined(__x86_64__) || defined(__ia64__)
+__typeof__(open) open64 __attribute__((__alias__("open")));
+#endif
+
+int isatty(int fd)
+{
+ return files[fd].type == FTYPE_CONSOLE;
+}
+
+int read(int fd, void *buf, size_t nbytes)
+{
+ switch (files[fd].type) {
+ case FTYPE_CONSOLE:
+ return 0;
+ case FTYPE_FILE: {
+ ssize_t ret;
+ if (nbytes > PAGE_SIZE)
+ nbytes = PAGE_SIZE;
+ ret = fs_read(fs_import, files[fd].file.fd, buf, nbytes, files[fd].file.offset);
+ if (ret > 0) {
+ files[fd].file.offset += ret;
+ return ret;
+ } else if (ret < 0) {
+ errno = EIO;
+ return -1;
+ }
+ return 0;
+ }
+ case FTYPE_SOCKET:
+ return lwip_read(files[fd].socket.fd, buf, nbytes);
+ case FTYPE_TAP: {
+ ssize_t ret;
+ ret = netfront_receive(files[fd].tap.dev, buf, nbytes);
+ if (ret <= 0) {
+ errno = EAGAIN;
+ return -1;
+ }
+ return ret;
+ }
+ case FTYPE_NONE:
+ case FTYPE_XENBUS:
+ case FTYPE_EVTCHN:
+ case FTYPE_BLK:
+ break;
+ }
+ printk("read(%d): Bad descriptor\n", fd);
+ errno = EBADF;
+ return -1;
+}
+
+int write(int fd, const void *buf, size_t nbytes)
+{
+ switch (files[fd].type) {
+ case FTYPE_CONSOLE:
+ console_print((char *)buf, nbytes);
+ return nbytes;
+ case FTYPE_FILE: {
+ ssize_t ret;
+ if (nbytes > PAGE_SIZE)
+ nbytes = PAGE_SIZE;
+ ret = fs_write(fs_import, files[fd].file.fd, (void *) buf, nbytes, files[fd].file.offset);
+ if (ret > 0) {
+ files[fd].file.offset += ret;
+ return ret;
+ } else if (ret < 0) {
+ errno = EIO;
+ return -1;
+ }
+ return 0;
+ }
+ case FTYPE_SOCKET:
+ return lwip_write(files[fd].socket.fd, (void*) buf, nbytes);
+ case FTYPE_TAP:
+ netfront_xmit(files[fd].tap.dev, (void*) buf, nbytes);
+ return nbytes;
+ case FTYPE_NONE:
+ case FTYPE_XENBUS:
+ case FTYPE_EVTCHN:
+ case FTYPE_BLK:
+ break;
+ }
+ printk("write(%d): Bad descriptor\n", fd);
+ errno = EBADF;
+ return -1;
+}
+
+off_t lseek(int fd, off_t offset, int whence)
+{
+ if (files[fd].type != FTYPE_FILE) {
+ errno = ESPIPE;
+ return (off_t) -1;
+ }
+ switch (whence) {
+ case SEEK_SET:
+ files[fd].file.offset = offset;
+ break;
+ case SEEK_CUR:
+ files[fd].file.offset += offset;
+ break;
+ case SEEK_END: {
+ struct stat st;
+ int ret;
+ ret = fstat(fd, &st);
+ if (ret)
+ return -1;
+ files[fd].file.offset = st.st_size + offset;
+ break;
+ }
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+ return files[fd].file.offset;
+}
+#if defined(__x86_64__) || defined(__ia64__)
+__typeof__(lseek) lseek64 __attribute__((__alias__("lseek")));
+#endif
+
+int fsync(int fd) {
+ switch (files[fd].type) {
+ case FTYPE_FILE: {
+ int ret;
+ ret = fs_sync(fs_import, files[fd].file.fd);
+ if (ret < 0) {
+ errno = EIO;
+ return -1;
+ }
+ return 0;
+ }
+ case FTYPE_NONE:
+ case FTYPE_CONSOLE:
+ case FTYPE_SOCKET:
+ case FTYPE_XENBUS:
+ case FTYPE_EVTCHN:
+ case FTYPE_TAP:
+ case FTYPE_BLK:
+ break;
+ }
+ printk("fsync(%d): Bad descriptor\n", fd);
+ errno = EBADF;
+ return -1;
+}
+
+int close(int fd)
+{
+ printk("close(%d)\n", fd);
+ switch (files[fd].type) {
+ case FTYPE_CONSOLE:
+ files[fd].type = FTYPE_NONE;
+ return 0;
+ case FTYPE_FILE: {
+ int ret = fs_close(fs_import, files[fd].file.fd);
+ files[fd].type = FTYPE_NONE;
+ if (ret < 0) {
+ errno = EIO;
+ return -1;
+ }
+ return 0;
+ }
+ case FTYPE_XENBUS:
+ xs_daemon_close((void*)(intptr_t) fd);
+ return 0;
+ case FTYPE_SOCKET: {
+ int res = lwip_close(files[fd].socket.fd);
+ files[fd].type = FTYPE_NONE;
+ return res;
+ }
+ case FTYPE_EVTCHN:
+ xc_evtchn_close(fd);
+ return 0;
+ case FTYPE_TAP:
+ shutdown_netfront(files[fd].tap.dev);
+ files[fd].type = FTYPE_NONE;
+ return 0;
+ case FTYPE_BLK:
+ shutdown_blkfront(files[fd].blk.dev);
+ files[fd].type = FTYPE_NONE;
+ return 0;
+ case FTYPE_NONE:
+ break;
+ }
+ printk("close(%d): Bad descriptor\n", fd);
+ errno = EBADF;
+ return -1;
+}
+
+static void init_stat(struct stat *buf)
+{
+ memset(buf, 0, sizeof(*buf));
+ buf->st_dev = 0;
+ buf->st_ino = 0;
+ buf->st_nlink = 1;
+ buf->st_rdev = 0;
+ buf->st_blksize = 4096;
+ buf->st_blocks = 0;
+}
+
+static void stat_from_fs(struct stat *buf, struct fsif_stat_response *stat)
+{
+ buf->st_mode = stat->stat_mode;
+ buf->st_uid = stat->stat_uid;
+ buf->st_gid = stat->stat_gid;
+ buf->st_size = stat->stat_size;
+ buf->st_atime = stat->stat_atime;
+ buf->st_mtime = stat->stat_mtime;
+ buf->st_ctime = stat->stat_ctime;
+}
+
+int stat(const char *path, struct stat *buf)
+{
+ struct fsif_stat_response stat;
+ int ret;
+ int fs_fd;
+ printk("stat(%s)\n", path);
+ fs_fd = fs_open(fs_import, (char*) path);
+ if (fs_fd < 0) {
+ errno = EIO;
+ ret = -1;
+ goto out;
+ }
+ ret = fs_stat(fs_import, fs_fd, &stat);
+ if (ret < 0) {
+ errno = EIO;
+ ret = -1;
+ goto outfd;
+ }
+ init_stat(buf);
+ stat_from_fs(buf, &stat);
+ ret = 0;
+
+outfd:
+ fs_close(fs_import, fs_fd);
+out:
+ return ret;
+}
+
+int fstat(int fd, struct stat *buf)
+{
+ init_stat(buf);
+ switch (files[fd].type) {
+ case FTYPE_CONSOLE:
+ case FTYPE_SOCKET: {
+ buf->st_mode = (files[fd].type == FTYPE_CONSOLE?S_IFCHR:S_IFSOCK) | S_IRUSR|S_IWUSR;
+ buf->st_uid = 0;
+ buf->st_gid = 0;
+ buf->st_size = 0;
+ buf->st_atime =
+ buf->st_mtime =
+ buf->st_ctime = time(NULL);
+ return 0;
+ }
+ case FTYPE_FILE: {
+ struct fsif_stat_response stat;
+ int ret;
+ ret = fs_stat(fs_import, files[fd].file.fd, &stat);
+ if (ret < 0) {
+ errno = EIO;
+ return -1;
+ }
+ /* The protocol is a bit evasive about this value */
+ stat_from_fs(buf, &stat);
+ return 0;
+ }
+ case FTYPE_NONE:
+ case FTYPE_XENBUS:
+ case FTYPE_EVTCHN:
+ case FTYPE_TAP:
+ case FTYPE_BLK:
+ break;
+ }
+
+ printk("statf(%d): Bad descriptor\n", fd);
+ errno = EBADF;
+ return -1;
+}
+
+int ftruncate(int fd, off_t length)
+{
+ switch (files[fd].type) {
+ case FTYPE_FILE: {
+ int ret;
+ ret = fs_truncate(fs_import, files[fd].file.fd, length);
+ if (ret < 0) {
+ errno = EIO;
+ return -1;
+ }
+ return 0;
+ }
+ case FTYPE_NONE:
+ case FTYPE_CONSOLE:
+ case FTYPE_SOCKET:
+ case FTYPE_XENBUS:
+ case FTYPE_EVTCHN:
+ case FTYPE_TAP:
+ case FTYPE_BLK:
+ break;
+ }
+
+ printk("ftruncate(%d): Bad descriptor\n", fd);
+ errno = EBADF;
+ return -1;
+}
+
+int remove(const char *pathname)
+{
+ int ret;
+ printk("remove(%s)", pathname);
+ ret = fs_remove(fs_import, (char*) pathname);
+ if (ret < 0) {
+ errno = EIO;
+ return -1;
+ }
+ return 0;
+}
+
+int unlink(const char *pathname)
+{
+ return remove(pathname);
+}
+
+int rmdir(const char *pathname)
+{
+ return remove(pathname);
+}
+
+int fcntl(int fd, int cmd, ...)
+{
+ long arg;
+ va_list ap;
+ va_start(ap, cmd);
+ arg = va_arg(ap, long);
+ va_end(ap);
+
+ switch (cmd) {
+ case F_SETFL:
+ if (files[fd].type == FTYPE_SOCKET && !(arg & ~O_NONBLOCK)) {
+ /* Only flag supported: non-blocking mode */
+ uint32_t nblock = !!(arg & O_NONBLOCK);
+ return lwip_ioctl(files[fd].socket.fd, FIONBIO, &nblock);
+ }
+ /* Fallthrough */
+ default:
+ printk("fcntl(%d, %d, %lx/%lo)\n", fd, cmd, arg, arg);
+ errno = ENOSYS;
+ return -1;
+ }
+}
+
+DIR *opendir(const char *name)
+{
+ DIR *ret;
+ ret = malloc(sizeof(*ret));
+ ret->name = strdup(name);
+ ret->offset = 0;
+ ret->entries = NULL;
+ ret->curentry = -1;
+ ret->nbentries = 0;
+ ret->has_more = 1;
+ return ret;
+}
+
+struct dirent *readdir(DIR *dir)
+{
+ if (dir->curentry >= 0) {
+ free(dir->entries[dir->curentry]);
+ dir->entries[dir->curentry] = NULL;
+ }
+ dir->curentry++;
+ if (dir->curentry >= dir->nbentries) {
+ dir->offset += dir->nbentries;
+ free(dir->entries);
+ dir->curentry = -1;
+ dir->nbentries = 0;
+ if (!dir->has_more)
+ return NULL;
+ dir->entries = fs_list(fs_import, dir->name, dir->offset, &dir->nbentries, &dir->has_more);
+ if (!dir->entries || !dir->nbentries)
+ return NULL;
+ dir->curentry = 0;
+ }
+ dir->dirent.d_name = dir->entries[dir->curentry];
+ return &dir->dirent;
+}
+int closedir(DIR *dir)
+{
+ int i;
+ for (i=0; i<dir->nbentries; i++)
+ free(dir->entries[i]);
+ free(dir->entries);
+ free(dir->name);
+ free(dir);
+ return 0;
+}
+
+/* We assume that only the main thread calls select(). */
+
+static const char file_types[] = {
+ [FTYPE_NONE] = 'N',
+ [FTYPE_CONSOLE] = 'C',
+ [FTYPE_FILE] = 'F',
+ [FTYPE_XENBUS] = 'X',
+ [FTYPE_EVTCHN] = 'E',
+ [FTYPE_SOCKET] = 'S',
+ [FTYPE_TAP] = 'T',
+ [FTYPE_BLK] = 'B',
+};
+#ifdef LIBC_DEBUG
+static void dump_set(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
+{
+ int i, comma;
+#define printfds(set) do {\
+ comma = 0; \
+ for (i = 0; i < nfds; i++) { \
+ if (FD_ISSET(i, set)) { \
+ if (comma) \
+ printk(", "); \
+ printk("%d(%c)", i, file_types[files[i].type]); \
+ comma = 1; \
+ } \
+ } \
+} while (0)
+
+ printk("[");
+ if (readfds)
+ printfds(readfds);
+ printk("], [");
+ if (writefds)
+ printfds(writefds);
+ printk("], [");
+ if (exceptfds)
+ printfds(exceptfds);
+ printk("], ");
+ if (timeout)
+ printk("{ %ld, %ld }", timeout->tv_sec, timeout->tv_usec);
+}
+#else
+#define dump_set(nfds, readfds, writefds, exceptfds, timeout)
+#endif
+
+/* Just poll without blocking */
+static int select_poll(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
+{
+ int i, n = 0, sock_n, sock_nfds = 0;
+ fd_set sock_readfds, sock_writefds, sock_exceptfds;
+ struct timeval timeout = { .tv_sec = 0, .tv_usec = 0};
+
+#ifdef LIBC_VERBOSE
+ static int nb;
+ static int nbread[NOFILE], nbwrite[NOFILE], nbexcept[NOFILE];
+ static s64_t lastshown;
+
+ nb++;
+#endif
+
+ /* first poll network */
+ FD_ZERO(&sock_readfds);
+ FD_ZERO(&sock_writefds);
+ FD_ZERO(&sock_exceptfds);
+ for (i = 0; i < nfds; i++) {
+ if (files[i].type == FTYPE_SOCKET) {
+ if (FD_ISSET(i, readfds)) {
+ FD_SET(files[i].socket.fd, &sock_readfds);
+ sock_nfds = i+1;
+ }
+ if (FD_ISSET(i, writefds)) {
+ FD_SET(files[i].socket.fd, &sock_writefds);
+ sock_nfds = i+1;
+ }
+ if (FD_ISSET(i, exceptfds)) {
+ FD_SET(files[i].socket.fd, &sock_exceptfds);
+ sock_nfds = i+1;
+ }
+ }
+ }
+ DEBUG("lwip_select(");
+ dump_set(nfds, &sock_readfds, &sock_writefds, &sock_exceptfds, &timeout);
+ DEBUG("); -> ");
+ sock_n = lwip_select(sock_nfds, &sock_readfds, &sock_writefds, &sock_exceptfds, &timeout);
+ dump_set(nfds, &sock_readfds, &sock_writefds, &sock_exceptfds, &timeout);
+ DEBUG("\n");
+
+ /* Then see others as well. */
+ for (i = 0; i < nfds; i++) {
+ switch(files[i].type) {
+ case FTYPE_NONE:
+ if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds))
+ printk("bogus fd %d in select\n", i);
+ /* Fallthrough. */
+ case FTYPE_FILE:
+ FD_CLR(i, readfds);
+ FD_CLR(i, writefds);
+ FD_CLR(i, exceptfds);
+ break;
+ case FTYPE_CONSOLE:
+ FD_CLR(i, readfds);
+ if (FD_ISSET(i, writefds))
+ n++;
+ FD_CLR(i, exceptfds);
+ break;
+ case FTYPE_XENBUS:
+ if (FD_ISSET(i, readfds)) {
+ if (files[i].xenbus.events)
+ n++;
+ else
+ FD_CLR(i, readfds);
+ }
+ FD_CLR(i, writefds);
+ FD_CLR(i, exceptfds);
+ break;
+ case FTYPE_EVTCHN:
+ case FTYPE_TAP:
+ case FTYPE_BLK:
+ if (FD_ISSET(i, readfds)) {
+ if (files[i].read)
+ n++;
+ else
+ FD_CLR(i, readfds);
+ }
+ FD_CLR(i, writefds);
+ FD_CLR(i, exceptfds);
+ break;
+ case FTYPE_SOCKET:
+ if (FD_ISSET(i, readfds)) {
+ /* Optimize no-network-packet case. */
+ if (sock_n && FD_ISSET(files[i].socket.fd, &sock_readfds))
+ n++;
+ else
+ FD_CLR(i, readfds);
+ }
+ if (FD_ISSET(i, writefds)) {
+ if (sock_n && FD_ISSET(files[i].socket.fd, &sock_writefds))
+ n++;
+ else
+ FD_CLR(i, writefds);
+ }
+ if (FD_ISSET(i, exceptfds)) {
+ if (sock_n && FD_ISSET(files[i].socket.fd, &sock_exceptfds))
+ n++;
+ else
+ FD_CLR(i, exceptfds);
+ }
+ break;
+ }
+#ifdef LIBC_VERBOSE
+ if (FD_ISSET(i, readfds))
+ nbread[i]++;
+ if (FD_ISSET(i, writefds))
+ nbwrite[i]++;
+ if (FD_ISSET(i, exceptfds))
+ nbexcept[i]++;
+#endif
+ }
+#ifdef LIBC_VERBOSE
+ if (NOW() > lastshown + 1000000000ull) {
+ lastshown = NOW();
+ printk("%lu MB free, ", num_free_pages() / ((1 << 20) / PAGE_SIZE));
+ printk("%d(%d): ", nb, sock_n);
+ for (i = 0; i < nfds; i++) {
+ if (nbread[i] || nbwrite[i] || nbexcept[i])
+ printk(" %d(%c):", i, file_types[files[i].type]);
+ if (nbread[i])
+ printk(" %dR", nbread[i]);
+ if (nbwrite[i])
+ printk(" %dW", nbwrite[i]);
+ if (nbexcept[i])
+ printk(" %dE", nbexcept[i]);
+ }
+ printk("\n");
+ memset(nbread, 0, sizeof(nbread));
+ memset(nbwrite, 0, sizeof(nbwrite));
+ memset(nbexcept, 0, sizeof(nbexcept));
+ nb = 0;
+ }
+#endif
+ return n;
+}
+
+/* The strategy is to
+ * - announce that we will maybe sleep
+ * - poll a bit ; if successful, return
+ * - if timeout, return
+ * - really sleep (except if somebody woke us in the meanwhile) */
+int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ struct timeval *timeout)
+{
+ int n, ret;
+ fd_set myread, mywrite, myexcept;
+ struct thread *thread = get_current();
+ s_time_t start = NOW(), stop;
+ DEFINE_WAIT(w1);
+ DEFINE_WAIT(w2);
+ DEFINE_WAIT(w3);
+ DEFINE_WAIT(w4);
+
+ assert(thread == main_thread);
+
+ DEBUG("select(%d, ", nfds);
+ dump_set(nfds, readfds, writefds, exceptfds, timeout);
+ DEBUG(");\n");
+
+ if (timeout)
+ stop = start + SECONDS(timeout->tv_sec) + timeout->tv_usec * 1000;
+ else
+ /* just make gcc happy */
+ stop = start;
+
+ /* Tell people we're going to sleep before looking at what they are
+ * saying, hence letting them wake us if events happen between here and
+ * schedule() */
+ add_waiter(w1, netfront_queue);
+ add_waiter(w2, event_queue);
+ add_waiter(w3, blkfront_queue);
+ add_waiter(w4, xenbus_watch_queue);
+
+ myread = *readfds;
+ mywrite = *writefds;
+ myexcept = *exceptfds;
+ DEBUG("polling ");
+ dump_set(nfds, &myread, &mywrite, &myexcept, timeout);
+ DEBUG("\n");
+ n = select_poll(nfds, &myread, &mywrite, &myexcept);
+
+ if (n) {
+ dump_set(nfds, readfds, writefds, exceptfds, timeout);
+ if (readfds)
+ *readfds = myread;
+ if (writefds)
+ *writefds = mywrite;
+ if (exceptfds)
+ *exceptfds = myexcept;
+ DEBUG(" -> ");
+ dump_set(nfds, readfds, writefds, exceptfds, timeout);
+ DEBUG("\n");
+ wake(thread);
+ ret = n;
+ goto out;
+ }
+ if (timeout && NOW() >= stop) {
+ if (readfds)
+ FD_ZERO(readfds);
+ if (writefds)
+ FD_ZERO(writefds);
+ if (exceptfds)
+ FD_ZERO(exceptfds);
+ timeout->tv_sec = 0;
+ timeout->tv_usec = 0;
+ wake(thread);
+ ret = 0;
+ goto out;
+ }
+
+ if (timeout)
+ thread->wakeup_time = stop;
+ schedule();
+
+ myread = *readfds;
+ mywrite = *writefds;
+ myexcept = *exceptfds;
+ n = select_poll(nfds, &myread, &mywrite, &myexcept);
+
+ if (n) {
+ if (readfds)
+ *readfds = myread;
+ if (writefds)
+ *writefds = mywrite;
+ if (exceptfds)
+ *exceptfds = myexcept;
+ ret = n;
+ goto out;
+ }
+ errno = EINTR;
+ ret = -1;
+
+out:
+ remove_waiter(w1);
+ remove_waiter(w2);
+ remove_waiter(w3);
+ remove_waiter(w4);
+ return ret;
+}
+
+int socket(int domain, int type, int protocol)
+{
+ int fd, res;
+ fd = lwip_socket(domain, type, protocol);
+ if (fd < 0)
+ return -1;
+ res = alloc_fd(FTYPE_SOCKET);
+ printk("socket -> %d\n", res);
+ files[res].socket.fd = fd;
+ return res;
+}
+
+int accept(int s, struct sockaddr *addr, socklen_t *addrlen)
+{
+ int fd, res;
+ if (files[s].type != FTYPE_SOCKET) {
+ printk("accept(%d): Bad descriptor\n", s);
+ errno = EBADF;
+ return -1;
+ }
+ fd = lwip_accept(files[s].socket.fd, addr, addrlen);
+ if (fd < 0)
+ return -1;
+ res = alloc_fd(FTYPE_SOCKET);
+ files[res].socket.fd = fd;
+ printk("accepted on %d -> %d\n", s, res);
+ return res;
+}
+
+#define LWIP_STUB(ret, name, proto, args) \
+ret name proto \
+{ \
+ if (files[s].type != FTYPE_SOCKET) { \
+ printk(#name "(%d): Bad descriptor\n", s); \
+ errno = EBADF; \
+ return -1; \
+ } \
+ s = files[s].socket.fd; \
+ return lwip_##name args; \
+}
+
+LWIP_STUB(int, bind, (int s, struct sockaddr *my_addr, socklen_t addrlen), (s, my_addr, addrlen))
+LWIP_STUB(int, getsockopt, (int s, int level, int optname, void *optval, socklen_t *optlen), (s, level, optname, optval, optlen))
+LWIP_STUB(int, setsockopt, (int s, int level, int optname, void *optval, socklen_t optlen), (s, level, optname, optval, optlen))
+LWIP_STUB(int, connect, (int s, struct sockaddr *serv_addr, socklen_t addrlen), (s, serv_addr, addrlen))
+LWIP_STUB(int, listen, (int s, int backlog), (s, backlog));
+LWIP_STUB(ssize_t, recv, (int s, void *buf, size_t len, int flags), (s, buf, len, flags))
+LWIP_STUB(ssize_t, recvfrom, (int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen), (s, buf, len, flags, from, fromlen))
+LWIP_STUB(ssize_t, send, (int s, void *buf, size_t len, int flags), (s, buf, len, flags))
+LWIP_STUB(ssize_t, sendto, (int s, void *buf, size_t len, int flags, struct sockaddr *to, socklen_t tolen), (s, buf, len, flags, to, tolen))
+LWIP_STUB(int, getsockname, (int s, struct sockaddr *name, socklen_t *namelen), (s, name, namelen))
+
+int nanosleep(const struct timespec *req, struct timespec *rem)
+{
+ s_time_t start = NOW();
+ s_time_t stop = start + SECONDS(req->tv_sec) + req->tv_nsec;
+ s_time_t stopped;
+ struct thread *thread = get_current();
+
+ thread->wakeup_time = stop;
+ clear_runnable(thread);
+ schedule();
+ stopped = NOW();
+
+ if (rem)
+ {
+ s_time_t remaining = stop - stopped;
+ if (remaining > 0)
+ {
+ rem->tv_nsec = remaining % 1000000000ULL;
+ rem->tv_sec = remaining / 1000000000ULL;
+ } else memset(rem, 0, sizeof(*rem));
+ }
+
+ return 0;
+}
+
+int usleep(useconds_t usec)
+{
+ /* "usec shall be less than one million." */
+ struct timespec req;
+ req.tv_nsec = usec * 1000;
+ req.tv_sec = 0;
+
+ if (nanosleep(&req, NULL))
+ return -1;
+
+ return 0;
+}
+
+unsigned int sleep(unsigned int seconds)
+{
+ struct timespec req, rem;
+ req.tv_sec = seconds;
+ req.tv_nsec = 0;
+
+ if (nanosleep(&req, &rem))
+ return -1;
+
+ if (rem.tv_nsec > 0)
+ rem.tv_sec++;
+
+ return rem.tv_sec;
+}
+
+int clock_gettime(clockid_t clk_id, struct timespec *tp)
+{
+ switch (clk_id) {
+ case CLOCK_MONOTONIC:
+ {
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+
+ tp->tv_sec = tv.tv_sec;
+ tp->tv_nsec = tv.tv_usec * 1000;
+
+ break;
+ }
+ case CLOCK_REALTIME:
+ {
+ u64 nsec = monotonic_clock();
+
+ tp->tv_sec = nsec / 1000000000ULL;
+ tp->tv_nsec = nsec % 1000000000ULL;
+
+ break;
+ }
+ default:
+ print_unsupported("clock_gettime(%d)", clk_id);
+ errno = EINVAL;
+ return -1;
+ }
+
+ return 0;
+}
+
+void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
+{
+ ASSERT(!start);
+ length = (length + PAGE_SIZE - 1) & PAGE_MASK;
+ ASSERT(prot == (PROT_READ|PROT_WRITE));
+ ASSERT(flags == (MAP_SHARED|MAP_ANON) || flags == (MAP_PRIVATE|MAP_ANON));
+ ASSERT(fd == -1);
+ ASSERT(offset == 0);
+
+ return map_zero(length / PAGE_SIZE, 1);
+}
+#if defined(__x86_64__) || defined(__ia64__)
+__typeof__(mmap) mmap64 __attribute__((__alias__("mmap")));
+#endif
+
+int munmap(void *start, size_t length)
+{
+ int i, n = length / PAGE_SIZE;
+ multicall_entry_t call[n];
+ unsigned char (*data)[PAGE_SIZE] = start;
+ int ret;
+ ASSERT(!((unsigned long)start & ~PAGE_MASK));
+ ASSERT(!(length & ~PAGE_MASK));
+
+ for (i = 0; i < n; i++) {
+ call[i].op = __HYPERVISOR_update_va_mapping;
+ call[i].args[0] = (unsigned long) &data[i];
+ call[i].args[1] = 0;
+ call[i].args[2] = 0;
+ call[i].args[3] = UVMF_INVLPG | UVMF_ALL;
+ }
+
+ ret = HYPERVISOR_multicall(call, n);
+ if (ret) {
+ errno = -ret;
+ return -1;
+ }
+
+ for (i = 0; i < n; i++) {
+ if (call[i].result) {
+ errno = call[i].result;
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/* Not supported by FS yet. */
+unsupported_function_crash(link);
+unsupported_function(int, readlink, -1);
+
+/* We could support that. */
+unsupported_function_log(int, chdir, -1);
+
+/* No dynamic library support. */
+unsupported_function_log(void *, dlopen, NULL);
+unsupported_function_log(void *, dlsym, NULL);
+unsupported_function_log(char *, dlerror, NULL);
+unsupported_function_log(int, dlclose, -1);
+
+/* We don't raise signals anyway. */
+unsupported_function(int, sigemptyset, -1);
+unsupported_function(int, sigfillset, -1);
+unsupported_function(int, sigaddset, -1);
+unsupported_function(int, sigdelset, -1);
+unsupported_function(int, sigismember, -1);
+unsupported_function(int, sigprocmask, -1);
+unsupported_function(int, sigaction, -1);
+unsupported_function(int, __sigsetjmp, 0);
+unsupported_function(int, sigaltstack, -1);
+unsupported_function_crash(kill);
+
+/* Linuxish abi for the Caml runtime, don't support */
+unsupported_function_log(struct dirent *, readdir64, NULL);
+unsupported_function_log(int, getrusage, -1);
+unsupported_function_log(int, getrlimit, -1);
+unsupported_function_log(int, getrlimit64, -1);
+unsupported_function_log(int, __xstat64, -1);
+unsupported_function_log(long, __strtol_internal, LONG_MIN);
+unsupported_function_log(double, __strtod_internal, HUGE_VAL);
+#endif
diff --git a/extras/mini-os/lib/xmalloc.c b/extras/mini-os/lib/xmalloc.c
index 9e59c9f834..d4c3941738 100644
--- a/extras/mini-os/lib/xmalloc.c
+++ b/extras/mini-os/lib/xmalloc.c
@@ -62,10 +62,19 @@ struct xmalloc_pad
size_t hdr_size;
};
+/* Return size, increased to alignment with align. */
+static inline size_t align_up(size_t size, size_t align)
+{
+ return (size + align - 1) & ~(align - 1);
+}
+
static void maybe_split(struct xmalloc_hdr *hdr, size_t size, size_t block)
{
struct xmalloc_hdr *extra;
- size_t leftover = block - size;
+ size_t leftover;
+ size = align_up(size, __alignof__(struct xmalloc_hdr));
+ size = align_up(size, __alignof__(struct xmalloc_pad));
+ leftover = block - size;
/* If enough is left to make a block, put it on free list. */
if ( leftover >= (2 * (sizeof(struct xmalloc_hdr) + sizeof(struct xmalloc_pad))) )
@@ -100,12 +109,6 @@ static struct xmalloc_hdr *xmalloc_new_page(size_t size)
return hdr;
}
-/* Return size, increased to alignment with align. */
-static inline size_t align_up(size_t size, size_t align)
-{
- return (size + align - 1) & ~(align - 1);
-}
-
/* Big object? Just use the page allocator. */
static void *xmalloc_whole_pages(size_t size, size_t align)
{
diff --git a/extras/mini-os/lib/xs.c b/extras/mini-os/lib/xs.c
new file mode 100644
index 0000000000..b654b0ee5d
--- /dev/null
+++ b/extras/mini-os/lib/xs.c
@@ -0,0 +1,187 @@
+/*
+ * libxs-compatible layer
+ *
+ * Samuel Thibault <Samuel.Thibault@eu.citrix.net>, 2007-2008
+ *
+ * Mere wrapper around xenbus_*
+ */
+
+#ifdef HAVE_LIBC
+#include <os.h>
+#include <lib.h>
+#include <xs.h>
+#include <xenbus.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static inline int _xs_fileno(struct xs_handle *h) {
+ return (intptr_t) h;
+}
+
+struct xs_handle *xs_daemon_open()
+{
+ int fd = alloc_fd(FTYPE_XENBUS);
+ files[fd].xenbus.events = NULL;
+ printk("xs_daemon_open -> %d, %p\n", fd, &files[fd].xenbus.events);
+ return (void*)(intptr_t) fd;
+}
+
+void xs_daemon_close(struct xs_handle *h)
+{
+ int fd = _xs_fileno(h);
+ struct xenbus_event *event;
+ for (event = files[fd].xenbus.events; event; event = event->next)
+ free(event);
+ files[fd].type = FTYPE_NONE;
+}
+
+int xs_fileno(struct xs_handle *h)
+{
+ return _xs_fileno(h);
+}
+
+void *xs_read(struct xs_handle *h, xs_transaction_t t,
+ const char *path, unsigned int *len)
+{
+ char *value;
+ char *msg;
+
+ msg = xenbus_read(t, path, &value);
+ if (msg) {
+ printk("xs_read(%s): %s\n", path, msg);
+ return NULL;
+ }
+
+ if (len)
+ *len = strlen(value);
+ return value;
+}
+
+bool xs_write(struct xs_handle *h, xs_transaction_t t,
+ const char *path, const void *data, unsigned int len)
+{
+ char value[len + 1];
+ char *msg;
+
+ memcpy(value, data, len);
+ value[len] = 0;
+
+ msg = xenbus_write(t, path, value);
+ if (msg) {
+ printk("xs_write(%s): %s\n", path, msg);
+ return false;
+ }
+ return true;
+}
+
+static bool xs_bool(char *reply)
+{
+ if (!reply)
+ return true;
+ free(reply);
+ return false;
+}
+
+bool xs_rm(struct xs_handle *h, xs_transaction_t t, const char *path)
+{
+ return xs_bool(xenbus_rm(t, path));
+}
+
+static void *xs_talkv(struct xs_handle *h, xs_transaction_t t,
+ enum xsd_sockmsg_type type,
+ struct write_req *iovec,
+ unsigned int num_vecs,
+ unsigned int *len)
+{
+ struct xsd_sockmsg *msg;
+ void *ret;
+
+ msg = xenbus_msg_reply(type, t, iovec, num_vecs);
+ ret = malloc(msg->len);
+ memcpy(ret, (char*) msg + sizeof(*msg), msg->len);
+ if (len)
+ *len = msg->len - 1;
+ free(msg);
+ return ret;
+}
+
+static void *xs_single(struct xs_handle *h, xs_transaction_t t,
+ enum xsd_sockmsg_type type,
+ const char *string,
+ unsigned int *len)
+{
+ struct write_req iovec;
+
+ iovec.data = (void *)string;
+ iovec.len = strlen(string) + 1;
+
+ return xs_talkv(h, t, type, &iovec, 1, len);
+}
+
+char *xs_get_domain_path(struct xs_handle *h, unsigned int domid)
+{
+ char domid_str[MAX_STRLEN(domid)];
+
+ sprintf(domid_str, "%u", domid);
+
+ return xs_single(h, XBT_NULL, XS_GET_DOMAIN_PATH, domid_str, NULL);
+}
+
+char **xs_directory(struct xs_handle *h, xs_transaction_t t,
+ const char *path, unsigned int *num)
+{
+ char *msg;
+ char **entries, **res;
+ char *entry;
+ int i, n;
+ int size;
+
+ msg = xenbus_ls(t, path, &res);
+ if (msg) {
+ printk("xs_directory(%s): %s\n", path, msg);
+ return NULL;
+ }
+
+ size = 0;
+ for (n = 0; res[n]; n++)
+ size += strlen(res[n]) + 1;
+
+ entries = malloc(n * sizeof(char *) + size);
+ entry = (char *) (&entries[n]);
+
+ for (i = 0; i < n; i++) {
+ int l = strlen(res[i]) + 1;
+ memcpy(entry, res[i], l);
+ free(res[i]);
+ entries[i] = entry;
+ entry += l;
+ }
+
+ *num = n;
+ return entries;
+}
+
+bool xs_watch(struct xs_handle *h, const char *path, const char *token)
+{
+ int fd = _xs_fileno(h);
+ printk("xs_watch(%s, %s)\n", path, token);
+ return xs_bool(xenbus_watch_path_token(XBT_NULL, path, token, &files[fd].xenbus.events));
+}
+
+char **xs_read_watch(struct xs_handle *h, unsigned int *num)
+{
+ int fd = _xs_fileno(h);
+ struct xenbus_event *event;
+ event = files[fd].xenbus.events;
+ files[fd].xenbus.events = event->next;
+ printk("xs_read_watch() -> %s %s\n", event->path, event->token);
+ *num = 2;
+ return (char **) &event->path;
+}
+
+bool xs_unwatch(struct xs_handle *h, const char *path, const char *token)
+{
+ printk("xs_unwatch(%s, %s)\n", path, token);
+ return xs_bool(xenbus_unwatch_path_token(XBT_NULL, path, token));
+}
+#endif
diff --git a/extras/mini-os/main-caml.c b/extras/mini-os/main-caml.c
new file mode 100644
index 0000000000..dd55aca38f
--- /dev/null
+++ b/extras/mini-os/main-caml.c
@@ -0,0 +1,42 @@
+/*
+ * Caml bootstrap
+ *
+ * Samuel Thibault <Samuel.Thibault@eu.citrix.net>, January 2008
+ */
+
+#include <stdio.h>
+#include <errno.h>
+
+#include <caml/mlvalues.h>
+#include <caml/callback.h>
+#include <unistd.h>
+
+/* Ugly binary compatibility with Linux */
+FILE *_stderr asm("stderr");
+int *__errno_location;
+/* Will probably break everything, probably need to fetch from glibc */
+void *__ctype_b_loc;
+
+int main(int argc, char *argv[], char *envp[])
+{
+ value *val;
+
+ /* Get current thread's value */
+ _stderr = stderr;
+ __errno_location = &errno;
+
+ printf("starting caml\n");
+
+ /* Wait before things might hang up */
+ sleep(1);
+
+ caml_startup(argv);
+ val = caml_named_value("main");
+ if (!val) {
+ printf("Couldn't find Caml main");
+ return 1;
+ }
+ caml_callback(*val, Val_int(0));
+ printf("callback returned\n");
+ return 0;
+}
diff --git a/extras/mini-os/main.c b/extras/mini-os/main.c
new file mode 100644
index 0000000000..345f7e9487
--- /dev/null
+++ b/extras/mini-os/main.c
@@ -0,0 +1,167 @@
+/*
+ * POSIX-compatible main layer
+ *
+ * Samuel Thibault <Samuel.Thibault@eu.citrix.net>, October 2007
+ */
+
+#ifdef HAVE_LIBC
+#include <os.h>
+#include <sched.h>
+#include <console.h>
+#include <netfront.h>
+#include <time.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fs.h>
+#include <xenbus.h>
+#include <events.h>
+
+extern int main(int argc, char *argv[], char *envp[]);
+extern void __libc_init_array(void);
+extern void __libc_fini_array(void);
+
+struct thread *main_thread;
+
+#if 0
+#include <stdio.h>
+int main(int argc, char *argv[], char *envp[])
+{
+ printf("Hello, World!\n");
+ return 1;
+}
+#endif
+
+void _init(void)
+{
+}
+
+void _fini(void)
+{
+}
+
+static void call_main(void *p)
+{
+ char *args, /**path,*/ *msg, *c;
+ int argc;
+ char **argv;
+ char *envp[] = { NULL };
+ char *vm;
+ int i;
+ char path[128];
+
+ /* Let other parts initialize (including console output) before maybe
+ * crashing. */
+ //sleep(1);
+
+ start_networking();
+ init_fs_frontend();
+
+#ifdef CONFIG_QEMU
+ if (!fs_import) {
+ printk("No FS backend found, is it running?\n");
+ do_exit();
+ }
+
+ /* Fetch argc, argv from XenStore */
+ char domid_s[10];
+ int domid;
+ domid = xenbus_read_integer("target");
+ if (domid == -1) {
+ printk("Couldn't read target\n");
+ do_exit();
+ }
+ snprintf(domid_s, sizeof(domid_s), "%d", domid);
+
+ snprintf(path, sizeof(path), "/local/domain/%d/vm", domid);
+ msg = xenbus_read(XBT_NIL, path, &vm);
+ if (msg) {
+ printk("Couldn't read vm path\n");
+ do_exit();
+ }
+ printk("vm is at %s\n", vm);
+#else
+ msg = xenbus_read(XBT_NIL, "vm", &vm);
+ if (msg) {
+ printk("Couldn't read vm path\n");
+ do_exit();
+ }
+#endif
+
+ snprintf(path, sizeof(path), "%s/image/dmargs", vm);
+ free(vm);
+ msg = xenbus_read(XBT_NIL, path, &args);
+
+ if (msg) {
+ printk("Couldn't get stubdom args: %s\n", msg);
+ args = strdup("");
+ }
+
+ argc = 1;
+#ifdef CONFIG_QEMU
+ argc += 2;
+#endif
+ c = args;
+ while (*c) {
+ if (*c != ' ') {
+ argc++;
+ while (*c && *c != ' ')
+ c++;
+ } else {
+ while (*c == ' ')
+ c++;
+ }
+ }
+ argv = alloca((argc + 1) * sizeof(char *));
+ argv[0] = "main";
+ argc = 1;
+#ifdef CONFIG_QEMU
+ argv[1] = "-d";
+ argv[2] = domid_s;
+ argc += 2;
+#endif
+ c = args;
+ while (*c) {
+ if (*c != ' ') {
+ argv[argc++] = c;
+ while (*c && *c != ' ')
+ c++;
+ } else {
+ *c++ = 0;
+ while (*c == ' ')
+ c++;
+ }
+ }
+ argv[argc] = NULL;
+
+ for (i = 0; i < argc; i++)
+ printf("\"%s\" ", argv[i]);
+ printf("\n");
+
+ __libc_init_array();
+ environ = envp;
+ tzset();
+
+ exit(main(argc, argv, envp));
+}
+
+void _exit(int ret)
+{
+ close_all_files();
+ __libc_fini_array();
+ printk("main returned %d\n", ret);
+ unbind_all_ports();
+ if (!ret) {
+ /* No problem, just shutdown. */
+ struct sched_shutdown sched_shutdown = { .reason = SHUTDOWN_poweroff };
+ HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
+ }
+ do_exit();
+}
+
+int app_main(start_info_t *si)
+{
+ printk("Dummy main: start_info=%p\n", si);
+ main_thread = create_thread("main", call_main, si);
+ return 0;
+}
+#endif
diff --git a/extras/mini-os/minios.mk b/extras/mini-os/minios.mk
index fa6f6bd0c9..078c396fc2 100644
--- a/extras/mini-os/minios.mk
+++ b/extras/mini-os/minios.mk
@@ -9,7 +9,7 @@ debug = y
DEF_CFLAGS += -fno-builtin -Wall -Werror -Wredundant-decls -Wno-format
DEF_CFLAGS += $(call cc-option,$(CC),-fno-stack-protector,)
DEF_CFLAGS += -Wstrict-prototypes -Wnested-externs -Wpointer-arith -Winline
-DEF_CFLAGS += -D__XEN_INTERFACE_VERSION__=$(XEN_INTERFACE_VERSION)
+DEF_CPPFLAGS += -D__XEN_INTERFACE_VERSION__=$(XEN_INTERFACE_VERSION)
DEF_ASFLAGS = -D__ASSEMBLY__
DEF_LDFLAGS =
@@ -24,12 +24,10 @@ endif
# DEF_... flags are the common mini-os flags,
# ARCH_... flags may be defined in arch/$(TARGET_ARCH_FAM/rules.mk
CFLAGS := $(DEF_CFLAGS) $(ARCH_CFLAGS)
+CPPFLAGS := $(DEF_CPPFLAGS) $(ARCH_CPPFLAGS)
ASFLAGS := $(DEF_ASFLAGS) $(ARCH_ASFLAGS)
LDFLAGS := $(DEF_LDFLAGS) $(ARCH_LDFLAGS)
-# The path pointing to the architecture specific header files.
-ARCH_INC := $(MINI-OS_ROOT)/include/$(TARGET_ARCH_FAM)
-
# Special build dependencies.
# Rebuild all after touching this/these file(s)
EXTRA_DEPS = $(MINI-OS_ROOT)/minios.mk \
@@ -44,18 +42,17 @@ extra_heads := $(foreach dir,$(EXTRA_INC),$(wildcard $(dir)/*.h))
HDRS += $(extra_heads)
# Add the special header directories to the include paths.
-extra_incl := $(foreach dir,$(EXTRA_INC),-I$(MINI-OS_ROOT)/include/$(dir))
-override CPPFLAGS := -I$(MINI-OS_ROOT)/include $(CPPFLAGS) -I$(ARCH_INC) $(extra_incl)
+override CPPFLAGS := $(CPPFLAGS) $(extra_incl)
# The name of the architecture specific library.
# This is on x86_32: libx86_32.a
# $(ARCH_LIB) has to built in the architecture specific directory.
-ARCH_LIB_NAME = $(TARGET_ARCH)
+ARCH_LIB_NAME = $(XEN_TARGET_ARCH)
ARCH_LIB := lib$(ARCH_LIB_NAME).a
# This object contains the entrypoint for startup from Xen.
# $(HEAD_ARCH_OBJ) has to be built in the architecture specific directory.
-HEAD_ARCH_OBJ := $(TARGET_ARCH).o
+HEAD_ARCH_OBJ := $(XEN_TARGET_ARCH).o
HEAD_OBJ := $(TARGET_ARCH_DIR)/$(HEAD_ARCH_OBJ)
diff --git a/extras/mini-os/mm.c b/extras/mini-os/mm.c
index 11e249d421..f204fa66ec 100644
--- a/extras/mini-os/mm.c
+++ b/extras/mini-os/mm.c
@@ -360,6 +360,29 @@ void free_pages(void *pointer, int order)
}
+#ifdef HAVE_LIBC
+void *sbrk(ptrdiff_t increment)
+{
+ unsigned long old_brk = brk;
+ unsigned long new_brk = old_brk + increment;
+
+ if (new_brk > heap_end) {
+ printk("Heap exhausted: %p + %lx = %p > %p\n", old_brk, increment, new_brk, heap_end);
+ return NULL;
+ }
+
+ if (new_brk > heap_mapped) {
+ unsigned long n = (new_brk - heap_mapped + PAGE_SIZE - 1) / PAGE_SIZE;
+ do_map_zero(heap_mapped, n);
+ heap_mapped += n * PAGE_SIZE;
+ }
+
+ brk = new_brk;
+
+ return (void *) old_brk;
+}
+#endif
+
void init_mm(void)
diff --git a/extras/mini-os/netfront.c b/extras/mini-os/netfront.c
index e3c56c10c4..095f55ca15 100644
--- a/extras/mini-os/netfront.c
+++ b/extras/mini-os/netfront.c
@@ -19,7 +19,10 @@
DECLARE_WAIT_QUEUE_HEAD(netfront_queue);
+#ifdef HAVE_LIBC
#define NETIF_SELECT_RX ((void*)-1)
+#endif
+
#define NET_TX_RING_SIZE __RING_SIZE((struct netif_tx_sring *)0, PAGE_SIZE)
@@ -50,6 +53,13 @@ struct netfront_dev {
char *nodename;
char *backend;
+#ifdef HAVE_LIBC
+ int fd;
+ unsigned char *data;
+ size_t len;
+ size_t rlen;
+#endif
+
void (*netif_rx)(unsigned char* data, int len);
};
@@ -92,7 +102,8 @@ moretodo:
cons = dev->rx.rsp_cons;
int nr_consumed=0;
- while ((cons != rp))
+ int some = 0;
+ while ((cons != rp) && !some)
{
struct net_buffer* buf;
unsigned char* page;
@@ -116,7 +127,18 @@ moretodo:
if(rx->status>0)
{
- dev->netif_rx(page+rx->offset,rx->status);
+#ifdef HAVE_LIBC
+ if (dev->netif_rx == NETIF_SELECT_RX) {
+ int len = rx->status;
+ ASSERT(current == main_thread);
+ if (len > dev->len)
+ len = dev->len;
+ memcpy(dev->data, page+rx->offset, len);
+ dev->rlen = len;
+ some = 1;
+ } else
+#endif
+ dev->netif_rx(page+rx->offset,rx->status);
}
nr_consumed++;
@@ -127,7 +149,7 @@ moretodo:
int more;
RING_FINAL_CHECK_FOR_RESPONSES(&dev->rx,more);
- if(more) goto moretodo;
+ if(more && !some) goto moretodo;
RING_IDX req_prod = dev->rx.req_prod_pvt;
@@ -178,6 +200,9 @@ void network_tx_buf_gc(struct netfront_dev *dev)
if (txrsp->status == NETIF_RSP_NULL)
continue;
+ if (txrsp->status == NETIF_RSP_ERROR)
+ printk("packet error\n");
+
id = txrsp->id;
struct net_buffer* buf = &dev->tx_buffers[id];
gnttab_end_access(buf->gref);
@@ -218,6 +243,22 @@ void netfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
local_irq_restore(flags);
}
+#ifdef HAVE_LIBC
+void netfront_select_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
+{
+ int flags;
+ struct netfront_dev *dev = data;
+ int fd = dev->fd;
+
+ local_irq_save(flags);
+ network_tx_buf_gc(dev);
+ local_irq_restore(flags);
+
+ files[fd].read = 1;
+ wake_up(&netfront_queue);
+}
+#endif
+
struct netfront_dev *init_netfront(char *nodename, void (*thenetif_rx)(unsigned char* data, int len), unsigned char rawmac[6])
{
xenbus_transaction_t xbt;
@@ -266,7 +307,12 @@ struct netfront_dev *init_netfront(char *nodename, void (*thenetif_rx)(unsigned
dev->dom = op.remote_dom = xenbus_read_integer(path);
HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
clear_evtchn(op.port); /* Without, handler gets invoked now! */
- dev->local_port = bind_evtchn(op.port, netfront_handler, dev);
+#ifdef HAVE_LIBC
+ if (thenetif_rx == NETIF_SELECT_RX)
+ dev->local_port = bind_evtchn(op.port, netfront_select_handler, dev);
+ else
+#endif
+ dev->local_port = bind_evtchn(op.port, netfront_handler, dev);
dev->evtchn=op.port;
txs = (struct netif_tx_sring*) alloc_page();
@@ -381,6 +427,23 @@ done:
return dev;
}
+#ifdef HAVE_LIBC
+int netfront_tap_open(char *nodename) {
+ struct netfront_dev *dev;
+
+ dev = init_netfront(nodename, NETIF_SELECT_RX, NULL);
+ if (!dev) {
+ printk("TAP open failed\n");
+ errno = EIO;
+ return -1;
+ }
+ dev->fd = alloc_fd(FTYPE_TAP);
+ printk("tap_open(%s) -> %d\n", nodename, dev->fd);
+ files[dev->fd].tap.dev = dev;
+ return dev->fd;
+}
+#endif
+
void shutdown_netfront(struct netfront_dev *dev)
{
char* err;
@@ -481,3 +544,30 @@ void netfront_xmit(struct netfront_dev *dev, unsigned char* data,int len)
network_tx_buf_gc(dev);
local_irq_restore(flags);
}
+
+#ifdef HAVE_LIBC
+ssize_t netfront_receive(struct netfront_dev *dev, unsigned char *data, size_t len)
+{
+ unsigned long flags;
+ int fd = dev->fd;
+ ASSERT(current == main_thread);
+
+ dev->rlen = 0;
+ dev->data = data;
+ dev->len = len;
+
+ local_irq_save(flags);
+ network_rx(dev);
+ if (!dev->rlen)
+ /* No data for us, make select stop returning */
+ files[fd].read = 0;
+ /* Before re-enabling the interrupts, in case a packet just arrived in the
+ * meanwhile. */
+ local_irq_restore(flags);
+
+ dev->data = NULL;
+ dev->len = 0;
+
+ return dev->rlen;
+}
+#endif
diff --git a/extras/mini-os/sched.c b/extras/mini-os/sched.c
index 18b3f01538..19a102f056 100644
--- a/extras/mini-os/sched.c
+++ b/extras/mini-os/sched.c
@@ -56,6 +56,7 @@
struct thread *idle_thread = NULL;
LIST_HEAD(exited_threads);
+static int threads_started;
void inline print_runqueue(void)
{
@@ -172,6 +173,9 @@ struct thread* create_thread(char *name, void (*function)(void *), void *data)
/* Not runable, not exited, not sleeping */
thread->flags = 0;
thread->wakeup_time = 0LL;
+#ifdef HAVE_LIBC
+ _REENT_INIT_PTR((&thread->reent))
+#endif
set_runnable(thread);
local_irq_save(flags);
if(idle_thread != NULL) {
@@ -185,6 +189,42 @@ struct thread* create_thread(char *name, void (*function)(void *), void *data)
return thread;
}
+#ifdef HAVE_LIBC
+static struct _reent callback_reent;
+struct _reent *__getreent(void)
+{
+ struct _reent *_reent;
+
+ if (!threads_started)
+ _reent = _impure_ptr;
+ else if (in_callback)
+ _reent = &callback_reent;
+ else
+ _reent = &get_current()->reent;
+
+#ifndef NDEBUG
+#if defined(__x86_64__) || defined(__x86__)
+ {
+#ifdef __x86_64__
+ register unsigned long sp asm ("rsp");
+#else
+ register unsigned long sp asm ("esp");
+#endif
+ if ((sp & (STACK_SIZE-1)) < STACK_SIZE / 16) {
+ static int overflowing;
+ if (!overflowing) {
+ overflowing = 1;
+ printk("stack overflow\n");
+ BUG();
+ }
+ }
+ }
+#endif
+#endif
+ return _reent;
+}
+#endif
+
void exit_thread(void)
{
unsigned long flags;
@@ -228,6 +268,7 @@ void wake(struct thread *thread)
void idle_thread_fn(void *unused)
{
s_time_t until;
+ threads_started = 1;
unsigned long flags;
struct list_head *iterator;
struct thread *next, *thread;
@@ -297,6 +338,9 @@ void init_sched(void)
{
printk("Initialising scheduler\n");
+#ifdef HAVE_LIBC
+ _REENT_INIT_PTR((&callback_reent))
+#endif
idle_thread = create_thread("Idle", idle_thread_fn, NULL);
INIT_LIST_HEAD(&idle_thread->thread_list);
}
diff --git a/stubdom/Makefile b/stubdom/Makefile
new file mode 100644
index 0000000000..7fdcdb22c0
--- /dev/null
+++ b/stubdom/Makefile
@@ -0,0 +1,259 @@
+XEN_ROOT = ..
+
+export XEN_OS=MiniOS
+
+include $(XEN_ROOT)/Config.mk
+export stubdom=y
+export debug=y
+
+IOEMU_OPTIONS=--disable-vnc-tls
+BINUTILS_VERSION=2.18
+GCC_VERSION=4.2.2
+ZLIB_VERSION=1.2.3
+LIBPCI_VERSION=2.2.9
+NEWLIB_DATE=2008-01-01
+LWIP_DATE=2008-02-08
+
+WGET=wget -c
+
+GNU_TARGET_ARCH:=$(XEN_TARGET_ARCH)
+ifeq ($(XEN_TARGET_ARCH),x86_32)
+GNU_TARGET_ARCH:=i686
+endif
+
+ifeq ($(GNU_TARGET_ARCH), i686)
+TARGET_CFLAGS=
+endif
+ifeq ($(GNU_TARGET_ARCH), x86_64)
+TARGET_CFLAGS=-mno-red-zone
+endif
+ifeq ($(GNU_TARGET_ARCH), ia64)
+TARGET_CFLAGS=-mconstant-gp
+endif
+
+CROSS_ROOT=cross-root-$(GNU_TARGET_ARCH)
+CROSS_PREFIX=$(CURDIR)/$(CROSS_ROOT)
+export CROSS_COMPILE=$(GNU_TARGET_ARCH)-xen-elf-
+export PATH:=$(CROSS_PREFIX)/bin:$(PATH)
+
+.PHONY: all
+all: qemu-stubdom
+
+################
+# Cross-binutils
+################
+
+binutils-$(BINUTILS_VERSION).tar.bz2:
+ $(WGET) http://ftp.gnu.org/gnu/binutils/$@
+binutils-$(BINUTILS_VERSION): binutils-$(BINUTILS_VERSION).tar.bz2
+ tar xjf $@.tar.bz2
+ ( cd binutils-$(BINUTILS_VERSION) && patch -p1 < ../binutils.patch )
+ touch $@
+
+BINUTILS_STAMPFILE=$(CROSS_ROOT)/bin/$(GNU_TARGET_ARCH)-xen-elf-ar
+.PHONY: cross-binutils
+cross-binutils: $(BINUTILS_STAMPFILE)
+$(BINUTILS_STAMPFILE): binutils-$(BINUTILS_VERSION)
+ mkdir -p binutils-build
+ ( cd binutils-build && \
+ ../binutils-$(BINUTILS_VERSION)/configure --prefix=$(CROSS_PREFIX) --verbose --target=$(GNU_TARGET_ARCH)-xen-elf && \
+ $(MAKE) && \
+ $(MAKE) check && \
+ $(MAKE) install )
+
+###########
+# Cross-gcc
+###########
+
+gcc-$(GCC_VERSION).tar.bz2:
+ $(WGET) http://ftp.gnu.org/gnu/gcc/gcc-$(GCC_VERSION)/gcc-$(GCC_VERSION).tar.bz2
+gcc-$(GCC_VERSION): gcc-$(GCC_VERSION).tar.bz2
+ tar xjf gcc-$(GCC_VERSION).tar.bz2
+ ( cd gcc-$(GCC_VERSION) && patch -p1 < ../gcc.patch )
+ touch $@
+
+GCC_STAMPFILE=$(CROSS_ROOT)/bin/$(GNU_TARGET_ARCH)-xen-elf-gcc-$(GCC_VERSION)
+.PHONY: cross-gcc
+cross-gcc: $(GCC_STAMPFILE)
+$(GCC_STAMPFILE): gcc-$(GCC_VERSION) $(BINUTILS_STAMPFILE)
+ mkdir -p gcc-build
+ ( cd gcc-build && \
+ ../gcc-$(GCC_VERSION)/configure --prefix=$(CROSS_PREFIX) --verbose --target=$(GNU_TARGET_ARCH)-xen-elf --enable-languages=c --disable-libssp --with-gnu-as --with-gnu-ld && \
+ $(MAKE) GCC_FOR_TARGET='$$$$r/gcc/xgcc -B$$$$r/gcc/ '"$(TARGET_CFLAGS)"' $$(FLAGS_FOR_TARGET)' && \
+ $(MAKE) install )
+
+##############
+# Cross-newlib
+##############
+
+newlib-cvs:
+ cvs -z 9 -d :pserver:anoncvs@sources.redhat.com:/cvs/src co -D $(NEWLIB_DATE) newlib
+ mv src newlib-cvs
+ ( cd newlib-cvs && patch -p0 < ../newlib.patch)
+
+NEWLIB_STAMPFILE=$(CROSS_ROOT)/$(GNU_TARGET_ARCH)-xen-elf/lib/libc.a
+.PHONY: cross-newlib
+cross-newlib: $(NEWLIB_STAMPFILE)
+$(NEWLIB_STAMPFILE): newlib-cvs $(GCC_STAMPFILE)
+ mkdir -p newlib-build
+ ( cd newlib-build && \
+ CC_FOR_TARGET="$(GNU_TARGET_ARCH)-xen-elf-gcc $(TARGET_CFLAGS)" ../newlib-cvs/configure --prefix=$(CROSS_PREFIX) --verbose --target=$(GNU_TARGET_ARCH)-xen-elf --enable-newlib-io-long-long && \
+ $(MAKE) && \
+ $(MAKE) install )
+
+############
+# Cross-zlib
+############
+
+zlib-$(ZLIB_VERSION).tar.gz:
+ $(WGET) http://www.zlib.net/zlib-$(ZLIB_VERSION).tar.gz
+
+ZLIB_STAMPFILE=$(CROSS_ROOT)/$(GNU_TARGET_ARCH)-xen-elf/lib/libz.a
+.PHONY: cross-zlib
+cross-zlib: $(ZLIB_STAMPFILE)
+$(ZLIB_STAMPFILE): zlib-$(ZLIB_VERSION).tar.gz $(NEWLIB_STAMPFILE)
+ tar xzf $<
+ ( cd zlib-$(ZLIB_VERSION) && \
+ CFLAGS="$(TARGET_CFLAGS)" CC=$(GNU_TARGET_ARCH)-xen-elf-gcc ./configure --prefix=$(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf && \
+ $(MAKE) libz.a && \
+ $(MAKE) install )
+
+##############
+# Cross-libpci
+##############
+
+pciutils-$(LIBPCI_VERSION).tar.bz2:
+ $(WGET) http://www.kernel.org/pub/software/utils/pciutils/pciutils-$(LIBPCI_VERSION).tar.bz2
+
+LIBPCI_STAMPFILE=$(CROSS_ROOT)/$(GNU_TARGET_ARCH)-xen-elf/lib/libpci.a
+.PHONY: cross-libpci
+cross-libpci: $(LIBPCI_STAMPFILE)
+$(LIBPCI_STAMPFILE): pciutils-$(LIBPCI_VERSION).tar.bz2 $(NEWLIB_STAMPFILE) $(ZLIB_STAMPFILE)
+ tar xjf $<
+ ( cd pciutils-$(LIBPCI_VERSION) && \
+ cp ../libpci.config.h lib/config.h && \
+ echo '#define PCILIB_VERSION "$(LIBPCI_VERSION)"' >> lib/config.h && \
+ cp ../libpci.config.mak lib/config.mk && \
+ $(MAKE) CC="$(GNU_TARGET_ARCH)-xen-elf-gcc $(TARGET_CFLAGS)" lib/libpci.a && \
+ $(INSTALL_DATA) lib/libpci.a $(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/lib/ && \
+ $(INSTALL_DIR) $(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/include/pci && \
+ $(INSTALL_DATA) lib/{config,header,pci,types}.h $(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/include/pci/ \
+ )
+
+######
+# lwIP
+######
+
+lwip-cvs:
+ cvs -z 9 -d :pserver:anonymous@cvs.savannah.nongnu.org:/sources/lwip co -D $(LWIP_DATE) lwip
+ mv lwip lwip-cvs
+
+#######
+# Links
+#######
+
+.PHONY: $(CROSS_ROOT)
+$(CROSS_ROOT): cross-newlib cross-zlib cross-libpci
+
+.PHONY: mk-symlinks
+mk-symlinks:
+ [ -h include ] || ln -sf ../tools/include .
+ mkdir -p libxc
+ [ -h libxc/Makefile ] || ( cd libxc && \
+ ln -sf ../../tools/libxc/*.h . && \
+ ln -sf ../../tools/libxc/*.c . && \
+ ln -sf ../../tools/libxc/Makefile . )
+ mkdir -p libxc/$(XEN_TARGET_ARCH)
+ [ -h libxc/$(XEN_TARGET_ARCH) ] || ( cd libxc/$(XEN_TARGET_ARCH) && \
+ ln -sf ../../tools/libxc/$(XEN_TARGET_ARCH)/*.c . && \
+ ln -sf ../../tools/libxc/$(XEN_TARGET_ARCH)/*.h . && \
+ ln -sf ../../tools/libxc/$(XEN_TARGET_ARCH)/Makefile . )
+ mkdir -p ioemu
+ [ -h ioemu/Makefile ] || ( cd ioemu && \
+ ln -sf ../../tools/ioemu/* . && \
+ ([ ! -h config-host.h ] || rm -f config-host.h) && \
+ ([ ! -h config-host.mak ] || rm -f config-host.mak) )
+ [ -h mini-os ] || ln -sf ../extras/mini-os .
+
+#######
+# libxc
+#######
+
+.PHONY: libxc
+libxc: cross-zlib mk-symlinks
+ $(MAKE) -C $@
+
+#######
+# ioemu
+#######
+
+.PHONY: ioemu
+ioemu: cross-zlib cross-libpci mk-symlinks libxc
+ [ -f ioemu/config-host.mak ] || \
+ ( cd ioemu ; XEN_TARGET_ARCH=$(XEN_TARGET_ARCH) sh configure --prefix=/usr --enable-stubdom $(IOEMU_OPTIONS))
+ $(MAKE) -C ioemu LWIPDIR=$(CURDIR)/lwip-cvs
+
+######
+# caml
+######
+
+.PHONY: caml
+caml:
+ $(MAKE) -C $@
+
+########
+# minios
+########
+
+.PHONY: qemu-stubdom
+qemu-stubdom: mk-symlinks lwip-cvs libxc ioemu
+ $(MAKE) -C mini-os LWIPDIR=$(CURDIR)/lwip-cvs QEMUDIR=$(CURDIR)/ioemu
+
+.PHONY: caml-stubdom
+caml-stubdom: mk-symlinks lwip-cvs libxc cross-libpci caml
+ $(MAKE) -C mini-os LWIPDIR=$(CURDIR)/lwia-cvs CAMLDIR=$(CURDIR)/caml
+
+#########
+# install
+#########
+
+install: mini-os/mini-os.gz
+ $(INSTALL_PROG) stubdom-dm "$(DESTDIR)/usr/lib/xen/bin"
+ $(INSTALL_PROG) mini-os/mini-os.gz "$(DESTDIR)/usr/lib/xen/boot/stubdom.gz"
+
+#######
+# clean
+#######
+
+# Only clean the libxc/ioemu/mini-os part
+.PHONY: clean
+clean:
+ -$(MAKE) -C mini-os LWIPDIR=$(CURDIR)/lwip-cvs clean
+ $(MAKE) -C caml clean
+ rm -fr libxc ioemu mini-os include
+
+# clean the cross-compilation result
+.PHONY: crossclean
+crossclean: clean
+ rm -fr $(CROSS_ROOT)
+ rm -fr binutils-build gcc-build newlib-build
+ rm -fr zlib-$(ZLIB_VERSION) pciutils-$(LIBPCI_VERSION)
+
+# clean patched sources
+.PHONY: patchclean
+patchclean: crossclean
+ rm -fr binutils-$(BINUTILS_VERSION)
+ rm -fr gcc-$(GCC_VERSION)
+ rm -fr newlib-cvs
+ rm -fr lwip-cvs
+
+# clean downloads
+.PHONY: downloadclean
+downloadclean: patchclean
+ rm -f binutils-$(BINUTILS_VERSION).tar.bz2
+ rm -f gcc-$(GCC_VERSION).tar.bz2
+ rm -f zlib-$(ZLIB_VERSION).tar.gz
+ rm -f pciutils-$(LIBPCI_VERSION).tar.bz2
+
+.PHONY: distclean
+distclean: downloadclean
diff --git a/stubdom/README b/stubdom/README
new file mode 100644
index 0000000000..42c47601fa
--- /dev/null
+++ b/stubdom/README
@@ -0,0 +1,41 @@
+To compile
+==========
+
+Just run make -j 4, that will download / patch / compile
+Then make install to install the result.
+
+Also, run make and make install in $XEN_ROOT/tools/fs-back
+
+To run
+======
+
+mkdir -p /exports/usr/share/qemu
+ln -s /usr/share/qemu/keymaps /exports/usr/share/qemu
+/usr/sbin/fs-backend &
+
+
+In your HVM config "hvmconfig",
+
+- use VNC, set vnclisten to "172.30.206.1" for instance:
+
+vnc=1
+vnclisten="172.30.206.1"
+
+- use /usr/lib/xen/bin/stubdom-dm as dm script
+
+device_model = '/usr/lib/xen/bin/stubdom-dm'
+
+- comment the disk statement:
+#disk = [ 'file:/tmp/install.iso,hdc:cdrom,r', 'phy:/dev/sda6,hda,w', 'file:/tmp/test,hdb,r' ]
+
+Create /etc/xen/stubdom-hvmconfig ("hvmconfig" must match your main config file)
+with
+
+kernel="/usr/lib/xen/boot/stubdom.gz"
+vif=[ 'ip=172.30.206.1', 'ip=10.0.1.1,mac=aa:00:00:12:23:34']
+disk = [ 'file:/tmp/install.iso,hdc:cdrom,r', 'phy:/dev/sda6,hda,w', 'file:/tmp/test,hdb,r' ]
+
+where
+- 172.30.206.1 is the IP for vnc,
+- 'ip=10.0.1.1,mac=' is the same net configuration as in the hvmconfig script,
+- and disk = is the same block configuration as in the hvmconfig script.
diff --git a/stubdom/binutils.patch b/stubdom/binutils.patch
new file mode 100644
index 0000000000..65f120a377
--- /dev/null
+++ b/stubdom/binutils.patch
@@ -0,0 +1,14 @@
+It looks like binutils has troubles with makeinfo and the doc generation.
+We don't need it anyway
+
+--- binutils-2.18/bfd/Makefile.inorig 2008-01-16 16:17:43.004484000 +0000
++++ binutils-2.18/bfd/Makefile.in 2008-01-16 16:17:50.505526000 +0000
+@@ -271,7 +271,7 @@
+ INCDIR = $(srcdir)/../include
+ CSEARCH = -I. -I$(srcdir) -I$(INCDIR)
+ MKDEP = gcc -MM
+-SUBDIRS = doc po
++SUBDIRS = po
+ bfddocdir = doc
+ bfdlib_LTLIBRARIES = libbfd.la
+ AM_CFLAGS = $(WARN_CFLAGS)
diff --git a/stubdom/caml/Makefile b/stubdom/caml/Makefile
new file mode 100644
index 0000000000..69595a8f99
--- /dev/null
+++ b/stubdom/caml/Makefile
@@ -0,0 +1,18 @@
+XEN_ROOT = ../..
+
+include $(XEN_ROOT)/Config.mk
+
+OCAMLFIND=ocamlfind
+OCAMLOPT=ocamlopt
+
+OBJS := hello.cmx
+LIBS :=
+
+%.cmx: %.ml
+ $(OCAMLFIND) $(OCAMLOPT) -c $< -o $@
+
+caml.o: $(OBJS)
+ $(OCAMLFIND) $(OCAMLOPT) $(LIBS) $^ -output-obj -o $@
+
+clean:
+ rm -f *.o *.cmx *.cmi
diff --git a/stubdom/caml/hello.ml b/stubdom/caml/hello.ml
new file mode 100644
index 0000000000..3a7181134a
--- /dev/null
+++ b/stubdom/caml/hello.ml
@@ -0,0 +1,4 @@
+let main arg =
+ Printf.printf "Hello, world!\n%!."
+
+let _ = Callback.register "main" main
diff --git a/stubdom/gcc.patch b/stubdom/gcc.patch
new file mode 100644
index 0000000000..d593986ab7
--- /dev/null
+++ b/stubdom/gcc.patch
@@ -0,0 +1,31 @@
+Backported from later versions
+
+--- gcc-4.2.2/gcc/config.gcc 2007-11-22 16:27:45.000000000 +0000
++++ gcc-4.2.2/gcc/config.gcc 2007-11-22 16:23:00.000000000 +0000
+@@ -1033,6 +1033,11 @@
+ tmake_file="i386/t-i386elf t-svr4"
+ use_fixproto=yes
+ ;;
++x86_64-*-elf*)
++ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h i386/i386elf.h i386/x86-64.h"
++ tmake_file="i386/t-i386elf t-svr4"
++ use_fixproto=yes
++ ;;
+ i[34567]86-sequent-ptx4* | i[34567]86-sequent-sysv4*)
+ if test x$gas = xyes
+ then
+
+We don't have a libc yet at this stage. Unused anyway
+
+--- gcc-4.2.2/gcc/unwind-generic.h.orig 2008-01-11 18:54:40.000000000 +0100
++++ gcc-4.2.2/gcc/unwind-generic.h 2008-01-11 18:54:31.000000000 +0100
+@@ -203,7 +203,6 @@
+ compatible with the standard ABI for IA-64, we inline these. */
+
+ #ifdef __ia64__
+-#include <stdlib.h>
+
+ static inline _Unwind_Ptr
+ _Unwind_GetDataRelBase (struct _Unwind_Context *_C)
+Backported from later versions
+
diff --git a/stubdom/libpci.config.h b/stubdom/libpci.config.h
new file mode 100644
index 0000000000..a84ead5708
--- /dev/null
+++ b/stubdom/libpci.config.h
@@ -0,0 +1,5 @@
+#define PCI_OS_STUBDOM
+#define PCI_HAVE_STDINT_H
+#define PCI_PATH_IDS_DIR "."
+#define PCI_COMPRESSED_IDS
+#define PCI_IDS "pci.ids.gz"
diff --git a/stubdom/libpci.config.mak b/stubdom/libpci.config.mak
new file mode 100644
index 0000000000..5bc5b261d0
--- /dev/null
+++ b/stubdom/libpci.config.mak
@@ -0,0 +1,2 @@
+LIBZ=-lz
+LDLIBS+=$(LIBZ)
diff --git a/stubdom/newlib.patch b/stubdom/newlib.patch
new file mode 100644
index 0000000000..217205cccf
--- /dev/null
+++ b/stubdom/newlib.patch
@@ -0,0 +1,203 @@
+There is a mix between longs and long longs.
+
+Index: newlib/libc/include/inttypes.h
+===================================================================
+RCS file: /cvs/src/src/newlib/libc/include/inttypes.h,v
+retrieving revision 1.3
+diff -u -p -r1.3 inttypes.h
+--- newlib/libc/include/inttypes.h 16 Dec 2005 19:03:12 -0000 1.3
++++ newlib/libc/include/inttypes.h 8 Nov 2007 16:32:44 -0000
+@@ -163,12 +163,12 @@
+
+
+ /* 64-bit types */
+-#if __have_longlong64
+-#define __PRI64(x) __STRINGIFY(ll##x)
+-#define __SCN64(x) __STRINGIFY(ll##x)
+-#elif __have_long64
++#if __have_long64
+ #define __PRI64(x) __STRINGIFY(l##x)
+ #define __SCN64(x) __STRINGIFY(l##x)
++#elif __have_longlong64
++#define __PRI64(x) __STRINGIFY(ll##x)
++#define __SCN64(x) __STRINGIFY(ll##x)
+ #else
+ #define __PRI64(x) __STRINGIFY(x)
+ #define __SCN64(x) __STRINGIFY(x)
+@@ -217,12 +217,12 @@
+ #endif
+
+ /* max-bit types */
+-#if __have_longlong64
+-#define __PRIMAX(x) __STRINGIFY(ll##x)
+-#define __SCNMAX(x) __STRINGIFY(ll##x)
+-#elif __have_long64
++#if __have_long64
+ #define __PRIMAX(x) __STRINGIFY(l##x)
+ #define __SCNMAX(x) __STRINGIFY(l##x)
++#elif __have_longlong64
++#define __PRIMAX(x) __STRINGIFY(ll##x)
++#define __SCNMAX(x) __STRINGIFY(ll##x)
+ #else
+ #define __PRIMAX(x) __STRINGIFY(x)
+ #define __SCNMAX(x) __STRINGIFY(x)
+@@ -242,12 +242,12 @@
+ #define SCNxMAX __SCNMAX(x)
+
+ /* ptr types */
+-#if __have_longlong64
+-#define __PRIPTR(x) __STRINGIFY(ll##x)
+-#define __SCNPTR(x) __STRINGIFY(ll##x)
+-#elif __have_long64
++#if __have_long64
+ #define __PRIPTR(x) __STRINGIFY(l##x)
+ #define __SCNPTR(x) __STRINGIFY(l##x)
++#elif __have_longlong64
++#define __PRIPTR(x) __STRINGIFY(ll##x)
++#define __SCNPTR(x) __STRINGIFY(ll##x)
+ #else
+ #define __PRIPTR(x) __STRINGIFY(x)
+ #define __SCNPTR(x) __STRINGIFY(x)
+
+We don't want u?int32_t to be long as our code assume in a lot of places to be
+int.
+
+Index: newlib/libc/include/stdint.h
+===================================================================
+RCS file: /cvs/src/src/newlib/libc/include/stdint.h,v
+retrieving revision 1.10
+diff -u -p -r1.10 stdint.h
+--- newlib/libc/include/stdint.h 16 Aug 2006 21:39:43 -0000 1.10
++++ newlib/libc/include/stdint.h 12 Feb 2008 13:07:52 -0000
+@@ -38,7 +38,7 @@ extern "C" {
+ #if __STDINT_EXP(LONG_MAX) > 0x7fffffff
+ #define __have_long64 1
+ #elif __STDINT_EXP(LONG_MAX) == 0x7fffffff && !defined(__SPU__)
+-#define __have_long32 1
++/* #define __have_long32 1 */
+ #endif
+
+ #if __STDINT_EXP(SCHAR_MAX) == 0x7f
+
+Define the basic ia64 jump buffer
+
+Index: newlib/libc/include/machine/setjmp.h
+===================================================================
+RCS file: /cvs/src/src/newlib/libc/include/machine/setjmp.h,v
+retrieving revision 1.34
+diff -u -p -r1.34 setjmp.h
+--- newlib/libc/include/machine/setjmp.h 7 Nov 2007 21:42:24 -0000 1.34
++++ newlib/libc/include/machine/setjmp.h 11 Jan 2008 18:10:43 -0000
+@@ -72,6 +72,11 @@ _BEGIN_STD_C
+ #define _JBLEN 8
+ #endif
+
++#ifdef __ia64__
++#define _JBTYPE long
++#define _JBLEN 70
++#endif
++
+ #ifdef __i960__
+ #define _JBLEN 35
+ #endif
+
+In mini-os we use a dynamic reentrency buffer.
+
+Index: newlib/libc/include/sys/config.h
+===================================================================
+RCS file: /cvs/src/src/newlib/libc/include/sys/config.h,v
+retrieving revision 1.47
+diff -u -p -r1.47 config.h
+--- newlib/libc/include/sys/config.h 15 Mar 2007 21:32:12 -0000 1.47
++++ newlib/libc/include/sys/config.h 8 Nov 2007 16:32:44 -0000
+@@ -71,6 +71,10 @@
+ #endif
+ #endif
+
++#ifndef __DYNAMIC_REENT__
++#define __DYNAMIC_REENT__
++#endif
++
+ #ifdef __mn10200__
+ #define __SMALL_BITFIELDS
+ #endif
+
+Dynamic pointer to our reentrancy zone
+
+Index: newlib/libc/reent/getreent.c
+===================================================================
+RCS file: /cvs/src/src/newlib/libc/reent/getreent.c,v
+retrieving revision 1.2
+diff -u -p -r1.2 getreent.c
+--- newlib/libc/reent/getreent.c 7 Sep 2007 00:45:55 -0000 1.2
++++ newlib/libc/reent/getreent.c 8 Nov 2007 16:32:44 -0000
+@@ -3,12 +3,20 @@
+ #include <_ansi.h>
+ #include <reent.h>
+
++#define weak_alias(name, aliasname) \
++ extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));
++
+ #ifdef __getreent
+ #undef __getreent
+ #endif
++#ifdef __libc_getreent
++#undef __libc_getreent
++#endif
+
+ struct _reent *
+-_DEFUN_VOID(__getreent)
++__libc_getreent (void)
+ {
+ return _impure_ptr;
+ }
++weak_alias(__libc_getreent,__getreent)
++
+
+We can't provide a red zone in mini-os.
+
+Index: newlib/libc/machine/x86_64/memcpy.S
+===================================================================
+RCS file: /cvs/src/src/newlib/libc/machine/x86_64/memcpy.S,v
+retrieving revision 1.1
+diff -u -p -r1.1 memcpy.S
+--- newlib/libc/machine/x86_64/memcpy.S 28 Aug 2007 21:56:49 -0000 1.1
++++ newlib/libc/machine/x86_64/memcpy.S 8 Nov 2007 16:32:44 -0000
+@@ -30,10 +30,18 @@ quadword_aligned:
+ cmpq $256, rdx
+ jb quadword_copy
+
++#if 1
++ subq $32, rsp
++ movq rax, 24 (rsp)
++ movq r12, 16 (rsp)
++ movq r13, 8 (rsp)
++ movq r14, 0 (rsp)
++#else
+ movq rax, -8 (rsp)
+ movq r12, -16 (rsp)
+ movq r13, -24 (rsp)
+ movq r14, -32 (rsp)
++#endif
+
+ movq rdx, rcx /* Copy 128 bytes at a time with minimum cache polution */
+ shrq $7, rcx
+@@ -89,10 +97,18 @@ loop:
+ movq rdx, rcx
+ andq $127, rcx
+ rep movsb
++#if 1
++ movq 24 (rsp), rax
++ movq 16 (rsp), r12
++ movq 8 (rsp), r13
++ movq 0 (rsp), r14
++ addq $32, rsp
++#else
+ movq -8 (rsp), rax
+ movq -16 (rsp), r12
+ movq -24 (rsp), r13
+ movq -32 (rsp), r14
++#endif
+ ret
+
+
diff --git a/stubdom/stubdom-dm b/stubdom/stubdom-dm
new file mode 100644
index 0000000000..3edeb9d2dc
--- /dev/null
+++ b/stubdom/stubdom-dm
@@ -0,0 +1,97 @@
+#!/bin/bash
+#
+# Copyright 2007-2008 Samuel Thibault <samuel.thibault@eu.citrix.net>
+#
+# dm script around stubdomains.
+#
+
+# To fit xterms nicely
+height=339
+
+# Parse arguments
+
+domid=
+domname=
+vncviewer=0
+vncpid=
+while [ "$#" -gt 0 ];
+do
+ if [ "$#" -ge 2 ];
+ then
+ case "$1" in
+ -d) domid=$2; shift ;;
+ -domain-name) domname=$2; shift ;;
+ -vnc)
+ ip=${2%:*};
+ vnc_port=${2#*:};
+ shift
+ ;;
+ esac
+ fi
+ case "$1" in
+ -vncviewer) vncviewer=1 ;;
+ esac
+ shift
+done
+
+[ -z "$domid" ] && ( echo "couldn't find domain ID" ; exit 1 )
+[ -z "$domname" ] && ( echo "couldn't find domain name" ; exit 1 )
+
+# Termination handler
+
+term() {
+ kill %1
+ (
+ [ -n "$vncpid" ] && kill -9 $vncpid
+ xm destroy stubdom-$domname
+ #xm destroy $domname
+ ) &
+ # We need to exit immediately so as to let xend do the commands above
+ exit 0
+}
+
+trap term SIGHUP
+
+############
+# stubdomain
+# Wait for any previous stubdom to terminate
+while xm list | grep stubdom-$domname
+do
+ sleep 1
+done
+
+creation="xm create -c stubdom-$domname target=$domid memory=32"
+
+(while true ; do sleep 60 ; done) | $creation &
+#xterm -geometry +0+0 -e /bin/sh -c "$creation ; echo ; echo press ENTER to shut down ; read" &
+consolepid=$!
+
+
+while ! vnc_port=`xenstore-read /local/domain/$domid/console/vnc-port`
+do
+ # Check that the stubdom job is still alive
+ kill -0 $consolepid || term
+ sleep 1
+done
+
+################
+# DEBUG: tcpdump
+#while ! stubdomid=`xm domid stubdom-$domname`
+#do
+# sleep 1
+#done
+#xterm -geometry 160x25+0+$height -e /bin/sh -c "tcpdump -n -i vif$stubdomid.0" &
+#xterm -geometry 160x25+0+$((2 * $height)) -e /bin/sh -c "tcpdump -n -i vif$stubdomid.1" &
+
+###########
+# vncviewer
+if [ "$vncviewer" = 1 ]
+then
+ vncviewer $ip:$vnc_port &
+ vncpid=$!
+fi
+
+# wait for SIGHUP or stubdom termination
+wait $consolepid
+
+term
diff --git a/tools/blktap/drivers/tapdisk.c b/tools/blktap/drivers/tapdisk.c
index 993e09b155..75f06c701c 100644
--- a/tools/blktap/drivers/tapdisk.c
+++ b/tools/blktap/drivers/tapdisk.c
@@ -641,7 +641,7 @@ static void get_io_request(struct td_state *s)
if (!run) return; /*We have received signal to close*/
rp = info->fe_ring.sring->req_prod;
- rmb();
+ xen_rmb();
for (j = info->fe_ring.req_cons; j != rp; j++)
{
int done = 0, start_seg = 0;
diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c
index 735a77b0e6..9573333c08 100644
--- a/tools/console/daemon/io.c
+++ b/tools/console/daemon/io.c
@@ -60,6 +60,8 @@
extern int log_reload;
extern int log_guest;
extern int log_hv;
+extern int log_time_hv;
+extern int log_time_guest;
extern char *log_dir;
static int log_hv_fd = -1;
@@ -99,6 +101,50 @@ struct domain
static struct domain *dom_head;
+static int write_all(int fd, const char* buf, size_t len)
+{
+ while (len) {
+ ssize_t ret = write(fd, buf, len);
+ if (ret == -1 && errno == EINTR)
+ continue;
+ if (ret <= 0)
+ return -1;
+ len -= ret;
+ buf += ret;
+ }
+
+ return 0;
+}
+
+static int write_with_timestamp(int fd, const char *data, size_t sz)
+{
+ char buf[sz+1];
+ char ts[32];
+ time_t now = time(NULL);
+ const struct tm *tmnow = localtime(&now);
+ size_t tslen = strftime(ts, sizeof(ts), "[%d-%m-%Y %H:%M:%S] ", tmnow);
+
+ memcpy(buf, data, sz);
+ while (sz > 0 && buf[sz-1] == '\r')
+ sz--; // Don't print trailing \r's
+ if (sz > 0 && buf[sz-1] != '\n')
+ buf[sz++] = '\n'; // Force ending newline
+ data = buf;
+
+ while (sz > 0) {
+ const char *nl = strchr(data, '\n') + 1;
+ size_t towrite = nl - data;
+ if (write_all(fd, ts, tslen) < 0)
+ return -1;
+ if (write_all(fd, data, towrite))
+ return -1;
+ sz -= towrite;
+ data = nl;
+ }
+
+ return 0;
+}
+
static void buffer_append(struct domain *dom)
{
struct buffer *buffer = &dom->buffer;
@@ -107,7 +153,7 @@ static void buffer_append(struct domain *dom)
cons = intf->out_cons;
prod = intf->out_prod;
- mb();
+ xen_mb();
size = prod - cons;
if ((size == 0) || (size > sizeof(intf->out)))
@@ -126,7 +172,7 @@ static void buffer_append(struct domain *dom)
buffer->data[buffer->size++] = intf->out[
MASK_XENCONS_IDX(cons++, intf->out)];
- mb();
+ xen_mb();
intf->out_cons = cons;
xc_evtchn_notify(dom->xce_handle, dom->local_port);
@@ -135,10 +181,13 @@ static void buffer_append(struct domain *dom)
* and handle_tty_write will stop being called.
*/
if (dom->log_fd != -1) {
- int len = write(dom->log_fd,
- buffer->data + buffer->size - size,
- size);
- if (len < 0)
+ int logret;
+ if (log_time_guest) {
+ logret = write_with_timestamp(dom->log_fd, buffer->data + buffer->size - size, size);
+ } else {
+ logret = write_all(dom->log_fd, buffer->data + buffer->size - size, size);
+ }
+ if (logret < 0)
dolog(LOG_ERR, "Write to log failed on domain %d: %d (%s)\n",
dom->domid, errno, strerror(errno));
}
@@ -195,6 +244,15 @@ static int create_hv_log(void)
if (fd == -1)
dolog(LOG_ERR, "Failed to open log %s: %d (%s)",
logfile, errno, strerror(errno));
+ if (fd != -1 && log_time_hv) {
+ if (write_with_timestamp(fd, "Logfile Opened",
+ strlen("Logfile Opened")) < 0) {
+ dolog(LOG_ERR, "Failed to log opening timestamp "
+ "in %s: %d (%s)", logfile, errno,
+ strerror(errno));
+ return -1;
+ }
+ }
return fd;
}
@@ -229,6 +287,15 @@ static int create_domain_log(struct domain *dom)
if (fd == -1)
dolog(LOG_ERR, "Failed to open log %s: %d (%s)",
logfile, errno, strerror(errno));
+ if (fd != -1 && log_time_guest) {
+ if (write_with_timestamp(fd, "Logfile Opened",
+ strlen("Logfile Opened")) < 0) {
+ dolog(LOG_ERR, "Failed to log opening timestamp "
+ "in %s: %d (%s)", logfile, errno,
+ strerror(errno));
+ return -1;
+ }
+ }
return fd;
}
@@ -683,7 +750,7 @@ static int ring_free_bytes(struct domain *dom)
cons = intf->in_cons;
prod = intf->in_prod;
- mb();
+ xen_mb();
space = prod - cons;
if (space > sizeof(intf->in))
@@ -730,7 +797,7 @@ static void handle_tty_read(struct domain *dom)
intf->in[MASK_XENCONS_IDX(prod++, intf->in)] =
msg[i];
}
- wmb();
+ xen_wmb();
intf->in_prod = prod;
xc_evtchn_notify(dom->xce_handle, dom->local_port);
} else {
@@ -817,11 +884,16 @@ static void handle_hv_logs(void)
if ((port = xc_evtchn_pending(xce_handle)) == -1)
return;
- if (xc_readconsolering(xc_handle, &bufptr, &size, 0, 1, &index) == 0) {
- int len = write(log_hv_fd, buffer, size);
- if (len < 0)
- dolog(LOG_ERR, "Failed to write hypervisor log: %d (%s)",
- errno, strerror(errno));
+ if (xc_readconsolering(xc_handle, &bufptr, &size, 0, 1, &index) == 0 && size > 0) {
+ int logret;
+ if (log_time_guest)
+ logret = write_with_timestamp(log_hv_fd, buffer, size);
+ else
+ logret = write_all(log_hv_fd, buffer, size);
+
+ if (logret < 0)
+ dolog(LOG_ERR, "Failed to write hypervisor log: "
+ "%d (%s)", errno, strerror(errno));
}
(void)xc_evtchn_unmask(xce_handle, port);
diff --git a/tools/console/daemon/main.c b/tools/console/daemon/main.c
index ea0648f400..c66642ff46 100644
--- a/tools/console/daemon/main.c
+++ b/tools/console/daemon/main.c
@@ -35,6 +35,8 @@
int log_reload = 0;
int log_guest = 0;
int log_hv = 0;
+int log_time_hv = 0;
+int log_time_guest = 0;
char *log_dir = NULL;
static void handle_hup(int sig)
@@ -44,7 +46,7 @@ static void handle_hup(int sig)
static void usage(char *name)
{
- printf("Usage: %s [-h] [-V] [-v] [-i] [--log=none|guest|hv|all] [--log-dir=DIR] [--pid-file=PATH]\n", name);
+ printf("Usage: %s [-h] [-V] [-v] [-i] [--log=none|guest|hv|all] [--log-dir=DIR] [--pid-file=PATH] [-t, --timestamp=none|guest|hv|all]\n", name);
}
static void version(char *name)
@@ -54,7 +56,7 @@ static void version(char *name)
int main(int argc, char **argv)
{
- const char *sopts = "hVvi";
+ const char *sopts = "hVvit:";
struct option lopts[] = {
{ "help", 0, 0, 'h' },
{ "version", 0, 0, 'V' },
@@ -63,6 +65,7 @@ int main(int argc, char **argv)
{ "log", 1, 0, 'l' },
{ "log-dir", 1, 0, 'r' },
{ "pid-file", 1, 0, 'p' },
+ { "timestamp", 1, 0, 't' },
{ 0 },
};
bool is_interactive = false;
@@ -103,6 +106,19 @@ int main(int argc, char **argv)
case 'p':
pidfile = strdup(optarg);
break;
+ case 't':
+ if (!strcmp(optarg, "all")) {
+ log_time_hv = 1;
+ log_time_guest = 1;
+ } else if (!strcmp(optarg, "hv")) {
+ log_time_hv = 1;
+ } else if (!strcmp(optarg, "guest")) {
+ log_time_guest = 1;
+ } else if (!strcmp(optarg, "none")) {
+ log_time_guest = 0;
+ log_time_hv = 0;
+ }
+ break;
case '?':
fprintf(stderr,
"Try `%s --help' for more information\n",
diff --git a/tools/firmware/hvmloader/acpi/build.c b/tools/firmware/hvmloader/acpi/build.c
index 247c3b5928..e33cc04795 100644
--- a/tools/firmware/hvmloader/acpi/build.c
+++ b/tools/firmware/hvmloader/acpi/build.c
@@ -62,11 +62,18 @@ static int uart_exists(uint16_t uart_base)
return ((b == 0) && (c == 0xf));
}
+static int hpet_exists(unsigned long hpet_base)
+{
+ uint32_t hpet_id = *(uint32_t *)hpet_base;
+ return ((hpet_id >> 16) == 0x8086);
+}
+
static int construct_bios_info_table(uint8_t *buf)
{
struct bios_info {
uint8_t com1_present:1;
uint8_t com2_present:1;
+ uint8_t hpet_present:1;
uint32_t pci_min, pci_len;
} *bios_info = (struct bios_info *)buf;
@@ -75,6 +82,8 @@ static int construct_bios_info_table(uint8_t *buf)
bios_info->com1_present = uart_exists(0x3f8);
bios_info->com2_present = uart_exists(0x2f8);
+ bios_info->hpet_present = hpet_exists(ACPI_HPET_ADDRESS);
+
bios_info->pci_min = 0xf0000000;
bios_info->pci_len = 0x0c000000;
@@ -272,9 +281,12 @@ static int construct_secondary_tables(uint8_t *buf, unsigned long *table_ptrs)
}
/* HPET. */
- hpet = (struct acpi_20_hpet *)&buf[offset];
- offset += construct_hpet(hpet);
- table_ptrs[nr_tables++] = (unsigned long)hpet;
+ if ( hpet_exists(ACPI_HPET_ADDRESS) )
+ {
+ hpet = (struct acpi_20_hpet *)&buf[offset];
+ offset += construct_hpet(hpet);
+ table_ptrs[nr_tables++] = (unsigned long)hpet;
+ }
/* Processor Object SSDT. */
table_ptrs[nr_tables++] = (unsigned long)&buf[offset];
diff --git a/tools/firmware/hvmloader/acpi/dsdt.asl b/tools/firmware/hvmloader/acpi/dsdt.asl
index f5c2fefda5..fde51ac0ad 100644
--- a/tools/firmware/hvmloader/acpi/dsdt.asl
+++ b/tools/firmware/hvmloader/acpi/dsdt.asl
@@ -49,6 +49,7 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, "Xen", "HVM", 0)
Field(BIOS, ByteAcc, NoLock, Preserve) {
UAR1, 1,
UAR2, 1,
+ HPET, 1,
Offset(4),
PMIN, 32,
PLEN, 32
@@ -296,6 +297,13 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, "Xen", "HVM", 0)
Device(HPET) {
Name(_HID, EISAID("PNP0103"))
Name(_UID, 0)
+ Method (_STA, 0, NotSerialized) {
+ If(LEqual(\_SB.HPET, 0)) {
+ Return(0x00)
+ } Else {
+ Return(0x0F)
+ }
+ }
Name(_CRS, ResourceTemplate() {
DWordMemory(
ResourceConsumer, PosDecode, MinFixed, MaxFixed,
diff --git a/tools/firmware/hvmloader/acpi/dsdt.c b/tools/firmware/hvmloader/acpi/dsdt.c
index ab34c068bb..54088c6746 100644
--- a/tools/firmware/hvmloader/acpi/dsdt.c
+++ b/tools/firmware/hvmloader/acpi/dsdt.c
@@ -5,15 +5,15 @@
* Copyright (C) 2000 - 2006 Intel Corporation
* Supports ACPI Specification Revision 3.0a
*
- * Compilation of "dsdt.asl" - Mon Jan 21 14:11:31 2008
+ * Compilation of "dsdt.asl" - Mon Feb 11 13:31:53 2008
*
* C source code output
*
*/
unsigned char AmlCode[] =
{
- 0x44,0x53,0x44,0x54,0x6F,0x0E,0x00,0x00, /* 00000000 "DSDTo..." */
- 0x02,0xE1,0x58,0x65,0x6E,0x00,0x00,0x00, /* 00000008 "..Xen..." */
+ 0x44,0x53,0x44,0x54,0x8E,0x0E,0x00,0x00, /* 00000000 "DSDT...." */
+ 0x02,0x6E,0x58,0x65,0x6E,0x00,0x00,0x00, /* 00000008 ".nXen..." */
0x48,0x56,0x4D,0x00,0x00,0x00,0x00,0x00, /* 00000010 "HVM....." */
0x00,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */
0x07,0x07,0x06,0x20,0x08,0x50,0x4D,0x42, /* 00000020 "... .PMB" */
@@ -27,452 +27,456 @@ unsigned char AmlCode[] =
0x04,0x0A,0x07,0x0A,0x07,0x00,0x00,0x08, /* 00000060 "........" */
0x50,0x49,0x43,0x44,0x00,0x14,0x0C,0x5F, /* 00000068 "PICD..._" */
0x50,0x49,0x43,0x01,0x70,0x68,0x50,0x49, /* 00000070 "PIC.phPI" */
- 0x43,0x44,0x10,0x44,0xDF,0x5F,0x53,0x42, /* 00000078 "CD.D._SB" */
+ 0x43,0x44,0x10,0x43,0xE1,0x5F,0x53,0x42, /* 00000078 "CD.C._SB" */
0x5F,0x5B,0x80,0x42,0x49,0x4F,0x53,0x00, /* 00000080 "_[.BIOS." */
0x0C,0x00,0xA0,0x0E,0x00,0x0A,0x10,0x5B, /* 00000088 ".......[" */
- 0x81,0x1C,0x42,0x49,0x4F,0x53,0x01,0x55, /* 00000090 "..BIOS.U" */
+ 0x81,0x21,0x42,0x49,0x4F,0x53,0x01,0x55, /* 00000090 ".!BIOS.U" */
0x41,0x52,0x31,0x01,0x55,0x41,0x52,0x32, /* 00000098 "AR1.UAR2" */
- 0x01,0x00,0x1E,0x50,0x4D,0x49,0x4E,0x20, /* 000000A0 "...PMIN " */
- 0x50,0x4C,0x45,0x4E,0x20,0x5B,0x82,0x49, /* 000000A8 "PLEN [.I" */
- 0x04,0x4D,0x45,0x4D,0x30,0x08,0x5F,0x48, /* 000000B0 ".MEM0._H" */
- 0x49,0x44,0x0C,0x41,0xD0,0x0C,0x02,0x08, /* 000000B8 "ID.A...." */
- 0x5F,0x43,0x52,0x53,0x11,0x33,0x0A,0x30, /* 000000C0 "_CRS.3.0" */
- 0x8A,0x2B,0x00,0x00,0x0D,0x03,0x00,0x00, /* 000000C8 ".+......" */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000D0 "........" */
- 0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF, /* 000000D8 "........" */
- 0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000E0 "........" */
+ 0x01,0x48,0x50,0x45,0x54,0x01,0x00,0x1D, /* 000000A0 ".HPET..." */
+ 0x50,0x4D,0x49,0x4E,0x20,0x50,0x4C,0x45, /* 000000A8 "PMIN PLE" */
+ 0x4E,0x20,0x5B,0x82,0x49,0x04,0x4D,0x45, /* 000000B0 "N [.I.ME" */
+ 0x4D,0x30,0x08,0x5F,0x48,0x49,0x44,0x0C, /* 000000B8 "M0._HID." */
+ 0x41,0xD0,0x0C,0x02,0x08,0x5F,0x43,0x52, /* 000000C0 "A...._CR" */
+ 0x53,0x11,0x33,0x0A,0x30,0x8A,0x2B,0x00, /* 000000C8 "S.3.0.+." */
+ 0x00,0x0D,0x03,0x00,0x00,0x00,0x00,0x00, /* 000000D0 "........" */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000D8 "........" */
+ 0x00,0x00,0x00,0xFF,0xFF,0x09,0x00,0x00, /* 000000E0 "........" */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000E8 "........" */
- 0x0A,0x00,0x00,0x00,0x00,0x00,0x79,0x00, /* 000000F0 "......y." */
- 0x5B,0x82,0x45,0xD7,0x50,0x43,0x49,0x30, /* 000000F8 "[.E.PCI0" */
- 0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 00000100 "._HID.A." */
- 0x0A,0x03,0x08,0x5F,0x55,0x49,0x44,0x00, /* 00000108 "..._UID." */
- 0x08,0x5F,0x41,0x44,0x52,0x00,0x08,0x5F, /* 00000110 "._ADR.._" */
- 0x42,0x42,0x4E,0x00,0x14,0x4E,0x0C,0x5F, /* 00000118 "BBN..N._" */
- 0x43,0x52,0x53,0x00,0x08,0x50,0x52,0x54, /* 00000120 "CRS..PRT" */
- 0x30,0x11,0x42,0x07,0x0A,0x6E,0x88,0x0D, /* 00000128 "0.B..n.." */
- 0x00,0x02,0x0E,0x00,0x00,0x00,0x00,0x00, /* 00000130 "........" */
- 0xFF,0x00,0x00,0x00,0x00,0x01,0x47,0x01, /* 00000138 "......G." */
- 0xF8,0x0C,0xF8,0x0C,0x01,0x08,0x88,0x0D, /* 00000140 "........" */
- 0x00,0x01,0x0C,0x03,0x00,0x00,0x00,0x00, /* 00000148 "........" */
- 0xF7,0x0C,0x00,0x00,0xF8,0x0C,0x88,0x0D, /* 00000150 "........" */
- 0x00,0x01,0x0C,0x03,0x00,0x00,0x00,0x0D, /* 00000158 "........" */
- 0xFF,0xFF,0x00,0x00,0x00,0xF3,0x87,0x17, /* 00000160 "........" */
- 0x00,0x00,0x0C,0x03,0x00,0x00,0x00,0x00, /* 00000168 "........" */
- 0x00,0x00,0x0A,0x00,0xFF,0xFF,0x0B,0x00, /* 00000170 "........" */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00, /* 00000178 "........" */
- 0x87,0x17,0x00,0x00,0x0C,0x03,0x00,0x00, /* 00000180 "........" */
- 0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0xFF, /* 00000188 "........" */
- 0xFF,0xF4,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000190 "........" */
- 0x00,0x05,0x79,0x00,0x8A,0x50,0x52,0x54, /* 00000198 "..y..PRT" */
- 0x30,0x0A,0x5C,0x4D,0x4D,0x49,0x4E,0x8A, /* 000001A0 "0.\MMIN." */
- 0x50,0x52,0x54,0x30,0x0A,0x60,0x4D,0x4D, /* 000001A8 "PRT0.`MM" */
- 0x41,0x58,0x8A,0x50,0x52,0x54,0x30,0x0A, /* 000001B0 "AX.PRT0." */
- 0x68,0x4D,0x4C,0x45,0x4E,0x70,0x50,0x4D, /* 000001B8 "hMLENpPM" */
- 0x49,0x4E,0x4D,0x4D,0x49,0x4E,0x70,0x50, /* 000001C0 "INMMINpP" */
- 0x4C,0x45,0x4E,0x4D,0x4C,0x45,0x4E,0x72, /* 000001C8 "LENMLENr" */
- 0x4D,0x4D,0x49,0x4E,0x4D,0x4C,0x45,0x4E, /* 000001D0 "MMINMLEN" */
- 0x4D,0x4D,0x41,0x58,0x74,0x4D,0x4D,0x41, /* 000001D8 "MMAXtMMA" */
- 0x58,0x01,0x4D,0x4D,0x41,0x58,0xA4,0x50, /* 000001E0 "X.MMAX.P" */
- 0x52,0x54,0x30,0x08,0x42,0x55,0x46,0x41, /* 000001E8 "RT0.BUFA" */
- 0x11,0x09,0x0A,0x06,0x23,0x20,0x0C,0x18, /* 000001F0 "....# .." */
- 0x79,0x00,0x08,0x42,0x55,0x46,0x42,0x11, /* 000001F8 "y..BUFB." */
- 0x09,0x0A,0x06,0x23,0x00,0x00,0x18,0x79, /* 00000200 "...#...y" */
- 0x00,0x8B,0x42,0x55,0x46,0x42,0x01,0x49, /* 00000208 "..BUFB.I" */
- 0x52,0x51,0x56,0x5B,0x82,0x48,0x08,0x4C, /* 00000210 "RQV[.H.L" */
- 0x4E,0x4B,0x41,0x08,0x5F,0x48,0x49,0x44, /* 00000218 "NKA._HID" */
- 0x0C,0x41,0xD0,0x0C,0x0F,0x08,0x5F,0x55, /* 00000220 ".A...._U" */
- 0x49,0x44,0x01,0x14,0x1C,0x5F,0x53,0x54, /* 00000228 "ID..._ST" */
- 0x41,0x00,0x7B,0x50,0x49,0x52,0x41,0x0A, /* 00000230 "A.{PIRA." */
- 0x80,0x60,0xA0,0x08,0x93,0x60,0x0A,0x80, /* 00000238 ".`...`.." */
- 0xA4,0x0A,0x09,0xA1,0x04,0xA4,0x0A,0x0B, /* 00000240 "........" */
- 0x14,0x0B,0x5F,0x50,0x52,0x53,0x00,0xA4, /* 00000248 ".._PRS.." */
- 0x42,0x55,0x46,0x41,0x14,0x11,0x5F,0x44, /* 00000250 "BUFA.._D" */
- 0x49,0x53,0x00,0x7D,0x50,0x49,0x52,0x41, /* 00000258 "IS.}PIRA" */
- 0x0A,0x80,0x50,0x49,0x52,0x41,0x14,0x1A, /* 00000260 "..PIRA.." */
- 0x5F,0x43,0x52,0x53,0x00,0x7B,0x50,0x49, /* 00000268 "_CRS.{PI" */
- 0x52,0x41,0x0A,0x0F,0x60,0x79,0x01,0x60, /* 00000270 "RA..`y.`" */
- 0x49,0x52,0x51,0x56,0xA4,0x42,0x55,0x46, /* 00000278 "IRQV.BUF" */
- 0x42,0x14,0x1B,0x5F,0x53,0x52,0x53,0x01, /* 00000280 "B.._SRS." */
- 0x8B,0x68,0x01,0x49,0x52,0x51,0x31,0x82, /* 00000288 ".h.IRQ1." */
- 0x49,0x52,0x51,0x31,0x60,0x76,0x60,0x70, /* 00000290 "IRQ1`v`p" */
- 0x60,0x50,0x49,0x52,0x41,0x5B,0x82,0x49, /* 00000298 "`PIRA[.I" */
- 0x08,0x4C,0x4E,0x4B,0x42,0x08,0x5F,0x48, /* 000002A0 ".LNKB._H" */
- 0x49,0x44,0x0C,0x41,0xD0,0x0C,0x0F,0x08, /* 000002A8 "ID.A...." */
- 0x5F,0x55,0x49,0x44,0x0A,0x02,0x14,0x1C, /* 000002B0 "_UID...." */
- 0x5F,0x53,0x54,0x41,0x00,0x7B,0x50,0x49, /* 000002B8 "_STA.{PI" */
- 0x52,0x42,0x0A,0x80,0x60,0xA0,0x08,0x93, /* 000002C0 "RB..`..." */
- 0x60,0x0A,0x80,0xA4,0x0A,0x09,0xA1,0x04, /* 000002C8 "`......." */
- 0xA4,0x0A,0x0B,0x14,0x0B,0x5F,0x50,0x52, /* 000002D0 "....._PR" */
- 0x53,0x00,0xA4,0x42,0x55,0x46,0x41,0x14, /* 000002D8 "S..BUFA." */
- 0x11,0x5F,0x44,0x49,0x53,0x00,0x7D,0x50, /* 000002E0 "._DIS.}P" */
- 0x49,0x52,0x42,0x0A,0x80,0x50,0x49,0x52, /* 000002E8 "IRB..PIR" */
- 0x42,0x14,0x1A,0x5F,0x43,0x52,0x53,0x00, /* 000002F0 "B.._CRS." */
- 0x7B,0x50,0x49,0x52,0x42,0x0A,0x0F,0x60, /* 000002F8 "{PIRB..`" */
- 0x79,0x01,0x60,0x49,0x52,0x51,0x56,0xA4, /* 00000300 "y.`IRQV." */
- 0x42,0x55,0x46,0x42,0x14,0x1B,0x5F,0x53, /* 00000308 "BUFB.._S" */
- 0x52,0x53,0x01,0x8B,0x68,0x01,0x49,0x52, /* 00000310 "RS..h.IR" */
- 0x51,0x31,0x82,0x49,0x52,0x51,0x31,0x60, /* 00000318 "Q1.IRQ1`" */
- 0x76,0x60,0x70,0x60,0x50,0x49,0x52,0x42, /* 00000320 "v`p`PIRB" */
- 0x5B,0x82,0x49,0x08,0x4C,0x4E,0x4B,0x43, /* 00000328 "[.I.LNKC" */
- 0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 00000330 "._HID.A." */
- 0x0C,0x0F,0x08,0x5F,0x55,0x49,0x44,0x0A, /* 00000338 "..._UID." */
- 0x03,0x14,0x1C,0x5F,0x53,0x54,0x41,0x00, /* 00000340 "..._STA." */
- 0x7B,0x50,0x49,0x52,0x43,0x0A,0x80,0x60, /* 00000348 "{PIRC..`" */
- 0xA0,0x08,0x93,0x60,0x0A,0x80,0xA4,0x0A, /* 00000350 "...`...." */
- 0x09,0xA1,0x04,0xA4,0x0A,0x0B,0x14,0x0B, /* 00000358 "........" */
- 0x5F,0x50,0x52,0x53,0x00,0xA4,0x42,0x55, /* 00000360 "_PRS..BU" */
- 0x46,0x41,0x14,0x11,0x5F,0x44,0x49,0x53, /* 00000368 "FA.._DIS" */
- 0x00,0x7D,0x50,0x49,0x52,0x43,0x0A,0x80, /* 00000370 ".}PIRC.." */
- 0x50,0x49,0x52,0x43,0x14,0x1A,0x5F,0x43, /* 00000378 "PIRC.._C" */
- 0x52,0x53,0x00,0x7B,0x50,0x49,0x52,0x43, /* 00000380 "RS.{PIRC" */
- 0x0A,0x0F,0x60,0x79,0x01,0x60,0x49,0x52, /* 00000388 "..`y.`IR" */
- 0x51,0x56,0xA4,0x42,0x55,0x46,0x42,0x14, /* 00000390 "QV.BUFB." */
- 0x1B,0x5F,0x53,0x52,0x53,0x01,0x8B,0x68, /* 00000398 "._SRS..h" */
- 0x01,0x49,0x52,0x51,0x31,0x82,0x49,0x52, /* 000003A0 ".IRQ1.IR" */
- 0x51,0x31,0x60,0x76,0x60,0x70,0x60,0x50, /* 000003A8 "Q1`v`p`P" */
- 0x49,0x52,0x43,0x5B,0x82,0x49,0x08,0x4C, /* 000003B0 "IRC[.I.L" */
- 0x4E,0x4B,0x44,0x08,0x5F,0x48,0x49,0x44, /* 000003B8 "NKD._HID" */
- 0x0C,0x41,0xD0,0x0C,0x0F,0x08,0x5F,0x55, /* 000003C0 ".A...._U" */
- 0x49,0x44,0x0A,0x04,0x14,0x1C,0x5F,0x53, /* 000003C8 "ID...._S" */
- 0x54,0x41,0x00,0x7B,0x50,0x49,0x52,0x44, /* 000003D0 "TA.{PIRD" */
- 0x0A,0x80,0x60,0xA0,0x08,0x93,0x60,0x0A, /* 000003D8 "..`...`." */
- 0x80,0xA4,0x0A,0x09,0xA1,0x04,0xA4,0x0A, /* 000003E0 "........" */
- 0x0B,0x14,0x0B,0x5F,0x50,0x52,0x53,0x00, /* 000003E8 "..._PRS." */
- 0xA4,0x42,0x55,0x46,0x41,0x14,0x11,0x5F, /* 000003F0 ".BUFA.._" */
- 0x44,0x49,0x53,0x00,0x7D,0x50,0x49,0x52, /* 000003F8 "DIS.}PIR" */
- 0x44,0x0A,0x80,0x50,0x49,0x52,0x44,0x14, /* 00000400 "D..PIRD." */
- 0x1A,0x5F,0x43,0x52,0x53,0x00,0x7B,0x50, /* 00000408 "._CRS.{P" */
- 0x49,0x52,0x44,0x0A,0x0F,0x60,0x79,0x01, /* 00000410 "IRD..`y." */
- 0x60,0x49,0x52,0x51,0x56,0xA4,0x42,0x55, /* 00000418 "`IRQV.BU" */
- 0x46,0x42,0x14,0x1B,0x5F,0x53,0x52,0x53, /* 00000420 "FB.._SRS" */
- 0x01,0x8B,0x68,0x01,0x49,0x52,0x51,0x31, /* 00000428 "..h.IRQ1" */
- 0x82,0x49,0x52,0x51,0x31,0x60,0x76,0x60, /* 00000430 ".IRQ1`v`" */
- 0x70,0x60,0x50,0x49,0x52,0x44,0x5B,0x82, /* 00000438 "p`PIRD[." */
- 0x3A,0x48,0x50,0x45,0x54,0x08,0x5F,0x48, /* 00000440 ":HPET._H" */
- 0x49,0x44,0x0C,0x41,0xD0,0x01,0x03,0x08, /* 00000448 "ID.A...." */
- 0x5F,0x55,0x49,0x44,0x00,0x08,0x5F,0x43, /* 00000450 "_UID.._C" */
- 0x52,0x53,0x11,0x1F,0x0A,0x1C,0x87,0x17, /* 00000458 "RS......" */
- 0x00,0x00,0x0D,0x01,0x00,0x00,0x00,0x00, /* 00000460 "........" */
- 0x00,0x00,0xD0,0xFE,0xFF,0x03,0xD0,0xFE, /* 00000468 "........" */
- 0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00, /* 00000470 "........" */
- 0x79,0x00,0x14,0x16,0x5F,0x50,0x52,0x54, /* 00000478 "y..._PRT" */
- 0x00,0xA0,0x0A,0x50,0x49,0x43,0x44,0xA4, /* 00000480 "...PICD." */
- 0x50,0x52,0x54,0x41,0xA4,0x50,0x52,0x54, /* 00000488 "PRTA.PRT" */
- 0x50,0x08,0x50,0x52,0x54,0x50,0x12,0x49, /* 00000490 "P.PRTP.I" */
- 0x36,0x3C,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 00000498 "6<......" */
- 0x01,0x00,0x00,0x4C,0x4E,0x4B,0x42,0x00, /* 000004A0 "...LNKB." */
- 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x01,0x00, /* 000004A8 "........" */
- 0x01,0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0E, /* 000004B0 ".LNKC..." */
- 0x04,0x0C,0xFF,0xFF,0x01,0x00,0x0A,0x02, /* 000004B8 "........" */
- 0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04, /* 000004C0 "LNKD...." */
- 0x0C,0xFF,0xFF,0x01,0x00,0x0A,0x03,0x4C, /* 000004C8 ".......L" */
- 0x4E,0x4B,0x41,0x00,0x12,0x0D,0x04,0x0C, /* 000004D0 "NKA....." */
- 0xFF,0xFF,0x02,0x00,0x00,0x4C,0x4E,0x4B, /* 000004D8 ".....LNK" */
- 0x43,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 000004E0 "C......." */
- 0x02,0x00,0x01,0x4C,0x4E,0x4B,0x44,0x00, /* 000004E8 "...LNKD." */
- 0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x02,0x00, /* 000004F0 "........" */
- 0x0A,0x02,0x4C,0x4E,0x4B,0x41,0x00,0x12, /* 000004F8 "..LNKA.." */
- 0x0E,0x04,0x0C,0xFF,0xFF,0x02,0x00,0x0A, /* 00000500 "........" */
- 0x03,0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0D, /* 00000508 ".LNKB..." */
- 0x04,0x0C,0xFF,0xFF,0x03,0x00,0x00,0x4C, /* 00000510 ".......L" */
- 0x4E,0x4B,0x44,0x00,0x12,0x0D,0x04,0x0C, /* 00000518 "NKD....." */
- 0xFF,0xFF,0x03,0x00,0x01,0x4C,0x4E,0x4B, /* 00000520 ".....LNK" */
- 0x41,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 00000528 "A......." */
- 0x03,0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x42, /* 00000530 "....LNKB" */
- 0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x03, /* 00000538 "........" */
- 0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x43,0x00, /* 00000540 "...LNKC." */
- 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x04,0x00, /* 00000548 "........" */
- 0x00,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0D, /* 00000550 ".LNKA..." */
- 0x04,0x0C,0xFF,0xFF,0x04,0x00,0x01,0x4C, /* 00000558 ".......L" */
- 0x4E,0x4B,0x42,0x00,0x12,0x0E,0x04,0x0C, /* 00000560 "NKB....." */
- 0xFF,0xFF,0x04,0x00,0x0A,0x02,0x4C,0x4E, /* 00000568 "......LN" */
- 0x4B,0x43,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 00000570 "KC......" */
- 0xFF,0x04,0x00,0x0A,0x03,0x4C,0x4E,0x4B, /* 00000578 ".....LNK" */
- 0x44,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 00000580 "D......." */
- 0x05,0x00,0x00,0x4C,0x4E,0x4B,0x42,0x00, /* 00000588 "...LNKB." */
- 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x05,0x00, /* 00000590 "........" */
- 0x01,0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0E, /* 00000598 ".LNKC..." */
- 0x04,0x0C,0xFF,0xFF,0x05,0x00,0x0A,0x02, /* 000005A0 "........" */
- 0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04, /* 000005A8 "LNKD...." */
- 0x0C,0xFF,0xFF,0x05,0x00,0x0A,0x03,0x4C, /* 000005B0 ".......L" */
- 0x4E,0x4B,0x41,0x00,0x12,0x0D,0x04,0x0C, /* 000005B8 "NKA....." */
- 0xFF,0xFF,0x06,0x00,0x00,0x4C,0x4E,0x4B, /* 000005C0 ".....LNK" */
- 0x43,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 000005C8 "C......." */
- 0x06,0x00,0x01,0x4C,0x4E,0x4B,0x44,0x00, /* 000005D0 "...LNKD." */
- 0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x06,0x00, /* 000005D8 "........" */
- 0x0A,0x02,0x4C,0x4E,0x4B,0x41,0x00,0x12, /* 000005E0 "..LNKA.." */
- 0x0E,0x04,0x0C,0xFF,0xFF,0x06,0x00,0x0A, /* 000005E8 "........" */
- 0x03,0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0D, /* 000005F0 ".LNKB..." */
- 0x04,0x0C,0xFF,0xFF,0x07,0x00,0x00,0x4C, /* 000005F8 ".......L" */
- 0x4E,0x4B,0x44,0x00,0x12,0x0D,0x04,0x0C, /* 00000600 "NKD....." */
- 0xFF,0xFF,0x07,0x00,0x01,0x4C,0x4E,0x4B, /* 00000608 ".....LNK" */
- 0x41,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 00000610 "A......." */
- 0x07,0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x42, /* 00000618 "....LNKB" */
- 0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x07, /* 00000620 "........" */
- 0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x43,0x00, /* 00000628 "...LNKC." */
- 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x08,0x00, /* 00000630 "........" */
- 0x00,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0D, /* 00000638 ".LNKA..." */
- 0x04,0x0C,0xFF,0xFF,0x08,0x00,0x01,0x4C, /* 00000640 ".......L" */
- 0x4E,0x4B,0x42,0x00,0x12,0x0E,0x04,0x0C, /* 00000648 "NKB....." */
- 0xFF,0xFF,0x08,0x00,0x0A,0x02,0x4C,0x4E, /* 00000650 "......LN" */
- 0x4B,0x43,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 00000658 "KC......" */
- 0xFF,0x08,0x00,0x0A,0x03,0x4C,0x4E,0x4B, /* 00000660 ".....LNK" */
- 0x44,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 00000668 "D......." */
- 0x09,0x00,0x00,0x4C,0x4E,0x4B,0x42,0x00, /* 00000670 "...LNKB." */
- 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x09,0x00, /* 00000678 "........" */
- 0x01,0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0E, /* 00000680 ".LNKC..." */
- 0x04,0x0C,0xFF,0xFF,0x09,0x00,0x0A,0x02, /* 00000688 "........" */
- 0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04, /* 00000690 "LNKD...." */
- 0x0C,0xFF,0xFF,0x09,0x00,0x0A,0x03,0x4C, /* 00000698 ".......L" */
- 0x4E,0x4B,0x41,0x00,0x12,0x0D,0x04,0x0C, /* 000006A0 "NKA....." */
- 0xFF,0xFF,0x0A,0x00,0x00,0x4C,0x4E,0x4B, /* 000006A8 ".....LNK" */
- 0x43,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 000006B0 "C......." */
- 0x0A,0x00,0x01,0x4C,0x4E,0x4B,0x44,0x00, /* 000006B8 "...LNKD." */
- 0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x0A,0x00, /* 000006C0 "........" */
- 0x0A,0x02,0x4C,0x4E,0x4B,0x41,0x00,0x12, /* 000006C8 "..LNKA.." */
- 0x0E,0x04,0x0C,0xFF,0xFF,0x0A,0x00,0x0A, /* 000006D0 "........" */
- 0x03,0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0D, /* 000006D8 ".LNKB..." */
- 0x04,0x0C,0xFF,0xFF,0x0B,0x00,0x00,0x4C, /* 000006E0 ".......L" */
- 0x4E,0x4B,0x44,0x00,0x12,0x0D,0x04,0x0C, /* 000006E8 "NKD....." */
- 0xFF,0xFF,0x0B,0x00,0x01,0x4C,0x4E,0x4B, /* 000006F0 ".....LNK" */
- 0x41,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 000006F8 "A......." */
- 0x0B,0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x42, /* 00000700 "....LNKB" */
- 0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x0B, /* 00000708 "........" */
- 0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x43,0x00, /* 00000710 "...LNKC." */
- 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x0C,0x00, /* 00000718 "........" */
- 0x00,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0D, /* 00000720 ".LNKA..." */
- 0x04,0x0C,0xFF,0xFF,0x0C,0x00,0x01,0x4C, /* 00000728 ".......L" */
- 0x4E,0x4B,0x42,0x00,0x12,0x0E,0x04,0x0C, /* 00000730 "NKB....." */
- 0xFF,0xFF,0x0C,0x00,0x0A,0x02,0x4C,0x4E, /* 00000738 "......LN" */
- 0x4B,0x43,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 00000740 "KC......" */
- 0xFF,0x0C,0x00,0x0A,0x03,0x4C,0x4E,0x4B, /* 00000748 ".....LNK" */
- 0x44,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 00000750 "D......." */
- 0x0D,0x00,0x00,0x4C,0x4E,0x4B,0x42,0x00, /* 00000758 "...LNKB." */
- 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x0D,0x00, /* 00000760 "........" */
- 0x01,0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0E, /* 00000768 ".LNKC..." */
- 0x04,0x0C,0xFF,0xFF,0x0D,0x00,0x0A,0x02, /* 00000770 "........" */
- 0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04, /* 00000778 "LNKD...." */
- 0x0C,0xFF,0xFF,0x0D,0x00,0x0A,0x03,0x4C, /* 00000780 ".......L" */
- 0x4E,0x4B,0x41,0x00,0x12,0x0D,0x04,0x0C, /* 00000788 "NKA....." */
- 0xFF,0xFF,0x0E,0x00,0x00,0x4C,0x4E,0x4B, /* 00000790 ".....LNK" */
- 0x43,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 00000798 "C......." */
- 0x0E,0x00,0x01,0x4C,0x4E,0x4B,0x44,0x00, /* 000007A0 "...LNKD." */
- 0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x0E,0x00, /* 000007A8 "........" */
- 0x0A,0x02,0x4C,0x4E,0x4B,0x41,0x00,0x12, /* 000007B0 "..LNKA.." */
- 0x0E,0x04,0x0C,0xFF,0xFF,0x0E,0x00,0x0A, /* 000007B8 "........" */
- 0x03,0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0D, /* 000007C0 ".LNKB..." */
- 0x04,0x0C,0xFF,0xFF,0x0F,0x00,0x00,0x4C, /* 000007C8 ".......L" */
- 0x4E,0x4B,0x44,0x00,0x12,0x0D,0x04,0x0C, /* 000007D0 "NKD....." */
- 0xFF,0xFF,0x0F,0x00,0x01,0x4C,0x4E,0x4B, /* 000007D8 ".....LNK" */
- 0x41,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 000007E0 "A......." */
- 0x0F,0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x42, /* 000007E8 "....LNKB" */
- 0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x0F, /* 000007F0 "........" */
- 0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x43,0x00, /* 000007F8 "...LNKC." */
- 0x08,0x50,0x52,0x54,0x41,0x12,0x41,0x2F, /* 00000800 ".PRTA.A/" */
- 0x3C,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x01, /* 00000808 "<......." */
- 0x00,0x00,0x00,0x0A,0x14,0x12,0x0B,0x04, /* 00000810 "........" */
- 0x0C,0xFF,0xFF,0x01,0x00,0x01,0x00,0x0A, /* 00000818 "........" */
- 0x15,0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x01, /* 00000820 "........" */
- 0x00,0x0A,0x02,0x00,0x0A,0x16,0x12,0x0C, /* 00000828 "........" */
- 0x04,0x0C,0xFF,0xFF,0x01,0x00,0x0A,0x03, /* 00000830 "........" */
- 0x00,0x0A,0x17,0x12,0x0B,0x04,0x0C,0xFF, /* 00000838 "........" */
- 0xFF,0x02,0x00,0x00,0x00,0x0A,0x18,0x12, /* 00000840 "........" */
- 0x0B,0x04,0x0C,0xFF,0xFF,0x02,0x00,0x01, /* 00000848 "........" */
- 0x00,0x0A,0x19,0x12,0x0C,0x04,0x0C,0xFF, /* 00000850 "........" */
- 0xFF,0x02,0x00,0x0A,0x02,0x00,0x0A,0x1A, /* 00000858 "........" */
- 0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x02,0x00, /* 00000860 "........" */
- 0x0A,0x03,0x00,0x0A,0x1B,0x12,0x0B,0x04, /* 00000868 "........" */
- 0x0C,0xFF,0xFF,0x03,0x00,0x00,0x00,0x0A, /* 00000870 "........" */
- 0x1C,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x03, /* 00000878 "........" */
- 0x00,0x01,0x00,0x0A,0x1D,0x12,0x0C,0x04, /* 00000880 "........" */
- 0x0C,0xFF,0xFF,0x03,0x00,0x0A,0x02,0x00, /* 00000888 "........" */
- 0x0A,0x1E,0x12,0x0C,0x04,0x0C,0xFF,0xFF, /* 00000890 "........" */
- 0x03,0x00,0x0A,0x03,0x00,0x0A,0x1F,0x12, /* 00000898 "........" */
- 0x0B,0x04,0x0C,0xFF,0xFF,0x04,0x00,0x00, /* 000008A0 "........" */
- 0x00,0x0A,0x20,0x12,0x0B,0x04,0x0C,0xFF, /* 000008A8 ".. ....." */
- 0xFF,0x04,0x00,0x01,0x00,0x0A,0x21,0x12, /* 000008B0 "......!." */
- 0x0C,0x04,0x0C,0xFF,0xFF,0x04,0x00,0x0A, /* 000008B8 "........" */
- 0x02,0x00,0x0A,0x22,0x12,0x0C,0x04,0x0C, /* 000008C0 "..."...." */
- 0xFF,0xFF,0x04,0x00,0x0A,0x03,0x00,0x0A, /* 000008C8 "........" */
- 0x23,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x05, /* 000008D0 "#......." */
- 0x00,0x00,0x00,0x0A,0x24,0x12,0x0B,0x04, /* 000008D8 "....$..." */
- 0x0C,0xFF,0xFF,0x05,0x00,0x01,0x00,0x0A, /* 000008E0 "........" */
- 0x25,0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x05, /* 000008E8 "%......." */
- 0x00,0x0A,0x02,0x00,0x0A,0x26,0x12,0x0C, /* 000008F0 ".....&.." */
- 0x04,0x0C,0xFF,0xFF,0x05,0x00,0x0A,0x03, /* 000008F8 "........" */
- 0x00,0x0A,0x27,0x12,0x0B,0x04,0x0C,0xFF, /* 00000900 "..'....." */
- 0xFF,0x06,0x00,0x00,0x00,0x0A,0x28,0x12, /* 00000908 "......(." */
- 0x0B,0x04,0x0C,0xFF,0xFF,0x06,0x00,0x01, /* 00000910 "........" */
- 0x00,0x0A,0x29,0x12,0x0C,0x04,0x0C,0xFF, /* 00000918 "..)....." */
- 0xFF,0x06,0x00,0x0A,0x02,0x00,0x0A,0x2A, /* 00000920 ".......*" */
- 0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x06,0x00, /* 00000928 "........" */
- 0x0A,0x03,0x00,0x0A,0x2B,0x12,0x0B,0x04, /* 00000930 "....+..." */
- 0x0C,0xFF,0xFF,0x07,0x00,0x00,0x00,0x0A, /* 00000938 "........" */
- 0x2C,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x07, /* 00000940 ",......." */
- 0x00,0x01,0x00,0x0A,0x2D,0x12,0x0C,0x04, /* 00000948 "....-..." */
- 0x0C,0xFF,0xFF,0x07,0x00,0x0A,0x02,0x00, /* 00000950 "........" */
- 0x0A,0x2E,0x12,0x0C,0x04,0x0C,0xFF,0xFF, /* 00000958 "........" */
- 0x07,0x00,0x0A,0x03,0x00,0x0A,0x2F,0x12, /* 00000960 "....../." */
- 0x0B,0x04,0x0C,0xFF,0xFF,0x08,0x00,0x00, /* 00000968 "........" */
- 0x00,0x0A,0x11,0x12,0x0B,0x04,0x0C,0xFF, /* 00000970 "........" */
- 0xFF,0x08,0x00,0x01,0x00,0x0A,0x12,0x12, /* 00000978 "........" */
- 0x0C,0x04,0x0C,0xFF,0xFF,0x08,0x00,0x0A, /* 00000980 "........" */
- 0x02,0x00,0x0A,0x13,0x12,0x0C,0x04,0x0C, /* 00000988 "........" */
- 0xFF,0xFF,0x08,0x00,0x0A,0x03,0x00,0x0A, /* 00000990 "........" */
- 0x14,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x09, /* 00000998 "........" */
- 0x00,0x00,0x00,0x0A,0x15,0x12,0x0B,0x04, /* 000009A0 "........" */
- 0x0C,0xFF,0xFF,0x09,0x00,0x01,0x00,0x0A, /* 000009A8 "........" */
- 0x16,0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x09, /* 000009B0 "........" */
- 0x00,0x0A,0x02,0x00,0x0A,0x17,0x12,0x0C, /* 000009B8 "........" */
- 0x04,0x0C,0xFF,0xFF,0x09,0x00,0x0A,0x03, /* 000009C0 "........" */
- 0x00,0x0A,0x18,0x12,0x0B,0x04,0x0C,0xFF, /* 000009C8 "........" */
- 0xFF,0x0A,0x00,0x00,0x00,0x0A,0x19,0x12, /* 000009D0 "........" */
- 0x0B,0x04,0x0C,0xFF,0xFF,0x0A,0x00,0x01, /* 000009D8 "........" */
- 0x00,0x0A,0x1A,0x12,0x0C,0x04,0x0C,0xFF, /* 000009E0 "........" */
- 0xFF,0x0A,0x00,0x0A,0x02,0x00,0x0A,0x1B, /* 000009E8 "........" */
- 0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x0A,0x00, /* 000009F0 "........" */
- 0x0A,0x03,0x00,0x0A,0x1C,0x12,0x0B,0x04, /* 000009F8 "........" */
- 0x0C,0xFF,0xFF,0x0B,0x00,0x00,0x00,0x0A, /* 00000A00 "........" */
- 0x1D,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x0B, /* 00000A08 "........" */
- 0x00,0x01,0x00,0x0A,0x1E,0x12,0x0C,0x04, /* 00000A10 "........" */
- 0x0C,0xFF,0xFF,0x0B,0x00,0x0A,0x02,0x00, /* 00000A18 "........" */
- 0x0A,0x1F,0x12,0x0C,0x04,0x0C,0xFF,0xFF, /* 00000A20 "........" */
- 0x0B,0x00,0x0A,0x03,0x00,0x0A,0x20,0x12, /* 00000A28 "...... ." */
- 0x0B,0x04,0x0C,0xFF,0xFF,0x0C,0x00,0x00, /* 00000A30 "........" */
- 0x00,0x0A,0x21,0x12,0x0B,0x04,0x0C,0xFF, /* 00000A38 "..!....." */
- 0xFF,0x0C,0x00,0x01,0x00,0x0A,0x22,0x12, /* 00000A40 "......"." */
- 0x0C,0x04,0x0C,0xFF,0xFF,0x0C,0x00,0x0A, /* 00000A48 "........" */
- 0x02,0x00,0x0A,0x23,0x12,0x0C,0x04,0x0C, /* 00000A50 "...#...." */
- 0xFF,0xFF,0x0C,0x00,0x0A,0x03,0x00,0x0A, /* 00000A58 "........" */
- 0x24,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x0D, /* 00000A60 "$......." */
- 0x00,0x00,0x00,0x0A,0x25,0x12,0x0B,0x04, /* 00000A68 "....%..." */
- 0x0C,0xFF,0xFF,0x0D,0x00,0x01,0x00,0x0A, /* 00000A70 "........" */
- 0x26,0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x0D, /* 00000A78 "&......." */
- 0x00,0x0A,0x02,0x00,0x0A,0x27,0x12,0x0C, /* 00000A80 ".....'.." */
- 0x04,0x0C,0xFF,0xFF,0x0D,0x00,0x0A,0x03, /* 00000A88 "........" */
- 0x00,0x0A,0x28,0x12,0x0B,0x04,0x0C,0xFF, /* 00000A90 "..(....." */
- 0xFF,0x0E,0x00,0x00,0x00,0x0A,0x29,0x12, /* 00000A98 "......)." */
- 0x0B,0x04,0x0C,0xFF,0xFF,0x0E,0x00,0x01, /* 00000AA0 "........" */
- 0x00,0x0A,0x2A,0x12,0x0C,0x04,0x0C,0xFF, /* 00000AA8 "..*....." */
- 0xFF,0x0E,0x00,0x0A,0x02,0x00,0x0A,0x2B, /* 00000AB0 ".......+" */
- 0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x0E,0x00, /* 00000AB8 "........" */
- 0x0A,0x03,0x00,0x0A,0x2C,0x12,0x0B,0x04, /* 00000AC0 "....,..." */
- 0x0C,0xFF,0xFF,0x0F,0x00,0x00,0x00,0x0A, /* 00000AC8 "........" */
- 0x2D,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x0F, /* 00000AD0 "-......." */
- 0x00,0x01,0x00,0x0A,0x2E,0x12,0x0C,0x04, /* 00000AD8 "........" */
- 0x0C,0xFF,0xFF,0x0F,0x00,0x0A,0x02,0x00, /* 00000AE0 "........" */
- 0x0A,0x2F,0x12,0x0C,0x04,0x0C,0xFF,0xFF, /* 00000AE8 "./......" */
- 0x0F,0x00,0x0A,0x03,0x00,0x0A,0x10,0x5B, /* 00000AF0 ".......[" */
- 0x82,0x46,0x37,0x49,0x53,0x41,0x5F,0x08, /* 00000AF8 ".F7ISA_." */
- 0x5F,0x41,0x44,0x52,0x0C,0x00,0x00,0x01, /* 00000B00 "_ADR...." */
- 0x00,0x5B,0x80,0x50,0x49,0x52,0x51,0x02, /* 00000B08 ".[.PIRQ." */
- 0x0A,0x60,0x0A,0x04,0x10,0x2E,0x5C,0x00, /* 00000B10 ".`....\." */
- 0x5B,0x81,0x29,0x5C,0x2F,0x04,0x5F,0x53, /* 00000B18 "[.)\/._S" */
- 0x42,0x5F,0x50,0x43,0x49,0x30,0x49,0x53, /* 00000B20 "B_PCI0IS" */
- 0x41,0x5F,0x50,0x49,0x52,0x51,0x01,0x50, /* 00000B28 "A_PIRQ.P" */
- 0x49,0x52,0x41,0x08,0x50,0x49,0x52,0x42, /* 00000B30 "IRA.PIRB" */
- 0x08,0x50,0x49,0x52,0x43,0x08,0x50,0x49, /* 00000B38 ".PIRC.PI" */
- 0x52,0x44,0x08,0x5B,0x82,0x46,0x0B,0x53, /* 00000B40 "RD.[.F.S" */
- 0x59,0x53,0x52,0x08,0x5F,0x48,0x49,0x44, /* 00000B48 "YSR._HID" */
- 0x0C,0x41,0xD0,0x0C,0x02,0x08,0x5F,0x55, /* 00000B50 ".A...._U" */
- 0x49,0x44,0x01,0x08,0x43,0x52,0x53,0x5F, /* 00000B58 "ID..CRS_" */
- 0x11,0x4E,0x08,0x0A,0x8A,0x47,0x01,0x10, /* 00000B60 ".N...G.." */
- 0x00,0x10,0x00,0x00,0x10,0x47,0x01,0x22, /* 00000B68 ".....G."" */
- 0x00,0x22,0x00,0x00,0x0C,0x47,0x01,0x30, /* 00000B70 "."...G.0" */
- 0x00,0x30,0x00,0x00,0x10,0x47,0x01,0x44, /* 00000B78 ".0...G.D" */
- 0x00,0x44,0x00,0x00,0x1C,0x47,0x01,0x62, /* 00000B80 ".D...G.b" */
- 0x00,0x62,0x00,0x00,0x02,0x47,0x01,0x65, /* 00000B88 ".b...G.e" */
- 0x00,0x65,0x00,0x00,0x0B,0x47,0x01,0x72, /* 00000B90 ".e...G.r" */
- 0x00,0x72,0x00,0x00,0x0E,0x47,0x01,0x80, /* 00000B98 ".r...G.." */
- 0x00,0x80,0x00,0x00,0x01,0x47,0x01,0x84, /* 00000BA0 ".....G.." */
- 0x00,0x84,0x00,0x00,0x03,0x47,0x01,0x88, /* 00000BA8 ".....G.." */
- 0x00,0x88,0x00,0x00,0x01,0x47,0x01,0x8C, /* 00000BB0 ".....G.." */
- 0x00,0x8C,0x00,0x00,0x03,0x47,0x01,0x90, /* 00000BB8 ".....G.." */
- 0x00,0x90,0x00,0x00,0x10,0x47,0x01,0xA2, /* 00000BC0 ".....G.." */
- 0x00,0xA2,0x00,0x00,0x1C,0x47,0x01,0xE0, /* 00000BC8 ".....G.." */
- 0x00,0xE0,0x00,0x00,0x10,0x47,0x01,0xA0, /* 00000BD0 ".....G.." */
- 0x08,0xA0,0x08,0x00,0x04,0x47,0x01,0xC0, /* 00000BD8 ".....G.." */
- 0x0C,0xC0,0x0C,0x00,0x10,0x47,0x01,0xD0, /* 00000BE0 ".....G.." */
- 0x04,0xD0,0x04,0x00,0x02,0x79,0x00,0x14, /* 00000BE8 ".....y.." */
- 0x0B,0x5F,0x43,0x52,0x53,0x00,0xA4,0x43, /* 00000BF0 "._CRS..C" */
- 0x52,0x53,0x5F,0x5B,0x82,0x2B,0x50,0x49, /* 00000BF8 "RS_[.+PI" */
- 0x43,0x5F,0x08,0x5F,0x48,0x49,0x44,0x0B, /* 00000C00 "C_._HID." */
- 0x41,0xD0,0x08,0x5F,0x43,0x52,0x53,0x11, /* 00000C08 "A.._CRS." */
- 0x18,0x0A,0x15,0x47,0x01,0x20,0x00,0x20, /* 00000C10 "...G. . " */
- 0x00,0x01,0x02,0x47,0x01,0xA0,0x00,0xA0, /* 00000C18 "...G...." */
- 0x00,0x01,0x02,0x22,0x04,0x00,0x79,0x00, /* 00000C20 "..."..y." */
- 0x5B,0x82,0x47,0x05,0x44,0x4D,0x41,0x30, /* 00000C28 "[.G.DMA0" */
- 0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 00000C30 "._HID.A." */
- 0x02,0x00,0x08,0x5F,0x43,0x52,0x53,0x11, /* 00000C38 "..._CRS." */
- 0x41,0x04,0x0A,0x3D,0x2A,0x10,0x04,0x47, /* 00000C40 "A..=*..G" */
- 0x01,0x00,0x00,0x00,0x00,0x00,0x10,0x47, /* 00000C48 ".......G" */
- 0x01,0x81,0x00,0x81,0x00,0x00,0x03,0x47, /* 00000C50 ".......G" */
- 0x01,0x87,0x00,0x87,0x00,0x00,0x01,0x47, /* 00000C58 ".......G" */
- 0x01,0x89,0x00,0x89,0x00,0x00,0x03,0x47, /* 00000C60 ".......G" */
- 0x01,0x8F,0x00,0x8F,0x00,0x00,0x01,0x47, /* 00000C68 ".......G" */
- 0x01,0xC0,0x00,0xC0,0x00,0x00,0x20,0x47, /* 00000C70 "...... G" */
- 0x01,0x80,0x04,0x80,0x04,0x00,0x10,0x79, /* 00000C78 ".......y" */
- 0x00,0x5B,0x82,0x25,0x54,0x4D,0x52,0x5F, /* 00000C80 ".[.%TMR_" */
- 0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 00000C88 "._HID.A." */
- 0x01,0x00,0x08,0x5F,0x43,0x52,0x53,0x11, /* 00000C90 "..._CRS." */
- 0x10,0x0A,0x0D,0x47,0x01,0x40,0x00,0x40, /* 00000C98 "...G.@.@" */
- 0x00,0x00,0x04,0x22,0x01,0x00,0x79,0x00, /* 00000CA0 "..."..y." */
- 0x5B,0x82,0x25,0x52,0x54,0x43,0x5F,0x08, /* 00000CA8 "[.%RTC_." */
- 0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,0x0B, /* 00000CB0 "_HID.A.." */
- 0x00,0x08,0x5F,0x43,0x52,0x53,0x11,0x10, /* 00000CB8 ".._CRS.." */
- 0x0A,0x0D,0x47,0x01,0x70,0x00,0x70,0x00, /* 00000CC0 "..G.p.p." */
- 0x00,0x02,0x22,0x00,0x01,0x79,0x00,0x5B, /* 00000CC8 ".."..y.[" */
- 0x82,0x22,0x53,0x50,0x4B,0x52,0x08,0x5F, /* 00000CD0 "."SPKR._" */
- 0x48,0x49,0x44,0x0C,0x41,0xD0,0x08,0x00, /* 00000CD8 "HID.A..." */
- 0x08,0x5F,0x43,0x52,0x53,0x11,0x0D,0x0A, /* 00000CE0 "._CRS..." */
- 0x0A,0x47,0x01,0x61,0x00,0x61,0x00,0x00, /* 00000CE8 ".G.a.a.." */
- 0x01,0x79,0x00,0x5B,0x82,0x31,0x50,0x53, /* 00000CF0 ".y.[.1PS" */
- 0x32,0x4D,0x08,0x5F,0x48,0x49,0x44,0x0C, /* 00000CF8 "2M._HID." */
- 0x41,0xD0,0x0F,0x13,0x08,0x5F,0x43,0x49, /* 00000D00 "A...._CI" */
- 0x44,0x0C,0x41,0xD0,0x0F,0x13,0x14,0x09, /* 00000D08 "D.A....." */
- 0x5F,0x53,0x54,0x41,0x00,0xA4,0x0A,0x0F, /* 00000D10 "_STA...." */
- 0x08,0x5F,0x43,0x52,0x53,0x11,0x08,0x0A, /* 00000D18 "._CRS..." */
- 0x05,0x22,0x00,0x10,0x79,0x00,0x5B,0x82, /* 00000D20 "."..y.[." */
- 0x42,0x04,0x50,0x53,0x32,0x4B,0x08,0x5F, /* 00000D28 "B.PS2K._" */
- 0x48,0x49,0x44,0x0C,0x41,0xD0,0x03,0x03, /* 00000D30 "HID.A..." */
- 0x08,0x5F,0x43,0x49,0x44,0x0C,0x41,0xD0, /* 00000D38 "._CID.A." */
- 0x03,0x0B,0x14,0x09,0x5F,0x53,0x54,0x41, /* 00000D40 "...._STA" */
- 0x00,0xA4,0x0A,0x0F,0x08,0x5F,0x43,0x52, /* 00000D48 "....._CR" */
- 0x53,0x11,0x18,0x0A,0x15,0x47,0x01,0x60, /* 00000D50 "S....G.`" */
- 0x00,0x60,0x00,0x00,0x01,0x47,0x01,0x64, /* 00000D58 ".`...G.d" */
- 0x00,0x64,0x00,0x00,0x01,0x22,0x02,0x00, /* 00000D60 ".d...".." */
- 0x79,0x00,0x5B,0x82,0x3A,0x46,0x44,0x43, /* 00000D68 "y.[.:FDC" */
- 0x30,0x08,0x5F,0x48,0x49,0x44,0x0C,0x41, /* 00000D70 "0._HID.A" */
- 0xD0,0x07,0x00,0x14,0x09,0x5F,0x53,0x54, /* 00000D78 "....._ST" */
- 0x41,0x00,0xA4,0x0A,0x0F,0x08,0x5F,0x43, /* 00000D80 "A....._C" */
- 0x52,0x53,0x11,0x1B,0x0A,0x18,0x47,0x01, /* 00000D88 "RS....G." */
- 0xF0,0x03,0xF0,0x03,0x01,0x06,0x47,0x01, /* 00000D90 "......G." */
- 0xF7,0x03,0xF7,0x03,0x01,0x01,0x22,0x40, /* 00000D98 "......"@" */
- 0x00,0x2A,0x04,0x00,0x79,0x00,0x5B,0x82, /* 00000DA0 ".*..y.[." */
- 0x46,0x04,0x55,0x41,0x52,0x31,0x08,0x5F, /* 00000DA8 "F.UAR1._" */
- 0x48,0x49,0x44,0x0C,0x41,0xD0,0x05,0x01, /* 00000DB0 "HID.A..." */
- 0x08,0x5F,0x55,0x49,0x44,0x01,0x14,0x19, /* 00000DB8 "._UID..." */
- 0x5F,0x53,0x54,0x41,0x00,0xA0,0x0D,0x93, /* 00000DC0 "_STA...." */
- 0x5E,0x5E,0x5E,0x5E,0x55,0x41,0x52,0x31, /* 00000DC8 "^^^^UAR1" */
- 0x00,0xA4,0x00,0xA1,0x04,0xA4,0x0A,0x0F, /* 00000DD0 "........" */
- 0x08,0x5F,0x43,0x52,0x53,0x11,0x10,0x0A, /* 00000DD8 "._CRS..." */
- 0x0D,0x47,0x01,0xF8,0x03,0xF8,0x03,0x08, /* 00000DE0 ".G......" */
- 0x08,0x22,0x10,0x00,0x79,0x00,0x5B,0x82, /* 00000DE8 "."..y.[." */
- 0x47,0x04,0x55,0x41,0x52,0x32,0x08,0x5F, /* 00000DF0 "G.UAR2._" */
- 0x48,0x49,0x44,0x0C,0x41,0xD0,0x05,0x01, /* 00000DF8 "HID.A..." */
- 0x08,0x5F,0x55,0x49,0x44,0x0A,0x02,0x14, /* 00000E00 "._UID..." */
- 0x19,0x5F,0x53,0x54,0x41,0x00,0xA0,0x0D, /* 00000E08 "._STA..." */
- 0x93,0x5E,0x5E,0x5E,0x5E,0x55,0x41,0x52, /* 00000E10 ".^^^^UAR" */
- 0x32,0x00,0xA4,0x00,0xA1,0x04,0xA4,0x0A, /* 00000E18 "2......." */
- 0x0F,0x08,0x5F,0x43,0x52,0x53,0x11,0x10, /* 00000E20 ".._CRS.." */
- 0x0A,0x0D,0x47,0x01,0xF8,0x02,0xF8,0x02, /* 00000E28 "..G....." */
- 0x08,0x08,0x22,0x08,0x00,0x79,0x00,0x5B, /* 00000E30 ".."..y.[" */
- 0x82,0x36,0x4C,0x54,0x50,0x31,0x08,0x5F, /* 00000E38 ".6LTP1._" */
- 0x48,0x49,0x44,0x0C,0x41,0xD0,0x04,0x00, /* 00000E40 "HID.A..." */
- 0x08,0x5F,0x55,0x49,0x44,0x0A,0x02,0x14, /* 00000E48 "._UID..." */
- 0x09,0x5F,0x53,0x54,0x41,0x00,0xA4,0x0A, /* 00000E50 "._STA..." */
- 0x0F,0x08,0x5F,0x43,0x52,0x53,0x11,0x10, /* 00000E58 ".._CRS.." */
- 0x0A,0x0D,0x47,0x01,0x78,0x03,0x78,0x03, /* 00000E60 "..G.x.x." */
- 0x08,0x08,0x22,0x80,0x00,0x79,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x00, /* 000000F0 "........" */
+ 0x00,0x00,0x00,0x79,0x00,0x5B,0x82,0x4F, /* 000000F8 "...y.[.O" */
+ 0xD8,0x50,0x43,0x49,0x30,0x08,0x5F,0x48, /* 00000100 ".PCI0._H" */
+ 0x49,0x44,0x0C,0x41,0xD0,0x0A,0x03,0x08, /* 00000108 "ID.A...." */
+ 0x5F,0x55,0x49,0x44,0x00,0x08,0x5F,0x41, /* 00000110 "_UID.._A" */
+ 0x44,0x52,0x00,0x08,0x5F,0x42,0x42,0x4E, /* 00000118 "DR.._BBN" */
+ 0x00,0x14,0x4E,0x0C,0x5F,0x43,0x52,0x53, /* 00000120 "..N._CRS" */
+ 0x00,0x08,0x50,0x52,0x54,0x30,0x11,0x42, /* 00000128 "..PRT0.B" */
+ 0x07,0x0A,0x6E,0x88,0x0D,0x00,0x02,0x0E, /* 00000130 "..n....." */
+ 0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00, /* 00000138 "........" */
+ 0x00,0x00,0x01,0x47,0x01,0xF8,0x0C,0xF8, /* 00000140 "...G...." */
+ 0x0C,0x01,0x08,0x88,0x0D,0x00,0x01,0x0C, /* 00000148 "........" */
+ 0x03,0x00,0x00,0x00,0x00,0xF7,0x0C,0x00, /* 00000150 "........" */
+ 0x00,0xF8,0x0C,0x88,0x0D,0x00,0x01,0x0C, /* 00000158 "........" */
+ 0x03,0x00,0x00,0x00,0x0D,0xFF,0xFF,0x00, /* 00000160 "........" */
+ 0x00,0x00,0xF3,0x87,0x17,0x00,0x00,0x0C, /* 00000168 "........" */
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x0A, /* 00000170 "........" */
+ 0x00,0xFF,0xFF,0x0B,0x00,0x00,0x00,0x00, /* 00000178 "........" */
+ 0x00,0x00,0x00,0x02,0x00,0x87,0x17,0x00, /* 00000180 "........" */
+ 0x00,0x0C,0x03,0x00,0x00,0x00,0x00,0x00, /* 00000188 "........" */
+ 0x00,0x00,0xF0,0xFF,0xFF,0xFF,0xF4,0x00, /* 00000190 "........" */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x79, /* 00000198 ".......y" */
+ 0x00,0x8A,0x50,0x52,0x54,0x30,0x0A,0x5C, /* 000001A0 "..PRT0.\" */
+ 0x4D,0x4D,0x49,0x4E,0x8A,0x50,0x52,0x54, /* 000001A8 "MMIN.PRT" */
+ 0x30,0x0A,0x60,0x4D,0x4D,0x41,0x58,0x8A, /* 000001B0 "0.`MMAX." */
+ 0x50,0x52,0x54,0x30,0x0A,0x68,0x4D,0x4C, /* 000001B8 "PRT0.hML" */
+ 0x45,0x4E,0x70,0x50,0x4D,0x49,0x4E,0x4D, /* 000001C0 "ENpPMINM" */
+ 0x4D,0x49,0x4E,0x70,0x50,0x4C,0x45,0x4E, /* 000001C8 "MINpPLEN" */
+ 0x4D,0x4C,0x45,0x4E,0x72,0x4D,0x4D,0x49, /* 000001D0 "MLENrMMI" */
+ 0x4E,0x4D,0x4C,0x45,0x4E,0x4D,0x4D,0x41, /* 000001D8 "NMLENMMA" */
+ 0x58,0x74,0x4D,0x4D,0x41,0x58,0x01,0x4D, /* 000001E0 "XtMMAX.M" */
+ 0x4D,0x41,0x58,0xA4,0x50,0x52,0x54,0x30, /* 000001E8 "MAX.PRT0" */
+ 0x08,0x42,0x55,0x46,0x41,0x11,0x09,0x0A, /* 000001F0 ".BUFA..." */
+ 0x06,0x23,0x20,0x0C,0x18,0x79,0x00,0x08, /* 000001F8 ".# ..y.." */
+ 0x42,0x55,0x46,0x42,0x11,0x09,0x0A,0x06, /* 00000200 "BUFB...." */
+ 0x23,0x00,0x00,0x18,0x79,0x00,0x8B,0x42, /* 00000208 "#...y..B" */
+ 0x55,0x46,0x42,0x01,0x49,0x52,0x51,0x56, /* 00000210 "UFB.IRQV" */
+ 0x5B,0x82,0x48,0x08,0x4C,0x4E,0x4B,0x41, /* 00000218 "[.H.LNKA" */
+ 0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 00000220 "._HID.A." */
+ 0x0C,0x0F,0x08,0x5F,0x55,0x49,0x44,0x01, /* 00000228 "..._UID." */
+ 0x14,0x1C,0x5F,0x53,0x54,0x41,0x00,0x7B, /* 00000230 ".._STA.{" */
+ 0x50,0x49,0x52,0x41,0x0A,0x80,0x60,0xA0, /* 00000238 "PIRA..`." */
+ 0x08,0x93,0x60,0x0A,0x80,0xA4,0x0A,0x09, /* 00000240 "..`....." */
+ 0xA1,0x04,0xA4,0x0A,0x0B,0x14,0x0B,0x5F, /* 00000248 "......._" */
+ 0x50,0x52,0x53,0x00,0xA4,0x42,0x55,0x46, /* 00000250 "PRS..BUF" */
+ 0x41,0x14,0x11,0x5F,0x44,0x49,0x53,0x00, /* 00000258 "A.._DIS." */
+ 0x7D,0x50,0x49,0x52,0x41,0x0A,0x80,0x50, /* 00000260 "}PIRA..P" */
+ 0x49,0x52,0x41,0x14,0x1A,0x5F,0x43,0x52, /* 00000268 "IRA.._CR" */
+ 0x53,0x00,0x7B,0x50,0x49,0x52,0x41,0x0A, /* 00000270 "S.{PIRA." */
+ 0x0F,0x60,0x79,0x01,0x60,0x49,0x52,0x51, /* 00000278 ".`y.`IRQ" */
+ 0x56,0xA4,0x42,0x55,0x46,0x42,0x14,0x1B, /* 00000280 "V.BUFB.." */
+ 0x5F,0x53,0x52,0x53,0x01,0x8B,0x68,0x01, /* 00000288 "_SRS..h." */
+ 0x49,0x52,0x51,0x31,0x82,0x49,0x52,0x51, /* 00000290 "IRQ1.IRQ" */
+ 0x31,0x60,0x76,0x60,0x70,0x60,0x50,0x49, /* 00000298 "1`v`p`PI" */
+ 0x52,0x41,0x5B,0x82,0x49,0x08,0x4C,0x4E, /* 000002A0 "RA[.I.LN" */
+ 0x4B,0x42,0x08,0x5F,0x48,0x49,0x44,0x0C, /* 000002A8 "KB._HID." */
+ 0x41,0xD0,0x0C,0x0F,0x08,0x5F,0x55,0x49, /* 000002B0 "A...._UI" */
+ 0x44,0x0A,0x02,0x14,0x1C,0x5F,0x53,0x54, /* 000002B8 "D...._ST" */
+ 0x41,0x00,0x7B,0x50,0x49,0x52,0x42,0x0A, /* 000002C0 "A.{PIRB." */
+ 0x80,0x60,0xA0,0x08,0x93,0x60,0x0A,0x80, /* 000002C8 ".`...`.." */
+ 0xA4,0x0A,0x09,0xA1,0x04,0xA4,0x0A,0x0B, /* 000002D0 "........" */
+ 0x14,0x0B,0x5F,0x50,0x52,0x53,0x00,0xA4, /* 000002D8 ".._PRS.." */
+ 0x42,0x55,0x46,0x41,0x14,0x11,0x5F,0x44, /* 000002E0 "BUFA.._D" */
+ 0x49,0x53,0x00,0x7D,0x50,0x49,0x52,0x42, /* 000002E8 "IS.}PIRB" */
+ 0x0A,0x80,0x50,0x49,0x52,0x42,0x14,0x1A, /* 000002F0 "..PIRB.." */
+ 0x5F,0x43,0x52,0x53,0x00,0x7B,0x50,0x49, /* 000002F8 "_CRS.{PI" */
+ 0x52,0x42,0x0A,0x0F,0x60,0x79,0x01,0x60, /* 00000300 "RB..`y.`" */
+ 0x49,0x52,0x51,0x56,0xA4,0x42,0x55,0x46, /* 00000308 "IRQV.BUF" */
+ 0x42,0x14,0x1B,0x5F,0x53,0x52,0x53,0x01, /* 00000310 "B.._SRS." */
+ 0x8B,0x68,0x01,0x49,0x52,0x51,0x31,0x82, /* 00000318 ".h.IRQ1." */
+ 0x49,0x52,0x51,0x31,0x60,0x76,0x60,0x70, /* 00000320 "IRQ1`v`p" */
+ 0x60,0x50,0x49,0x52,0x42,0x5B,0x82,0x49, /* 00000328 "`PIRB[.I" */
+ 0x08,0x4C,0x4E,0x4B,0x43,0x08,0x5F,0x48, /* 00000330 ".LNKC._H" */
+ 0x49,0x44,0x0C,0x41,0xD0,0x0C,0x0F,0x08, /* 00000338 "ID.A...." */
+ 0x5F,0x55,0x49,0x44,0x0A,0x03,0x14,0x1C, /* 00000340 "_UID...." */
+ 0x5F,0x53,0x54,0x41,0x00,0x7B,0x50,0x49, /* 00000348 "_STA.{PI" */
+ 0x52,0x43,0x0A,0x80,0x60,0xA0,0x08,0x93, /* 00000350 "RC..`..." */
+ 0x60,0x0A,0x80,0xA4,0x0A,0x09,0xA1,0x04, /* 00000358 "`......." */
+ 0xA4,0x0A,0x0B,0x14,0x0B,0x5F,0x50,0x52, /* 00000360 "....._PR" */
+ 0x53,0x00,0xA4,0x42,0x55,0x46,0x41,0x14, /* 00000368 "S..BUFA." */
+ 0x11,0x5F,0x44,0x49,0x53,0x00,0x7D,0x50, /* 00000370 "._DIS.}P" */
+ 0x49,0x52,0x43,0x0A,0x80,0x50,0x49,0x52, /* 00000378 "IRC..PIR" */
+ 0x43,0x14,0x1A,0x5F,0x43,0x52,0x53,0x00, /* 00000380 "C.._CRS." */
+ 0x7B,0x50,0x49,0x52,0x43,0x0A,0x0F,0x60, /* 00000388 "{PIRC..`" */
+ 0x79,0x01,0x60,0x49,0x52,0x51,0x56,0xA4, /* 00000390 "y.`IRQV." */
+ 0x42,0x55,0x46,0x42,0x14,0x1B,0x5F,0x53, /* 00000398 "BUFB.._S" */
+ 0x52,0x53,0x01,0x8B,0x68,0x01,0x49,0x52, /* 000003A0 "RS..h.IR" */
+ 0x51,0x31,0x82,0x49,0x52,0x51,0x31,0x60, /* 000003A8 "Q1.IRQ1`" */
+ 0x76,0x60,0x70,0x60,0x50,0x49,0x52,0x43, /* 000003B0 "v`p`PIRC" */
+ 0x5B,0x82,0x49,0x08,0x4C,0x4E,0x4B,0x44, /* 000003B8 "[.I.LNKD" */
+ 0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 000003C0 "._HID.A." */
+ 0x0C,0x0F,0x08,0x5F,0x55,0x49,0x44,0x0A, /* 000003C8 "..._UID." */
+ 0x04,0x14,0x1C,0x5F,0x53,0x54,0x41,0x00, /* 000003D0 "..._STA." */
+ 0x7B,0x50,0x49,0x52,0x44,0x0A,0x80,0x60, /* 000003D8 "{PIRD..`" */
+ 0xA0,0x08,0x93,0x60,0x0A,0x80,0xA4,0x0A, /* 000003E0 "...`...." */
+ 0x09,0xA1,0x04,0xA4,0x0A,0x0B,0x14,0x0B, /* 000003E8 "........" */
+ 0x5F,0x50,0x52,0x53,0x00,0xA4,0x42,0x55, /* 000003F0 "_PRS..BU" */
+ 0x46,0x41,0x14,0x11,0x5F,0x44,0x49,0x53, /* 000003F8 "FA.._DIS" */
+ 0x00,0x7D,0x50,0x49,0x52,0x44,0x0A,0x80, /* 00000400 ".}PIRD.." */
+ 0x50,0x49,0x52,0x44,0x14,0x1A,0x5F,0x43, /* 00000408 "PIRD.._C" */
+ 0x52,0x53,0x00,0x7B,0x50,0x49,0x52,0x44, /* 00000410 "RS.{PIRD" */
+ 0x0A,0x0F,0x60,0x79,0x01,0x60,0x49,0x52, /* 00000418 "..`y.`IR" */
+ 0x51,0x56,0xA4,0x42,0x55,0x46,0x42,0x14, /* 00000420 "QV.BUFB." */
+ 0x1B,0x5F,0x53,0x52,0x53,0x01,0x8B,0x68, /* 00000428 "._SRS..h" */
+ 0x01,0x49,0x52,0x51,0x31,0x82,0x49,0x52, /* 00000430 ".IRQ1.IR" */
+ 0x51,0x31,0x60,0x76,0x60,0x70,0x60,0x50, /* 00000438 "Q1`v`p`P" */
+ 0x49,0x52,0x44,0x5B,0x82,0x44,0x05,0x48, /* 00000440 "IRD[.D.H" */
+ 0x50,0x45,0x54,0x08,0x5F,0x48,0x49,0x44, /* 00000448 "PET._HID" */
+ 0x0C,0x41,0xD0,0x01,0x03,0x08,0x5F,0x55, /* 00000450 ".A...._U" */
+ 0x49,0x44,0x00,0x14,0x18,0x5F,0x53,0x54, /* 00000458 "ID..._ST" */
+ 0x41,0x00,0xA0,0x0C,0x93,0x5E,0x5E,0x5E, /* 00000460 "A....^^^" */
+ 0x48,0x50,0x45,0x54,0x00,0xA4,0x00,0xA1, /* 00000468 "HPET...." */
+ 0x04,0xA4,0x0A,0x0F,0x08,0x5F,0x43,0x52, /* 00000470 "....._CR" */
+ 0x53,0x11,0x1F,0x0A,0x1C,0x87,0x17,0x00, /* 00000478 "S......." */
+ 0x00,0x0D,0x01,0x00,0x00,0x00,0x00,0x00, /* 00000480 "........" */
+ 0x00,0xD0,0xFE,0xFF,0x03,0xD0,0xFE,0x00, /* 00000488 "........" */
+ 0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x79, /* 00000490 ".......y" */
+ 0x00,0x14,0x16,0x5F,0x50,0x52,0x54,0x00, /* 00000498 "..._PRT." */
+ 0xA0,0x0A,0x50,0x49,0x43,0x44,0xA4,0x50, /* 000004A0 "..PICD.P" */
+ 0x52,0x54,0x41,0xA4,0x50,0x52,0x54,0x50, /* 000004A8 "RTA.PRTP" */
+ 0x08,0x50,0x52,0x54,0x50,0x12,0x49,0x36, /* 000004B0 ".PRTP.I6" */
+ 0x3C,0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x01, /* 000004B8 "<......." */
+ 0x00,0x00,0x4C,0x4E,0x4B,0x42,0x00,0x12, /* 000004C0 "..LNKB.." */
+ 0x0D,0x04,0x0C,0xFF,0xFF,0x01,0x00,0x01, /* 000004C8 "........" */
+ 0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0E,0x04, /* 000004D0 "LNKC...." */
+ 0x0C,0xFF,0xFF,0x01,0x00,0x0A,0x02,0x4C, /* 000004D8 ".......L" */
+ 0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04,0x0C, /* 000004E0 "NKD....." */
+ 0xFF,0xFF,0x01,0x00,0x0A,0x03,0x4C,0x4E, /* 000004E8 "......LN" */
+ 0x4B,0x41,0x00,0x12,0x0D,0x04,0x0C,0xFF, /* 000004F0 "KA......" */
+ 0xFF,0x02,0x00,0x00,0x4C,0x4E,0x4B,0x43, /* 000004F8 "....LNKC" */
+ 0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x02, /* 00000500 "........" */
+ 0x00,0x01,0x4C,0x4E,0x4B,0x44,0x00,0x12, /* 00000508 "..LNKD.." */
+ 0x0E,0x04,0x0C,0xFF,0xFF,0x02,0x00,0x0A, /* 00000510 "........" */
+ 0x02,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0E, /* 00000518 ".LNKA..." */
+ 0x04,0x0C,0xFF,0xFF,0x02,0x00,0x0A,0x03, /* 00000520 "........" */
+ 0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0D,0x04, /* 00000528 "LNKB...." */
+ 0x0C,0xFF,0xFF,0x03,0x00,0x00,0x4C,0x4E, /* 00000530 "......LN" */
+ 0x4B,0x44,0x00,0x12,0x0D,0x04,0x0C,0xFF, /* 00000538 "KD......" */
+ 0xFF,0x03,0x00,0x01,0x4C,0x4E,0x4B,0x41, /* 00000540 "....LNKA" */
+ 0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x03, /* 00000548 "........" */
+ 0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x42,0x00, /* 00000550 "...LNKB." */
+ 0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x03,0x00, /* 00000558 "........" */
+ 0x0A,0x03,0x4C,0x4E,0x4B,0x43,0x00,0x12, /* 00000560 "..LNKC.." */
+ 0x0D,0x04,0x0C,0xFF,0xFF,0x04,0x00,0x00, /* 00000568 "........" */
+ 0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0D,0x04, /* 00000570 "LNKA...." */
+ 0x0C,0xFF,0xFF,0x04,0x00,0x01,0x4C,0x4E, /* 00000578 "......LN" */
+ 0x4B,0x42,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 00000580 "KB......" */
+ 0xFF,0x04,0x00,0x0A,0x02,0x4C,0x4E,0x4B, /* 00000588 ".....LNK" */
+ 0x43,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 00000590 "C......." */
+ 0x04,0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x44, /* 00000598 "....LNKD" */
+ 0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x05, /* 000005A0 "........" */
+ 0x00,0x00,0x4C,0x4E,0x4B,0x42,0x00,0x12, /* 000005A8 "..LNKB.." */
+ 0x0D,0x04,0x0C,0xFF,0xFF,0x05,0x00,0x01, /* 000005B0 "........" */
+ 0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0E,0x04, /* 000005B8 "LNKC...." */
+ 0x0C,0xFF,0xFF,0x05,0x00,0x0A,0x02,0x4C, /* 000005C0 ".......L" */
+ 0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04,0x0C, /* 000005C8 "NKD....." */
+ 0xFF,0xFF,0x05,0x00,0x0A,0x03,0x4C,0x4E, /* 000005D0 "......LN" */
+ 0x4B,0x41,0x00,0x12,0x0D,0x04,0x0C,0xFF, /* 000005D8 "KA......" */
+ 0xFF,0x06,0x00,0x00,0x4C,0x4E,0x4B,0x43, /* 000005E0 "....LNKC" */
+ 0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x06, /* 000005E8 "........" */
+ 0x00,0x01,0x4C,0x4E,0x4B,0x44,0x00,0x12, /* 000005F0 "..LNKD.." */
+ 0x0E,0x04,0x0C,0xFF,0xFF,0x06,0x00,0x0A, /* 000005F8 "........" */
+ 0x02,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0E, /* 00000600 ".LNKA..." */
+ 0x04,0x0C,0xFF,0xFF,0x06,0x00,0x0A,0x03, /* 00000608 "........" */
+ 0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0D,0x04, /* 00000610 "LNKB...." */
+ 0x0C,0xFF,0xFF,0x07,0x00,0x00,0x4C,0x4E, /* 00000618 "......LN" */
+ 0x4B,0x44,0x00,0x12,0x0D,0x04,0x0C,0xFF, /* 00000620 "KD......" */
+ 0xFF,0x07,0x00,0x01,0x4C,0x4E,0x4B,0x41, /* 00000628 "....LNKA" */
+ 0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x07, /* 00000630 "........" */
+ 0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x42,0x00, /* 00000638 "...LNKB." */
+ 0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x07,0x00, /* 00000640 "........" */
+ 0x0A,0x03,0x4C,0x4E,0x4B,0x43,0x00,0x12, /* 00000648 "..LNKC.." */
+ 0x0D,0x04,0x0C,0xFF,0xFF,0x08,0x00,0x00, /* 00000650 "........" */
+ 0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0D,0x04, /* 00000658 "LNKA...." */
+ 0x0C,0xFF,0xFF,0x08,0x00,0x01,0x4C,0x4E, /* 00000660 "......LN" */
+ 0x4B,0x42,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 00000668 "KB......" */
+ 0xFF,0x08,0x00,0x0A,0x02,0x4C,0x4E,0x4B, /* 00000670 ".....LNK" */
+ 0x43,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 00000678 "C......." */
+ 0x08,0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x44, /* 00000680 "....LNKD" */
+ 0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x09, /* 00000688 "........" */
+ 0x00,0x00,0x4C,0x4E,0x4B,0x42,0x00,0x12, /* 00000690 "..LNKB.." */
+ 0x0D,0x04,0x0C,0xFF,0xFF,0x09,0x00,0x01, /* 00000698 "........" */
+ 0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0E,0x04, /* 000006A0 "LNKC...." */
+ 0x0C,0xFF,0xFF,0x09,0x00,0x0A,0x02,0x4C, /* 000006A8 ".......L" */
+ 0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04,0x0C, /* 000006B0 "NKD....." */
+ 0xFF,0xFF,0x09,0x00,0x0A,0x03,0x4C,0x4E, /* 000006B8 "......LN" */
+ 0x4B,0x41,0x00,0x12,0x0D,0x04,0x0C,0xFF, /* 000006C0 "KA......" */
+ 0xFF,0x0A,0x00,0x00,0x4C,0x4E,0x4B,0x43, /* 000006C8 "....LNKC" */
+ 0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x0A, /* 000006D0 "........" */
+ 0x00,0x01,0x4C,0x4E,0x4B,0x44,0x00,0x12, /* 000006D8 "..LNKD.." */
+ 0x0E,0x04,0x0C,0xFF,0xFF,0x0A,0x00,0x0A, /* 000006E0 "........" */
+ 0x02,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0E, /* 000006E8 ".LNKA..." */
+ 0x04,0x0C,0xFF,0xFF,0x0A,0x00,0x0A,0x03, /* 000006F0 "........" */
+ 0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0D,0x04, /* 000006F8 "LNKB...." */
+ 0x0C,0xFF,0xFF,0x0B,0x00,0x00,0x4C,0x4E, /* 00000700 "......LN" */
+ 0x4B,0x44,0x00,0x12,0x0D,0x04,0x0C,0xFF, /* 00000708 "KD......" */
+ 0xFF,0x0B,0x00,0x01,0x4C,0x4E,0x4B,0x41, /* 00000710 "....LNKA" */
+ 0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x0B, /* 00000718 "........" */
+ 0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x42,0x00, /* 00000720 "...LNKB." */
+ 0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x0B,0x00, /* 00000728 "........" */
+ 0x0A,0x03,0x4C,0x4E,0x4B,0x43,0x00,0x12, /* 00000730 "..LNKC.." */
+ 0x0D,0x04,0x0C,0xFF,0xFF,0x0C,0x00,0x00, /* 00000738 "........" */
+ 0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0D,0x04, /* 00000740 "LNKA...." */
+ 0x0C,0xFF,0xFF,0x0C,0x00,0x01,0x4C,0x4E, /* 00000748 "......LN" */
+ 0x4B,0x42,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 00000750 "KB......" */
+ 0xFF,0x0C,0x00,0x0A,0x02,0x4C,0x4E,0x4B, /* 00000758 ".....LNK" */
+ 0x43,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 00000760 "C......." */
+ 0x0C,0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x44, /* 00000768 "....LNKD" */
+ 0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x0D, /* 00000770 "........" */
+ 0x00,0x00,0x4C,0x4E,0x4B,0x42,0x00,0x12, /* 00000778 "..LNKB.." */
+ 0x0D,0x04,0x0C,0xFF,0xFF,0x0D,0x00,0x01, /* 00000780 "........" */
+ 0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0E,0x04, /* 00000788 "LNKC...." */
+ 0x0C,0xFF,0xFF,0x0D,0x00,0x0A,0x02,0x4C, /* 00000790 ".......L" */
+ 0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04,0x0C, /* 00000798 "NKD....." */
+ 0xFF,0xFF,0x0D,0x00,0x0A,0x03,0x4C,0x4E, /* 000007A0 "......LN" */
+ 0x4B,0x41,0x00,0x12,0x0D,0x04,0x0C,0xFF, /* 000007A8 "KA......" */
+ 0xFF,0x0E,0x00,0x00,0x4C,0x4E,0x4B,0x43, /* 000007B0 "....LNKC" */
+ 0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x0E, /* 000007B8 "........" */
+ 0x00,0x01,0x4C,0x4E,0x4B,0x44,0x00,0x12, /* 000007C0 "..LNKD.." */
+ 0x0E,0x04,0x0C,0xFF,0xFF,0x0E,0x00,0x0A, /* 000007C8 "........" */
+ 0x02,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0E, /* 000007D0 ".LNKA..." */
+ 0x04,0x0C,0xFF,0xFF,0x0E,0x00,0x0A,0x03, /* 000007D8 "........" */
+ 0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0D,0x04, /* 000007E0 "LNKB...." */
+ 0x0C,0xFF,0xFF,0x0F,0x00,0x00,0x4C,0x4E, /* 000007E8 "......LN" */
+ 0x4B,0x44,0x00,0x12,0x0D,0x04,0x0C,0xFF, /* 000007F0 "KD......" */
+ 0xFF,0x0F,0x00,0x01,0x4C,0x4E,0x4B,0x41, /* 000007F8 "....LNKA" */
+ 0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x0F, /* 00000800 "........" */
+ 0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x42,0x00, /* 00000808 "...LNKB." */
+ 0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x0F,0x00, /* 00000810 "........" */
+ 0x0A,0x03,0x4C,0x4E,0x4B,0x43,0x00,0x08, /* 00000818 "..LNKC.." */
+ 0x50,0x52,0x54,0x41,0x12,0x41,0x2F,0x3C, /* 00000820 "PRTA.A/<" */
+ 0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x01,0x00, /* 00000828 "........" */
+ 0x00,0x00,0x0A,0x14,0x12,0x0B,0x04,0x0C, /* 00000830 "........" */
+ 0xFF,0xFF,0x01,0x00,0x01,0x00,0x0A,0x15, /* 00000838 "........" */
+ 0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x01,0x00, /* 00000840 "........" */
+ 0x0A,0x02,0x00,0x0A,0x16,0x12,0x0C,0x04, /* 00000848 "........" */
+ 0x0C,0xFF,0xFF,0x01,0x00,0x0A,0x03,0x00, /* 00000850 "........" */
+ 0x0A,0x17,0x12,0x0B,0x04,0x0C,0xFF,0xFF, /* 00000858 "........" */
+ 0x02,0x00,0x00,0x00,0x0A,0x18,0x12,0x0B, /* 00000860 "........" */
+ 0x04,0x0C,0xFF,0xFF,0x02,0x00,0x01,0x00, /* 00000868 "........" */
+ 0x0A,0x19,0x12,0x0C,0x04,0x0C,0xFF,0xFF, /* 00000870 "........" */
+ 0x02,0x00,0x0A,0x02,0x00,0x0A,0x1A,0x12, /* 00000878 "........" */
+ 0x0C,0x04,0x0C,0xFF,0xFF,0x02,0x00,0x0A, /* 00000880 "........" */
+ 0x03,0x00,0x0A,0x1B,0x12,0x0B,0x04,0x0C, /* 00000888 "........" */
+ 0xFF,0xFF,0x03,0x00,0x00,0x00,0x0A,0x1C, /* 00000890 "........" */
+ 0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x03,0x00, /* 00000898 "........" */
+ 0x01,0x00,0x0A,0x1D,0x12,0x0C,0x04,0x0C, /* 000008A0 "........" */
+ 0xFF,0xFF,0x03,0x00,0x0A,0x02,0x00,0x0A, /* 000008A8 "........" */
+ 0x1E,0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x03, /* 000008B0 "........" */
+ 0x00,0x0A,0x03,0x00,0x0A,0x1F,0x12,0x0B, /* 000008B8 "........" */
+ 0x04,0x0C,0xFF,0xFF,0x04,0x00,0x00,0x00, /* 000008C0 "........" */
+ 0x0A,0x20,0x12,0x0B,0x04,0x0C,0xFF,0xFF, /* 000008C8 ". ......" */
+ 0x04,0x00,0x01,0x00,0x0A,0x21,0x12,0x0C, /* 000008D0 ".....!.." */
+ 0x04,0x0C,0xFF,0xFF,0x04,0x00,0x0A,0x02, /* 000008D8 "........" */
+ 0x00,0x0A,0x22,0x12,0x0C,0x04,0x0C,0xFF, /* 000008E0 ".."....." */
+ 0xFF,0x04,0x00,0x0A,0x03,0x00,0x0A,0x23, /* 000008E8 ".......#" */
+ 0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x05,0x00, /* 000008F0 "........" */
+ 0x00,0x00,0x0A,0x24,0x12,0x0B,0x04,0x0C, /* 000008F8 "...$...." */
+ 0xFF,0xFF,0x05,0x00,0x01,0x00,0x0A,0x25, /* 00000900 ".......%" */
+ 0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x05,0x00, /* 00000908 "........" */
+ 0x0A,0x02,0x00,0x0A,0x26,0x12,0x0C,0x04, /* 00000910 "....&..." */
+ 0x0C,0xFF,0xFF,0x05,0x00,0x0A,0x03,0x00, /* 00000918 "........" */
+ 0x0A,0x27,0x12,0x0B,0x04,0x0C,0xFF,0xFF, /* 00000920 ".'......" */
+ 0x06,0x00,0x00,0x00,0x0A,0x28,0x12,0x0B, /* 00000928 ".....(.." */
+ 0x04,0x0C,0xFF,0xFF,0x06,0x00,0x01,0x00, /* 00000930 "........" */
+ 0x0A,0x29,0x12,0x0C,0x04,0x0C,0xFF,0xFF, /* 00000938 ".)......" */
+ 0x06,0x00,0x0A,0x02,0x00,0x0A,0x2A,0x12, /* 00000940 "......*." */
+ 0x0C,0x04,0x0C,0xFF,0xFF,0x06,0x00,0x0A, /* 00000948 "........" */
+ 0x03,0x00,0x0A,0x2B,0x12,0x0B,0x04,0x0C, /* 00000950 "...+...." */
+ 0xFF,0xFF,0x07,0x00,0x00,0x00,0x0A,0x2C, /* 00000958 ".......," */
+ 0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x07,0x00, /* 00000960 "........" */
+ 0x01,0x00,0x0A,0x2D,0x12,0x0C,0x04,0x0C, /* 00000968 "...-...." */
+ 0xFF,0xFF,0x07,0x00,0x0A,0x02,0x00,0x0A, /* 00000970 "........" */
+ 0x2E,0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x07, /* 00000978 "........" */
+ 0x00,0x0A,0x03,0x00,0x0A,0x2F,0x12,0x0B, /* 00000980 "...../.." */
+ 0x04,0x0C,0xFF,0xFF,0x08,0x00,0x00,0x00, /* 00000988 "........" */
+ 0x0A,0x11,0x12,0x0B,0x04,0x0C,0xFF,0xFF, /* 00000990 "........" */
+ 0x08,0x00,0x01,0x00,0x0A,0x12,0x12,0x0C, /* 00000998 "........" */
+ 0x04,0x0C,0xFF,0xFF,0x08,0x00,0x0A,0x02, /* 000009A0 "........" */
+ 0x00,0x0A,0x13,0x12,0x0C,0x04,0x0C,0xFF, /* 000009A8 "........" */
+ 0xFF,0x08,0x00,0x0A,0x03,0x00,0x0A,0x14, /* 000009B0 "........" */
+ 0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x09,0x00, /* 000009B8 "........" */
+ 0x00,0x00,0x0A,0x15,0x12,0x0B,0x04,0x0C, /* 000009C0 "........" */
+ 0xFF,0xFF,0x09,0x00,0x01,0x00,0x0A,0x16, /* 000009C8 "........" */
+ 0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x09,0x00, /* 000009D0 "........" */
+ 0x0A,0x02,0x00,0x0A,0x17,0x12,0x0C,0x04, /* 000009D8 "........" */
+ 0x0C,0xFF,0xFF,0x09,0x00,0x0A,0x03,0x00, /* 000009E0 "........" */
+ 0x0A,0x18,0x12,0x0B,0x04,0x0C,0xFF,0xFF, /* 000009E8 "........" */
+ 0x0A,0x00,0x00,0x00,0x0A,0x19,0x12,0x0B, /* 000009F0 "........" */
+ 0x04,0x0C,0xFF,0xFF,0x0A,0x00,0x01,0x00, /* 000009F8 "........" */
+ 0x0A,0x1A,0x12,0x0C,0x04,0x0C,0xFF,0xFF, /* 00000A00 "........" */
+ 0x0A,0x00,0x0A,0x02,0x00,0x0A,0x1B,0x12, /* 00000A08 "........" */
+ 0x0C,0x04,0x0C,0xFF,0xFF,0x0A,0x00,0x0A, /* 00000A10 "........" */
+ 0x03,0x00,0x0A,0x1C,0x12,0x0B,0x04,0x0C, /* 00000A18 "........" */
+ 0xFF,0xFF,0x0B,0x00,0x00,0x00,0x0A,0x1D, /* 00000A20 "........" */
+ 0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x0B,0x00, /* 00000A28 "........" */
+ 0x01,0x00,0x0A,0x1E,0x12,0x0C,0x04,0x0C, /* 00000A30 "........" */
+ 0xFF,0xFF,0x0B,0x00,0x0A,0x02,0x00,0x0A, /* 00000A38 "........" */
+ 0x1F,0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x0B, /* 00000A40 "........" */
+ 0x00,0x0A,0x03,0x00,0x0A,0x20,0x12,0x0B, /* 00000A48 "..... .." */
+ 0x04,0x0C,0xFF,0xFF,0x0C,0x00,0x00,0x00, /* 00000A50 "........" */
+ 0x0A,0x21,0x12,0x0B,0x04,0x0C,0xFF,0xFF, /* 00000A58 ".!......" */
+ 0x0C,0x00,0x01,0x00,0x0A,0x22,0x12,0x0C, /* 00000A60 ".....".." */
+ 0x04,0x0C,0xFF,0xFF,0x0C,0x00,0x0A,0x02, /* 00000A68 "........" */
+ 0x00,0x0A,0x23,0x12,0x0C,0x04,0x0C,0xFF, /* 00000A70 "..#....." */
+ 0xFF,0x0C,0x00,0x0A,0x03,0x00,0x0A,0x24, /* 00000A78 ".......$" */
+ 0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x0D,0x00, /* 00000A80 "........" */
+ 0x00,0x00,0x0A,0x25,0x12,0x0B,0x04,0x0C, /* 00000A88 "...%...." */
+ 0xFF,0xFF,0x0D,0x00,0x01,0x00,0x0A,0x26, /* 00000A90 ".......&" */
+ 0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x0D,0x00, /* 00000A98 "........" */
+ 0x0A,0x02,0x00,0x0A,0x27,0x12,0x0C,0x04, /* 00000AA0 "....'..." */
+ 0x0C,0xFF,0xFF,0x0D,0x00,0x0A,0x03,0x00, /* 00000AA8 "........" */
+ 0x0A,0x28,0x12,0x0B,0x04,0x0C,0xFF,0xFF, /* 00000AB0 ".(......" */
+ 0x0E,0x00,0x00,0x00,0x0A,0x29,0x12,0x0B, /* 00000AB8 ".....).." */
+ 0x04,0x0C,0xFF,0xFF,0x0E,0x00,0x01,0x00, /* 00000AC0 "........" */
+ 0x0A,0x2A,0x12,0x0C,0x04,0x0C,0xFF,0xFF, /* 00000AC8 ".*......" */
+ 0x0E,0x00,0x0A,0x02,0x00,0x0A,0x2B,0x12, /* 00000AD0 "......+." */
+ 0x0C,0x04,0x0C,0xFF,0xFF,0x0E,0x00,0x0A, /* 00000AD8 "........" */
+ 0x03,0x00,0x0A,0x2C,0x12,0x0B,0x04,0x0C, /* 00000AE0 "...,...." */
+ 0xFF,0xFF,0x0F,0x00,0x00,0x00,0x0A,0x2D, /* 00000AE8 ".......-" */
+ 0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x0F,0x00, /* 00000AF0 "........" */
+ 0x01,0x00,0x0A,0x2E,0x12,0x0C,0x04,0x0C, /* 00000AF8 "........" */
+ 0xFF,0xFF,0x0F,0x00,0x0A,0x02,0x00,0x0A, /* 00000B00 "........" */
+ 0x2F,0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x0F, /* 00000B08 "/......." */
+ 0x00,0x0A,0x03,0x00,0x0A,0x10,0x5B,0x82, /* 00000B10 "......[." */
+ 0x46,0x37,0x49,0x53,0x41,0x5F,0x08,0x5F, /* 00000B18 "F7ISA_._" */
+ 0x41,0x44,0x52,0x0C,0x00,0x00,0x01,0x00, /* 00000B20 "ADR....." */
+ 0x5B,0x80,0x50,0x49,0x52,0x51,0x02,0x0A, /* 00000B28 "[.PIRQ.." */
+ 0x60,0x0A,0x04,0x10,0x2E,0x5C,0x00,0x5B, /* 00000B30 "`....\.[" */
+ 0x81,0x29,0x5C,0x2F,0x04,0x5F,0x53,0x42, /* 00000B38 ".)\/._SB" */
+ 0x5F,0x50,0x43,0x49,0x30,0x49,0x53,0x41, /* 00000B40 "_PCI0ISA" */
+ 0x5F,0x50,0x49,0x52,0x51,0x01,0x50,0x49, /* 00000B48 "_PIRQ.PI" */
+ 0x52,0x41,0x08,0x50,0x49,0x52,0x42,0x08, /* 00000B50 "RA.PIRB." */
+ 0x50,0x49,0x52,0x43,0x08,0x50,0x49,0x52, /* 00000B58 "PIRC.PIR" */
+ 0x44,0x08,0x5B,0x82,0x46,0x0B,0x53,0x59, /* 00000B60 "D.[.F.SY" */
+ 0x53,0x52,0x08,0x5F,0x48,0x49,0x44,0x0C, /* 00000B68 "SR._HID." */
+ 0x41,0xD0,0x0C,0x02,0x08,0x5F,0x55,0x49, /* 00000B70 "A...._UI" */
+ 0x44,0x01,0x08,0x43,0x52,0x53,0x5F,0x11, /* 00000B78 "D..CRS_." */
+ 0x4E,0x08,0x0A,0x8A,0x47,0x01,0x10,0x00, /* 00000B80 "N...G..." */
+ 0x10,0x00,0x00,0x10,0x47,0x01,0x22,0x00, /* 00000B88 "....G."." */
+ 0x22,0x00,0x00,0x0C,0x47,0x01,0x30,0x00, /* 00000B90 ""...G.0." */
+ 0x30,0x00,0x00,0x10,0x47,0x01,0x44,0x00, /* 00000B98 "0...G.D." */
+ 0x44,0x00,0x00,0x1C,0x47,0x01,0x62,0x00, /* 00000BA0 "D...G.b." */
+ 0x62,0x00,0x00,0x02,0x47,0x01,0x65,0x00, /* 00000BA8 "b...G.e." */
+ 0x65,0x00,0x00,0x0B,0x47,0x01,0x72,0x00, /* 00000BB0 "e...G.r." */
+ 0x72,0x00,0x00,0x0E,0x47,0x01,0x80,0x00, /* 00000BB8 "r...G..." */
+ 0x80,0x00,0x00,0x01,0x47,0x01,0x84,0x00, /* 00000BC0 "....G..." */
+ 0x84,0x00,0x00,0x03,0x47,0x01,0x88,0x00, /* 00000BC8 "....G..." */
+ 0x88,0x00,0x00,0x01,0x47,0x01,0x8C,0x00, /* 00000BD0 "....G..." */
+ 0x8C,0x00,0x00,0x03,0x47,0x01,0x90,0x00, /* 00000BD8 "....G..." */
+ 0x90,0x00,0x00,0x10,0x47,0x01,0xA2,0x00, /* 00000BE0 "....G..." */
+ 0xA2,0x00,0x00,0x1C,0x47,0x01,0xE0,0x00, /* 00000BE8 "....G..." */
+ 0xE0,0x00,0x00,0x10,0x47,0x01,0xA0,0x08, /* 00000BF0 "....G..." */
+ 0xA0,0x08,0x00,0x04,0x47,0x01,0xC0,0x0C, /* 00000BF8 "....G..." */
+ 0xC0,0x0C,0x00,0x10,0x47,0x01,0xD0,0x04, /* 00000C00 "....G..." */
+ 0xD0,0x04,0x00,0x02,0x79,0x00,0x14,0x0B, /* 00000C08 "....y..." */
+ 0x5F,0x43,0x52,0x53,0x00,0xA4,0x43,0x52, /* 00000C10 "_CRS..CR" */
+ 0x53,0x5F,0x5B,0x82,0x2B,0x50,0x49,0x43, /* 00000C18 "S_[.+PIC" */
+ 0x5F,0x08,0x5F,0x48,0x49,0x44,0x0B,0x41, /* 00000C20 "_._HID.A" */
+ 0xD0,0x08,0x5F,0x43,0x52,0x53,0x11,0x18, /* 00000C28 ".._CRS.." */
+ 0x0A,0x15,0x47,0x01,0x20,0x00,0x20,0x00, /* 00000C30 "..G. . ." */
+ 0x01,0x02,0x47,0x01,0xA0,0x00,0xA0,0x00, /* 00000C38 "..G....." */
+ 0x01,0x02,0x22,0x04,0x00,0x79,0x00,0x5B, /* 00000C40 ".."..y.[" */
+ 0x82,0x47,0x05,0x44,0x4D,0x41,0x30,0x08, /* 00000C48 ".G.DMA0." */
+ 0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,0x02, /* 00000C50 "_HID.A.." */
+ 0x00,0x08,0x5F,0x43,0x52,0x53,0x11,0x41, /* 00000C58 ".._CRS.A" */
+ 0x04,0x0A,0x3D,0x2A,0x10,0x04,0x47,0x01, /* 00000C60 "..=*..G." */
+ 0x00,0x00,0x00,0x00,0x00,0x10,0x47,0x01, /* 00000C68 "......G." */
+ 0x81,0x00,0x81,0x00,0x00,0x03,0x47,0x01, /* 00000C70 "......G." */
+ 0x87,0x00,0x87,0x00,0x00,0x01,0x47,0x01, /* 00000C78 "......G." */
+ 0x89,0x00,0x89,0x00,0x00,0x03,0x47,0x01, /* 00000C80 "......G." */
+ 0x8F,0x00,0x8F,0x00,0x00,0x01,0x47,0x01, /* 00000C88 "......G." */
+ 0xC0,0x00,0xC0,0x00,0x00,0x20,0x47,0x01, /* 00000C90 "..... G." */
+ 0x80,0x04,0x80,0x04,0x00,0x10,0x79,0x00, /* 00000C98 "......y." */
+ 0x5B,0x82,0x25,0x54,0x4D,0x52,0x5F,0x08, /* 00000CA0 "[.%TMR_." */
+ 0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,0x01, /* 00000CA8 "_HID.A.." */
+ 0x00,0x08,0x5F,0x43,0x52,0x53,0x11,0x10, /* 00000CB0 ".._CRS.." */
+ 0x0A,0x0D,0x47,0x01,0x40,0x00,0x40,0x00, /* 00000CB8 "..G.@.@." */
+ 0x00,0x04,0x22,0x01,0x00,0x79,0x00,0x5B, /* 00000CC0 ".."..y.[" */
+ 0x82,0x25,0x52,0x54,0x43,0x5F,0x08,0x5F, /* 00000CC8 ".%RTC_._" */
+ 0x48,0x49,0x44,0x0C,0x41,0xD0,0x0B,0x00, /* 00000CD0 "HID.A..." */
+ 0x08,0x5F,0x43,0x52,0x53,0x11,0x10,0x0A, /* 00000CD8 "._CRS..." */
+ 0x0D,0x47,0x01,0x70,0x00,0x70,0x00,0x00, /* 00000CE0 ".G.p.p.." */
+ 0x02,0x22,0x00,0x01,0x79,0x00,0x5B,0x82, /* 00000CE8 "."..y.[." */
+ 0x22,0x53,0x50,0x4B,0x52,0x08,0x5F,0x48, /* 00000CF0 ""SPKR._H" */
+ 0x49,0x44,0x0C,0x41,0xD0,0x08,0x00,0x08, /* 00000CF8 "ID.A...." */
+ 0x5F,0x43,0x52,0x53,0x11,0x0D,0x0A,0x0A, /* 00000D00 "_CRS...." */
+ 0x47,0x01,0x61,0x00,0x61,0x00,0x00,0x01, /* 00000D08 "G.a.a..." */
+ 0x79,0x00,0x5B,0x82,0x31,0x50,0x53,0x32, /* 00000D10 "y.[.1PS2" */
+ 0x4D,0x08,0x5F,0x48,0x49,0x44,0x0C,0x41, /* 00000D18 "M._HID.A" */
+ 0xD0,0x0F,0x13,0x08,0x5F,0x43,0x49,0x44, /* 00000D20 "...._CID" */
+ 0x0C,0x41,0xD0,0x0F,0x13,0x14,0x09,0x5F, /* 00000D28 ".A....._" */
+ 0x53,0x54,0x41,0x00,0xA4,0x0A,0x0F,0x08, /* 00000D30 "STA....." */
+ 0x5F,0x43,0x52,0x53,0x11,0x08,0x0A,0x05, /* 00000D38 "_CRS...." */
+ 0x22,0x00,0x10,0x79,0x00,0x5B,0x82,0x42, /* 00000D40 ""..y.[.B" */
+ 0x04,0x50,0x53,0x32,0x4B,0x08,0x5F,0x48, /* 00000D48 ".PS2K._H" */
+ 0x49,0x44,0x0C,0x41,0xD0,0x03,0x03,0x08, /* 00000D50 "ID.A...." */
+ 0x5F,0x43,0x49,0x44,0x0C,0x41,0xD0,0x03, /* 00000D58 "_CID.A.." */
+ 0x0B,0x14,0x09,0x5F,0x53,0x54,0x41,0x00, /* 00000D60 "..._STA." */
+ 0xA4,0x0A,0x0F,0x08,0x5F,0x43,0x52,0x53, /* 00000D68 "...._CRS" */
+ 0x11,0x18,0x0A,0x15,0x47,0x01,0x60,0x00, /* 00000D70 "....G.`." */
+ 0x60,0x00,0x00,0x01,0x47,0x01,0x64,0x00, /* 00000D78 "`...G.d." */
+ 0x64,0x00,0x00,0x01,0x22,0x02,0x00,0x79, /* 00000D80 "d..."..y" */
+ 0x00,0x5B,0x82,0x3A,0x46,0x44,0x43,0x30, /* 00000D88 ".[.:FDC0" */
+ 0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 00000D90 "._HID.A." */
+ 0x07,0x00,0x14,0x09,0x5F,0x53,0x54,0x41, /* 00000D98 "...._STA" */
+ 0x00,0xA4,0x0A,0x0F,0x08,0x5F,0x43,0x52, /* 00000DA0 "....._CR" */
+ 0x53,0x11,0x1B,0x0A,0x18,0x47,0x01,0xF0, /* 00000DA8 "S....G.." */
+ 0x03,0xF0,0x03,0x01,0x06,0x47,0x01,0xF7, /* 00000DB0 ".....G.." */
+ 0x03,0xF7,0x03,0x01,0x01,0x22,0x40,0x00, /* 00000DB8 "....."@." */
+ 0x2A,0x04,0x00,0x79,0x00,0x5B,0x82,0x46, /* 00000DC0 "*..y.[.F" */
+ 0x04,0x55,0x41,0x52,0x31,0x08,0x5F,0x48, /* 00000DC8 ".UAR1._H" */
+ 0x49,0x44,0x0C,0x41,0xD0,0x05,0x01,0x08, /* 00000DD0 "ID.A...." */
+ 0x5F,0x55,0x49,0x44,0x01,0x14,0x19,0x5F, /* 00000DD8 "_UID..._" */
+ 0x53,0x54,0x41,0x00,0xA0,0x0D,0x93,0x5E, /* 00000DE0 "STA....^" */
+ 0x5E,0x5E,0x5E,0x55,0x41,0x52,0x31,0x00, /* 00000DE8 "^^^UAR1." */
+ 0xA4,0x00,0xA1,0x04,0xA4,0x0A,0x0F,0x08, /* 00000DF0 "........" */
+ 0x5F,0x43,0x52,0x53,0x11,0x10,0x0A,0x0D, /* 00000DF8 "_CRS...." */
+ 0x47,0x01,0xF8,0x03,0xF8,0x03,0x08,0x08, /* 00000E00 "G......." */
+ 0x22,0x10,0x00,0x79,0x00,0x5B,0x82,0x47, /* 00000E08 ""..y.[.G" */
+ 0x04,0x55,0x41,0x52,0x32,0x08,0x5F,0x48, /* 00000E10 ".UAR2._H" */
+ 0x49,0x44,0x0C,0x41,0xD0,0x05,0x01,0x08, /* 00000E18 "ID.A...." */
+ 0x5F,0x55,0x49,0x44,0x0A,0x02,0x14,0x19, /* 00000E20 "_UID...." */
+ 0x5F,0x53,0x54,0x41,0x00,0xA0,0x0D,0x93, /* 00000E28 "_STA...." */
+ 0x5E,0x5E,0x5E,0x5E,0x55,0x41,0x52,0x32, /* 00000E30 "^^^^UAR2" */
+ 0x00,0xA4,0x00,0xA1,0x04,0xA4,0x0A,0x0F, /* 00000E38 "........" */
+ 0x08,0x5F,0x43,0x52,0x53,0x11,0x10,0x0A, /* 00000E40 "._CRS..." */
+ 0x0D,0x47,0x01,0xF8,0x02,0xF8,0x02,0x08, /* 00000E48 ".G......" */
+ 0x08,0x22,0x08,0x00,0x79,0x00,0x5B,0x82, /* 00000E50 "."..y.[." */
+ 0x36,0x4C,0x54,0x50,0x31,0x08,0x5F,0x48, /* 00000E58 "6LTP1._H" */
+ 0x49,0x44,0x0C,0x41,0xD0,0x04,0x00,0x08, /* 00000E60 "ID.A...." */
+ 0x5F,0x55,0x49,0x44,0x0A,0x02,0x14,0x09, /* 00000E68 "_UID...." */
+ 0x5F,0x53,0x54,0x41,0x00,0xA4,0x0A,0x0F, /* 00000E70 "_STA...." */
+ 0x08,0x5F,0x43,0x52,0x53,0x11,0x10,0x0A, /* 00000E78 "._CRS..." */
+ 0x0D,0x47,0x01,0x78,0x03,0x78,0x03,0x08, /* 00000E80 ".G.x.x.." */
+ 0x08,0x22,0x80,0x00,0x79,0x00,
};
int DsdtLen=sizeof(AmlCode);
diff --git a/tools/fs-back/fs-backend.c b/tools/fs-back/fs-backend.c
index 634d5fa31e..fd5ba2b46b 100644
--- a/tools/fs-back/fs-backend.c
+++ b/tools/fs-back/fs-backend.c
@@ -140,8 +140,8 @@ void* handle_mount(void *data)
handle_aio_events(mount);
moretodo:
rp = mount->ring.sring->req_prod;
- rmb(); /* Ensure we see queued requests up to 'rp'. */
-
+ xen_rmb(); /* Ensure we see queued requests up to 'rp'. */
+
while ((cons = mount->ring.req_cons) != rp)
{
int i;
diff --git a/tools/ioemu/Makefile.target b/tools/ioemu/Makefile.target
index ebd691b5f0..965d726adf 100644
--- a/tools/ioemu/Makefile.target
+++ b/tools/ioemu/Makefile.target
@@ -15,7 +15,7 @@ TARGET_BASE_ARCH:=sparc
endif
TARGET_PATH=$(SRC_PATH)/target-$(TARGET_BASE_ARCH)$(TARGET_SUB)
VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw:$(SRC_PATH)/audio
-CPPFLAGS=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH)
+CPPFLAGS+=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH)
CPPFLAGS+= -I$(XEN_ROOT)/tools/libxc
CPPFLAGS+= -I$(XEN_ROOT)/tools/xenstore
CPPFLAGS+= -I$(XEN_ROOT)/tools/include
@@ -66,7 +66,11 @@ else
QEMU_SYSTEM=qemu-fast
endif
+ifdef CONFIG_STUBDOM
+QEMU_SYSTEM=qemu.a
+else
QEMU_SYSTEM=qemu-dm
+endif
ifdef CONFIG_USER_ONLY
PROGS=$(QEMU_USER)
@@ -345,14 +349,25 @@ VL_OBJS=vl.o osdep.o readline.o monitor.o pci.o console.o isa_mmio.o
VL_OBJS+=cutils.o
VL_OBJS+=block.o block-raw.o
VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o block-qcow2.o
+ifdef CONFIG_STUBDOM
+VL_OBJS+=block-vbd.o
+endif
ifdef CONFIG_WIN32
VL_OBJS+=tap-win32.o
endif
-ifeq (,$(wildcard /usr/include/pci))
+ifdef CONFIG_STUBDOM
+CONFIG_PASSTHROUGH=1
+else
+ ifeq (,$(wildcard /usr/include/pci))
$(warning *** pciutils-devl package not found - missing /usr/include/pci)
$(warning *** PCI passthrough capability has been disabled)
-else
+ else
+CONFIG_PASSTHROUGH=1
+ endif
+endif
+
+ifdef CONFIG_PASSTHROUGH
LIBS+=-lpci
VL_OBJS+= pass-through.o
CFLAGS += -DCONFIG_PASSTHROUGH
@@ -404,13 +419,13 @@ VL_OBJS+= ne2000.o rtl8139.o pcnet.o e100.o
ifeq ($(TARGET_BASE_ARCH), i386)
# Hardware support
-VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV) extboot.o
+VL_OBJS+= ide.o pckbd.o ps2.o vga.o dma.o extboot.o
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
+VL_OBJS+= cirrus_vga.o parallel.o acpi.o
VL_OBJS+= usb-uhci.o smbus_eeprom.o
VL_OBJS+= piix4acpi.o
VL_OBJS+= xenstore.o
@@ -419,22 +434,32 @@ VL_OBJS+= xen_machine_fv.o
VL_OBJS+= xen_machine_pv.o
VL_OBJS+= xenfb.o
VL_OBJS+= xen_console.o
+ifndef CONFIG_STUBDOM
VL_OBJS+= tpm_tis.o
+VL_OBJS+= $(SOUND_HW) $(AUDIODRV) mixeng.o
+CPPFLAGS += -DHAS_TPM
CPPFLAGS += -DHAS_AUDIO
endif
+endif
ifeq ($(TARGET_BASE_ARCH), ppc)
-VL_OBJS+= ppc.o ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
+VL_OBJS+= ppc.o ide.o pckbd.o ps2.o vga.o dma.o
VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o mixeng.o
VL_OBJS+= grackle_pci.o prep_pci.o unin_pci.o
+ifndef CONFIG_STUBDOM
+VL_OBJS+= $(SOUND_HW) $(AUDIODRV)
CPPFLAGS += -DHAS_AUDIO
endif
+endif
ifeq ($(TARGET_ARCH), mips)
VL_OBJS+= mips_r4k.o mips_malta.o mips_timer.o mips_int.o dma.o vga.o serial.o i8254.o i8259.o
VL_OBJS+= ide.o gt64xxx.o pckbd.o ps2.o fdc.o mc146818rtc.o usb-uhci.o acpi.o
-VL_OBJS+= piix_pci.o parallel.o mixeng.o cirrus_vga.o $(SOUND_HW) $(AUDIODRV)
+VL_OBJS+= piix_pci.o parallel.o mixeng.o cirrus_vga.o
+ifndef CONFIG_STUBDOM
+VL_OBJS+= $(SOUND_HW) $(AUDIODRV)
DEFINES += -DHAS_AUDIO
endif
+endif
ifeq ($(TARGET_BASE_ARCH), sparc)
ifeq ($(TARGET_ARCH), sparc64)
VL_OBJS+= sun4u.o ide.o pckbd.o ps2.o vga.o apb_pci.o
@@ -512,7 +537,11 @@ SDL_LIBS := $(filter-out -mwindows, $(SDL_LIBS)) -mconsole
endif
$(QEMU_SYSTEM): $(VL_OBJS) libqemu.a
+ifdef CONFIG_STUBDOM
+ $(AR) rcs $@ $(VL_OBJS)
+else
$(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS)
+endif
cocoa.o: cocoa.m
$(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
diff --git a/tools/ioemu/aes.c b/tools/ioemu/aes.c
index cd4484ff9b..e75b168a80 100644
--- a/tools/ioemu/aes.c
+++ b/tools/ioemu/aes.c
@@ -33,9 +33,11 @@
#define NDEBUG
#include <assert.h>
+#ifndef CONFIG_STUBDOM
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;
+#endif
#define MAXKC (256/32)
#define MAXKB (256/8)
diff --git a/tools/ioemu/block-raw.c b/tools/ioemu/block-raw.c
index 68e8a370ca..182d2ec55e 100644
--- a/tools/ioemu/block-raw.c
+++ b/tools/ioemu/block-raw.c
@@ -25,7 +25,9 @@
#include "block_int.h"
#include <assert.h>
#ifndef _WIN32
+#ifndef NO_AIO
#include <aio.h>
+#endif
#ifndef QEMU_TOOL
#include "exec-all.h"
@@ -167,10 +169,16 @@ static int raw_pread(BlockDriverState *bs, int64_t offset,
}
s->lseek_err_cnt=0;
- ret = read(s->fd, buf, count);
- if (ret == count)
- goto label__raw_read__success;
+ uint64_t done;
+ for (done = 0; done < count; done += ret) {
+ ret = read(s->fd, buf + done, count - done);
+ if (ret == -1)
+ goto label__raw_read__error;
+ }
+ ret = count;
+ goto label__raw_read__success;
+label__raw_read__error:
DEBUG_BLOCK_PRINT("raw_read(%d:%s, %" PRId64 ", %p, %d) [%" PRId64 "] read failed %d : %d = %s\n",
s->fd,
bs->filename,
@@ -232,9 +240,16 @@ static int raw_pwrite(BlockDriverState *bs, int64_t offset,
}
s->lseek_err_cnt = 0;
- ret = write(s->fd, buf, count);
- if (ret == count)
- goto label__raw_write__success;
+ uint64_t done;
+ for (done = 0; done < count; done += ret) {
+ ret = write(s->fd, buf + done, count - done);
+ if (ret == -1)
+ goto label__raw_write__error;
+ }
+ ret = count;
+ goto label__raw_write__success;
+
+label__raw_write__error:
DEBUG_BLOCK_PRINT("raw_write(%d:%s, %" PRId64 ", %p, %d) [%" PRId64 "] write failed %d : %d = %s\n",
s->fd,
@@ -255,6 +270,7 @@ label__raw_write__success:
/***********************************************************/
/* Unix AIO using POSIX AIO */
+#ifndef NO_AIO
typedef struct RawAIOCB {
BlockDriverAIOCB common;
struct aiocb aiocb;
@@ -480,6 +496,7 @@ static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
pacb = &acb->next;
}
}
+#endif
static void raw_close(BlockDriverState *bs)
{
@@ -600,10 +617,12 @@ BlockDriver bdrv_raw = {
raw_create,
raw_flush,
+#ifndef NO_AIO
.bdrv_aio_read = raw_aio_read,
.bdrv_aio_write = raw_aio_write,
.bdrv_aio_cancel = raw_aio_cancel,
.aiocb_size = sizeof(RawAIOCB),
+#endif
.protocol_name = "file",
.bdrv_pread = raw_pread,
.bdrv_pwrite = raw_pwrite,
@@ -936,10 +955,12 @@ BlockDriver bdrv_host_device = {
NULL,
raw_flush,
+#ifndef NO_AIO
.bdrv_aio_read = raw_aio_read,
.bdrv_aio_write = raw_aio_write,
.bdrv_aio_cancel = raw_aio_cancel,
.aiocb_size = sizeof(RawAIOCB),
+#endif
.bdrv_pread = raw_pread,
.bdrv_pwrite = raw_pwrite,
.bdrv_getlength = raw_getlength,
diff --git a/tools/ioemu/block-vbd.c b/tools/ioemu/block-vbd.c
new file mode 100644
index 0000000000..937bb5e62d
--- /dev/null
+++ b/tools/ioemu/block-vbd.c
@@ -0,0 +1,345 @@
+/*
+ * Block driver for Mini-os PV devices
+ * Based on block-raw.c
+ *
+ * Copyright (c) 2006 Fabrice Bellard, 2007 Samuel Thibault
+ *
+ * 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"
+#include "block_int.h"
+#include <assert.h>
+#include <xenbus.h>
+#include <blkfront.h>
+#include <malloc.h>
+
+#define SECTOR_SIZE 512
+
+#ifndef QEMU_TOOL
+#include "exec-all.h"
+#endif
+
+#define DEBUG_BLOCK
+#ifdef DEBUG_BLOCK
+#define DEBUG_BLOCK_PRINT( formatCstr, args... ) fprintf( logfile, formatCstr, ##args ); fflush( logfile )
+#else
+#define DEBUG_BLOCK_PRINT( formatCstr, args... )
+#endif
+
+#define FTYPE_FILE 0
+#define FTYPE_CD 1
+#define FTYPE_FD 2
+
+typedef struct BDRVVbdState {
+ struct blkfront_dev *dev;
+ int fd;
+ int type;
+ int mode;
+ uint64_t sectors;
+ unsigned sector_size;
+ QEMU_LIST_ENTRY(BDRVVbdState) list;
+} BDRVVbdState;
+
+QEMU_LIST_HEAD(, BDRVVbdState) vbds;
+
+static int vbd_probe(const uint8_t *buf, int buf_size, const char *filename)
+{
+ char *value;
+ if (xenbus_read(XBT_NIL, filename, &value))
+ return 0;
+ free(value);
+ return 100;
+}
+
+static void vbd_io_completed(void *opaque)
+{
+ BDRVVbdState *s = opaque;
+ blkfront_aio_poll(s->dev);
+}
+
+static int vbd_open(BlockDriverState *bs, const char *filename, int flags)
+{
+ BDRVVbdState *s = bs->opaque;
+
+ //handy to test posix access
+ //return -EIO;
+
+ s->dev = init_blkfront((char *) filename, &s->sectors, &s->sector_size, &s->mode);
+
+ if (!s->dev)
+ return -EIO;
+
+ if (SECTOR_SIZE % s->sector_size) {
+ printf("sector size is %d, we only support sector sizes that divide %d\n", s->sector_size, SECTOR_SIZE);
+ return -EIO;
+ }
+
+ s->fd = blkfront_open(s->dev);
+ qemu_set_fd_handler(s->fd, vbd_io_completed, NULL, s);
+
+ QEMU_LIST_INSERT_HEAD(&vbds, s, list);
+
+ return 0;
+}
+
+typedef struct VbdAIOCB {
+ BlockDriverAIOCB common;
+ struct blkfront_aiocb aiocb;
+} VbdAIOCB;
+
+void qemu_aio_init(void)
+{
+}
+
+void qemu_aio_poll(void)
+{
+}
+
+/* Wait for all IO requests to complete. */
+void qemu_aio_flush(void)
+{
+ BDRVVbdState *s;
+ for (s = vbds.lh_first; s; s = s->list.le_next)
+ blkfront_sync(s->dev);
+}
+
+void qemu_aio_wait_start(void)
+{
+}
+
+void qemu_aio_wait(void)
+{
+ int some = 0;
+ DEFINE_WAIT(w);
+ while (1) {
+ BDRVVbdState *s;
+ add_waiter(w, blkfront_queue);
+ for (s = vbds.lh_first; s; s = s->list.le_next)
+ if (blkfront_aio_poll(s->dev))
+ some = 1;
+ if (some)
+ break;
+ schedule();
+ }
+ remove_waiter(w);
+}
+
+void qemu_aio_wait_end(void)
+{
+}
+
+static void vbd_aio_callback(struct blkfront_aiocb *aiocbp, int ret) {
+ VbdAIOCB *acb = aiocbp->data;
+
+ acb->common.cb(acb->common.opaque, ret);
+ qemu_aio_release(acb);
+}
+
+static VbdAIOCB *vbd_aio_setup(BlockDriverState *bs,
+ int64_t sector_num, uint8_t *buf, int nb_sectors,
+ BlockDriverCompletionFunc *cb, void *opaque)
+{
+ BDRVVbdState *s = bs->opaque;
+ VbdAIOCB *acb;
+
+ acb = qemu_aio_get(bs, cb, opaque);
+ if (!acb)
+ return NULL;
+ acb->aiocb.aio_dev = s->dev;
+ acb->aiocb.aio_buf = buf;
+ acb->aiocb.aio_nbytes = nb_sectors * SECTOR_SIZE;
+ acb->aiocb.aio_offset = sector_num * SECTOR_SIZE;
+ acb->aiocb.aio_cb = vbd_aio_callback;
+ acb->aiocb.data = acb;
+
+ return acb;
+}
+
+static BlockDriverAIOCB *vbd_aio_read(BlockDriverState *bs,
+ int64_t sector_num, uint8_t *buf, int nb_sectors,
+ BlockDriverCompletionFunc *cb, void *opaque)
+{
+ VbdAIOCB *acb;
+
+ acb = vbd_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
+ if (!acb)
+ return NULL;
+ blkfront_aio(&acb->aiocb, 0);
+ return &acb->common;
+}
+
+static BlockDriverAIOCB *vbd_aio_write(BlockDriverState *bs,
+ int64_t sector_num, const uint8_t *buf, int nb_sectors,
+ BlockDriverCompletionFunc *cb, void *opaque)
+{
+ VbdAIOCB *acb;
+
+ acb = vbd_aio_setup(bs, sector_num, (uint8_t*) buf, nb_sectors, cb, opaque);
+ if (!acb)
+ return NULL;
+ blkfront_aio(&acb->aiocb, 1);
+ return &acb->common;
+}
+
+static void vbd_cb(void *data, int ret) {
+ int *result = data;
+ result[0] = 1;
+ result[1] = ret;
+}
+
+static int vbd_aligned_io(BlockDriverState *bs,
+ int64_t sector_num, uint8_t *buf, int nb_sectors, int write)
+{
+ VbdAIOCB *acb;
+ int result[2];
+ result[0] = 0;
+ qemu_aio_wait_start();
+ acb = vbd_aio_setup(bs, sector_num, (uint8_t*) buf, nb_sectors, vbd_cb, &result);
+ blkfront_aio(&acb->aiocb, write);
+ while (!result[0])
+ qemu_aio_wait();
+ qemu_aio_wait_end();
+ return result[1];
+}
+
+static int vbd_read(BlockDriverState *bs,
+ int64_t sector_num, uint8_t *buf, int nb_sectors)
+{
+ uint8_t *iobuf;
+ int ret;
+ /* page alignment would be a bit better, but that's still fine compared to
+ * copying */
+ if (!((uintptr_t)buf & (SECTOR_SIZE-1)))
+ return vbd_aligned_io(bs, sector_num, buf, nb_sectors, 0);
+ iobuf = qemu_memalign(PAGE_SIZE, nb_sectors * SECTOR_SIZE);
+ ret = vbd_aligned_io(bs, sector_num, iobuf, nb_sectors, 0);
+ memcpy(buf, iobuf, nb_sectors * SECTOR_SIZE);
+ free(iobuf);
+ if (ret < 0)
+ return ret;
+ else if (ret != nb_sectors * SECTOR_SIZE)
+ return -EINVAL;
+ else
+ return 0;
+}
+
+static int vbd_write(BlockDriverState *bs,
+ int64_t sector_num, const uint8_t *buf, int nb_sectors)
+{
+ uint8_t *iobuf;
+ int ret;
+ if (!((uintptr_t)buf & (SECTOR_SIZE-1)))
+ return vbd_aligned_io(bs, sector_num, (uint8_t*) buf, nb_sectors, 1);
+ iobuf = qemu_memalign(PAGE_SIZE, nb_sectors * SECTOR_SIZE);
+ memcpy(iobuf, buf, nb_sectors * SECTOR_SIZE);
+ ret = vbd_aligned_io(bs, sector_num, iobuf, nb_sectors, 1);
+ free(iobuf);
+ if (ret < 0)
+ return ret;
+ else if (ret != nb_sectors * SECTOR_SIZE)
+ return -EINVAL;
+ else
+ return 0;
+}
+
+static void vbd_aio_cancel(BlockDriverAIOCB *blockacb)
+{
+ /* TODO */
+ //VbdAIOCB *acb = (VbdAIOCB *)blockacb;
+
+ // Try to cancel. If can't, wait for it, drop the callback and call qemu_aio_release(acb)
+}
+
+static void vbd_close(BlockDriverState *bs)
+{
+ BDRVVbdState *s = bs->opaque;
+ bs->total_sectors = 0;
+ if (s->fd >= 0) {
+ close(s->fd);
+ s->fd = -1;
+ }
+ QEMU_LIST_REMOVE(s, list);
+}
+
+static int64_t vbd_getlength(BlockDriverState *bs)
+{
+ BDRVVbdState *s = bs->opaque;
+ return s->sectors * s->sector_size;
+}
+
+static void vbd_flush(BlockDriverState *bs)
+{
+ BDRVVbdState *s = bs->opaque;
+ blkfront_sync(s->dev);
+}
+
+/***********************************************/
+/* host device */
+
+static int vbd_is_inserted(BlockDriverState *bs)
+{
+ /* TODO: monitor the backend */
+ return 1;
+}
+
+/* currently only used by fdc.c, but a CD version would be good too */
+static int vbd_media_changed(BlockDriverState *bs)
+{
+ /* TODO: monitor the backend */
+ return -ENOTSUP;
+}
+
+static int vbd_eject(BlockDriverState *bs, int eject_flag)
+{
+ /* TODO: Xen support needed */
+ return -ENOTSUP;
+}
+
+static int vbd_set_locked(BlockDriverState *bs, int locked)
+{
+ /* TODO: Xen support needed */
+ return -ENOTSUP;
+}
+
+BlockDriver bdrv_vbd = {
+ "vbd",
+ sizeof(BDRVVbdState),
+ vbd_probe,
+ vbd_open,
+ NULL,
+ NULL,
+ vbd_close,
+ NULL,
+ vbd_flush,
+
+ .bdrv_aio_read = vbd_aio_read,
+ .bdrv_aio_write = vbd_aio_write,
+ .bdrv_aio_cancel = vbd_aio_cancel,
+ .aiocb_size = sizeof(VbdAIOCB),
+ .bdrv_read = vbd_read,
+ .bdrv_write = vbd_write,
+ .bdrv_getlength = vbd_getlength,
+
+ /* removable device support */
+ .bdrv_is_inserted = vbd_is_inserted,
+ .bdrv_media_changed = vbd_media_changed,
+ .bdrv_eject = vbd_eject,
+ .bdrv_set_locked = vbd_set_locked,
+};
+
diff --git a/tools/ioemu/block.c b/tools/ioemu/block.c
index cf84e8ffbb..a43f3fe27b 100644
--- a/tools/ioemu/block.c
+++ b/tools/ioemu/block.c
@@ -1235,6 +1235,9 @@ void bdrv_init(void)
{
bdrv_register(&bdrv_raw);
bdrv_register(&bdrv_host_device);
+#ifdef CONFIG_STUBDOM
+ bdrv_register(&bdrv_vbd);
+#endif
#ifndef _WIN32
bdrv_register(&bdrv_cow);
#endif
diff --git a/tools/ioemu/configure b/tools/ioemu/configure
index ef0bac1f8e..3e3b427b87 100755
--- a/tools/ioemu/configure
+++ b/tools/ioemu/configure
@@ -74,6 +74,7 @@ softmmu="yes"
linux_user="no"
darwin_user="no"
build_docs="no"
+stubdom="no"
uname_release=""
# OS specific
@@ -231,6 +232,8 @@ for opt do
;;
--enable-uname-release=*) uname_release="$optarg"
;;
+ --enable-stubdom) stubdom="yes"
+ ;;
esac
done
@@ -416,7 +419,11 @@ if test -z "$target_list" ; then
target_list="i386-darwin-user ppc-darwin-user $target_list"
fi
# the i386-dm target
- target_list="i386-dm"
+ if test "$stubdom" = "yes"; then
+ target_list="i386-dm-stubdom"
+ else
+ target_list="i386-dm"
+ fi
else
target_list=`echo "$target_list" | sed -e 's/,/ /g'`
fi
@@ -575,6 +582,11 @@ bindir="$prefix/$libdir/xen/bin"
configdir="/etc/xen"
fi
+if test "$stubdom" = "yes"; then
+ oss="no"
+ sdl="no"
+fi
+
echo "Install prefix $prefix"
echo "BIOS directory $datadir"
echo "binary directory $bindir"
@@ -943,6 +955,14 @@ if expr $target : '.*-dm' > /dev/null ; then
echo "#define CONFIG_DM 1" >> $config_h
fi
+if test "$stubdom" = "yes" ; then
+ echo "CONFIG_STUBDOM=yes" >> $config_mak
+ echo "#define CONFIG_STUBDOM 1" >> $config_h
+ echo "#define NO_UNIX_SOCKETS 1" >> $config_h
+ echo "#define NO_DAEMONIZE 1" >> $config_h
+ echo "#define NO_AIO 1" >> $config_h
+fi
+
if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = "sparc" -o "$target_cpu" = "sparc64" -o "$target_cpu" = "m68k"; then
echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
echo "#define CONFIG_SOFTFLOAT 1" >> $config_h
diff --git a/tools/ioemu/console.c b/tools/ioemu/console.c
index 634e3d85d0..dc904f6574 100644
--- a/tools/ioemu/console.c
+++ b/tools/ioemu/console.c
@@ -169,16 +169,12 @@ static unsigned int vga_get_color(DisplayState *ds, unsigned int rgba)
unsigned int r, g, b, color;
switch(ds->depth) {
-#if 0
case 8:
r = (rgba >> 16) & 0xff;
g = (rgba >> 8) & 0xff;
b = (rgba) & 0xff;
- color = (rgb_to_index[r] * 6 * 6) +
- (rgb_to_index[g] * 6) +
- (rgb_to_index[b]);
+ color = ((r >> 5) << 5 | (g >> 5) << 2 | (b >> 6));
break;
-#endif
case 15:
r = (rgba >> 16) & 0xff;
g = (rgba >> 8) & 0xff;
diff --git a/tools/ioemu/cpu-all.h b/tools/ioemu/cpu-all.h
index 2f125b785d..9cc854ed7c 100644
--- a/tools/ioemu/cpu-all.h
+++ b/tools/ioemu/cpu-all.h
@@ -116,6 +116,7 @@ static inline void tswap64s(uint64_t *s)
#define bswaptls(s) bswap64s(s)
#endif
+#ifdef CONFIG_SOFTFLOAT
/* NOTE: arm FPA is horrible as double 32 bit words are stored in big
endian ! */
typedef union {
@@ -134,6 +135,7 @@ typedef union {
#endif
uint64_t ll;
} CPU_DoubleU;
+#endif
/* CPU memory access without any memory or io remapping */
@@ -267,6 +269,7 @@ static inline void stq_le_p(void *ptr, uint64_t v)
stl_le_p(p + 4, v >> 32);
}
+#ifdef CONFIG_SOFTFLOAT
/* float access */
static inline float32 ldfl_le_p(void *ptr)
@@ -304,6 +307,7 @@ static inline void stfq_le_p(void *ptr, float64 v)
stl_le_p(ptr, u.l.lower);
stl_le_p(ptr + 4, u.l.upper);
}
+#endif
#else
@@ -342,6 +346,7 @@ static inline void stq_le_p(void *ptr, uint64_t v)
*(uint64_t *)ptr = v;
}
+#ifdef CONFIG_SOFTFLOAT
/* float access */
static inline float32 ldfl_le_p(void *ptr)
@@ -364,6 +369,7 @@ static inline void stfq_le_p(void *ptr, float64 v)
*(float64 *)ptr = v;
}
#endif
+#endif
#if !defined(WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
@@ -456,6 +462,7 @@ static inline void stq_be_p(void *ptr, uint64_t v)
stl_be_p(ptr + 4, v);
}
+#ifdef CONFIG_SOFTFLOAT
/* float access */
static inline float32 ldfl_be_p(void *ptr)
@@ -493,6 +500,7 @@ static inline void stfq_be_p(void *ptr, float64 v)
stl_be_p(ptr, u.l.upper);
stl_be_p(ptr + 4, u.l.lower);
}
+#endif
#else
@@ -531,6 +539,7 @@ static inline void stq_be_p(void *ptr, uint64_t v)
*(uint64_t *)ptr = v;
}
+#ifdef CONFIG_SOFTFLOAT
/* float access */
static inline float32 ldfl_be_p(void *ptr)
@@ -552,6 +561,7 @@ static inline void stfq_be_p(void *ptr, float64 v)
{
*(float64 *)ptr = v;
}
+#endif
#endif
diff --git a/tools/ioemu/exec-all.h b/tools/ioemu/exec-all.h
index f6804b1a0a..28c120d4ca 100644
--- a/tools/ioemu/exec-all.h
+++ b/tools/ioemu/exec-all.h
@@ -481,6 +481,9 @@ static inline int testandset (int *p)
}
#endif
+#ifdef CONFIG_STUBDOM
+#include <spinlock.h>
+#else
typedef int spinlock_t;
#define SPIN_LOCK_UNLOCKED 0
@@ -514,6 +517,7 @@ static inline int spin_trylock(spinlock_t *lock)
return 1;
}
#endif
+#endif
extern spinlock_t tb_lock;
diff --git a/tools/ioemu/hw/fdc.c b/tools/ioemu/hw/fdc.c
index dc2ea6ebff..5989afd7d0 100644
--- a/tools/ioemu/hw/fdc.c
+++ b/tools/ioemu/hw/fdc.c
@@ -378,7 +378,7 @@ struct fdctrl_t {
uint8_t cur_drv;
uint8_t bootsel;
/* Command FIFO */
- uint8_t fifo[FD_SECTOR_LEN];
+ uint8_t *fifo;
uint32_t data_pos;
uint32_t data_len;
uint8_t data_state;
@@ -497,6 +497,11 @@ fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped,
fdctrl = qemu_mallocz(sizeof(fdctrl_t));
if (!fdctrl)
return NULL;
+ fdctrl->fifo = qemu_memalign(512, FD_SECTOR_LEN);
+ if (fdctrl->fifo == NULL) {
+ qemu_free(fdctrl);
+ return NULL;
+ }
fdctrl->result_timer = qemu_new_timer(vm_clock,
fdctrl_result_timer, fdctrl);
diff --git a/tools/ioemu/hw/ide.c b/tools/ioemu/hw/ide.c
index 0e65141ec6..9dd9653aa9 100644
--- a/tools/ioemu/hw/ide.c
+++ b/tools/ioemu/hw/ide.c
@@ -22,6 +22,7 @@
* THE SOFTWARE.
*/
#include "vl.h"
+#include <malloc.h>
/* debug IDE devices */
//#define DEBUG_IDE
@@ -347,7 +348,7 @@ typedef struct IDEState {
EndTransferFunc *end_transfer_func;
uint8_t *data_ptr;
uint8_t *data_end;
- uint8_t io_buffer[MAX_MULT_SECTORS*512 + 4];
+ uint8_t *io_buffer;
QEMUTimer *sector_write_timer; /* only used for win2k instal hack */
uint32_t irq_count; /* counts IRQs when using win2k install hack */
} IDEState;
@@ -2305,6 +2306,7 @@ static void ide_init2(IDEState *ide_state,
for(i = 0; i < 2; i++) {
s = ide_state + i;
+ s->io_buffer = qemu_memalign(getpagesize(), MAX_MULT_SECTORS*512 + 4);
if (i == 0)
s->bs = hd0;
else
diff --git a/tools/ioemu/hw/pc.c b/tools/ioemu/hw/pc.c
index 5d982016a6..c6ebc6780d 100644
--- a/tools/ioemu/hw/pc.c
+++ b/tools/ioemu/hw/pc.c
@@ -361,6 +361,7 @@ void bochs_bios_init(void)
register_ioport_write(0x503, 1, 1, bochs_bios_write, NULL);
}
+#if defined(__i386__) || defined(__x86_64__)
/* Generate an initial boot sector which sets state and jump to
a specified vector */
static void generate_bootsect(uint32_t gpr[8], uint16_t segs[6], uint16_t ip)
@@ -718,6 +719,14 @@ static void load_linux(const char *kernel_filename,
generate_bootsect(gpr, seg, 0);
}
+#else /* __ia64__ */
+static void load_linux(const char *kernel_filename,
+ const char *initrd_filename,
+ const char *kernel_cmdline)
+{
+ /* Direct Linux boot is unsupported. */
+}
+#endif
static void main_cpu_reset(void *opaque)
{
@@ -1013,8 +1022,10 @@ static void pc_init1(uint64_t ram_size, int vga_ram_size, char *boot_device,
}
}
+#ifdef HAS_TPM
if (has_tpm_device())
tpm_tis_init(&pic_set_irq_new, isa_pic, 11);
+#endif
kbd_init();
DMA_init(0);
diff --git a/tools/ioemu/hw/scsi-disk.c b/tools/ioemu/hw/scsi-disk.c
index c6280fd559..acbe75fc98 100644
--- a/tools/ioemu/hw/scsi-disk.c
+++ b/tools/ioemu/hw/scsi-disk.c
@@ -26,13 +26,18 @@ do { printf("scsi-disk: " fmt , ##args); } while (0)
do { fprintf(stderr, "scsi-disk: " fmt , ##args); } while (0)
#include "vl.h"
+#include <malloc.h>
#define SENSE_NO_SENSE 0
#define SENSE_NOT_READY 2
#define SENSE_HARDWARE_ERROR 4
#define SENSE_ILLEGAL_REQUEST 5
+#ifdef CONFIG_STUBDOM
+#define SCSI_DMA_BUF_SIZE 32768
+#else
#define SCSI_DMA_BUF_SIZE 65536
+#endif
typedef struct SCSIRequest {
SCSIDevice *dev;
@@ -44,7 +49,7 @@ typedef struct SCSIRequest {
int sector_count;
/* The amounnt of data in the buffer. */
int buf_len;
- uint8_t dma_buf[SCSI_DMA_BUF_SIZE];
+ uint8_t *dma_buf;
BlockDriverAIOCB *aiocb;
struct SCSIRequest *next;
} SCSIRequest;
@@ -76,6 +81,7 @@ static SCSIRequest *scsi_new_request(SCSIDevice *s, uint32_t tag)
free_requests = r->next;
} else {
r = qemu_malloc(sizeof(SCSIRequest));
+ r->dma_buf = qemu_memalign(getpagesize(), SCSI_DMA_BUF_SIZE);
}
r->dev = s;
r->tag = tag;
diff --git a/tools/ioemu/hw/usb-hid.c b/tools/ioemu/hw/usb-hid.c
index e947977313..78b48b8dbb 100644
--- a/tools/ioemu/hw/usb-hid.c
+++ b/tools/ioemu/hw/usb-hid.c
@@ -224,15 +224,37 @@ static const uint8_t qemu_tablet_hid_report_descriptor[] = {
0xC0, /* End Collection */
};
+static int currentbutton = 0;
+typedef struct _mouseclick {
+ int button_state;
+ struct _mouseclick *next;
+} mouseclick;
+static mouseclick mousequeue[20];
+static mouseclick *head = mousequeue;
+static mouseclick *tail = mousequeue;
+
static void usb_mouse_event(void *opaque,
int dx1, int dy1, int dz1, int buttons_state)
{
USBMouseState *s = opaque;
+ if (s->status_changed == 1){
+ //A mouse event is lost
+ if (buttons_state != currentbutton && tail->next != head) {
+ //A left click event is lost: let's add it to the queue
+ //counter++;
+ tail->button_state = buttons_state;
+ tail = tail->next;
+ }
+ }
+ else {
+ s->buttons_state = buttons_state;
+ }
+
s->dx += dx1;
s->dy += dy1;
s->dz += dz1;
- s->buttons_state = buttons_state;
+ currentbutton = buttons_state;
s->status_changed = 1;
}
@@ -240,11 +262,24 @@ static void usb_tablet_event(void *opaque,
int x, int y, int dz, int buttons_state)
{
USBMouseState *s = opaque;
+
+ if (s->status_changed == 1){
+ //A mouse event is lost
+ if (buttons_state != currentbutton && tail->next != head) {
+ //A left click event is lost: let's add it to the queue
+ //counter++;
+ tail->button_state = buttons_state;
+ tail = tail->next;
+ }
+ }
+ else {
+ s->buttons_state = buttons_state;
+ }
s->x = x;
s->y = y;
s->dz += dz;
- s->buttons_state = buttons_state;
+ currentbutton = buttons_state;
s->status_changed = 1;
}
@@ -493,10 +528,17 @@ static int usb_mouse_handle_data(USBDevice *dev, USBPacket *p)
else if (s->kind == USB_TABLET)
ret = usb_tablet_poll(s, p->data, p->len);
- if (!s->status_changed)
+ if (!s->status_changed) {
ret = USB_RET_NAK;
- else
- s->status_changed = 0;
+ } else {
+ if (head != tail) {
+ s->buttons_state = head->button_state;
+ head = head->next;
+ }
+ else {
+ s->status_changed = 0;
+ }
+ }
} else {
goto fail;
@@ -567,6 +609,14 @@ int usb_mouse_load(QEMUFile *f, void *opaque, int version_id)
USBDevice *usb_tablet_init(void)
{
USBMouseState *s;
+ int i;
+
+ for (i = 0; i < 19; i++) {
+ mousequeue[i].button_state = 0;
+ mousequeue[i].next = &(mousequeue[i + 1]);
+ }
+ mousequeue[i].button_state = 0;
+ mousequeue[i].next = mousequeue;
s = qemu_mallocz(sizeof(USBMouseState));
if (!s)
@@ -591,6 +641,14 @@ USBDevice *usb_tablet_init(void)
USBDevice *usb_mouse_init(void)
{
USBMouseState *s;
+ int i;
+
+ for (i = 0; i < 19; i++) {
+ mousequeue[i].button_state = 0;
+ mousequeue[i].next = &(mousequeue[i + 1]);
+ }
+ mousequeue[i].button_state = 0;
+ mousequeue[i].next = mousequeue;
s = qemu_mallocz(sizeof(USBMouseState));
if (!s)
diff --git a/tools/ioemu/hw/vga.c b/tools/ioemu/hw/vga.c
index 17538bbddc..4e2f9525a7 100644
--- a/tools/ioemu/hw/vga.c
+++ b/tools/ioemu/hw/vga.c
@@ -1071,7 +1071,7 @@ static const uint8_t cursor_glyph[32 * 4] = {
*/
static void vga_draw_text(VGAState *s, int full_update)
{
- int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
+ int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr, depth;
int cx_min, cx_max, linesize, x_incr;
uint32_t offset, fgcol, bgcol, v, cursor_offset;
uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
@@ -1134,6 +1134,11 @@ static void vga_draw_text(VGAState *s, int full_update)
return;
}
+ depth = s->get_bpp(s);
+ if (depth == 24)
+ depth = 32;
+ if (s->ds->dpy_colourdepth != NULL && s->ds->depth != depth)
+ s->ds->dpy_colourdepth(s->ds, depth);
if (width != s->last_width || height != s->last_height ||
cw != s->last_cw || cheight != s->last_ch) {
s->last_scr_width = width * cw;
@@ -1477,7 +1482,7 @@ void check_sse2(void)
*/
static void vga_draw_graphic(VGAState *s, int full_update)
{
- int y1, y, update, linesize, y_start, double_scan, mask;
+ int y1, y, update, linesize, y_start, double_scan, mask, depth;
int width, height, shift_control, line_offset, bwidth;
ram_addr_t page0, page1;
int disp_width, multi_scan, multi_run;
@@ -1551,6 +1556,11 @@ static void vga_draw_graphic(VGAState *s, int full_update)
}
vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
+ depth = s->get_bpp(s);
+ if (depth == 24)
+ depth = 32;
+ if (s->ds->dpy_colourdepth != NULL && s->ds->depth != depth)
+ s->ds->dpy_colourdepth(s->ds, depth);
if (disp_width != s->last_width ||
height != s->last_height) {
dpy_resize(s->ds, disp_width, height);
diff --git a/tools/ioemu/hw/xen_console.c b/tools/ioemu/hw/xen_console.c
index 76aca8f3ee..44f8bcca48 100644
--- a/tools/ioemu/hw/xen_console.c
+++ b/tools/ioemu/hw/xen_console.c
@@ -75,7 +75,7 @@ static void buffer_append(struct domain *dom)
cons = intf->out_cons;
prod = intf->out_prod;
- mb();
+ xen_mb();
size = prod - cons;
if ((size == 0) || (size > sizeof(intf->out)))
@@ -94,7 +94,7 @@ static void buffer_append(struct domain *dom)
buffer->data[buffer->size++] = intf->out[
MASK_XENCONS_IDX(cons++, intf->out)];
- mb();
+ xen_mb();
intf->out_cons = cons;
xc_evtchn_notify(dom->xce_handle, dom->local_port);
@@ -289,7 +289,7 @@ static int ring_free_bytes(struct domain *dom)
cons = intf->in_cons;
prod = intf->in_prod;
- mb();
+ xen_mb();
space = prod - cons;
if (space > sizeof(intf->in))
@@ -322,7 +322,7 @@ static void xencons_receive(void *opaque, const uint8_t *buf, int len)
intf->in[MASK_XENCONS_IDX(prod++, intf->in)] =
buf[i];
}
- wmb();
+ xen_wmb();
intf->in_prod = prod;
xc_evtchn_notify(dom->xce_handle, dom->local_port);
}
diff --git a/tools/ioemu/hw/xen_machine_fv.c b/tools/ioemu/hw/xen_machine_fv.c
index 22ba1dbc3f..272f67946f 100644
--- a/tools/ioemu/hw/xen_machine_fv.c
+++ b/tools/ioemu/hw/xen_machine_fv.c
@@ -24,6 +24,9 @@
*/
#include "vl.h"
+#ifdef CONFIG_STUBDOM
+#include <xenbus.h>
+#endif
#include <xen/hvm/params.h>
#include <sys/mman.h>
diff --git a/tools/ioemu/hw/xenfb.c b/tools/ioemu/hw/xenfb.c
index f0d7f7936e..5418986178 100644
--- a/tools/ioemu/hw/xenfb.c
+++ b/tools/ioemu/hw/xenfb.c
@@ -485,7 +485,7 @@ static void xenfb_on_fb_event(struct xenfb *xenfb)
prod = page->out_prod;
if (prod == page->out_cons)
return;
- rmb(); /* ensure we see ring contents up to prod */
+ xen_rmb(); /* ensure we see ring contents up to prod */
for (cons = page->out_cons; cons != prod; cons++) {
union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons);
int x, y, w, h;
@@ -512,7 +512,7 @@ static void xenfb_on_fb_event(struct xenfb *xenfb)
break;
}
}
- mb(); /* ensure we're done with ring contents */
+ xen_mb(); /* ensure we're done with ring contents */
page->out_cons = cons;
xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port);
}
@@ -571,9 +571,9 @@ static int xenfb_kbd_event(struct xenfb *xenfb,
return -1;
}
- mb(); /* ensure ring space available */
+ xen_mb(); /* ensure ring space available */
XENKBD_IN_RING_REF(page, prod) = *event;
- wmb(); /* ensure ring contents visible */
+ xen_wmb(); /* ensure ring contents visible */
page->in_prod = prod + 1;
return xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port);
}
diff --git a/tools/ioemu/osdep.c b/tools/ioemu/osdep.c
index d1eff8deb5..5ec16b47da 100644
--- a/tools/ioemu/osdep.c
+++ b/tools/ioemu/osdep.c
@@ -61,6 +61,10 @@ void *qemu_malloc(size_t size)
}
#if defined(_WIN32)
+void *qemu_memalign(size_t alignment, size_t size)
+{
+ return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
+}
void *qemu_vmalloc(size_t size)
{
@@ -172,6 +176,22 @@ void kqemu_vfree(void *ptr)
#endif
+void *qemu_memalign(size_t alignment, size_t size)
+{
+#if defined(_POSIX_C_SOURCE)
+ int ret;
+ void *ptr;
+ ret = posix_memalign(&ptr, alignment, size);
+ if (ret != 0)
+ return NULL;
+ return ptr;
+#elif defined(_BSD)
+ return valloc(size);
+#else
+ return memalign(alignment, size);
+#endif
+}
+
/* alloc shared memory pages */
void *qemu_vmalloc(size_t size)
{
diff --git a/tools/ioemu/osdep.h b/tools/ioemu/osdep.h
index bd6ffc1713..6df1d87d12 100644
--- a/tools/ioemu/osdep.h
+++ b/tools/ioemu/osdep.h
@@ -14,6 +14,7 @@ void *qemu_mallocz(size_t size);
void qemu_free(void *ptr);
char *qemu_strdup(const char *str);
+void *qemu_memalign(size_t alignment, size_t size);
void *qemu_vmalloc(size_t size);
void qemu_vfree(void *ptr);
diff --git a/tools/ioemu/sdl.c b/tools/ioemu/sdl.c
index 4d6d73a6a1..4d09469858 100644
--- a/tools/ioemu/sdl.c
+++ b/tools/ioemu/sdl.c
@@ -259,11 +259,9 @@ static void sdl_grab_end(void)
sdl_update_caption();
}
-static void sdl_send_mouse_event(int dz)
+static void sdl_send_mouse_event(int dx, int dy, int dz, int state)
{
- int dx, dy, state, buttons;
- state = SDL_GetRelativeMouseState(&dx, &dy);
- buttons = 0;
+ int buttons = 0;
if (state & SDL_BUTTON(SDL_BUTTON_LEFT))
buttons |= MOUSE_EVENT_LBUTTON;
if (state & SDL_BUTTON(SDL_BUTTON_RIGHT))
@@ -425,11 +423,19 @@ static void sdl_refresh(DisplayState *ds)
case SDL_MOUSEMOTION:
if (gui_grab || kbd_mouse_is_absolute() ||
absolute_enabled) {
- sdl_send_mouse_event(0);
+ int dx, dy, state;
+ state = SDL_GetRelativeMouseState(&dx, &dy);
+ sdl_send_mouse_event(dx, dy, 0, state);
}
break;
- case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
+ if (gui_grab || kbd_mouse_is_absolute()) {
+ int dx, dy, state;
+ state = SDL_GetRelativeMouseState(&dx, &dy);
+ sdl_send_mouse_event(dx, dy, 0, state);
+ }
+ break;
+ case SDL_MOUSEBUTTONDOWN:
{
SDL_MouseButtonEvent *bev = &ev->button;
if (!gui_grab && !kbd_mouse_is_absolute()) {
@@ -439,16 +445,19 @@ static void sdl_refresh(DisplayState *ds)
sdl_grab_start();
}
} else {
- int dz;
+ int dx, dy, dz, state;
dz = 0;
+ state = SDL_GetRelativeMouseState(&dx, &dy);
#ifdef SDL_BUTTON_WHEELUP
- if (bev->button == SDL_BUTTON_WHEELUP && ev->type == SDL_MOUSEBUTTONDOWN) {
+ if (bev->button == SDL_BUTTON_WHEELUP) {
dz = -1;
- } else if (bev->button == SDL_BUTTON_WHEELDOWN && ev->type == SDL_MOUSEBUTTONDOWN) {
+ } else if (bev->button == SDL_BUTTON_WHEELDOWN) {
dz = 1;
+ } else {
+ state = bev->button | state;
}
#endif
- sdl_send_mouse_event(dz);
+ sdl_send_mouse_event(dx, dy, dz, state);
}
}
break;
@@ -499,6 +508,7 @@ void sdl_display_init(DisplayState *ds, int full_screen)
ds->dpy_update = sdl_update;
ds->dpy_resize = sdl_resize;
ds->dpy_refresh = sdl_refresh;
+ ds->dpy_colourdepth = NULL;
sdl_resize(ds, 640, 400);
sdl_update_caption();
diff --git a/tools/ioemu/target-i386-dm/cpu.h b/tools/ioemu/target-i386-dm/cpu.h
index 017b8c021b..6071a8529e 100644
--- a/tools/ioemu/target-i386-dm/cpu.h
+++ b/tools/ioemu/target-i386-dm/cpu.h
@@ -37,17 +37,21 @@
#include "cpu-defs.h"
+#ifdef CONFIG_SOFTFLOAT
#include "softfloat.h"
+#endif
#if defined(__i386__) && !defined(CONFIG_SOFTMMU)
#define USE_CODE_COPY
#endif
+#ifdef CONFIG_SOFTFLOAT
#ifdef USE_X86LDOUBLE
typedef floatx80 CPU86_LDouble;
#else
typedef float64 CPU86_LDouble;
#endif
+#endif
/* Empty for now */
typedef struct CPUX86State {
diff --git a/tools/ioemu/target-i386-dm/helper2.c b/tools/ioemu/target-i386-dm/helper2.c
index d45ac7a999..4896b11ab8 100644
--- a/tools/ioemu/target-i386-dm/helper2.c
+++ b/tools/ioemu/target-i386-dm/helper2.c
@@ -218,7 +218,7 @@ static ioreq_t *__cpu_get_ioreq(int vcpu)
return NULL;
}
- rmb(); /* see IOREQ_READY /then/ read contents of ioreq */
+ xen_rmb(); /* see IOREQ_READY /then/ read contents of ioreq */
req->state = STATE_IOREQ_INPROCESS;
return req;
@@ -568,7 +568,7 @@ void __handle_buffered_iopage(CPUState *env)
__handle_ioreq(env, &req);
- mb();
+ xen_mb();
buffered_io_page->read_pointer += qw ? 2 : 1;
}
}
@@ -603,7 +603,7 @@ void cpu_handle_ioreq(void *opaque)
return;
}
- wmb(); /* Update ioreq contents /then/ update state. */
+ xen_wmb(); /* Update ioreq contents /then/ update state. */
/*
* We do this before we send the response so that the tools
diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c
index fc81fd16e1..703f1bfd6d 100644
--- a/tools/ioemu/vl.c
+++ b/tools/ioemu/vl.c
@@ -36,22 +36,29 @@
#include <sys/times.h>
#include <sys/wait.h>
#include <termios.h>
+#ifndef CONFIG_STUBDOM
#include <sys/poll.h>
+#endif
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <netinet/in.h>
+#ifndef CONFIG_STUBDOM
#include <net/if.h>
+#endif
#if defined(__NetBSD__)
#include <net/if_tap.h>
#endif
#if defined(__linux__) || defined(__Linux__)
#include <linux/if_tun.h>
#endif
+#ifndef CONFIG_STUBDOM
#include <arpa/inet.h>
#include <dirent.h>
+#endif
#include <netdb.h>
+#ifndef CONFIG_STUBDOM
#ifdef _BSD
#include <sys/stat.h>
#ifndef _BSD
@@ -70,6 +77,7 @@
#include <stropts.h>
#endif
#endif
+#endif
#if defined(CONFIG_SLIRP)
#include "libslirp.h"
@@ -80,6 +88,7 @@
#include <windows.h>
#define getopt_long_only getopt_long
#define memalign(align, size) malloc(size)
+#define NO_DAEMONIZE 1
#endif
#include "qemu_socket.h"
@@ -131,10 +140,9 @@
#define MAX_IOPORTS 65536
const char *bios_dir = CONFIG_QEMU_SHAREDIR;
-char phys_ram_file[1024];
-void *ioport_opaque[MAX_IOPORTS];
-IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
-IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
+void **ioport_opaque;
+IOPortReadFunc *(*ioport_read_table)[MAX_IOPORTS];
+IOPortWriteFunc *(*ioport_write_table)[MAX_IOPORTS];
/* Note: bs_table[MAX_DISKS] is a dummy block driver if none available
to store the VM snapshots */
BlockDriverState *bs_table[MAX_DISKS + MAX_SCSI_DISKS + 1], *fd_table[MAX_FD];
@@ -186,7 +194,9 @@ const char *vnc_display;
int acpi_enabled = 0;
int fd_bootchk = 1;
int no_reboot = 0;
+#ifndef NO_DAEMONIZE
int daemonize = 0;
+#endif
const char *option_rom[MAX_OPTION_ROMS];
int nb_option_roms;
int semihosting_enabled = 0;
@@ -224,17 +234,29 @@ void default_ioport_writeb(void *opaque, uint32_t address, uint32_t data)
uint32_t default_ioport_readw(void *opaque, uint32_t address)
{
uint32_t data;
- data = ioport_read_table[0][address](ioport_opaque[address], address);
+ IOPortReadFunc *func = ioport_read_table[0][address];
+ if (!func)
+ func = default_ioport_readb;
+ data = func(ioport_opaque[address], address);
address = (address + 1) & (MAX_IOPORTS - 1);
- data |= ioport_read_table[0][address](ioport_opaque[address], address) << 8;
+ func = ioport_read_table[0][address];
+ if (!func)
+ func = default_ioport_readb;
+ data |= func(ioport_opaque[address], address) << 8;
return data;
}
void default_ioport_writew(void *opaque, uint32_t address, uint32_t data)
{
- ioport_write_table[0][address](ioport_opaque[address], address, data & 0xff);
+ IOPortWriteFunc *func = ioport_write_table[0][address];
+ if (!func)
+ func = default_ioport_writeb;
+ func(ioport_opaque[address], address, data & 0xff);
address = (address + 1) & (MAX_IOPORTS - 1);
- ioport_write_table[0][address](ioport_opaque[address], address, (data >> 8) & 0xff);
+ func = ioport_write_table[0][address];
+ if (!func)
+ func = default_ioport_writeb;
+ func(ioport_opaque[address], address, (data >> 8) & 0xff);
}
uint32_t default_ioport_readl(void *opaque, uint32_t address)
@@ -254,16 +276,9 @@ void default_ioport_writel(void *opaque, uint32_t address, uint32_t data)
void init_ioports(void)
{
- int i;
-
- for(i = 0; i < MAX_IOPORTS; i++) {
- ioport_read_table[0][i] = default_ioport_readb;
- ioport_write_table[0][i] = default_ioport_writeb;
- ioport_read_table[1][i] = default_ioport_readw;
- ioport_write_table[1][i] = default_ioport_writew;
- ioport_read_table[2][i] = default_ioport_readl;
- ioport_write_table[2][i] = default_ioport_writel;
- }
+ ioport_opaque = malloc(MAX_IOPORTS * sizeof(*ioport_opaque));
+ ioport_read_table = malloc(3 * MAX_IOPORTS * sizeof(**ioport_read_table));
+ ioport_write_table = malloc(3 * MAX_IOPORTS * sizeof(**ioport_write_table));
}
/* size is the word size in byte */
@@ -335,11 +350,14 @@ void isa_unassign_ioport(int start, int length)
void cpu_outb(CPUState *env, int addr, int val)
{
+ IOPortWriteFunc *func = ioport_write_table[0][addr];
+ if (!func)
+ func = default_ioport_writeb;
#ifdef DEBUG_IOPORT
if (loglevel & CPU_LOG_IOPORT)
fprintf(logfile, "outb: %04x %02x\n", addr, val);
#endif
- ioport_write_table[0][addr](ioport_opaque[addr], addr, val);
+ func(ioport_opaque[addr], addr, val);
#ifdef USE_KQEMU
if (env)
env->last_io_time = cpu_get_time_fast();
@@ -348,11 +366,14 @@ void cpu_outb(CPUState *env, int addr, int val)
void cpu_outw(CPUState *env, int addr, int val)
{
+ IOPortWriteFunc *func = ioport_write_table[1][addr];
+ if (!func)
+ func = default_ioport_writew;
#ifdef DEBUG_IOPORT
if (loglevel & CPU_LOG_IOPORT)
fprintf(logfile, "outw: %04x %04x\n", addr, val);
#endif
- ioport_write_table[1][addr](ioport_opaque[addr], addr, val);
+ func(ioport_opaque[addr], addr, val);
#ifdef USE_KQEMU
if (env)
env->last_io_time = cpu_get_time_fast();
@@ -361,11 +382,14 @@ void cpu_outw(CPUState *env, int addr, int val)
void cpu_outl(CPUState *env, int addr, int val)
{
+ IOPortWriteFunc *func = ioport_write_table[2][addr];
+ if (!func)
+ func = default_ioport_writel;
#ifdef DEBUG_IOPORT
if (loglevel & CPU_LOG_IOPORT)
fprintf(logfile, "outl: %04x %08x\n", addr, val);
#endif
- ioport_write_table[2][addr](ioport_opaque[addr], addr, val);
+ func(ioport_opaque[addr], addr, val);
#ifdef USE_KQEMU
if (env)
env->last_io_time = cpu_get_time_fast();
@@ -375,7 +399,10 @@ void cpu_outl(CPUState *env, int addr, int val)
int cpu_inb(CPUState *env, int addr)
{
int val;
- val = ioport_read_table[0][addr](ioport_opaque[addr], addr);
+ IOPortReadFunc *func = ioport_read_table[0][addr];
+ if (!func)
+ func = default_ioport_readb;
+ val = func(ioport_opaque[addr], addr);
#ifdef DEBUG_IOPORT
if (loglevel & CPU_LOG_IOPORT)
fprintf(logfile, "inb : %04x %02x\n", addr, val);
@@ -390,7 +417,10 @@ int cpu_inb(CPUState *env, int addr)
int cpu_inw(CPUState *env, int addr)
{
int val;
- val = ioport_read_table[1][addr](ioport_opaque[addr], addr);
+ IOPortReadFunc *func = ioport_read_table[1][addr];
+ if (!func)
+ func = default_ioport_readw;
+ val = func(ioport_opaque[addr], addr);
#ifdef DEBUG_IOPORT
if (loglevel & CPU_LOG_IOPORT)
fprintf(logfile, "inw : %04x %04x\n", addr, val);
@@ -405,7 +435,10 @@ int cpu_inw(CPUState *env, int addr)
int cpu_inl(CPUState *env, int addr)
{
int val;
- val = ioport_read_table[2][addr](ioport_opaque[addr], addr);
+ IOPortReadFunc *func = ioport_read_table[2][addr];
+ if (!func)
+ func = default_ioport_readl;
+ val = func(ioport_opaque[addr], addr);
#ifdef DEBUG_IOPORT
if (loglevel & CPU_LOG_IOPORT)
fprintf(logfile, "inl : %04x %08x\n", addr, val);
@@ -773,9 +806,6 @@ static QEMUTimer *active_timers[2];
static MMRESULT timerID;
static HANDLE host_alarm = NULL;
static unsigned int period = 1;
-#else
-/* frequency of the times() clock tick */
-static int timer_freq;
#endif
QEMUClock *qemu_new_clock(int type)
@@ -1113,9 +1143,6 @@ static void init_timer_alarm(void)
struct itimerval itv;
#endif
- /* get times() syscall frequency */
- timer_freq = sysconf(_SC_CLK_TCK);
-
#ifndef CONFIG_DM
/* timer signal */
sigfillset(&act.sa_mask);
@@ -1473,6 +1500,7 @@ static CharDriverState *qemu_chr_open_file_out(const char *file_out)
return qemu_chr_open_fd(-1, fd_out);
}
+#ifndef CONFIG_STUBDOM
static CharDriverState *qemu_chr_open_pipe(const char *filename)
{
int fd_in, fd_out;
@@ -1718,6 +1746,7 @@ static CharDriverState *qemu_chr_open_stdio(void)
}
return chr;
}
+#endif
/*
* Create a store entry for a device (e.g., monitor, serial/parallel lines).
@@ -1727,6 +1756,9 @@ static CharDriverState *qemu_chr_open_stdio(void)
static int store_dev_info(char *devName, int domid,
CharDriverState *cState, char *storeString)
{
+#ifdef CONFIG_STUBDOM
+ return 0;
+#else
int xc_handle;
struct xs_handle *xs;
char *path;
@@ -1802,8 +1834,10 @@ static int store_dev_info(char *devName, int domid,
close(xc_handle);
return 0;
+#endif
}
+#ifndef CONFIG_STUBDOM
#ifdef __sun__
/* Once Solaris has openpty(), this is going to be removed. */
int openpty(int *amaster, int *aslave, char *name,
@@ -2462,6 +2496,7 @@ static CharDriverState *qemu_chr_open_win_file_out(const char *file_out)
return qemu_chr_open_win_file(fd_out);
}
#endif
+#endif
/***********************************************************/
/* UDP Net console */
@@ -2532,7 +2567,7 @@ static void udp_chr_update_read_handler(CharDriverState *chr)
}
int parse_host_port(struct sockaddr_in *saddr, const char *str);
-#ifndef _WIN32
+#ifndef NO_UNIX_SOCKETS
static int parse_unix_path(struct sockaddr_un *uaddr, const char *str);
#endif
int parse_host_src_port(struct sockaddr_in *haddr,
@@ -2740,7 +2775,7 @@ static void tcp_chr_accept(void *opaque)
CharDriverState *chr = opaque;
TCPCharDriver *s = chr->opaque;
struct sockaddr_in saddr;
-#ifndef _WIN32
+#ifndef NO_UNIX_SOCKETS
struct sockaddr_un uaddr;
#endif
struct sockaddr *addr;
@@ -2748,7 +2783,7 @@ static void tcp_chr_accept(void *opaque)
int fd;
for(;;) {
-#ifndef _WIN32
+#ifndef NO_UNIX_SOCKETS
if (s->is_unix) {
len = sizeof(uaddr);
addr = (struct sockaddr *)&uaddr;
@@ -2797,13 +2832,13 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
int do_nodelay = 0;
const char *ptr;
struct sockaddr_in saddr;
-#ifndef _WIN32
+#ifndef NO_UNIX_SOCKETS
struct sockaddr_un uaddr;
#endif
struct sockaddr *addr;
socklen_t addrlen;
-#ifndef _WIN32
+#ifndef NO_UNIX_SOCKETS
if (is_unix) {
addr = (struct sockaddr *)&uaddr;
addrlen = sizeof(uaddr);
@@ -2842,7 +2877,7 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
if (!s)
goto fail;
-#ifndef _WIN32
+#ifndef NO_UNIX_SOCKETS
if (is_unix)
fd = socket(PF_UNIX, SOCK_STREAM, 0);
else
@@ -2867,7 +2902,7 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str,
if (is_listen) {
/* allow fast reuse */
-#ifndef _WIN32
+#ifndef NO_UNIX_SOCKETS
if (is_unix) {
char path[109];
strncpy(path, uaddr.sun_path, 108);
@@ -2954,12 +2989,14 @@ CharDriverState *qemu_chr_open(const char *filename)
return qemu_chr_open_tcp(p, 0, 1);
} else if (strstart(filename, "file:", &p)) {
return qemu_chr_open_file_out(p);
+#ifndef CONFIG_STUBDOM
} else if (strstart(filename, "pipe:", &p)) {
return qemu_chr_open_pipe(p);
} else if (!strcmp(filename, "pty")) {
return qemu_chr_open_pty();
} else if (!strcmp(filename, "stdio")) {
return qemu_chr_open_stdio();
+#endif
} else
#endif
#if defined(__linux__)
@@ -3449,7 +3486,16 @@ static TAPState *net_tap_fd_init(VLANState *vlan, int fd)
return s;
}
-#ifdef _BSD
+#ifdef CONFIG_STUBDOM
+#include <netfront.h>
+static int tap_open(char *ifname, int ifname_size)
+{
+ char nodename[64];
+ static int num = 1; // 0 is for our own TCP/IP networking
+ snprintf(nodename, sizeof(nodename), "device/vif/%d", num++);
+ return netfront_tap_open(nodename);
+}
+#elif defined(_BSD)
static int tap_open(char *ifname, int ifname_size)
{
int fd;
@@ -3537,6 +3583,7 @@ static int net_tap_init(VLANState *vlan, const char *ifname1,
if (fd < 0)
return -1;
+#ifndef CONFIG_STUBDOM
if (!setup_script || !strcmp(setup_script, "no"))
setup_script = "";
if (setup_script[0] != '\0') {
@@ -3569,6 +3616,7 @@ static int net_tap_init(VLANState *vlan, const char *ifname1,
}
}
}
+#endif
s = net_tap_fd_init(vlan, fd);
if (!s)
return -1;
@@ -4397,6 +4445,7 @@ void dumb_display_init(DisplayState *ds)
ds->depth = 0;
ds->dpy_update = dumb_update;
ds->dpy_resize = dumb_resize;
+ ds->dpy_colourdepth = NULL;
ds->dpy_refresh = dumb_refresh;
}
@@ -6510,7 +6559,7 @@ void help(void)
"-vnc display start a VNC server on display\n"
"-vncviewer start a vncviewer process for this domain\n"
"-vncunused bind the VNC server to an unused port\n"
-#ifndef _WIN32
+#ifndef NO_DAEMONIZE
"-daemonize daemonize QEMU after initializing\n"
#endif
"-option-rom rom load a file, rom, into the option ROM space\n"
@@ -6600,7 +6649,9 @@ enum {
QEMU_OPTION_vnc,
QEMU_OPTION_no_acpi,
QEMU_OPTION_no_reboot,
+#ifndef NO_DAEMONIZE
QEMU_OPTION_daemonize,
+#endif
QEMU_OPTION_option_rom,
QEMU_OPTION_semihosting
,
@@ -6698,7 +6749,9 @@ const QEMUOption qemu_options[] = {
{ "cirrusvga", 0, QEMU_OPTION_cirrusvga },
{ "no-acpi", 0, QEMU_OPTION_no_acpi },
{ "no-reboot", 0, QEMU_OPTION_no_reboot },
+#ifndef NO_DAEMONIZE
{ "daemonize", 0, QEMU_OPTION_daemonize },
+#endif
{ "option-rom", HAS_ARG, QEMU_OPTION_option_rom },
#if defined(TARGET_ARM)
{ "semihosting", 0, QEMU_OPTION_semihosting },
@@ -7009,12 +7062,14 @@ int main(int argc, char **argv)
char usb_devices[MAX_USB_CMDLINE][128];
int usb_devices_index;
int fds[2];
+#ifndef CONFIG_STUBDOM
struct rlimit rl;
+#endif
sigset_t set;
char qemu_dm_logfilename[128];
const char *direct_pci = NULL;
-#ifndef __sun__
+#if !defined(__sun__) && !defined(CONFIG_STUBDOM)
/* Maximise rlimits. Needed where default constraints are tight (*BSD). */
if (getrlimit(RLIMIT_STACK, &rl) != 0) {
perror("getrlimit(RLIMIT_STACK)");
@@ -7040,6 +7095,7 @@ int main(int argc, char **argv)
perror("setrlimit(RLIMIT_MEMLOCK)");
#endif
+#ifndef CONFIG_STUBDOM
/* Ensure that SIGUSR2 is blocked by default when a new thread is created,
then only the threads that use the signal unblock it -- this fixes a
race condition in Qcow support where the AIO signal is misdelivered. */
@@ -7082,6 +7138,7 @@ int main(int argc, char **argv)
}
}
#endif
+#endif
register_machines();
machine = first_machine;
@@ -7496,9 +7553,11 @@ int main(int argc, char **argv)
case QEMU_OPTION_no_reboot:
no_reboot = 1;
break;
+#ifndef NO_DAEMONIZE
case QEMU_OPTION_daemonize:
daemonize = 1;
break;
+#endif
case QEMU_OPTION_option_rom:
if (nb_option_roms >= MAX_OPTION_ROMS) {
fprintf(stderr, "Too many option ROMs\n");
@@ -7542,7 +7601,7 @@ int main(int argc, char **argv)
sprintf(qemu_dm_logfilename, "/var/log/xen/qemu-dm-%d.log", domid);
cpu_set_log_filename(qemu_dm_logfilename);
-#ifndef _WIN32
+#ifndef NO_DAEMONIZE
if (daemonize && !nographic && vnc_display == NULL && vncunused == 0) {
fprintf(stderr, "Can only daemonize if using -nographic or -vnc\n");
daemonize = 0;
@@ -7593,7 +7652,15 @@ int main(int argc, char **argv)
#ifdef CONFIG_DM
bdrv_init();
xc_handle = xc_interface_open();
+#ifdef CONFIG_STUBDOM
+ char *domid_s, *msg;
+ if ((msg = xenbus_read(XBT_NIL, "domid", &domid_s)))
+ fprintf(stderr,"Can not read our own domid\n", msg);
+ else
+ xenstore_parse_domain_config(atoi(domid_s));
+#else /* CONFIG_STUBDOM */
xenstore_parse_domain_config(domid);
+#endif /* CONFIG_STUBDOM */
#endif /* CONFIG_DM */
#ifdef USE_KQEMU
@@ -7760,8 +7827,10 @@ int main(int argc, char **argv)
vnc_display_password(ds, password);
if ((vnc_display_port = vnc_display_open(ds, vnc_display, vncunused)) < 0)
exit (0);
+#ifndef CONFIG_STUBDOM
if (vncviewer)
vnc_start_viewer(vnc_display_port);
+#endif
xenstore_write_vncport(vnc_display_port);
} else {
#if defined(CONFIG_SDL)
@@ -7863,6 +7932,7 @@ int main(int argc, char **argv)
}
}
+#ifndef NO_DAEMONIZE
if (daemonize) {
uint8_t status = 0;
ssize_t len;
@@ -7886,12 +7956,17 @@ int main(int argc, char **argv)
close(fd);
}
+#endif
- /* Unblock SIGTERM, which may have been blocked by the caller */
+#ifndef CONFIG_STUBDOM
+ /* Unblock SIGTERM and SIGHUP, which may have been blocked by the caller */
+ signal(SIGHUP, SIG_DFL);
sigemptyset(&set);
sigaddset(&set, SIGTERM);
+ sigaddset(&set, SIGHUP);
if (sigprocmask(SIG_UNBLOCK, &set, NULL) == -1)
- fprintf(stderr, "Failed to unblock SIGTERM\n");
+ fprintf(stderr, "Failed to unblock SIGTERM and SIGHUP\n");
+#endif
main_loop();
quit_timers();
diff --git a/tools/ioemu/vl.h b/tools/ioemu/vl.h
index 9d78cd25d9..00f5c16333 100644
--- a/tools/ioemu/vl.h
+++ b/tools/ioemu/vl.h
@@ -574,6 +574,9 @@ typedef struct BlockDriver BlockDriver;
extern BlockDriver bdrv_raw;
extern BlockDriver bdrv_host_device;
+#ifdef CONFIG_STUBDOM
+extern BlockDriver bdrv_vbd;
+#endif
extern BlockDriver bdrv_cow;
extern BlockDriver bdrv_qcow;
extern BlockDriver bdrv_vmdk;
@@ -912,8 +915,11 @@ struct DisplayState {
int height;
void *opaque;
+ int switchbpp;
+
void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h);
void (*dpy_resize)(struct DisplayState *s, int w, int h);
+ void (*dpy_colourdepth)(struct DisplayState *s, int depth);
void (*dpy_refresh)(struct DisplayState *s);
void (*dpy_copy)(struct DisplayState *s, int src_x, int src_y, int dst_x, int dst_y, int w, int h);
};
diff --git a/tools/ioemu/vnc.c b/tools/ioemu/vnc.c
index 0dd78dd4b4..7f87f8ed18 100644
--- a/tools/ioemu/vnc.c
+++ b/tools/ioemu/vnc.c
@@ -30,6 +30,9 @@
#include "vl.h"
#include "qemu_socket.h"
#include <assert.h>
+#ifdef CONFIG_STUBDOM
+#include <netfront.h>
+#endif
/* The refresh interval starts at BASE. If we scan the buffer and
find no change, we increase by INC, up to MAX. If the mouse moves
@@ -85,8 +88,8 @@ typedef void VncWritePixels(VncState *vs, void *data, int size);
typedef void VncSendHextileTile(VncState *vs,
int x, int y, int w, int h,
- uint32_t *last_bg,
- uint32_t *last_fg,
+ void *last_bg,
+ void *last_fg,
int *has_bg, int *has_fg);
#if 0
@@ -154,6 +157,7 @@ struct VncState
int has_resize;
int has_hextile;
int has_pointer_type_change;
+ int has_WMVi;
int absolute;
int last_x;
int last_y;
@@ -187,9 +191,9 @@ struct VncState
VncWritePixels *write_pixels;
VncSendHextileTile *send_hextile_tile;
int pix_bpp, pix_big_endian;
- int red_shift, red_max, red_shift1;
- int green_shift, green_max, green_shift1;
- int blue_shift, blue_max, blue_shift1;
+ int red_shift, red_max, red_shift1, red_max1;
+ int green_shift, green_max, green_shift1, green_max1;
+ int blue_shift, blue_max, blue_shift1, blue_max1;
VncReadEvent *read_handler;
size_t read_handler_expect;
@@ -379,54 +383,67 @@ static void vnc_write_pixels_copy(VncState *vs, void *pixels, int size)
/* slowest but generic code. */
static void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
{
- unsigned int r, g, b;
+ uint8_t r, g, b;
- r = (v >> vs->red_shift1) & vs->red_max;
- g = (v >> vs->green_shift1) & vs->green_max;
- b = (v >> vs->blue_shift1) & vs->blue_max;
- v = (r << vs->red_shift) |
- (g << vs->green_shift) |
- (b << vs->blue_shift);
+ r = ((v >> vs->red_shift1) & vs->red_max1) * (vs->red_max + 1) / (vs->red_max1 + 1);
+ g = ((v >> vs->green_shift1) & vs->green_max1) * (vs->green_max + 1) / (vs->green_max1 + 1);
+ b = ((v >> vs->blue_shift1) & vs->blue_max1) * (vs->blue_max + 1) / (vs->blue_max1 + 1);
switch(vs->pix_bpp) {
case 1:
- buf[0] = v;
+ buf[0] = (r << vs->red_shift) | (g << vs->green_shift) | (b << vs->blue_shift);
break;
case 2:
+ {
+ uint16_t *p = (uint16_t *) buf;
+ *p = (r << vs->red_shift) | (g << vs->green_shift) | (b << vs->blue_shift);
if (vs->pix_big_endian) {
- buf[0] = v >> 8;
- buf[1] = v;
- } else {
- buf[1] = v >> 8;
- buf[0] = v;
+ *p = htons(*p);
}
+ }
break;
default:
case 4:
+ {
+ uint32_t *p = (uint32_t *) buf;
+ *p = (r << vs->red_shift) | (g << vs->green_shift) | (b << vs->blue_shift);
if (vs->pix_big_endian) {
- buf[0] = v >> 24;
- buf[1] = v >> 16;
- buf[2] = v >> 8;
- buf[3] = v;
- } else {
- buf[3] = v >> 24;
- buf[2] = v >> 16;
- buf[1] = v >> 8;
- buf[0] = v;
+ *p = htonl(*p);
}
break;
}
+ }
}
static void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size)
{
- uint32_t *pixels = pixels1;
uint8_t buf[4];
- int n, i;
- n = size >> 2;
- for(i = 0; i < n; i++) {
- vnc_convert_pixel(vs, buf, pixels[i]);
- vnc_write(vs, buf, vs->pix_bpp);
+ if (vs->depth == 4) {
+ uint32_t *pixels = pixels1;
+ int n, i;
+ n = size >> 2;
+ for(i = 0; i < n; i++) {
+ vnc_convert_pixel(vs, buf, pixels[i]);
+ vnc_write(vs, buf, vs->pix_bpp);
+ }
+ } else if (vs->depth == 2) {
+ uint16_t *pixels = pixels1;
+ int n, i;
+ n = size >> 1;
+ for(i = 0; i < n; i++) {
+ vnc_convert_pixel(vs, buf, pixels[i]);
+ vnc_write(vs, buf, vs->pix_bpp);
+ }
+ } else if (vs->depth == 1) {
+ uint8_t *pixels = pixels1;
+ int n, i;
+ n = size;
+ for(i = 0; i < n; i++) {
+ vnc_convert_pixel(vs, buf, pixels[i]);
+ vnc_write(vs, buf, vs->pix_bpp);
+ }
+ } else {
+ fprintf(stderr, "vnc_write_pixels_generic: VncState color depth not supported\n");
}
}
@@ -463,6 +480,18 @@ static void hextile_enc_cord(uint8_t *ptr, int x, int y, int w, int h)
#undef BPP
#define GENERIC
+#define BPP 8
+#include "vnchextile.h"
+#undef BPP
+#undef GENERIC
+
+#define GENERIC
+#define BPP 16
+#include "vnchextile.h"
+#undef BPP
+#undef GENERIC
+
+#define GENERIC
#define BPP 32
#include "vnchextile.h"
#undef BPP
@@ -472,18 +501,22 @@ static void send_framebuffer_update_hextile(VncState *vs, int x, int y, int w, i
{
int i, j;
int has_fg, has_bg;
- uint32_t last_fg32, last_bg32;
+ void *last_fg, *last_bg;
vnc_framebuffer_update(vs, x, y, w, h, 5);
+ last_fg = (void *) malloc(vs->depth);
+ last_bg = (void *) malloc(vs->depth);
has_fg = has_bg = 0;
for (j = y; j < (y + h); j += 16) {
for (i = x; i < (x + w); i += 16) {
vs->send_hextile_tile(vs, i, j,
MIN(16, x + w - i), MIN(16, y + h - j),
- &last_bg32, &last_fg32, &has_bg, &has_fg);
+ last_bg, last_fg, &has_bg, &has_fg);
}
}
+ free(last_fg);
+ free(last_bg);
}
static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
@@ -1278,6 +1311,7 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
vs->has_hextile = 0;
vs->has_resize = 0;
vs->has_pointer_type_change = 0;
+ vs->has_WMVi = 0;
vs->absolute = -1;
vs->ds->dpy_copy = NULL;
@@ -1298,6 +1332,8 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
case -257:
vs->has_pointer_type_change = 1;
break;
+ case 0x574D5669:
+ vs->has_WMVi = 1;
default:
break;
}
@@ -1306,17 +1342,6 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
check_pointer_type_change(vs, kbd_mouse_is_absolute());
}
-static int compute_nbits(unsigned int val)
-{
- int n;
- n = 0;
- while (val != 0) {
- n++;
- val >>= 1;
- }
- return n;
-}
-
static void set_pixel_format(VncState *vs,
int bits_per_pixel, int depth,
int big_endian_flag, int true_color_flag,
@@ -1335,23 +1360,24 @@ static void set_pixel_format(VncState *vs,
vnc_client_error(vs);
return;
}
- if (bits_per_pixel == 32 &&
+ if (bits_per_pixel == 32 &&
+ bits_per_pixel == vs->depth * 8 &&
host_big_endian_flag == big_endian_flag &&
red_max == 0xff && green_max == 0xff && blue_max == 0xff &&
red_shift == 16 && green_shift == 8 && blue_shift == 0) {
- vs->depth = 4;
vs->write_pixels = vnc_write_pixels_copy;
vs->send_hextile_tile = send_hextile_tile_32;
} else
- if (bits_per_pixel == 16 &&
+ if (bits_per_pixel == 16 &&
+ bits_per_pixel == vs->depth * 8 &&
host_big_endian_flag == big_endian_flag &&
red_max == 31 && green_max == 63 && blue_max == 31 &&
red_shift == 11 && green_shift == 5 && blue_shift == 0) {
- vs->depth = 2;
vs->write_pixels = vnc_write_pixels_copy;
vs->send_hextile_tile = send_hextile_tile_16;
} else
if (bits_per_pixel == 8 &&
+ bits_per_pixel == vs->depth * 8 &&
red_max == 7 && green_max == 7 && blue_max == 3 &&
red_shift == 5 && green_shift == 2 && blue_shift == 0) {
vs->depth = 1;
@@ -1364,28 +1390,170 @@ static void set_pixel_format(VncState *vs,
bits_per_pixel != 16 &&
bits_per_pixel != 32)
goto fail;
- vs->depth = 4;
- vs->red_shift = red_shift;
- vs->red_max = red_max;
- vs->red_shift1 = 24 - compute_nbits(red_max);
- vs->green_shift = green_shift;
- vs->green_max = green_max;
- vs->green_shift1 = 16 - compute_nbits(green_max);
- vs->blue_shift = blue_shift;
- vs->blue_max = blue_max;
- vs->blue_shift1 = 8 - compute_nbits(blue_max);
- vs->pix_bpp = bits_per_pixel / 8;
+ if (vs->depth == 4) {
+ vs->send_hextile_tile = send_hextile_tile_generic_32;
+ } else if (vs->depth == 2) {
+ vs->send_hextile_tile = send_hextile_tile_generic_16;
+ } else {
+ vs->send_hextile_tile = send_hextile_tile_generic_8;
+ }
+
vs->pix_big_endian = big_endian_flag;
vs->write_pixels = vnc_write_pixels_generic;
- vs->send_hextile_tile = send_hextile_tile_generic;
}
-
- vnc_dpy_resize(vs->ds, vs->ds->width, vs->ds->height);
+
+ vs->red_shift = red_shift;
+ vs->red_max = red_max;
+ vs->green_shift = green_shift;
+ vs->green_max = green_max;
+ vs->blue_shift = blue_shift;
+ vs->blue_max = blue_max;
+ vs->pix_bpp = bits_per_pixel / 8;
vga_hw_invalidate();
vga_hw_update();
}
+static void pixel_format_message (VncState *vs) {
+ char pad[3] = { 0, 0, 0 };
+
+ vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */
+ if (vs->depth == 4) vnc_write_u8(vs, 24); /* depth */
+ else vnc_write_u8(vs, vs->depth * 8); /* depth */
+
+#ifdef WORDS_BIGENDIAN
+ vnc_write_u8(vs, 1); /* big-endian-flag */
+#else
+ vnc_write_u8(vs, 0); /* big-endian-flag */
+#endif
+ vnc_write_u8(vs, 1); /* true-color-flag */
+ if (vs->depth == 4) {
+ vnc_write_u16(vs, 0xFF); /* red-max */
+ vnc_write_u16(vs, 0xFF); /* green-max */
+ vnc_write_u16(vs, 0xFF); /* blue-max */
+ vnc_write_u8(vs, 16); /* red-shift */
+ vnc_write_u8(vs, 8); /* green-shift */
+ vnc_write_u8(vs, 0); /* blue-shift */
+ vs->send_hextile_tile = send_hextile_tile_32;
+ } else if (vs->depth == 2) {
+ vnc_write_u16(vs, 31); /* red-max */
+ vnc_write_u16(vs, 63); /* green-max */
+ vnc_write_u16(vs, 31); /* blue-max */
+ vnc_write_u8(vs, 11); /* red-shift */
+ vnc_write_u8(vs, 5); /* green-shift */
+ vnc_write_u8(vs, 0); /* blue-shift */
+ vs->send_hextile_tile = send_hextile_tile_16;
+ } else if (vs->depth == 1) {
+ /* XXX: change QEMU pixel 8 bit pixel format to match the VNC one ? */
+ vnc_write_u16(vs, 7); /* red-max */
+ vnc_write_u16(vs, 7); /* green-max */
+ vnc_write_u16(vs, 3); /* blue-max */
+ vnc_write_u8(vs, 5); /* red-shift */
+ vnc_write_u8(vs, 2); /* green-shift */
+ vnc_write_u8(vs, 0); /* blue-shift */
+ vs->send_hextile_tile = send_hextile_tile_8;
+ }
+ vs->red_max = vs->red_max1;
+ vs->green_max = vs->green_max1;
+ vs->blue_max = vs->blue_max1;
+ vs->red_shift = vs->red_shift1;
+ vs->green_shift = vs->green_shift1;
+ vs->blue_shift = vs->blue_shift1;
+ vs->pix_bpp = vs->depth * 8;
+ vs->write_pixels = vnc_write_pixels_copy;
+
+ vnc_write(vs, pad, 3); /* padding */
+}
+
+static void vnc_dpy_colourdepth(DisplayState *ds, int depth)
+{
+ int host_big_endian_flag;
+ struct VncState *vs;
+
+ if (!depth) return;
+
+#ifdef WORDS_BIGENDIAN
+ host_big_endian_flag = 1;
+#else
+ host_big_endian_flag = 0;
+#endif
+ vs = ds->opaque;
+
+ switch (depth) {
+ case 8:
+ vs->depth = depth / 8;
+ vs->red_max1 = 7;
+ vs->green_max1 = 7;
+ vs->blue_max1 = 3;
+ vs->red_shift1 = 5;
+ vs->green_shift1 = 2;
+ vs->blue_shift1 = 0;
+ break;
+ case 16:
+ vs->depth = depth / 8;
+ vs->red_max1 = 31;
+ vs->green_max1 = 63;
+ vs->blue_max1 = 31;
+ vs->red_shift1 = 11;
+ vs->green_shift1 = 5;
+ vs->blue_shift1 = 0;
+ break;
+ case 32:
+ vs->depth = 4;
+ vs->red_max1 = 255;
+ vs->green_max1 = 255;
+ vs->blue_max1 = 255;
+ vs->red_shift1 = 16;
+ vs->green_shift1 = 8;
+ vs->blue_shift1 = 0;
+ break;
+ default:
+ return;
+ }
+ if (ds->switchbpp) {
+ vnc_client_error(vs);
+ } else if (vs->csock != -1 && vs->has_WMVi) {
+ /* Sending a WMVi message to notify the client*/
+ vnc_write_u8(vs, 0); /* msg id */
+ vnc_write_u8(vs, 0);
+ vnc_write_u16(vs, 1); /* number of rects */
+ vnc_framebuffer_update(vs, 0, 0, ds->width, ds->height, 0x574D5669);
+ pixel_format_message(vs);
+ vnc_flush(vs);
+ } else {
+ if (vs->pix_bpp == 4 && vs->depth == 4 &&
+ host_big_endian_flag == vs->pix_big_endian &&
+ vs->red_max == 0xff && vs->green_max == 0xff && vs->blue_max == 0xff &&
+ vs->red_shift == 16 && vs->green_shift == 8 && vs->blue_shift == 0) {
+ vs->write_pixels = vnc_write_pixels_copy;
+ vs->send_hextile_tile = send_hextile_tile_32;
+ } else if (vs->pix_bpp == 2 && vs->depth == 2 &&
+ host_big_endian_flag == vs->pix_big_endian &&
+ vs->red_max == 31 && vs->green_max == 63 && vs->blue_max == 31 &&
+ vs->red_shift == 11 && vs->green_shift == 5 && vs->blue_shift == 0) {
+ vs->write_pixels = vnc_write_pixels_copy;
+ vs->send_hextile_tile = send_hextile_tile_16;
+ } else if (vs->pix_bpp == 1 && vs->depth == 1 &&
+ host_big_endian_flag == vs->pix_big_endian &&
+ vs->red_max == 7 && vs->green_max == 7 && vs->blue_max == 3 &&
+ vs->red_shift == 5 && vs->green_shift == 2 && vs->blue_shift == 0) {
+ vs->write_pixels = vnc_write_pixels_copy;
+ vs->send_hextile_tile = send_hextile_tile_8;
+ } else {
+ if (vs->depth == 4) {
+ vs->send_hextile_tile = send_hextile_tile_generic_32;
+ } else if (vs->depth == 2) {
+ vs->send_hextile_tile = send_hextile_tile_generic_16;
+ } else {
+ vs->send_hextile_tile = send_hextile_tile_generic_8;
+ }
+ vs->write_pixels = vnc_write_pixels_generic;
+ }
+ }
+
+ vnc_dpy_resize(ds, ds->width, ds->height);
+}
+
static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
{
int i;
@@ -1473,7 +1641,6 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
{
size_t l;
- char pad[3] = { 0, 0, 0 };
vga_hw_update();
@@ -1482,43 +1649,7 @@ static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
vnc_write_u16(vs, vs->ds->width);
vnc_write_u16(vs, vs->ds->height);
- vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */
- vnc_write_u8(vs, vs->depth * 8); /* depth */
-#ifdef WORDS_BIGENDIAN
- vnc_write_u8(vs, 1); /* big-endian-flag */
-#else
- vnc_write_u8(vs, 0); /* big-endian-flag */
-#endif
- vnc_write_u8(vs, 1); /* true-color-flag */
- if (vs->depth == 4) {
- vnc_write_u16(vs, 0xFF); /* red-max */
- vnc_write_u16(vs, 0xFF); /* green-max */
- vnc_write_u16(vs, 0xFF); /* blue-max */
- vnc_write_u8(vs, 16); /* red-shift */
- vnc_write_u8(vs, 8); /* green-shift */
- vnc_write_u8(vs, 0); /* blue-shift */
- vs->send_hextile_tile = send_hextile_tile_32;
- } else if (vs->depth == 2) {
- vnc_write_u16(vs, 31); /* red-max */
- vnc_write_u16(vs, 63); /* green-max */
- vnc_write_u16(vs, 31); /* blue-max */
- vnc_write_u8(vs, 11); /* red-shift */
- vnc_write_u8(vs, 5); /* green-shift */
- vnc_write_u8(vs, 0); /* blue-shift */
- vs->send_hextile_tile = send_hextile_tile_16;
- } else if (vs->depth == 1) {
- /* XXX: change QEMU pixel 8 bit pixel format to match the VNC one ? */
- vnc_write_u16(vs, 7); /* red-max */
- vnc_write_u16(vs, 7); /* green-max */
- vnc_write_u16(vs, 3); /* blue-max */
- vnc_write_u8(vs, 5); /* red-shift */
- vnc_write_u8(vs, 2); /* green-shift */
- vnc_write_u8(vs, 0); /* blue-shift */
- vs->send_hextile_tile = send_hextile_tile_8;
- }
- vs->write_pixels = vnc_write_pixels_copy;
-
- vnc_write(vs, pad, 3); /* padding */
+ pixel_format_message(vs);
l = strlen(domain_name);
vnc_write_u32(vs, l);
@@ -2160,7 +2291,6 @@ void vnc_display_init(DisplayState *ds)
vs->lsock = -1;
vs->csock = -1;
- vs->depth = 4;
vs->last_x = -1;
vs->last_y = -1;
@@ -2177,9 +2307,12 @@ void vnc_display_init(DisplayState *ds)
vs->ds->data = NULL;
vs->ds->dpy_update = vnc_dpy_update;
vs->ds->dpy_resize = vnc_dpy_resize;
+ vs->ds->dpy_colourdepth = vnc_dpy_colourdepth;
vs->ds->dpy_refresh = vnc_dpy_refresh;
- vnc_dpy_resize(vs->ds, 640, 400);
+ vs->ds->width = 640;
+ vs->ds->height = 400;
+ vnc_dpy_colourdepth(vs->ds, 32);
}
#if CONFIG_VNC_TLS
@@ -2297,10 +2430,12 @@ int vnc_display_open(DisplayState *ds, const char *display, int find_unused)
{
struct sockaddr *addr;
struct sockaddr_in iaddr;
-#ifndef _WIN32
+#ifndef NO_UNIX_SOCKETS
struct sockaddr_un uaddr;
#endif
+#ifndef CONFIG_STUBDOM
int reuse_addr, ret;
+#endif
socklen_t addrlen;
const char *p;
VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
@@ -2325,6 +2460,8 @@ int vnc_display_open(DisplayState *ds, const char *display, int find_unused)
options++;
if (strncmp(options, "password", 8) == 0) {
password = 1; /* Require password auth */
+ } else if (strncmp(options, "switchbpp", 9) == 0) {
+ ds->switchbpp = 1;
#if CONFIG_VNC_TLS
} else if (strncmp(options, "tls", 3) == 0) {
tls = 1; /* Require TLS */
@@ -2432,6 +2569,15 @@ int vnc_display_open(DisplayState *ds, const char *display, int find_unused)
return -1;
}
+#ifdef CONFIG_STUBDOM
+ {
+ struct ip_addr ipaddr = { iaddr.sin_addr.s_addr };
+ struct ip_addr netmask = { 0 };
+ struct ip_addr gw = { 0 };
+ networking_set_addr(&ipaddr, &netmask, &gw);
+ }
+#endif
+
iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 5900);
vs->lsock = socket(PF_INET, SOCK_STREAM, 0);
@@ -2442,6 +2588,7 @@ int vnc_display_open(DisplayState *ds, const char *display, int find_unused)
return -1;
}
+#ifndef CONFIG_STUBDOM
reuse_addr = 1;
ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR,
(const char *)&reuse_addr, sizeof(reuse_addr));
@@ -2453,6 +2600,7 @@ int vnc_display_open(DisplayState *ds, const char *display, int find_unused)
vs->display = NULL;
return -1;
}
+#endif
}
while (bind(vs->lsock, addr, addrlen) == -1) {
@@ -2483,6 +2631,7 @@ int vnc_display_open(DisplayState *ds, const char *display, int find_unused)
return ntohs(iaddr.sin_port);
}
+#ifndef CONFIG_STUBDOM
int vnc_start_viewer(int port)
{
int pid, i, open_max;
@@ -2510,4 +2659,5 @@ int vnc_start_viewer(int port)
return pid;
}
}
+#endif
diff --git a/tools/ioemu/vnchextile.h b/tools/ioemu/vnchextile.h
index 3d894cd574..29b74840f5 100644
--- a/tools/ioemu/vnchextile.h
+++ b/tools/ioemu/vnchextile.h
@@ -2,29 +2,29 @@
#define CONCAT(a, b) CONCAT_I(a, b)
#define pixel_t CONCAT(uint, CONCAT(BPP, _t))
#ifdef GENERIC
-#define NAME generic
+#define NAME CONCAT(generic_, BPP)
#else
#define NAME BPP
#endif
static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
int x, int y, int w, int h,
- uint32_t *last_bg32,
- uint32_t *last_fg32,
+ void *last_bg_,
+ void *last_fg_,
int *has_bg, int *has_fg)
{
uint8_t *row = (vs->ds->data + y * vs->ds->linesize + x * vs->depth);
pixel_t *irow = (pixel_t *)row;
int j, i;
- pixel_t *last_bg = (pixel_t *)last_bg32;
- pixel_t *last_fg = (pixel_t *)last_fg32;
+ pixel_t *last_bg = (pixel_t *)last_bg_;
+ pixel_t *last_fg = (pixel_t *)last_fg_;
pixel_t bg = 0;
pixel_t fg = 0;
int n_colors = 0;
int bg_count = 0;
int fg_count = 0;
int flags = 0;
- uint8_t data[(sizeof(pixel_t) + 2) * 16 * 16];
+ uint8_t data[(vs->pix_bpp + 2) * 16 * 16];
int n_data = 0;
int n_subtiles = 0;
diff --git a/tools/ioemu/xenstore.c b/tools/ioemu/xenstore.c
index 9d33237cb3..8cad6bda2d 100644
--- a/tools/ioemu/xenstore.c
+++ b/tools/ioemu/xenstore.c
@@ -11,8 +11,10 @@
#include "vl.h"
#include "block_int.h"
#include <unistd.h>
+#ifndef CONFIG_STUBDOM
#include <sys/ipc.h>
#include <sys/shm.h>
+#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@@ -219,10 +221,18 @@ void xenstore_parse_domain_config(int domid)
}
/* open device now if media present */
+#ifdef CONFIG_STUBDOM
+ if (pasprintf(&buf, "%s/device/vbd/%s", path, e[i]) == -1)
+ continue;
+ if (bdrv_open2(bs, buf, 0 /* snapshot */, &bdrv_vbd) == 0) {
+ pstrcpy(bs->filename, sizeof(bs->filename), params);
+ continue;
+ }
+#endif
+
if (params[0]) {
if (bdrv_open(bs, params, 0 /* snapshot */) < 0)
- fprintf(stderr, "qemu: could not open hard disk image '%s'\n",
- params);
+ fprintf(stderr, "qemu: could not open vbd '%s' or hard disk image '%s'\n", buf, params);
}
}
@@ -265,6 +275,10 @@ extern int vga_ram_size, bios_size;
void xenstore_process_logdirty_event(void)
{
+#ifdef CONFIG_STUBDOM
+ /* XXX we just can't use shm. */
+ return;
+#else
char *act;
static char *active_path = NULL;
static char *next_active_path = NULL;
@@ -367,6 +381,7 @@ void xenstore_process_logdirty_event(void)
/* Ack that we've switched */
xs_write(xsh, XBT_NULL, active_path, act, len);
free(act);
+#endif
}
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
index ffc5662052..b73bbfe55b 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -5,10 +5,12 @@ MAJOR = 3.2
MINOR = 0
CTRL_SRCS-y :=
+ifneq ($(stubdom),y)
CTRL_SRCS-y += xc_core.c
CTRL_SRCS-$(CONFIG_X86) += xc_core_x86.c
CTRL_SRCS-$(CONFIG_IA64) += xc_core_ia64.c
CTRL_SRCS-$(CONFIG_POWERPC) += xc_core_powerpc.c
+endif
CTRL_SRCS-y += xc_domain.c
CTRL_SRCS-y += xc_evtchn.c
CTRL_SRCS-y += xc_misc.c
@@ -19,21 +21,27 @@ CTRL_SRCS-y += xc_private.c
CTRL_SRCS-y += xc_sedf.c
CTRL_SRCS-y += xc_csched.c
CTRL_SRCS-y += xc_tbuf.c
+ifneq ($(stubdom),y)
CTRL_SRCS-y += xc_resume.c
+endif
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
CTRL_SRCS-$(CONFIG_NetBSD) += xc_netbsd.c
+CTRL_SRCS-$(CONFIG_MiniOS) += xc_minios.c
GUEST_SRCS-y :=
GUEST_SRCS-y += xg_private.c
+ifneq ($(stubdom),y)
GUEST_SRCS-$(CONFIG_MIGRATE) += xc_domain_restore.c xc_domain_save.c
GUEST_SRCS-$(CONFIG_HVM) += xc_hvm_build.c
+endif
VPATH = ../../xen/common/libelf
CFLAGS += -I../../xen/common/libelf
+ifneq ($(stubdom),y)
GUEST_SRCS-y += libelf-tools.c libelf-loader.c
GUEST_SRCS-y += libelf-dominfo.c libelf-relocate.c
@@ -46,6 +54,7 @@ GUEST_SRCS-y += xc_dom_compat_linux.c
GUEST_SRCS-$(CONFIG_X86) += xc_dom_x86.c
GUEST_SRCS-$(CONFIG_IA64) += xc_dom_ia64.c
GUEST_SRCS-$(CONFIG_POWERPC) += xc_dom_powerpc.c
+endif
-include $(XEN_TARGET_ARCH)/Makefile
@@ -71,10 +80,14 @@ GUEST_LIB_OBJS := $(patsubst %.c,%.o,$(GUEST_SRCS-y))
GUEST_PIC_OBJS := $(patsubst %.c,%.opic,$(GUEST_SRCS-y))
LIB := libxenctrl.a
+ifneq ($(stubdom),y)
LIB += libxenctrl.so libxenctrl.so.$(MAJOR) libxenctrl.so.$(MAJOR).$(MINOR)
+endif
LIB += libxenguest.a
+ifneq ($(stubdom),y)
LIB += libxenguest.so libxenguest.so.$(MAJOR) libxenguest.so.$(MAJOR).$(MINOR)
+endif
.PHONY: all
all: build
@@ -133,7 +146,7 @@ libxenctrl.so.$(MAJOR): libxenctrl.so.$(MAJOR).$(MINOR)
ln -sf $< $@
libxenctrl.so.$(MAJOR).$(MINOR): $(CTRL_PIC_OBJS)
- $(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenctrl.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $^ -lpthread
+ $(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenctrl.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $^ $(PTHREAD_LIBS)
# libxenguest
@@ -146,7 +159,7 @@ libxenguest.so.$(MAJOR): libxenguest.so.$(MAJOR).$(MINOR)
ln -sf $< $@
libxenguest.so.$(MAJOR).$(MINOR): $(GUEST_PIC_OBJS) libxenctrl.so
- $(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenguest.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $(GUEST_PIC_OBJS) -lz -lxenctrl -lpthread
+ $(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenguest.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $(GUEST_PIC_OBJS) -lz -lxenctrl $(PTHREAD_LIBS)
-include $(DEPS)
diff --git a/tools/libxc/ia64/Makefile b/tools/libxc/ia64/Makefile
index 8a23024b24..4fd4fbbe86 100644
--- a/tools/libxc/ia64/Makefile
+++ b/tools/libxc/ia64/Makefile
@@ -1,3 +1,4 @@
+ifneq ($(stubdom),y)
CTRL_SRCS-y += ia64/xc_ia64_stubs.c
GUEST_SRCS-y += ia64/xc_ia64_hvm_build.c
@@ -8,6 +9,7 @@ GUEST_SRCS-y += ia64/xc_dom_ia64_util.c
GUEST_SRCS-y += ia64/dom_fw_acpi.c
DOMFW_SRCS_BASE := dom_fw_common.c dom_fw_domu.c dom_fw_asm.S
+endif
DOMFW_SRCS := $(addprefix ia64/, $(DOMFW_SRCS_BASE))
$(DOMFW_SRCS):
ln -sf ../$(XEN_ROOT)/xen/arch/ia64/xen/$(@F) $@
diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
index f75955c577..0f28ed5ca5 100644
--- a/tools/libxc/xc_domain.c
+++ b/tools/libxc/xc_domain.c
@@ -350,21 +350,6 @@ int xc_shadow_control(int xc_handle,
return (rc == 0) ? domctl.u.shadow_op.pages : rc;
}
-int xc_domain_setcpuweight(int xc_handle,
- uint32_t domid,
- float weight)
-{
- int sched_id;
- int ret;
-
- /* Figure out which scheduler is currently used: */
- if ( (ret = xc_sched_id(xc_handle, &sched_id)) != 0 )
- return ret;
-
- /* No-op. */
- return 0;
-}
-
int xc_domain_setmaxmem(int xc_handle,
uint32_t domid,
unsigned int max_memkb)
diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c
index ec7e8fc9a2..52fc1155d2 100644
--- a/tools/libxc/xc_domain_restore.c
+++ b/tools/libxc/xc_domain_restore.c
@@ -251,7 +251,7 @@ static xen_pfn_t *load_p2m_frame_list(
/* Now that we know the guest's word-size, can safely allocate
* the p2m frame list */
- if ( (p2m_frame_list = malloc(P2M_FL_SIZE)) == NULL )
+ if ( (p2m_frame_list = malloc(P2M_TOOLS_FL_SIZE)) == NULL )
{
ERROR("Couldn't allocate p2m_frame_list array");
return NULL;
@@ -1040,7 +1040,7 @@ int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom,
SET_FIELD(&ctxt, gdt_frames[j], p2m[pfn]);
}
/* Uncanonicalise the page table base pointer. */
- pfn = xen_cr3_to_pfn(GET_FIELD(&ctxt, ctrlreg[3]));
+ pfn = UNFOLD_CR3(GET_FIELD(&ctxt, ctrlreg[3]));
if ( pfn >= p2m_size )
{
@@ -1057,12 +1057,12 @@ int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom,
(unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT);
goto out;
}
- SET_FIELD(&ctxt, ctrlreg[3], xen_pfn_to_cr3(p2m[pfn]));
+ SET_FIELD(&ctxt, ctrlreg[3], FOLD_CR3(p2m[pfn]));
/* Guest pagetable (x86/64) stored in otherwise-unused CR1. */
if ( (pt_levels == 4) && (ctxt.x64.ctrlreg[1] & 1) )
{
- pfn = xen_cr3_to_pfn(ctxt.x64.ctrlreg[1] & ~1);
+ pfn = UNFOLD_CR3(ctxt.x64.ctrlreg[1] & ~1);
if ( pfn >= p2m_size )
{
ERROR("User PT base is bad: pfn=%lu p2m_size=%lu",
@@ -1077,7 +1077,7 @@ int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom,
(unsigned long)pt_levels<<XEN_DOMCTL_PFINFO_LTAB_SHIFT);
goto out;
}
- ctxt.x64.ctrlreg[1] = xen_pfn_to_cr3(p2m[pfn]);
+ ctxt.x64.ctrlreg[1] = FOLD_CR3(p2m[pfn]);
}
domctl.cmd = XEN_DOMCTL_setvcpucontext;
domctl.domain = (domid_t)dom;
@@ -1158,7 +1158,7 @@ int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom,
if ( guest_width > sizeof (xen_pfn_t) )
for ( i = p2m_size - 1; i >= 0; i-- )
((uint64_t *)p2m)[i] = p2m[i];
- else if ( guest_width > sizeof (xen_pfn_t) )
+ else if ( guest_width < sizeof (xen_pfn_t) )
for ( i = 0; i < p2m_size; i++ )
((uint32_t *)p2m)[i] = p2m[i];
diff --git a/tools/libxc/xc_domain_save.c b/tools/libxc/xc_domain_save.c
index d37ea9cd51..3bd2db08b6 100644
--- a/tools/libxc/xc_domain_save.c
+++ b/tools/libxc/xc_domain_save.c
@@ -61,10 +61,11 @@ unsigned int guest_width;
#define mfn_to_pfn(_mfn) (live_m2p[(_mfn)])
-#define pfn_to_mfn(_pfn) \
- ((xen_pfn_t) ((guest_width==8) \
- ? (((uint64_t *)live_p2m)[(_pfn)]) \
- : (((uint32_t *)live_p2m)[(_pfn)])))
+#define pfn_to_mfn(_pfn) \
+ ((xen_pfn_t) ((guest_width==8) \
+ ? (((uint64_t *)live_p2m)[(_pfn)]) \
+ : ((((uint32_t *)live_p2m)[(_pfn)]) == 0xffffffffU \
+ ? (-1UL) : (((uint32_t *)live_p2m)[(_pfn)]))))
/*
* Returns TRUE if the given machine frame number has a unique mapping
@@ -496,10 +497,9 @@ static int canonicalize_pagetable(unsigned long type, unsigned long pfn,
xen_start = L3_PAGETABLE_ENTRIES_PAE;
/*
- ** in PAE only the L2 mapping the top 1GB contains Xen mappings.
- ** We can spot this by looking for the guest linear mapping which
- ** Xen always ensures is present in that L2. Guests must ensure
- ** that this check will fail for other L2s.
+ ** In PAE only the L2 mapping the top 1GB contains Xen mappings.
+ ** We can spot this by looking for the guest's mappingof the m2p.
+ ** Guests must ensure that this check will fail for other L2s.
*/
if ( (pt_levels == 3) && (type == XEN_DOMCTL_PFINFO_L2TAB) )
{
@@ -555,7 +555,13 @@ static int canonicalize_pagetable(unsigned long type, unsigned long pfn,
/* This will happen if the type info is stale which
is quite feasible under live migration */
pfn = 0; /* zap it - we'll retransmit this page later */
- race = 1; /* inform the caller of race; fatal if !live */
+ /* XXX: We can't spot Xen mappings in compat-mode L2es
+ * from 64-bit tools, but the only thing in them is the
+ * compat m2p, so we quietly zap them. This doesn't
+ * count as a race, so don't report it. */
+ if ( !(type == XEN_DOMCTL_PFINFO_L2TAB
+ && sizeof (unsigned long) > guest_width) )
+ race = 1; /* inform the caller; fatal if !live */
}
else
pfn = mfn_to_pfn(mfn);
@@ -690,7 +696,7 @@ static xen_pfn_t *map_and_save_p2m_table(int xc_handle,
else
p2m_frame_list_list[i] = 0;
else if ( guest_width < sizeof(unsigned long) )
- for ( i = PAGE_SIZE/sizeof(unsigned long) - 1; i >= 0; i++ )
+ for ( i = PAGE_SIZE/sizeof(unsigned long) - 1; i >= 0; i-- )
p2m_frame_list_list[i] = ((uint32_t *)p2m_frame_list_list)[i];
live_p2m_frame_list =
@@ -704,19 +710,20 @@ static xen_pfn_t *map_and_save_p2m_table(int xc_handle,
}
/* Get a local copy of the live_P2M_frame_list */
- if ( !(p2m_frame_list = malloc(P2M_FL_SIZE)) )
+ if ( !(p2m_frame_list = malloc(P2M_TOOLS_FL_SIZE)) )
{
ERROR("Couldn't allocate p2m_frame_list array");
goto out;
}
- memcpy(p2m_frame_list, live_p2m_frame_list, P2M_FL_SIZE);
+ memset(p2m_frame_list, 0, P2M_TOOLS_FL_SIZE);
+ memcpy(p2m_frame_list, live_p2m_frame_list, P2M_GUEST_FL_SIZE);
/* Canonicalize guest's unsigned long vs ours */
if ( guest_width > sizeof(unsigned long) )
for ( i = 0; i < P2M_FL_ENTRIES; i++ )
p2m_frame_list[i] = ((uint64_t *)p2m_frame_list)[i];
else if ( guest_width < sizeof(unsigned long) )
- for ( i = P2M_FL_ENTRIES - 1; i >= 0; i++ )
+ for ( i = P2M_FL_ENTRIES - 1; i >= 0; i-- )
p2m_frame_list[i] = ((uint32_t *)p2m_frame_list)[i];
@@ -1559,31 +1566,26 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
}
/* Canonicalise the page table base pointer. */
- if ( !MFN_IS_IN_PSEUDOPHYS_MAP(xen_cr3_to_pfn(
- GET_FIELD(&ctxt, ctrlreg[3]))) )
+ if ( !MFN_IS_IN_PSEUDOPHYS_MAP(UNFOLD_CR3(
+ GET_FIELD(&ctxt, ctrlreg[3]))) )
{
ERROR("PT base is not in range of pseudophys map");
goto out;
}
SET_FIELD(&ctxt, ctrlreg[3],
- xen_pfn_to_cr3(
- mfn_to_pfn(
- xen_cr3_to_pfn(
- GET_FIELD(&ctxt, ctrlreg[3])))));
+ FOLD_CR3(mfn_to_pfn(UNFOLD_CR3(GET_FIELD(&ctxt, ctrlreg[3])))));
/* Guest pagetable (x86/64) stored in otherwise-unused CR1. */
if ( (pt_levels == 4) && ctxt.x64.ctrlreg[1] )
{
- if ( !MFN_IS_IN_PSEUDOPHYS_MAP(
- xen_cr3_to_pfn(ctxt.x64.ctrlreg[1])) )
+ if ( !MFN_IS_IN_PSEUDOPHYS_MAP(UNFOLD_CR3(ctxt.x64.ctrlreg[1])) )
{
ERROR("PT base is not in range of pseudophys map");
goto out;
}
/* Least-significant bit means 'valid PFN'. */
ctxt.x64.ctrlreg[1] = 1 |
- xen_pfn_to_cr3(
- mfn_to_pfn(xen_cr3_to_pfn(ctxt.x64.ctrlreg[1])));
+ FOLD_CR3(mfn_to_pfn(UNFOLD_CR3(ctxt.x64.ctrlreg[1])));
}
if ( write_exact(io_fd, &ctxt, ((guest_width==8)
diff --git a/tools/libxc/xc_minios.c b/tools/libxc/xc_minios.c
new file mode 100644
index 0000000000..53f7a148da
--- /dev/null
+++ b/tools/libxc/xc_minios.c
@@ -0,0 +1,313 @@
+/******************************************************************************
+ *
+ * Copyright 2007-2008 Samuel Thibault <samuel.thibault@eu.citrix.com>.
+ * 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.
+ */
+
+#undef NDEBUG
+#include <types.h>
+#include <os.h>
+#include <mm.h>
+#include <lib.h>
+#include <events.h>
+#include <wait.h>
+#include <sys/mman.h>
+#include <errno.h>
+
+#include <xen/memory.h>
+#include <xen/sys/evtchn.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+#include "xc_private.h"
+
+extern struct wait_queue_head event_queue;
+
+int xc_interface_open(void)
+{
+ return 0;
+}
+
+int xc_interface_close(int xc_handle)
+{
+ return 0;
+}
+
+void *xc_map_foreign_batch(int xc_handle, uint32_t dom, int prot,
+ xen_pfn_t *arr, int num)
+{
+ unsigned long pt_prot = 0;
+#ifdef __ia64__
+ /* TODO */
+#else
+ if (prot & PROT_READ)
+ pt_prot = L1_PROT_RO;
+ if (prot & PROT_WRITE)
+ pt_prot = L1_PROT;
+#endif
+ return map_frames_ex(arr, num, 1, 0, 1, dom, 1, pt_prot);
+}
+
+void *xc_map_foreign_range(int xc_handle, uint32_t dom,
+ int size, int prot,
+ unsigned long mfn)
+{
+ unsigned long pt_prot = 0;
+ printf("xc_map_foreign_range(%lx, %d)\n", mfn, size);
+#ifdef __ia64__
+ /* TODO */
+#else
+ if (prot & PROT_READ)
+ pt_prot = L1_PROT_RO;
+ if (prot & PROT_WRITE)
+ pt_prot = L1_PROT;
+#endif
+ assert(!(size % getpagesize()));
+ return map_frames_ex(&mfn, size / getpagesize(), 0, 1, 1, dom, 0, pt_prot);
+}
+
+int xc_map_foreign_ranges(int xc_handle, uint32_t dom,
+ privcmd_mmap_entry_t *entries, int nr)
+{
+ printf("xc_map_foreign_ranges, TODO\n");
+ do_exit();
+}
+
+int do_xen_hypercall(int xc_handle, privcmd_hypercall_t *hypercall)
+{
+ multicall_entry_t call;
+ int i, ret;
+
+ call.op = hypercall->op;
+ for (i = 0; i < sizeof(hypercall->arg) / sizeof(*hypercall->arg); i++)
+ call.args[i] = hypercall->arg[i];
+
+ ret = HYPERVISOR_multicall(&call, 1);
+
+ if (ret < 0) {
+ errno = -ret;
+ return -1;
+ }
+ if (call.result < 0) {
+ errno = -call.result;
+ return -1;
+ }
+ return call.result;
+}
+
+int xc_find_device_number(const char *name)
+{
+ printf("xc_find_device_number(%s)\n", name);
+ do_exit();
+}
+
+int xc_evtchn_open(void)
+{
+ int fd = alloc_fd(FTYPE_EVTCHN), i;
+ for (i = 0; i < MAX_EVTCHN_PORTS; i++) {
+ files[fd].evtchn.ports[i].port = -1;
+ files[fd].evtchn.ports[i].bound = 0;
+ }
+ printf("evtchn_open() -> %d\n", fd);
+ return fd;
+}
+
+int xc_evtchn_close(int xce_handle)
+{
+ int i;
+ for (i = 0; i < MAX_EVTCHN_PORTS; i++)
+ if (files[xce_handle].evtchn.ports[i].bound)
+ unbind_evtchn(files[xce_handle].evtchn.ports[i].port);
+ files[xce_handle].type = FTYPE_NONE;
+ return 0;
+}
+
+int xc_evtchn_fd(int xce_handle)
+{
+ return xce_handle;
+}
+
+int xc_evtchn_notify(int xce_handle, evtchn_port_t port)
+{
+ int ret;
+
+ ret = notify_remote_via_evtchn(port);
+
+ if (ret < 0) {
+ errno = -ret;
+ ret = -1;
+ }
+ return ret;
+}
+
+/* XXX Note: This is not threadsafe */
+static int port_alloc(int xce_handle) {
+ int i;
+ for (i= 0; i < MAX_EVTCHN_PORTS; i++)
+ if (files[xce_handle].evtchn.ports[i].port == -1)
+ break;
+ if (i == MAX_EVTCHN_PORTS) {
+ printf("Too many ports in xc handle\n");
+ errno = EMFILE;
+ return -1;
+ }
+ files[xce_handle].evtchn.ports[i].pending = 0;
+ return i;
+}
+
+static void poke_port(int xce_handle, evtchn_port_t port)
+{
+ shared_info_t *s = HYPERVISOR_shared_info;
+ printk("poking port %d\n", port);
+ synch_set_bit(port, &s->evtchn_pending[0]);
+ xc_evtchn_unmask(xce_handle, port);
+}
+
+static void evtchn_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
+{
+ int xce_handle = (intptr_t) data;
+ int i;
+ assert(files[xce_handle].type == FTYPE_EVTCHN);
+ mask_evtchn(port);
+ for (i= 0; i < MAX_EVTCHN_PORTS; i++)
+ if (files[xce_handle].evtchn.ports[i].port == port)
+ break;
+ if (i == MAX_EVTCHN_PORTS) {
+ printk("Unknown port for handle %d\n", xce_handle);
+ return;
+ }
+ files[xce_handle].evtchn.ports[i].pending++;
+ files[xce_handle].read = 1;
+ wake_up(&event_queue);
+}
+
+evtchn_port_or_error_t xc_evtchn_bind_unbound_port(int xce_handle, int domid)
+{
+ int ret, i;
+ evtchn_port_t port;
+
+ assert(get_current() == main_thread);
+ i = port_alloc(xce_handle);
+ if (i == -1)
+ return -1;
+
+ printf("xc_evtchn_bind_unbound_port(%d)", domid);
+ ret = evtchn_alloc_unbound(domid, evtchn_handler, (void*)(intptr_t)xce_handle, &port);
+ printf(" = %d\n", ret);
+
+ if (ret < 0) {
+ errno = -ret;
+ return -1;
+ }
+ files[xce_handle].evtchn.ports[i].bound = 1;
+ files[xce_handle].evtchn.ports[i].port = port;
+ return port;
+}
+
+evtchn_port_or_error_t xc_evtchn_bind_interdomain(int xce_handle, int domid,
+ evtchn_port_t remote_port)
+{
+ evtchn_port_t local_port;
+ int ret, i;
+
+ assert(get_current() == main_thread);
+ i = port_alloc(xce_handle);
+ if (i == -1)
+ return -1;
+
+ printf("xc_evtchn_bind_interdomain(%d, %"PRId32")", domid, remote_port);
+ ret = evtchn_bind_interdomain(domid, remote_port, evtchn_handler, (void*)(intptr_t)xce_handle, &local_port);
+ printf(" = %d\n", ret);
+
+ if (ret < 0) {
+ errno = -ret;
+ return -1;
+ }
+ files[xce_handle].evtchn.ports[i].bound = 1;
+ files[xce_handle].evtchn.ports[i].port = local_port;
+/* Poke port on start: HVM won't send an event for the very first request since
+ * we were not ready yet */
+ poke_port(xce_handle, local_port);
+ return local_port;
+}
+
+int xc_evtchn_unbind(int xce_handle, evtchn_port_t port)
+{
+ int i;
+ for (i = 0; i < MAX_EVTCHN_PORTS; i++)
+ if (files[xce_handle].evtchn.ports[i].port == port) {
+ files[xce_handle].evtchn.ports[i].port = -1;
+ break;
+ }
+ if (i == MAX_EVTCHN_PORTS)
+ printf("Warning: couldn't find port %"PRId32" for xc handle %x\n", port, xce_handle);
+ files[xce_handle].evtchn.ports[i].bound = 0;
+ unbind_evtchn(port);
+ return 0;
+}
+
+evtchn_port_or_error_t xc_evtchn_bind_virq(int xce_handle, unsigned int virq)
+{
+ evtchn_port_t port;
+ int i;
+
+ assert(get_current() == main_thread);
+ i = port_alloc(xce_handle);
+ if (i == -1)
+ return -1;
+
+ printf("xc_evtchn_bind_virq(%d)", virq);
+ port = bind_virq(virq, evtchn_handler, (void*)(intptr_t)xce_handle);
+
+ if (port < 0) {
+ errno = -port;
+ return -1;
+ }
+ files[xce_handle].evtchn.ports[i].bound = 1;
+ files[xce_handle].evtchn.ports[i].port = port;
+ return port;
+}
+
+evtchn_port_or_error_t xc_evtchn_pending(int xce_handle)
+{
+ int i;
+ unsigned long flags;
+ local_irq_save(flags);
+ for (i = 0; i < MAX_EVTCHN_PORTS; i++) {
+ evtchn_port_t port = files[xce_handle].evtchn.ports[i].port;
+ if (port != -1 && files[xce_handle].evtchn.ports[i].pending) {
+ files[xce_handle].evtchn.ports[i].pending--;
+ local_irq_restore(flags);
+ return port;
+ }
+ }
+ files[xce_handle].read = 0;
+ local_irq_restore(flags);
+ return -1;
+}
+
+int xc_evtchn_unmask(int xce_handle, evtchn_port_t port)
+{
+ unmask_evtchn(port);
+ return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
index f6778dd946..afc80a36df 100644
--- a/tools/libxc/xenctrl.h
+++ b/tools/libxc/xenctrl.h
@@ -43,22 +43,21 @@
*/
#if defined(__i386__)
-#define mb() __asm__ __volatile__ ( "lock; addl $0,0(%%esp)" : : : "memory" )
-#define rmb() __asm__ __volatile__ ( "lock; addl $0,0(%%esp)" : : : "memory" )
-#define wmb() __asm__ __volatile__ ( "" : : : "memory")
+#define xen_mb() asm volatile ( "lock; addl $0,0(%%esp)" : : : "memory" )
+#define xen_rmb() asm volatile ( "lock; addl $0,0(%%esp)" : : : "memory" )
+#define xen_wmb() asm volatile ( "" : : : "memory")
#elif defined(__x86_64__)
-#define mb() __asm__ __volatile__ ( "mfence" : : : "memory")
-#define rmb() __asm__ __volatile__ ( "lfence" : : : "memory")
-#define wmb() __asm__ __volatile__ ( "" : : : "memory")
+#define xen_mb() asm volatile ( "mfence" : : : "memory")
+#define xen_rmb() asm volatile ( "lfence" : : : "memory")
+#define xen_wmb() asm volatile ( "" : : : "memory")
#elif defined(__ia64__)
-#define mb() __asm__ __volatile__ ("mf" ::: "memory")
-#define rmb() __asm__ __volatile__ ("mf" ::: "memory")
-#define wmb() __asm__ __volatile__ ("mf" ::: "memory")
+#define xen_mb() asm volatile ("mf" ::: "memory")
+#define xen_rmb() asm volatile ("mf" ::: "memory")
+#define xen_wmb() asm volatile ("mf" ::: "memory")
#elif defined(__powerpc__)
-/* XXX loosen these up later */
-#define mb() __asm__ __volatile__ ("sync" : : : "memory")
-#define rmb() __asm__ __volatile__ ("sync" : : : "memory") /* lwsync? */
-#define wmb() __asm__ __volatile__ ("sync" : : : "memory") /* eieio? */
+#define xen_mb() asm volatile ("sync" : : : "memory")
+#define xen_rmb() asm volatile ("sync" : : : "memory") /* lwsync? */
+#define xen_wmb() asm volatile ("sync" : : : "memory") /* eieio? */
#else
#error "Define barriers"
#endif
@@ -380,9 +379,6 @@ int xc_vcpu_getinfo(int xc_handle,
uint32_t vcpu,
xc_vcpuinfo_t *info);
-int xc_domain_setcpuweight(int xc_handle,
- uint32_t domid,
- float weight);
long long xc_domain_get_cpu_usage(int xc_handle,
domid_t domid,
int vcpu);
diff --git a/tools/libxc/xg_private.h b/tools/libxc/xg_private.h
index 679c31896c..2ed3f55849 100644
--- a/tools/libxc/xg_private.h
+++ b/tools/libxc/xg_private.h
@@ -155,7 +155,9 @@ typedef l4_pgentry_64_t l4_pgentry_t;
#define P2M_FL_ENTRIES (((p2m_size)+FPP-1)/FPP)
/* Size in bytes of the pfn_to_mfn_frame_list */
-#define P2M_FL_SIZE ((P2M_FL_ENTRIES)*(guest_width))
+#define P2M_GUEST_FL_SIZE ((P2M_FL_ENTRIES) * (guest_width))
+#define P2M_TOOLS_FL_SIZE ((P2M_FL_ENTRIES) * \
+ MAX((sizeof (xen_pfn_t)), guest_width))
/* Masks for PTE<->PFN conversions */
#define MADDR_BITS_X86 ((guest_width == 8) ? 52 : 44)
diff --git a/tools/libxc/xg_save_restore.h b/tools/libxc/xg_save_restore.h
index b0379a4550..2da1e2090d 100644
--- a/tools/libxc/xg_save_restore.h
+++ b/tools/libxc/xg_save_restore.h
@@ -68,6 +68,13 @@ static inline int get_platform_info(int xc_handle, uint32_t dom,
*guest_width = domctl.u.address_size.size / 8;
+ /* 64-bit tools will see the 64-bit hvirt_start, but 32-bit guests
+ * will be using the compat one. */
+ if ( *guest_width < sizeof (unsigned long) )
+ /* XXX need to fix up a way of extracting this value from Xen if
+ * XXX it becomes variable for domU */
+ *hvirt_start = 0xf5800000;
+
if (strstr(xen_caps, "xen-3.0-x86_64"))
/* Depends on whether it's a compat 32-on-64 guest */
*pt_levels = ( (*guest_width == 8) ? 4 : 3 );
@@ -136,6 +143,16 @@ typedef union
(_p)->x32._f = (_v); \
} while (0)
+#define UNFOLD_CR3(_c) \
+ ((uint64_t)((guest_width == 8) \
+ ? ((_c) >> 12) \
+ : (((uint32_t)(_c) >> 12) | ((uint32_t)(_c) << 20))))
+
+#define FOLD_CR3(_c) \
+ ((uint64_t)((guest_width == 8) \
+ ? ((uint64_t)(_c)) << 12 \
+ : (((uint32_t)(_c) << 12) | ((uint32_t)(_c) >> 20))))
+
#define MEMCPY_FIELD(_d, _s, _f) do { \
if (guest_width == 8) \
memcpy(&(_d)->x64._f, &(_s)->x64._f,sizeof((_d)->x64._f)); \
diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
index 425ed7b0fe..305138bd70 100644
--- a/tools/python/xen/lowlevel/xc/xc.c
+++ b/tools/python/xen/lowlevel/xc/xc.c
@@ -237,26 +237,6 @@ static PyObject *pyxc_vcpu_setaffinity(XcObject *self,
return zero;
}
-static PyObject *pyxc_domain_setcpuweight(XcObject *self,
- PyObject *args,
- PyObject *kwds)
-{
- uint32_t dom;
- float cpuweight = 1;
-
- static char *kwd_list[] = { "domid", "cpuweight", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|f", kwd_list,
- &dom, &cpuweight) )
- return NULL;
-
- if ( xc_domain_setcpuweight(self->xc_handle, dom, cpuweight) != 0 )
- return pyxc_error_to_exception();
-
- Py_INCREF(zero);
- return zero;
-}
-
static PyObject *pyxc_domain_sethandle(XcObject *self, PyObject *args)
{
int i;
@@ -1325,14 +1305,6 @@ static PyMethodDef pyxc_methods[] = {
" cpumap [list, []]: list of usable CPUs.\n\n"
"Returns: [int] 0 on success; -1 on error.\n" },
- { "domain_setcpuweight",
- (PyCFunction)pyxc_domain_setcpuweight,
- METH_VARARGS | METH_KEYWORDS, "\n"
- "Set cpuweight scheduler parameter for domain.\n"
- " dom [int]: Identifier of domain to be changed.\n"
- " cpuweight [float, 1]: VCPU being pinned.\n"
- "Returns: [int] 0 on success; -1 on error.\n" },
-
{ "domain_sethandle",
(PyCFunction)pyxc_domain_sethandle,
METH_VARARGS, "\n"
diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py
index 1eb7ee78ca..fafe3e8534 100644
--- a/tools/python/xen/xend/XendConfig.py
+++ b/tools/python/xen/xend/XendConfig.py
@@ -127,7 +127,7 @@ LEGACY_CFG_TO_XENAPI_CFG = reverse_dict(XENAPI_CFG_TO_LEGACY_CFG)
XENAPI_PLATFORM_CFG = [ 'acpi', 'apic', 'boot', 'device_model', 'loader', 'display',
'fda', 'fdb', 'keymap', 'isa', 'localtime', 'monitor',
'nographic', 'pae', 'rtc_timeoffset', 'serial', 'sdl',
- 'soundhw','stdvga', 'usb', 'usbdevice', 'vnc',
+ 'soundhw','stdvga', 'usb', 'usbdevice', 'hpet', 'vnc',
'vncconsole', 'vncdisplay', 'vnclisten', 'timer_mode',
'vncpasswd', 'vncunused', 'xauthority', 'pci', 'vhpt',
'guest_os_type', 'hap']
@@ -406,15 +406,13 @@ class XendConfig(dict):
if self.is_hvm():
if 'loader' not in self['platform']:
- log.debug("No loader present")
- # Old configs may have hvmloder set as PV_kernel param,
- # so lets migrate them....
- if self['PV_kernel'] == "/usr/lib/xen/boot/hvmloader":
+ # Old configs may have hvmloader set as PV_kernel param
+ if self.has_key('PV_kernel') and re.search('hvmloader', self['PV_kernel']):
self['platform']['loader'] = self['PV_kernel']
- log.debug("Loader copied from kernel %s" % str(self['platform']['loader']))
+ self['PV_kernel'] = ''
else:
self['platform']['loader'] = "/usr/lib/xen/boot/hvmloader"
- log.debug("Loader %s" % str(self['platform']['loader']))
+ log.debug("Loader is %s" % str(self['platform']['loader']))
# Compatibility hack, can go away soon.
if 'soundhw' not in self['platform'] and \
diff --git a/tools/python/xen/xend/XendConstants.py b/tools/python/xen/xend/XendConstants.py
index a99dbdc92f..bca3ee7dd1 100644
--- a/tools/python/xen/xend/XendConstants.py
+++ b/tools/python/xen/xend/XendConstants.py
@@ -47,6 +47,7 @@ HVM_PARAM_NVRAM_FD = 7
HVM_PARAM_VHPT_SIZE = 8
HVM_PARAM_BUFPIOREQ_PFN = 9
HVM_PARAM_TIMER_MODE = 10
+HVM_PARAM_HPET_ENABLED = 11
restart_modes = [
"restart",
diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py
index 1e9c1b11f5..c1cb6aa998 100644
--- a/tools/python/xen/xend/XendDomainInfo.py
+++ b/tools/python/xen/xend/XendDomainInfo.py
@@ -707,9 +707,6 @@ class XendDomainInfo:
log.debug("Setting memory maximum of domain %s (%s) to %d MiB.",
self.info['name_label'], str(self.domid), limit)
- if limit <= 0:
- raise XendError('Invalid memory size')
-
MiB = 1024 * 1024
self._safe_set_memory('memory_static_max', limit * MiB)
@@ -1692,6 +1689,12 @@ class XendDomainInfo:
xc.hvm_set_param(self.domid, HVM_PARAM_TIMER_MODE,
long(timer_mode))
+ # Optionally enable virtual HPET
+ hpet = self.info["platform"].get("hpet")
+ if hvm and hpet is not None:
+ xc.hvm_set_param(self.domid, HVM_PARAM_HPET_ENABLED,
+ long(hpet))
+
# Set maximum number of vcpus in domain
xc.domain_max_vcpus(self.domid, int(self.info['VCPUs_max']))
@@ -1750,9 +1753,6 @@ class XendDomainInfo:
self.image = image.create(self, self.info)
- xc.domain_setcpuweight(self.domid, \
- self.info['vcpus_params']['weight'])
-
# repin domain vcpus if a restricted cpus list is provided
# this is done prior to memory allocation to aide in memory
# distribution for NUMA systems.
diff --git a/tools/python/xen/xend/XendPBD.py b/tools/python/xen/xend/XendPBD.py
index 10d8c32b81..2187cd7850 100644
--- a/tools/python/xen/xend/XendPBD.py
+++ b/tools/python/xen/xend/XendPBD.py
@@ -20,6 +20,7 @@ import uuid
from XendLogging import log
from xen.xend.XendBase import XendBase
from xen.xend import XendAPIStore
+from xen.xend import uuid as genuuid
class XendPBD(XendBase):
"""Physical block devices."""
@@ -39,8 +40,7 @@ class XendPBD(XendBase):
return XendBase.getAttrRW() + attrRW
def getAttrInst(self):
- return ['uuid',
- 'host',
+ return ['host',
'SR',
'device_config']
@@ -61,31 +61,31 @@ class XendPBD(XendBase):
getFuncs = classmethod(getFuncs)
def recreate(uuid, record):
- pbd = XendPBD(uuid, record)
+ pbd = XendPBD(record, uuid)
return uuid
def create(cls, record):
uuid = genuuid.createString()
- pbd = XendPBD(uuid, record)
- return uuid
+ pbd = XendPBD(record, uuid)
+ return uuid
create = classmethod(create)
- def __init__(self, uuid, record):
+ def __init__(self, record, uuid):
XendBase.__init__(self, uuid, record)
- this.currently_attached = True
+ self.currently_attached = True
def get_host(self):
- return this.host
+ return self.host
def get_SR(self):
- return this.SR
+ return self.SR
def get_device_config(self):
- return this.device_config
+ return self.device_config
def get_currently_attached(self):
- return this.currently_attached
+ return self.currently_attached
def destroy(self):
pass
diff --git a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py
index 02ea81c748..069cde7dbe 100644
--- a/tools/python/xen/xend/image.py
+++ b/tools/python/xen/xend/image.py
@@ -91,12 +91,12 @@ class ImageHandler:
("image/cmdline", self.cmdline),
("image/ramdisk", self.ramdisk))
- self.dmargs = self.parseDeviceModelArgs(vmConfig)
self.device_model = vmConfig['platform'].get('device_model')
self.display = vmConfig['platform'].get('display')
self.xauthority = vmConfig['platform'].get('xauthority')
self.vncconsole = vmConfig['platform'].get('vncconsole')
+ self.dmargs = self.parseDeviceModelArgs(vmConfig)
self.pid = None
@@ -204,8 +204,14 @@ class ImageHandler:
for dev_uuid in vmConfig['console_refs']:
dev_type, dev_info = vmConfig['devices'][dev_uuid]
if dev_type == 'vfb':
- vnc_config = dev_info.get('other_config', {})
- has_vnc = True
+ vfb_type = dev_info.get('type', {})
+ if vfb_type == 'sdl':
+ self.display = dev_info.get('display', {})
+ self.xauthority = dev_info.get('xauthority', {})
+ has_sdl = True
+ else:
+ vnc_config = dev_info.get('other_config', {})
+ has_vnc = True
break
keymap = vmConfig['platform'].get("keymap")
@@ -329,16 +335,27 @@ class ImageHandler:
return
if self.pid:
try:
- os.kill(self.pid, signal.SIGKILL)
+ os.kill(self.pid, signal.SIGHUP)
except OSError, exn:
log.exception(exn)
try:
- os.waitpid(self.pid, 0)
+ # Try to reap the child every 100ms for 10s. Then SIGKILL it.
+ for i in xrange(100):
+ (p, rv) = os.waitpid(self.pid, os.WNOHANG)
+ if p == self.pid:
+ break
+ time.sleep(0.1)
+ else:
+ log.warning("DeviceModel %d took more than 10s "
+ "to terminate: sending SIGKILL" % self.pid)
+ os.kill(self.pid, signal.SIGKILL)
+ os.waitpid(self.pid, 0)
except OSError, exn:
# This is expected if Xend has been restarted within the
# life of this domain. In this case, we can kill the process,
# but we can't wait for it because it's not our child.
- pass
+ # We just make really sure it's going away (SIGKILL) first.
+ os.kill(self.pid, signal.SIGKILL)
self.pid = None
state = xstransact.Remove("/local/domain/0/device-model/%i"
% self.vm.getDomid())
@@ -449,7 +466,7 @@ class HVMImageHandler(ImageHandler):
ret = ImageHandler.parseDeviceModelArgs(self, vmConfig)
ret = ret + ['-vcpus', str(self.vm.getVCpuCount())]
- if self.kernel and self.kernel != "/usr/lib/xen/boot/hvmloader":
+ if self.kernel:
log.debug("kernel = %s", self.kernel)
ret = ret + ['-kernel', self.kernel]
if self.ramdisk:
diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py
index 1c508becd3..7a3d764c6b 100644
--- a/tools/python/xen/xm/create.py
+++ b/tools/python/xen/xm/create.py
@@ -198,6 +198,10 @@ gopts.var('pae', val='PAE',
fn=set_int, default=1,
use="Disable or enable PAE of HVM domain.")
+gopts.var('hpet', val='HPET',
+ fn=set_int, default=0,
+ use="Enable virtual high-precision event timer.")
+
gopts.var('timer_mode', val='TIMER_MODE',
fn=set_int, default=0,
use="""Timer mode (0=delay virtual time when ticks are missed;
@@ -740,7 +744,7 @@ def configure_hvm(config_image, vals):
'localtime', 'serial', 'stdvga', 'isa', 'nographic', 'soundhw',
'vnc', 'vncdisplay', 'vncunused', 'vncconsole', 'vnclisten',
'sdl', 'display', 'xauthority', 'rtc_timeoffset', 'monitor',
- 'acpi', 'apic', 'usb', 'usbdevice', 'keymap', 'pci',
+ 'acpi', 'apic', 'usb', 'usbdevice', 'keymap', 'pci', 'hpet',
'guest_os_type', 'hap']
for a in args:
diff --git a/tools/python/xen/xm/xenapi_create.py b/tools/python/xen/xm/xenapi_create.py
index 04abcc4e4e..9c16376955 100644
--- a/tools/python/xen/xm/xenapi_create.py
+++ b/tools/python/xen/xm/xenapi_create.py
@@ -818,7 +818,8 @@ class sxp2xml:
def extract_platform(self, image, document):
- platform_keys = ['acpi', 'apic', 'pae', 'vhpt', 'timer_mode', 'hap']
+ platform_keys = ['acpi', 'apic', 'pae', 'vhpt', 'timer_mode',
+ 'hap', 'hpet']
def extract_platform_key(key):
platform = document.createElement("platform")
diff --git a/tools/xenmon/xenbaked.c b/tools/xenmon/xenbaked.c
index 728f14b753..32ca9f36c3 100644
--- a/tools/xenmon/xenbaked.c
+++ b/tools/xenmon/xenbaked.c
@@ -511,10 +511,10 @@ int monitor_tbufs(void)
{
while ( meta[i]->cons != meta[i]->prod )
{
- rmb(); /* read prod, then read item. */
+ xen_rmb(); /* read prod, then read item. */
rec_size = process_record(
i, (struct t_rec *)(data[i] + meta[i]->cons % data_size));
- mb(); /* read item, then update cons. */
+ xen_mb(); /* read item, then update cons. */
meta[i]->cons += rec_size;
}
}
diff --git a/tools/xenstore/xenstored_domain.c b/tools/xenstore/xenstored_domain.c
index 2cc9881eb4..d1d59f9f6f 100644
--- a/tools/xenstore/xenstored_domain.c
+++ b/tools/xenstore/xenstored_domain.c
@@ -112,7 +112,7 @@ static int writechn(struct connection *conn,
/* Must read indexes once, and before anything else, and verified. */
cons = intf->rsp_cons;
prod = intf->rsp_prod;
- mb();
+ xen_mb();
if (!check_indexes(cons, prod)) {
errno = EIO;
@@ -124,7 +124,7 @@ static int writechn(struct connection *conn,
len = avail;
memcpy(dest, data, len);
- mb();
+ xen_mb();
intf->rsp_prod += len;
xc_evtchn_notify(xce_handle, conn->domain->port);
@@ -142,7 +142,7 @@ static int readchn(struct connection *conn, void *data, unsigned int len)
/* Must read indexes once, and before anything else, and verified. */
cons = intf->req_cons;
prod = intf->req_prod;
- mb();
+ xen_mb();
if (!check_indexes(cons, prod)) {
errno = EIO;
@@ -154,7 +154,7 @@ static int readchn(struct connection *conn, void *data, unsigned int len)
len = avail;
memcpy(data, src, len);
- mb();
+ xen_mb();
intf->req_cons += len;
xc_evtchn_notify(xce_handle, conn->domain->port);
diff --git a/tools/xentrace/xentrace.c b/tools/xentrace/xentrace.c
index 26415bdb7d..7f394d2af0 100644
--- a/tools/xentrace/xentrace.c
+++ b/tools/xentrace/xentrace.c
@@ -23,6 +23,7 @@
#include <string.h>
#include <getopt.h>
#include <assert.h>
+#include <sys/poll.h>
#include <xen/xen.h>
#include <xen/trace.h>
@@ -40,9 +41,6 @@ do { \
/***** Compile time configuration of defaults ********************************/
-/* when we've got more records than this waiting, we log it to the output */
-#define NEW_DATA_THRESH 1
-
/* sleep for this long (milliseconds) between checking the trace buffers */
#define POLL_SLEEP_MILLIS 100
@@ -51,8 +49,7 @@ do { \
typedef struct settings_st {
char *outfile;
- struct timespec poll_sleep;
- unsigned long new_data_thresh;
+ unsigned long poll_sleep; /* milliseconds to sleep between polls */
uint32_t evt_mask;
uint32_t cpu_mask;
unsigned long tbuf_size;
@@ -63,26 +60,16 @@ settings_t opts;
int interrupted = 0; /* gets set if we get a SIGHUP */
+static int xc_handle = -1;
+static int event_fd = -1;
+static int virq_port = -1;
+
void close_handler(int signal)
{
interrupted = 1;
}
/**
- * millis_to_timespec - convert a time in milliseconds to a struct timespec
- * @millis: time interval in milliseconds
- */
-struct timespec millis_to_timespec(unsigned long millis)
-{
- struct timespec spec;
-
- spec.tv_sec = millis / 1000;
- spec.tv_nsec = (millis % 1000) * 1000;
-
- return spec;
-}
-
-/**
* write_buffer - write a section of the trace buffer
* @cpu - source buffer CPU ID
* @start
@@ -143,14 +130,8 @@ void write_buffer(unsigned int cpu, unsigned char *start, int size,
static void get_tbufs(unsigned long *mfn, unsigned long *size)
{
- int xc_handle = xc_interface_open();
int ret;
- if ( xc_handle < 0 )
- {
- exit(EXIT_FAILURE);
- }
-
if(!opts.tbuf_size)
opts.tbuf_size = DEFAULT_TBUF_SIZE;
@@ -161,8 +142,6 @@ static void get_tbufs(unsigned long *mfn, unsigned long *size)
perror("Couldn't enable trace buffers");
exit(1);
}
-
- xc_interface_close(xc_handle);
}
/**
@@ -176,22 +155,12 @@ static void get_tbufs(unsigned long *mfn, unsigned long *size)
struct t_buf *map_tbufs(unsigned long tbufs_mfn, unsigned int num,
unsigned long size)
{
- int xc_handle;
struct t_buf *tbufs_mapped;
- xc_handle = xc_interface_open();
-
- if ( xc_handle < 0 )
- {
- exit(EXIT_FAILURE);
- }
-
tbufs_mapped = xc_map_foreign_range(xc_handle, DOMID_XEN,
size * num, PROT_READ | PROT_WRITE,
tbufs_mfn);
- xc_interface_close(xc_handle);
-
if ( tbufs_mapped == 0 )
{
PERROR("Failed to mmap trace buffers");
@@ -210,7 +179,6 @@ struct t_buf *map_tbufs(unsigned long tbufs_mfn, unsigned int num,
void set_mask(uint32_t mask, int type)
{
int ret = 0;
- int xc_handle = xc_interface_open(); /* for accessing control interface */
if (type == 1) {
ret = xc_tbuf_set_cpu_mask(xc_handle, mask);
@@ -220,8 +188,6 @@ void set_mask(uint32_t mask, int type)
fprintf(stderr, "change evtmask to 0x%x\n", mask);
}
- xc_interface_close(xc_handle);
-
if ( ret != 0 )
{
PERROR("Failure to get trace buffer pointer from Xen and set the new mask");
@@ -295,7 +261,6 @@ unsigned char **init_rec_ptrs(struct t_buf **meta, unsigned int num)
unsigned int get_num_cpus(void)
{
xc_physinfo_t physinfo = { 0 };
- int xc_handle = xc_interface_open();
int ret;
ret = xc_physinfo(xc_handle, &physinfo);
@@ -306,11 +271,70 @@ unsigned int get_num_cpus(void)
exit(EXIT_FAILURE);
}
- xc_interface_close(xc_handle);
-
return physinfo.nr_cpus;
}
+/**
+ * event_init - setup to receive the VIRQ_TBUF event
+ */
+void event_init(void)
+{
+ int rc;
+
+ rc = xc_evtchn_open();
+ if (rc < 0) {
+ perror(xc_get_last_error()->message);
+ exit(EXIT_FAILURE);
+ }
+ event_fd = rc;
+
+ rc = xc_evtchn_bind_virq(event_fd, VIRQ_TBUF);
+ if (rc == -1) {
+ PERROR("failed to bind to VIRQ port");
+ exit(EXIT_FAILURE);
+ }
+ virq_port = rc;
+}
+
+/**
+ * wait_for_event_or_timeout - sleep for the specified number of milliseconds,
+ * or until an VIRQ_TBUF event occurs
+ */
+void wait_for_event_or_timeout(unsigned long milliseconds)
+{
+ int rc;
+ struct pollfd fd = { .fd = event_fd,
+ .events = POLLIN | POLLERR };
+ int port;
+
+ rc = poll(&fd, 1, milliseconds);
+ if (rc == -1) {
+ if (errno == EINTR)
+ return;
+ PERROR("poll exitted with an error");
+ exit(EXIT_FAILURE);
+ }
+
+ if (rc == 1) {
+ port = xc_evtchn_pending(event_fd);
+ if (port == -1) {
+ PERROR("failed to read port from evtchn");
+ exit(EXIT_FAILURE);
+ }
+ if (port != virq_port) {
+ fprintf(stderr,
+ "unexpected port returned from evtchn (got %d vs expected %d)\n",
+ port, virq_port);
+ exit(EXIT_FAILURE);
+ }
+ rc = xc_evtchn_unmask(event_fd, port);
+ if (rc == -1) {
+ PERROR("failed to write port to evtchn");
+ exit(EXIT_FAILURE);
+ }
+ }
+}
+
/**
* monitor_tbufs - monitor the contents of tbufs and output to a file
@@ -330,6 +354,9 @@ int monitor_tbufs(int outfd)
unsigned long data_size;
+ /* prepare to listen for VIRQ_TBUF */
+ event_init();
+
/* get number of logical CPUs (and therefore number of trace buffers) */
num = get_num_cpus();
@@ -357,14 +384,23 @@ int monitor_tbufs(int outfd)
/* Read window information only once. */
cons = meta[i]->cons;
prod = meta[i]->prod;
- rmb(); /* read prod, then read item. */
-
+ xen_rmb(); /* read prod, then read item. */
+
if ( cons == prod )
continue;
- assert(prod > cons);
+ assert(cons < 2*data_size);
+ assert(prod < 2*data_size);
+
+ // NB: if (prod<cons), then (prod-cons)%data_size will not yield
+ // the correct answer because data_size is not a power of 2.
+ if ( prod < cons )
+ window_size = (prod + 2*data_size) - cons;
+ else
+ window_size = prod - cons;
+ assert(window_size > 0);
+ assert(window_size <= data_size);
- window_size = prod - cons;
start_offset = cons % data_size;
end_offset = prod % data_size;
@@ -392,11 +428,11 @@ int monitor_tbufs(int outfd)
outfd);
}
- mb(); /* read buffer, then update cons. */
+ xen_mb(); /* read buffer, then update cons. */
meta[i]->cons = prod;
}
- nanosleep(&opts.poll_sleep, NULL);
+ wait_for_event_or_timeout(opts.poll_sleep);
}
/* cleanup */
@@ -416,7 +452,7 @@ int monitor_tbufs(int outfd)
#define xstr(x) str(x)
#define str(x) #x
-const char *program_version = "xentrace v1.1";
+const char *program_version = "xentrace v1.2";
const char *program_bug_address = "<mark.a.williamson@intel.com>";
void usage(void)
@@ -435,9 +471,6 @@ void usage(void)
" N.B. that the trace buffer cannot be resized.\n" \
" if it has already been set this boot cycle,\n" \
" this argument will be ignored.\n" \
-" -t, --log-thresh=l Set number, l, of new records required to\n" \
-" trigger a write to output (default " \
- xstr(NEW_DATA_THRESH) ").\n" \
" -?, --help Show this message\n" \
" -V, --version Print program version\n" \
"\n" \
@@ -516,12 +549,8 @@ void parse_args(int argc, char **argv)
{
switch ( option )
{
- case 't': /* set new records threshold for logging */
- opts.new_data_thresh = argtol(optarg, 0);
- break;
-
case 's': /* set sleep time (given in milliseconds) */
- opts.poll_sleep = millis_to_timespec(argtol(optarg, 0));
+ opts.poll_sleep = argtol(optarg, 0);
break;
case 'c': /* set new cpu mask for filtering*/
@@ -565,13 +594,19 @@ int main(int argc, char **argv)
struct sigaction act;
opts.outfile = 0;
- opts.poll_sleep = millis_to_timespec(POLL_SLEEP_MILLIS);
- opts.new_data_thresh = NEW_DATA_THRESH;
+ opts.poll_sleep = POLL_SLEEP_MILLIS;
opts.evt_mask = 0;
opts.cpu_mask = 0;
parse_args(argc, argv);
-
+
+ xc_handle = xc_interface_open();
+ if ( xc_handle < 0 )
+ {
+ perror(xc_get_last_error()->message);
+ exit(EXIT_FAILURE);
+ }
+
if ( opts.evt_mask != 0 )
set_mask(opts.evt_mask, 0);
diff --git a/unmodified_drivers/linux-2.6/platform-pci/Kbuild b/unmodified_drivers/linux-2.6/platform-pci/Kbuild
index 50951f94fd..7b332ee804 100644
--- a/unmodified_drivers/linux-2.6/platform-pci/Kbuild
+++ b/unmodified_drivers/linux-2.6/platform-pci/Kbuild
@@ -7,6 +7,7 @@ EXTRA_CFLAGS += -I$(M)/platform-pci
xen-platform-pci-objs := evtchn.o platform-pci.o gnttab.o xen_support.o
xen-platform-pci-objs += features.o platform-compat.o
xen-platform-pci-objs += reboot.o machine_reboot.o
+xen-platform-pci-objs += panic-handler.o
xen-platform-pci-objs += ../xenbus/xenbus_comms.o
xen-platform-pci-objs += ../xenbus/xenbus_xs.o
diff --git a/unmodified_drivers/linux-2.6/platform-pci/panic-handler.c b/unmodified_drivers/linux-2.6/platform-pci/panic-handler.c
new file mode 100644
index 0000000000..91bc03549b
--- /dev/null
+++ b/unmodified_drivers/linux-2.6/platform-pci/panic-handler.c
@@ -0,0 +1,54 @@
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/notifier.h>
+#include <asm/hypervisor.h>
+
+MODULE_LICENSE("GPL");
+
+#ifdef __ia64__
+static void
+xen_panic_hypercall(struct unw_frame_info *info, void *arg)
+{
+ current->thread.ksp = (__u64)info->sw - 16;
+ HYPERVISOR_shutdown(SHUTDOWN_crash);
+ /* we're never actually going to get here... */
+}
+#endif
+
+static int
+xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+#ifdef __ia64__
+ unw_init_running(xen_panic_hypercall, NULL);
+#else /* !__ia64__ */
+ HYPERVISOR_shutdown(SHUTDOWN_crash);
+#endif
+ /* we're never actually going to get here... */
+ return NOTIFY_DONE;
+}
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
+static struct notifier_block xen_panic_block = {
+ xen_panic_event, NULL, 0 /* try to go last */
+};
+#else
+static struct notifier_block xen_panic_block = {
+ .notifier_call= xen_panic_event,
+ .next= NULL,
+ .priority= 0/* try to go last */
+};
+#endif /*LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)*/
+
+static int __init setup_panic_event(void)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
+ notifier_chain_register(&panic_notifier_list, &xen_panic_block);
+#else
+ atomic_notifier_chain_register(&panic_notifier_list, &xen_panic_block);
+#endif /*LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)*/
+ return 0;
+}
+
+int xen_panic_handler_init(void)
+{
+ return setup_panic_event();
+}
diff --git a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c
index 7a512073d2..3d3a4c79a1 100644
--- a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c
+++ b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c
@@ -249,6 +249,7 @@ static int set_callback_via(uint64_t via)
int xen_irq_init(struct pci_dev *pdev);
int xenbus_init(void);
int xen_reboot_init(void);
+int xen_panic_handler_init(void);
int gnttab_init(void);
static int __devinit platform_pci_init(struct pci_dev *pdev,
@@ -317,6 +318,9 @@ static int __devinit platform_pci_init(struct pci_dev *pdev,
if ((ret = xen_reboot_init()))
goto out;
+ if ((ret = xen_panic_handler_init()))
+ goto out;
+
out:
if (ret) {
release_mem_region(mmio_addr, mmio_len);
diff --git a/xen/arch/x86/boot/trampoline.S b/xen/arch/x86/boot/trampoline.S
index 2c92dc6a00..143612c91f 100644
--- a/xen/arch/x86/boot/trampoline.S
+++ b/xen/arch/x86/boot/trampoline.S
@@ -155,6 +155,13 @@ trampoline_boot_cpu_entry:
lidt bootsym(rm_idt)
sti
+#if defined(__x86_64__)
+ /* Declare that our target operating mode is long mode. */
+ movw $0xec00,%ax # declare target operating mode
+ movw $0x0002,%bx # long mode
+ int $0x15
+#endif
+
/*
* Do real-mode work:
* 1. Get memory map.
diff --git a/xen/arch/x86/cpu/mtrr/main.c b/xen/arch/x86/cpu/mtrr/main.c
index 4881055d1a..2a606f0320 100644
--- a/xen/arch/x86/cpu/mtrr/main.c
+++ b/xen/arch/x86/cpu/mtrr/main.c
@@ -46,8 +46,6 @@
#define DEFINE_MUTEX(_m) DEFINE_SPINLOCK(_m)
#define mutex_lock(_m) spin_lock(_m)
#define mutex_unlock(_m) spin_unlock(_m)
-#define lock_cpu_hotplug() ((void)0)
-#define unlock_cpu_hotplug() ((void)0)
#define dump_stack() ((void)0)
#define get_cpu() smp_processor_id()
#define put_cpu() do {} while(0)
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index 9d0537a9f9..25bc2c7148 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -82,7 +82,6 @@ static void default_idle(void)
static void play_dead(void)
{
- __cpu_disable();
/* This must be done before dead CPU ack */
cpu_exit_clear();
hvm_cpu_down();
@@ -101,7 +100,7 @@ void idle_loop(void)
{
for ( ; ; )
{
- if (cpu_is_offline(smp_processor_id()))
+ if ( cpu_is_offline(smp_processor_id()) )
play_dead();
page_scrub_schedule_work();
default_idle();
diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
index 1460f8e620..abfda3e737 100644
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -530,7 +530,7 @@ long arch_do_domctl(
u8 bus, devfn;
ret = -EINVAL;
- if ( !vtd_enabled )
+ if ( !iommu_enabled )
break;
bus = (domctl->u.assign_device.machine_bdf >> 16) & 0xff;
@@ -553,7 +553,7 @@ long arch_do_domctl(
u8 bus, devfn;
ret = -EINVAL;
- if ( !vtd_enabled )
+ if ( !iommu_enabled )
break;
if ( unlikely((d = get_domain_by_id(domctl->domain)) == NULL) )
@@ -589,9 +589,9 @@ long arch_do_domctl(
if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL )
break;
bind = &(domctl->u.bind_pt_irq);
- if (vtd_enabled)
+ if ( iommu_enabled )
ret = pt_irq_create_bind_vtd(d, bind);
- if (ret < 0)
+ if ( ret < 0 )
gdprintk(XENLOG_ERR, "pt_irq_create_bind failed!\n");
rcu_unlock_domain(d);
}
diff --git a/xen/arch/x86/hvm/Makefile b/xen/arch/x86/hvm/Makefile
index bb2e0e42c1..4e6e70e188 100644
--- a/xen/arch/x86/hvm/Makefile
+++ b/xen/arch/x86/hvm/Makefile
@@ -6,6 +6,7 @@ obj-y += i8254.o
obj-y += instrlen.o
obj-y += intercept.o
obj-y += io.o
+obj-y += iommu.o
obj-y += irq.o
obj-y += mtrr.o
obj-y += platform.o
diff --git a/xen/arch/x86/hvm/hpet.c b/xen/arch/x86/hvm/hpet.c
index f6845755a0..49ca998d37 100644
--- a/xen/arch/x86/hvm/hpet.c
+++ b/xen/arch/x86/hvm/hpet.c
@@ -353,7 +353,8 @@ static void hpet_write(
static int hpet_range(struct vcpu *v, unsigned long addr)
{
- return ((addr >= HPET_BASE_ADDRESS) &&
+ return (v->domain->arch.hvm_domain.params[HVM_PARAM_HPET_ENABLED] &&
+ (addr >= HPET_BASE_ADDRESS) &&
(addr < (HPET_BASE_ADDRESS + HPET_MMAP_SIZE)));
}
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 14c965cef9..92a63bf325 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -232,6 +232,8 @@ int hvm_domain_initialise(struct domain *d)
spin_lock_init(&d->arch.hvm_domain.irq_lock);
spin_lock_init(&d->arch.hvm_domain.uc_lock);
+ d->arch.hvm_domain.params[HVM_PARAM_HPET_ENABLED] = 1;
+
hvm_init_cacheattr_region_list(d);
rc = paging_enable(d, PG_refcounts|PG_translate|PG_external);
@@ -285,9 +287,10 @@ static int hvm_save_cpu_ctxt(struct domain *d, hvm_domain_context_t *h)
{
struct vcpu *v;
struct hvm_hw_cpu ctxt;
+ struct segment_register seg;
struct vcpu_guest_context *vc;
- for_each_vcpu(d, v)
+ for_each_vcpu ( d, v )
{
/* We don't need to save state for a vcpu that is down; the restore
* code will leave it down if there is nothing saved. */
@@ -297,12 +300,69 @@ static int hvm_save_cpu_ctxt(struct domain *d, hvm_domain_context_t *h)
/* Architecture-specific vmcs/vmcb bits */
hvm_funcs.save_cpu_ctxt(v, &ctxt);
- /* Other vcpu register state */
+ hvm_get_segment_register(v, x86_seg_idtr, &seg);
+ ctxt.idtr_limit = seg.limit;
+ ctxt.idtr_base = seg.base;
+
+ hvm_get_segment_register(v, x86_seg_gdtr, &seg);
+ ctxt.gdtr_limit = seg.limit;
+ ctxt.gdtr_base = seg.base;
+
+ hvm_get_segment_register(v, x86_seg_cs, &seg);
+ ctxt.cs_sel = seg.sel;
+ ctxt.cs_limit = seg.limit;
+ ctxt.cs_base = seg.base;
+ ctxt.cs_arbytes = seg.attr.bytes;
+
+ hvm_get_segment_register(v, x86_seg_ds, &seg);
+ ctxt.ds_sel = seg.sel;
+ ctxt.ds_limit = seg.limit;
+ ctxt.ds_base = seg.base;
+ ctxt.ds_arbytes = seg.attr.bytes;
+
+ hvm_get_segment_register(v, x86_seg_es, &seg);
+ ctxt.es_sel = seg.sel;
+ ctxt.es_limit = seg.limit;
+ ctxt.es_base = seg.base;
+ ctxt.es_arbytes = seg.attr.bytes;
+
+ hvm_get_segment_register(v, x86_seg_ss, &seg);
+ ctxt.ss_sel = seg.sel;
+ ctxt.ss_limit = seg.limit;
+ ctxt.ss_base = seg.base;
+ ctxt.ss_arbytes = seg.attr.bytes;
+
+ hvm_get_segment_register(v, x86_seg_fs, &seg);
+ ctxt.fs_sel = seg.sel;
+ ctxt.fs_limit = seg.limit;
+ ctxt.fs_base = seg.base;
+ ctxt.fs_arbytes = seg.attr.bytes;
+
+ hvm_get_segment_register(v, x86_seg_gs, &seg);
+ ctxt.gs_sel = seg.sel;
+ ctxt.gs_limit = seg.limit;
+ ctxt.gs_base = seg.base;
+ ctxt.gs_arbytes = seg.attr.bytes;
+
+ hvm_get_segment_register(v, x86_seg_tr, &seg);
+ ctxt.tr_sel = seg.sel;
+ ctxt.tr_limit = seg.limit;
+ ctxt.tr_base = seg.base;
+ ctxt.tr_arbytes = seg.attr.bytes;
+
+ hvm_get_segment_register(v, x86_seg_ldtr, &seg);
+ ctxt.ldtr_sel = seg.sel;
+ ctxt.ldtr_limit = seg.limit;
+ ctxt.ldtr_base = seg.base;
+ ctxt.ldtr_arbytes = seg.attr.bytes;
+
vc = &v->arch.guest_context;
+
if ( v->fpu_initialised )
memcpy(ctxt.fpu_regs, &vc->fpu_ctxt, sizeof(ctxt.fpu_regs));
else
memset(ctxt.fpu_regs, 0, sizeof(ctxt.fpu_regs));
+
ctxt.rax = vc->user_regs.eax;
ctxt.rbx = vc->user_regs.ebx;
ctxt.rcx = vc->user_regs.ecx;
@@ -341,6 +401,7 @@ static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h)
int vcpuid, rc;
struct vcpu *v;
struct hvm_hw_cpu ctxt;
+ struct segment_register seg;
struct vcpu_guest_context *vc;
/* Which vcpu is this? */
@@ -396,8 +457,64 @@ static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h)
if ( hvm_funcs.load_cpu_ctxt(v, &ctxt) < 0 )
return -EINVAL;
- /* Other vcpu register state */
+ seg.limit = ctxt.idtr_limit;
+ seg.base = ctxt.idtr_base;
+ hvm_set_segment_register(v, x86_seg_idtr, &seg);
+
+ seg.limit = ctxt.gdtr_limit;
+ seg.base = ctxt.gdtr_base;
+ hvm_set_segment_register(v, x86_seg_gdtr, &seg);
+
+ seg.sel = ctxt.cs_sel;
+ seg.limit = ctxt.cs_limit;
+ seg.base = ctxt.cs_base;
+ seg.attr.bytes = ctxt.cs_arbytes;
+ hvm_set_segment_register(v, x86_seg_cs, &seg);
+
+ seg.sel = ctxt.ds_sel;
+ seg.limit = ctxt.ds_limit;
+ seg.base = ctxt.ds_base;
+ seg.attr.bytes = ctxt.ds_arbytes;
+ hvm_set_segment_register(v, x86_seg_ds, &seg);
+
+ seg.sel = ctxt.es_sel;
+ seg.limit = ctxt.es_limit;
+ seg.base = ctxt.es_base;
+ seg.attr.bytes = ctxt.es_arbytes;
+ hvm_set_segment_register(v, x86_seg_es, &seg);
+
+ seg.sel = ctxt.ss_sel;
+ seg.limit = ctxt.ss_limit;
+ seg.base = ctxt.ss_base;
+ seg.attr.bytes = ctxt.ss_arbytes;
+ hvm_set_segment_register(v, x86_seg_ss, &seg);
+
+ seg.sel = ctxt.fs_sel;
+ seg.limit = ctxt.fs_limit;
+ seg.base = ctxt.fs_base;
+ seg.attr.bytes = ctxt.fs_arbytes;
+ hvm_set_segment_register(v, x86_seg_fs, &seg);
+
+ seg.sel = ctxt.gs_sel;
+ seg.limit = ctxt.gs_limit;
+ seg.base = ctxt.gs_base;
+ seg.attr.bytes = ctxt.gs_arbytes;
+ hvm_set_segment_register(v, x86_seg_gs, &seg);
+
+ seg.sel = ctxt.tr_sel;
+ seg.limit = ctxt.tr_limit;
+ seg.base = ctxt.tr_base;
+ seg.attr.bytes = ctxt.tr_arbytes;
+ hvm_set_segment_register(v, x86_seg_tr, &seg);
+
+ seg.sel = ctxt.ldtr_sel;
+ seg.limit = ctxt.ldtr_limit;
+ seg.base = ctxt.ldtr_base;
+ seg.attr.bytes = ctxt.ldtr_arbytes;
+ hvm_set_segment_register(v, x86_seg_ldtr, &seg);
+
memcpy(&vc->fpu_ctxt, ctxt.fpu_regs, sizeof(ctxt.fpu_regs));
+
vc->user_regs.eax = ctxt.rax;
vc->user_regs.ebx = ctxt.rbx;
vc->user_regs.ecx = ctxt.rcx;
@@ -1269,6 +1386,7 @@ void hvm_task_switch(
static enum hvm_copy_result __hvm_copy(
void *buf, paddr_t addr, int size, int dir, int virt, int fetch)
{
+ struct vcpu *curr = current;
unsigned long gfn, mfn;
p2m_type_t p2mt;
char *p;
@@ -1277,12 +1395,22 @@ static enum hvm_copy_result __hvm_copy(
if ( virt )
{
- struct segment_register sreg;
- hvm_get_segment_register(current, x86_seg_ss, &sreg);
- if ( sreg.attr.fields.dpl == 3 )
- pfec |= PFEC_user_mode;
+ /*
+ * We cannot use hvm_get_segment_register() while executing in
+ * vmx_realmode() as segment register state is cached. Furthermore,
+ * VMREADs on every data access hurts emulation performance.
+ */
+ if ( !curr->arch.hvm_vmx.vmxemul )
+ {
+ struct segment_register sreg;
+ hvm_get_segment_register(curr, x86_seg_ss, &sreg);
+ if ( sreg.attr.fields.dpl == 3 )
+ pfec |= PFEC_user_mode;
+ }
+
if ( dir )
pfec |= PFEC_write_access;
+
if ( fetch )
pfec |= PFEC_insn_fetch;
}
@@ -1294,7 +1422,7 @@ static enum hvm_copy_result __hvm_copy(
if ( virt )
{
- gfn = paging_gva_to_gfn(current, addr, &pfec);
+ gfn = paging_gva_to_gfn(curr, addr, &pfec);
if ( gfn == INVALID_GFN )
{
if ( virt == 2 ) /* 2 means generate a fault */
@@ -1318,7 +1446,7 @@ static enum hvm_copy_result __hvm_copy(
if ( dir )
{
memcpy(p, buf, count); /* dir == TRUE: *to* guest */
- paging_mark_dirty(current->domain, mfn);
+ paging_mark_dirty(curr->domain, mfn);
}
else
memcpy(buf, p, count); /* dir == FALSE: *from guest */
diff --git a/xen/arch/x86/hvm/iommu.c b/xen/arch/x86/hvm/iommu.c
new file mode 100644
index 0000000000..30c92f42ea
--- /dev/null
+++ b/xen/arch/x86/hvm/iommu.c
@@ -0,0 +1,135 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <xen/init.h>
+#include <xen/irq.h>
+#include <xen/spinlock.h>
+#include <xen/sched.h>
+#include <xen/xmalloc.h>
+#include <xen/domain_page.h>
+#include <asm/delay.h>
+#include <asm/string.h>
+#include <asm/mm.h>
+#include <asm/iommu.h>
+#include <asm/hvm/vmx/intel-iommu.h>
+
+extern struct iommu_ops intel_iommu_ops;
+extern struct iommu_ops amd_iommu_ops;
+
+int iommu_domain_init(struct domain *domain)
+{
+ struct hvm_iommu *hd = domain_hvm_iommu(domain);
+
+ spin_lock_init(&hd->mapping_lock);
+ spin_lock_init(&hd->iommu_list_lock);
+ INIT_LIST_HEAD(&hd->pdev_list);
+ INIT_LIST_HEAD(&hd->g2m_ioport_list);
+
+ if ( !iommu_enabled )
+ return 0;
+
+ switch ( boot_cpu_data.x86_vendor )
+ {
+ case X86_VENDOR_INTEL:
+ hd->platform_ops = &intel_iommu_ops;
+ break;
+ case X86_VENDOR_AMD:
+ hd->platform_ops = &amd_iommu_ops;
+ break;
+ default:
+ BUG();
+ }
+
+ return hd->platform_ops->init(domain);
+}
+
+int assign_device(struct domain *d, u8 bus, u8 devfn)
+{
+ struct hvm_iommu *hd = domain_hvm_iommu(d);
+
+ if ( !iommu_enabled || !hd->platform_ops)
+ return 0;
+
+ return hd->platform_ops->assign_device(d, bus, devfn);
+}
+
+void iommu_domain_destroy(struct domain *d)
+{
+ struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
+ uint32_t i;
+ struct hvm_iommu *hd = domain_hvm_iommu(d);
+ struct list_head *ioport_list, *digl_list, *tmp;
+ struct g2m_ioport *ioport;
+ struct dev_intx_gsi_link *digl;
+
+ if ( !iommu_enabled || !hd->platform_ops)
+ return;
+
+ if ( hvm_irq_dpci != NULL )
+ {
+ for ( i = 0; i < NR_IRQS; i++ )
+ {
+ if ( !hvm_irq_dpci->mirq[i].valid )
+ continue;
+
+ pirq_guest_unbind(d, i);
+ kill_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(i)]);
+
+ list_for_each_safe ( digl_list, tmp,
+ &hvm_irq_dpci->mirq[i].digl_list )
+ {
+ digl = list_entry(digl_list,
+ struct dev_intx_gsi_link, list);
+ list_del(&digl->list);
+ xfree(digl);
+ }
+ }
+
+ d->arch.hvm_domain.irq.dpci = NULL;
+ xfree(hvm_irq_dpci);
+ }
+
+ if ( hd )
+ {
+ list_for_each_safe ( ioport_list, tmp, &hd->g2m_ioport_list )
+ {
+ ioport = list_entry(ioport_list, struct g2m_ioport, list);
+ list_del(&ioport->list);
+ xfree(ioport);
+ }
+ }
+
+ return hd->platform_ops->teardown(d);
+}
+
+int iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn)
+{
+ struct hvm_iommu *hd = domain_hvm_iommu(d);
+
+ if ( !iommu_enabled || !hd->platform_ops)
+ return 0;
+
+ return hd->platform_ops->map_page(d, gfn, mfn);
+}
+
+int iommu_unmap_page(struct domain *d, unsigned long gfn)
+{
+ struct hvm_iommu *hd = domain_hvm_iommu(d);
+
+ if ( !iommu_enabled || !hd->platform_ops)
+ return 0;
+
+ return hd->platform_ops->unmap_page(d, gfn);
+}
diff --git a/xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-detect.c b/xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-detect.c
index 032ac0028d..c94be5f95d 100644
--- a/xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-detect.c
+++ b/xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-detect.c
@@ -89,12 +89,14 @@ int __init get_iommu_capabilities(u8 bus, u8 dev, u8 func, u8 cap_ptr,
u32 cap_header, cap_range;
u64 mmio_bar;
+#if HACK_BIOS_SETTINGS
/* remove it when BIOS available */
write_pci_config(bus, dev, func,
cap_ptr + PCI_CAP_MMIO_BAR_HIGH_OFFSET, 0x00000000);
write_pci_config(bus, dev, func,
cap_ptr + PCI_CAP_MMIO_BAR_LOW_OFFSET, 0x40000001);
/* remove it when BIOS available */
+#endif
mmio_bar = (u64)read_pci_config(bus, dev, func,
cap_ptr + PCI_CAP_MMIO_BAR_HIGH_OFFSET) << 32;
diff --git a/xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-map.c b/xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-map.c
index cd98ad0c87..7bdd289ca2 100644
--- a/xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-map.c
+++ b/xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-map.c
@@ -30,22 +30,20 @@ static int queue_iommu_command(struct amd_iommu *iommu, u32 cmd[])
u32 tail, head, *cmd_buffer;
int i;
- BUG_ON( !iommu || !cmd );
-
tail = iommu->cmd_buffer_tail;
- if ( ++tail == iommu->cmd_buffer.entries ) {
+ if ( ++tail == iommu->cmd_buffer.entries )
tail = 0;
- }
head = get_field_from_reg_u32(
- readl(iommu->mmio_base+IOMMU_CMD_BUFFER_HEAD_OFFSET),
- IOMMU_CMD_BUFFER_HEAD_MASK,
- IOMMU_CMD_BUFFER_HEAD_SHIFT);
- if ( head != tail ) {
+ readl(iommu->mmio_base+IOMMU_CMD_BUFFER_HEAD_OFFSET),
+ IOMMU_CMD_BUFFER_HEAD_MASK,
+ IOMMU_CMD_BUFFER_HEAD_SHIFT);
+ if ( head != tail )
+ {
cmd_buffer = (u32 *)(iommu->cmd_buffer.buffer +
- (iommu->cmd_buffer_tail * IOMMU_CMD_BUFFER_ENTRY_SIZE));
- for ( i = 0; i < IOMMU_CMD_BUFFER_U32_PER_ENTRY; ++i ) {
+ (iommu->cmd_buffer_tail *
+ IOMMU_CMD_BUFFER_ENTRY_SIZE));
+ for ( i = 0; i < IOMMU_CMD_BUFFER_U32_PER_ENTRY; i++ )
cmd_buffer[i] = cmd[i];
- }
iommu->cmd_buffer_tail = tail;
return 1;
@@ -58,27 +56,25 @@ static void commit_iommu_command_buffer(struct amd_iommu *iommu)
{
u32 tail;
- BUG_ON( !iommu );
-
set_field_in_reg_u32(iommu->cmd_buffer_tail, 0,
- IOMMU_CMD_BUFFER_TAIL_MASK,
- IOMMU_CMD_BUFFER_TAIL_SHIFT, &tail);
+ IOMMU_CMD_BUFFER_TAIL_MASK,
+ IOMMU_CMD_BUFFER_TAIL_SHIFT, &tail);
writel(tail, iommu->mmio_base+IOMMU_CMD_BUFFER_TAIL_OFFSET);
}
int send_iommu_command(struct amd_iommu *iommu, u32 cmd[])
{
- BUG_ON( !iommu || !cmd );
-
- if ( queue_iommu_command(iommu, cmd) ) {
+ if ( queue_iommu_command(iommu, cmd) )
+ {
commit_iommu_command_buffer(iommu);
return 1;
}
+
return 0;
}
static void invalidate_iommu_page(struct amd_iommu *iommu,
- u64 io_addr, u16 domain_id)
+ u64 io_addr, u16 domain_id)
{
u64 addr_lo, addr_hi;
u32 cmd[4], entry;
@@ -87,51 +83,52 @@ static void invalidate_iommu_page(struct amd_iommu *iommu,
addr_hi = io_addr >> 32;
set_field_in_reg_u32(domain_id, 0,
- IOMMU_INV_IOMMU_PAGES_DOMAIN_ID_MASK,
- IOMMU_INV_IOMMU_PAGES_DOMAIN_ID_SHIFT, &entry);
+ IOMMU_INV_IOMMU_PAGES_DOMAIN_ID_MASK,
+ IOMMU_INV_IOMMU_PAGES_DOMAIN_ID_SHIFT, &entry);
set_field_in_reg_u32(IOMMU_CMD_INVALIDATE_IOMMU_PAGES, entry,
- IOMMU_CMD_OPCODE_MASK, IOMMU_CMD_OPCODE_SHIFT, &entry);
+ IOMMU_CMD_OPCODE_MASK, IOMMU_CMD_OPCODE_SHIFT,
+ &entry);
cmd[1] = entry;
set_field_in_reg_u32(IOMMU_CONTROL_DISABLED, 0,
- IOMMU_INV_IOMMU_PAGES_S_FLAG_MASK,
- IOMMU_INV_IOMMU_PAGES_S_FLAG_SHIFT, &entry);
+ IOMMU_INV_IOMMU_PAGES_S_FLAG_MASK,
+ IOMMU_INV_IOMMU_PAGES_S_FLAG_SHIFT, &entry);
set_field_in_reg_u32(IOMMU_CONTROL_DISABLED, entry,
- IOMMU_INV_IOMMU_PAGES_PDE_FLAG_MASK,
- IOMMU_INV_IOMMU_PAGES_PDE_FLAG_SHIFT, &entry);
+ IOMMU_INV_IOMMU_PAGES_PDE_FLAG_MASK,
+ IOMMU_INV_IOMMU_PAGES_PDE_FLAG_SHIFT, &entry);
set_field_in_reg_u32((u32)addr_lo >> PAGE_SHIFT, entry,
- IOMMU_INV_IOMMU_PAGES_ADDR_LOW_MASK,
- IOMMU_INV_IOMMU_PAGES_ADDR_LOW_SHIFT, &entry);
+ IOMMU_INV_IOMMU_PAGES_ADDR_LOW_MASK,
+ IOMMU_INV_IOMMU_PAGES_ADDR_LOW_SHIFT, &entry);
cmd[2] = entry;
set_field_in_reg_u32((u32)addr_hi, 0,
- IOMMU_INV_IOMMU_PAGES_ADDR_HIGH_MASK,
- IOMMU_INV_IOMMU_PAGES_ADDR_HIGH_SHIFT, &entry);
+ IOMMU_INV_IOMMU_PAGES_ADDR_HIGH_MASK,
+ IOMMU_INV_IOMMU_PAGES_ADDR_HIGH_SHIFT, &entry);
cmd[3] = entry;
cmd[0] = 0;
send_iommu_command(iommu, cmd);
}
-static void flush_command_buffer(struct amd_iommu *iommu)
+void flush_command_buffer(struct amd_iommu *iommu)
{
u32 cmd[4], status;
int loop_count, comp_wait;
/* clear 'ComWaitInt' in status register (WIC) */
set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, 0,
- IOMMU_STATUS_COMP_WAIT_INT_MASK,
- IOMMU_STATUS_COMP_WAIT_INT_SHIFT, &status);
+ IOMMU_STATUS_COMP_WAIT_INT_MASK,
+ IOMMU_STATUS_COMP_WAIT_INT_SHIFT, &status);
writel(status, iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET);
/* send an empty COMPLETION_WAIT command to flush command buffer */
cmd[3] = cmd[2] = 0;
set_field_in_reg_u32(IOMMU_CMD_COMPLETION_WAIT, 0,
- IOMMU_CMD_OPCODE_MASK,
- IOMMU_CMD_OPCODE_SHIFT, &cmd[1]);
+ IOMMU_CMD_OPCODE_MASK,
+ IOMMU_CMD_OPCODE_SHIFT, &cmd[1]);
set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, 0,
- IOMMU_COMP_WAIT_I_FLAG_MASK,
- IOMMU_COMP_WAIT_I_FLAG_SHIFT, &cmd[0]);
+ IOMMU_COMP_WAIT_I_FLAG_MASK,
+ IOMMU_COMP_WAIT_I_FLAG_SHIFT, &cmd[0]);
send_iommu_command(iommu, cmd);
/* wait for 'ComWaitInt' to signal comp#endifletion? */
@@ -139,34 +136,36 @@ static void flush_command_buffer(struct amd_iommu *iommu)
loop_count = amd_iommu_poll_comp_wait;
do {
status = readl(iommu->mmio_base +
- IOMMU_STATUS_MMIO_OFFSET);
- comp_wait = get_field_from_reg_u32(status,
- IOMMU_STATUS_COMP_WAIT_INT_MASK,
- IOMMU_STATUS_COMP_WAIT_INT_SHIFT);
+ IOMMU_STATUS_MMIO_OFFSET);
+ comp_wait = get_field_from_reg_u32(
+ status,
+ IOMMU_STATUS_COMP_WAIT_INT_MASK,
+ IOMMU_STATUS_COMP_WAIT_INT_SHIFT);
--loop_count;
} while ( loop_count && !comp_wait );
- if ( comp_wait ) {
+ if ( comp_wait )
+ {
/* clear 'ComWaitInt' in status register (WIC) */
status &= IOMMU_STATUS_COMP_WAIT_INT_MASK;
writel(status, iommu->mmio_base +
- IOMMU_STATUS_MMIO_OFFSET);
- } else
- dprintk(XENLOG_WARNING, "AMD IOMMU: %s(): Warning:"
- " ComWaitInt bit did not assert!\n",
- __FUNCTION__);
+ IOMMU_STATUS_MMIO_OFFSET);
+ }
+ else
+ dprintk(XENLOG_WARNING, "AMD IOMMU: Warning:"
+ " ComWaitInt bit did not assert!\n");
}
}
static void clear_page_table_entry_present(u32 *pte)
{
set_field_in_reg_u32(IOMMU_CONTROL_DISABLED, pte[0],
- IOMMU_PTE_PRESENT_MASK,
- IOMMU_PTE_PRESENT_SHIFT, &pte[0]);
+ IOMMU_PTE_PRESENT_MASK,
+ IOMMU_PTE_PRESENT_SHIFT, &pte[0]);
}
static void set_page_table_entry_present(u32 *pte, u64 page_addr,
- int iw, int ir)
+ int iw, int ir)
{
u64 addr_lo, addr_hi;
u32 entry;
@@ -175,33 +174,33 @@ static void set_page_table_entry_present(u32 *pte, u64 page_addr,
addr_hi = page_addr >> 32;
set_field_in_reg_u32((u32)addr_hi, 0,
- IOMMU_PTE_ADDR_HIGH_MASK,
- IOMMU_PTE_ADDR_HIGH_SHIFT, &entry);
+ IOMMU_PTE_ADDR_HIGH_MASK,
+ IOMMU_PTE_ADDR_HIGH_SHIFT, &entry);
set_field_in_reg_u32(iw ? IOMMU_CONTROL_ENABLED :
- IOMMU_CONTROL_DISABLED, entry,
- IOMMU_PTE_IO_WRITE_PERMISSION_MASK,
- IOMMU_PTE_IO_WRITE_PERMISSION_SHIFT, &entry);
+ IOMMU_CONTROL_DISABLED, entry,
+ IOMMU_PTE_IO_WRITE_PERMISSION_MASK,
+ IOMMU_PTE_IO_WRITE_PERMISSION_SHIFT, &entry);
set_field_in_reg_u32(ir ? IOMMU_CONTROL_ENABLED :
- IOMMU_CONTROL_DISABLED, entry,
- IOMMU_PTE_IO_READ_PERMISSION_MASK,
- IOMMU_PTE_IO_READ_PERMISSION_SHIFT, &entry);
+ IOMMU_CONTROL_DISABLED, entry,
+ IOMMU_PTE_IO_READ_PERMISSION_MASK,
+ IOMMU_PTE_IO_READ_PERMISSION_SHIFT, &entry);
pte[1] = entry;
set_field_in_reg_u32((u32)addr_lo >> PAGE_SHIFT, 0,
- IOMMU_PTE_ADDR_LOW_MASK,
- IOMMU_PTE_ADDR_LOW_SHIFT, &entry);
+ IOMMU_PTE_ADDR_LOW_MASK,
+ IOMMU_PTE_ADDR_LOW_SHIFT, &entry);
set_field_in_reg_u32(IOMMU_PAGING_MODE_LEVEL_0, entry,
- IOMMU_PTE_NEXT_LEVEL_MASK,
- IOMMU_PTE_NEXT_LEVEL_SHIFT, &entry);
+ IOMMU_PTE_NEXT_LEVEL_MASK,
+ IOMMU_PTE_NEXT_LEVEL_SHIFT, &entry);
set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
- IOMMU_PTE_PRESENT_MASK,
- IOMMU_PTE_PRESENT_SHIFT, &entry);
+ IOMMU_PTE_PRESENT_MASK,
+ IOMMU_PTE_PRESENT_SHIFT, &entry);
pte[0] = entry;
}
static void amd_iommu_set_page_directory_entry(u32 *pde,
- u64 next_ptr, u8 next_level)
+ u64 next_ptr, u8 next_level)
{
u64 addr_lo, addr_hi;
u32 entry;
@@ -211,29 +210,31 @@ static void amd_iommu_set_page_directory_entry(u32 *pde,
/* enable read/write permissions,which will be enforced at the PTE */
set_field_in_reg_u32((u32)addr_hi, 0,
- IOMMU_PDE_ADDR_HIGH_MASK, IOMMU_PDE_ADDR_HIGH_SHIFT, &entry);
+ IOMMU_PDE_ADDR_HIGH_MASK,
+ IOMMU_PDE_ADDR_HIGH_SHIFT, &entry);
set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
- IOMMU_PDE_IO_WRITE_PERMISSION_MASK,
- IOMMU_PDE_IO_WRITE_PERMISSION_SHIFT, &entry);
+ IOMMU_PDE_IO_WRITE_PERMISSION_MASK,
+ IOMMU_PDE_IO_WRITE_PERMISSION_SHIFT, &entry);
set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
- IOMMU_PDE_IO_READ_PERMISSION_MASK,
- IOMMU_PDE_IO_READ_PERMISSION_SHIFT, &entry);
+ IOMMU_PDE_IO_READ_PERMISSION_MASK,
+ IOMMU_PDE_IO_READ_PERMISSION_SHIFT, &entry);
pde[1] = entry;
/* mark next level as 'present' */
set_field_in_reg_u32((u32)addr_lo >> PAGE_SHIFT, 0,
- IOMMU_PDE_ADDR_LOW_MASK, IOMMU_PDE_ADDR_LOW_SHIFT, &entry);
+ IOMMU_PDE_ADDR_LOW_MASK,
+ IOMMU_PDE_ADDR_LOW_SHIFT, &entry);
set_field_in_reg_u32(next_level, entry,
- IOMMU_PDE_NEXT_LEVEL_MASK,
- IOMMU_PDE_NEXT_LEVEL_SHIFT, &entry);
+ IOMMU_PDE_NEXT_LEVEL_MASK,
+ IOMMU_PDE_NEXT_LEVEL_SHIFT, &entry);
set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
- IOMMU_PDE_PRESENT_MASK,
- IOMMU_PDE_PRESENT_SHIFT, &entry);
+ IOMMU_PDE_PRESENT_MASK,
+ IOMMU_PDE_PRESENT_SHIFT, &entry);
pde[0] = entry;
}
void amd_iommu_set_dev_table_entry(u32 *dte, u64 root_ptr, u16 domain_id,
- u8 paging_mode)
+ u8 paging_mode)
{
u64 addr_hi, addr_lo;
u32 entry;
@@ -241,54 +242,56 @@ void amd_iommu_set_dev_table_entry(u32 *dte, u64 root_ptr, u16 domain_id,
dte[6] = dte[5] = dte[4] = 0;
set_field_in_reg_u32(IOMMU_DEV_TABLE_SYS_MGT_MSG_FORWARDED, 0,
- IOMMU_DEV_TABLE_SYS_MGT_MSG_ENABLE_MASK,
- IOMMU_DEV_TABLE_SYS_MGT_MSG_ENABLE_SHIFT, &entry);
+ IOMMU_DEV_TABLE_SYS_MGT_MSG_ENABLE_MASK,
+ IOMMU_DEV_TABLE_SYS_MGT_MSG_ENABLE_SHIFT, &entry);
dte[3] = entry;
set_field_in_reg_u32(domain_id, 0,
- IOMMU_DEV_TABLE_DOMAIN_ID_MASK,
- IOMMU_DEV_TABLE_DOMAIN_ID_SHIFT, &entry);
+ IOMMU_DEV_TABLE_DOMAIN_ID_MASK,
+ IOMMU_DEV_TABLE_DOMAIN_ID_SHIFT, &entry);
dte[2] = entry;
addr_lo = root_ptr & DMA_32BIT_MASK;
addr_hi = root_ptr >> 32;
set_field_in_reg_u32((u32)addr_hi, 0,
- IOMMU_DEV_TABLE_PAGE_TABLE_PTR_HIGH_MASK,
- IOMMU_DEV_TABLE_PAGE_TABLE_PTR_HIGH_SHIFT, &entry);
+ IOMMU_DEV_TABLE_PAGE_TABLE_PTR_HIGH_MASK,
+ IOMMU_DEV_TABLE_PAGE_TABLE_PTR_HIGH_SHIFT, &entry);
set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
- IOMMU_DEV_TABLE_IO_WRITE_PERMISSION_MASK,
- IOMMU_DEV_TABLE_IO_WRITE_PERMISSION_SHIFT, &entry);
+ IOMMU_DEV_TABLE_IO_WRITE_PERMISSION_MASK,
+ IOMMU_DEV_TABLE_IO_WRITE_PERMISSION_SHIFT, &entry);
set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
- IOMMU_DEV_TABLE_IO_READ_PERMISSION_MASK,
- IOMMU_DEV_TABLE_IO_READ_PERMISSION_SHIFT, &entry);
+ IOMMU_DEV_TABLE_IO_READ_PERMISSION_MASK,
+ IOMMU_DEV_TABLE_IO_READ_PERMISSION_SHIFT, &entry);
dte[1] = entry;
set_field_in_reg_u32((u32)addr_lo >> PAGE_SHIFT, 0,
- IOMMU_DEV_TABLE_PAGE_TABLE_PTR_LOW_MASK,
- IOMMU_DEV_TABLE_PAGE_TABLE_PTR_LOW_SHIFT, &entry);
+ IOMMU_DEV_TABLE_PAGE_TABLE_PTR_LOW_MASK,
+ IOMMU_DEV_TABLE_PAGE_TABLE_PTR_LOW_SHIFT, &entry);
set_field_in_reg_u32(paging_mode, entry,
- IOMMU_DEV_TABLE_PAGING_MODE_MASK,
- IOMMU_DEV_TABLE_PAGING_MODE_SHIFT, &entry);
+ IOMMU_DEV_TABLE_PAGING_MODE_MASK,
+ IOMMU_DEV_TABLE_PAGING_MODE_SHIFT, &entry);
set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
- IOMMU_DEV_TABLE_TRANSLATION_VALID_MASK,
- IOMMU_DEV_TABLE_TRANSLATION_VALID_SHIFT, &entry);
+ IOMMU_DEV_TABLE_TRANSLATION_VALID_MASK,
+ IOMMU_DEV_TABLE_TRANSLATION_VALID_SHIFT, &entry);
set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
- IOMMU_DEV_TABLE_VALID_MASK,
- IOMMU_DEV_TABLE_VALID_SHIFT, &entry);
+ IOMMU_DEV_TABLE_VALID_MASK,
+ IOMMU_DEV_TABLE_VALID_SHIFT, &entry);
dte[0] = entry;
}
-static void *amd_iommu_get_vptr_from_page_table_entry(u32 *entry)
+void *amd_iommu_get_vptr_from_page_table_entry(u32 *entry)
{
u64 addr_lo, addr_hi, ptr;
- addr_lo = get_field_from_reg_u32(entry[0],
- IOMMU_DEV_TABLE_PAGE_TABLE_PTR_LOW_MASK,
- IOMMU_DEV_TABLE_PAGE_TABLE_PTR_LOW_SHIFT);
+ addr_lo = get_field_from_reg_u32(
+ entry[0],
+ IOMMU_DEV_TABLE_PAGE_TABLE_PTR_LOW_MASK,
+ IOMMU_DEV_TABLE_PAGE_TABLE_PTR_LOW_SHIFT);
- addr_hi = get_field_from_reg_u32(entry[1],
- IOMMU_DEV_TABLE_PAGE_TABLE_PTR_HIGH_MASK,
- IOMMU_DEV_TABLE_PAGE_TABLE_PTR_HIGH_SHIFT);
+ addr_hi = get_field_from_reg_u32(
+ entry[1],
+ IOMMU_DEV_TABLE_PAGE_TABLE_PTR_HIGH_MASK,
+ IOMMU_DEV_TABLE_PAGE_TABLE_PTR_HIGH_SHIFT);
ptr = (addr_hi << 32) | (addr_lo << PAGE_SHIFT);
return ptr ? maddr_to_virt((unsigned long)ptr) : NULL;
@@ -297,42 +300,74 @@ static void *amd_iommu_get_vptr_from_page_table_entry(u32 *entry)
static int amd_iommu_is_pte_present(u32 *entry)
{
return (get_field_from_reg_u32(entry[0],
- IOMMU_PDE_PRESENT_MASK,
- IOMMU_PDE_PRESENT_SHIFT));
+ IOMMU_PDE_PRESENT_MASK,
+ IOMMU_PDE_PRESENT_SHIFT));
+}
+
+void invalidate_dev_table_entry(struct amd_iommu *iommu,
+ u16 device_id)
+{
+ u32 cmd[4], entry;
+
+ cmd[3] = cmd[2] = 0;
+ set_field_in_reg_u32(device_id, 0,
+ IOMMU_INV_DEVTAB_ENTRY_DEVICE_ID_MASK,
+ IOMMU_INV_DEVTAB_ENTRY_DEVICE_ID_SHIFT, &entry);
+ cmd[0] = entry;
+
+ set_field_in_reg_u32(IOMMU_CMD_INVALIDATE_DEVTAB_ENTRY, 0,
+ IOMMU_CMD_OPCODE_MASK, IOMMU_CMD_OPCODE_SHIFT,
+ &entry);
+ cmd[1] = entry;
+
+ send_iommu_command(iommu, cmd);
+}
+
+int amd_iommu_is_dte_page_translation_valid(u32 *entry)
+{
+ return (get_field_from_reg_u32(entry[0],
+ IOMMU_DEV_TABLE_VALID_MASK,
+ IOMMU_DEV_TABLE_VALID_SHIFT) &&
+ get_field_from_reg_u32(entry[0],
+ IOMMU_DEV_TABLE_TRANSLATION_VALID_MASK,
+ IOMMU_DEV_TABLE_TRANSLATION_VALID_SHIFT));
}
static void *get_pte_from_page_tables(void *table, int level,
- unsigned long io_pfn)
+ unsigned long io_pfn)
{
unsigned long offset;
- void *pde = 0;
+ void *pde = NULL;
- BUG_ON( !table );
+ BUG_ON(table == NULL);
while ( level > 0 )
{
- void *next_table = 0;
- unsigned long next_ptr;
offset = io_pfn >> ((PTE_PER_TABLE_SHIFT *
- (level - IOMMU_PAGING_MODE_LEVEL_1)));
+ (level - IOMMU_PAGING_MODE_LEVEL_1)));
offset &= ~PTE_PER_TABLE_MASK;
pde = table + (offset * IOMMU_PAGE_TABLE_ENTRY_SIZE);
if ( level == 1 )
break;
if ( !pde )
- return NULL;
- if ( !amd_iommu_is_pte_present(pde) ) {
- next_table = alloc_xenheap_page();
+ return NULL;
+ if ( !amd_iommu_is_pte_present(pde) )
+ {
+ void *next_table = alloc_xenheap_page();
if ( next_table == NULL )
return NULL;
memset(next_table, 0, PAGE_SIZE);
- if ( *(u64*)(pde) == 0 ) {
- next_ptr = (u64)virt_to_maddr(next_table);
- amd_iommu_set_page_directory_entry((u32 *)pde,
- next_ptr, level - 1);
- } else
+ if ( *(u64 *)pde == 0 )
+ {
+ unsigned long next_ptr = (u64)virt_to_maddr(next_table);
+ amd_iommu_set_page_directory_entry(
+ (u32 *)pde, next_ptr, level - 1);
+ }
+ else
+ {
free_xenheap_page(next_table);
+ }
}
table = amd_iommu_get_vptr_from_page_table_entry(pde);
level--;
@@ -341,8 +376,7 @@ static void *get_pte_from_page_tables(void *table, int level,
return pde;
}
-int amd_iommu_map_page(struct domain *d, unsigned long gfn,
- unsigned long mfn)
+int amd_iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn)
{
void *pte;
unsigned long flags;
@@ -352,7 +386,7 @@ int amd_iommu_map_page(struct domain *d, unsigned long gfn,
BUG_ON( !hd->root_table );
- maddr = (u64)(mfn << PAGE_SHIFT);
+ maddr = (u64)mfn << PAGE_SHIFT;
iw = IOMMU_IO_WRITE_ENABLED;
ir = IOMMU_IO_READ_ENABLED;
@@ -360,18 +394,18 @@ int amd_iommu_map_page(struct domain *d, unsigned long gfn,
spin_lock_irqsave(&hd->mapping_lock, flags);
pte = get_pte_from_page_tables(hd->root_table, hd->paging_mode, gfn);
-
- if ( pte != 0 ) {
- set_page_table_entry_present((u32 *)pte, maddr, iw, ir);
- spin_unlock_irqrestore(&hd->mapping_lock, flags);
- return 0;
- } else {
+ if ( pte == 0 )
+ {
dprintk(XENLOG_ERR,
- "%s() AMD IOMMU: Invalid IO pagetable entry gfn = %lx\n",
- __FUNCTION__, gfn);
+ "AMD IOMMU: Invalid IO pagetable entry gfn = %lx\n", gfn);
spin_unlock_irqrestore(&hd->mapping_lock, flags);
return -EIO;
}
+
+ set_page_table_entry_present((u32 *)pte, maddr, iw, ir);
+
+ spin_unlock_irqrestore(&hd->mapping_lock, flags);
+ return 0;
}
int amd_iommu_unmap_page(struct domain *d, unsigned long gfn)
@@ -386,34 +420,31 @@ int amd_iommu_unmap_page(struct domain *d, unsigned long gfn)
BUG_ON( !hd->root_table );
requestor_id = hd->domain_id;
- io_addr = (u64)(gfn << PAGE_SHIFT);
+ io_addr = (u64)gfn << PAGE_SHIFT;
spin_lock_irqsave(&hd->mapping_lock, flags);
pte = get_pte_from_page_tables(hd->root_table, hd->paging_mode, gfn);
-
- if ( pte != 0 ) {
- /* mark PTE as 'page not present' */
- clear_page_table_entry_present((u32 *)pte);
- spin_unlock_irqrestore(&hd->mapping_lock, flags);
-
- /* send INVALIDATE_IOMMU_PAGES command */
- for_each_amd_iommu(iommu) {
-
- spin_lock_irqsave(&iommu->lock, flags);
-
- invalidate_iommu_page(iommu, io_addr, requestor_id);
- flush_command_buffer(iommu);
-
- spin_unlock_irqrestore(&iommu->lock, flags);
- }
-
- return 0;
- } else {
+ if ( pte == 0 )
+ {
dprintk(XENLOG_ERR,
- "%s() AMD IOMMU: Invalid IO pagetable entry gfn = %lx\n",
- __FUNCTION__, gfn);
+ "AMD IOMMU: Invalid IO pagetable entry gfn = %lx\n", gfn);
spin_unlock_irqrestore(&hd->mapping_lock, flags);
return -EIO;
}
+
+ /* mark PTE as 'page not present' */
+ clear_page_table_entry_present((u32 *)pte);
+ spin_unlock_irqrestore(&hd->mapping_lock, flags);
+
+ /* send INVALIDATE_IOMMU_PAGES command */
+ for_each_amd_iommu(iommu)
+ {
+ spin_lock_irqsave(&iommu->lock, flags);
+ invalidate_iommu_page(iommu, io_addr, requestor_id);
+ flush_command_buffer(iommu);
+ spin_unlock_irqrestore(&iommu->lock, flags);
+ }
+
+ return 0;
}
diff --git a/xen/arch/x86/hvm/svm/amd_iommu/pci-amd-iommu.c b/xen/arch/x86/hvm/svm/amd_iommu/pci-amd-iommu.c
index 8b99a78257..7caa276f73 100644
--- a/xen/arch/x86/hvm/svm/amd_iommu/pci-amd-iommu.c
+++ b/xen/arch/x86/hvm/svm/amd_iommu/pci-amd-iommu.c
@@ -51,19 +51,17 @@ static void __init init_cleanup(void)
{
struct amd_iommu *iommu;
- dprintk(XENLOG_ERR, "AMD IOMMU: %s()\n", __FUNCTION__);
-
- for_each_amd_iommu(iommu) {
+ for_each_amd_iommu ( iommu )
unmap_iommu_mmio_region(iommu);
- }
}
static void __init deallocate_iommu_table_struct(
- struct table_struct *table)
+ struct table_struct *table)
{
- if (table->buffer) {
+ if ( table->buffer )
+ {
free_xenheap_pages(table->buffer,
- get_order_from_bytes(table->alloc_size));
+ get_order_from_bytes(table->alloc_size));
table->buffer = NULL;
}
}
@@ -76,11 +74,10 @@ static void __init deallocate_iommu_resources(struct amd_iommu *iommu)
static void __init detect_cleanup(void)
{
- struct amd_iommu *iommu;
+ struct amd_iommu *iommu, *next;
- dprintk(XENLOG_ERR, "AMD IOMMU: %s()\n", __FUNCTION__);
-
- for_each_amd_iommu(iommu) {
+ list_for_each_entry_safe ( iommu, next, &amd_iommu_head, list )
+ {
list_del(&iommu->list);
deallocate_iommu_resources(iommu);
xfree(iommu);
@@ -91,19 +88,21 @@ static int requestor_id_from_bdf(int bdf)
{
/* HACK - HACK */
/* account for possible 'aliasing' by parent device */
- return bdf;
+ return bdf;
}
static int __init allocate_iommu_table_struct(struct table_struct *table,
- const char *name)
+ const char *name)
{
table->buffer = (void *) alloc_xenheap_pages(
get_order_from_bytes(table->alloc_size));
- if ( !table->buffer ) {
+ if ( !table->buffer )
+ {
dprintk(XENLOG_ERR, "AMD IOMMU: Error allocating %s\n", name);
return -ENOMEM;
}
+
memset(table->buffer, 0, table->alloc_size);
return 0;
@@ -114,32 +113,32 @@ static int __init allocate_iommu_resources(struct amd_iommu *iommu)
/* allocate 'device table' on a 4K boundary */
iommu->dev_table.alloc_size =
PAGE_ALIGN(((iommu->last_downstream_bus + 1) *
- IOMMU_DEV_TABLE_ENTRIES_PER_BUS) *
- IOMMU_DEV_TABLE_ENTRY_SIZE);
+ IOMMU_DEV_TABLE_ENTRIES_PER_BUS) *
+ IOMMU_DEV_TABLE_ENTRY_SIZE);
iommu->dev_table.entries =
iommu->dev_table.alloc_size / IOMMU_DEV_TABLE_ENTRY_SIZE;
- if (allocate_iommu_table_struct(&iommu->dev_table,
- "Device Table") != 0)
+ if ( allocate_iommu_table_struct(&iommu->dev_table,
+ "Device Table") != 0 )
goto error_out;
/* allocate 'command buffer' in power of 2 increments of 4K */
iommu->cmd_buffer_tail = 0;
iommu->cmd_buffer.alloc_size =
PAGE_SIZE << get_order_from_bytes(
- PAGE_ALIGN(amd_iommu_cmd_buffer_entries *
- IOMMU_CMD_BUFFER_ENTRY_SIZE));
+ PAGE_ALIGN(amd_iommu_cmd_buffer_entries *
+ IOMMU_CMD_BUFFER_ENTRY_SIZE));
- iommu->cmd_buffer.entries =
+ iommu->cmd_buffer.entries =
iommu->cmd_buffer.alloc_size / IOMMU_CMD_BUFFER_ENTRY_SIZE;
if ( allocate_iommu_table_struct(&iommu->cmd_buffer,
- "Command Buffer") != 0 )
+ "Command Buffer") != 0 )
goto error_out;
return 0;
-error_out:
+ error_out:
deallocate_iommu_resources(iommu);
return -ENOMEM;
}
@@ -149,7 +148,8 @@ int iommu_detect_callback(u8 bus, u8 dev, u8 func, u8 cap_ptr)
struct amd_iommu *iommu;
iommu = (struct amd_iommu *) xmalloc(struct amd_iommu);
- if ( !iommu ) {
+ if ( !iommu )
+ {
dprintk(XENLOG_ERR, "AMD IOMMU: Error allocating amd_iommu\n");
return -ENOMEM;
}
@@ -170,7 +170,7 @@ int iommu_detect_callback(u8 bus, u8 dev, u8 func, u8 cap_ptr)
return 0;
-error_out:
+ error_out:
xfree(iommu);
return -ENODEV;
}
@@ -180,11 +180,12 @@ static int __init amd_iommu_init(void)
struct amd_iommu *iommu;
unsigned long flags;
- for_each_amd_iommu(iommu) {
+ for_each_amd_iommu ( iommu )
+ {
spin_lock_irqsave(&iommu->lock, flags);
/* register IOMMU data strucures in MMIO space */
- if (map_iommu_mmio_region(iommu) != 0)
+ if ( map_iommu_mmio_region(iommu) != 0 )
goto error_out;
register_iommu_dev_table_in_mmio_space(iommu);
register_iommu_cmd_buffer_in_mmio_space(iommu);
@@ -200,7 +201,7 @@ static int __init amd_iommu_init(void)
return 0;
-error_out:
+ error_out:
init_cleanup();
return -ENODEV;
}
@@ -209,13 +210,16 @@ struct amd_iommu *find_iommu_for_device(int bus, int devfn)
{
struct amd_iommu *iommu;
- for_each_amd_iommu(iommu) {
- if ( bus == iommu->root_bus ) {
- if ( devfn >= iommu->first_devfn &&
- devfn <= iommu->last_devfn )
+ for_each_amd_iommu ( iommu )
+ {
+ if ( bus == iommu->root_bus )
+ {
+ if ( (devfn >= iommu->first_devfn) &&
+ (devfn <= iommu->last_devfn) )
return iommu;
}
- else if ( bus <= iommu->last_downstream_bus ) {
+ else if ( bus <= iommu->last_downstream_bus )
+ {
if ( iommu->downstream_bus_present[bus] )
return iommu;
}
@@ -238,16 +242,21 @@ void amd_iommu_setup_domain_device(
dte = iommu->dev_table.buffer +
(requestor_id * IOMMU_DEV_TABLE_ENTRY_SIZE);
- spin_lock_irqsave(&iommu->lock, flags);
+ if ( !amd_iommu_is_dte_page_translation_valid((u32 *)dte) )
+ {
+ spin_lock_irqsave(&iommu->lock, flags);
- amd_iommu_set_dev_table_entry((u32 *)dte,
- root_ptr, hd->domain_id, hd->paging_mode);
+ amd_iommu_set_dev_table_entry(
+ (u32 *)dte,
+ root_ptr, hd->domain_id, hd->paging_mode);
+ invalidate_dev_table_entry(iommu, requestor_id);
+ flush_command_buffer(iommu);
+ dprintk(XENLOG_INFO, "AMD IOMMU: Set DTE req_id:%x, "
+ "root_ptr:%"PRIx64", domain_id:%d, paging_mode:%d\n",
+ requestor_id, root_ptr, hd->domain_id, hd->paging_mode);
- dprintk(XENLOG_INFO, "AMD IOMMU: Set DTE req_id:%x, "
- "root_ptr:%"PRIx64", domain_id:%d, paging_mode:%d\n",
- requestor_id, root_ptr, hd->domain_id, hd->paging_mode);
-
- spin_unlock_irqrestore(&iommu->lock, flags);
+ spin_unlock_irqrestore(&iommu->lock, flags);
+ }
}
void __init amd_iommu_setup_dom0_devices(void)
@@ -259,13 +268,16 @@ void __init amd_iommu_setup_dom0_devices(void)
u32 l;
int req_id, bdf;
- for ( bus = 0; bus < 256; bus++ ) {
- for ( dev = 0; dev < 32; dev++ ) {
- for ( func = 0; func < 8; func++ ) {
+ for ( bus = 0; bus < 256; bus++ )
+ {
+ for ( dev = 0; dev < 32; dev++ )
+ {
+ for ( func = 0; func < 8; func++ )
+ {
l = read_pci_config(bus, dev, func, PCI_VENDOR_ID);
/* some broken boards return 0 or ~0 if a slot is empty: */
if ( l == 0xffffffff || l == 0x00000000 ||
- l == 0x0000ffff || l == 0xffff0000 )
+ l == 0x0000ffff || l == 0xffff0000 )
continue;
pdev = xmalloc(struct pci_dev);
@@ -288,29 +300,33 @@ int amd_iommu_detect(void)
{
unsigned long i;
- if ( !enable_amd_iommu ) {
+ if ( !enable_amd_iommu )
+ {
printk("AMD IOMMU: Disabled\n");
return 0;
}
INIT_LIST_HEAD(&amd_iommu_head);
- if ( scan_for_iommu(iommu_detect_callback) != 0 ) {
+ if ( scan_for_iommu(iommu_detect_callback) != 0 )
+ {
dprintk(XENLOG_ERR, "AMD IOMMU: Error detection\n");
goto error_out;
}
- if ( !iommu_found() ) {
+ if ( !iommu_found() )
+ {
printk("AMD IOMMU: Not found!\n");
return 0;
}
- if ( amd_iommu_init() != 0 ) {
+ if ( amd_iommu_init() != 0 )
+ {
dprintk(XENLOG_ERR, "AMD IOMMU: Error initialization\n");
goto error_out;
}
- if ( amd_iommu_domain_init(dom0) != 0 )
+ if ( iommu_domain_init(dom0) != 0 )
goto error_out;
/* setup 1:1 page table for dom0 */
@@ -320,21 +336,31 @@ int amd_iommu_detect(void)
amd_iommu_setup_dom0_devices();
return 0;
-error_out:
- detect_cleanup();
- return -ENODEV;
+ error_out:
+ detect_cleanup();
+ return -ENODEV;
}
static int allocate_domain_resources(struct hvm_iommu *hd)
{
/* allocate root table */
- hd->root_table = (void *)alloc_xenheap_page();
+ unsigned long flags;
+
+ spin_lock_irqsave(&hd->mapping_lock, flags);
if ( !hd->root_table )
- return -ENOMEM;
- memset((u8*)hd->root_table, 0, PAGE_SIZE);
+ {
+ hd->root_table = (void *)alloc_xenheap_page();
+ if ( !hd->root_table )
+ goto error_out;
+ memset((u8*)hd->root_table, 0, PAGE_SIZE);
+ }
+ spin_unlock_irqrestore(&hd->mapping_lock, flags);
return 0;
+ error_out:
+ spin_unlock_irqrestore(&hd->mapping_lock, flags);
+ return -ENOMEM;
}
static int get_paging_mode(unsigned long entries)
@@ -346,7 +372,8 @@ static int get_paging_mode(unsigned long entries)
if ( entries > max_page )
entries = max_page;
- while ( entries > PTE_PER_TABLE_SIZE ) {
+ while ( entries > PTE_PER_TABLE_SIZE )
+ {
entries = PTE_PER_TABLE_ALIGN(entries) >> PTE_PER_TABLE_SHIFT;
++level;
if ( level > 6 )
@@ -362,14 +389,11 @@ int amd_iommu_domain_init(struct domain *domain)
{
struct hvm_iommu *hd = domain_hvm_iommu(domain);
- spin_lock_init(&hd->mapping_lock);
- spin_lock_init(&hd->iommu_list_lock);
- INIT_LIST_HEAD(&hd->pdev_list);
-
/* allocate page directroy */
- if ( allocate_domain_resources(hd) != 0 ) {
- dprintk(XENLOG_ERR, "AMD IOMMU: %s()\n", __FUNCTION__);
- goto error_out;
+ if ( allocate_domain_resources(hd) != 0 )
+ {
+ deallocate_domain_resources(hd);
+ return -ENOMEM;
}
if ( is_hvm_domain(domain) )
@@ -380,10 +404,168 @@ int amd_iommu_domain_init(struct domain *domain)
hd->domain_id = domain->domain_id;
return 0;
+}
-error_out:
- deallocate_domain_resources(hd);
- return -ENOMEM;
+static void amd_iommu_disable_domain_device(
+ struct domain *domain, struct amd_iommu *iommu, u16 requestor_id)
+{
+ void *dte;
+ unsigned long flags;
+
+ dte = iommu->dev_table.buffer +
+ (requestor_id * IOMMU_DEV_TABLE_ENTRY_SIZE);
+
+ if ( amd_iommu_is_dte_page_translation_valid((u32 *)dte) )
+ {
+ spin_lock_irqsave(&iommu->lock, flags);
+ memset (dte, 0, IOMMU_DEV_TABLE_ENTRY_SIZE);
+ invalidate_dev_table_entry(iommu, requestor_id);
+ flush_command_buffer(iommu);
+ dprintk(XENLOG_INFO , "AMD IOMMU: disable DTE 0x%x,"
+ " domain_id:%d, paging_mode:%d\n",
+ requestor_id, domain_hvm_iommu(domain)->domain_id,
+ domain_hvm_iommu(domain)->paging_mode);
+ spin_unlock_irqrestore(&iommu->lock, flags);
+ }
+}
+
+extern void pdev_flr(u8 bus, u8 devfn);
+
+static int reassign_device( struct domain *source, struct domain *target,
+ u8 bus, u8 devfn)
+{
+ struct hvm_iommu *source_hd = domain_hvm_iommu(source);
+ struct hvm_iommu *target_hd = domain_hvm_iommu(target);
+ struct pci_dev *pdev;
+ struct amd_iommu *iommu;
+ int req_id, bdf;
+ unsigned long flags;
+
+ for_each_pdev( source, pdev )
+ {
+ if ( (pdev->bus != bus) || (pdev->devfn != devfn) )
+ continue;
+
+ pdev->bus = bus;
+ pdev->devfn = devfn;
+
+ bdf = (bus << 8) | devfn;
+ req_id = requestor_id_from_bdf(bdf);
+ iommu = find_iommu_for_device(bus, devfn);
+
+ if ( iommu )
+ {
+ amd_iommu_disable_domain_device(source, iommu, req_id);
+ /* Move pci device from the source domain to target domain. */
+ spin_lock_irqsave(&source_hd->iommu_list_lock, flags);
+ spin_lock_irqsave(&target_hd->iommu_list_lock, flags);
+ list_move(&pdev->list, &target_hd->pdev_list);
+ spin_unlock_irqrestore(&target_hd->iommu_list_lock, flags);
+ spin_unlock_irqrestore(&source_hd->iommu_list_lock, flags);
+
+ amd_iommu_setup_domain_device(target, iommu, req_id);
+ gdprintk(XENLOG_INFO ,
+ "AMD IOMMU: reassign %x:%x.%x domain %d -> domain %d\n",
+ bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
+ source->domain_id, target->domain_id);
+ }
+ else
+ {
+ gdprintk(XENLOG_ERR , "AMD IOMMU: fail to find iommu."
+ " %x:%x.%x cannot be assigned to domain %d\n",
+ bus, PCI_SLOT(devfn), PCI_FUNC(devfn), target->domain_id);
+ return -ENODEV;
+ }
+
+ break;
+ }
+ return 0;
+}
+
+int amd_iommu_assign_device(struct domain *d, u8 bus, u8 devfn)
+{
+ pdev_flr(bus, devfn);
+ return reassign_device(dom0, d, bus, devfn);
}
+static void release_domain_devices(struct domain *d)
+{
+ struct hvm_iommu *hd = domain_hvm_iommu(d);
+ struct pci_dev *pdev;
+
+ while ( !list_empty(&hd->pdev_list) )
+ {
+ pdev = list_entry(hd->pdev_list.next, typeof(*pdev), list);
+ pdev_flr(pdev->bus, pdev->devfn);
+ gdprintk(XENLOG_INFO ,
+ "AMD IOMMU: release devices %x:%x.%x\n",
+ pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+ reassign_device(d, dom0, pdev->bus, pdev->devfn);
+ }
+}
+
+static void deallocate_next_page_table(void *table, unsigned long index,
+ int level)
+{
+ unsigned long next_index;
+ void *next_table, *pde;
+ int next_level;
+
+ pde = table + (index * IOMMU_PAGE_TABLE_ENTRY_SIZE);
+ next_table = amd_iommu_get_vptr_from_page_table_entry((u32 *)pde);
+
+ if ( next_table )
+ {
+ next_level = level - 1;
+ if ( next_level > 1 )
+ {
+ next_index = 0;
+ do
+ {
+ deallocate_next_page_table(next_table,
+ next_index, next_level);
+ ++next_index;
+ } while (next_index < PTE_PER_TABLE_SIZE);
+ }
+
+ free_xenheap_page(next_table);
+ }
+}
+
+static void deallocate_iommu_page_tables(struct domain *d)
+{
+ unsigned long index;
+ struct hvm_iommu *hd = domain_hvm_iommu(d);
+
+ if ( hd ->root_table )
+ {
+ index = 0;
+ do
+ {
+ deallocate_next_page_table(hd->root_table,
+ index, hd->paging_mode);
+ ++index;
+ } while ( index < PTE_PER_TABLE_SIZE );
+
+ free_xenheap_page(hd ->root_table);
+ }
+
+ hd ->root_table = NULL;
+}
+
+void amd_iommu_domain_destroy(struct domain *d)
+{
+ if ( !amd_iommu_enabled )
+ return;
+
+ deallocate_iommu_page_tables(d);
+ release_domain_devices(d);
+}
+struct iommu_ops amd_iommu_ops = {
+ .init = amd_iommu_domain_init,
+ .assign_device = amd_iommu_assign_device,
+ .teardown = amd_iommu_domain_destroy,
+ .map_page = amd_iommu_map_page,
+ .unmap_page = amd_iommu_unmap_page,
+};
diff --git a/xen/arch/x86/hvm/svm/intr.c b/xen/arch/x86/hvm/svm/intr.c
index d2ba799a42..17a9c3bc7b 100644
--- a/xen/arch/x86/hvm/svm/intr.c
+++ b/xen/arch/x86/hvm/svm/intr.c
@@ -94,6 +94,46 @@ static void enable_intr_window(struct vcpu *v, struct hvm_intack intack)
vmcb->general1_intercepts |= GENERAL1_INTERCEPT_VINTR;
}
+static void svm_dirq_assist(struct vcpu *v)
+{
+ unsigned int irq;
+ uint32_t device, intx;
+ struct domain *d = v->domain;
+ struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
+ struct dev_intx_gsi_link *digl;
+
+ if ( !amd_iommu_enabled || (v->vcpu_id != 0) || (hvm_irq_dpci == NULL) )
+ return;
+
+ for ( irq = find_first_bit(hvm_irq_dpci->dirq_mask, NR_IRQS);
+ irq < NR_IRQS;
+ irq = find_next_bit(hvm_irq_dpci->dirq_mask, NR_IRQS, irq + 1) )
+ {
+ stop_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(irq)]);
+ clear_bit(irq, &hvm_irq_dpci->dirq_mask);
+
+ list_for_each_entry ( digl, &hvm_irq_dpci->mirq[irq].digl_list, list )
+ {
+ device = digl->device;
+ intx = digl->intx;
+ hvm_pci_intx_assert(d, device, intx);
+ spin_lock(&hvm_irq_dpci->dirq_lock);
+ hvm_irq_dpci->mirq[irq].pending++;
+ spin_unlock(&hvm_irq_dpci->dirq_lock);
+ }
+
+ /*
+ * Set a timer to see if the guest can finish the interrupt or not. For
+ * example, the guest OS may unmask the PIC during boot, before the
+ * guest driver is loaded. hvm_pci_intx_assert() may succeed, but the
+ * guest will never deal with the irq, then the physical interrupt line
+ * will never be deasserted.
+ */
+ set_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(irq)],
+ NOW() + PT_IRQ_TIME_OUT);
+ }
+}
+
asmlinkage void svm_intr_assist(void)
{
struct vcpu *v = current;
@@ -102,6 +142,7 @@ asmlinkage void svm_intr_assist(void)
/* Crank the handle on interrupt state. */
pt_update_irq(v);
+ svm_dirq_assist(v);
do {
intack = hvm_vcpu_has_pending_irq(v);
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index 3845946633..ed42ece5e5 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -181,7 +181,7 @@ static void svm_restore_dr(struct vcpu *v)
__restore_debug_registers(v);
}
-int svm_vmcb_save(struct vcpu *v, struct hvm_hw_cpu *c)
+static int svm_vmcb_save(struct vcpu *v, struct hvm_hw_cpu *c)
{
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
@@ -190,52 +190,6 @@ int svm_vmcb_save(struct vcpu *v, struct hvm_hw_cpu *c)
c->cr3 = v->arch.hvm_vcpu.guest_cr[3];
c->cr4 = v->arch.hvm_vcpu.guest_cr[4];
- c->idtr_limit = vmcb->idtr.limit;
- c->idtr_base = vmcb->idtr.base;
-
- c->gdtr_limit = vmcb->gdtr.limit;
- c->gdtr_base = vmcb->gdtr.base;
-
- c->cs_sel = vmcb->cs.sel;
- c->cs_limit = vmcb->cs.limit;
- c->cs_base = vmcb->cs.base;
- c->cs_arbytes = vmcb->cs.attr.bytes;
-
- c->ds_sel = vmcb->ds.sel;
- c->ds_limit = vmcb->ds.limit;
- c->ds_base = vmcb->ds.base;
- c->ds_arbytes = vmcb->ds.attr.bytes;
-
- c->es_sel = vmcb->es.sel;
- c->es_limit = vmcb->es.limit;
- c->es_base = vmcb->es.base;
- c->es_arbytes = vmcb->es.attr.bytes;
-
- c->ss_sel = vmcb->ss.sel;
- c->ss_limit = vmcb->ss.limit;
- c->ss_base = vmcb->ss.base;
- c->ss_arbytes = vmcb->ss.attr.bytes;
-
- c->fs_sel = vmcb->fs.sel;
- c->fs_limit = vmcb->fs.limit;
- c->fs_base = vmcb->fs.base;
- c->fs_arbytes = vmcb->fs.attr.bytes;
-
- c->gs_sel = vmcb->gs.sel;
- c->gs_limit = vmcb->gs.limit;
- c->gs_base = vmcb->gs.base;
- c->gs_arbytes = vmcb->gs.attr.bytes;
-
- c->tr_sel = vmcb->tr.sel;
- c->tr_limit = vmcb->tr.limit;
- c->tr_base = vmcb->tr.base;
- c->tr_arbytes = vmcb->tr.attr.bytes;
-
- c->ldtr_sel = vmcb->ldtr.sel;
- c->ldtr_limit = vmcb->ldtr.limit;
- c->ldtr_base = vmcb->ldtr.base;
- c->ldtr_arbytes = vmcb->ldtr.attr.bytes;
-
c->sysenter_cs = vmcb->sysenter_cs;
c->sysenter_esp = vmcb->sysenter_esp;
c->sysenter_eip = vmcb->sysenter_eip;
@@ -253,8 +207,7 @@ int svm_vmcb_save(struct vcpu *v, struct hvm_hw_cpu *c)
return 1;
}
-
-int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c)
+static int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c)
{
unsigned long mfn = 0;
p2m_type_t p2mt;
@@ -301,53 +254,6 @@ int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c)
__func__, c->cr3, c->cr0, c->cr4);
#endif
- vmcb->idtr.limit = c->idtr_limit;
- vmcb->idtr.base = c->idtr_base;
-
- vmcb->gdtr.limit = c->gdtr_limit;
- vmcb->gdtr.base = c->gdtr_base;
-
- vmcb->cs.sel = c->cs_sel;
- vmcb->cs.limit = c->cs_limit;
- vmcb->cs.base = c->cs_base;
- vmcb->cs.attr.bytes = c->cs_arbytes;
-
- vmcb->ds.sel = c->ds_sel;
- vmcb->ds.limit = c->ds_limit;
- vmcb->ds.base = c->ds_base;
- vmcb->ds.attr.bytes = c->ds_arbytes;
-
- vmcb->es.sel = c->es_sel;
- vmcb->es.limit = c->es_limit;
- vmcb->es.base = c->es_base;
- vmcb->es.attr.bytes = c->es_arbytes;
-
- vmcb->ss.sel = c->ss_sel;
- vmcb->ss.limit = c->ss_limit;
- vmcb->ss.base = c->ss_base;
- vmcb->ss.attr.bytes = c->ss_arbytes;
- vmcb->cpl = vmcb->ss.attr.fields.dpl;
-
- vmcb->fs.sel = c->fs_sel;
- vmcb->fs.limit = c->fs_limit;
- vmcb->fs.base = c->fs_base;
- vmcb->fs.attr.bytes = c->fs_arbytes;
-
- vmcb->gs.sel = c->gs_sel;
- vmcb->gs.limit = c->gs_limit;
- vmcb->gs.base = c->gs_base;
- vmcb->gs.attr.bytes = c->gs_arbytes;
-
- vmcb->tr.sel = c->tr_sel;
- vmcb->tr.limit = c->tr_limit;
- vmcb->tr.base = c->tr_base;
- vmcb->tr.attr.bytes = c->tr_arbytes;
-
- vmcb->ldtr.sel = c->ldtr_sel;
- vmcb->ldtr.limit = c->ldtr_limit;
- vmcb->ldtr.base = c->ldtr_base;
- vmcb->ldtr.attr.bytes = c->ldtr_arbytes;
-
vmcb->sysenter_cs = c->sysenter_cs;
vmcb->sysenter_esp = c->sysenter_esp;
vmcb->sysenter_eip = c->sysenter_eip;
diff --git a/xen/arch/x86/hvm/vioapic.c b/xen/arch/x86/hvm/vioapic.c
index cfc80c5aa1..c01618c69f 100644
--- a/xen/arch/x86/hvm/vioapic.c
+++ b/xen/arch/x86/hvm/vioapic.c
@@ -458,7 +458,7 @@ void vioapic_update_EOI(struct domain *d, int vector)
ent->fields.remote_irr = 0;
- if ( vtd_enabled )
+ if ( iommu_enabled )
{
spin_unlock(&d->arch.hvm_domain.irq_lock);
hvm_dpci_eoi(current->domain, gsi, ent);
diff --git a/xen/arch/x86/hvm/vmx/realmode.c b/xen/arch/x86/hvm/vmx/realmode.c
index 6c591d1f16..8d7572e0d5 100644
--- a/xen/arch/x86/hvm/vmx/realmode.c
+++ b/xen/arch/x86/hvm/vmx/realmode.c
@@ -13,6 +13,7 @@
#include <xen/init.h>
#include <xen/lib.h>
#include <xen/sched.h>
+#include <xen/paging.h>
#include <asm/event.h>
#include <asm/hvm/hvm.h>
#include <asm/hvm/support.h>
@@ -313,6 +314,57 @@ realmode_rep_outs(
return X86EMUL_OKAY;
}
+static int
+realmode_rep_movs(
+ enum x86_segment src_seg,
+ unsigned long src_offset,
+ enum x86_segment dst_seg,
+ unsigned long dst_offset,
+ unsigned int bytes_per_rep,
+ unsigned long *reps,
+ struct x86_emulate_ctxt *ctxt)
+{
+ struct realmode_emulate_ctxt *rm_ctxt =
+ container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
+ struct vcpu *curr = current;
+ uint32_t saddr = virtual_to_linear(src_seg, src_offset, rm_ctxt);
+ uint32_t daddr = virtual_to_linear(dst_seg, dst_offset, rm_ctxt);
+ p2m_type_t p2mt;
+
+ if ( (curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE) ||
+ curr->arch.hvm_vmx.real_mode_io_in_progress )
+ return X86EMUL_UNHANDLEABLE;
+
+ mfn_x(gfn_to_mfn_current(saddr >> PAGE_SHIFT, &p2mt));
+ if ( !p2m_is_ram(p2mt) )
+ {
+ if ( !curr->arch.hvm_vmx.real_mode_io_completed )
+ {
+ curr->arch.hvm_vmx.real_mode_io_in_progress = 1;
+ send_mmio_req(IOREQ_TYPE_COPY, saddr, *reps, bytes_per_rep,
+ daddr, IOREQ_READ,
+ !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1);
+ }
+
+ if ( !curr->arch.hvm_vmx.real_mode_io_completed )
+ return X86EMUL_RETRY;
+
+ curr->arch.hvm_vmx.real_mode_io_completed = 0;
+ }
+ else
+ {
+ mfn_x(gfn_to_mfn_current(daddr >> PAGE_SHIFT, &p2mt));
+ if ( p2m_is_ram(p2mt) )
+ return X86EMUL_UNHANDLEABLE;
+ curr->arch.hvm_vmx.real_mode_io_in_progress = 1;
+ send_mmio_req(IOREQ_TYPE_COPY, daddr, *reps, bytes_per_rep,
+ saddr, IOREQ_WRITE,
+ !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1);
+ }
+
+ return X86EMUL_OKAY;
+}
+
static int
realmode_read_segment(
enum x86_segment seg,
@@ -600,6 +652,7 @@ static struct x86_emulate_ops realmode_emulator_ops = {
.cmpxchg = realmode_emulate_cmpxchg,
.rep_ins = realmode_rep_ins,
.rep_outs = realmode_rep_outs,
+ .rep_movs = realmode_rep_movs,
.read_segment = realmode_read_segment,
.write_segment = realmode_write_segment,
.read_io = realmode_read_io,
@@ -728,7 +781,7 @@ void vmx_realmode(struct cpu_user_regs *regs)
struct vcpu *curr = current;
struct realmode_emulate_ctxt rm_ctxt;
unsigned long intr_info = __vmread(VM_ENTRY_INTR_INFO);
- int i;
+ unsigned int i, emulations = 0;
rm_ctxt.ctxt.regs = regs;
@@ -751,11 +804,19 @@ void vmx_realmode(struct cpu_user_regs *regs)
while ( curr->arch.hvm_vmx.vmxemul &&
!softirq_pending(smp_processor_id()) &&
- !curr->arch.hvm_vmx.real_mode_io_in_progress &&
- /* Check for pending interrupts only in proper real mode. */
- ((curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE) ||
- !hvm_local_events_need_delivery(curr)) )
+ !curr->arch.hvm_vmx.real_mode_io_in_progress )
+ {
+ /*
+ * Check for pending interrupts only every 16 instructions, because
+ * hvm_local_events_need_delivery() is moderately expensive, and only
+ * in real mode, because we don't emulate protected-mode IDT vectoring.
+ */
+ if ( unlikely(!(++emulations & 15)) &&
+ !(curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE) &&
+ hvm_local_events_need_delivery(curr) )
+ break;
realmode_emulate_one(&rm_ctxt);
+ }
if ( !curr->arch.hvm_vmx.vmxemul )
{
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index 50efb4fcd9..8d4629df36 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -450,7 +450,7 @@ static void vmx_restore_dr(struct vcpu *v)
__restore_debug_registers(v);
}
-void vmx_vmcs_save(struct vcpu *v, struct hvm_hw_cpu *c)
+static void vmx_vmcs_save(struct vcpu *v, struct hvm_hw_cpu *c)
{
uint32_t ev;
@@ -463,52 +463,6 @@ void vmx_vmcs_save(struct vcpu *v, struct hvm_hw_cpu *c)
c->msr_efer = v->arch.hvm_vcpu.guest_efer;
- c->idtr_limit = __vmread(GUEST_IDTR_LIMIT);
- c->idtr_base = __vmread(GUEST_IDTR_BASE);
-
- c->gdtr_limit = __vmread(GUEST_GDTR_LIMIT);
- c->gdtr_base = __vmread(GUEST_GDTR_BASE);
-
- c->cs_sel = __vmread(GUEST_CS_SELECTOR);
- c->cs_limit = __vmread(GUEST_CS_LIMIT);
- c->cs_base = __vmread(GUEST_CS_BASE);
- c->cs_arbytes = __vmread(GUEST_CS_AR_BYTES);
-
- c->ds_sel = __vmread(GUEST_DS_SELECTOR);
- c->ds_limit = __vmread(GUEST_DS_LIMIT);
- c->ds_base = __vmread(GUEST_DS_BASE);
- c->ds_arbytes = __vmread(GUEST_DS_AR_BYTES);
-
- c->es_sel = __vmread(GUEST_ES_SELECTOR);
- c->es_limit = __vmread(GUEST_ES_LIMIT);
- c->es_base = __vmread(GUEST_ES_BASE);
- c->es_arbytes = __vmread(GUEST_ES_AR_BYTES);
-
- c->ss_sel = __vmread(GUEST_SS_SELECTOR);
- c->ss_limit = __vmread(GUEST_SS_LIMIT);
- c->ss_base = __vmread(GUEST_SS_BASE);
- c->ss_arbytes = __vmread(GUEST_SS_AR_BYTES);
-
- c->fs_sel = __vmread(GUEST_FS_SELECTOR);
- c->fs_limit = __vmread(GUEST_FS_LIMIT);
- c->fs_base = __vmread(GUEST_FS_BASE);
- c->fs_arbytes = __vmread(GUEST_FS_AR_BYTES);
-
- c->gs_sel = __vmread(GUEST_GS_SELECTOR);
- c->gs_limit = __vmread(GUEST_GS_LIMIT);
- c->gs_base = __vmread(GUEST_GS_BASE);
- c->gs_arbytes = __vmread(GUEST_GS_AR_BYTES);
-
- c->tr_sel = __vmread(GUEST_TR_SELECTOR);
- c->tr_limit = __vmread(GUEST_TR_LIMIT);
- c->tr_base = __vmread(GUEST_TR_BASE);
- c->tr_arbytes = __vmread(GUEST_TR_AR_BYTES);
-
- c->ldtr_sel = __vmread(GUEST_LDTR_SELECTOR);
- c->ldtr_limit = __vmread(GUEST_LDTR_LIMIT);
- c->ldtr_base = __vmread(GUEST_LDTR_BASE);
- c->ldtr_arbytes = __vmread(GUEST_LDTR_AR_BYTES);
-
c->sysenter_cs = __vmread(GUEST_SYSENTER_CS);
c->sysenter_esp = __vmread(GUEST_SYSENTER_ESP);
c->sysenter_eip = __vmread(GUEST_SYSENTER_EIP);
@@ -552,7 +506,7 @@ static int vmx_restore_cr0_cr3(
return 0;
}
-int vmx_vmcs_restore(struct vcpu *v, struct hvm_hw_cpu *c)
+static int vmx_vmcs_restore(struct vcpu *v, struct hvm_hw_cpu *c)
{
int rc;
@@ -585,52 +539,6 @@ int vmx_vmcs_restore(struct vcpu *v, struct hvm_hw_cpu *c)
v->arch.hvm_vcpu.guest_efer = c->msr_efer;
vmx_update_guest_efer(v);
- __vmwrite(GUEST_IDTR_LIMIT, c->idtr_limit);
- __vmwrite(GUEST_IDTR_BASE, c->idtr_base);
-
- __vmwrite(GUEST_GDTR_LIMIT, c->gdtr_limit);
- __vmwrite(GUEST_GDTR_BASE, c->gdtr_base);
-
- __vmwrite(GUEST_CS_SELECTOR, c->cs_sel);
- __vmwrite(GUEST_CS_LIMIT, c->cs_limit);
- __vmwrite(GUEST_CS_BASE, c->cs_base);
- __vmwrite(GUEST_CS_AR_BYTES, c->cs_arbytes);
-
- __vmwrite(GUEST_DS_SELECTOR, c->ds_sel);
- __vmwrite(GUEST_DS_LIMIT, c->ds_limit);
- __vmwrite(GUEST_DS_BASE, c->ds_base);
- __vmwrite(GUEST_DS_AR_BYTES, c->ds_arbytes);
-
- __vmwrite(GUEST_ES_SELECTOR, c->es_sel);
- __vmwrite(GUEST_ES_LIMIT, c->es_limit);
- __vmwrite(GUEST_ES_BASE, c->es_base);
- __vmwrite(GUEST_ES_AR_BYTES, c->es_arbytes);
-
- __vmwrite(GUEST_SS_SELECTOR, c->ss_sel);
- __vmwrite(GUEST_SS_LIMIT, c->ss_limit);
- __vmwrite(GUEST_SS_BASE, c->ss_base);
- __vmwrite(GUEST_SS_AR_BYTES, c->ss_arbytes);
-
- __vmwrite(GUEST_FS_SELECTOR, c->fs_sel);
- __vmwrite(GUEST_FS_LIMIT, c->fs_limit);
- __vmwrite(GUEST_FS_BASE, c->fs_base);
- __vmwrite(GUEST_FS_AR_BYTES, c->fs_arbytes);
-
- __vmwrite(GUEST_GS_SELECTOR, c->gs_sel);
- __vmwrite(GUEST_GS_LIMIT, c->gs_limit);
- __vmwrite(GUEST_GS_BASE, c->gs_base);
- __vmwrite(GUEST_GS_AR_BYTES, c->gs_arbytes);
-
- __vmwrite(GUEST_TR_SELECTOR, c->tr_sel);
- __vmwrite(GUEST_TR_LIMIT, c->tr_limit);
- __vmwrite(GUEST_TR_BASE, c->tr_base);
- __vmwrite(GUEST_TR_AR_BYTES, c->tr_arbytes);
-
- __vmwrite(GUEST_LDTR_SELECTOR, c->ldtr_sel);
- __vmwrite(GUEST_LDTR_LIMIT, c->ldtr_limit);
- __vmwrite(GUEST_LDTR_BASE, c->ldtr_base);
- __vmwrite(GUEST_LDTR_AR_BYTES, c->ldtr_arbytes);
-
__vmwrite(GUEST_SYSENTER_CS, c->sysenter_cs);
__vmwrite(GUEST_SYSENTER_ESP, c->sysenter_esp);
__vmwrite(GUEST_SYSENTER_EIP, c->sysenter_eip);
@@ -821,7 +729,7 @@ static void vmx_get_segment_register(struct vcpu *v, enum x86_segment seg,
{
uint32_t attr = 0;
- ASSERT(v == current);
+ vmx_vmcs_enter(v);
switch ( seg )
{
@@ -885,6 +793,8 @@ static void vmx_get_segment_register(struct vcpu *v, enum x86_segment seg,
BUG();
}
+ vmx_vmcs_exit(v);
+
reg->attr.bytes = (attr & 0xff) | ((attr >> 4) & 0xf00);
/* Unusable flag is folded into Present flag. */
if ( attr & (1u<<16) )
@@ -896,8 +806,6 @@ static void vmx_set_segment_register(struct vcpu *v, enum x86_segment seg,
{
uint32_t attr;
- ASSERT((v == current) || !vcpu_runnable(v));
-
attr = reg->attr.bytes;
attr = ((attr & 0xf00) << 4) | (attr & 0xff);
@@ -1009,6 +917,14 @@ static enum hvm_intblk vmx_interrupt_blocked(
{
unsigned long intr_shadow;
+ /*
+ * Test EFLAGS.IF first. It is often the most likely reason for interrupt
+ * blockage, and is the cheapest to test (because no VMREAD is required).
+ */
+ if ( (intack.source != hvm_intsrc_nmi) &&
+ !(guest_cpu_user_regs()->eflags & X86_EFLAGS_IF) )
+ return hvm_intblk_rflags_ie;
+
intr_shadow = __vmread(GUEST_INTERRUPTIBILITY_INFO);
if ( intr_shadow & (VMX_INTR_SHADOW_STI|VMX_INTR_SHADOW_MOV_SS) )
@@ -1021,15 +937,11 @@ static enum hvm_intblk vmx_interrupt_blocked(
ASSERT((intack.source == hvm_intsrc_pic) ||
(intack.source == hvm_intsrc_lapic));
- if ( !(guest_cpu_user_regs()->eflags & X86_EFLAGS_IF) )
- return hvm_intblk_rflags_ie;
-
return hvm_intblk_none;
}
static void vmx_update_host_cr3(struct vcpu *v)
{
- ASSERT((v == current) || !vcpu_runnable(v));
vmx_vmcs_enter(v);
__vmwrite(HOST_CR3, v->arch.cr3);
vmx_vmcs_exit(v);
@@ -1037,8 +949,6 @@ static void vmx_update_host_cr3(struct vcpu *v)
static void vmx_update_guest_cr(struct vcpu *v, unsigned int cr)
{
- ASSERT((v == current) || !vcpu_runnable(v));
-
vmx_vmcs_enter(v);
switch ( cr )
@@ -1089,8 +999,6 @@ static void vmx_update_guest_efer(struct vcpu *v)
#ifdef __x86_64__
unsigned long vm_entry_value;
- ASSERT((v == current) || !vcpu_runnable(v));
-
vmx_vmcs_enter(v);
vm_entry_value = __vmread(VM_ENTRY_CONTROLS);
diff --git a/xen/arch/x86/hvm/vmx/vtd/Makefile b/xen/arch/x86/hvm/vmx/vtd/Makefile
index 1cae6385ab..dcff4e3ab1 100644
--- a/xen/arch/x86/hvm/vmx/vtd/Makefile
+++ b/xen/arch/x86/hvm/vmx/vtd/Makefile
@@ -3,3 +3,4 @@ obj-y += dmar.o
obj-y += utils.o
obj-y += io.o
obj-y += qinval.o
+obj-y += intremap.o
diff --git a/xen/arch/x86/hvm/vmx/vtd/extern.h b/xen/arch/x86/hvm/vmx/vtd/extern.h
index 6143b935b9..9e2ac576ea 100644
--- a/xen/arch/x86/hvm/vmx/vtd/extern.h
+++ b/xen/arch/x86/hvm/vmx/vtd/extern.h
@@ -23,11 +23,6 @@
#include "dmar.h"
-extern int iommu_setup_done;
-extern int vtd2_thurley_enabled;
-extern int vtd2_qinval_enabled;
-
-extern spinlock_t ioapic_lock;
extern struct qi_ctrl *qi_ctrl;
extern struct ir_ctrl *ir_ctrl;
@@ -37,6 +32,7 @@ void print_vtd_entries(struct domain *d, struct iommu *iommu,
void pdev_flr(u8 bus, u8 devfn);
int qinval_setup(struct iommu *iommu);
+int intremap_setup(struct iommu *iommu);
int queue_invalidate_context(struct iommu *iommu,
u16 did, u16 source_id, u8 function_mask, u8 granu);
int queue_invalidate_iotlb(struct iommu *iommu,
@@ -46,7 +42,6 @@ int queue_invalidate_iec(struct iommu *iommu,
int invalidate_sync(struct iommu *iommu);
int iommu_flush_iec_global(struct iommu *iommu);
int iommu_flush_iec_index(struct iommu *iommu, u8 im, u16 iidx);
-void gsi_remapping(unsigned int gsi);
void print_iommu_regs(struct acpi_drhd_unit *drhd);
int vtd_hw_check(void);
struct iommu * ioapic_to_iommu(unsigned int apic_id);
diff --git a/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c b/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c
index 4b05f1d87c..c497b9c392 100644
--- a/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c
+++ b/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c
@@ -1047,7 +1047,7 @@ static void free_iommu(struct iommu *iommu)
agaw = 64; \
agaw; })
-int iommu_domain_init(struct domain *domain)
+int intel_iommu_domain_init(struct domain *domain)
{
struct hvm_iommu *hd = domain_hvm_iommu(domain);
struct iommu *iommu = NULL;
@@ -1056,11 +1056,6 @@ int iommu_domain_init(struct domain *domain)
unsigned long sagaw;
struct acpi_drhd_unit *drhd;
- spin_lock_init(&hd->mapping_lock);
- spin_lock_init(&hd->iommu_list_lock);
- INIT_LIST_HEAD(&hd->pdev_list);
- INIT_LIST_HEAD(&hd->g2m_ioport_list);
-
if ( !vtd_enabled || list_empty(&acpi_drhd_units) )
return 0;
@@ -1550,7 +1545,8 @@ static int domain_context_mapped(struct pci_dev *pdev)
return 0;
}
-int iommu_map_page(struct domain *d, paddr_t gfn, paddr_t mfn)
+int intel_iommu_map_page(
+ struct domain *d, unsigned long gfn, unsigned long mfn)
{
struct acpi_drhd_unit *drhd;
struct iommu *iommu;
@@ -1566,12 +1562,12 @@ int iommu_map_page(struct domain *d, paddr_t gfn, paddr_t mfn)
return 0;
#endif
- pg = addr_to_dma_page(d, gfn << PAGE_SHIFT_4K);
+ pg = addr_to_dma_page(d, (paddr_t)gfn << PAGE_SHIFT_4K);
if ( !pg )
return -ENOMEM;
pte = (struct dma_pte *)map_domain_page(page_to_mfn(pg));
pte += gfn & LEVEL_MASK;
- dma_set_pte_addr(*pte, mfn << PAGE_SHIFT_4K);
+ dma_set_pte_addr(*pte, (paddr_t)mfn << PAGE_SHIFT_4K);
dma_set_pte_prot(*pte, DMA_PTE_READ | DMA_PTE_WRITE);
iommu_flush_cache_entry(iommu, pte);
unmap_domain_page(pte);
@@ -1581,7 +1577,7 @@ int iommu_map_page(struct domain *d, paddr_t gfn, paddr_t mfn)
iommu = drhd->iommu;
if ( cap_caching_mode(iommu->cap) )
iommu_flush_iotlb_psi(iommu, domain_iommu_domid(d),
- gfn << PAGE_SHIFT_4K, 1, 0);
+ (paddr_t)gfn << PAGE_SHIFT_4K, 1, 0);
else if ( cap_rwbf(iommu->cap) )
iommu_flush_write_buffer(iommu);
}
@@ -1589,7 +1585,7 @@ int iommu_map_page(struct domain *d, paddr_t gfn, paddr_t mfn)
return 0;
}
-int iommu_unmap_page(struct domain *d, dma_addr_t gfn)
+int intel_iommu_unmap_page(struct domain *d, unsigned long gfn)
{
struct acpi_drhd_unit *drhd;
struct iommu *iommu;
@@ -1603,12 +1599,12 @@ int iommu_unmap_page(struct domain *d, dma_addr_t gfn)
return 0;
#endif
- dma_pte_clear_one(d, gfn << PAGE_SHIFT_4K);
+ dma_pte_clear_one(d, (paddr_t)gfn << PAGE_SHIFT_4K);
return 0;
}
-int iommu_page_mapping(struct domain *domain, dma_addr_t iova,
+int iommu_page_mapping(struct domain *domain, paddr_t iova,
void *hpa, size_t size, int prot)
{
struct acpi_drhd_unit *drhd;
@@ -1655,14 +1651,14 @@ int iommu_page_mapping(struct domain *domain, dma_addr_t iova,
return 0;
}
-int iommu_page_unmapping(struct domain *domain, dma_addr_t addr, size_t size)
+int iommu_page_unmapping(struct domain *domain, paddr_t addr, size_t size)
{
dma_pte_clear_range(domain, addr, addr + size);
return 0;
}
-void iommu_flush(struct domain *d, dma_addr_t gfn, u64 *p2m_entry)
+void iommu_flush(struct domain *d, unsigned long gfn, u64 *p2m_entry)
{
struct acpi_drhd_unit *drhd;
struct iommu *iommu = NULL;
@@ -1673,7 +1669,7 @@ void iommu_flush(struct domain *d, dma_addr_t gfn, u64 *p2m_entry)
iommu = drhd->iommu;
if ( cap_caching_mode(iommu->cap) )
iommu_flush_iotlb_psi(iommu, domain_iommu_domid(d),
- gfn << PAGE_SHIFT_4K, 1, 0);
+ (paddr_t)gfn << PAGE_SHIFT_4K, 1, 0);
else if ( cap_rwbf(iommu->cap) )
iommu_flush_write_buffer(iommu);
}
@@ -1816,9 +1812,13 @@ static int init_vtd_hw(void)
flush->context = flush_context_reg;
flush->iotlb = flush_iotlb_reg;
- if ( qinval_setup(iommu) != 0);
+ if ( qinval_setup(iommu) != 0 )
dprintk(XENLOG_ERR VTDPREFIX,
"Queued Invalidation hardware not found\n");
+
+ if ( intremap_setup(iommu) != 0 )
+ dprintk(XENLOG_ERR VTDPREFIX,
+ "Interrupt Remapping hardware not found\n");
}
return 0;
}
@@ -1917,7 +1917,7 @@ int device_assigned(u8 bus, u8 devfn)
return 1;
}
-int assign_device(struct domain *d, u8 bus, u8 devfn)
+int intel_iommu_assign_device(struct domain *d, u8 bus, u8 devfn)
{
struct acpi_rmrr_unit *rmrr;
struct pci_dev *pdev;
@@ -2147,6 +2147,14 @@ int iommu_resume(void)
return 0;
}
+struct iommu_ops intel_iommu_ops = {
+ .init = intel_iommu_domain_init,
+ .assign_device = intel_iommu_assign_device,
+ .teardown = iommu_domain_teardown,
+ .map_page = intel_iommu_map_page,
+ .unmap_page = intel_iommu_unmap_page,
+};
+
/*
* Local variables:
* mode: C
diff --git a/xen/arch/x86/hvm/vmx/vtd/intremap.c b/xen/arch/x86/hvm/vmx/vtd/intremap.c
new file mode 100644
index 0000000000..21645599b6
--- /dev/null
+++ b/xen/arch/x86/hvm/vmx/vtd/intremap.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 2006, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Copyright (C) Allen Kay <allen.m.kay@intel.com>
+ * Copyright (C) Xiaohui Xin <xiaohui.xin@intel.com>
+ */
+
+#include <xen/config.h>
+#include <xen/lib.h>
+#include <xen/init.h>
+#include <xen/irq.h>
+#include <xen/delay.h>
+#include <xen/sched.h>
+#include <xen/acpi.h>
+#include <xen/keyhandler.h>
+#include <xen/spinlock.h>
+#include <asm/io.h>
+#include <asm/mc146818rtc.h>
+#include <asm/smp.h>
+#include <asm/desc.h>
+#include <mach_apic.h>
+#include <io_ports.h>
+
+#include <xen/spinlock.h>
+#include <xen/xmalloc.h>
+#include <xen/domain_page.h>
+#include <asm/delay.h>
+#include <asm/string.h>
+#include <asm/iommu.h>
+#include <asm/hvm/vmx/intel-iommu.h>
+#include "dmar.h"
+#include "vtd.h"
+#include "pci-direct.h"
+#include "pci_regs.h"
+#include "msi.h"
+#include "extern.h"
+
+u16 apicid_to_bdf(int apic_id)
+{
+ struct acpi_drhd_unit *drhd = ioapic_to_drhd(apic_id);
+ struct acpi_ioapic_unit *acpi_ioapic_unit;
+
+ list_for_each_entry ( acpi_ioapic_unit, &drhd->ioapic_list, list )
+ if ( acpi_ioapic_unit->apic_id == apic_id )
+ return acpi_ioapic_unit->ioapic.info;
+
+ dprintk(XENLOG_ERR VTDPREFIX, "Didn't find the bdf for the apic_id!\n");
+ return 0;
+}
+
+static void remap_entry_to_ioapic_rte(
+ struct iommu *iommu, struct IO_APIC_route_entry *old_rte)
+{
+ struct iremap_entry *iremap_entry = NULL;
+ struct IO_APIC_route_remap_entry *remap_rte;
+ unsigned int index;
+ unsigned long flags;
+ struct ir_ctrl *ir_ctrl = iommu_ir_ctrl(iommu);
+
+ if ( ir_ctrl == NULL )
+ {
+ dprintk(XENLOG_ERR VTDPREFIX,
+ "remap_entry_to_ioapic_rte: ir_ctl == NULL");
+ return;
+ }
+
+ remap_rte = (struct IO_APIC_route_remap_entry *) old_rte;
+ index = (remap_rte->index_15 << 15) + remap_rte->index_0_14;
+
+ if ( index > ir_ctrl->iremap_index )
+ {
+ dprintk(XENLOG_ERR VTDPREFIX,
+ "Index is larger than remap table entry size. Error!\n");
+ return;
+ }
+
+ spin_lock_irqsave(&ir_ctrl->iremap_lock, flags);
+
+ iremap_entry = &ir_ctrl->iremap[index];
+
+ old_rte->vector = iremap_entry->lo.vector;
+ old_rte->delivery_mode = iremap_entry->lo.dlm;
+ old_rte->dest_mode = iremap_entry->lo.dm;
+ old_rte->trigger = iremap_entry->lo.tm;
+ old_rte->__reserved_2 = 0;
+ old_rte->dest.logical.__reserved_1 = 0;
+ old_rte->dest.logical.logical_dest = iremap_entry->lo.dst;
+
+ spin_unlock_irqrestore(&ir_ctrl->iremap_lock, flags);
+}
+
+static void ioapic_rte_to_remap_entry(struct iommu *iommu,
+ int apic_id, struct IO_APIC_route_entry *old_rte)
+{
+ struct iremap_entry *iremap_entry = NULL;
+ struct IO_APIC_route_remap_entry *remap_rte;
+ unsigned int index;
+ unsigned long flags;
+ int ret = 0;
+ struct ir_ctrl *ir_ctrl = iommu_ir_ctrl(iommu);
+
+ remap_rte = (struct IO_APIC_route_remap_entry *) old_rte;
+ spin_lock_irqsave(&ir_ctrl->iremap_lock, flags);
+ index = ir_ctrl->iremap_index;
+ if ( index > IREMAP_ENTRY_NR - 1 )
+ {
+ dprintk(XENLOG_ERR VTDPREFIX,
+ "The interrupt number is more than 256!\n");
+ goto out;
+ }
+
+ iremap_entry = &(ir_ctrl->iremap[index]);
+ if ( *(u64 *)iremap_entry != 0 )
+ dprintk(XENLOG_WARNING VTDPREFIX,
+ "Interrupt remapping entry is in use already!\n");
+ iremap_entry->lo.fpd = 0;
+ iremap_entry->lo.dm = old_rte->dest_mode;
+ iremap_entry->lo.rh = 0;
+ iremap_entry->lo.tm = old_rte->trigger;
+ iremap_entry->lo.dlm = old_rte->delivery_mode;
+ iremap_entry->lo.avail = 0;
+ iremap_entry->lo.res_1 = 0;
+ iremap_entry->lo.vector = old_rte->vector;
+ iremap_entry->lo.res_2 = 0;
+ iremap_entry->lo.dst = (old_rte->dest.logical.logical_dest << 8);
+ iremap_entry->hi.sid = apicid_to_bdf(apic_id);
+ iremap_entry->hi.sq = 0; /* comparing all 16-bit of SID */
+ iremap_entry->hi.svt = 1; /* turn on requestor ID verification SID/SQ */
+ iremap_entry->hi.res_1 = 0;
+ iremap_entry->lo.p = 1; /* finally, set present bit */
+ ir_ctrl->iremap_index++;
+
+ iommu_flush_iec_index(iommu, 0, index);
+ ret = invalidate_sync(iommu);
+
+ /* now construct new ioapic rte entry */
+ remap_rte->vector = old_rte->vector;
+ remap_rte->delivery_mode = 0; /* has to be 0 for remap format */
+ remap_rte->index_15 = index & 0x8000;
+ remap_rte->index_0_14 = index & 0x7fff;
+ remap_rte->delivery_status = old_rte->delivery_status;
+ remap_rte->polarity = old_rte->polarity;
+ remap_rte->irr = old_rte->irr;
+ remap_rte->trigger = old_rte->trigger;
+ remap_rte->mask = 1;
+ remap_rte->reserved = 0;
+ remap_rte->format = 1; /* indicate remap format */
+out:
+ spin_unlock_irqrestore(&ir_ctrl->iremap_lock, flags);
+ return;
+}
+
+unsigned int
+io_apic_read_remap_rte(
+ unsigned int apic, unsigned int reg)
+{
+ struct IO_APIC_route_entry old_rte = { 0 };
+ struct IO_APIC_route_remap_entry *remap_rte;
+ int rte_upper = (reg & 1) ? 1 : 0;
+ struct iommu *iommu = ioapic_to_iommu(mp_ioapics[apic].mpc_apicid);
+ struct ir_ctrl *ir_ctrl = iommu_ir_ctrl(iommu);
+
+ if ( !iommu || !(ir_ctrl->iremap) )
+ {
+ *IO_APIC_BASE(apic) = reg;
+ return *(IO_APIC_BASE(apic)+4);
+ }
+
+ if ( rte_upper )
+ reg--;
+
+ /* read lower and upper 32-bits of rte entry */
+ *IO_APIC_BASE(apic) = reg;
+ *(((u32 *)&old_rte) + 0) = *(IO_APIC_BASE(apic)+4);
+ *IO_APIC_BASE(apic) = reg + 1;
+ *(((u32 *)&old_rte) + 1) = *(IO_APIC_BASE(apic)+4);
+
+ remap_rte = (struct IO_APIC_route_remap_entry *) &old_rte;
+
+ if ( remap_rte->mask || (remap_rte->format == 0) )
+ {
+ *IO_APIC_BASE(apic) = reg;
+ return *(IO_APIC_BASE(apic)+4);
+ }
+
+ remap_entry_to_ioapic_rte(iommu, &old_rte);
+ if ( rte_upper )
+ {
+ *IO_APIC_BASE(apic) = reg + 1;
+ return (*(((u32 *)&old_rte) + 1));
+ }
+ else
+ {
+ *IO_APIC_BASE(apic) = reg;
+ return (*(((u32 *)&old_rte) + 0));
+ }
+}
+
+void
+io_apic_write_remap_rte(
+ unsigned int apic, unsigned int reg, unsigned int value)
+{
+ struct IO_APIC_route_entry old_rte = { 0 };
+ struct IO_APIC_route_remap_entry *remap_rte;
+ int rte_upper = (reg & 1) ? 1 : 0;
+ struct iommu *iommu = ioapic_to_iommu(mp_ioapics[apic].mpc_apicid);
+ struct ir_ctrl *ir_ctrl = iommu_ir_ctrl(iommu);
+
+ if ( !iommu || !(ir_ctrl->iremap) )
+ {
+ *IO_APIC_BASE(apic) = reg;
+ *(IO_APIC_BASE(apic)+4) = value;
+ return;
+ }
+
+ if ( rte_upper )
+ reg--;
+
+ /* read both lower and upper 32-bits of rte entry */
+ *IO_APIC_BASE(apic) = reg;
+ *(((u32 *)&old_rte) + 0) = *(IO_APIC_BASE(apic)+4);
+ *IO_APIC_BASE(apic) = reg + 1;
+ *(((u32 *)&old_rte) + 1) = *(IO_APIC_BASE(apic)+4);
+
+ remap_rte = (struct IO_APIC_route_remap_entry *) &old_rte;
+ if ( remap_rte->mask || (remap_rte->format == 0) )
+ {
+ *IO_APIC_BASE(apic) = rte_upper ? ++reg : reg;
+ *(IO_APIC_BASE(apic)+4) = value;
+ return;
+ }
+
+ *(((u32 *)&old_rte) + rte_upper) = value;
+ ioapic_rte_to_remap_entry(iommu, mp_ioapics[apic].mpc_apicid, &old_rte);
+
+ /* write new entry to ioapic */
+ *IO_APIC_BASE(apic) = reg;
+ *(IO_APIC_BASE(apic)+4) = *(((int *)&old_rte)+0);
+ *IO_APIC_BASE(apic) = reg + 1;
+ *(IO_APIC_BASE(apic)+4) = *(((int *)&old_rte)+1);
+}
+
+int intremap_setup(struct iommu *iommu)
+{
+ struct ir_ctrl *ir_ctrl;
+ unsigned long start_time;
+ u64 paddr;
+
+ if ( !ecap_intr_remap(iommu->ecap) )
+ return -ENODEV;
+
+ ir_ctrl = iommu_ir_ctrl(iommu);
+ if ( ir_ctrl->iremap == NULL )
+ {
+ ir_ctrl->iremap = alloc_xenheap_page();
+ if ( ir_ctrl->iremap == NULL )
+ {
+ dprintk(XENLOG_WARNING VTDPREFIX,
+ "Cannot allocate memory for ir_ctrl->iremap\n");
+ return -ENODEV;
+ }
+ memset(ir_ctrl->iremap, 0, PAGE_SIZE);
+ }
+
+ paddr = virt_to_maddr(ir_ctrl->iremap);
+#if defined(ENABLED_EXTENDED_INTERRUPT_SUPPORT)
+ /* set extended interrupt mode bit */
+ paddr |= ecap_ext_intr(iommu->ecap) ? (1 << IRTA_REG_EIMI_SHIFT) : 0;
+#endif
+ /* size field = 256 entries per 4K page = 8 - 1 */
+ paddr |= 7;
+ dmar_writeq(iommu->reg, DMAR_IRTA_REG, paddr);
+
+ /* set SIRTP */
+ iommu->gcmd |= DMA_GCMD_SIRTP;
+ dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd);
+
+ /* Make sure hardware complete it */
+ start_time = jiffies;
+ while ( !(dmar_readl(iommu->reg, DMAR_GSTS_REG) & DMA_GSTS_SIRTPS) )
+ {
+ if ( time_after(jiffies, start_time + DMAR_OPERATION_TIMEOUT) )
+ {
+ dprintk(XENLOG_ERR VTDPREFIX,
+ "Cannot set SIRTP field for interrupt remapping\n");
+ return -ENODEV;
+ }
+ cpu_relax();
+ }
+
+ /* enable comaptiblity format interrupt pass through */
+ iommu->gcmd |= DMA_GCMD_CFI;
+ dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd);
+
+ start_time = jiffies;
+ while ( !(dmar_readl(iommu->reg, DMAR_GSTS_REG) & DMA_GSTS_CFIS) )
+ {
+ if ( time_after(jiffies, start_time + DMAR_OPERATION_TIMEOUT) )
+ {
+ dprintk(XENLOG_ERR VTDPREFIX,
+ "Cannot set CFI field for interrupt remapping\n");
+ return -ENODEV;
+ }
+ cpu_relax();
+ }
+
+ /* enable interrupt remapping hardware */
+ iommu->gcmd |= DMA_GCMD_IRE;
+ dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd);
+
+ start_time = jiffies;
+ while ( !(dmar_readl(iommu->reg, DMAR_GSTS_REG) & DMA_GSTS_IRES) )
+ {
+ if ( time_after(jiffies, start_time + DMAR_OPERATION_TIMEOUT) )
+ {
+ dprintk(XENLOG_ERR VTDPREFIX,
+ "Cannot set IRE field for interrupt remapping\n");
+ return -ENODEV;
+ }
+ cpu_relax();
+ }
+
+ /* After set SIRTP, we should do globally invalidate the IEC */
+ iommu_flush_iec_global(iommu);
+
+ return 0;
+}
diff --git a/xen/arch/x86/hvm/vmx/vtd/io.c b/xen/arch/x86/hvm/vmx/vtd/io.c
index 39029fab9f..0962757a0e 100644
--- a/xen/arch/x86/hvm/vmx/vtd/io.c
+++ b/xen/arch/x86/hvm/vmx/vtd/io.c
@@ -141,7 +141,7 @@ int hvm_do_IRQ_dpci(struct domain *d, unsigned int mirq)
{
struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
- if ( !vtd_enabled || (d == dom0) || (hvm_irq->dpci == NULL) ||
+ if ( !iommu_enabled || (d == dom0) || (hvm_irq->dpci == NULL) ||
!hvm_irq->dpci->mirq[mirq].valid )
return 0;
@@ -167,7 +167,7 @@ static void hvm_dpci_isairq_eoi(struct domain *d, unsigned int isairq)
int i;
ASSERT(isairq < NR_ISAIRQS);
- if ( !vtd_enabled || !dpci ||
+ if ( !iommu_enabled || !dpci ||
!test_bit(isairq, dpci->isairq_map) )
return;
@@ -205,7 +205,7 @@ void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi,
struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
uint32_t device, intx, machine_gsi;
- if ( !vtd_enabled || (hvm_irq_dpci == NULL) ||
+ if ( !iommu_enabled || (hvm_irq_dpci == NULL) ||
(guest_gsi >= NR_ISAIRQS &&
!hvm_irq_dpci->girq[guest_gsi].valid) )
return;
@@ -235,50 +235,3 @@ void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi,
else
spin_unlock(&hvm_irq_dpci->dirq_lock);
}
-
-void iommu_domain_destroy(struct domain *d)
-{
- struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci;
- uint32_t i;
- struct hvm_iommu *hd = domain_hvm_iommu(d);
- struct list_head *ioport_list, *digl_list, *tmp;
- struct g2m_ioport *ioport;
- struct dev_intx_gsi_link *digl;
-
- if ( !vtd_enabled )
- return;
-
- if ( hvm_irq_dpci != NULL )
- {
- for ( i = 0; i < NR_IRQS; i++ )
- if ( hvm_irq_dpci->mirq[i].valid )
- {
- pirq_guest_unbind(d, i);
- kill_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(i)]);
-
- list_for_each_safe ( digl_list, tmp,
- &hvm_irq_dpci->mirq[i].digl_list )
- {
- digl = list_entry(digl_list,
- struct dev_intx_gsi_link, list);
- list_del(&digl->list);
- xfree(digl);
- }
- }
-
- d->arch.hvm_domain.irq.dpci = NULL;
- xfree(hvm_irq_dpci);
- }
-
- if ( hd )
- {
- list_for_each_safe ( ioport_list, tmp, &hd->g2m_ioport_list )
- {
- ioport = list_entry(ioport_list, struct g2m_ioport, list);
- list_del(&ioport->list);
- xfree(ioport);
- }
- }
-
- iommu_domain_teardown(d);
-}
diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
index ee98ae8c6a..b114de3e80 100644
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -255,8 +255,21 @@ set_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn, p2m_type_t p2mt)
/* level 1 entry */
paging_write_p2m_entry(d, gfn, p2m_entry, table_mfn, entry_content, 1);
- if ( vtd_enabled && (p2mt == p2m_mmio_direct) && is_hvm_domain(d) )
- iommu_flush(d, gfn, (u64*)p2m_entry);
+ if ( iommu_enabled && is_hvm_domain(d) )
+ {
+ if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
+ {
+ if ( (p2mt == p2m_mmio_direct) )
+ iommu_flush(d, gfn, (u64*)p2m_entry);
+ }
+ else if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD )
+ {
+ if ( p2mt == p2m_ram_rw )
+ iommu_map_page(d, gfn, mfn_x(mfn));
+ else
+ iommu_unmap_page(d, gfn);
+ }
+ }
/* Success */
rv = 1;
@@ -486,6 +499,7 @@ static void audit_p2m(struct domain *d)
mfn_t p2mfn;
unsigned long orphans_d = 0, orphans_i = 0, mpbad = 0, pmbad = 0;
int test_linear;
+ p2m_type_t type;
if ( !paging_mode_translate(d) )
return;
@@ -534,7 +548,7 @@ static void audit_p2m(struct domain *d)
continue;
}
- p2mfn = gfn_to_mfn_foreign(d, gfn);
+ p2mfn = gfn_to_mfn_foreign(d, gfn, &type);
if ( mfn_x(p2mfn) != mfn )
{
mpbad++;
@@ -547,12 +561,12 @@ static void audit_p2m(struct domain *d)
/* This m2p entry is stale: the domain has another frame in
* this physical slot. No great disaster, but for neatness,
* blow away the m2p entry. */
- set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY, __PAGE_HYPERVISOR|_PAGE_USER);
+ set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY);
}
if ( test_linear && (gfn <= d->arch.p2m.max_mapped_pfn) )
{
- lp2mfn = mfn_x(gfn_to_mfn_current(gfn));
+ lp2mfn = mfn_x(gfn_to_mfn_current(gfn, &type));
if ( lp2mfn != mfn_x(p2mfn) )
{
P2M_PRINTK("linear mismatch gfn %#lx -> mfn %#lx "
diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c
index f12a97fbde..8407beacf7 100644
--- a/xen/arch/x86/mm/shadow/multi.c
+++ b/xen/arch/x86/mm/shadow/multi.c
@@ -1470,10 +1470,14 @@ void sh_install_xen_entries_in_l4(struct vcpu *v, mfn_t gl4mfn, mfn_t sl4mfn)
shadow_l4e_from_mfn(page_to_mfn(virt_to_page(d->arch.mm_perdomain_l3)),
__PAGE_HYPERVISOR);
- /* Linear mapping */
+ /* Shadow linear mapping for 4-level shadows. N.B. for 3-level
+ * shadows on 64-bit xen, this linear mapping is later replaced by the
+ * monitor pagetable structure, which is built in make_monitor_table
+ * and maintained by sh_update_linear_entries. */
sl4e[shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START)] =
shadow_l4e_from_mfn(sl4mfn, __PAGE_HYPERVISOR);
+ /* Self linear mapping. */
if ( shadow_mode_translate(v->domain) && !shadow_mode_external(v->domain) )
{
// linear tables may not be used with translated PV guests
@@ -1745,7 +1749,7 @@ sh_make_monitor_table(struct vcpu *v)
ASSERT(pagetable_get_pfn(v->arch.monitor_table) == 0);
/* Guarantee we can get the memory we need */
- shadow_prealloc(d, SH_type_monitor_table, CONFIG_PAGING_LEVELS - 1);
+ shadow_prealloc(d, SH_type_monitor_table, CONFIG_PAGING_LEVELS);
#if CONFIG_PAGING_LEVELS == 4
{
@@ -1755,22 +1759,34 @@ sh_make_monitor_table(struct vcpu *v)
/* Remember the level of this table */
mfn_to_page(m4mfn)->shadow_flags = 4;
#if SHADOW_PAGING_LEVELS < 4
- // Install a monitor l3 table in slot 0 of the l4 table.
- // This is used for shadow linear maps.
{
- mfn_t m3mfn;
+ mfn_t m3mfn, m2mfn;
l4_pgentry_t *l4e;
+ l3_pgentry_t *l3e;
+ /* Install an l3 table and an l2 table that will hold the shadow
+ * linear map entries. This overrides the linear map entry that
+ * was installed by sh_install_xen_entries_in_l4. */
+ l4e = sh_map_domain_page(m4mfn);
+
m3mfn = shadow_alloc(d, SH_type_monitor_table, 0);
mfn_to_page(m3mfn)->shadow_flags = 3;
- l4e = sh_map_domain_page(m4mfn);
- l4e[0] = l4e_from_pfn(mfn_x(m3mfn), __PAGE_HYPERVISOR);
- sh_unmap_domain_page(l4e);
+ l4e[shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START)]
+ = l4e_from_pfn(mfn_x(m3mfn), __PAGE_HYPERVISOR);
+
+ m2mfn = shadow_alloc(d, SH_type_monitor_table, 0);
+ mfn_to_page(m2mfn)->shadow_flags = 2;
+ l3e = sh_map_domain_page(m3mfn);
+ l3e[0] = l3e_from_pfn(mfn_x(m2mfn), __PAGE_HYPERVISOR);
+ sh_unmap_domain_page(l3e);
+
if ( is_pv_32on64_vcpu(v) )
{
- // Install a monitor l2 table in slot 3 of the l3 table.
- // This is used for all Xen entries.
- mfn_t m2mfn;
- l3_pgentry_t *l3e;
+ /* For 32-on-64 PV guests, we need to map the 32-bit Xen
+ * area into its usual VAs in the monitor tables */
+ m3mfn = shadow_alloc(d, SH_type_monitor_table, 0);
+ mfn_to_page(m3mfn)->shadow_flags = 3;
+ l4e[0] = l4e_from_pfn(mfn_x(m3mfn), __PAGE_HYPERVISOR);
+
m2mfn = shadow_alloc(d, SH_type_monitor_table, 0);
mfn_to_page(m2mfn)->shadow_flags = 2;
l3e = sh_map_domain_page(m3mfn);
@@ -1778,6 +1794,8 @@ sh_make_monitor_table(struct vcpu *v)
sh_install_xen_entries_in_l2h(v, m2mfn);
sh_unmap_domain_page(l3e);
}
+
+ sh_unmap_domain_page(l4e);
}
#endif /* SHADOW_PAGING_LEVELS < 4 */
return m4mfn;
@@ -2181,21 +2199,34 @@ void sh_destroy_monitor_table(struct vcpu *v, mfn_t mmfn)
ASSERT(mfn_to_shadow_page(mmfn)->type == SH_type_monitor_table);
#if (CONFIG_PAGING_LEVELS == 4) && (SHADOW_PAGING_LEVELS != 4)
- /* Need to destroy the l3 monitor page in slot 0 too */
{
mfn_t m3mfn;
l4_pgentry_t *l4e = sh_map_domain_page(mmfn);
- ASSERT(l4e_get_flags(l4e[0]) & _PAGE_PRESENT);
- m3mfn = _mfn(l4e_get_pfn(l4e[0]));
+ l3_pgentry_t *l3e;
+ int linear_slot = shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START);
+
+ /* Need to destroy the l3 and l2 monitor pages used
+ * for the linear map */
+ ASSERT(l4e_get_flags(l4e[linear_slot]) & _PAGE_PRESENT);
+ m3mfn = _mfn(l4e_get_pfn(l4e[linear_slot]));
+ l3e = sh_map_domain_page(m3mfn);
+ ASSERT(l3e_get_flags(l3e[0]) & _PAGE_PRESENT);
+ shadow_free(d, _mfn(l3e_get_pfn(l3e[0])));
+ sh_unmap_domain_page(l3e);
+ shadow_free(d, m3mfn);
+
if ( is_pv_32on64_vcpu(v) )
{
- /* Need to destroy the l2 monitor page in slot 3 too */
- l3_pgentry_t *l3e = sh_map_domain_page(m3mfn);
+ /* Need to destroy the l3 and l2 monitor pages that map the
+ * Xen VAs at 3GB-4GB */
+ ASSERT(l4e_get_flags(l4e[0]) & _PAGE_PRESENT);
+ m3mfn = _mfn(l4e_get_pfn(l4e[0]));
+ l3e = sh_map_domain_page(m3mfn);
ASSERT(l3e_get_flags(l3e[3]) & _PAGE_PRESENT);
shadow_free(d, _mfn(l3e_get_pfn(l3e[3])));
sh_unmap_domain_page(l3e);
+ shadow_free(d, m3mfn);
}
- shadow_free(d, m3mfn);
sh_unmap_domain_page(l4e);
}
#elif CONFIG_PAGING_LEVELS == 3
@@ -3222,28 +3253,33 @@ sh_update_linear_entries(struct vcpu *v)
if ( shadow_mode_external(d) )
{
- /* Install copies of the shadow l3es into the monitor l3 table.
- * The monitor l3 table is hooked into slot 0 of the monitor
- * l4 table, so we use l3 linear indices 0 to 3 */
+ /* Install copies of the shadow l3es into the monitor l2 table
+ * that maps SH_LINEAR_PT_VIRT_START. */
shadow_l3e_t *sl3e;
- l3_pgentry_t *ml3e;
- mfn_t l3mfn;
+ l2_pgentry_t *ml2e;
int i;
/* Use linear mappings if we can; otherwise make new mappings */
- if ( v == current )
- {
- ml3e = __linear_l3_table;
- l3mfn = _mfn(l4e_get_pfn(__linear_l4_table[0]));
- }
+ if ( v == current )
+ ml2e = __linear_l2_table
+ + l2_linear_offset(SH_LINEAR_PT_VIRT_START);
else
{
+ mfn_t l3mfn, l2mfn;
l4_pgentry_t *ml4e;
+ l3_pgentry_t *ml3e;
+ int linear_slot = shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START);
ml4e = sh_map_domain_page(pagetable_get_mfn(v->arch.monitor_table));
- ASSERT(l4e_get_flags(ml4e[0]) & _PAGE_PRESENT);
- l3mfn = _mfn(l4e_get_pfn(ml4e[0]));
+
+ ASSERT(l4e_get_flags(ml4e[linear_slot]) & _PAGE_PRESENT);
+ l3mfn = _mfn(l4e_get_pfn(ml4e[linear_slot]));
ml3e = sh_map_domain_page(l3mfn);
sh_unmap_domain_page(ml4e);
+
+ ASSERT(l3e_get_flags(ml3e[0]) & _PAGE_PRESENT);
+ l2mfn = _mfn(l3e_get_pfn(ml3e[0]));
+ ml2e = sh_map_domain_page(l2mfn);
+ sh_unmap_domain_page(ml3e);
}
/* Shadow l3 tables are made up by sh_update_cr3 */
@@ -3251,15 +3287,15 @@ sh_update_linear_entries(struct vcpu *v)
for ( i = 0; i < SHADOW_L3_PAGETABLE_ENTRIES; i++ )
{
- ml3e[i] =
+ ml2e[i] =
(shadow_l3e_get_flags(sl3e[i]) & _PAGE_PRESENT)
- ? l3e_from_pfn(mfn_x(shadow_l3e_get_mfn(sl3e[i])),
+ ? l2e_from_pfn(mfn_x(shadow_l3e_get_mfn(sl3e[i])),
__PAGE_HYPERVISOR)
- : l3e_empty();
+ : l2e_empty();
}
if ( v != current )
- sh_unmap_domain_page(ml3e);
+ sh_unmap_domain_page(ml2e);
}
else
domain_crash(d); /* XXX */
@@ -4180,15 +4216,12 @@ sh_x86_emulate_write(struct vcpu *v, unsigned long vaddr, void *src,
if ( (vaddr & (bytes - 1)) && !is_hvm_vcpu(v) )
return X86EMUL_UNHANDLEABLE;
- shadow_lock(v->domain);
addr = emulate_map_dest(v, vaddr, bytes, sh_ctxt);
if ( emulate_map_dest_failed(addr) )
- {
- shadow_unlock(v->domain);
return ((addr == MAPPING_EXCEPTION) ?
X86EMUL_EXCEPTION : X86EMUL_UNHANDLEABLE);
- }
+ shadow_lock(v->domain);
memcpy(addr, src, bytes);
emulate_unmap_dest(v, addr, bytes, sh_ctxt);
@@ -4210,16 +4243,12 @@ sh_x86_emulate_cmpxchg(struct vcpu *v, unsigned long vaddr,
if ( (vaddr & (bytes - 1)) && !is_hvm_vcpu(v) )
return X86EMUL_UNHANDLEABLE;
- shadow_lock(v->domain);
-
addr = emulate_map_dest(v, vaddr, bytes, sh_ctxt);
if ( emulate_map_dest_failed(addr) )
- {
- shadow_unlock(v->domain);
return ((addr == MAPPING_EXCEPTION) ?
X86EMUL_EXCEPTION : X86EMUL_UNHANDLEABLE);
- }
+ shadow_lock(v->domain);
switch ( bytes )
{
case 1: prev = cmpxchg(((u8 *)addr), old, new); break;
@@ -4258,18 +4287,15 @@ sh_x86_emulate_cmpxchg8b(struct vcpu *v, unsigned long vaddr,
if ( (vaddr & 7) && !is_hvm_vcpu(v) )
return X86EMUL_UNHANDLEABLE;
- shadow_lock(v->domain);
-
addr = emulate_map_dest(v, vaddr, 8, sh_ctxt);
if ( emulate_map_dest_failed(addr) )
- {
- shadow_unlock(v->domain);
return ((addr == MAPPING_EXCEPTION) ?
X86EMUL_EXCEPTION : X86EMUL_UNHANDLEABLE);
- }
old = (((u64) old_hi) << 32) | (u64) old_lo;
new = (((u64) new_hi) << 32) | (u64) new_lo;
+
+ shadow_lock(v->domain);
prev = cmpxchg(((u64 *)addr), old, new);
if ( prev != old )
diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c
index 32668e9455..1377355048 100644
--- a/xen/arch/x86/smpboot.c
+++ b/xen/arch/x86/smpboot.c
@@ -54,6 +54,7 @@
#include <mach_apic.h>
#include <mach_wakecpu.h>
#include <smpboot_hooks.h>
+#include <xen/stop_machine.h>
#define set_kernel_exec(x, y) (0)
#define setup_trampoline() (bootsym_phys(trampoline_realmode_entry))
@@ -111,7 +112,7 @@ static void map_cpu_to_logical_apicid(void);
DEFINE_PER_CPU(int, cpu_state) = { 0 };
static void *stack_base[NR_CPUS] __cacheline_aligned;
-spinlock_t cpu_add_remove_lock;
+static DEFINE_SPINLOCK(cpu_add_remove_lock);
/*
* The bootstrap kernel entry code has set these up. Save them for
@@ -1163,7 +1164,6 @@ void __devinit smp_prepare_boot_cpu(void)
cpu_set(smp_processor_id(), cpu_present_map);
cpu_set(smp_processor_id(), cpu_possible_map);
per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
- spin_lock_init(&cpu_add_remove_lock);
}
#ifdef CONFIG_HOTPLUG_CPU
@@ -1208,6 +1208,15 @@ int __cpu_disable(void)
if (cpu == 0)
return -EBUSY;
+ /*
+ * Only S3 is using this path, and thus idle vcpus are running on all
+ * APs when we are called. To support full cpu hotplug, other
+ * notification mechanisms should be introduced (e.g., migrate vcpus
+ * off this physical cpu before rendezvous point).
+ */
+ if (!is_idle_vcpu(current))
+ return -EINVAL;
+
local_irq_disable();
clear_local_APIC();
/* Allow any queued timer interrupts to get serviced */
@@ -1244,6 +1253,11 @@ void __cpu_die(unsigned int cpu)
printk(KERN_ERR "CPU %u didn't die...\n", cpu);
}
+static int take_cpu_down(void *unused)
+{
+ return __cpu_disable();
+}
+
/*
* XXX: One important thing missed here is to migrate vcpus
* from dead cpu to other online ones and then put whole
@@ -1269,7 +1283,6 @@ void __cpu_die(unsigned int cpu)
int cpu_down(unsigned int cpu)
{
int err = 0;
- cpumask_t mask;
spin_lock(&cpu_add_remove_lock);
if (num_online_cpus() == 1) {
@@ -1283,11 +1296,10 @@ int cpu_down(unsigned int cpu)
}
printk("Prepare to bring CPU%d down...\n", cpu);
- /* Send notification to remote idle vcpu */
- cpus_clear(mask);
- cpu_set(cpu, mask);
- per_cpu(cpu_state, cpu) = CPU_DYING;
- smp_send_event_check_mask(mask);
+
+ err = stop_machine_run(take_cpu_down, NULL, cpu);
+ if ( err < 0 )
+ goto out;
__cpu_die(cpu);
diff --git a/xen/arch/x86/trace.c b/xen/arch/x86/trace.c
index ddb32202bd..65e66a3280 100644
--- a/xen/arch/x86/trace.c
+++ b/xen/arch/x86/trace.c
@@ -15,9 +15,6 @@ asmlinkage void trace_hypercall(void)
{
struct cpu_user_regs *regs = guest_cpu_user_regs();
- if ( !tb_init_done )
- return;
-
#ifdef __x86_64__
if ( is_pv_32on64_vcpu(current) )
{
@@ -52,9 +49,6 @@ asmlinkage void trace_hypercall(void)
void __trace_pv_trap(int trapnr, unsigned long eip,
int use_error_code, unsigned error_code)
{
- if ( !tb_init_done )
- return;
-
#ifdef __x86_64__
if ( is_pv_32on64_vcpu(current) )
{
@@ -99,9 +93,6 @@ void __trace_pv_page_fault(unsigned long addr, unsigned error_code)
{
unsigned long eip = guest_cpu_user_regs()->eip;
- if ( !tb_init_done )
- return;
-
#ifdef __x86_64__
if ( is_pv_32on64_vcpu(current) )
{
@@ -135,9 +126,6 @@ void __trace_pv_page_fault(unsigned long addr, unsigned error_code)
void __trace_trap_one_addr(unsigned event, unsigned long va)
{
- if ( !tb_init_done )
- return;
-
#ifdef __x86_64__
if ( is_pv_32on64_vcpu(current) )
{
@@ -155,9 +143,6 @@ void __trace_trap_one_addr(unsigned event, unsigned long va)
void __trace_trap_two_addr(unsigned event, unsigned long va1,
unsigned long va2)
{
- if ( !tb_init_done )
- return;
-
#ifdef __x86_64__
if ( is_pv_32on64_vcpu(current) )
{
@@ -185,9 +170,6 @@ void __trace_ptwr_emulation(unsigned long addr, l1_pgentry_t npte)
{
unsigned long eip = guest_cpu_user_regs()->eip;
- if ( !tb_init_done )
- return;
-
/* We have a couple of different modes to worry about:
* - 32-on-32: 32-bit pte, 32-bit virtual addresses
* - pae-on-pae, pae-on-64: 64-bit pte, 32-bit virtual addresses
diff --git a/xen/arch/x86/x86_emulate.c b/xen/arch/x86/x86_emulate.c
index ee0118a7b3..b240a0a48e 100644
--- a/xen/arch/x86/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate.c
@@ -1710,11 +1710,14 @@ x86_emulate(
switch ( src.bytes )
{
case 1:
+ dst.val = (uint8_t)dst.val;
dst.val *= src.val;
if ( (uint8_t)dst.val != (uint16_t)dst.val )
_regs.eflags |= EFLG_OF|EFLG_CF;
+ dst.bytes = 2;
break;
case 2:
+ dst.val = (uint16_t)dst.val;
dst.val *= src.val;
if ( (uint16_t)dst.val != (uint32_t)dst.val )
_regs.eflags |= EFLG_OF|EFLG_CF;
@@ -1722,6 +1725,7 @@ x86_emulate(
break;
#ifdef __x86_64__
case 4:
+ dst.val = (uint32_t)dst.val;
dst.val *= src.val;
if ( (uint32_t)dst.val != dst.val )
_regs.eflags |= EFLG_OF|EFLG_CF;
@@ -1751,6 +1755,7 @@ x86_emulate(
(uint16_t)(int8_t)dst.val);
if ( (int8_t)dst.val != (uint16_t)dst.val )
_regs.eflags |= EFLG_OF|EFLG_CF;
+ dst.bytes = 2;
break;
case 2:
dst.val = ((uint32_t)(int16_t)src.val *
@@ -2221,11 +2226,12 @@ x86_emulate(
dst.bytes = !(b & 1) ? 1 : (op_bytes == 8) ? 4 : op_bytes;
dst.mem.seg = x86_seg_es;
dst.mem.off = truncate_ea(_regs.edi);
- if ( (nr_reps > 1) && (ops->rep_ins != NULL) )
+ if ( (nr_reps > 1) && (ops->rep_ins != NULL) &&
+ ((rc = ops->rep_ins((uint16_t)_regs.edx, dst.mem.seg,
+ dst.mem.off, dst.bytes,
+ &nr_reps, ctxt)) != X86EMUL_UNHANDLEABLE) )
{
- if ( (rc = ops->rep_ins((uint16_t)_regs.edx, dst.mem.seg,
- dst.mem.off, dst.bytes,
- &nr_reps, ctxt)) != 0 )
+ if ( rc != 0 )
goto done;
}
else
@@ -2248,11 +2254,12 @@ x86_emulate(
unsigned long nr_reps = get_rep_prefix();
generate_exception_if(!mode_iopl(), EXC_GP);
dst.bytes = !(b & 1) ? 1 : (op_bytes == 8) ? 4 : op_bytes;
- if ( (nr_reps > 1) && (ops->rep_outs != NULL) )
+ if ( (nr_reps > 1) && (ops->rep_outs != NULL) &&
+ ((rc = ops->rep_outs(ea.mem.seg, truncate_ea(_regs.esi),
+ (uint16_t)_regs.edx, dst.bytes,
+ &nr_reps, ctxt)) != X86EMUL_UNHANDLEABLE) )
{
- if ( (rc = ops->rep_outs(ea.mem.seg, truncate_ea(_regs.esi),
- (uint16_t)_regs.edx, dst.bytes,
- &nr_reps, ctxt)) != 0 )
+ if ( rc != 0 )
goto done;
}
else
@@ -2399,11 +2406,12 @@ x86_emulate(
dst.bytes = (d & ByteOp) ? 1 : op_bytes;
dst.mem.seg = x86_seg_es;
dst.mem.off = truncate_ea(_regs.edi);
- if ( (nr_reps > 1) && (ops->rep_movs != NULL) )
+ if ( (nr_reps > 1) && (ops->rep_movs != NULL) &&
+ ((rc = ops->rep_movs(ea.mem.seg, truncate_ea(_regs.esi),
+ dst.mem.seg, dst.mem.off, dst.bytes,
+ &nr_reps, ctxt)) != X86EMUL_UNHANDLEABLE) )
{
- if ( (rc = ops->rep_movs(ea.mem.seg, truncate_ea(_regs.esi),
- dst.mem.seg, dst.mem.off, dst.bytes,
- &nr_reps, ctxt)) != 0 )
+ if ( rc != 0 )
goto done;
}
else
diff --git a/xen/common/Makefile b/xen/common/Makefile
index 1bf38310bf..631ac384bd 100644
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -16,6 +16,7 @@ obj-y += sched_sedf.o
obj-y += schedule.o
obj-y += shutdown.o
obj-y += softirq.o
+obj-y += stop_machine.o
obj-y += string.o
obj-y += symbols.o
obj-y += sysctl.o
diff --git a/xen/common/stop_machine.c b/xen/common/stop_machine.c
new file mode 100644
index 0000000000..1411b9f197
--- /dev/null
+++ b/xen/common/stop_machine.c
@@ -0,0 +1,158 @@
+/******************************************************************************
+ * common/stop_machine.c
+ *
+ * Facilities to put whole machine in a safe 'stop' state
+ *
+ * Copyright 2005 Rusty Russell rusty@rustcorp.com.au IBM Corporation
+ * Copyright 2008 Kevin Tian <kevin.tian@intel.com>, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <xen/config.h>
+#include <xen/init.h>
+#include <xen/sched.h>
+#include <xen/spinlock.h>
+#include <xen/softirq.h>
+#include <xen/errno.h>
+#include <xen/smp.h>
+#include <asm/current.h>
+#include <asm/processor.h>
+
+enum stopmachine_state {
+ STOPMACHINE_START,
+ STOPMACHINE_PREPARE,
+ STOPMACHINE_DISABLE_IRQ,
+ STOPMACHINE_INVOKE,
+ STOPMACHINE_EXIT
+};
+
+struct stopmachine_data {
+ unsigned int nr_cpus;
+
+ enum stopmachine_state state;
+ atomic_t done;
+
+ unsigned int fn_cpu;
+ int fn_result;
+ int (*fn)(void *);
+ void *fn_data;
+};
+
+static struct stopmachine_data stopmachine_data;
+static DEFINE_SPINLOCK(stopmachine_lock);
+
+static void stopmachine_set_state(enum stopmachine_state state)
+{
+ atomic_set(&stopmachine_data.done, 0);
+ smp_wmb();
+ stopmachine_data.state = state;
+ while ( atomic_read(&stopmachine_data.done) != stopmachine_data.nr_cpus )
+ cpu_relax();
+}
+
+int stop_machine_run(int (*fn)(void *), void *data, unsigned int cpu)
+{
+ cpumask_t allbutself;
+ unsigned int i, nr_cpus;
+ int ret;
+
+ BUG_ON(!local_irq_is_enabled());
+
+ allbutself = cpu_online_map;
+ cpu_clear(smp_processor_id(), allbutself);
+ nr_cpus = cpus_weight(allbutself);
+
+ if ( nr_cpus == 0 )
+ {
+ BUG_ON(cpu != smp_processor_id());
+ return (*fn)(data);
+ }
+
+ /* Note: We shouldn't spin on lock when it's held by others since others
+ * is expecting this cpus to enter softirq context. Or else deadlock
+ * is caused.
+ */
+ if ( !spin_trylock(&stopmachine_lock) )
+ return -EBUSY;
+
+ stopmachine_data.fn = fn;
+ stopmachine_data.fn_data = data;
+ stopmachine_data.nr_cpus = nr_cpus;
+ stopmachine_data.fn_cpu = cpu;
+ atomic_set(&stopmachine_data.done, 0);
+ stopmachine_data.state = STOPMACHINE_START;
+
+ smp_wmb();
+
+ for_each_cpu_mask ( i, allbutself )
+ cpu_raise_softirq(i, STOPMACHINE_SOFTIRQ);
+
+ stopmachine_set_state(STOPMACHINE_PREPARE);
+
+ local_irq_disable();
+ stopmachine_set_state(STOPMACHINE_DISABLE_IRQ);
+
+ if ( cpu == smp_processor_id() )
+ stopmachine_data.fn_result = (*fn)(data);
+ stopmachine_set_state(STOPMACHINE_INVOKE);
+ ret = stopmachine_data.fn_result;
+
+ stopmachine_set_state(STOPMACHINE_EXIT);
+ local_irq_enable();
+
+ spin_unlock(&stopmachine_lock);
+
+ return ret;
+}
+
+static void stopmachine_softirq(void)
+{
+ enum stopmachine_state state = STOPMACHINE_START;
+
+ smp_mb();
+
+ while ( state != STOPMACHINE_EXIT )
+ {
+ while ( stopmachine_data.state == state )
+ cpu_relax();
+
+ state = stopmachine_data.state;
+ switch ( state )
+ {
+ case STOPMACHINE_DISABLE_IRQ:
+ local_irq_disable();
+ break;
+ case STOPMACHINE_INVOKE:
+ if ( stopmachine_data.fn_cpu == smp_processor_id() )
+ stopmachine_data.fn_result =
+ stopmachine_data.fn(stopmachine_data.fn_data);
+ break;
+ default:
+ break;
+ }
+
+ smp_mb();
+ atomic_inc(&stopmachine_data.done);
+ }
+
+ local_irq_enable();
+}
+
+static int __init cpu_stopmachine_init(void)
+{
+ open_softirq(STOPMACHINE_SOFTIRQ, stopmachine_softirq);
+ return 0;
+}
+__initcall(cpu_stopmachine_init);
diff --git a/xen/common/trace.c b/xen/common/trace.c
index 9af70798bb..863816b9ee 100644
--- a/xen/common/trace.c
+++ b/xen/common/trace.c
@@ -239,14 +239,46 @@ static inline int calc_rec_size(int cycles, int extra)
return rec_size;
}
+static inline int calc_unconsumed_bytes(struct t_buf *buf)
+{
+ int x = buf->prod - buf->cons;
+ if ( x < 0 )
+ x += 2*data_size;
+
+ ASSERT(x >= 0);
+ ASSERT(x <= data_size);
+
+ return x;
+}
+
static inline int calc_bytes_to_wrap(struct t_buf *buf)
{
- return data_size - (buf->prod % data_size);
+ int x = data_size - buf->prod;
+ if ( x <= 0 )
+ x += data_size;
+
+ ASSERT(x > 0);
+ ASSERT(x <= data_size);
+
+ return x;
+}
+
+static inline int calc_bytes_avail(struct t_buf *buf)
+{
+ return data_size - calc_unconsumed_bytes(buf);
}
-static inline unsigned calc_bytes_avail(struct t_buf *buf)
+static inline struct t_rec *
+next_record(struct t_buf *buf)
{
- return data_size - (buf->prod - buf->cons);
+ int x = buf->prod;
+ if ( x >= data_size )
+ x -= data_size;
+
+ ASSERT(x >= 0);
+ ASSERT(x < data_size);
+
+ return (struct t_rec *)&this_cpu(t_data)[x];
}
static inline int __insert_record(struct t_buf *buf,
@@ -260,24 +292,25 @@ static inline int __insert_record(struct t_buf *buf,
unsigned char *dst;
unsigned long extra_word = extra/sizeof(u32);
int local_rec_size = calc_rec_size(cycles, extra);
+ uint32_t next;
BUG_ON(local_rec_size != rec_size);
+ BUG_ON(extra & 3);
/* Double-check once more that we have enough space.
* Don't bugcheck here, in case the userland tool is doing
* something stupid. */
if ( calc_bytes_avail(buf) < rec_size )
{
- printk("%s: %u bytes left (%u - (%u - %u)) recsize %u.\n",
+ printk("%s: %u bytes left (%u - ((%u - %u) %% %u) recsize %u.\n",
__func__,
- data_size - (buf->prod - buf->cons),
- data_size,
- buf->prod, buf->cons, rec_size);
+ calc_bytes_avail(buf),
+ data_size, buf->prod, buf->cons, data_size, rec_size);
return 0;
}
rmb();
- rec = (struct t_rec *)&this_cpu(t_data)[buf->prod % data_size];
+ rec = next_record(buf);
rec->event = event;
rec->extra_u32 = extra_word;
dst = (unsigned char *)rec->u.nocycles.extra_u32;
@@ -293,7 +326,13 @@ static inline int __insert_record(struct t_buf *buf,
memcpy(dst, extra_data, extra);
wmb();
- buf->prod += rec_size;
+
+ next = buf->prod + rec_size;
+ if ( next >= 2*data_size )
+ next -= 2*data_size;
+ ASSERT(next >= 0);
+ ASSERT(next < 2*data_size);
+ buf->prod = next;
return rec_size;
}
@@ -395,7 +434,7 @@ void __trace_var(u32 event, int cycles, int extra, unsigned char *extra_data)
local_irq_save(flags);
- started_below_highwater = ((buf->prod - buf->cons) < t_buf_highwater);
+ started_below_highwater = (calc_unconsumed_bytes(buf) < t_buf_highwater);
/* Calculate the record size */
rec_size = calc_rec_size(cycles, extra);
@@ -413,10 +452,6 @@ void __trace_var(u32 event, int cycles, int extra, unsigned char *extra_data)
total_size = 0;
/* First, check to see if we need to include a lost_record.
- *
- * calc_bytes_to_wrap() involves integer division, which we'd like to
- * avoid if we can. So do the math, check it in debug versions, and
- * do a final check always if we happen to write a record.
*/
if ( this_cpu(lost_records) )
{
@@ -425,25 +460,18 @@ void __trace_var(u32 event, int cycles, int extra, unsigned char *extra_data)
total_size += bytes_to_wrap;
bytes_to_wrap = data_size;
}
- else
- {
- bytes_to_wrap -= LOST_REC_SIZE;
- if ( bytes_to_wrap == 0 )
- bytes_to_wrap = data_size;
- }
total_size += LOST_REC_SIZE;
+ bytes_to_wrap -= LOST_REC_SIZE;
+
+ /* LOST_REC might line up perfectly with the buffer wrap */
+ if ( bytes_to_wrap == 0 )
+ bytes_to_wrap = data_size;
}
if ( rec_size > bytes_to_wrap )
{
total_size += bytes_to_wrap;
- bytes_to_wrap = data_size;
}
- else
- {
- bytes_to_wrap -= rec_size;
- }
-
total_size += rec_size;
/* Do we have enough space for everything? */
@@ -466,14 +494,12 @@ void __trace_var(u32 event, int cycles, int extra, unsigned char *extra_data)
insert_wrap_record(buf, LOST_REC_SIZE);
bytes_to_wrap = data_size;
}
- else
- {
- bytes_to_wrap -= LOST_REC_SIZE;
- /* LOST_REC might line up perfectly with the buffer wrap */
- if ( bytes_to_wrap == 0 )
- bytes_to_wrap = data_size;
- }
insert_lost_records(buf);
+ bytes_to_wrap -= LOST_REC_SIZE;
+
+ /* LOST_REC might line up perfectly with the buffer wrap */
+ if ( bytes_to_wrap == 0 )
+ bytes_to_wrap = data_size;
}
if ( rec_size > bytes_to_wrap )
@@ -486,7 +512,7 @@ void __trace_var(u32 event, int cycles, int extra, unsigned char *extra_data)
/* Notify trace buffer consumer that we've crossed the high water mark. */
if ( started_below_highwater &&
- ((buf->prod - buf->cons) >= t_buf_highwater) )
+ (calc_unconsumed_bytes(buf) >= t_buf_highwater) )
raise_softirq(TRACE_SOFTIRQ);
}
diff --git a/xen/include/asm-x86/hvm/iommu.h b/xen/include/asm-x86/hvm/iommu.h
index 210530947f..5ac7aef1c9 100644
--- a/xen/include/asm-x86/hvm/iommu.h
+++ b/xen/include/asm-x86/hvm/iommu.h
@@ -48,6 +48,9 @@ struct hvm_iommu {
int domain_id;
int paging_mode;
void *root_table;
+
+ /* iommu_ops */
+ struct iommu_ops *platform_ops;
};
#endif // __ASM_X86_HVM_IOMMU_H__
diff --git a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h
index 56089a5317..bece80c5db 100644
--- a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h
+++ b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h
@@ -263,6 +263,10 @@
#define IOMMU_INV_IOMMU_PAGES_ADDR_HIGH_MASK 0xFFFFFFFF
#define IOMMU_INV_IOMMU_PAGES_ADDR_HIGH_SHIFT 0
+/* INVALIDATE_DEVTAB_ENTRY command */
+#define IOMMU_INV_DEVTAB_ENTRY_DEVICE_ID_MASK 0x0000FFFF
+#define IOMMU_INV_DEVTAB_ENTRY_DEVICE_ID_SHIFT 0
+
/* Event Log */
#define IOMMU_EVENT_LOG_BASE_LOW_OFFSET 0x10
#define IOMMU_EVENT_LOG_BASE_HIGH_OFFSET 0x14
@@ -415,5 +419,6 @@
#define IOMMU_PAGE_TABLE_LEVEL_4 4
#define IOMMU_IO_WRITE_ENABLED 1
#define IOMMU_IO_READ_ENABLED 1
+#define HACK_BIOS_SETTINGS 0
#endif /* _ASM_X86_64_AMD_IOMMU_DEFS_H */
diff --git a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h
index d9b21a5973..592f908946 100644
--- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h
+++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h
@@ -27,13 +27,15 @@
list_for_each_entry(amd_iommu, \
&amd_iommu_head, list)
+#define for_each_pdev(domain, pdev) \
+ list_for_each_entry(pdev, \
+ &(domain->arch.hvm_domain.hvm_iommu.pdev_list), list)
+
#define DMA_32BIT_MASK 0x00000000ffffffffULL
#define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK)
-#define PAGE_SHIFT_4K (12)
-#define PAGE_SIZE_4K (1UL << PAGE_SHIFT_4K)
-#define PAGE_MASK_4K (((u64)-1) << PAGE_SHIFT_4K)
-typedef int (*iommu_detect_callback_ptr_t)(u8 bus, u8 dev, u8 func, u8 cap_ptr);
+typedef int (*iommu_detect_callback_ptr_t)(
+ u8 bus, u8 dev, u8 func, u8 cap_ptr);
/* amd-iommu-detect functions */
int __init scan_for_iommu(iommu_detect_callback_ptr_t iommu_detect_callback);
@@ -49,16 +51,20 @@ void __init register_iommu_cmd_buffer_in_mmio_space(struct amd_iommu *iommu);
void __init enable_iommu(struct amd_iommu *iommu);
/* mapping functions */
-int amd_iommu_map_page(struct domain *d, unsigned long gfn,
- unsigned long mfn);
+int amd_iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn);
int amd_iommu_unmap_page(struct domain *d, unsigned long gfn);
+void *amd_iommu_get_vptr_from_page_table_entry(u32 *entry);
/* device table functions */
void amd_iommu_set_dev_table_entry(u32 *dte,
u64 root_ptr, u16 domain_id, u8 paging_mode);
+int amd_iommu_is_dte_page_translation_valid(u32 *entry);
+void invalidate_dev_table_entry(struct amd_iommu *iommu,
+ u16 devic_id);
/* send cmd to iommu */
int send_iommu_command(struct amd_iommu *iommu, u32 cmd[]);
+void flush_command_buffer(struct amd_iommu *iommu);
/* iommu domain funtions */
int amd_iommu_domain_init(struct domain *domain);
diff --git a/xen/include/asm-x86/hvm/trace.h b/xen/include/asm-x86/hvm/trace.h
index 54c578f912..cb4dc10ad8 100644
--- a/xen/include/asm-x86/hvm/trace.h
+++ b/xen/include/asm-x86/hvm/trace.h
@@ -31,14 +31,15 @@
#define DO_TRC_HVM_CLTS 1
#define DO_TRC_HVM_LMSW 1
-
-
static inline void hvmtrace_vmexit(struct vcpu *v,
unsigned long rip,
unsigned long exit_reason)
{
+ if ( likely(!tb_init_done) )
+ return;
+
#ifdef __x86_64__
- if(hvm_long_mode_enabled(v))
+ if ( hvm_long_mode_enabled(v) )
{
struct {
unsigned did:16, vid:16;
@@ -50,9 +51,12 @@ static inline void hvmtrace_vmexit(struct vcpu *v,
d.vid = v->vcpu_id;
d.exit_reason = exit_reason;
d.rip = rip;
- trace_var(TRC_HVM_VMEXIT64, 1/*cycles*/, sizeof(d), (unsigned char *)&d);
- } else {
+ __trace_var(TRC_HVM_VMEXIT64, 1/*cycles*/, sizeof(d),
+ (unsigned char *)&d);
+ }
+ else
#endif
+ {
struct {
unsigned did:16, vid:16;
unsigned exit_reason:32;
@@ -63,10 +67,9 @@ static inline void hvmtrace_vmexit(struct vcpu *v,
d.vid = v->vcpu_id;
d.exit_reason = exit_reason;
d.eip = rip;
- trace_var(TRC_HVM_VMEXIT, 1/*cycles*/, sizeof(d), (unsigned char *)&d);
-#ifdef __x86_64__
+ __trace_var(TRC_HVM_VMEXIT, 1/*cycles*/, sizeof(d),
+ (unsigned char *)&d);
}
-#endif
}
@@ -75,9 +78,13 @@ static inline void hvmtrace_vmentry(struct vcpu *v)
struct {
unsigned did:16, vid:16;
} d;
+
+ if ( likely(!tb_init_done) )
+ return;
+
d.did = v->domain->domain_id;
d.vid = v->vcpu_id;
- trace_var(TRC_HVM_VMENTRY, 1/*cycles*/, sizeof(d), (unsigned char *)&d);
+ __trace_var(TRC_HVM_VMENTRY, 1/*cycles*/, sizeof(d), (unsigned char *)&d);
}
static inline void hvmtrace_msr_read(struct vcpu *v, u32 ecx, u64 msr_content)
@@ -87,11 +94,16 @@ static inline void hvmtrace_msr_read(struct vcpu *v, u32 ecx, u64 msr_content)
u32 ecx;
u64 msr_content;
} d;
+
+ if ( likely(!tb_init_done) )
+ return;
+
d.did = v->domain->domain_id;
d.vid = v->vcpu_id;
d.ecx = ecx;
d.msr_content = msr_content;
- trace_var(TRC_HVM_MSR_READ, 0/*!cycles*/, sizeof(d), (unsigned char *)&d);
+ __trace_var(TRC_HVM_MSR_READ, 0/*!cycles*/, sizeof(d),
+ (unsigned char *)&d);
}
static inline void hvmtrace_msr_write(struct vcpu *v, u32 ecx, u64 msr_content)
@@ -101,18 +113,26 @@ static inline void hvmtrace_msr_write(struct vcpu *v, u32 ecx, u64 msr_content)
u32 ecx;
u64 msr_content;
} d;
+
+ if ( likely(!tb_init_done) )
+ return;
+
d.did = v->domain->domain_id;
d.vid = v->vcpu_id;
d.ecx = ecx;
d.msr_content = msr_content;
- trace_var(TRC_HVM_MSR_WRITE, 0/*!cycles*/,sizeof(d), (unsigned char *)&d);
+ __trace_var(TRC_HVM_MSR_WRITE, 0/*!cycles*/,sizeof(d),
+ (unsigned char *)&d);
}
static inline void hvmtrace_pf_xen(struct vcpu *v, unsigned long va,
u32 error_code)
{
+ if ( likely(!tb_init_done) )
+ return;
+
#ifdef __x86_64__
- if(hvm_long_mode_enabled(v))
+ if( hvm_long_mode_enabled(v) )
{
struct {
unsigned did:16, vid:16;
@@ -123,10 +143,12 @@ static inline void hvmtrace_pf_xen(struct vcpu *v, unsigned long va,
d.vid = v->vcpu_id;
d.error_code = error_code;
d.va = va;
- trace_var(TRC_HVM_PF_XEN64, 0/*!cycles*/,sizeof(d),
- (unsigned char *)&d);
- } else {
+ __trace_var(TRC_HVM_PF_XEN64, 0/*!cycles*/,sizeof(d),
+ (unsigned char *)&d);
+ }
+ else
#endif
+ {
struct {
unsigned did:16, vid:16;
u32 error_code;
@@ -136,15 +158,14 @@ static inline void hvmtrace_pf_xen(struct vcpu *v, unsigned long va,
d.vid = v->vcpu_id;
d.error_code = error_code;
d.va = va;
- trace_var(TRC_HVM_PF_XEN, 0/*!cycles*/,sizeof(d), (unsigned char *)&d);
-#ifdef __x86_64__
+ __trace_var(TRC_HVM_PF_XEN, 0/*!cycles*/,sizeof(d),
+ (unsigned char *)&d);
}
-#endif
}
#define HVMTRACE_ND(evt, vcpu, count, d1, d2, d3, d4) \
do { \
- if (DO_TRC_HVM_ ## evt) \
+ if ( unlikely(tb_init_done) && DO_TRC_HVM_ ## evt ) \
{ \
struct { \
unsigned did:16, vid:16; \
@@ -156,8 +177,8 @@ static inline void hvmtrace_pf_xen(struct vcpu *v, unsigned long va,
_d.d[1]=(d2); \
_d.d[2]=(d3); \
_d.d[3]=(d4); \
- trace_var(TRC_HVM_ ## evt, 0/*!cycles*/, \
- sizeof(u32)*count+1, (unsigned char *)&_d); \
+ __trace_var(TRC_HVM_ ## evt, 0/*!cycles*/, \
+ sizeof(u32)*count+1, (unsigned char *)&_d); \
} \
} while(0)
@@ -167,7 +188,8 @@ static inline void hvmtrace_pf_xen(struct vcpu *v, unsigned long va,
#define HVMTRACE_1D(evt, vcpu, d1) HVMTRACE_ND(evt, vcpu, 1, d1, 0, 0, 0)
#define HVMTRACE_0D(evt, vcpu) HVMTRACE_ND(evt, vcpu, 0, 0, 0, 0, 0)
-#endif //__ASM_X86_HVM_TRACE_H__
+#endif /* __ASM_X86_HVM_TRACE_H__ */
+
/*
* Local variables:
* mode: C
diff --git a/xen/include/asm-x86/hvm/vmx/intel-iommu.h b/xen/include/asm-x86/hvm/vmx/intel-iommu.h
index 0f9c08c50f..07b07c09d3 100644
--- a/xen/include/asm-x86/hvm/vmx/intel-iommu.h
+++ b/xen/include/asm-x86/hvm/vmx/intel-iommu.h
@@ -422,8 +422,6 @@ struct poll_info {
#define VTD_PAGE_TABLE_LEVEL_3 3
#define VTD_PAGE_TABLE_LEVEL_4 4
-typedef paddr_t dma_addr_t;
-
#define DEFAULT_DOMAIN_ADDRESS_WIDTH 48
#define MAX_IOMMUS 32
#define MAX_IOMMU_REGS 0xc0
@@ -447,8 +445,10 @@ struct ir_ctrl {
};
struct iommu_flush {
- int (*context)(void *iommu, u16 did, u16 source_id, u8 function_mask, u64 type, int non_present_entry_flush);
- int (*iotlb)(void *iommu, u16 did, u64 addr, unsigned int size_order, u64 type, int non_present_entry_flush);
+ int (*context)(void *iommu, u16 did, u16 source_id,
+ u8 function_mask, u64 type, int non_present_entry_flush);
+ int (*iotlb)(void *iommu, u16 did, u64 addr, unsigned int size_order,
+ u64 type, int non_present_entry_flush);
};
struct intel_iommu {
diff --git a/xen/include/asm-x86/io_apic.h b/xen/include/asm-x86/io_apic.h
index e8e102a6b8..86c91b6762 100644
--- a/xen/include/asm-x86/io_apic.h
+++ b/xen/include/asm-x86/io_apic.h
@@ -6,6 +6,7 @@
#include <asm/mpspec.h>
#include <asm/apicdef.h>
#include <asm/fixmap.h>
+#include <asm/iommu.h>
/*
* Intel IO-APIC support for SMP and UP systems.
@@ -124,12 +125,16 @@ extern int mpc_default_type;
static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
{
+ if (vtd_enabled)
+ return io_apic_read_remap_rte(apic, reg);
*IO_APIC_BASE(apic) = reg;
return *(IO_APIC_BASE(apic)+4);
}
static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
{
+ if (vtd_enabled)
+ return io_apic_write_remap_rte(apic, reg, value);
*IO_APIC_BASE(apic) = reg;
*(IO_APIC_BASE(apic)+4) = value;
}
diff --git a/xen/include/asm-x86/iommu.h b/xen/include/asm-x86/iommu.h
index daec64bf76..6707f94cbe 100644
--- a/xen/include/asm-x86/iommu.h
+++ b/xen/include/asm-x86/iommu.h
@@ -28,7 +28,9 @@
#include <public/domctl.h>
extern int vtd_enabled;
+extern int amd_iommu_enabled;
+#define iommu_enabled ( amd_iommu_enabled || vtd_enabled )
#define domain_hvm_iommu(d) (&d->arch.hvm_domain.hvm_iommu)
#define domain_vmx_iommu(d) (&d->arch.hvm_domain.hvm_iommu.vmx_iommu)
#define iommu_qi_ctrl(iommu) (&(iommu->intel.qi_ctrl));
@@ -72,17 +74,29 @@ int iommu_domain_init(struct domain *d);
void iommu_domain_destroy(struct domain *d);
int device_assigned(u8 bus, u8 devfn);
int assign_device(struct domain *d, u8 bus, u8 devfn);
-int iommu_map_page(struct domain *d, dma_addr_t gfn, dma_addr_t mfn);
-int iommu_unmap_page(struct domain *d, dma_addr_t gfn);
-void iommu_flush(struct domain *d, dma_addr_t gfn, u64 *p2m_entry);
+int iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn);
+int iommu_unmap_page(struct domain *d, unsigned long gfn);
+void iommu_flush(struct domain *d, unsigned long gfn, u64 *p2m_entry);
void iommu_set_pgd(struct domain *d);
void iommu_domain_teardown(struct domain *d);
int hvm_do_IRQ_dpci(struct domain *d, unsigned int irq);
int dpci_ioport_intercept(ioreq_t *p);
int pt_irq_create_bind_vtd(struct domain *d,
xen_domctl_bind_pt_irq_t *pt_irq_bind);
+unsigned int io_apic_read_remap_rte(
+ unsigned int apic, unsigned int reg);
+void io_apic_write_remap_rte(unsigned int apic,
+ unsigned int reg, unsigned int value);
#define PT_IRQ_TIME_OUT MILLISECS(8)
#define VTDPREFIX "[VT-D]"
+struct iommu_ops {
+ int (*init)(struct domain *d);
+ int (*assign_device)(struct domain *d, u8 bus, u8 devfn);
+ void (*teardown)(struct domain *d);
+ int (*map_page)(struct domain *d, unsigned long gfn, unsigned long mfn);
+ int (*unmap_page)(struct domain *d, unsigned long gfn);
+};
+
#endif /* _IOMMU_H_ */
diff --git a/xen/include/asm-x86/smp.h b/xen/include/asm-x86/smp.h
index 55b8cf7705..cf5159603d 100644
--- a/xen/include/asm-x86/smp.h
+++ b/xen/include/asm-x86/smp.h
@@ -51,12 +51,11 @@ extern u8 x86_cpu_to_apicid[];
/* State of each CPU. */
#define CPU_ONLINE 0x0002 /* CPU is up */
-#define CPU_DYING 0x0003 /* CPU is requested to die */
#define CPU_DEAD 0x0004 /* CPU is dead */
DECLARE_PER_CPU(int, cpu_state);
#ifdef CONFIG_HOTPLUG_CPU
-#define cpu_is_offline(cpu) unlikely(per_cpu(cpu_state,cpu) == CPU_DYING)
+#define cpu_is_offline(cpu) unlikely(!cpu_online(cpu))
extern int cpu_down(unsigned int cpu);
extern int cpu_up(unsigned int cpu);
extern void cpu_exit_clear(void);
diff --git a/xen/include/asm-x86/trace.h b/xen/include/asm-x86/trace.h
index c8b13c4b86..e65b5de6ee 100644
--- a/xen/include/asm-x86/trace.h
+++ b/xen/include/asm-x86/trace.h
@@ -8,7 +8,7 @@ void __trace_pv_trap(int trapnr, unsigned long eip,
static inline void trace_pv_trap(int trapnr, unsigned long eip,
int use_error_code, unsigned error_code)
{
- if ( tb_init_done )
+ if ( unlikely(tb_init_done) )
__trace_pv_trap(trapnr, eip, use_error_code, error_code);
}
@@ -16,14 +16,14 @@ void __trace_pv_page_fault(unsigned long addr, unsigned error_code);
static inline void trace_pv_page_fault(unsigned long addr,
unsigned error_code)
{
- if ( tb_init_done )
+ if ( unlikely(tb_init_done) )
__trace_pv_page_fault(addr, error_code);
}
void __trace_trap_one_addr(unsigned event, unsigned long va);
static inline void trace_trap_one_addr(unsigned event, unsigned long va)
{
- if ( tb_init_done )
+ if ( unlikely(tb_init_done) )
__trace_trap_one_addr(event, va);
}
@@ -32,14 +32,14 @@ void __trace_trap_two_addr(unsigned event, unsigned long va1,
static inline void trace_trap_two_addr(unsigned event, unsigned long va1,
unsigned long va2)
{
- if ( tb_init_done )
+ if ( unlikely(tb_init_done) )
__trace_trap_two_addr(event, va1, va2);
}
void __trace_ptwr_emulation(unsigned long addr, l1_pgentry_t npte);
static inline void trace_ptwr_emulation(unsigned long addr, l1_pgentry_t npte)
{
- if ( tb_init_done )
+ if ( unlikely(tb_init_done) )
__trace_ptwr_emulation(addr, npte);
}
diff --git a/xen/include/public/hvm/params.h b/xen/include/public/hvm/params.h
index 486499816d..aad2196db3 100644
--- a/xen/include/public/hvm/params.h
+++ b/xen/include/public/hvm/params.h
@@ -81,6 +81,9 @@
#define HVMPTM_no_missed_ticks_pending 2
#define HVMPTM_one_missed_tick_pending 3
-#define HVM_NR_PARAMS 11
+/* Boolean: Enable virtual HPET (high-precision event timer)? (x86-only) */
+#define HVM_PARAM_HPET_ENABLED 11
+
+#define HVM_NR_PARAMS 12
#endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
diff --git a/xen/include/public/io/ring.h b/xen/include/public/io/ring.h
index 355eba5545..6ce1d0d485 100644
--- a/xen/include/public/io/ring.h
+++ b/xen/include/public/io/ring.h
@@ -27,6 +27,14 @@
#ifndef __XEN_PUBLIC_IO_RING_H__
#define __XEN_PUBLIC_IO_RING_H__
+#include "../xen-compat.h"
+
+#if __XEN_INTERFACE_VERSION__ < 0x00030208
+#define xen_mb() mb()
+#define xen_rmb() rmb()
+#define xen_wmb() wmb()
+#endif
+
typedef unsigned int RING_IDX;
/* Round a 32-bit unsigned constant down to the nearest power of two. */
@@ -211,12 +219,12 @@ typedef struct __name##_back_ring __name##_back_ring_t
(((_cons) - (_r)->rsp_prod_pvt) >= RING_SIZE(_r))
#define RING_PUSH_REQUESTS(_r) do { \
- wmb(); /* back sees requests /before/ updated producer index */ \
+ xen_wmb(); /* back sees requests /before/ updated producer index */ \
(_r)->sring->req_prod = (_r)->req_prod_pvt; \
} while (0)
#define RING_PUSH_RESPONSES(_r) do { \
- wmb(); /* front sees responses /before/ updated producer index */ \
+ xen_wmb(); /* front sees resps /before/ updated producer index */ \
(_r)->sring->rsp_prod = (_r)->rsp_prod_pvt; \
} while (0)
@@ -253,9 +261,9 @@ typedef struct __name##_back_ring __name##_back_ring_t
#define RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(_r, _notify) do { \
RING_IDX __old = (_r)->sring->req_prod; \
RING_IDX __new = (_r)->req_prod_pvt; \
- wmb(); /* back sees requests /before/ updated producer index */ \
+ xen_wmb(); /* back sees requests /before/ updated producer index */ \
(_r)->sring->req_prod = __new; \
- mb(); /* back sees new requests /before/ we check req_event */ \
+ xen_mb(); /* back sees new requests /before/ we check req_event */ \
(_notify) = ((RING_IDX)(__new - (_r)->sring->req_event) < \
(RING_IDX)(__new - __old)); \
} while (0)
@@ -263,9 +271,9 @@ typedef struct __name##_back_ring __name##_back_ring_t
#define RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(_r, _notify) do { \
RING_IDX __old = (_r)->sring->rsp_prod; \
RING_IDX __new = (_r)->rsp_prod_pvt; \
- wmb(); /* front sees responses /before/ updated producer index */ \
+ xen_wmb(); /* front sees resps /before/ updated producer index */ \
(_r)->sring->rsp_prod = __new; \
- mb(); /* front sees new responses /before/ we check rsp_event */ \
+ xen_mb(); /* front sees new resps /before/ we check rsp_event */ \
(_notify) = ((RING_IDX)(__new - (_r)->sring->rsp_event) < \
(RING_IDX)(__new - __old)); \
} while (0)
@@ -274,7 +282,7 @@ typedef struct __name##_back_ring __name##_back_ring_t
(_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r); \
if (_work_to_do) break; \
(_r)->sring->req_event = (_r)->req_cons + 1; \
- mb(); \
+ xen_mb(); \
(_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r); \
} while (0)
@@ -282,7 +290,7 @@ typedef struct __name##_back_ring __name##_back_ring_t
(_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \
if (_work_to_do) break; \
(_r)->sring->rsp_event = (_r)->rsp_cons + 1; \
- mb(); \
+ xen_mb(); \
(_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \
} while (0)
diff --git a/xen/include/public/trace.h b/xen/include/public/trace.h
index 4cbb896342..21fe15ffb9 100644
--- a/xen/include/public/trace.h
+++ b/xen/include/public/trace.h
@@ -141,6 +141,14 @@ struct t_rec {
* field, indexes into an array of struct t_rec's.
*/
struct t_buf {
+ /* Assume the data buffer size is X. X is generally not a power of 2.
+ * CONS and PROD are incremented modulo (2*X):
+ * 0 <= cons < 2*X
+ * 0 <= prod < 2*X
+ * This is done because addition modulo X breaks at 2^32 when X is not a
+ * power of 2:
+ * (((2^32 - 1) % X) + 1) % X != (2^32) % X
+ */
uint32_t cons; /* Offset of next item to be consumed by control tools. */
uint32_t prod; /* Offset of next item to be produced by Xen. */
/* Records follow immediately after the meta-data header. */
diff --git a/xen/include/public/xen-compat.h b/xen/include/public/xen-compat.h
index c9f369f0e9..c2894990cd 100644
--- a/xen/include/public/xen-compat.h
+++ b/xen/include/public/xen-compat.h
@@ -27,7 +27,7 @@
#ifndef __XEN_PUBLIC_XEN_COMPAT_H__
#define __XEN_PUBLIC_XEN_COMPAT_H__
-#define __XEN_LATEST_INTERFACE_VERSION__ 0x00030207
+#define __XEN_LATEST_INTERFACE_VERSION__ 0x00030208
#if defined(__XEN__) || defined(__XEN_TOOLS__)
/* Xen is built with matching headers and implements the latest interface. */
diff --git a/xen/include/xen/smp.h b/xen/include/xen/smp.h
index c02ecd4dc3..6ab913a430 100644
--- a/xen/include/xen/smp.h
+++ b/xen/include/xen/smp.h
@@ -1,23 +1,10 @@
-#ifndef __LINUX_SMP_H
-#define __LINUX_SMP_H
-
-/*
- * Generic SMP support
- * Alan Cox. <alan@redhat.com>
- */
+#ifndef __XEN_SMP_H__
+#define __XEN_SMP_H__
#include <xen/config.h>
-
-#ifdef CONFIG_SMP
-
#include <asm/smp.h>
/*
- * main cross-CPU interfaces, handles INIT, TLB flush, STOP, etc.
- * (defined in asm header):
- */
-
-/*
* stops all CPUs but the current one:
*/
extern void smp_send_stop(void);
@@ -66,38 +53,6 @@ extern int on_selected_cpus(
*/
void smp_prepare_boot_cpu(void);
-#else
-
-/*
- * These macros fold the SMP functionality into a single CPU system
- */
-
-#define smp_send_event_check_mask(m) ((void)0)
-#define smp_send_event_check_cpu(p) ((void)0)
-#define raw_smp_processor_id() 0
-#define hard_smp_processor_id() 0
-#define smp_call_function(func,info,retry,wait) ({ do {} while (0); 0; })
-#define num_booting_cpus() 1
-#define smp_prepare_boot_cpu() do {} while (0)
-
-static inline int on_selected_cpus(
- cpumask_t selected,
- void (*func) (void *info),
- void *info,
- int retry,
- int wait)
-{
- if ( cpu_isset(0, selected) )
- {
- local_irq_disable();
- func(info);
- local_irq_enable();
- }
- return 0;
-}
-
-#endif
-
/*
* Call a function on all processors
*/
@@ -112,4 +67,8 @@ static inline int on_each_cpu(
#define smp_processor_id() raw_smp_processor_id()
-#endif
+/* No Xen contexts can be preempted by CPU hotplug. */
+#define lock_cpu_hotplug() ((void)0)
+#define unlock_cpu_hotplug() ((void)0)
+
+#endif /* __XEN_SMP_H__ */
diff --git a/xen/include/xen/softirq.h b/xen/include/xen/softirq.h
index 9a66e0fb03..7734b3374d 100644
--- a/xen/include/xen/softirq.h
+++ b/xen/include/xen/softirq.h
@@ -10,8 +10,9 @@
#define PAGE_SCRUB_SOFTIRQ 5
#define TRACE_SOFTIRQ 6
#define RCU_SOFTIRQ 7
+#define STOPMACHINE_SOFTIRQ 8
-#define NR_COMMON_SOFTIRQS 8
+#define NR_COMMON_SOFTIRQS 9
#include <asm/softirq.h>
diff --git a/xen/include/xen/stop_machine.h b/xen/include/xen/stop_machine.h
new file mode 100644
index 0000000000..7d4506869f
--- /dev/null
+++ b/xen/include/xen/stop_machine.h
@@ -0,0 +1,19 @@
+#ifndef __XEN_STOP_MACHINE_H__
+#define __XEN_STOP_MACHINE_H__
+
+/**
+ * stop_machine_run: freeze the machine on all CPUs and run this function
+ * @fn: the function to run
+ * @data: the data ptr for the @fn()
+ * @cpu: the cpu to run @fn() on (or any, if @cpu == NR_CPUS).
+ *
+ * Description: This causes every other cpu to enter a safe point, with
+ * each of which disables interrupts, and finally interrupts are disabled
+ * on the current CPU. The result is that none is holding a spinlock
+ * or inside any other preempt-disabled region when @fn() runs.
+ *
+ * This can be thought of as a very heavy write lock, equivalent to
+ * grabbing every spinlock in the kernel. */
+int stop_machine_run(int (*fn)(void *), void *data, unsigned int cpu);
+
+#endif /* __XEN_STOP_MACHINE_H__ */
diff --git a/xen/include/xen/trace.h b/xen/include/xen/trace.h
index 7635f2dbf6..c5ce88f7ca 100644
--- a/xen/include/xen/trace.h
+++ b/xen/include/xen/trace.h
@@ -39,7 +39,7 @@ void __trace_var(u32 event, int cycles, int extra, unsigned char *extra_data);
static inline void trace_var(u32 event, int cycles, int extra,
unsigned char *extra_data)
{
- if( unlikely(tb_init_done) )
+ if ( unlikely(tb_init_done) )
__trace_var(event, cycles, extra, extra_data);
}
@@ -49,49 +49,64 @@ static inline void trace_var(u32 event, int cycles, int extra,
trace_var(_e, 1, 0, NULL); \
} while ( 0 )
-#define TRACE_1D(_e,_d) \
+#define TRACE_1D(_e,d1) \
do { \
- u32 _d1; \
- _d1 = _d; \
- trace_var(_e, 1, sizeof(_d1), (unsigned char *)&_d1); \
+ if ( unlikely(tb_init_done) ) \
+ { \
+ u32 _d[1]; \
+ _d[0] = d1; \
+ __trace_var(_e, 1, sizeof(*_d), (unsigned char *)_d); \
+ } \
} while ( 0 )
#define TRACE_2D(_e,d1,d2) \
- do { \
- u32 _d[2]; \
- _d[0]=d1; \
- _d[1]=d2; \
- trace_var(_e, 1, sizeof(*_d)*2, (unsigned char *)_d); \
+ do { \
+ if ( unlikely(tb_init_done) ) \
+ { \
+ u32 _d[2]; \
+ _d[0] = d1; \
+ _d[1] = d2; \
+ __trace_var(_e, 1, sizeof(*_d)*2, (unsigned char *)_d); \
+ } \
} while ( 0 )
#define TRACE_3D(_e,d1,d2,d3) \
do { \
- u32 _d[3]; \
- _d[0]=d1; \
- _d[1]=d2; \
- _d[2]=d3; \
- trace_var(_e, 1, sizeof(*_d)*3, (unsigned char *)_d); \
+ if ( unlikely(tb_init_done) ) \
+ { \
+ u32 _d[3]; \
+ _d[0] = d1; \
+ _d[1] = d2; \
+ _d[2] = d3; \
+ __trace_var(_e, 1, sizeof(*_d)*3, (unsigned char *)_d); \
+ } \
} while ( 0 )
#define TRACE_4D(_e,d1,d2,d3,d4) \
do { \
- u32 _d[4]; \
- _d[0]=d1; \
- _d[1]=d2; \
- _d[2]=d3; \
- _d[3]=d4; \
- trace_var(_e, 1, sizeof(*_d)*4, (unsigned char *)_d); \
+ if ( unlikely(tb_init_done) ) \
+ { \
+ u32 _d[4]; \
+ _d[0] = d1; \
+ _d[1] = d2; \
+ _d[2] = d3; \
+ _d[3] = d4; \
+ __trace_var(_e, 1, sizeof(*_d)*4, (unsigned char *)_d); \
+ } \
} while ( 0 )
#define TRACE_5D(_e,d1,d2,d3,d4,d5) \
- do { \
- u32 _d[5]; \
- _d[0]=d1; \
- _d[1]=d2; \
- _d[2]=d3; \
- _d[3]=d4; \
- _d[4]=d5; \
- trace_var(_e, 1, sizeof(*_d)*5, (unsigned char *)_d); \
+ do { \
+ if ( unlikely(tb_init_done) ) \
+ { \
+ u32 _d[5]; \
+ _d[0] = d1; \
+ _d[1] = d2; \
+ _d[2] = d3; \
+ _d[3] = d4; \
+ _d[4] = d5; \
+ __trace_var(_e, 1, sizeof(*_d)*5, (unsigned char *)_d); \
+ } \
} while ( 0 )
#endif /* __XEN_TRACE_H__ */