# HG changeset patch
# User Alex Williamson <alex.williamson@xxxxxx>
# Date 1193780084 21600
# Node ID a07288a8478521002c2302ad18fac52eb6600055
# Parent c17bfb09179095567c0cdae0aef3177afd6fad53
# Parent 7eb68d995aa7b3527721376b6112b995ef539168
merge with xen-unstable.hg (staging)
---
buildconfigs/mk.linux-2.6-paravirt | 15
tools/check/check_libvncserver | 38
tools/check/check_sdl | 27
tools/xenfb/Makefile | 32
tools/xenfb/sdlfb.c | 342 --
tools/xenfb/vncfb.c | 522 ----
tools/xenfb/xenfb.c | 779 ------
tools/xenfb/xenfb.h | 35
Config.mk | 1
Makefile | 42
README | 54
buildconfigs/mk.linux-2.6 | 6
buildconfigs/mk.linux-2.6-common | 158 +
buildconfigs/mk.linux-2.6-native | 4
buildconfigs/mk.linux-2.6-xen | 161 -
buildconfigs/mk.linux-2.6.5-SLES-xen | 2
buildconfigs/mk.linux-2.6.9-RHEL-xen | 2
buildconfigs/src.tarball | 14
docs/misc/vtd.txt | 50
tools/Makefile | 1
tools/check/Makefile | 4
tools/console/daemon/io.c | 142 +
tools/examples/xend-config.sxp | 33
tools/firmware/hvmloader/acpi/build.c | 2
tools/firmware/rombios/32bit/tcgbios/tcgbios.c | 2
tools/firmware/vgabios/clext.c | 26
tools/firmware/vmxassist/machine.h | 5
tools/firmware/vmxassist/vm86.c | 267 ++
tools/ioemu/Makefile.target | 17
tools/ioemu/configure | 28
tools/ioemu/hw/cirrus_vga.c | 12
tools/ioemu/hw/xen_console.c | 432 +++
tools/ioemu/hw/xen_console.h | 25
tools/ioemu/hw/xen_machine_fv.c | 296 ++
tools/ioemu/hw/xen_machine_pv.c | 73
tools/ioemu/hw/xen_platform.c | 14
tools/ioemu/hw/xenfb.c | 1157
++++++++++
tools/ioemu/hw/xenfb.h | 13
tools/ioemu/monitor.c | 26
tools/ioemu/target-i386-dm/helper2.c | 35
tools/ioemu/vl.c | 273 --
tools/ioemu/vl.h | 14
tools/ioemu/vnc.c | 1153
++++++++-
tools/ioemu/xenstore.c | 42
tools/libxc/xc_domain.c | 6
tools/libxc/xc_domain_restore.c | 88
tools/libxc/xc_domain_save.c | 40
tools/libxc/xc_misc.c | 16
tools/libxc/xenctrl.h | 8
tools/python/xen/lowlevel/xc/xc.c | 16
tools/python/xen/util/acmpolicy.py | 30
tools/python/xen/util/xsm/acm/acm.py | 38
tools/python/xen/xend/XendCheckpoint.py | 5
tools/python/xen/xend/XendConfig.py | 101
tools/python/xen/xend/XendConstants.py | 1
tools/python/xen/xend/XendDomain.py | 11
tools/python/xen/xend/XendDomainInfo.py | 101
tools/python/xen/xend/XendOptions.py | 29
tools/python/xen/xend/XendXSPolicyAdmin.py | 41
tools/python/xen/xend/image.py | 398 +--
tools/python/xen/xend/server/ConsoleController.py | 9
tools/python/xen/xend/server/DevController.py | 33
tools/python/xen/xend/server/blkif.py | 17
tools/python/xen/xend/server/netif.py | 9
tools/python/xen/xend/server/pciif.py | 4
tools/python/xen/xend/server/tpmif.py | 4
tools/python/xen/xend/server/vfbif.py | 117 -
tools/python/xen/xm/addlabel.py | 17
tools/python/xen/xm/create.py | 9
tools/python/xen/xm/rmlabel.py | 24
tools/python/xen/xm/setpolicy.py | 12
tools/python/xen/xm/xenapi_create.py | 2
tools/xenstore/xenstored_watch.c | 11
tools/xentrace/xentrace.c | 2
tools/xm-test/lib/XmTestLib/XenAPIDomain.py | 11
tools/xm-test/tests/security-acm/08_security-acm_xapi.py | 5
tools/xm-test/tests/vtpm/09_vtpm-xapi.py | 2
unmodified_drivers/linux-2.6/README | 10
unmodified_drivers/linux-2.6/compat-include/xen/platform-compat.h | 8
unmodified_drivers/linux-2.6/overrides.mk | 2
unmodified_drivers/linux-2.6/platform-pci/evtchn.c | 22
unmodified_drivers/linux-2.6/platform-pci/machine_reboot.c | 1
unmodified_drivers/linux-2.6/platform-pci/platform-pci.c | 4
xen/arch/ia64/vmx/mmio.c | 121 -
xen/arch/x86/Makefile | 1
xen/arch/x86/acpi/boot.c | 1
xen/arch/x86/acpi/power.c | 55
xen/arch/x86/boot/cmdline.S | 8
xen/arch/x86/boot/trampoline.S | 4
xen/arch/x86/domain.c | 31
xen/arch/x86/domain_build.c | 14
xen/arch/x86/domctl.c | 97
xen/arch/x86/flushtlb.c | 33
xen/arch/x86/hvm/Makefile | 2
xen/arch/x86/hvm/hvm.c | 17
xen/arch/x86/hvm/intercept.c | 96
xen/arch/x86/hvm/irq.c | 16
xen/arch/x86/hvm/mtrr.c | 258 +-
xen/arch/x86/hvm/platform.c | 3
xen/arch/x86/hvm/stdvga.c | 697 ++++++
xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-detect.c | 2
xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-init.c | 2
xen/arch/x86/hvm/svm/svm.c | 2
xen/arch/x86/hvm/vioapic.c | 4
xen/arch/x86/hvm/vlapic.c | 13
xen/arch/x86/hvm/vmx/vmcs.c | 10
xen/arch/x86/hvm/vmx/vmx.c | 6
xen/arch/x86/hvm/vmx/vtd/io.c | 31
xen/arch/x86/hvm/vpic.c | 14
xen/arch/x86/hvm/vpt.c | 99
xen/arch/x86/mm.c | 11
xen/arch/x86/mm/shadow/common.c | 12
xen/arch/x86/mm/shadow/multi.c | 15
xen/arch/x86/setup.c | 5
xen/arch/x86/shutdown.c | 14
xen/arch/x86/smp.c | 6
xen/arch/x86/smpboot.c | 2
xen/arch/x86/tboot.c | 70
xen/arch/x86/traps.c | 469 +++-
xen/arch/x86/x86_32/asm-offsets.c | 5
xen/arch/x86/x86_32/entry.S | 11
xen/arch/x86/x86_64/asm-offsets.c | 5
xen/arch/x86/x86_64/compat/entry.S | 11
xen/arch/x86/x86_64/compat/traps.c | 6
xen/arch/x86/x86_64/entry.S | 10
xen/arch/x86/x86_64/mm.c | 27
xen/common/sysctl.c | 5
xen/drivers/char/console.c | 52
xen/drivers/char/ns16550.c | 4
xen/drivers/char/serial.c | 61
xen/include/asm-x86/amd-iommu.h | 2
xen/include/asm-x86/apic.h | 8
xen/include/asm-x86/domain.h | 2
xen/include/asm-x86/fixmap.h | 1
xen/include/asm-x86/flushtlb.h | 20
xen/include/asm-x86/hvm/cacheattr.h | 16
xen/include/asm-x86/hvm/domain.h | 1
xen/include/asm-x86/hvm/hvm.h | 6
xen/include/asm-x86/hvm/io.h | 42
xen/include/asm-x86/hvm/irq.h | 5
xen/include/asm-x86/hvm/vpt.h | 4
xen/include/asm-x86/io_apic.h | 3
xen/include/asm-x86/iommu.h | 5
xen/include/asm-x86/msr.h | 8
xen/include/asm-x86/page.h | 3
xen/include/asm-x86/processor.h | 21
xen/include/asm-x86/smp.h | 1
xen/include/asm-x86/tboot.h | 90
xen/include/asm-x86/x86_32/elf.h | 4
xen/include/asm-x86/x86_64/elf.h | 4
xen/include/public/domctl.h | 40
xen/include/public/hvm/ioreq.h | 17
xen/include/public/hvm/params.h | 24
xen/include/public/sysctl.h | 25
xen/include/xen/console.h | 3
xen/xsm/xsm_policy.c | 2
156 files changed, 6885 insertions(+), 3550 deletions(-)
diff -r c17bfb091790 -r a07288a84785 Config.mk
--- a/Config.mk Tue Oct 30 11:33:55 2007 -0600
+++ b/Config.mk Tue Oct 30 15:34:44 2007 -0600
@@ -89,7 +89,6 @@ XENSTAT_XENTOP ?= y
XENSTAT_XENTOP ?= y
VTPM_TOOLS ?= n
LIBXENAPI_BINDINGS ?= n
-XENFB_TOOLS ?= n
PYTHON_TOOLS ?= y
-include $(XEN_ROOT)/.config
diff -r c17bfb091790 -r a07288a84785 Makefile
--- a/Makefile Tue Oct 30 11:33:55 2007 -0600
+++ b/Makefile Tue Oct 30 15:34:44 2007 -0600
@@ -103,7 +103,7 @@ world:
# clean doesn't do a kclean
.PHONY: clean
-clean::
+clean::
$(MAKE) -C xen clean
$(MAKE) -C tools clean
$(MAKE) -C docs clean
@@ -153,6 +153,11 @@ help:
@echo ' prep-kernels - prepares kernel directories, does not build'
@echo ' uninstall - attempt to remove installed Xen tools'
@echo ' (use with extreme care!)'
+ @echo
+ @echo 'Trusted Boot (tboot) targets:'
+ @echo ' build-tboot - download and build the tboot module'
+ @echo ' install-tboot - download, build, and install the tboot
module'
+ @echo ' clean-tboot - clean the tboot module if it exists'
@echo
@echo 'Environment:'
@echo ' XEN_PYTHON_NATIVE_INSTALL=y'
@@ -194,8 +199,43 @@ uninstall:
rm -rf $(D)/usr/share/xen
rm -rf $(D)/usr/share/man/man1/xen*
rm -rf $(D)/usr/share/man/man8/xen*
+ rm -rf $(D)/boot/tboot*
# Legacy targets for compatibility
.PHONY: linux26
linux26:
$(MAKE) 'KERNELS=linux-2.6*' kernels
+
+
+#
+# tboot targets
+#
+
+TBOOT_TARFILE = tboot-20071029.tar.gz
+TBOOT_BASE_URL = http://downloads.sourceforge.net/tboot
+
+.PHONY: build-tboot
+build-tboot: download_tboot
+ $(MAKE) -C tboot build
+
+.PHONY: install-tboot
+install-tboot: download_tboot
+ $(MAKE) -C tboot install
+
+.PHONY: clean-tboot
+clean-tboot:
+ [ ! -d tboot ] || $(MAKE) -C tboot clean
+
+.PHONY: distclean-tboot
+distclean-tboot:
+ [ ! -d tboot ] || $(MAKE) -C tboot distclean
+
+.PHONY: download_tboot
+download_tboot: tboot/Makefile
+
+tboot/Makefile: tboot/$(TBOOT_TARFILE)
+ [ -e tboot/Makefile ] || tar -xzf tboot/$(TBOOT_TARFILE) -C tboot/
--strip-components 1
+
+tboot/$(TBOOT_TARFILE):
+ mkdir -p tboot
+ wget -O tboot/$(TBOOT_TARFILE) $(TBOOT_BASE_URL)/$(TBOOT_TARFILE)
diff -r c17bfb091790 -r a07288a84785 README
--- a/README Tue Oct 30 11:33:55 2007 -0600
+++ b/README Tue Oct 30 15:34:44 2007 -0600
@@ -1,13 +1,13 @@
-#############################
- __ __ _____ _
- \ \/ /___ _ __ |___ / / |
- \ // _ \ '_ \ |_ \ | |
- / \ __/ | | | ___) || |
- /_/\_\___|_| |_| |____(_)_|
-
-#############################
-
-http://www.xensource.com/xen/about.html
+#################################
+ __ __ _____ ____
+ \ \/ /___ _ __ |___ / |___ \
+ \ // _ \ '_ \ |_ \ __) |
+ / \ __/ | | | ___) | / __/
+ /_/\_\___|_| |_| |____(_)_____|
+
+#################################
+
+http://www.xen.org/
What is Xen?
============
@@ -21,7 +21,7 @@ by the original Xen development team to
by the original Xen development team to build enterprise products
around Xen.
-The 3.1 release offers excellent performance, hardware support and
+The 3.2 release offers excellent performance, hardware support and
enterprise-grade features such as x86_32-PAE, x86_64, SMP guests and
live relocation of VMs. This install tree contains source for a Linux
2.6 guest; ports to Linux 2.4, NetBSD, FreeBSD and Solaris are
@@ -55,8 +55,8 @@ 2. Configure your bootloader to boot Xen
/boot/grub/menu.lst: edit this file to include an entry like the
following:
- title Xen 3.1 / XenLinux 2.6
- kernel /boot/xen-3.1.gz console=vga
+ title Xen 3.2 / XenLinux 2.6
+ kernel /boot/xen-3.2.gz console=vga
module /boot/vmlinuz-2.6-xen root=<root-dev> ro console=tty0
module /boot/initrd-2.6-xen.img
@@ -75,7 +75,7 @@ 2. Configure your bootloader to boot Xen
32MB memory for internal use, which is not available for allocation
to virtual machines.
-3. Reboot your system and select the "Xen 3.1 / XenLinux 2.6" menu
+3. Reboot your system and select the "Xen 3.2 / XenLinux 2.6" menu
option. After booting Xen, Linux will start and your initialisation
scripts should execute in the usual way.
@@ -202,3 +202,29 @@ Xend (the Xen daemon) has the following
* For optional XenAPI support in XM, PyXML:
URL: http://pyxml.sourceforge.net
YUM: PyXML
+
+
+Intel(R) Trusted Execution Technology Support
+=============================================
+
+Intel's technology for safer computing, Intel(R) Trusted Execution Technology
+(Intel(R) TXT), defines platform-level enhancements that provide the building
+blocks for creating trusted platforms. For more information, see
+http://www.intel.com/technology/security/.
+
+Intel(R) TXT support is provided by the Trusted Boot (tboot) module in
+conjunction with minimal logic in the Xen hypervisor.
+
+Tboot is an open source, pre- kernel/VMM module that uses Intel(R) TXT to
+perform a measured and verified launch of an OS kernel/VMM.
+
+The Trusted Boot module is available from
+http://sourceforge.net/projects/tboot. This project hosts the code in a
+mercurial repo at http://tboot.sourceforge.net/hg/tboot.hg and contains
+tarballs of the source. Instructions in the tboot README describe how
+to modify grub.conf to use tboot to launch Xen.
+
+There are optional targets as part of Xen's top-level makefile that will
+downlaod and build tboot: install-tboot, build-tboot, dist-tboot, clean-tboot.
+These will download the latest tar file from the SourceForge site using wget,
+then build/install/dist according to Xen's settings.
diff -r c17bfb091790 -r a07288a84785 buildconfigs/mk.linux-2.6
--- a/buildconfigs/mk.linux-2.6 Tue Oct 30 11:33:55 2007 -0600
+++ b/buildconfigs/mk.linux-2.6 Tue Oct 30 15:34:44 2007 -0600
@@ -1,14 +1,10 @@ XEN_LINUX_SOURCE ?= tarball
XEN_LINUX_SOURCE ?= tarball
LINUX_VER ?= 2.6
-XEN_LINUX_TARBALL_KETCHUP := y
-
IMAGE_TARGET ?= vmlinux bzImage
-
-XEN_LINUX_ALLOW_INTERFACE_MISMATCH := y
XEN_LINUX_CONFIG_UPDATE := buildconfigs/enable-xen-config
EXTRAVERSION ?=
-include buildconfigs/mk.linux-2.6-xen
+include buildconfigs/mk.linux-2.6-common
diff -r c17bfb091790 -r a07288a84785 buildconfigs/mk.linux-2.6-common
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/buildconfigs/mk.linux-2.6-common Tue Oct 30 15:34:44 2007 -0600
@@ -0,0 +1,158 @@
+LINUX_SERIES = 2.6
+
+# Linux search path, will be searched for tarballs and mercurial
+# repositories.
+LINUX_SRC_PATH ?= .:..
+
+# The source directory is not automatically updated to avoid blowing
+# away developer's changes. If you want to automatically pull a new
+# version of the Linux tree then add `XEN_LINUX_UPDATE=y' to your make
+# command line.
+ifeq ($(XEN_LINUX_UPDATE),y)
+__XEN_LINUX_UPDATE = $(LINUX_SRCDIR)/.force-update
+else
+__XEN_LINUX_UPDATE =
+endif
+
+# Let XEN_TARGET_ARCH override ARCH.
+ifeq ($(XEN_TARGET_ARCH),x86_32)
+LINUX_ARCH ?= i386
+else
+LINUX_ARCH ?= $(XEN_TARGET_ARCH)
+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)))
+
+.PHONY: _build
+_build: build
+
+include buildconfigs/src.$(XEN_LINUX_SOURCE)
+
+# Default to allowing interface mismatch
+ifndef XEN_LINUX_ALLOW_INTERFACE_MISMATCH
+XEN_LINUX_ALLOW_INTERFACE_MISMATCH := y
+endif
+
+KERNELRELEASE = $(shell $(MAKE) -s --no-print-directory -C $(LINUX_DIR)
kernelrelease)
+
+# The real action starts here!
+.PHONY: build
+build: $(LINUX_DIR)/include/linux/autoconf.h
+ifneq ($(XEN_LINUX_ALLOW_INTERFACE_MISMATCH),y)
+ @if ! diff -urN -X buildconfigs/interface.exclude \
+ $(LINUX_SRCDIR)/include/xen/interface xen/include/public ; then \
+ echo "" 1>&2 ; \
+ echo " *** $(LINUX_SRCDIR)/include/xen/interface is out of date
" 1>&2 ; \
+ echo " *** relative to $(XEN_ROOT)/xen/include/public." 1>&2 ; \
+ echo "" 1>&2 ; \
+ exit 1 ; \
+ fi
+endif
+ if grep "^CONFIG_MODULES=" $(LINUX_DIR)/.config ; then \
+ $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) modules ; \
+ $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH)
INSTALL_MOD_PATH=$(DESTDIR) modules_install ; \
+ 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)
+
+$(LINUX_DIR)/include/linux/autoconf.h:
CONFIG_FILE=$(CURDIR)/$(LINUX_DIR)/.config
+$(LINUX_DIR)/include/linux/autoconf.h: $(LINUX_SRCDIR)/.valid-src
+ rm -rf $(LINUX_DIR)
+ mkdir -p $(LINUX_DIR)
+ # Re-use config from install dir if one exists. Next try to use
+ # buildconfigs/create_config.sh is one is provided by the source
+ # tree. Finally attempt to use make defconfig.
+ set -e ; \
+ CONFIG_VERSION=$$(sed -ne 's/$$(XENGUEST)//; s/^EXTRAVERSION = //p'
$(LINUX_SRCDIR)/Makefile); \
+ if [ -r
$(DESTDIR)/boot/config-$(LINUX_VER3)$$CONFIG_VERSION$(EXTRAVERSION) ] ; then \
+ cp
$(DESTDIR)/boot/config-$(LINUX_VER3)$$CONFIG_VERSION$(EXTRAVERSION)
$(CONFIG_FILE) ; \
+ elif [ -e $(LINUX_SRCDIR)/buildconfigs/create_config.sh ] ; then \
+ cd $(LINUX_SRCDIR) && sh buildconfigs/create_config.sh \
+ $(CONFIG_FILE) $(EXTRAVERSION) $(XEN_TARGET_ARCH)
$(XEN_SYSTYPE) ; \
+ echo "Configured $(LINUX_DIR) using create_config.sh" ; \
+ elif $(MAKE) -C $(LINUX_SRCDIR) ARCH=$(LINUX_ARCH) defconfig
O=$$(/bin/pwd)/$(LINUX_DIR) ; then \
+ echo "Configured $(LINUX_DIR) using defconfig" ; \
+ else \
+ echo "No configuration method found for this kernel" ; \
+ fi
+ifneq ($(XEN_LINUX_CONFIG_UPDATE),)
+ echo "Updating $(CONFIG_FILE) using $(XEN_LINUX_CONFIG_UPDATE)"
+ sh $(XEN_LINUX_CONFIG_UPDATE) $(CONFIG_FILE)
+endif
+ifeq ($(XEN_TARGET_ARCH),x86_32)
+ifeq ($(pae),y)
+ sed -e 's!^CONFIG_HIGHMEM4G=y$$!\# CONFIG_HIGHMEM4G is not set!;s!^\#
CONFIG_HIGHMEM64G is not set$$!CONFIG_HIGHMEM64G=y!' $(CONFIG_FILE) >
$(CONFIG_FILE)- && mv $(CONFIG_FILE)- $(CONFIG_FILE)
+else
+ grep '^CONFIG_HIGHMEM64G=y' $(CONFIG_FILE) >/dev/null && ( sed -e
's!^CONFIG_HIGHMEM64G=y$$!\# CONFIG_HIGHMEM64G is not set!;s!^\#
CONFIG_HIGHMEM4G is not set$$!CONFIG_HIGHMEM4G=y!' $(CONFIG_FILE) >
$(CONFIG_FILE)- && mv $(CONFIG_FILE)- $(CONFIG_FILE) ) || true
+endif
+endif
+ifneq ($(EXTRAVERSION),)
+ echo "$(EXTRAVERSION)" >$(LINUX_DIR)/localversion-xen
+endif
+ $(MAKE) -C $(LINUX_SRCDIR) ARCH=$(LINUX_ARCH) oldconfig
O=$$(/bin/pwd)/$(LINUX_DIR)
+ @if [ ! -f $(LINUX_DIR)/Makefile ] ; then \
+ echo "***********************************"; \
+ echo "oldconfig did not create a Makefile"; \
+ echo "Generating $(LINUX_DIR)/Makefile "; \
+ echo "***********************************"; \
+ ( echo "# Automatically generated: don't edit"; \
+ echo ""; \
+ echo "VERSION = 2"; \
+ echo "PATCHLEVEL = 6"; \
+ echo ""; \
+ echo "KERNELSRC := $(CURDIR)/$(LINUX_SRCDIR)"; \
+ echo "KERNELOUTPUT := $(CURDIR)/$(LINUX_DIR)"; \
+ echo ""; \
+ echo "MAKEFLAGS += --no-print-directory"; \
+ echo ""; \
+ echo ".PHONY: all \$$(MAKECMDGOALS)"; \
+ echo ""; \
+ echo "all:"; \
+ echo " \$$(MAKE) -C \$$(KERNELSRC) O=\$$(KERNELOUTPUT)"; \
+ echo ""; \
+ echo "Makefile:;"; \
+ echo ""; \
+ echo "\$$(filter-out all Makefile,\$$(MAKECMDGOALS)) %/:"; \
+ echo " \$$(MAKE) -C \$$(KERNELSRC) O=\$$(KERNELOUTPUT) \$$@"; \
+ ) > $(LINUX_DIR)/Makefile ; \
+ fi
+ $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) prepare
+
+.PHONY: prep
+prep: $(LINUX_DIR)/include/linux/autoconf.h
+
+.PHONY: config
+config: CONFIGMODE = menuconfig
+config: $(LINUX_DIR)/include/linux/autoconf.h
+ $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) $(CONFIGMODE)
+
+.PHONY: clean
+clean::
+ [ ! -d $(LINUX_DIR) ] || \
+ $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) clean
+
+.PHONY: delete
+delete:
+ rm -rf tmp-linux-$(LINUX_VER) $(LINUX_DIR) $(LINUX_SRCDIR)
+
+.PHONY: mrproper
+mrproper:
+ rm -rf $(LINUX_SRCDIR)
+ rm -f linux-$(LINUX_VER).tar.bz2
+
+.PHONY: $(LINUX_SRCDIR)/.force-update
+$(LINUX_SRCDIR)/.force-update:
+ @ :
diff -r c17bfb091790 -r a07288a84785 buildconfigs/mk.linux-2.6-native
--- a/buildconfigs/mk.linux-2.6-native Tue Oct 30 11:33:55 2007 -0600
+++ b/buildconfigs/mk.linux-2.6-native Tue Oct 30 15:34:44 2007 -0600
@@ -2,6 +2,4 @@ IMAGE_TARGET = bzImage
IMAGE_TARGET = bzImage
INSTALL_BOOT_PATH = $(DESTDIR)/boot
-XEN_LINUX_ALLOW_INTERFACE_MISMATCH := y
-
-include buildconfigs/mk.linux-2.6-xen
+include buildconfigs/mk.linux-2.6-common
diff -r c17bfb091790 -r a07288a84785 buildconfigs/mk.linux-2.6-paravirt
--- a/buildconfigs/mk.linux-2.6-paravirt Tue Oct 30 11:33:55 2007 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-XEN_LINUX_SOURCE ?= tarball
-XEN_LINUX_MIRROR ?= http://xenbits.xensource.com/ext/paravirt_ops/
-LINUX_VER ?= 2.6-paravirt
-
-# This target currently only supports x86_32.
-XEN_TARGET_ARCH = x86_32
-IMAGE_TARGET ?= vmlinux bzImage
-
-XEN_LINUX_ALLOW_INTERFACE_MISMATCH := y
-
-XEN_LINUX_CONFIG_UPDATE := buildconfigs/enable-xen-config
-
-EXTRAVERSION ?= -paravirt
-
-include buildconfigs/mk.linux-2.6-xen
diff -r c17bfb091790 -r a07288a84785 buildconfigs/mk.linux-2.6-xen
--- a/buildconfigs/mk.linux-2.6-xen Tue Oct 30 11:33:55 2007 -0600
+++ b/buildconfigs/mk.linux-2.6-xen Tue Oct 30 15:34:44 2007 -0600
@@ -1,163 +1,6 @@ LINUX_SERIES = 2.6
-LINUX_SERIES = 2.6
+EXTRAVERSION ?= -xen
LINUX_VER ?= 2.6.18
-
-EXTRAVERSION ?= -xen
-
-# Linux search path, will be searched for tarballs and mercurial
-# repositories.
-LINUX_SRC_PATH ?= .:..
-
-# The source directory is not automatically updated to avoid blowing
-# away developer's changes. If you want to automatically pull a new
-# version of the Linux tree then add `XEN_LINUX_UPDATE=y' to your make
-# command line.
-ifeq ($(XEN_LINUX_UPDATE),y)
-__XEN_LINUX_UPDATE = $(LINUX_SRCDIR)/.force-update
-else
-__XEN_LINUX_UPDATE =
-endif
XEN_LINUX_SOURCE ?= hg-clone
-# Let XEN_TARGET_ARCH override ARCH.
-ifeq ($(XEN_TARGET_ARCH),x86_32)
-LINUX_ARCH ?= i386
-else
-LINUX_ARCH ?= $(XEN_TARGET_ARCH)
-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)))
-
-.PHONY: _build
-_build: build
-
-include buildconfigs/src.$(XEN_LINUX_SOURCE)
-
-# Default to allowing interface mismatch
-ifndef XEN_LINUX_ALLOW_INTERFACE_MISMATCH
-XEN_LINUX_ALLOW_INTERFACE_MISMATCH := y
-endif
-
-KERNELRELEASE = $(shell $(MAKE) -s --no-print-directory -C $(LINUX_DIR)
kernelrelease)
-
-# The real action starts here!
-.PHONY: build
-build: $(LINUX_DIR)/include/linux/autoconf.h
-ifneq ($(XEN_LINUX_ALLOW_INTERFACE_MISMATCH),y)
- @if ! diff -urN -X buildconfigs/interface.exclude \
- $(LINUX_SRCDIR)/include/xen/interface xen/include/public ; then \
- echo "" 1>&2 ; \
- echo " *** $(LINUX_SRCDIR)/include/xen/interface is out of date
" 1>&2 ; \
- echo " *** relative to $(XEN_ROOT)/xen/include/public." 1>&2 ; \
- echo "" 1>&2 ; \
- exit 1 ; \
- fi
-endif
- if grep "^CONFIG_MODULES=" $(LINUX_DIR)/.config ; then \
- $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) modules ; \
- $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH)
INSTALL_MOD_PATH=$(DESTDIR) modules_install ; \
- 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)
-
-$(LINUX_DIR)/include/linux/autoconf.h:
CONFIG_FILE=$(CURDIR)/$(LINUX_DIR)/.config
-$(LINUX_DIR)/include/linux/autoconf.h: $(LINUX_SRCDIR)/.valid-src
- rm -rf $(LINUX_DIR)
- mkdir -p $(LINUX_DIR)
- # Re-use config from install dir if one exists. Next try to use
- # buildconfigs/create_config.sh is one is provided by the source
- # tree. Finally attempt to use make defconfig.
- set -e ; \
- CONFIG_VERSION=$$(sed -ne 's/$$(XENGUEST)//; s/^EXTRAVERSION = //p'
$(LINUX_SRCDIR)/Makefile); \
- if [ -r
$(DESTDIR)/boot/config-$(LINUX_VER3)$$CONFIG_VERSION$(EXTRAVERSION) ] ; then \
- cp
$(DESTDIR)/boot/config-$(LINUX_VER3)$$CONFIG_VERSION$(EXTRAVERSION)
$(CONFIG_FILE) ; \
- elif [ -e $(LINUX_SRCDIR)/buildconfigs/create_config.sh ] ; then \
- cd $(LINUX_SRCDIR) && sh buildconfigs/create_config.sh \
- $(CONFIG_FILE) $(EXTRAVERSION) $(XEN_TARGET_ARCH)
$(XEN_SYSTYPE) ; \
- echo "Configured $(LINUX_DIR) using create_config.sh" ; \
- elif $(MAKE) -C $(LINUX_SRCDIR) ARCH=$(LINUX_ARCH) defconfig
O=$$(/bin/pwd)/$(LINUX_DIR) ; then \
- echo "Configured $(LINUX_DIR) using defconfig" ; \
- else \
- echo "No configuration method found for this kernel" ; \
- fi
-ifneq ($(XEN_LINUX_CONFIG_UPDATE),)
- echo "Updating $(CONFIG_FILE) using $(XEN_LINUX_CONFIG_UPDATE)"
- sh $(XEN_LINUX_CONFIG_UPDATE) $(CONFIG_FILE)
-endif
-ifeq ($(XEN_TARGET_ARCH),x86_32)
-ifeq ($(pae),y)
- sed -e 's!^CONFIG_HIGHMEM4G=y$$!\# CONFIG_HIGHMEM4G is not set!;s!^\#
CONFIG_HIGHMEM64G is not set$$!CONFIG_HIGHMEM64G=y!' $(CONFIG_FILE) >
$(CONFIG_FILE)- && mv $(CONFIG_FILE)- $(CONFIG_FILE)
-else
- grep '^CONFIG_HIGHMEM64G=y' $(CONFIG_FILE) >/dev/null && ( sed -e
's!^CONFIG_HIGHMEM64G=y$$!\# CONFIG_HIGHMEM64G is not set!;s!^\#
CONFIG_HIGHMEM4G is not set$$!CONFIG_HIGHMEM4G=y!' $(CONFIG_FILE) >
$(CONFIG_FILE)- && mv $(CONFIG_FILE)- $(CONFIG_FILE) ) || true
-endif
-endif
-ifneq ($(EXTRAVERSION),)
- echo "$(EXTRAVERSION)" >$(LINUX_DIR)/localversion-xen
-endif
- $(MAKE) -C $(LINUX_SRCDIR) ARCH=$(LINUX_ARCH) oldconfig
O=$$(/bin/pwd)/$(LINUX_DIR)
- @if [ ! -f $(LINUX_DIR)/Makefile ] ; then \
- echo "***********************************"; \
- echo "oldconfig did not create a Makefile"; \
- echo "Generating $(LINUX_DIR)/Makefile "; \
- echo "***********************************"; \
- ( echo "# Automatically generated: don't edit"; \
- echo ""; \
- echo "VERSION = 2"; \
- echo "PATCHLEVEL = 6"; \
- echo ""; \
- echo "KERNELSRC := $(CURDIR)/$(LINUX_SRCDIR)"; \
- echo "KERNELOUTPUT := $(CURDIR)/$(LINUX_DIR)"; \
- echo ""; \
- echo "MAKEFLAGS += --no-print-directory"; \
- echo ""; \
- echo ".PHONY: all \$$(MAKECMDGOALS)"; \
- echo ""; \
- echo "all:"; \
- echo " \$$(MAKE) -C \$$(KERNELSRC) O=\$$(KERNELOUTPUT)"; \
- echo ""; \
- echo "Makefile:;"; \
- echo ""; \
- echo "\$$(filter-out all Makefile,\$$(MAKECMDGOALS)) %/:"; \
- echo " \$$(MAKE) -C \$$(KERNELSRC) O=\$$(KERNELOUTPUT) \$$@"; \
- ) > $(LINUX_DIR)/Makefile ; \
- fi
- $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) prepare
-
-.PHONY: prep
-prep: $(LINUX_DIR)/include/linux/autoconf.h
-
-.PHONY: config
-config: CONFIGMODE = menuconfig
-config: $(LINUX_DIR)/include/linux/autoconf.h
- $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) $(CONFIGMODE)
-
-.PHONY: clean
-clean::
- [ ! -d $(LINUX_DIR) ] || \
- $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) clean
-
-.PHONY: delete
-delete:
- rm -rf tmp-linux-$(LINUX_VER) $(LINUX_DIR) $(LINUX_SRCDIR)
-
-.PHONY: mrproper
-mrproper:
- rm -rf $(LINUX_SRCDIR)
- rm -f linux-$(LINUX_VER).tar.bz2
-
-.PHONY: $(LINUX_SRCDIR)/.force-update
-$(LINUX_SRCDIR)/.force-update:
- @ :
+include buildconfigs/mk.linux-2.6-common
diff -r c17bfb091790 -r a07288a84785 buildconfigs/mk.linux-2.6.5-SLES-xen
--- a/buildconfigs/mk.linux-2.6.5-SLES-xen Tue Oct 30 11:33:55 2007 -0600
+++ b/buildconfigs/mk.linux-2.6.5-SLES-xen Tue Oct 30 15:34:44 2007 -0600
@@ -1,8 +1,6 @@
# This tree only supports PAE
XEN_TARGET_ARCH = x86_32
XEN_TARGET_X86_PAE = y
-
-XEN_LINUX_ALLOW_INTERFACE_MISMATCH := y
EXTRAVERSION = -xen
LINUX_VER = 2.6.5-SLES
diff -r c17bfb091790 -r a07288a84785 buildconfigs/mk.linux-2.6.9-RHEL-xen
--- a/buildconfigs/mk.linux-2.6.9-RHEL-xen Tue Oct 30 11:33:55 2007 -0600
+++ b/buildconfigs/mk.linux-2.6.9-RHEL-xen Tue Oct 30 15:34:44 2007 -0600
@@ -1,8 +1,6 @@
# This tree only supports PAE
XEN_TARGET_ARCH = x86_32
XEN_TARGET_X86_PAE = y
-
-XEN_LINUX_ALLOW_INTERFACE_MISMATCH := y
EXTRAVERSION = -xen
LINUX_VER = 2.6.9-RHEL
diff -r c17bfb091790 -r a07288a84785 buildconfigs/src.tarball
--- a/buildconfigs/src.tarball Tue Oct 30 11:33:55 2007 -0600
+++ b/buildconfigs/src.tarball Tue Oct 30 15:34:44 2007 -0600
@@ -1,8 +1,5 @@ XEN_LINUX_MIRROR ?= http://www.kernel.or
XEN_LINUX_MIRROR ?= http://www.kernel.org/pub/linux/kernel/v2.6/
XEN_LINUX_TARBALL ?= linux-$(LINUX_VER)-xen.tar.bz2
-
-# Update using ketchup instead of manipulating tarball manually.
-XEN_LINUX_TARBALL_KETCHUP ?= n
LINUX_SRCDIR ?= linux-$(LINUX_VER)
@@ -17,17 +14,6 @@ linux-%.tar.bz2:
# XXX create a pristine tree for diff -Nurp convenience
-ifeq ($(XEN_LINUX_TARBALL_KETCHUP),y)
%/.valid-src: $(__XEN_LINUX_UPDATE)
$(KETCHUP) -d $(@D) $(LINUX_VER)
touch $@ # update timestamp to avoid rebuild
-else
-%/.valid-src: $(__XEN_LINUX_UPDATE) %.tar.bz2
- rm -rf tmp-linux-$* $(@D)
- mkdir -p tmp-linux-$*
- tar -C tmp-linux-$* -jxf $<
- -@rm -f tmp-linux-$*/pax_global_header
- mv tmp-linux-$*/* $(@D)
- @rm -rf tmp-linux-$*
- touch $@ # update timestamp to avoid rebuild
-endif
diff -r c17bfb091790 -r a07288a84785 docs/misc/vtd.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/misc/vtd.txt Tue Oct 30 15:34:44 2007 -0600
@@ -0,0 +1,50 @@
+Title : How to do PCI Passthrough with VT-d
+Authors : Allen Kay <allen.m.kay@xxxxxxxxx>
+ Weidong Han <weidong.han@xxxxxxxxx>
+Created : October-24-2007
+Updated : October-24-2007
+
+How to turn on VT-d in Xen
+--------------------------
+
+1 ) cd xen-unstable.hg
+2 ) make install
+3 ) make linux-2.6-xen-config CONFIGMODE=menuconfig
+4 ) change XEN->"PCI-device backend driver" from "M" to "*".
+5 ) make linux-2.6-xen-build
+6 ) make linux-2.6-xen-install
+7 ) depmod 2.6.18.8-xen
+8 ) mkinitrd -v -f --with=ahci --with=aacraid --with=sd_mod --with=scsi_mod
initrd-2.6.18-xen.img 2.6.18.8-xen
+9 ) cp initrd-2.6.18-xen.img /boot
+10) lspci - select the PCI BDF you want to assign to guest OS
+11) "hide" pci device from dom0 as following sample grub entry:
+
+title Xen-Fedora Core (2.6.18-xen)
+ root (hd0,0)
+ kernel /boot/xen.gz com1=115200,8n1 console=com1 vtd=1
+ module /boot/vmlinuz-2.6.18.8-xen root=LABEL=/ ro console=tty0
console=ttyS0,115200,8n1 pciback.hide=(01:00.0)(03:00.0)
pciback.verbose_request=1 apic=debug maxcpus=1
+ module /boot/initrd-2.6.18-xen.img
+
+12) reboot system
+13) add "pci" line in /etc/xen/hvm.conf for to assigned devices
+ pci = [ '01:00.0', '03:00.0' ]
+15) start hvm guest and use "lspci" to see the passthru device and
+ "ifconfig" to see if IP address has been assigned to NIC devices.
+
+
+VT-d Enabled Systems
+--------------------
+
+1) For VT-d enabling work on Xen, we have been using development
+systems using following Intel motherboards:
+ - DQ35MP
+ - DQ35JO
+
+2) As far as we know, following OEM systems also has vt-d enabled.
+Feel free to add others as they become available.
+
+- Dell: Optiplex 755
+http://www.dell.com/content/products/category.aspx/optix?c=us&cs=555&l=en&s=biz
+
+- HP Compaq: DC7800
+http://h10010.www1.hp.com/wwpc/us/en/en/WF04a/12454-12454-64287-321860-3328898.html
diff -r c17bfb091790 -r a07288a84785 tools/Makefile
--- a/tools/Makefile Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/Makefile Tue Oct 30 15:34:44 2007 -0600
@@ -20,7 +20,6 @@ SUBDIRS-y += libaio
SUBDIRS-y += libaio
SUBDIRS-y += blktap
SUBDIRS-y += libfsimage
-SUBDIRS-$(XENFB_TOOLS) += xenfb
SUBDIRS-$(LIBXENAPI_BINDINGS) += libxen
# These don't cross-compile
diff -r c17bfb091790 -r a07288a84785 tools/check/Makefile
--- a/tools/check/Makefile Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/check/Makefile Tue Oct 30 15:34:44 2007 -0600
@@ -7,7 +7,7 @@ all: build
# Check this machine is OK for building on.
.PHONY: build
build:
- XENFB_TOOLS=$(XENFB_TOOLS) LIBXENAPI_BINDINGS=$(LIBXENAPI_BINDINGS)
ACM_SECURITY=$(ACM_SECURITY) ./chk build
+ LIBXENAPI_BINDINGS=$(LIBXENAPI_BINDINGS) ACM_SECURITY=$(ACM_SECURITY)
./chk build
# Check this machine is OK for installing on.
# DO NOT use this check from 'make install' in the parent
@@ -15,7 +15,7 @@ build:
# copy rather than actually installing.
.PHONY: install
install:
- XENFB_TOOLS=$(XENFB_TOOLS) LIBXENAPI_BINDINGS=$(LIBXENAPI_BINDINGS)
ACM_SECURITY=$(ACM_SECURITY) ./chk install
+ LIBXENAPI_BINDINGS=$(LIBXENAPI_BINDINGS) ACM_SECURITY=$(ACM_SECURITY)
./chk install
.PHONY: clean
clean:
diff -r c17bfb091790 -r a07288a84785 tools/check/check_libvncserver
--- a/tools/check/check_libvncserver Tue Oct 30 11:33:55 2007 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-#!/bin/sh
-# CHECK-BUILD CHECK-INSTALL
-
-if [ ! "$XENFB_TOOLS" = "y" ]
-then
- echo -n "unused, "
- exit 0
-fi
-
-RC=0
-
-LIBVNCSERVER_CONFIG="$(which libvncserver-config)"
-tmpfile=$(mktemp)
-
-if test -z ${LIBVNCSERVER_CONFIG}; then
- RC=1
-else
- ${LIBVNCSERVER_CONFIG} --libs 2>&1 > /dev/null
- RC=$?
-fi
-
-if test $RC -ne 0; then
- echo "FAILED"
- echo " *** libvncserver-config is missing. "
- echo " *** Please install libvncserver."
-elif ! ld $($LIBVNCSERVER_CONFIG --libs) -o $tmpfile >/dev/null 2>&1; then
- echo "FAILED"
- echo " *** dependency libraries for libvncserver are missing: "
- RC=1
- for i in $(ld $($LIBVNCSERVER_CONFIG --libs) -o $tmpfile 2>&1 >/dev/null);
do
- case $i in
- -l*) echo lib${i#-l}
- esac
- done
-fi
-rm -f $tmpfile
-
-exit $RC
diff -r c17bfb091790 -r a07288a84785 tools/check/check_sdl
--- a/tools/check/check_sdl Tue Oct 30 11:33:55 2007 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-#!/bin/sh
-# CHECK-BUILD CHECK-INSTALL
-
-if [ ! "$XENFB_TOOLS" = "y" ]
-then
- echo -n "unused, "
- exit 0
-fi
-
-RC=0
-
-SDL_CONFIG="$(which sdl-config)"
-
-if test -z ${SDL_CONFIG}; then
- RC=1
-else
- ${SDL_CONFIG} --libs 2>&1 > /dev/null
- RC=$?
-fi
-
-if test $RC -ne 0; then
- echo "FAILED"
- echo " *** sdl-config is missing. "
- echo " *** Please install libsdl-dev or sdl."
-fi
-
-exit $RC
diff -r c17bfb091790 -r a07288a84785 tools/console/daemon/io.c
--- a/tools/console/daemon/io.c Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/console/daemon/io.c Tue Oct 30 15:34:44 2007 -0600
@@ -35,6 +35,7 @@
#include <termios.h>
#include <stdarg.h>
#include <sys/mman.h>
+#include <sys/time.h>
#if defined(__NetBSD__) || defined(__OpenBSD__)
#include <util.h>
#elif defined(__linux__) || defined(__Linux__)
@@ -47,13 +48,20 @@
/* Each 10 bits takes ~ 3 digits, plus one, plus one for nul terminator. */
#define MAX_STRLEN(x) ((sizeof(x) * CHAR_BIT + CHAR_BIT-1) / 10 * 3 + 2)
+/* How many events are allowed in each time period */
+#define RATE_LIMIT_ALLOWANCE 30
+/* Duration of each time period in ms */
+#define RATE_LIMIT_PERIOD 200
+
extern int log_reload;
extern int log_guest;
extern int log_hv;
extern char *log_dir;
static int log_hv_fd = -1;
+static evtchn_port_or_error_t log_hv_evtchn = -1;
static int xc_handle = -1;
+static int xce_handle = -1;
struct buffer
{
@@ -76,10 +84,12 @@ struct domain
char *serialpath;
int use_consolepath;
int ring_ref;
- evtchn_port_t local_port;
- evtchn_port_t remote_port;
+ evtchn_port_or_error_t local_port;
+ evtchn_port_or_error_t remote_port;
int xce_handle;
struct xencons_interface *interface;
+ int event_count;
+ long long next_period;
};
static struct domain *dom_head;
@@ -377,6 +387,7 @@ static int domain_create_ring(struct dom
static int domain_create_ring(struct domain *dom)
{
int err, remote_port, ring_ref, rc;
+ char *type, path[PATH_MAX];
err = xs_gather(xs, dom->serialpath,
"ring-ref", "%u", &ring_ref,
@@ -393,6 +404,14 @@ static int domain_create_ring(struct dom
} else
dom->use_consolepath = 0;
+ sprintf(path, "%s/type", dom->use_consolepath ? dom->conspath:
dom->serialpath);
+ type = xs_read(xs, XBT_NULL, path, NULL);
+ if (type && strcmp(type, "xenconsoled") != 0) {
+ free(type);
+ return 0;
+ }
+ free(type);
+
if ((ring_ref == dom->ring_ref) && (remote_port == dom->remote_port))
goto out;
@@ -483,6 +502,13 @@ static struct domain *create_domain(int
{
struct domain *dom;
char *s;
+ struct timeval tv;
+
+ if (gettimeofday(&tv, NULL) < 0) {
+ dolog(LOG_ERR, "Cannot get time of day %s:%s:L%d",
+ __FILE__, __FUNCTION__, __LINE__);
+ return NULL;
+ }
dom = (struct domain *)malloc(sizeof(struct domain));
if (dom == NULL) {
@@ -518,6 +544,8 @@ static struct domain *create_domain(int
dom->buffer.size = 0;
dom->buffer.capacity = 0;
dom->buffer.max_capacity = 0;
+ dom->event_count = 0;
+ dom->next_period = (tv.tv_sec * 1000) + (tv.tv_usec / 1000) +
RATE_LIMIT_PERIOD;
dom->next = NULL;
dom->ring_ref = -1;
@@ -704,14 +732,17 @@ static void handle_tty_write(struct doma
static void handle_ring_read(struct domain *dom)
{
- evtchn_port_t port;
+ evtchn_port_or_error_t port;
if ((port = xc_evtchn_pending(dom->xce_handle)) == -1)
return;
+ dom->event_count++;
+
buffer_append(dom);
- (void)xc_evtchn_unmask(dom->xce_handle, port);
+ if (dom->event_count < RATE_LIMIT_ALLOWANCE)
+ (void)xc_evtchn_unmask(dom->xce_handle, port);
}
static void handle_xs(void)
@@ -743,12 +774,20 @@ static void handle_hv_logs(void)
char buffer[1024*16];
char *bufptr = buffer;
unsigned int size = sizeof(buffer);
- if (xc_readconsolering(xc_handle, &bufptr, &size, 1) == 0) {
+ static uint32_t index = 0;
+ evtchn_port_or_error_t port;
+
+ 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));
}
+
+ (void)xc_evtchn_unmask(xce_handle, port);
}
static void handle_log_reload(void)
@@ -776,17 +815,34 @@ void handle_io(void)
if (log_hv) {
xc_handle = xc_interface_open();
- if (xc_handle == -1)
+ if (xc_handle == -1) {
dolog(LOG_ERR, "Failed to open xc handle: %d (%s)",
errno, strerror(errno));
- else
- log_hv_fd = create_hv_log();
+ goto out;
+ }
+ xce_handle = xc_evtchn_open();
+ if (xce_handle == -1) {
+ dolog(LOG_ERR, "Failed to open xce handle: %d (%s)",
+ errno, strerror(errno));
+ goto out;
+ }
+ log_hv_fd = create_hv_log();
+ if (log_hv_fd == -1)
+ goto out;
+ log_hv_evtchn = xc_evtchn_bind_virq(xce_handle, VIRQ_CON_RING);
+ if (log_hv_evtchn == -1) {
+ dolog(LOG_ERR, "Failed to bind to VIRQ_CON_RING: "
+ "%d (%s)", errno, strerror(errno));
+ goto out;
+ }
}
for (;;) {
struct domain *d, *n;
- struct timeval timeout = { 1, 0 }; /* Read HV logs every 1
second */
int max_fd = -1;
+ struct timeval timeout;
+ struct timeval tv;
+ long long now, next_timeout = 0;
FD_ZERO(&readfds);
FD_ZERO(&writefds);
@@ -794,8 +850,38 @@ void handle_io(void)
FD_SET(xs_fileno(xs), &readfds);
max_fd = MAX(xs_fileno(xs), max_fd);
+ if (log_hv) {
+ FD_SET(xc_evtchn_fd(xce_handle), &readfds);
+ max_fd = MAX(xc_evtchn_fd(xce_handle), max_fd);
+ }
+
+ if (gettimeofday(&tv, NULL) < 0)
+ return;
+ now = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
+
+ /* Re-calculate any event counter allowances & unblock
+ domains with new allowance */
for (d = dom_head; d; d = d->next) {
- if (d->xce_handle != -1) {
+ /* Add 5ms of fuzz since select() often returns
+ a couple of ms sooner than requested. Without
+ the fuzz we typically do an extra spin in select()
+ with a 1/2 ms timeout every other iteration */
+ if ((now+5) > d->next_period) {
+ d->next_period = now + RATE_LIMIT_PERIOD;
+ if (d->event_count >= RATE_LIMIT_ALLOWANCE) {
+ (void)xc_evtchn_unmask(d->xce_handle,
d->local_port);
+ }
+ d->event_count = 0;
+ }
+ }
+
+ for (d = dom_head; d; d = d->next) {
+ if (d->event_count >= RATE_LIMIT_ALLOWANCE) {
+ /* Determine if we're going to be the next time
slice to expire */
+ if (!next_timeout ||
+ d->next_period < next_timeout)
+ next_timeout = d->next_period;
+ } else if (d->xce_handle != -1) {
int evtchn_fd = xc_evtchn_fd(d->xce_handle);
FD_SET(evtchn_fd, &readfds);
max_fd = MAX(evtchn_fd, max_fd);
@@ -811,11 +897,19 @@ void handle_io(void)
}
}
- /* XXX I wish we didn't have to busy wait for hypervisor logs
- * but there's no obvious way to get event channel notifications
- * for new HV log data as we can with guest */
+ /* If any domain has been rate limited, we need to work
+ out what timeout to supply to select */
+ if (next_timeout) {
+ long long duration = (next_timeout - now);
+ if (duration <= 0) /* sanity check */
+ duration = 1;
+ timeout.tv_sec = duration / 1000;
+ timeout.tv_usec = ((duration - (timeout.tv_sec * 1000))
+ * 1000);
+ }
+
ret = select(max_fd + 1, &readfds, &writefds, 0,
- log_hv_fd != -1 ? &timeout : NULL);
+ next_timeout ? &timeout : NULL);
if (log_reload) {
handle_log_reload();
@@ -832,12 +926,10 @@ void handle_io(void)
break;
}
- /* Always process HV logs even if not a timeout */
- if (log_hv_fd != -1)
+ if (log_hv && FD_ISSET(xc_evtchn_fd(xce_handle), &readfds))
handle_hv_logs();
- /* Must not check returned FDSET if it was a timeout */
- if (ret == 0)
+ if (ret <= 0)
continue;
if (FD_ISSET(xs_fileno(xs), &readfds))
@@ -845,9 +937,11 @@ void handle_io(void)
for (d = dom_head; d; d = n) {
n = d->next;
- if (d->xce_handle != -1 &&
- FD_ISSET(xc_evtchn_fd(d->xce_handle), &readfds))
- handle_ring_read(d);
+ if (d->event_count < RATE_LIMIT_ALLOWANCE) {
+ if (d->xce_handle != -1 &&
+ FD_ISSET(xc_evtchn_fd(d->xce_handle),
&readfds))
+ handle_ring_read(d);
+ }
if (d->tty_fd != -1 && FD_ISSET(d->tty_fd, &readfds))
handle_tty_read(d);
@@ -860,6 +954,7 @@ void handle_io(void)
}
}
+ out:
if (log_hv_fd != -1) {
close(log_hv_fd);
log_hv_fd = -1;
@@ -868,6 +963,11 @@ void handle_io(void)
xc_interface_close(xc_handle);
xc_handle = -1;
}
+ if (xce_handle != -1) {
+ xc_evtchn_close(xce_handle);
+ xce_handle = -1;
+ }
+ log_hv_evtchn = -1;
}
/*
diff -r c17bfb091790 -r a07288a84785 tools/examples/xend-config.sxp
--- a/tools/examples/xend-config.sxp Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/examples/xend-config.sxp Tue Oct 30 15:34:44 2007 -0600
@@ -192,8 +192,39 @@
# Empty string is no authentication.
(vncpasswd '')
+# The VNC server can be told to negotiate a TLS session
+# to encryption all traffic, and provide x509 cert to
+# clients enalbing them to verify server identity. The
+# GTK-VNC widget, virt-viewer, virt-manager and VeNCrypt
+# all support the VNC extension for TLS used in QEMU. The
+# TightVNC/RealVNC/UltraVNC clients do not.
+#
+# To enable this create x509 certificates / keys in the
+# directory /etc/xen/vnc
+#
+# ca-cert.pem - The CA certificate
+# server-cert.pem - The Server certificate signed by the CA
+# server-key.pem - The server private key
+#
+# and then uncomment this next line
+# (vnc-tls 1)
+
+# The certificate dir can be pointed elsewhere..
+#
+# (vnc-x509-cert-dir /etc/xen/vnc)
+
+# The server can be told to request & validate an x509
+# certificate from the client. Only clients with a cert
+# signed by the trusted CA will be able to connect. This
+# is more secure the password auth alone. Passwd auth can
+# used at the same time if desired. To enable client cert
+# checking uncomment this:
+#
+# (vnc-x509-verify 1)
+
# The default keymap to use for the VM's virtual keyboard
# when not specififed in VM's configuration
#(keymap 'en-us')
-
+# Script to run when the label of a resource has changed.
+#(resource-label-change-script '')
diff -r c17bfb091790 -r a07288a84785 tools/firmware/hvmloader/acpi/build.c
--- a/tools/firmware/hvmloader/acpi/build.c Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/firmware/hvmloader/acpi/build.c Tue Oct 30 15:34:44 2007 -0600
@@ -226,7 +226,7 @@ static int construct_processor_objects(u
}
/* NameString */
- strncpy(p, pr_scope, strlen(pr_scope));
+ strncpy((char *)p, pr_scope, strlen(pr_scope));
p += strlen(pr_scope);
/*
diff -r c17bfb091790 -r a07288a84785
tools/firmware/rombios/32bit/tcgbios/tcgbios.c
--- a/tools/firmware/rombios/32bit/tcgbios/tcgbios.c Tue Oct 30 11:33:55
2007 -0600
+++ b/tools/firmware/rombios/32bit/tcgbios/tcgbios.c Tue Oct 30 15:34:44
2007 -0600
@@ -591,7 +591,7 @@ void tcpa_add_measurement(uint32_t pcrIn
case EV_SEPARATOR:
tcpa_add_measurement_to_log_simple(pcrIndex,
event_type,
- evt_separator,
+ (uint8_t *)evt_separator,
4);
break;
case EV_ACTION:
diff -r c17bfb091790 -r a07288a84785 tools/firmware/vgabios/clext.c
--- a/tools/firmware/vgabios/clext.c Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/firmware/vgabios/clext.c Tue Oct 30 15:34:44 2007 -0600
@@ -1489,14 +1489,26 @@ cirrus_clear_vram_1:
mov dx, #0x3ce
out dx, ax
push ax
- mov cx, #0xa000
- mov es, cx
- xor di, di
+
+;; Windows Vista appears to be emulating this sequence as part of changing
+;; screen resolution, but it generates 4096 writes per iteration.
+;; Instead, use a magic register sequence to write the whole bank.
+;;mov cx, #0xa000
+;;mov es, cx
+;;xor di, di
+;;mov ax, si
+;;mov cx, #8192
+;;cld
+;;rep
+;; stosw
mov ax, si
- mov cx, #8192
- cld
- rep
- stosw
+ shl ax, #8
+ mov al, #0xfe
+ out dx, ax ;; Low byte of value to be written to the bank
+ mov ax, si
+ mov al, #0xff
+ out dx, ax ;; High byte and trigger the write
+
pop ax
inc ah
cmp ah, bl
diff -r c17bfb091790 -r a07288a84785 tools/firmware/vmxassist/machine.h
--- a/tools/firmware/vmxassist/machine.h Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/firmware/vmxassist/machine.h Tue Oct 30 15:34:44 2007 -0600
@@ -38,10 +38,15 @@
#define CR4_PSE (1 << 4)
#define CR4_PAE (1 << 5)
+#define EFLAGS_CF (1 << 0)
+#define EFLAGS_PF (1 << 2)
+#define EFLAGS_AF (1 << 4)
#define EFLAGS_ZF (1 << 6)
+#define EFLAGS_SF (1 << 7)
#define EFLAGS_TF (1 << 8)
#define EFLAGS_IF (1 << 9)
#define EFLAGS_DF (1 << 10)
+#define EFLAGS_OF (1 << 11)
#define EFLAGS_IOPL (3 << 12)
#define EFLAGS_VM ((1 << 17) | EFLAGS_IOPL)
#define EFLAGS_VIF (1 << 19)
diff -r c17bfb091790 -r a07288a84785 tools/firmware/vmxassist/vm86.c
--- a/tools/firmware/vmxassist/vm86.c Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/firmware/vmxassist/vm86.c Tue Oct 30 15:34:44 2007 -0600
@@ -33,6 +33,7 @@
#define SEG_SS 0x0020
#define SEG_FS 0x0040
#define SEG_GS 0x0080
+#define REP 0x0100
static unsigned prev_eip = 0;
enum vm86_mode mode = 0;
@@ -656,6 +657,108 @@ movr(struct regs *regs, unsigned prefix,
}
/*
+ * We need to handle string moves that address memory beyond the 64KB segment
+ * limit that VM8086 mode enforces.
+ */
+static inline int
+movs(struct regs *regs, unsigned prefix, unsigned opc)
+{
+ unsigned eip = regs->eip - 1;
+ unsigned sseg = segment(prefix, regs, regs->vds);
+ unsigned dseg = regs->ves;
+ unsigned saddr, daddr;
+ unsigned count = 1;
+ int incr = ((regs->eflags & EFLAGS_DF) == 0) ? 1 : -1;
+
+ saddr = address(regs, sseg, regs->esi);
+ daddr = address(regs, dseg, regs->edi);
+
+ if ((prefix & REP) != 0) {
+ count = regs->ecx;
+ regs->ecx = 0;
+ }
+
+ switch (opc) {
+ case 0xA4: /* movsb */
+ regs->esi += (incr * count);
+ regs->edi += (incr * count);
+
+ while (count-- != 0) {
+ write8(daddr, read8(saddr));
+ daddr += incr;
+ saddr += incr;
+ }
+ TRACE((regs, regs->eip - eip, "movsb (%%esi),%%es:(%%edi)"));
+ break;
+
+ case 0xA5: /* movsw */
+ if ((prefix & DATA32) == 0) {
+ incr = 2 * incr;
+ regs->esi += (incr * count);
+ regs->edi += (incr * count);
+
+ while (count-- != 0) {
+ write16(daddr, read16(saddr));
+ daddr += incr;
+ saddr += incr;
+ }
+ } else {
+ incr = 4 * incr;
+ regs->esi += (incr * count);
+ regs->edi += (incr * count);
+
+ while (count-- != 0) {
+ write32(daddr, read32(saddr));
+ daddr += incr;
+ saddr += incr;
+ }
+ }
+ TRACE((regs, regs->eip - eip, "movsw %s(%%esi),%%es:(%%edi)"));
+ break;
+ }
+
+ return 1;
+}
+
+static inline int
+lods(struct regs *regs, unsigned prefix, unsigned opc)
+{
+ unsigned eip = regs->eip - 1;
+ unsigned seg = segment(prefix, regs, regs->vds);
+ unsigned addr = address(regs, seg, regs->esi);
+ unsigned count = 1;
+ int incr = ((regs->eflags & EFLAGS_DF) == 0) ? 1 : -1;
+
+ if ((prefix & REP) != 0) {
+ count = regs->ecx;
+ regs->ecx = 0;
+ }
+
+ switch (opc) {
+ case 0xAD: /* lodsw */
+ if ((prefix & DATA32) == 0) {
+ incr = 2 * incr;
+ regs->esi += (incr * count);
+ while (count-- != 0) {
+ setreg16(regs, 0, read16(addr));
+ addr += incr;
+ }
+
+ TRACE((regs, regs->eip - eip, "lodsw (%%esi),%%ax"));
+ } else {
+ incr = 4 * incr;
+ regs->esi += (incr * count);
+ while (count-- != 0) {
+ setreg32(regs, 0, read32(addr));
+ addr += incr;
+ }
+ TRACE((regs, regs->eip - eip, "lodsw (%%esi),%%eax"));
+ }
+ break;
+ }
+ return 1;
+}
+/*
* Move to and from a control register.
*/
static int
@@ -718,6 +821,55 @@ static inline void set_eflags_ZF(unsigne
regs->eflags &= ~EFLAGS_ZF;
}
+static void set_eflags_add(unsigned hi_bit_mask, unsigned v1, unsigned v2,
+ unsigned result, struct regs *regs)
+{
+ int bit_count;
+ unsigned tmp;
+ unsigned full_mask;
+ unsigned nonsign_mask;
+
+ /* Carry out of high order bit? */
+ if ( v1 & v2 & hi_bit_mask )
+ regs->eflags |= EFLAGS_CF;
+ else
+ regs->eflags &= ~EFLAGS_CF;
+
+ /* Even parity in least significant byte? */
+ tmp = result & 0xff;
+ for (bit_count = 0; tmp != 0; bit_count++)
+ tmp &= (tmp - 1);
+
+ if (bit_count & 1)
+ regs->eflags &= ~EFLAGS_PF;
+ else
+ regs->eflags |= EFLAGS_PF;
+
+ /* Carry out of least significant BCD digit? */
+ if ( v1 & v2 & (1<<3) )
+ regs->eflags |= EFLAGS_AF;
+ else
+ regs->eflags &= ~EFLAGS_AF;
+
+ /* Result is zero? */
+ full_mask = (hi_bit_mask - 1) | hi_bit_mask;
+ set_eflags_ZF(full_mask, result, regs);
+
+ /* Sign of result? */
+ if ( result & hi_bit_mask )
+ regs->eflags |= EFLAGS_SF;
+ else
+ regs->eflags &= ~EFLAGS_SF;
+
+ /* Carry out of highest non-sign bit? */
+ nonsign_mask = (hi_bit_mask >> 1) & ~hi_bit_mask;
+ if ( v1 & v2 & hi_bit_mask )
+ regs->eflags |= EFLAGS_OF;
+ else
+ regs->eflags &= ~EFLAGS_OF;
+
+}
+
/*
* We need to handle cmp opcodes that address memory beyond the 64KB
* segment limit that VM8086 mode enforces.
@@ -787,6 +939,82 @@ test(struct regs *regs, unsigned prefix,
/* other test opcodes ... */
}
+
+ return 1;
+}
+
+/*
+ * We need to handle add opcodes that address memory beyond the 64KB
+ * segment limit that VM8086 mode enforces.
+ */
+static int
+add(struct regs *regs, unsigned prefix, unsigned opc)
+{
+ unsigned eip = regs->eip - 1;
+ unsigned modrm = fetch8(regs);
+ unsigned addr = operand(prefix, regs, modrm);
+ unsigned r = (modrm >> 3) & 7;
+
+ unsigned val1 = 0;
+ unsigned val2 = 0;
+ unsigned result = 0;
+ unsigned hi_bit;
+
+ if ((modrm & 0xC0) == 0xC0) /* no registers */
+ return 0;
+
+ switch (opc) {
+ case 0x00: /* addr32 add r8, r/m8 */
+ val1 = getreg8(regs, r);
+ val2 = read8(addr);
+ result = val1 + val2;
+ write8(addr, result);
+ TRACE((regs, regs->eip - eip,
+ "addb %%e%s, *0x%x", rnames[r], addr));
+ break;
+
+ case 0x01: /* addr32 add r16, r/m16 */
+ if (prefix & DATA32) {
+ val1 = getreg32(regs, r);
+ val2 = read32(addr);
+ result = val1 + val2;
+ write32(addr, result);
+ TRACE((regs, regs->eip - eip,
+ "addl %%e%s, *0x%x", rnames[r], addr));
+ } else {
+ val1 = getreg16(regs, r);
+ val2 = read16(addr);
+ result = val1 + val2;
+ write16(addr, result);
+ TRACE((regs, regs->eip - eip,
+ "addw %%e%s, *0x%x", rnames[r], addr));
+ }
+ break;
+
+ case 0x03: /* addr32 add r/m16, r16 */
+ if (prefix & DATA32) {
+ val1 = getreg32(regs, r);
+ val2 = read32(addr);
+ result = val1 + val2;
+ setreg32(regs, r, result);
+ TRACE((regs, regs->eip - eip,
+ "addl *0x%x, %%e%s", addr, rnames[r]));
+ } else {
+ val1 = getreg16(regs, r);
+ val2 = read16(addr);
+ result = val1 + val2;
+ setreg16(regs, r, result);
+ TRACE((regs, regs->eip - eip,
+ "addw *0x%x, %%%s", addr, rnames[r]));
+ }
+ break;
+ }
+
+ if (opc == 0x00)
+ hi_bit = (1<<7);
+ else
+ hi_bit = (prefix & DATA32) ? (1<<31) : (1<<15);
+ set_eflags_add(hi_bit, val1, val2, result, regs);
return 1;
}
@@ -1314,6 +1542,18 @@ opcode(struct regs *regs)
for (;;) {
switch ((opc = fetch8(regs))) {
+
+ case 0x00: /* addr32 add r8, r/m8 */
+ case 0x01: /* addr32 add r16, r/m16 */
+ case 0x03: /* addr32 add r/m16, r16 */
+ if (mode != VM86_REAL && mode != VM86_REAL_TO_PROTECTED)
+ goto invalid;
+ if ((prefix & ADDR32) == 0)
+ goto invalid;
+ if (!add(regs, prefix, opc))
+ goto invalid;
+ return OPC_EMULATED;
+
case 0x07: /* pop %es */
regs->ves = (prefix & DATA32) ?
pop32(regs) : pop16(regs);
@@ -1510,6 +1750,21 @@ opcode(struct regs *regs)
return OPC_EMULATED;
}
+ case 0xA4: /* movsb */
+ case 0xA5: /* movsw */
+ if ((prefix & ADDR32) == 0)
+ goto invalid;
+ if (!movs(regs, prefix, opc))
+ goto invalid;
+ return OPC_EMULATED;
+
+ case 0xAD: /* lodsw */
+ if ((prefix & ADDR32) == 0)
+ goto invalid;
+ if (!lods(regs, prefix, opc))
+ goto invalid;
+ return OPC_EMULATED;
+
case 0xBB: /* mov bx, imm16 */
{
int data;
@@ -1627,6 +1882,11 @@ opcode(struct regs *regs)
/* Do something power-saving here! */
return OPC_EMULATED;
+ case 0xF3: /* rep/repe/repz */
+ TRACE((regs, regs->eip - eip, "rep"));
+ prefix |= REP;
+ continue;
+
case 0xF6: /* addr32 testb $imm, r/m8 */
if (!(prefix & ADDR32))
goto invalid;
@@ -1660,6 +1920,7 @@ emulate(struct regs *regs)
{
unsigned flteip;
int nemul = 0;
+ unsigned ip;
/* emulate as many instructions as possible */
while (opcode(regs) != OPC_INVALID)
@@ -1668,6 +1929,12 @@ emulate(struct regs *regs)
/* detect the case where we are not making progress */
if (nemul == 0 && prev_eip == regs->eip) {
flteip = address(regs, MASK16(regs->cs), regs->eip);
+
+ printf("Undecoded sequence: \n");
+ for (ip=flteip; ip < flteip+16; ip++)
+ printf("0x%02x ", read8(ip));
+ printf("\n");
+
panic("Unknown opcode at %04x:%04x=0x%x",
MASK16(regs->cs), regs->eip, flteip);
} else
diff -r c17bfb091790 -r a07288a84785 tools/ioemu/Makefile.target
--- a/tools/ioemu/Makefile.target Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/ioemu/Makefile.target Tue Oct 30 15:34:44 2007 -0600
@@ -387,6 +387,11 @@ endif
endif
AUDIODRV+= wavcapture.o
+ifdef CONFIG_VNC_TLS
+CPPFLAGS += $(CONFIG_VNC_TLS_CFLAGS)
+LIBS += $(CONFIG_VNC_TLS_LIBS)
+endif
+
# SCSI layer
VL_OBJS+= scsi-disk.o cdrom.o lsi53c895a.o
@@ -409,6 +414,10 @@ VL_OBJS+= piix4acpi.o
VL_OBJS+= piix4acpi.o
VL_OBJS+= xenstore.o
VL_OBJS+= xen_platform.o
+VL_OBJS+= xen_machine_fv.o
+VL_OBJS+= xen_machine_pv.o
+VL_OBJS+= xenfb.o
+VL_OBJS+= xen_console.o
VL_OBJS+= tpm_tis.o
CPPFLAGS += -DHAS_AUDIO
endif
@@ -452,8 +461,7 @@ ifdef CONFIG_SDL
ifdef CONFIG_SDL
VL_OBJS+=sdl.o x_keymap.o
endif
-VL_OBJS+=vnc.o
-VL_OBJS+=d3des.o
+VL_OBJS+=vnc.o d3des.o
ifdef CONFIG_COCOA
VL_OBJS+=cocoa.o
COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa -framework IOKit
@@ -511,11 +519,8 @@ sdl.o: sdl.c keymaps.c sdl_keysym.h
sdl.o: sdl.c keymaps.c sdl_keysym.h
$(CC) $(CFLAGS) $(CPPFLAGS) $(SDL_CFLAGS) $(BASE_CFLAGS) -c -o $@ $<
-vnc.o: vnc.c keymaps.c sdl_keysym.h vnchextile.h
+vnc.o: vnc.c keymaps.c sdl_keysym.h vnchextile.h d3des.c d3des.h
$(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
-
-d3des.o: d3des.c d3des.h
- $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
sdlaudio.o: sdlaudio.c
$(CC) $(CFLAGS) $(CPPFLAGS) $(SDL_CFLAGS) $(BASE_CFLAGS) -c -o $@ $<
diff -r c17bfb091790 -r a07288a84785 tools/ioemu/configure
--- a/tools/ioemu/configure Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/ioemu/configure Tue Oct 30 15:34:44 2007 -0600
@@ -87,6 +87,7 @@ fmod="no"
fmod="no"
fmod_lib=""
fmod_inc=""
+vnc_tls="yes"
bsd="no"
linux="no"
kqemu="no"
@@ -225,6 +226,8 @@ for opt do
;;
--fmod-inc=*) fmod_inc="$optarg"
;;
+ --disable-vnc-tls) vnc_tls="no"
+ ;;
--enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-" ; user="no"
;;
--disable-slirp) slirp="no"
@@ -292,6 +295,7 @@ echo " --enable-alsa enable
echo " --enable-alsa enable ALSA audio driver"
echo " --enable-fmod enable FMOD audio driver"
echo " --enabled-dsound enable DirectSound audio driver"
+echo " --disable-vnc-tls disable TLS encryption for VNC server"
echo " --enable-system enable all system emulation targets"
echo " --disable-system disable all system emulation targets"
echo " --enable-linux-user enable all linux usermode emulation targets"
@@ -410,6 +414,18 @@ if test "$solaris" = "yes" ; then
fi
fi
+##########################################
+
+# VNC TLS detection
+if test "$vnc_tls" = "yes" ; then
+ `pkg-config gnutls` || vnc_tls="no"
+fi
+if test "$vnc_tls" = "yes" ; then
+ vnc_tls_cflags=`pkg-config --cflags gnutls`
+ vnc_tls_libs=`pkg-config --libs gnutls`
+fi
+
+##########################################
if test -z "$target_list" ; then
# these targets are portable
@@ -771,6 +787,12 @@ if test "$fmod" = "yes" ; then
echo "CONFIG_FMOD_LIB=$fmod_lib" >> $config_mak
echo "CONFIG_FMOD_INC=$fmod_inc" >> $config_mak
echo "#define CONFIG_FMOD 1" >> $config_h
+fi
+if test "$vnc_tls" = "yes" ; then
+ echo "CONFIG_VNC_TLS=yes" >> $config_mak
+ echo "CONFIG_VNC_TLS_CFLAGS=$vnc_tls_cflags" >> $config_mak
+ echo "CONFIG_VNC_TLS_LIBS=$vnc_tls_libs" >> $config_mak
+ echo "#define CONFIG_VNC_TLS 1" >> $config_h
fi
qemu_version=`head $source_path/VERSION`
echo "VERSION=$qemu_version" >>$config_mak
@@ -999,4 +1021,10 @@ if test "$source_path_used" = "yes" ; th
done
fi
+echo "VNC TLS support $vnc_tls"
+if test "$vnc_tls" = "yes" ; then
+ echo " TLS CFLAGS $vnc_tls_cflags"
+ echo " TLS LIBS $vnc_tls_libs"
+fi
+
rm -f $TMPO $TMPC $TMPE $TMPS
diff -r c17bfb091790 -r a07288a84785 tools/ioemu/hw/cirrus_vga.c
--- a/tools/ioemu/hw/cirrus_vga.c Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/ioemu/hw/cirrus_vga.c Tue Oct 30 15:34:44 2007 -0600
@@ -294,6 +294,7 @@ void *shared_vram;
static void cirrus_bitblt_reset(CirrusVGAState *s);
static void cirrus_update_memory_access(CirrusVGAState *s);
+static void cirrus_vga_mem_writew(void *opaque, target_phys_addr_t addr,
uint32_t val);
/***************************************
*
@@ -1497,6 +1498,17 @@ cirrus_hook_write_gr(CirrusVGAState * s,
case 0x31: // BLT STATUS/START
cirrus_write_bitblt(s, reg_value);
break;
+
+ // Extension to allow BIOS to clear 16K VRAM bank in one operation
+ case 0xFE:
+ s->gr[reg_index] = reg_value; // Lower byte of value to be written
+ break;
+ case 0xFF: {
+ target_phys_addr_t addr;
+ for (addr = 0xa0000; addr < 0xa4000; addr += 2)
+ cirrus_vga_mem_writew(s, addr, (reg_value << 8) | s->gr[0xFE]);
+ }
+ break;
default:
#ifdef DEBUG_CIRRUS
printf("cirrus: outport gr_index %02x, gr_value %02x\n", reg_index,
diff -r c17bfb091790 -r a07288a84785 tools/ioemu/hw/xen_console.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/hw/xen_console.c Tue Oct 30 15:34:44 2007 -0600
@@ -0,0 +1,432 @@
+/*
+ * Copyright (C) International Business Machines Corp., 2005
+ * Author(s): Anthony Liguori <aliguori@xxxxxxxxxx>
+ *
+ * Copyright (C) Red Hat 2007
+ *
+ * Xen Console
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; under version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <malloc.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/select.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <termios.h>
+#include <stdarg.h>
+#include <sys/mman.h>
+#include <xs.h>
+#include <xen/io/console.h>
+#include <xenctrl.h>
+
+#include "vl.h"
+
+#include "xen_console.h"
+
+#define dolog(val, fmt, ...) fprintf(stderr, fmt "\n", ## __VA_ARGS__)
+
+struct buffer
+{
+ uint8_t *data;
+ size_t consumed;
+ size_t size;
+ size_t capacity;
+ size_t max_capacity;
+};
+
+struct domain
+{
+ int domid;
+ struct buffer buffer;
+
+ char *conspath;
+ char *serialpath;
+ int use_consolepath;
+ int ring_ref;
+ evtchn_port_t local_port;
+ evtchn_port_t remote_port;
+ int xce_handle;
+ struct xs_handle *xsh;
+ struct xencons_interface *interface;
+ CharDriverState *chr;
+};
+
+
+static void buffer_append(struct domain *dom)
+{
+ struct buffer *buffer = &dom->buffer;
+ XENCONS_RING_IDX cons, prod, size;
+ struct xencons_interface *intf = dom->interface;
+
+ cons = intf->out_cons;
+ prod = intf->out_prod;
+ mb();
+
+ size = prod - cons;
+ if ((size == 0) || (size > sizeof(intf->out)))
+ return;
+
+ if ((buffer->capacity - buffer->size) < size) {
+ buffer->capacity += (size + 1024);
+ buffer->data = realloc(buffer->data, buffer->capacity);
+ if (buffer->data == NULL) {
+ dolog(LOG_ERR, "Memory allocation failed");
+ exit(ENOMEM);
+ }
+ }
+
+ while (cons != prod)
+ buffer->data[buffer->size++] = intf->out[
+ MASK_XENCONS_IDX(cons++, intf->out)];
+
+ mb();
+ intf->out_cons = cons;
+ xc_evtchn_notify(dom->xce_handle, dom->local_port);
+
+ if (buffer->max_capacity &&
+ buffer->size > buffer->max_capacity) {
+ /* Discard the middle of the data. */
+
+ size_t over = buffer->size - buffer->max_capacity;
+ uint8_t *maxpos = buffer->data + buffer->max_capacity;
+
+ memmove(maxpos - over, maxpos, over);
+ buffer->data = realloc(buffer->data, buffer->max_capacity);
+ buffer->size = buffer->capacity = buffer->max_capacity;
+
+ if (buffer->consumed > buffer->max_capacity - over)
+ buffer->consumed = buffer->max_capacity - over;
+ }
+}
+
+static void buffer_advance(struct buffer *buffer, size_t len)
+{
+ buffer->consumed += len;
+ if (buffer->consumed == buffer->size) {
+ buffer->consumed = 0;
+ buffer->size = 0;
+ }
+}
+
+/* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
+int xs_gather(struct xs_handle *xs, const char *dir, ...)
+{
+ va_list ap;
+ const char *name;
+ char *path;
+ int ret = 0;
+
+ va_start(ap, dir);
+ while (ret == 0 && (name = va_arg(ap, char *)) != NULL) {
+ const char *fmt = va_arg(ap, char *);
+ void *result = va_arg(ap, void *);
+ char *p;
+
+ if (asprintf(&path, "%s/%s", dir, name) == -1) {
+ ret = ENOMEM;
+ break;
+ }
+ p = xs_read(xs, XBT_NULL, path, NULL);
+ free(path);
+ if (p == NULL) {
+ ret = ENOENT;
+ break;
+ }
+ if (fmt) {
+ if (sscanf(p, fmt, result) == 0)
+ ret = EINVAL;
+ free(p);
+ } else
+ *(char **)result = p;
+ }
+ va_end(ap);
+ return ret;
+}
+
+static int domain_create_ring(struct domain *dom)
+{
+ int err, remote_port, ring_ref, rc;
+
+ err = xs_gather(dom->xsh, dom->serialpath,
+ "ring-ref", "%u", &ring_ref,
+ "port", "%i", &remote_port,
+ NULL);
+ if (err) {
+ err = xs_gather(dom->xsh, dom->conspath,
+ "ring-ref", "%u", &ring_ref,
+ "port", "%i", &remote_port,
+ NULL);
+ if (err) {
+ fprintf(stderr, "Console: failed to find ring-ref/port
yet\n");
+ goto out;
+ }
+ dom->use_consolepath = 1;
+ } else
+ dom->use_consolepath = 0;
+ fprintf(stderr, "Console: got ring-ref %d port %d\n", ring_ref,
remote_port);
+
+ if ((ring_ref == dom->ring_ref) && (remote_port == dom->remote_port))
+ goto out;
+
+ if (ring_ref != dom->ring_ref) {
+ if (dom->interface != NULL)
+ munmap(dom->interface, getpagesize());
+ dom->interface = xc_map_foreign_range(
+ xc_handle, dom->domid, getpagesize(),
+ PROT_READ|PROT_WRITE,
+ (unsigned long)ring_ref);
+ if (dom->interface == NULL) {
+ err = errno;
+ goto out;
+ }
+ dom->ring_ref = ring_ref;
+ }
+
+ dom->local_port = -1;
+ dom->remote_port = -1;
+
+ dom->xce_handle = xc_evtchn_open();
+ if (dom->xce_handle == -1) {
+ err = errno;
+ goto out;
+ }
+
+ rc = xc_evtchn_bind_interdomain(dom->xce_handle,
+ dom->domid, remote_port);
+
+ if (rc == -1) {
+ err = errno;
+ xc_evtchn_close(dom->xce_handle);
+ dom->xce_handle = -1;
+ goto out;
+ }
+ dom->local_port = rc;
+ dom->remote_port = remote_port;
+
+ out:
+ return err;
+}
+
+
+static struct domain *create_domain(int domid, CharDriverState *chr)
+{
+ struct domain *dom;
+ char *s;
+
+ dom = (struct domain *)malloc(sizeof(struct domain));
+ if (dom == NULL) {
+ dolog(LOG_ERR, "Out of memory %s:%s():L%d",
+ __FILE__, __FUNCTION__, __LINE__);
+ exit(ENOMEM);
+ }
+
+ dom->domid = domid;
+ dom->chr = chr;
+
+ dom->xsh = xs_daemon_open();
+ if (dom->xsh == NULL) {
+ fprintf(logfile, "Could not contact xenstore for console
watch\n");
+ goto out;
+ }
+
+ dom->serialpath = xs_get_domain_path(dom->xsh, dom->domid);
+ s = realloc(dom->serialpath, strlen(dom->serialpath) +
+ strlen("/serial/0") + 1);
+ if (s == NULL)
+ goto out;
+ dom->serialpath = s;
+ strcat(dom->serialpath, "/serial/0");
+
+ dom->conspath = xs_get_domain_path(dom->xsh, dom->domid);
+ s = realloc(dom->conspath, strlen(dom->conspath) +
+ strlen("/console") + 1);
+ if (s == NULL)
+ goto out;
+ dom->conspath = s;
+ strcat(dom->conspath, "/console");
+
+ dom->buffer.data = 0;
+ dom->buffer.consumed = 0;
+ dom->buffer.size = 0;
+ dom->buffer.capacity = 0;
+ dom->buffer.max_capacity = 0;
+
+ dom->ring_ref = -1;
+ dom->local_port = -1;
+ dom->remote_port = -1;
+ dom->interface = NULL;
+ dom->xce_handle = -1;
+
+
+ return dom;
+ out:
+ free(dom->serialpath);
+ free(dom->conspath);
+ free(dom);
+ return NULL;
+}
+
+
+static int ring_free_bytes(struct domain *dom)
+{
+ struct xencons_interface *intf = dom->interface;
+ XENCONS_RING_IDX cons, prod, space;
+
+ cons = intf->in_cons;
+ prod = intf->in_prod;
+ mb();
+
+ space = prod - cons;
+ if (space > sizeof(intf->in))
+ return 0; /* ring is screwed: ignore it */
+
+ return (sizeof(intf->in) - space);
+}
+
+static int xencons_can_receive(void *opaque)
+{
+ struct domain *dom = (struct domain *)opaque;
+
+ return ring_free_bytes(dom);
+}
+
+static void xencons_receive(void *opaque, const uint8_t *buf, int len)
+{
+ struct domain *dom = (struct domain *)opaque;
+ int i, max;
+ struct xencons_interface *intf = dom->interface;
+ XENCONS_RING_IDX prod;
+
+ max = ring_free_bytes(dom);
+ /* The can_receive() func limits this, but check again anyway */
+ if (max < len)
+ len = max;
+
+ prod = intf->in_prod;
+ for (i = 0; i < len; i++) {
+ intf->in[MASK_XENCONS_IDX(prod++, intf->in)] =
+ buf[i];
+ }
+ wmb();
+ intf->in_prod = prod;
+ xc_evtchn_notify(dom->xce_handle, dom->local_port);
+}
+
+static void xencons_send(struct domain *dom)
+{
+ ssize_t len;
+ len = qemu_chr_write(dom->chr, dom->buffer.data + dom->buffer.consumed,
+ dom->buffer.size - dom->buffer.consumed);
+ if (len < 1) {
+ /*
+ * Disable log because if we're redirecting to /dev/pts/N we
+ * don't want to flood logs when no client has the PTY open
+ */
+ /*
+ dolog(LOG_DEBUG, "Write failed on domain %d: %zd, %d\n",
+ dom->domid, len, errno);
+ */
+ } else {
+ buffer_advance(&dom->buffer, len);
+ }
+}
+
+static void xencons_ring_read(void *opaque)
+{
+ evtchn_port_t port;
+ struct domain *dom = (struct domain *)opaque;
+
+ if ((port = xc_evtchn_pending(dom->xce_handle)) == -1)
+ return;
+
+ buffer_append(dom);
+
+ (void)xc_evtchn_unmask(dom->xce_handle, port);
+
+ if (dom->buffer.size - dom->buffer.consumed)
+ xencons_send(dom);
+}
+
+static void xencons_startup(void *opaque)
+{
+ struct domain *dom = (struct domain *)opaque;
+ unsigned dummy;
+ char **vec;
+ int err;
+ vec = xs_read_watch(dom->xsh, &dummy);
+ if (vec)
+ free(vec);
+ fprintf(stderr, "Console: got watch\n");
+ err = domain_create_ring(dom);
+ if (err)
+ return;
+
+ xs_unwatch(dom->xsh, dom->conspath, "");
+ xs_unwatch(dom->xsh, dom->serialpath, "");
+ qemu_set_fd_handler2(xs_fileno(dom->xsh), NULL, NULL, NULL, NULL);
+
+ fprintf(stderr, "Console: connected to guest frontend\n");
+ if (qemu_set_fd_handler2(dom->xce_handle, NULL, xencons_ring_read,
NULL, dom) < 0)
+ return;
+
+ qemu_chr_add_handlers(dom->chr, xencons_can_receive, xencons_receive,
+ NULL, dom);
+}
+
+
+int xencons_init(int domid, CharDriverState *chr)
+{
+ struct domain *dom = create_domain(domid, chr);
+
+ if (!dom)
+ return -1;
+
+ /* Setup watches so we asynchronously connect to serial console */
+ if (!(xs_watch(dom->xsh, dom->conspath, ""))) {
+ fprintf(stderr, "Unable to watch console %s\n", dom->conspath);
+ goto fail;
+ }
+ if (!(xs_watch(dom->xsh, dom->serialpath, ""))) {
+ fprintf(stderr, "Unable to watch console %s\n", dom->conspath);
+ xs_unwatch(dom->xsh, dom->conspath, "");
+ goto fail;
+ }
+ qemu_set_fd_handler2(xs_fileno(dom->xsh), NULL, xencons_startup, NULL,
dom);
+ fprintf(stderr, "Console: prepared domain, waiting for ringref at %s or
%s\n",
+ dom->conspath, dom->serialpath);
+
+ return 0;
+
+fail:
+ xs_daemon_close(dom->xsh);
+ free(dom->serialpath);
+ free(dom->conspath);
+ free(dom);
+ return -1;
+}
+
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r c17bfb091790 -r a07288a84785 tools/ioemu/hw/xen_console.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/hw/xen_console.h Tue Oct 30 15:34:44 2007 -0600
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) International Business Machines Corp., 2005
+ * Author(s): Anthony Liguori <aliguori@xxxxxxxxxx>
+ *
+ * Copyright (C) Red Hat 2007
+ *
+ * Xen Console
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; under version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "vl.h"
+
+extern int xencons_init(int domid, CharDriverState *chr);
diff -r c17bfb091790 -r a07288a84785 tools/ioemu/hw/xen_machine_fv.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/hw/xen_machine_fv.c Tue Oct 30 15:34:44 2007 -0600
@@ -0,0 +1,296 @@
+/*
+ * QEMU Xen FV Machine
+ *
+ * Copyright (c) 2003-2007 Fabrice Bellard
+ * Copyright (c) 2007 Red Hat
+ *
+ * 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 <xen/hvm/params.h>
+#include <sys/mman.h>
+
+#ifndef PAGE_SIZE
+#define PAGE_SIZE XC_PAGE_SIZE
+#endif
+#ifndef PAGE_SHIFT
+#define PAGE_SHIFT XC_PAGE_SHIFT
+#endif
+
+#if defined(MAPCACHE)
+
+#if defined(__i386__)
+#define MAX_MCACHE_SIZE 0x40000000 /* 1GB max for x86 */
+#define MCACHE_BUCKET_SHIFT 16
+#elif defined(__x86_64__)
+#define MAX_MCACHE_SIZE 0x1000000000 /* 64GB max for x86_64 */
+#define MCACHE_BUCKET_SHIFT 20
+#endif
+
+#define MCACHE_BUCKET_SIZE (1UL << MCACHE_BUCKET_SHIFT)
+
+#define BITS_PER_LONG (sizeof(long)*8)
+#define BITS_TO_LONGS(bits) \
+ (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG)
+#define DECLARE_BITMAP(name,bits) \
+ unsigned long name[BITS_TO_LONGS(bits)]
+#define test_bit(bit,map) \
+ (!!((map)[(bit)/BITS_PER_LONG] & (1UL << ((bit)%BITS_PER_LONG))))
+
+struct map_cache {
+ unsigned long paddr_index;
+ uint8_t *vaddr_base;
+ DECLARE_BITMAP(valid_mapping, MCACHE_BUCKET_SIZE>>PAGE_SHIFT);
+};
+
+static struct map_cache *mapcache_entry;
+static unsigned long nr_buckets;
+
+/* For most cases (>99.9%), the page address is the same. */
+static unsigned long last_address_index = ~0UL;
+static uint8_t *last_address_vaddr;
+
+static int qemu_map_cache_init(void)
+{
+ unsigned long size;
+
+ nr_buckets = (((MAX_MCACHE_SIZE >> PAGE_SHIFT) +
+ (1UL << (MCACHE_BUCKET_SHIFT - PAGE_SHIFT)) - 1) >>
+ (MCACHE_BUCKET_SHIFT - PAGE_SHIFT));
+
+ /*
+ * Use mmap() directly: lets us allocate a big hash table with no up-front
+ * cost in storage space. The OS will allocate memory only for the buckets
+ * that we actually use. All others will contain all zeroes.
+ */
+ size = nr_buckets * sizeof(struct map_cache);
+ size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
+ fprintf(logfile, "qemu_map_cache_init nr_buckets = %lx size %lu\n",
nr_buckets, size);
+ mapcache_entry = mmap(NULL, size, PROT_READ|PROT_WRITE,
+ MAP_SHARED|MAP_ANON, -1, 0);
+ if (mapcache_entry == MAP_FAILED) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ return 0;
+}
+
+static void qemu_remap_bucket(struct map_cache *entry,
+ unsigned long address_index)
+{
+ uint8_t *vaddr_base;
+ unsigned long pfns[MCACHE_BUCKET_SIZE >> PAGE_SHIFT];
+ unsigned int i, j;
+
+ if (entry->vaddr_base != NULL) {
+ errno = munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE);
+ if (errno) {
+ fprintf(logfile, "unmap fails %d\n", errno);
+ exit(-1);
+ }
+ }
+
+ for (i = 0; i < MCACHE_BUCKET_SIZE >> PAGE_SHIFT; i++)
+ pfns[i] = (address_index << (MCACHE_BUCKET_SHIFT-PAGE_SHIFT)) + i;
+
+ vaddr_base = xc_map_foreign_batch(xc_handle, domid, PROT_READ|PROT_WRITE,
+ pfns, MCACHE_BUCKET_SIZE >> PAGE_SHIFT);
+ if (vaddr_base == NULL) {
+ fprintf(logfile, "xc_map_foreign_batch error %d\n", errno);
+ exit(-1);
+ }
+
+ entry->vaddr_base = vaddr_base;
+ entry->paddr_index = address_index;
+
+ for (i = 0; i < MCACHE_BUCKET_SIZE >> PAGE_SHIFT; i += BITS_PER_LONG) {
+ unsigned long word = 0;
+ j = ((i + BITS_PER_LONG) > (MCACHE_BUCKET_SIZE >> PAGE_SHIFT)) ?
+ (MCACHE_BUCKET_SIZE >> PAGE_SHIFT) % BITS_PER_LONG : BITS_PER_LONG;
+ while (j > 0)
+ word = (word << 1) | (((pfns[i + --j] >> 28) & 0xf) != 0xf);
+ entry->valid_mapping[i / BITS_PER_LONG] = word;
+ }
+}
+
+uint8_t *qemu_map_cache(target_phys_addr_t phys_addr)
+{
+ struct map_cache *entry;
+ unsigned long address_index = phys_addr >> MCACHE_BUCKET_SHIFT;
+ unsigned long address_offset = phys_addr & (MCACHE_BUCKET_SIZE-1);
+
+ if (address_index == last_address_index)
+ return last_address_vaddr + address_offset;
+
+ entry = &mapcache_entry[address_index % nr_buckets];
+
+ if (entry->vaddr_base == NULL || entry->paddr_index != address_index ||
+ !test_bit(address_offset>>PAGE_SHIFT, entry->valid_mapping))
+ qemu_remap_bucket(entry, address_index);
+
+ if (!test_bit(address_offset>>PAGE_SHIFT, entry->valid_mapping))
+ return NULL;
+
+ last_address_index = address_index;
+ last_address_vaddr = entry->vaddr_base;
+
+ return last_address_vaddr + address_offset;
+}
+
+void qemu_invalidate_map_cache(void)
+{
+ unsigned long i;
+
+ mapcache_lock();
+
+ for (i = 0; i < nr_buckets; i++) {
+ struct map_cache *entry = &mapcache_entry[i];
+
+ if (entry->vaddr_base == NULL)
+ continue;
+
+ errno = munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE);
+ if (errno) {
+ fprintf(logfile, "unmap fails %d\n", errno);
+ exit(-1);
+ }
+
+ entry->paddr_index = 0;
+ entry->vaddr_base = NULL;
+ }
+
+ last_address_index = ~0UL;
+ last_address_vaddr = NULL;
+
+ mapcache_unlock();
+}
+
+#endif /* defined(MAPCACHE) */
+
+
+static void xen_init_fv(uint64_t ram_size, int vga_ram_size, char *boot_device,
+ DisplayState *ds, const char **fd_filename,
+ int snapshot,
+ const char *kernel_filename,
+ const char *kernel_cmdline,
+ const char *initrd_filename,
+ const char *direct_pci)
+{
+ unsigned long ioreq_pfn;
+ extern void *shared_page;
+ extern void *buffered_io_page;
+#ifdef __ia64__
+ unsigned long nr_pages;
+ xen_pfn_t *page_array;
+ extern void *buffered_pio_page;
+ int i;
+#endif
+
+#if defined(__i386__) || defined(__x86_64__)
+
+ if (qemu_map_cache_init()) {
+ fprintf(logfile, "qemu_map_cache_init returned: error %d\n", errno);
+ exit(-1);
+ }
+
+ xc_get_hvm_param(xc_handle, domid, HVM_PARAM_IOREQ_PFN, &ioreq_pfn);
+ fprintf(logfile, "shared page at pfn %lx\n", ioreq_pfn);
+ shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
+ PROT_READ|PROT_WRITE, ioreq_pfn);
+ if (shared_page == NULL) {
+ fprintf(logfile, "map shared IO page returned error %d\n", errno);
+ exit(-1);
+ }
+
+ xc_get_hvm_param(xc_handle, domid, HVM_PARAM_BUFIOREQ_PFN, &ioreq_pfn);
+ fprintf(logfile, "buffered io page at pfn %lx\n", ioreq_pfn);
+ buffered_io_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
+ PROT_READ|PROT_WRITE, ioreq_pfn);
+ if (buffered_io_page == NULL) {
+ fprintf(logfile, "map buffered IO page returned error %d\n", errno);
+ exit(-1);
+ }
+
+#elif defined(__ia64__)
+
+ nr_pages = ram_size/PAGE_SIZE;
+
+ page_array = (xen_pfn_t *)malloc(nr_pages * sizeof(xen_pfn_t));
+ if (page_array == NULL) {
+ fprintf(logfile, "malloc returned error %d\n", errno);
+ exit(-1);
+ }
+
+ shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
+ PROT_READ|PROT_WRITE,
+ IO_PAGE_START >> PAGE_SHIFT);
+
+ buffered_io_page =xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
+ PROT_READ|PROT_WRITE,
+ BUFFER_IO_PAGE_START >> PAGE_SHIFT);
+
+ buffered_pio_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
+ PROT_READ|PROT_WRITE,
+ BUFFER_PIO_PAGE_START >> PAGE_SHIFT);
+
+ for (i = 0; i < nr_pages; i++)
+ page_array[i] = i;
+
+ /* VTI will not use memory between 3G~4G, so we just pass a legal pfn
+ to make QEMU map continuous virtual memory space */
+ if (ram_size > MMIO_START) {
+ for (i = 0 ; i < (MEM_G >> PAGE_SHIFT); i++)
+ page_array[(MMIO_START >> PAGE_SHIFT) + i] =
+ (STORE_PAGE_START >> PAGE_SHIFT);
+ }
+
+ phys_ram_base = xc_map_foreign_batch(xc_handle, domid,
+ PROT_READ|PROT_WRITE,
+ page_array, nr_pages);
+ if (phys_ram_base == 0) {
+ fprintf(logfile, "xc_map_foreign_batch returned error %d\n", errno);
+ exit(-1);
+ }
+ free(page_array);
+#endif
+
+ timeoffset_get();
+
+
+ pc_machine.init(ram_size, vga_ram_size, boot_device, ds, fd_filename,
+ snapshot, kernel_filename, kernel_cmdline, initrd_filename,
+ direct_pci);
+}
+
+QEMUMachine xenfv_machine = {
+ "xenfv",
+ "Xen Fully-virtualized PC",
+ xen_init_fv,
+};
+
+/*
+ * Local variables:
+ * indent-tabs-mode: nil
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
diff -r c17bfb091790 -r a07288a84785 tools/ioemu/hw/xen_machine_pv.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/hw/xen_machine_pv.c Tue Oct 30 15:34:44 2007 -0600
@@ -0,0 +1,73 @@
+/*
+ * QEMU Xen PV Machine
+ *
+ * Copyright (c) 2007 Red Hat
+ *
+ * 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 "xen_console.h"
+#include "xenfb.h"
+
+/* The Xen PV machine currently provides
+ * - a virtual framebuffer
+ * - ....
+ */
+static void xen_init_pv(uint64_t ram_size, int vga_ram_size, char *boot_device,
+ DisplayState *ds, const char **fd_filename,
+ int snapshot,
+ const char *kernel_filename,
+ const char *kernel_cmdline,
+ const char *initrd_filename)
+{
+ struct xenfb *xenfb;
+ extern int domid;
+
+ /* Connect to text console */
+ if (serial_hds[0]) {
+ if (xencons_init(domid, serial_hds[0]) < 0) {
+ fprintf(stderr, "Could not connect to domain console\n");
+ exit(1);
+ }
+ }
+
+ /* Prepare PVFB state */
+ xenfb = xenfb_new(domid, ds);
+ if (xenfb == NULL) {
+ fprintf(stderr, "Could not create framebuffer (%s)\n",
+ strerror(errno));
+ exit(1);
+ }
+}
+
+QEMUMachine xenpv_machine = {
+ "xenpv",
+ "Xen Para-virtualized PC",
+ xen_init_pv,
+};
+
+/*
+ * Local variables:
+ * indent-tabs-mode: nil
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
diff -r c17bfb091790 -r a07288a84785 tools/ioemu/hw/xen_platform.c
--- a/tools/ioemu/hw/xen_platform.c Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/ioemu/hw/xen_platform.c Tue Oct 30 15:34:44 2007 -0600
@@ -36,14 +36,24 @@ static void platform_ioport_map(PCIDevic
static uint32_t platform_mmio_read(void *opaque, target_phys_addr_t addr)
{
- fprintf(logfile, "Warning: try read from xen platform mmio space\n");
+ static int warnings = 0;
+ if (warnings < 5) {
+ fprintf(logfile, "Warning: attempted read from physical address "
+ "0x%lx in xen platform mmio space\n", addr);
+ warnings++;
+ }
return 0;
}
static void platform_mmio_write(void *opaque, target_phys_addr_t addr,
uint32_t val)
{
- fprintf(logfile, "Warning: try write to xen platform mmio space\n");
+ static int warnings = 0;
+ if (warnings < 5) {
+ fprintf(logfile, "Warning: attempted write of 0x%x to physical "
+ "address 0x%lx in xen platform mmio space\n", val, addr);
+ warnings++;
+ }
return;
}
diff -r c17bfb091790 -r a07288a84785 tools/ioemu/hw/xenfb.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/hw/xenfb.c Tue Oct 30 15:34:44 2007 -0600
@@ -0,0 +1,1157 @@
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <xenctrl.h>
+#include <xen/io/xenbus.h>
+#include <xen/io/fbif.h>
+#include <xen/io/kbdif.h>
+#include <xen/io/protocols.h>
+#include <stdbool.h>
+#include <xen/event_channel.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <xs.h>
+#include <linux/input.h>
+
+#include "xenfb.h"
+
+// FIXME defend against malicious frontend?
+
+struct xenfb;
+
+struct xenfb_device {
+ const char *devicetype;
+ char nodename[64]; /* backend xenstore dir */
+ char otherend[64]; /* frontend xenstore dir */
+ int otherend_id; /* frontend domid */
+ enum xenbus_state state; /* backend state */
+ void *page; /* shared page */
+ evtchn_port_t port;
+ struct xenfb *xenfb;
+};
+
+struct xenfb {
+ DisplayState *ds; /* QEMU graphical console state */
+ int evt_xch; /* event channel driver handle */
+ int xc; /* hypervisor interface handle */
+ struct xs_handle *xsh; /* xs daemon handle */
+ struct xenfb_device fb, kbd;
+ void *pixels; /* guest framebuffer data */
+ size_t fb_len; /* size of framebuffer */
+ int row_stride; /* width of one row in framebuffer */
+ int depth; /* colour depth of guest framebuffer */
+ int width; /* pixel width of guest framebuffer */
+ int height; /* pixel height of guest framebuffer */
+ int abs_pointer_wanted; /* Whether guest supports absolute pointer */
+ int button_state; /* Last seen pointer button state */
+ char protocol[64]; /* frontend protocol */
+};
+
+/* Functions for frontend/backend state machine*/
+static int xenfb_wait_for_frontend(struct xenfb_device *dev, IOHandler
*handler);
+static int xenfb_wait_for_backend(struct xenfb_device *dev, IOHandler
*handler);
+static void xenfb_backend_created_kbd(void *opaque);
+static void xenfb_backend_created_fb(void *opaque);
+static void xenfb_frontend_initialized_kbd(void *opaque);
+static void xenfb_frontend_initialized_fb(void *opaque);
+static void xenfb_frontend_connected_kbd(void *opaque);
+
+/* Helper functions for checking state of frontend/backend devices */
+static int xenfb_frontend_connected(struct xenfb_device *dev);
+static int xenfb_frontend_initialized(struct xenfb_device *dev);
+static int xenfb_backend_created(struct xenfb_device *dev);
+
+/* Functions which tie the PVFB into the QEMU device model */
+static void xenfb_key_event(void *opaque, int keycode);
+static void xenfb_mouse_event(void *opaque,
+ int dx, int dy, int dz, int button_state);
+static void xenfb_guest_copy(struct xenfb *xenfb, int x, int y, int w, int h);
+static void xenfb_update(void *opaque);
+static void xenfb_invalidate(void *opaque);
+static void xenfb_screen_dump(void *opaque, const char *name);
+static int xenfb_register_console(struct xenfb *xenfb);
+
+/*
+ * Tables to map from scancode to Linux input layer keycode.
+ * Scancodes are hardware-specific. These maps assumes a
+ * standard AT or PS/2 keyboard which is what QEMU feeds us.
+ */
+static const unsigned char atkbd_set2_keycode[512] = {
+
+ 0, 67, 65, 63, 61, 59, 60, 88, 0, 68, 66, 64, 62, 15, 41,117,
+ 0, 56, 42, 93, 29, 16, 2, 0, 0, 0, 44, 31, 30, 17, 3, 0,
+ 0, 46, 45, 32, 18, 5, 4, 95, 0, 57, 47, 33, 20, 19, 6,183,
+ 0, 49, 48, 35, 34, 21, 7,184, 0, 0, 50, 36, 22, 8, 9,185,
+ 0, 51, 37, 23, 24, 11, 10, 0, 0, 52, 53, 38, 39, 25, 12, 0,
+ 0, 89, 40, 0, 26, 13, 0, 0, 58, 54, 28, 27, 0, 43, 0, 85,
+ 0, 86, 91, 90, 92, 0, 14, 94, 0, 79,124, 75, 71,121, 0, 0,
+ 82, 83, 80, 76, 77, 72, 1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 217,100,255, 0, 97,165, 0, 0,156, 0, 0, 0, 0, 0, 0,125,
+ 173,114, 0,113, 0, 0, 0,126,128, 0, 0,140, 0, 0, 0,127,
+ 159, 0,115, 0,164, 0, 0,116,158, 0,150,166, 0, 0, 0,142,
+ 157, 0, 0, 0, 0, 0, 0, 0,155, 0, 98, 0, 0,163, 0, 0,
+ 226, 0, 0, 0, 0, 0, 0, 0, 0,255, 96, 0, 0, 0,143, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0,105,102, 0, 0,112,
+ 110,111,108,112,106,103, 0,119, 0,118,109, 0, 99,104,119, 0,
+
+};
+
+static const unsigned char atkbd_unxlate_table[128] = {
+
+ 0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
+ 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
+ 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
+ 50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88, 5, 6, 4, 12, 3,
+ 11, 2, 10, 1, 9,119,126,108,117,125,123,107,115,116,121,105,
+ 114,122,112,113,127, 96, 97,120, 7, 15, 23, 31, 39, 47, 55, 63,
+ 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
+ 19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
+
+};
+
+static unsigned char scancode2linux[512];
+
+static int xenfb_xs_scanf1(struct xs_handle *xsh,
+ const char *dir, const char *node,
+ const char *fmt, void *dest)
+{
+ char buf[1024];
+ char *p;
+ int ret;
+
+ if (snprintf(buf, sizeof(buf), "%s/%s", dir, node) >= sizeof(buf)) {
+ errno = ENOENT;
+ return -1;
+ }
+ p = xs_read(xsh, XBT_NULL, buf, NULL);
+ if (!p) {
+ errno = ENOENT;
+ return -1;
+ }
+ ret = sscanf(p, fmt, dest);
+ free(p);
+ if (ret != 1) {
+ errno = EDOM;
+ return -1;
+ }
+ return ret;
+}
+
+static int xenfb_xs_printf(struct xs_handle *xsh,
+ const char *dir, const char *node, char *fmt, ...)
+{
+ va_list ap;
+ char key[1024];
+ char val[1024];
+ int n;
+
+ if (snprintf(key, sizeof(key), "%s/%s", dir, node) >= sizeof(key)) {
+ errno = ENOENT;
+ return -1;
+ }
+
+ va_start(ap, fmt);
+ n = vsnprintf(val, sizeof(val), fmt, ap);
+ va_end(ap);
+ if (n >= sizeof(val)) {
+ errno = ENOSPC; /* close enough */
+ return -1;
+ }
+
+ if (!xs_write(xsh, XBT_NULL, key, val, n))
+ return -1;
+ return 0;
+}
+
+static void xenfb_device_init(struct xenfb_device *dev,
+ const char *type,
+ struct xenfb *xenfb)
+{
+ dev->devicetype = type;
+ dev->otherend_id = -1;
+ dev->port = -1;
+ dev->xenfb = xenfb;
+}
+
+static char *xenfb_path_in_dom(struct xs_handle *xsh,
+ char *buf, size_t size,
+ unsigned domid, const char *fmt, ...)
+{
+ va_list ap;
+ char *domp = xs_get_domain_path(xsh, domid);
+ int n;
+
+ if (domp == NULL)
+ return NULL;
+
+ n = snprintf(buf, size, "%s/", domp);
+ free(domp);
+ if (n >= size)
+ return NULL;
+
+ va_start(ap, fmt);
+ n += vsnprintf(buf + n, size - n, fmt, ap);
+ va_end(ap);
+ if (n >= size)
+ return NULL;
+
+ return buf;
+}
+
+static int xenfb_device_set_domain(struct xenfb_device *dev, int domid)
+{
+ dev->otherend_id = domid;
+
+ if (!xenfb_path_in_dom(dev->xenfb->xsh,
+ dev->otherend, sizeof(dev->otherend),
+ domid, "device/%s/0", dev->devicetype)) {
+ errno = ENOENT;
+ return -1;
+ }
+ if (!xenfb_path_in_dom(dev->xenfb->xsh,
+ dev->nodename, sizeof(dev->nodename),
+ 0, "backend/%s/%d/0", dev->devicetype, domid)) {
+ errno = ENOENT;
+ return -1;
+ }
+
+ return 0;
+}
+
+struct xenfb *xenfb_new(int domid, DisplayState *ds)
+{
+ struct xenfb *xenfb = qemu_malloc(sizeof(struct xenfb));
+ int serrno;
+ int i;
+
+ if (xenfb == NULL)
+ return NULL;
+
+ /* Prepare scancode mapping table */
+ for (i = 0; i < 128; i++) {
+ scancode2linux[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
+ scancode2linux[i | 0x80] =
+ atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
+ }
+
+ memset(xenfb, 0, sizeof(*xenfb));
+ xenfb->evt_xch = xenfb->xc = -1;
+ xenfb_device_init(&xenfb->fb, "vfb", xenfb);
+ xenfb_device_init(&xenfb->kbd, "vkbd", xenfb);
+
+ xenfb->evt_xch = xc_evtchn_open();
+ if (xenfb->evt_xch == -1)
+ goto fail;
+
+ xenfb->xc = xc_interface_open();
+ if (xenfb->xc == -1)
+ goto fail;
+
+ xenfb->xsh = xs_daemon_open();
+ if (!xenfb->xsh)
+ goto fail;
+
+ xenfb->ds = ds;
+ xenfb_device_set_domain(&xenfb->fb, domid);
+ xenfb_device_set_domain(&xenfb->kbd, domid);
+
+ fprintf(stderr, "FB: Waiting for KBD backend creation\n");
+ xenfb_wait_for_backend(&xenfb->kbd, xenfb_backend_created_kbd);
+
+ return xenfb;
+
+ fail:
+ serrno = errno;
+ xenfb_shutdown(xenfb);
+ errno = serrno;
+ return NULL;
+}
+
+
+static enum xenbus_state xenfb_read_state(struct xs_handle *xsh,
+ const char *dir)
+{
+ int ret, state;
+
+ ret = xenfb_xs_scanf1(xsh, dir, "state", "%d", &state);
+ if (ret < 0)
+ return XenbusStateUnknown;
+
+ if ((unsigned)state > XenbusStateClosed)
+ state = XenbusStateUnknown;
+ return state;
+}
+
+static int xenfb_switch_state(struct xenfb_device *dev,
+ enum xenbus_state state)
+{
+ struct xs_handle *xsh = dev->xenfb->xsh;
+
+ if (xenfb_xs_printf(xsh, dev->nodename, "state", "%d", state) < 0)
+ return -1;
+ dev->state = state;
+ return 0;
+}
+
+
+static int xenfb_hotplug(struct xenfb_device *dev)
+{
+ if (xenfb_xs_printf(dev->xenfb->xsh, dev->nodename,
+ "hotplug-status", "connected"))
+ return -1;
+ return 0;
+}
+
+static void xenfb_copy_mfns(int mode, int count, unsigned long *dst, void *src)
+{
+ uint32_t *src32 = src;
+ uint64_t *src64 = src;
+ int i;
+
+ for (i = 0; i < count; i++)
+ dst[i] = (mode == 32) ? src32[i] : src64[i];
+}
+
+static int xenfb_map_fb(struct xenfb *xenfb, int domid)
+{
+ struct xenfb_page *page = xenfb->fb.page;
+ int n_fbmfns;
+ int n_fbdirs;
+ unsigned long *pgmfns = NULL;
+ unsigned long *fbmfns = NULL;
+ void *map, *pd;
+ int mode, ret = -1;
+
+ /* default to native */
+ pd = page->pd;
+ mode = sizeof(unsigned long) * 8;
+
+ if (0 == strlen(xenfb->protocol)) {
+ /*
+ * Undefined protocol, some guesswork needed.
+ *
+ * Old frontends which don't set the protocol use
+ * one page directory only, thus pd[1] must be zero.
+ * pd[1] of the 32bit struct layout and the lower
+ * 32 bits of pd[0] of the 64bit struct layout have
+ * the same location, so we can check that ...
+ */
+ uint32_t *ptr32 = NULL;
+ uint32_t *ptr64 = NULL;
+#if defined(__i386__)
+ ptr32 = (void*)page->pd;
+ ptr64 = ((void*)page->pd) + 4;
+#elif defined(__x86_64__)
+ ptr32 = ((void*)page->pd) - 4;
+ ptr64 = (void*)page->pd;
+#endif
+ if (ptr32) {
+ if (0 == ptr32[1]) {
+ mode = 32;
+ pd = ptr32;
+ } else {
+ mode = 64;
+ pd = ptr64;
+ }
+ }
+#if defined(__x86_64__)
+ } else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_32)) {
+ /* 64bit dom0, 32bit domU */
+ mode = 32;
+ pd = ((void*)page->pd) - 4;
+#elif defined(__i386__)
+ } else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_64)) {
+ /* 32bit dom0, 64bit domU */
+ mode = 64;
+ pd = ((void*)page->pd) + 4;
+#endif
+ }
+
+ n_fbmfns = (xenfb->fb_len + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
+ n_fbdirs = n_fbmfns * mode / 8;
+ n_fbdirs = (n_fbdirs + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
+
+ pgmfns = malloc(sizeof(unsigned long) * n_fbdirs);
+ fbmfns = malloc(sizeof(unsigned long) * n_fbmfns);
+ if (!pgmfns || !fbmfns)
+ goto out;
+
+ xenfb_copy_mfns(mode, n_fbdirs, pgmfns, pd);
+ map = xc_map_foreign_pages(xenfb->xc, domid,
+ PROT_READ, pgmfns, n_fbdirs);
+ if (map == NULL)
+ goto out;
+ xenfb_copy_mfns(mode, n_fbmfns, fbmfns, map);
+ munmap(map, n_fbdirs * XC_PAGE_SIZE);
+
+ xenfb->pixels = xc_map_foreign_pages(xenfb->xc, domid,
+ PROT_READ | PROT_WRITE, fbmfns, n_fbmfns);
+ if (xenfb->pixels == NULL)
+ goto out;
+
+ ret = 0; /* all is fine */
+
+ out:
+ if (pgmfns)
+ free(pgmfns);
+ if (fbmfns)
+ free(fbmfns);
+ return ret;
+}
+
+static int xenfb_bind(struct xenfb_device *dev)
+{
+ struct xenfb *xenfb = dev->xenfb;
+ unsigned long mfn;
+ evtchn_port_t evtchn;
+
+ if (xenfb_xs_scanf1(xenfb->xsh, dev->otherend, "page-ref", "%lu",
+ &mfn) < 0)
+ return -1;
+ if (xenfb_xs_scanf1(xenfb->xsh, dev->otherend, "event-channel", "%u",
+ &evtchn) < 0)
+ return -1;
+
+ dev->port = xc_evtchn_bind_interdomain(xenfb->evt_xch,
+ dev->otherend_id, evtchn);
+ if (dev->port == -1)
+ return -1;
+
+ dev->page = xc_map_foreign_range(xenfb->xc, dev->otherend_id,
+ XC_PAGE_SIZE, PROT_READ | PROT_WRITE, mfn);
+ if (dev->page == NULL)
+ return -1;
+
+ return 0;
+}
+
+static void xenfb_unbind(struct xenfb_device *dev)
+{
+ if (dev->page) {
+ munmap(dev->page, XC_PAGE_SIZE);
+ dev->page = NULL;
+ }
+ if (dev->port >= 0) {
+ xc_evtchn_unbind(dev->xenfb->evt_xch, dev->port);
+ dev->port = -1;
+ }
+}
+
+
+static void xenfb_detach_dom(struct xenfb *xenfb)
+{
+ xenfb_unbind(&xenfb->fb);
+ xenfb_unbind(&xenfb->kbd);
+ if (xenfb->pixels) {
+ munmap(xenfb->pixels, xenfb->fb_len);
+ xenfb->pixels = NULL;
+ }
+}
+
+/* Remove the backend area in xenbus since the framebuffer really is
+ going away. */
+void xenfb_shutdown(struct xenfb *xenfb)
+{
+ fprintf(stderr, "FB: Shutting down backend\n");
+ xs_rm(xenfb->xsh, XBT_NULL, xenfb->fb.nodename);
+ xs_rm(xenfb->xsh, XBT_NULL, xenfb->kbd.nodename);
+
+ xenfb_detach_dom(xenfb);
+ if (xenfb->xc >= 0)
+ xc_interface_close(xenfb->xc);
+ if (xenfb->evt_xch >= 0)
+ xc_evtchn_close(xenfb->evt_xch);
+ if (xenfb->xsh)
+ xs_daemon_close(xenfb->xsh);
+ free(xenfb);
+}
+
+
+static void xenfb_on_fb_event(struct xenfb *xenfb)
+{
+ uint32_t prod, cons;
+ struct xenfb_page *page = xenfb->fb.page;
+
+ prod = page->out_prod;
+ if (prod == page->out_cons)
+ return;
+ 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);
+
+ switch (event->type) {
+ case XENFB_TYPE_UPDATE:
+ xenfb_guest_copy(xenfb,
+ event->update.x, event->update.y,
+ event->update.width,
event->update.height);
+ break;
+ }
+ }
+ mb(); /* ensure we're done with ring contents */
+ page->out_cons = cons;
+ xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port);
+}
+
+static void xenfb_on_kbd_event(struct xenfb *xenfb)
+{
+ struct xenkbd_page *page = xenfb->kbd.page;
+
+ /* We don't understand any keyboard events, so just ignore them. */
+ if (page->out_prod == page->out_cons)
+ return;
+ page->out_cons = page->out_prod;
+ xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port);
+}
+
+static int xenfb_on_state_change(struct xenfb_device *dev)
+{
+ enum xenbus_state state;
+
+ state = xenfb_read_state(dev->xenfb->xsh, dev->otherend);
+
+ switch (state) {
+ case XenbusStateUnknown:
+ /* There was an error reading the frontend state. The
+ domain has probably gone away; in any case, there's
+ not much point in us continuing. */
+ return -1;
+ case XenbusStateInitialising:
+ case XenbusStateInitWait:
+ case XenbusStateInitialised:
+ case XenbusStateConnected:
+ break;
+ case XenbusStateClosing:
+ xenfb_unbind(dev);
+ xenfb_switch_state(dev, state);
+ break;
+ case XenbusStateClosed:
+ xenfb_switch_state(dev, state);
+ }
+ return 0;
+}
+
+/* Send an event to the keyboard frontend driver */
+static int xenfb_kbd_event(struct xenfb *xenfb,
+ union xenkbd_in_event *event)
+{
+ uint32_t prod;
+ struct xenkbd_page *page = xenfb->kbd.page;
+
+ if (xenfb->kbd.state != XenbusStateConnected)
+ return 0;
+
+ prod = page->in_prod;
+ if (prod - page->in_cons == XENKBD_IN_RING_LEN) {
+ errno = EAGAIN;
+ return -1;
+ }
+
+ mb(); /* ensure ring space available */
+ XENKBD_IN_RING_REF(page, prod) = *event;
+ wmb(); /* ensure ring contents visible */
+ page->in_prod = prod + 1;
+ return xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port);
+}
+
+/* Send a keyboard (or mouse button) event */
+static int xenfb_send_key(struct xenfb *xenfb, bool down, int keycode)
+{
+ union xenkbd_in_event event;
+
+ memset(&event, 0, XENKBD_IN_EVENT_SIZE);
+ event.type = XENKBD_TYPE_KEY;
+ event.key.pressed = down ? 1 : 0;
+ event.key.keycode = keycode;
+
+ return xenfb_kbd_event(xenfb, &event);
+}
+
+/* Send a relative mouse movement event */
+static int xenfb_send_motion(struct xenfb *xenfb, int rel_x, int rel_y)
+{
+ union xenkbd_in_event event;
+
+ memset(&event, 0, XENKBD_IN_EVENT_SIZE);
+ event.type = XENKBD_TYPE_MOTION;
+ event.motion.rel_x = rel_x;
+ event.motion.rel_y = rel_y;
+
+ return xenfb_kbd_event(xenfb, &event);
+}
+
+/* Send an absolute mouse movement event */
+static int xenfb_send_position(struct xenfb *xenfb, int abs_x, int abs_y)
+{
+ union xenkbd_in_event event;
+
+ memset(&event, 0, XENKBD_IN_EVENT_SIZE);
+ event.type = XENKBD_TYPE_POS;
+ event.pos.abs_x = abs_x;
+ event.pos.abs_y = abs_y;
+
+ return xenfb_kbd_event(xenfb, &event);
+}
+
+/* Process events from the frontend event channel */
+static void xenfb_dispatch_channel(void *opaque)
+{
+ struct xenfb *xenfb = (struct xenfb *)opaque;
+ evtchn_port_t port;
+ port = xc_evtchn_pending(xenfb->evt_xch);
+ if (port == -1) {
+ xenfb_shutdown(xenfb);
+ exit(1);
+ }
+
+ if (port == xenfb->fb.port)
+ xenfb_on_fb_event(xenfb);
+ else if (port == xenfb->kbd.port)
+ xenfb_on_kbd_event(xenfb);
+
+ if (xc_evtchn_unmask(xenfb->evt_xch, port) == -1) {
+ xenfb_shutdown(xenfb);
+ exit(1);
+ }
+}
+
+/* Process ongoing events from the frontend devices */
+static void xenfb_dispatch_store(void *opaque)
+{
+ struct xenfb *xenfb = (struct xenfb *)opaque;
+ unsigned dummy;
+ char **vec;
+ int r;
+
+ vec = xs_read_watch(xenfb->xsh, &dummy);
+ free(vec);
+ r = xenfb_on_state_change(&xenfb->fb);
+ if (r == 0)
+ r = xenfb_on_state_change(&xenfb->kbd);
+ if (r < 0) {
+ xenfb_shutdown(xenfb);
+ exit(1);
+ }
+}
+
+
+/****************************************************************
+ *
+ * Functions for processing frontend config
+ *
+ ****************************************************************/
+
+
+/* Process the frontend framebuffer config */
+static int xenfb_read_frontend_fb_config(struct xenfb *xenfb) {
+ struct xenfb_page *fb_page;
+ int val;
+
+ if (xenfb_xs_scanf1(xenfb->xsh, xenfb->fb.otherend, "feature-update",
+ "%d", &val) < 0)
+ val = 0;
+ if (!val) {
+ fprintf(stderr, "feature-update not supported\n");
+ errno = ENOTSUP;
+ return -1;
+ }
+ if (xenfb_xs_scanf1(xenfb->xsh, xenfb->fb.otherend, "protocol", "%63s",
+ xenfb->protocol) < 0)
+ xenfb->protocol[0] = '\0';
+ xenfb_xs_printf(xenfb->xsh, xenfb->fb.nodename, "request-update", "1");
+
+ /* TODO check for permitted ranges */
+ fb_page = xenfb->fb.page;
+ xenfb->depth = fb_page->depth;
+ xenfb->width = fb_page->width;
+ xenfb->height = fb_page->height;
+ /* TODO check for consistency with the above */
+ xenfb->fb_len = fb_page->mem_length;
+ xenfb->row_stride = fb_page->line_length;
+ fprintf(stderr, "Framebuffer depth %d width %d height %d line %d\n",
+ fb_page->depth, fb_page->width, fb_page->height,
fb_page->line_length);
+ if (xenfb_map_fb(xenfb, xenfb->fb.otherend_id) < 0)
+ return -1;
+
+ if (xenfb_switch_state(&xenfb->fb, XenbusStateConnected))
+ return -1;
+ if (xenfb_switch_state(&xenfb->kbd, XenbusStateConnected))
+ return -1;
+
+ return 0;
+}
+
+/* Process the frontend keyboard config */
+static int xenfb_read_frontend_kbd_config(struct xenfb *xenfb)
+{
+ int val;
+
+ if (xenfb_xs_scanf1(xenfb->xsh, xenfb->kbd.otherend,
"request-abs-pointer",
+ "%d", &val) < 0)
+ val = 0;
+ xenfb->abs_pointer_wanted = val;
+
+ return 0;
+}
+
+
+/****************************************************************
+ *
+ * Functions for frontend/backend state machine
+ *
+ ****************************************************************/
+
+/* Register a watch against a frontend device, and setup
+ * QEMU event loop to poll the xenstore FD for notification */
+static int xenfb_wait_for_frontend(struct xenfb_device *dev, IOHandler
*handler)
+{
+ fprintf(stderr, "Doing frontend watch on %s\n", dev->otherend);
+ if (!xs_watch(dev->xenfb->xsh, dev->otherend, "")) {
+ fprintf(stderr, "Watch for dev failed\n");
+ return -1;
+ }
+
+ if (qemu_set_fd_handler2(xs_fileno(dev->xenfb->xsh), NULL, handler,
NULL, dev) < 0)
+ return -1;
+
+ return 0;
+}
+
+/* Register a watch against a backend device, and setup
+ * QEMU event loop to poll the xenstore FD for notification */
+static int xenfb_wait_for_backend(struct xenfb_device *dev, IOHandler *handler)
+{
+ fprintf(stderr, "Doing backend watch on %s\n", dev->nodename);
+ if (!xs_watch(dev->xenfb->xsh, dev->nodename, "")) {
+ fprintf(stderr, "Watch for dev failed\n");
+ return -1;
+ }
+
+ if (qemu_set_fd_handler2(xs_fileno(dev->xenfb->xsh), NULL, handler,
NULL, dev) < 0)
+ return -1;
+
+ return 0;
+}
+
+/* Callback invoked while waiting for KBD backend to change
+ * to the created state */
+static void xenfb_backend_created_kbd(void *opaque)
+{
+ struct xenfb_device *dev = (struct xenfb_device *)opaque;
+ int ret = xenfb_backend_created(dev);
+ if (ret < 0) {
+ xenfb_shutdown(dev->xenfb);
+ exit(1);
+ }
+ if (ret)
+ return; /* Still waiting */
+
+ if (xenfb_xs_printf(dev->xenfb->xsh, dev->nodename,
"feature-abs-pointer", "1")) {
+ xenfb_shutdown(dev->xenfb);
+ exit(1);
+ }
+
+ fprintf(stderr, "FB: Waiting for FB backend creation\n");
+ xenfb_wait_for_backend(&dev->xenfb->fb, xenfb_backend_created_fb);
+}
+
+/* Callback invoked while waiting for FB backend to change
+ * to the created state */
+static void xenfb_backend_created_fb(void *opaque)
+{
+ struct xenfb_device *dev = (struct xenfb_device *)opaque;
+ int ret = xenfb_backend_created(dev);
+ if (ret < 0) {
+ xenfb_shutdown(dev->xenfb);
+ exit(1);
+ }
+ if (ret)
+ return; /* Still waiting */
+
+ fprintf(stderr, "FB: Waiting for KBD frontend initialization\n");
+ xenfb_wait_for_frontend(&dev->xenfb->kbd,
xenfb_frontend_initialized_kbd);
+}
+
+/* Callback invoked while waiting for KBD frontend to change
+ * to the initialized state */
+static void xenfb_frontend_initialized_kbd(void *opaque)
+{
+ struct xenfb_device *dev = (struct xenfb_device *)opaque;
+ int ret = xenfb_frontend_initialized(dev);
+ if (ret < 0) {
+ xenfb_shutdown(dev->xenfb);
+ exit(1);
+ }
+ if (ret)
+ return; /* Still waiting */
+
+
+ fprintf(stderr, "FB: Waiting for FB frontend initialization\n");
+ xenfb_wait_for_frontend(&dev->xenfb->fb, xenfb_frontend_initialized_fb);
+}
+
+/* Callback invoked while waiting for FB frontend to change
+ * to the initialized state */
+static void xenfb_frontend_initialized_fb(void *opaque)
+{
+ struct xenfb_device *dev = (struct xenfb_device *)opaque;
+ int ret = xenfb_frontend_initialized(dev);
+ if (ret < 0) {
+ xenfb_shutdown(dev->xenfb);
+ exit(1);
+ }
+ if (ret)
+ return; /* Still waiting */
+
+
+ if (xenfb_read_frontend_fb_config(dev->xenfb)) {
+ xenfb_shutdown(dev->xenfb);
+ exit(1);
+ }
+
+ fprintf(stderr, "FB: Waiting for KBD frontend connection\n");
+ xenfb_wait_for_frontend(&dev->xenfb->kbd, xenfb_frontend_connected_kbd);
+}
+
+/* Callback invoked while waiting for KBD frontend to change
+ * to the connected state */
+static void xenfb_frontend_connected_kbd(void *opaque)
+{
+ struct xenfb_device *dev = (struct xenfb_device *)opaque;
+ int ret = xenfb_frontend_connected(dev);
+ if (ret < 0) {
+ xenfb_shutdown(dev->xenfb);
+ exit(1);
+ }
+ if (ret)
+ return; /* Still waiting */
+
+ if (xenfb_read_frontend_kbd_config(dev->xenfb) < 0) {
+ xenfb_shutdown(dev->xenfb);
+ exit(1);
+ }
+
+ xenfb_register_console(dev->xenfb);
+}
+
+
+/****************************************************************
+ *
+ * Helper functions for checking state of frontend/backend devices
+ *
+ ****************************************************************/
+
+/* Helper to determine if a frontend device is in Connected state */
+static int xenfb_frontend_connected(struct xenfb_device *dev)
+{
+ unsigned int state;
+ unsigned int dummy;
+ char **vec;
+ vec = xs_read_watch(dev->xenfb->xsh, &dummy);
+ if (!vec)
+ return -1;
+ free(vec);
+
+ state = xenfb_read_state(dev->xenfb->xsh, dev->otherend);
+ if (!((1 <<state) & ((1 << XenbusStateUnknown) |
+ (1 << XenbusStateConnected)))) {
+ fprintf(stderr, "FB: Carry on waiting\n");
+ return 1;
+ }
+
+ /* Don't unwatch frontend - we need to detect shutdown */
+ /*xs_unwatch(dev->xenfb->xsh, dev->otherend, "");*/
+
+ switch (state) {
+ case XenbusStateConnected:
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+
+/* Helper to determine if a frontend device is in Initialized state */
+static int xenfb_frontend_initialized(struct xenfb_device *dev)
+{
+ unsigned int state;
+ unsigned int dummy;
+ char **vec;
+ vec = xs_read_watch(dev->xenfb->xsh, &dummy);
+ if (!vec)
+ return -1;
+ free(vec);
+
+ state = xenfb_read_state(dev->xenfb->xsh, dev->otherend);
+
+ if (!((1 << state) & ((1 << XenbusStateUnknown)
+ | (1 << XenbusStateInitialised)
+#if 1 /* TODO fudging state to permit restarting; to be removed */
+ | (1 << XenbusStateConnected)
+#endif
+ ))) {
+ fprintf(stderr, "FB: Carry on waiting\n");
+ return 1;
+ }
+
+ xs_unwatch(dev->xenfb->xsh, dev->otherend, "");
+
+ switch (state) {
+#if 1
+ case XenbusStateConnected:
+ printf("Fudging state to %d\n", XenbusStateInitialised); /*
FIXME */
+#endif
+ case XenbusStateInitialised:
+ break;
+ default:
+ return -1;
+ }
+
+ if (xenfb_bind(dev) < 0)
+ return -1;
+
+ return 0;
+}
+
+/* Helper to determine if a backend device is in Created state */
+static int xenfb_backend_created(struct xenfb_device *dev)
+{
+ unsigned int state;
+ unsigned int dummy;
+ char **vec;
+ vec = xs_read_watch(dev->xenfb->xsh, &dummy);
+ if (!vec)
+ return -1;
+ free(vec);
+
+ state = xenfb_read_state(dev->xenfb->xsh, dev->nodename);
+
+ if (!((1 <<state) & ((1 << XenbusStateUnknown)
+ | (1 << XenbusStateInitialising)
+ | (1 << XenbusStateClosed)
+#if 1 /* TODO fudging state to permit restarting; to be removed */
+ | (1 << XenbusStateInitWait)
+ | (1 << XenbusStateConnected)
+ | (1 << XenbusStateClosing)
+#endif
+ ))) {
+ fprintf(stderr, "FB: Carry on waiting\n");
+ return 1;
+ }
+
+ xs_unwatch(dev->xenfb->xsh, dev->nodename, "");
+
+ switch (state) {
+#if 1
+ case XenbusStateInitWait:
+ case XenbusStateConnected:
+ printf("Fudging state to %d\n", XenbusStateInitialising); /*
FIXME */
+#endif
+ case XenbusStateInitialising:
+ case XenbusStateClosing:
+ case XenbusStateClosed:
+ break;
+ default:
+ fprintf(stderr, "Wrong state %d\n", state);
+ return -1;
+ }
+ xenfb_switch_state(dev, XenbusStateInitWait);
+ if (xenfb_hotplug(dev) < 0)
+ return -1;
+
+ return 0;
+}
+
+
+/****************************************************************
+ *
+ * QEMU device model integration functions
+ *
+ ****************************************************************/
+
+/*
+ * Send a key event from the client to the guest OS
+ * QEMU gives us a raw scancode from an AT / PS/2 style keyboard.
+ * We have to turn this into a Linux Input layer keycode.
+ *
+ * Extra complexity from the fact that with extended scancodes
+ * (like those produced by arrow keys) this method gets called
+ * twice, but we only want to send a single event. So we have to
+ * track the '0xe0' scancode state & collapse the extended keys
+ * as needed.
+ *
+ * Wish we could just send scancodes straight to the guest which
+ * already has code for dealing with this...
+ */
+static void xenfb_key_event(void *opaque, int scancode)
+{
+ static int extended = 0;
+ int down = 1;
+ if (scancode == 0xe0) {
+ extended = 1;
+ return;
+ } else if (scancode & 0x80) {
+ scancode &= 0x7f;
+ down = 0;
+ }
+ if (extended) {
+ scancode |= 0x80;
+ extended = 0;
+ }
+ xenfb_send_key(opaque, down, scancode2linux[scancode]);
+}
+
+/*
+ * Send a mouse event from the client to the guest OS
+ *
+ * The QEMU mouse can be in either relative, or absolute mode.
+ * Movement is sent separately from button state, which has to
+ * be encoded as virtual key events. We also don't actually get
+ * given any button up/down events, so have to track changes in
+ * the button state.
+ */
+static void xenfb_mouse_event(void *opaque,
+ int dx, int dy, int dz, int button_state)
+{
+ int i;
+ struct xenfb *xenfb = opaque;
+ if (xenfb->abs_pointer_wanted)
+ xenfb_send_position(xenfb,
+ dx * xenfb->ds->width / 0x7fff,
+ dy * xenfb->ds->height / 0x7fff);
+ else
+ xenfb_send_motion(xenfb, dx, dy);
+
+ for (i = 0 ; i < 8 ; i++) {
+ int lastDown = xenfb->button_state & (1 << i);
+ int down = button_state & (1 << i);
+ if (down == lastDown)
+ continue;
+
+ if (xenfb_send_key(xenfb, down, BTN_LEFT+i) < 0)
+ return;
+ }
+ xenfb->button_state = button_state;
+}
+
+/* A convenient function for munging pixels between different depths */
+#define BLT(SRC_T,DST_T,RLS,GLS,BLS,RRS,GRS,BRS,RM,GM,BM) \
+ for (line = y ; line < h ; line++) { \
+ SRC_T *src = (SRC_T *)(xenfb->pixels \
+ + (line * xenfb->row_stride) \
+ + (x * xenfb->depth / 8)); \
+ DST_T *dst = (DST_T *)(xenfb->ds->data
\
+ + (line * xenfb->ds->linesize)
\
+ + (x * xenfb->ds->depth / 8));
\
+ int col; \
+ for (col = x ; col < w ; col++) { \
+ *dst = (((*src >> RRS) & RM) << RLS) | \
+ (((*src >> GRS) & GM) << GLS) | \
+ (((*src >> GRS) & BM) << BLS); \
+ src++; \
+ dst++; \
+ } \
+ }
+
+
+/* This copies data from the guest framebuffer region, into QEMU's copy
+ * NB. QEMU's copy is stored in the pixel format of a) the local X
+ * server (SDL case) or b) the current VNC client pixel format.
+ * When shifting between colour depths we preserve the MSB.
+ */
+static void xenfb_guest_copy(struct xenfb *xenfb, int x, int y, int w, int h)
+{
+ int line;
+
+ if (xenfb->depth == xenfb->ds->depth) { /* Perfect match can use fast path
*/
+ for (line = y ; line < (y+h) ; line++) {
+ memcpy(xenfb->ds->data + (line * xenfb->ds->linesize) + (x *
xenfb->ds->depth / 8),
+ xenfb->pixels + (line * xenfb->row_stride) + (x *
xenfb->depth / 8),
+ w * xenfb->depth / 8);
+ }
+ } else { /* Mismatch requires slow pixel munging */
+ if (xenfb->depth == 8) {
+ /* 8 bit source == r:3 g:3 b:2 */
+ if (xenfb->ds->depth == 16) {
+ BLT(uint8_t, uint16_t, 5, 2, 0, 11, 5, 0, 7, 7, 3);
+ } else if (xenfb->ds->depth == 32) {
+ BLT(uint8_t, uint32_t, 5, 2, 0, 16, 8, 0, 7, 7, 3);
+ }
+ } else if (xenfb->depth == 16) {
+ /* 16 bit source == r:5 g:6 b:5 */
+ if (xenfb->ds->depth == 8) {
+ BLT(uint16_t, uint8_t, 11, 5, 0, 5, 2, 0, 31, 63, 31);
+ } else if (xenfb->ds->depth == 32) {
+ BLT(uint16_t, uint32_t, 11, 5, 0, 16, 8, 0, 31, 63, 31);
+ }
+ } else if (xenfb->depth == 32) {
+ /* 32 bit source == r:8 g:8 b:8 (padding:8) */
+ if (xenfb->ds->depth == 8) {
+ BLT(uint32_t, uint8_t, 16, 8, 0, 5, 2, 0, 255, 255,
255);
+ } else if (xenfb->ds->depth == 16) {
+ BLT(uint32_t, uint16_t, 16, 8, 0, 11, 5, 0, 255, 255,
255);
+ }
+ }
+ }
+ dpy_update(xenfb->ds, x, y, w, h);
+}
+
+/* QEMU display state changed, so refresh the framebuffer copy */
+/* XXX - can we optimize this, or the next func at all ? */
+static void xenfb_update(void *opaque)
+{
+ struct xenfb *xenfb = opaque;
+ xenfb_guest_copy(xenfb, 0, 0, xenfb->width, xenfb->height);
+}
+
+/* QEMU display state changed, so refresh the framebuffer copy */
+static void xenfb_invalidate(void *opaque)
+{
+ struct xenfb *xenfb = opaque;
+ xenfb_guest_copy(xenfb, 0, 0, xenfb->width, xenfb->height);
+}
+
+/* Screen dump is not used in Xen, so no need to impl this....yet */
+static void xenfb_screen_dump(void *opaque, const char *name) { }
+
+
+/* Register a QEMU graphical console, and key/mouse handler,
+ * connecting up their events to the frontend */
+static int xenfb_register_console(struct xenfb *xenfb) {
+ /* Register our keyboard & mouse handlers */
+ qemu_add_kbd_event_handler(xenfb_key_event, xenfb);
+ qemu_add_mouse_event_handler(xenfb_mouse_event, xenfb,
+ xenfb->abs_pointer_wanted,
+ "Xen PVFB Mouse");
+
+ /* Tell QEMU to allocate a graphical console */
+ graphic_console_init(xenfb->ds,
+ xenfb_update,
+ xenfb_invalidate,
+ xenfb_screen_dump,
+ xenfb);
+ dpy_resize(xenfb->ds, xenfb->width, xenfb->height);
+
+ if (qemu_set_fd_handler2(xenfb->evt_xch, NULL, xenfb_dispatch_channel,
NULL, xenfb) < 0)
+ return -1;
+ if (qemu_set_fd_handler2(xs_fileno(xenfb->xsh), NULL,
xenfb_dispatch_store, NULL, xenfb) < 0)
+ return -1;
+
+ fprintf(stderr, "Xen Framebuffer registered\n");
+ return 0;
+}
+
+/*
+ * Local variables:
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r c17bfb091790 -r a07288a84785 tools/ioemu/hw/xenfb.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ioemu/hw/xenfb.h Tue Oct 30 15:34:44 2007 -0600
@@ -0,0 +1,13 @@
+#ifndef _XENFB_H_
+#define _XENFB_H_
+
+#include "vl.h"
+#include <stdbool.h>
+#include <sys/types.h>
+
+struct xenfb;
+
+struct xenfb *xenfb_new(int domid, DisplayState *ds);
+void xenfb_shutdown(struct xenfb *xenfb);
+
+#endif
diff -r c17bfb091790 -r a07288a84785 tools/ioemu/monitor.c
--- a/tools/ioemu/monitor.c Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/ioemu/monitor.c Tue Oct 30 15:34:44 2007 -0600
@@ -374,7 +374,7 @@ void do_eject(int force, const char *fil
eject_device(bs, force);
}
-void do_change(const char *device, const char *filename)
+static void do_change_block(const char *device, const char *filename)
{
BlockDriverState *bs;
int i;
@@ -396,6 +396,30 @@ void do_change(const char *device, const
break;
term_printf("invalid password\n");
}
+ }
+}
+
+static void do_change_vnc(const char *target)
+{
+ if (strcmp(target, "passwd") == 0 ||
+ strcmp(target, "password") == 0) {
+ char password[9];
+ monitor_readline("Password: ", 1, password, sizeof(password)-1);
+ password[sizeof(password)-1] = '\0';
+ if (vnc_display_password(NULL, password) < 0)
+ term_printf("could not set VNC server password\n");
+ } else {
+ if (vnc_display_open(NULL, target, 0) < 0)
+ term_printf("could not start VNC server on %s\n", target);
+ }
+}
+
+void do_change(const char *device, const char *target)
+{
+ if (strcmp(device, "vnc") == 0) {
+ do_change_vnc(target);
+ } else {
+ do_change_block(device, target);
}
}
diff -r c17bfb091790 -r a07288a84785 tools/ioemu/target-i386-dm/helper2.c
--- a/tools/ioemu/target-i386-dm/helper2.c Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/ioemu/target-i386-dm/helper2.c Tue Oct 30 15:34:44 2007 -0600
@@ -478,6 +478,7 @@ void cpu_ioreq_timeoffset(CPUState *env,
time_offset += (ulong)req->data;
+ fprintf(logfile, "Time offset set %ld, added offset %ld\n", time_offset,
req->data);
sprintf(b, "%ld", time_offset);
xenstore_vm_write(domid, "rtc/timeoffset", b);
}
@@ -538,20 +539,39 @@ void __handle_ioreq(CPUState *env, ioreq
void __handle_buffered_iopage(CPUState *env)
{
- ioreq_t *req = NULL;
+ buf_ioreq_t *buf_req = NULL;
+ ioreq_t req;
+ int qw = 0;
if (!buffered_io_page)
return;
while (buffered_io_page->read_pointer !=
buffered_io_page->write_pointer) {
- req = &buffered_io_page->ioreq[buffered_io_page->read_pointer %
+ memset(&req, 0, sizeof(req));
+ buf_req = &buffered_io_page->buf_ioreq[buffered_io_page->read_pointer %
IOREQ_BUFFER_SLOT_NUM];
-
- __handle_ioreq(env, req);
+ req.size = 1UL << buf_req->size;
+ req.count = 1;
+ req.data = buf_req->data;
+ req.state = STATE_IOREQ_READY;
+ req.dir = buf_req->dir;
+ req.type = buf_req->type;
+ qw = req.size == 8;
+ if (qw) {
+ req.data |= ((uint64_t)buf_req->addr) << 16;
+ buf_req =
&buffered_io_page->buf_ioreq[(buffered_io_page->read_pointer+1) %
+ IOREQ_BUFFER_SLOT_NUM];
+ req.data |= ((uint64_t)buf_req->data) << 32;
+ req.data |= ((uint64_t)buf_req->addr) << 48;
+ }
+ else
+ req.addr = buf_req->addr;
+
+ __handle_ioreq(env, &req);
mb();
- buffered_io_page->read_pointer++;
+ buffered_io_page->read_pointer += qw ? 2 : 1;
}
}
@@ -616,7 +636,7 @@ int main_loop(void)
extern int shutdown_requested;
extern int suspend_requested;
CPUState *env = cpu_single_env;
- int evtchn_fd = xc_evtchn_fd(xce_handle);
+ int evtchn_fd = xce_handle == -1 ? -1 : xc_evtchn_fd(xce_handle);
char qemu_file[PATH_MAX];
fd_set fds;
@@ -624,7 +644,8 @@ int main_loop(void)
cpu_single_env);
qemu_mod_timer(buffered_io_timer, qemu_get_clock(rt_clock));
- qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, env);
+ if (evtchn_fd != -1)
+ qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, env);
xenstore_record_dm_state("running");
while (1) {
diff -r c17bfb091790 -r a07288a84785 tools/ioemu/vl.c
--- a/tools/ioemu/vl.c Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/ioemu/vl.c Tue Oct 30 15:34:44 2007 -0600
@@ -96,7 +96,6 @@
#include "exec-all.h"
-#include <xen/hvm/params.h>
#define DEFAULT_NETWORK_SCRIPT "/etc/xen/qemu-ifup"
#ifdef _BSD
#define DEFAULT_BRIDGE "bridge0"
@@ -194,11 +193,8 @@ extern int vcpus;
int xc_handle;
-char domain_name[64] = "Xen-HVM-no-name";
+char domain_name[64] = "Xen-no-name";
extern int domid;
-
-char vncpasswd[64];
-unsigned char challenge[AUTHCHALLENGESIZE];
/***********************************************************/
/* x86 ISA bus support */
@@ -6204,12 +6200,10 @@ void main_loop_wait(int timeout)
IOHandlerRecord **pioh;
for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) {
- if (ioh->deleted)
- continue;
- if (ioh->fd_read && FD_ISSET(ioh->fd, &rfds)) {
+ if (!ioh->deleted && ioh->fd_read && FD_ISSET(ioh->fd, &rfds)) {
ioh->fd_read(ioh->opaque);
}
- if (ioh->fd_write && FD_ISSET(ioh->fd, &wfds)) {
+ if (!ioh->deleted && ioh->fd_write && FD_ISSET(ioh->fd, &wfds)) {
ioh->fd_write(ioh->opaque);
}
}
@@ -6696,8 +6690,13 @@ void register_machines(void)
void register_machines(void)
{
#if defined(TARGET_I386)
+#ifndef CONFIG_DM
qemu_register_machine(&pc_machine);
qemu_register_machine(&isapc_machine);
+#else
+ qemu_register_machine(&xenfv_machine);
+ qemu_register_machine(&xenpv_machine);
+#endif
#elif defined(TARGET_PPC)
qemu_register_machine(&heathrow_machine);
qemu_register_machine(&core99_machine);
@@ -6905,156 +6904,6 @@ int set_mm_mapping(int xc_handle, uint32
return 0;
}
-#if defined(MAPCACHE)
-
-#if defined(__i386__)
-#define MAX_MCACHE_SIZE 0x40000000 /* 1GB max for x86 */
-#define MCACHE_BUCKET_SHIFT 16
-#elif defined(__x86_64__)
-#define MAX_MCACHE_SIZE 0x1000000000 /* 64GB max for x86_64 */
-#define MCACHE_BUCKET_SHIFT 20
-#endif
-
-#define MCACHE_BUCKET_SIZE (1UL << MCACHE_BUCKET_SHIFT)
-
-#define BITS_PER_LONG (sizeof(long)*8)
-#define BITS_TO_LONGS(bits) \
- (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG)
-#define DECLARE_BITMAP(name,bits) \
- unsigned long name[BITS_TO_LONGS(bits)]
-#define test_bit(bit,map) \
- (!!((map)[(bit)/BITS_PER_LONG] & (1UL << ((bit)%BITS_PER_LONG))))
-
-struct map_cache {
- unsigned long paddr_index;
- uint8_t *vaddr_base;
- DECLARE_BITMAP(valid_mapping, MCACHE_BUCKET_SIZE>>PAGE_SHIFT);
-};
-
-static struct map_cache *mapcache_entry;
-static unsigned long nr_buckets;
-
-/* For most cases (>99.9%), the page address is the same. */
-static unsigned long last_address_index = ~0UL;
-static uint8_t *last_address_vaddr;
-
-static int qemu_map_cache_init(void)
-{
- unsigned long size;
-
- nr_buckets = (((MAX_MCACHE_SIZE >> PAGE_SHIFT) +
- (1UL << (MCACHE_BUCKET_SHIFT - PAGE_SHIFT)) - 1) >>
- (MCACHE_BUCKET_SHIFT - PAGE_SHIFT));
-
- /*
- * Use mmap() directly: lets us allocate a big hash table with no up-front
- * cost in storage space. The OS will allocate memory only for the buckets
- * that we actually use. All others will contain all zeroes.
- */
- size = nr_buckets * sizeof(struct map_cache);
- size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
- fprintf(logfile, "qemu_map_cache_init nr_buckets = %lx size %lu\n",
nr_buckets, size);
- mapcache_entry = mmap(NULL, size, PROT_READ|PROT_WRITE,
- MAP_SHARED|MAP_ANON, -1, 0);
- if (mapcache_entry == MAP_FAILED) {
- errno = ENOMEM;
- return -1;
- }
-
- return 0;
-}
-
-static void qemu_remap_bucket(struct map_cache *entry,
- unsigned long address_index)
-{
- uint8_t *vaddr_base;
- unsigned long pfns[MCACHE_BUCKET_SIZE >> PAGE_SHIFT];
- unsigned int i, j;
-
- if (entry->vaddr_base != NULL) {
- errno = munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE);
- if (errno) {
- fprintf(logfile, "unmap fails %d\n", errno);
- exit(-1);
- }
- }
-
- for (i = 0; i < MCACHE_BUCKET_SIZE >> PAGE_SHIFT; i++)
- pfns[i] = (address_index << (MCACHE_BUCKET_SHIFT-PAGE_SHIFT)) + i;
-
- vaddr_base = xc_map_foreign_batch(xc_handle, domid, PROT_READ|PROT_WRITE,
- pfns, MCACHE_BUCKET_SIZE >> PAGE_SHIFT);
- if (vaddr_base == NULL) {
- fprintf(logfile, "xc_map_foreign_batch error %d\n", errno);
- exit(-1);
- }
-
- entry->vaddr_base = vaddr_base;
- entry->paddr_index = address_index;
-
- for (i = 0; i < MCACHE_BUCKET_SIZE >> PAGE_SHIFT; i += BITS_PER_LONG) {
- unsigned long word = 0;
- j = ((i + BITS_PER_LONG) > (MCACHE_BUCKET_SIZE >> PAGE_SHIFT)) ?
- (MCACHE_BUCKET_SIZE >> PAGE_SHIFT) % BITS_PER_LONG : BITS_PER_LONG;
- while (j > 0)
- word = (word << 1) | (((pfns[i + --j] >> 28) & 0xf) != 0xf);
- entry->valid_mapping[i / BITS_PER_LONG] = word;
- }
-}
-
-uint8_t *qemu_map_cache(target_phys_addr_t phys_addr)
-{
- struct map_cache *entry;
- unsigned long address_index = phys_addr >> MCACHE_BUCKET_SHIFT;
- unsigned long address_offset = phys_addr & (MCACHE_BUCKET_SIZE-1);
-
- if (address_index == last_address_index)
- return last_address_vaddr + address_offset;
-
- entry = &mapcache_entry[address_index % nr_buckets];
-
- if (entry->vaddr_base == NULL || entry->paddr_index != address_index ||
- !test_bit(address_offset>>PAGE_SHIFT, entry->valid_mapping))
- qemu_remap_bucket(entry, address_index);
-
- if (!test_bit(address_offset>>PAGE_SHIFT, entry->valid_mapping))
- return NULL;
-
- last_address_index = address_index;
- last_address_vaddr = entry->vaddr_base;
-
- return last_address_vaddr + address_offset;
-}
-
-void qemu_invalidate_map_cache(void)
-{
- unsigned long i;
-
- mapcache_lock();
-
- for (i = 0; i < nr_buckets; i++) {
- struct map_cache *entry = &mapcache_entry[i];
-
- if (entry->vaddr_base == NULL)
- continue;
-
- errno = munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE);
- if (errno) {
- fprintf(logfile, "unmap fails %d\n", errno);
- exit(-1);
- }
-
- entry->paddr_index = 0;
- entry->vaddr_base = NULL;
- }
-
- last_address_index = ~0UL;
- last_address_vaddr = NULL;
-
- mapcache_unlock();
-}
-
-#endif /* defined(MAPCACHE) */
int main(int argc, char **argv)
{
@@ -7089,15 +6938,7 @@ int main(int argc, char **argv)
char usb_devices[MAX_USB_CMDLINE][128];
int usb_devices_index;
int fds[2];
- unsigned long ioreq_pfn;
- extern void *shared_page;
- extern void *buffered_io_page;
struct rlimit rl;
-#ifdef __ia64__
- unsigned long nr_pages;
- xen_pfn_t *page_array;
- extern void *buffered_pio_page;
-#endif
sigset_t set;
char qemu_dm_logfilename[128];
const char *direct_pci = NULL;
@@ -7193,7 +7034,6 @@ int main(int argc, char **argv)
vncunused = 0;
kernel_filename = NULL;
kernel_cmdline = "";
- *vncpasswd = '\0';
#ifndef CONFIG_DM
#ifdef TARGET_PPC
cdrom_index = 1;
@@ -7601,7 +7441,7 @@ int main(int argc, char **argv)
break;
case QEMU_OPTION_domainname:
snprintf(domain_name, sizeof(domain_name),
- "Xen-HVM-%s", optarg);
+ "Xen-%s", optarg);
break;
case QEMU_OPTION_d:
domid = atoi(optarg);
@@ -7681,6 +7521,7 @@ int main(int argc, char **argv)
#ifdef CONFIG_DM
bdrv_init();
+ xc_handle = xc_interface_open();
xenstore_parse_domain_config(domid);
#endif /* CONFIG_DM */
@@ -7774,83 +7615,6 @@ int main(int argc, char **argv)
}
phys_ram_size += ret;
}
-#endif /* !CONFIG_DM */
-
-#ifdef CONFIG_DM
-
- xc_handle = xc_interface_open();
-
-#if defined(__i386__) || defined(__x86_64__)
-
- if (qemu_map_cache_init()) {
- fprintf(logfile, "qemu_map_cache_init returned: error %d\n", errno);
- exit(-1);
- }
-
- xc_get_hvm_param(xc_handle, domid, HVM_PARAM_IOREQ_PFN, &ioreq_pfn);
- fprintf(logfile, "shared page at pfn %lx\n", ioreq_pfn);
- shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
- PROT_READ|PROT_WRITE, ioreq_pfn);
- if (shared_page == NULL) {
- fprintf(logfile, "map shared IO page returned error %d\n", errno);
- exit(-1);
- }
-
- xc_get_hvm_param(xc_handle, domid, HVM_PARAM_BUFIOREQ_PFN, &ioreq_pfn);
- fprintf(logfile, "buffered io page at pfn %lx\n", ioreq_pfn);
- buffered_io_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
- PROT_READ|PROT_WRITE, ioreq_pfn);
- if (buffered_io_page == NULL) {
- fprintf(logfile, "map buffered IO page returned error %d\n", errno);
- exit(-1);
- }
-
-#elif defined(__ia64__)
-
- nr_pages = ram_size/PAGE_SIZE;
-
- page_array = (xen_pfn_t *)malloc(nr_pages * sizeof(xen_pfn_t));
- if (page_array == NULL) {
- fprintf(logfile, "malloc returned error %d\n", errno);
- exit(-1);
- }
-
- shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
- PROT_READ|PROT_WRITE,
- IO_PAGE_START >> PAGE_SHIFT);
-
- buffered_io_page =xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
- PROT_READ|PROT_WRITE,
- BUFFER_IO_PAGE_START >> PAGE_SHIFT);
-
- buffered_pio_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
- PROT_READ|PROT_WRITE,
- BUFFER_PIO_PAGE_START >> PAGE_SHIFT);
-
- for (i = 0; i < nr_pages; i++)
- page_array[i] = i;
-
- /* VTI will not use memory between 3G~4G, so we just pass a legal pfn
- to make QEMU map continuous virtual memory space */
- if (ram_size > MMIO_START) {
- for (i = 0 ; i < (MEM_G >> PAGE_SHIFT); i++)
- page_array[(MMIO_START >> PAGE_SHIFT) + i] =
- (STORE_PAGE_START >> PAGE_SHIFT);
- }
-
- phys_ram_base = xc_map_foreign_batch(xc_handle, domid,
- PROT_READ|PROT_WRITE,
- page_array, nr_pages);
- if (phys_ram_base == 0) {
- fprintf(logfile, "xc_map_foreign_batch returned error %d\n", errno);
- exit(-1);
- }
- free(page_array);
-#endif
-
- timeoffset_get();
-
-#else /* !CONFIG_DM */
phys_ram_base = qemu_vmalloc(phys_ram_size);
if (!phys_ram_base) {
@@ -7858,9 +7622,6 @@ int main(int argc, char **argv)
exit(1);
}
-#endif /* !CONFIG_DM */
-
-#ifndef CONFIG_DM
/* we always create the cdrom drive, even if no disk is there */
bdrv_init();
if (cdrom_index >= 0) {
@@ -7917,17 +7678,19 @@ int main(int argc, char **argv)
init_ioports();
- /* read vncpasswd from xenstore */
- if (0 > xenstore_read_vncpasswd(domid))
- exit(1);
-
/* terminal init */
if (nographic) {
dumb_display_init(ds);
} else if (vnc_display != NULL || vncunused != 0) {
int vnc_display_port;
- vnc_display_port = vnc_display_init(ds, vnc_display, vncunused);
- if (vncviewer)
+ char password[20];
+ vnc_display_init(ds);
+ if (xenstore_read_vncpasswd(domid, password, sizeof(password)) < 0)
+ exit(0);
+ vnc_display_password(ds, password);
+ if ((vnc_display_port = vnc_display_open(ds, vnc_display, vncunused)) <
0)
+ exit (0);
+ if (vncviewer)
vnc_start_viewer(vnc_display_port);
xenstore_write_vncport(vnc_display_port);
} else {
diff -r c17bfb091790 -r a07288a84785 tools/ioemu/vl.h
--- a/tools/ioemu/vl.h Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/ioemu/vl.h Tue Oct 30 15:34:44 2007 -0600
@@ -943,7 +943,10 @@ void cocoa_display_init(DisplayState *ds
void cocoa_display_init(DisplayState *ds, int full_screen);
/* vnc.c */
-int vnc_display_init(DisplayState *ds, const char *display, int find_unused);
+void vnc_display_init(DisplayState *ds);
+void vnc_display_close(DisplayState *ds);
+int vnc_display_open(DisplayState *ds, const char * display, int find_unused);
+int vnc_display_password(DisplayState *ds, const char *password);
void do_info_vnc(void);
int vnc_start_viewer(int port);
@@ -1108,6 +1111,10 @@ extern void pci_piix4_acpi_init(PCIBus *
/* pc.c */
extern QEMUMachine pc_machine;
extern QEMUMachine isapc_machine;
+#ifdef CONFIG_DM
+extern QEMUMachine xenfv_machine;
+extern QEMUMachine xenpv_machine;
+#endif
extern int fd_bootchk;
void ioport_set_a20(int enable);
@@ -1449,7 +1456,7 @@ void xenstore_record_dm_state(char *stat
void xenstore_record_dm_state(char *state);
void xenstore_check_new_media_present(int timeout);
void xenstore_write_vncport(int vnc_display);
-int xenstore_read_vncpasswd(int domid);
+int xenstore_read_vncpasswd(int domid, char *pwbuf, size_t pwbuflen);
int xenstore_domain_has_devtype(struct xs_handle *handle,
const char *devtype);
@@ -1486,9 +1493,6 @@ extern char domain_name[];
void destroy_hvm_domain(void);
-/* VNC Authentication */
-#define AUTHCHALLENGESIZE 16
-
#ifdef __ia64__
static inline void xc_domain_shutdown_hook(int xc_handle, uint32_t domid)
{
diff -r c17bfb091790 -r a07288a84785 tools/ioemu/vnc.c
--- a/tools/ioemu/vnc.c Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/ioemu/vnc.c Tue Oct 30 15:34:44 2007 -0600
@@ -49,6 +49,27 @@
#include "keymaps.c"
#include "d3des.h"
+#if CONFIG_VNC_TLS
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#endif /* CONFIG_VNC_TLS */
+
+// #define _VNC_DEBUG 1
+
+#if _VNC_DEBUG
+#define VNC_DEBUG(fmt, ...) do { fprintf(stderr, fmt, ## __VA_ARGS__); } while
(0)
+
+#if CONFIG_VNC_TLS && _VNC_DEBUG >= 2
+/* Very verbose, so only enabled for _VNC_DEBUG >= 2 */
+static void vnc_debug_gnutls_log(int level, const char* str) {
+ VNC_DEBUG("%d %s", level, str);
+}
+#endif /* CONFIG_VNC_TLS && _VNC_DEBUG */
+#else
+#define VNC_DEBUG(fmt, ...) do { } while (0)
+#endif
+
+
typedef struct Buffer
{
size_t capacity;
@@ -73,6 +94,45 @@ typedef void VncSendHextileTile(VncState
#define VNC_MAX_HEIGHT 2048
#define VNC_DIRTY_WORDS (VNC_MAX_WIDTH / (16 * 32))
#endif
+
+#define VNC_AUTH_CHALLENGE_SIZE 16
+
+enum {
+ VNC_AUTH_INVALID = 0,
+ VNC_AUTH_NONE = 1,
+ VNC_AUTH_VNC = 2,
+ VNC_AUTH_RA2 = 5,
+ VNC_AUTH_RA2NE = 6,
+ VNC_AUTH_TIGHT = 16,
+ VNC_AUTH_ULTRA = 17,
+ VNC_AUTH_TLS = 18,
+ VNC_AUTH_VENCRYPT = 19
+};
+
+#if CONFIG_VNC_TLS
+enum {
+ VNC_WIREMODE_CLEAR,
+ VNC_WIREMODE_TLS,
+};
+
+enum {
+ VNC_AUTH_VENCRYPT_PLAIN = 256,
+ VNC_AUTH_VENCRYPT_TLSNONE = 257,
+ VNC_AUTH_VENCRYPT_TLSVNC = 258,
+ VNC_AUTH_VENCRYPT_TLSPLAIN = 259,
+ VNC_AUTH_VENCRYPT_X509NONE = 260,
+ VNC_AUTH_VENCRYPT_X509VNC = 261,
+ VNC_AUTH_VENCRYPT_X509PLAIN = 262,
+};
+
+#if CONFIG_VNC_TLS
+#define X509_CA_CERT_FILE "ca-cert.pem"
+#define X509_CA_CRL_FILE "ca-crl.pem"
+#define X509_SERVER_KEY_FILE "server-key.pem"
+#define X509_SERVER_CERT_FILE "server-cert.pem"
+#endif
+
+#endif /* CONFIG_VNC_TLS */
struct VncState
{
@@ -98,7 +158,27 @@ struct VncState
int last_x;
int last_y;
- const char *display;
+ int major;
+ int minor;
+
+ char *display;
+ char *password;
+ int auth;
+#if CONFIG_VNC_TLS
+ int subauth;
+ int x509verify;
+
+ char *x509cacert;
+ char *x509cacrl;
+ char *x509cert;
+ char *x509key;
+#endif
+ char challenge[VNC_AUTH_CHALLENGE_SIZE];
+
+#if CONFIG_VNC_TLS
+ int wiremode;
+ gnutls_session_t tls_session;
+#endif
Buffer output;
Buffer input;
@@ -164,9 +244,6 @@ static void vnc_update_client(void *opaq
static void vnc_update_client(void *opaque);
static void vnc_client_read(void *opaque);
static void framebuffer_set_updated(VncState *vs, int x, int y, int w, int h);
-static int make_challenge(unsigned char *random, int size);
-static void set_seed(unsigned int *seedp);
-static void get_random(int len, unsigned char *buf);
#if 0
static inline void vnc_set_bit(uint32_t *d, int k)
@@ -702,11 +779,19 @@ static int vnc_client_io_error(VncState
if (ret == -1 && (last_errno == EINTR || last_errno == EAGAIN))
return 0;
+ VNC_DEBUG("Closing down client sock %d %d\n", ret, ret < 0 ? last_errno
: 0);
qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
closesocket(vs->csock);
vs->csock = -1;
buffer_reset(&vs->input);
buffer_reset(&vs->output);
+#if CONFIG_VNC_TLS
+ if (vs->tls_session) {
+ gnutls_deinit(vs->tls_session);
+ vs->tls_session = NULL;
+ }
+ vs->wiremode = VNC_WIREMODE_CLEAR;
+#endif /* CONFIG_VNC_TLS */
return 0;
}
return ret;
@@ -722,7 +807,19 @@ static void vnc_client_write(void *opaqu
long ret;
VncState *vs = opaque;
- ret = send(vs->csock, vs->output.buffer, vs->output.offset, 0);
+#if CONFIG_VNC_TLS
+ if (vs->tls_session) {
+ ret = gnutls_write(vs->tls_session, vs->output.buffer,
vs->output.offset);
+ if (ret < 0) {
+ if (ret == GNUTLS_E_AGAIN)
+ errno = EAGAIN;
+ else
+ errno = EIO;
+ ret = -1;
+ }
+ } else
+#endif /* CONFIG_VNC_TLS */
+ ret = send(vs->csock, vs->output.buffer, vs->output.offset, 0);
ret = vnc_client_io_error(vs, ret, socket_error());
if (!ret)
return;
@@ -748,7 +845,19 @@ static void vnc_client_read(void *opaque
buffer_reserve(&vs->input, 4096);
- ret = recv(vs->csock, buffer_end(&vs->input), 4096, 0);
+#if CONFIG_VNC_TLS
+ if (vs->tls_session) {
+ ret = gnutls_read(vs->tls_session, buffer_end(&vs->input), 4096);
+ if (ret < 0) {
+ if (ret == GNUTLS_E_AGAIN)
+ errno = EAGAIN;
+ else
+ errno = EIO;
+ ret = -1;
+ }
+ } else
+#endif /* CONFIG_VNC_TLS */
+ ret = recv(vs->csock, buffer_end(&vs->input), 4096, 0);
ret = vnc_client_io_error(vs, ret, socket_error());
if (!ret)
return;
@@ -844,6 +953,41 @@ static uint32_t read_u32(uint8_t *data,
return ((data[offset] << 24) | (data[offset + 1] << 16) |
(data[offset + 2] << 8) | data[offset + 3]);
}
+
+#if CONFIG_VNC_TLS
+ssize_t vnc_tls_push(gnutls_transport_ptr_t transport,
+ const void *data,
+ size_t len) {
+ struct VncState *vs = (struct VncState *)transport;
+ int ret;
+
+ retry:
+ ret = send(vs->csock, data, len, 0);
+ if (ret < 0) {
+ if (errno == EINTR)
+ goto retry;
+ return -1;
+ }
+ return ret;
+}
+
+
+ssize_t vnc_tls_pull(gnutls_transport_ptr_t transport,
+ void *data,
+ size_t len) {
+ struct VncState *vs = (struct VncState *)transport;
+ int ret;
+
+ retry:
+ ret = recv(vs->csock, data, len, 0);
+ if (ret < 0) {
+ if (errno == EINTR)
+ goto retry;
+ return -1;
+ }
+ return ret;
+}
+#endif /* CONFIG_VNC_TLS */
static void client_cut_text(VncState *vs, size_t len, char *text)
{
@@ -1387,91 +1531,591 @@ static int protocol_client_init(VncState
return 0;
}
-static int protocol_response(VncState *vs, uint8_t *client_response, size_t
len)
-{
- extern char vncpasswd[64];
- extern unsigned char challenge[AUTHCHALLENGESIZE];
- unsigned char cryptchallenge[AUTHCHALLENGESIZE];
- unsigned char key[8];
- int passwdlen, i, j;
-
- memcpy(cryptchallenge, challenge, AUTHCHALLENGESIZE);
-
- /* Calculate the sent challenge */
- passwdlen = strlen(vncpasswd);
- for (i=0; i<8; i++)
- key[i] = i<passwdlen ? vncpasswd[i] : 0;
- deskey(key, EN0);
- for (j = 0; j < AUTHCHALLENGESIZE; j += 8)
- des(cryptchallenge+j, cryptchallenge+j);
-
- /* Check the actual response */
- if (memcmp(cryptchallenge, client_response, AUTHCHALLENGESIZE) != 0) {
- /* password error */
- vnc_write_u32(vs, 1);
- vnc_write_u32(vs, 22);
- vnc_write(vs, "Authentication failure", 22);
+
+static void make_challenge(VncState *vs)
+{
+ int i;
+
+ srand(time(NULL)+getpid()+getpid()*987654+rand());
+
+ for (i = 0 ; i < sizeof(vs->challenge) ; i++)
+ vs->challenge[i] = (int) (256.0*rand()/(RAND_MAX+1.0));
+}
+
+static int protocol_client_auth_vnc(VncState *vs, char *data, size_t len)
+{
+ char response[VNC_AUTH_CHALLENGE_SIZE];
+ int i, j, pwlen;
+ char key[8];
+
+ if (!vs->password || !vs->password[0]) {
+ VNC_DEBUG("No password configured on server");
+ vnc_write_u32(vs, 1); /* Reject auth */
+ if (vs->minor >= 8) {
+ static const char err[] = "Authentication failed";
+ vnc_write_u32(vs, sizeof(err));
+ vnc_write(vs, err, sizeof(err));
+ }
vnc_flush(vs);
- fprintf(stderr, "VNC Password error.\n");
vnc_client_error(vs);
return 0;
}
- vnc_write_u32(vs, 0);
+ memcpy(response, vs->challenge, VNC_AUTH_CHALLENGE_SIZE);
+
+ /* Calculate the expected challenge response */
+ pwlen = strlen(vs->password);
+ for (i=0; i<sizeof(key); i++)
+ key[i] = i<pwlen ? vs->password[i] : 0;
+ deskey(key, EN0);
+ for (j = 0; j < VNC_AUTH_CHALLENGE_SIZE; j += 8)
+ des(response+j, response+j);
+
+ /* Compare expected vs actual challenge response */
+ if (memcmp(response, data, VNC_AUTH_CHALLENGE_SIZE) != 0) {
+ VNC_DEBUG("Client challenge reponse did not match\n");
+ vnc_write_u32(vs, 1); /* Reject auth */
+ if (vs->minor >= 8) {
+ static const char err[] = "Authentication failed";
+ vnc_write_u32(vs, sizeof(err));
+ vnc_write(vs, err, sizeof(err));
+ }
+ vnc_flush(vs);
+ vnc_client_error(vs);
+ } else {
+ VNC_DEBUG("Accepting VNC challenge response\n");
+ vnc_write_u32(vs, 0); /* Accept auth */
+ vnc_flush(vs);
+
+ vnc_read_when(vs, protocol_client_init, 1);
+ }
+ return 0;
+}
+
+static int start_auth_vnc(VncState *vs)
+{
+ make_challenge(vs);
+ /* Send client a 'random' challenge */
+ vnc_write(vs, vs->challenge, sizeof(vs->challenge));
vnc_flush(vs);
- vnc_read_when(vs, protocol_client_init, 1);
-
+ vnc_read_when(vs, protocol_client_auth_vnc, sizeof(vs->challenge));
return 0;
}
-static int protocol_version(VncState *vs, uint8_t *version, size_t len)
-{
- extern char vncpasswd[64];
- extern unsigned char challenge[AUTHCHALLENGESIZE];
+
+#if CONFIG_VNC_TLS
+#define DH_BITS 1024
+static gnutls_dh_params_t dh_params;
+
+static int vnc_tls_initialize(void)
+{
+ static int tlsinitialized = 0;
+
+ if (tlsinitialized)
+ return 1;
+
+ if (gnutls_global_init () < 0)
+ return 0;
+
+ /* XXX ought to re-generate diffie-hellmen params periodically */
+ if (gnutls_dh_params_init (&dh_params) < 0)
+ return 0;
+ if (gnutls_dh_params_generate2 (dh_params, DH_BITS) < 0)
+ return 0;
+
+#if _VNC_DEBUG == 2
+ gnutls_global_set_log_level(10);
+ gnutls_global_set_log_function(vnc_debug_gnutls_log);
+#endif
+
+ tlsinitialized = 1;
+
+ return 1;
+}
+
+static gnutls_anon_server_credentials vnc_tls_initialize_anon_cred(void)
+{
+ gnutls_anon_server_credentials anon_cred;
+ int ret;
+
+ if ((ret = gnutls_anon_allocate_server_credentials(&anon_cred)) < 0) {
+ VNC_DEBUG("Cannot allocate credentials %s\n", gnutls_strerror(ret));
+ return NULL;
+ }
+
+ gnutls_anon_set_server_dh_params(anon_cred, dh_params);
+
+ return anon_cred;
+}
+
+
+static gnutls_certificate_credentials_t vnc_tls_initialize_x509_cred(VncState
*vs)
+{
+ gnutls_certificate_credentials_t x509_cred;
+ int ret;
+
+ if (!vs->x509cacert) {
+ VNC_DEBUG("No CA x509 certificate specified\n");
+ return NULL;
+ }
+ if (!vs->x509cert) {
+ VNC_DEBUG("No server x509 certificate specified\n");
+ return NULL;
+ }
+ if (!vs->x509key) {
+ VNC_DEBUG("No server private key specified\n");
+ return NULL;
+ }
+
+ if ((ret = gnutls_certificate_allocate_credentials(&x509_cred)) < 0) {
+ VNC_DEBUG("Cannot allocate credentials %s\n", gnutls_strerror(ret));
+ return NULL;
+ }
+ if ((ret = gnutls_certificate_set_x509_trust_file(x509_cred,
+ vs->x509cacert,
+ GNUTLS_X509_FMT_PEM)) <
0) {
+ VNC_DEBUG("Cannot load CA certificate %s\n", gnutls_strerror(ret));
+ gnutls_certificate_free_credentials(x509_cred);
+ return NULL;
+ }
+
+ if ((ret = gnutls_certificate_set_x509_key_file (x509_cred,
+ vs->x509cert,
+ vs->x509key,
+ GNUTLS_X509_FMT_PEM)) < 0)
{
+ VNC_DEBUG("Cannot load certificate & key %s\n", gnutls_strerror(ret));
+ gnutls_certificate_free_credentials(x509_cred);
+ return NULL;
+ }
+
+ if (vs->x509cacrl) {
+ if ((ret = gnutls_certificate_set_x509_crl_file(x509_cred,
+ vs->x509cacrl,
+ GNUTLS_X509_FMT_PEM)) <
0) {
+ VNC_DEBUG("Cannot load CRL %s\n", gnutls_strerror(ret));
+ gnutls_certificate_free_credentials(x509_cred);
+ return NULL;
+ }
+ }
+
+ gnutls_certificate_set_dh_params (x509_cred, dh_params);
+
+ return x509_cred;
+}
+
+static int vnc_validate_certificate(struct VncState *vs)
+{
+ int ret;
+ unsigned int status;
+ const gnutls_datum_t *certs;
+ unsigned int nCerts, i;
+ time_t now;
+
+ VNC_DEBUG("Validating client certificate\n");
+ if ((ret = gnutls_certificate_verify_peers2 (vs->tls_session, &status)) <
0) {
+ VNC_DEBUG("Verify failed %s\n", gnutls_strerror(ret));
+ return -1;
+ }
+
+ if ((now = time(NULL)) == ((time_t)-1)) {
+ return -1;
+ }
+
+ if (status != 0) {
+ if (status & GNUTLS_CERT_INVALID)
+ VNC_DEBUG("The certificate is not trusted.\n");
+
+ if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
+ VNC_DEBUG("The certificate hasn't got a known issuer.\n");
+
+ if (status & GNUTLS_CERT_REVOKED)
+ VNC_DEBUG("The certificate has been revoked.\n");
+
+ if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
+ VNC_DEBUG("The certificate uses an insecure algorithm\n");
+
+ return -1;
+ } else {
+ VNC_DEBUG("Certificate is valid!\n");
+ }
+
+ /* Only support x509 for now */
+ if (gnutls_certificate_type_get(vs->tls_session) != GNUTLS_CRT_X509)
+ return -1;
+
+ if (!(certs = gnutls_certificate_get_peers(vs->tls_session, &nCerts)))
+ return -1;
+
+ for (i = 0 ; i < nCerts ; i++) {
+ gnutls_x509_crt_t cert;
+ VNC_DEBUG ("Checking certificate chain %d\n", i);
+ if (gnutls_x509_crt_init (&cert) < 0)
+ return -1;
+
+ if (gnutls_x509_crt_import(cert, &certs[i], GNUTLS_X509_FMT_DER) < 0) {
+ gnutls_x509_crt_deinit (cert);
+ return -1;
+ }
+
+ if (gnutls_x509_crt_get_expiration_time (cert) < now) {
+ VNC_DEBUG("The certificate has expired\n");
+ gnutls_x509_crt_deinit (cert);
+ return -1;
+ }
+
+ if (gnutls_x509_crt_get_activation_time (cert) > now) {
+ VNC_DEBUG("The certificate is not yet activated\n");
+ gnutls_x509_crt_deinit (cert);
+ return -1;
+ }
+
+ if (gnutls_x509_crt_get_activation_time (cert) > now) {
+ VNC_DEBUG("The certificate is not yet activated\n");
+ gnutls_x509_crt_deinit (cert);
+ return -1;
+ }
+
+ gnutls_x509_crt_deinit (cert);
+ }
+
+ return 0;
+}
+
+
+static int start_auth_vencrypt_subauth(VncState *vs)
+{
+ switch (vs->subauth) {
+ case VNC_AUTH_VENCRYPT_TLSNONE:
+ case VNC_AUTH_VENCRYPT_X509NONE:
+ VNC_DEBUG("Accept TLS auth none\n");
+ vnc_write_u32(vs, 0); /* Accept auth completion */
+ vnc_read_when(vs, protocol_client_init, 1);
+ break;
+
+ case VNC_AUTH_VENCRYPT_TLSVNC:
+ case VNC_AUTH_VENCRYPT_X509VNC:
+ VNC_DEBUG("Start TLS auth VNC\n");
+ return start_auth_vnc(vs);
+
+ default: /* Should not be possible, but just in case */
+ VNC_DEBUG("Reject auth %d\n", vs->auth);
+ vnc_write_u8(vs, 1);
+ if (vs->minor >= 8) {
+ static const char err[] = "Unsupported authentication type";
+ vnc_write_u32(vs, sizeof(err));
+ vnc_write(vs, err, sizeof(err));
+ }
+ vnc_client_error(vs);
+ }
+
+ return 0;
+}
+
+static void vnc_handshake_io(void *opaque);
+
+static int vnc_continue_handshake(struct VncState *vs) {
+ int ret;
+
+ if ((ret = gnutls_handshake(vs->tls_session)) < 0) {
+ if (!gnutls_error_is_fatal(ret)) {
+ VNC_DEBUG("Handshake interrupted (blocking)\n");
+ if (!gnutls_record_get_direction(vs->tls_session))
+ qemu_set_fd_handler(vs->csock, vnc_handshake_io, NULL, vs);
+ else
+ qemu_set_fd_handler(vs->csock, NULL, vnc_handshake_io, vs);
+ return 0;
+ }
+ VNC_DEBUG("Handshake failed %s\n", gnutls_strerror(ret));
+ vnc_client_error(vs);
+ return -1;
+ }
+
+ if (vs->x509verify) {
+ if (vnc_validate_certificate(vs) < 0) {
+ VNC_DEBUG("Client verification failed\n");
+ vnc_client_error(vs);
+ return -1;
+ } else {
+ VNC_DEBUG("Client verification passed\n");
+ }
+ }
+
+ VNC_DEBUG("Handshake done, switching to TLS data mode\n");
+ vs->wiremode = VNC_WIREMODE_TLS;
+ qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write,
vs);
+
+ return start_auth_vencrypt_subauth(vs);
+}
+
+static void vnc_handshake_io(void *opaque) {
+ struct VncState *vs = (struct VncState *)opaque;
+
+ VNC_DEBUG("Handshake IO continue\n");
+ vnc_continue_handshake(vs);
+}
+
+#define NEED_X509_AUTH(vs) \
+ ((vs)->subauth == VNC_AUTH_VENCRYPT_X509NONE || \
+ (vs)->subauth == VNC_AUTH_VENCRYPT_X509VNC || \
+ (vs)->subauth == VNC_AUTH_VENCRYPT_X509PLAIN)
+
+
+static int vnc_start_tls(struct VncState *vs) {
+ static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
+ static const int protocol_priority[]= { GNUTLS_TLS1_1, GNUTLS_TLS1_0,
GNUTLS_SSL3, 0 };
+ static const int kx_anon[] = {GNUTLS_KX_ANON_DH, 0};
+ static const int kx_x509[] = {GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA,
GNUTLS_KX_DHE_RSA, GNUTLS_KX_SRP, 0};
+
+ VNC_DEBUG("Do TLS setup\n");
+ if (vnc_tls_initialize() < 0) {
+ VNC_DEBUG("Failed to init TLS\n");
+ vnc_client_error(vs);
+ return -1;
+ }
+ if (vs->tls_session == NULL) {
+ if (gnutls_init(&vs->tls_session, GNUTLS_SERVER) < 0) {
+ vnc_client_error(vs);
+ return -1;
+ }
+
+ if (gnutls_set_default_priority(vs->tls_session) < 0) {
+ gnutls_deinit(vs->tls_session);
+ vs->tls_session = NULL;
+ vnc_client_error(vs);
+ return -1;
+ }
+
+ if (gnutls_kx_set_priority(vs->tls_session, NEED_X509_AUTH(vs) ?
kx_x509 : kx_anon) < 0) {
+ gnutls_deinit(vs->tls_session);
+ vs->tls_session = NULL;
+ vnc_client_error(vs);
+ return -1;
+ }
+
+ if (gnutls_certificate_type_set_priority(vs->tls_session,
cert_type_priority) < 0) {
+ gnutls_deinit(vs->tls_session);
+ vs->tls_session = NULL;
+ vnc_client_error(vs);
+ return -1;
+ }
+
+ if (gnutls_protocol_set_priority(vs->tls_session, protocol_priority) <
0) {
+ gnutls_deinit(vs->tls_session);
+ vs->tls_session = NULL;
+ vnc_client_error(vs);
+ return -1;
+ }
+
+ if (NEED_X509_AUTH(vs)) {
+ gnutls_certificate_server_credentials x509_cred =
vnc_tls_initialize_x509_cred(vs);
+ if (!x509_cred) {
+ gnutls_deinit(vs->tls_session);
+ vs->tls_session = NULL;
+ vnc_client_error(vs);
+ return -1;
+ }
+ if (gnutls_credentials_set(vs->tls_session, GNUTLS_CRD_CERTIFICATE,
x509_cred) < 0) {
+ gnutls_deinit(vs->tls_session);
+ vs->tls_session = NULL;
+ gnutls_certificate_free_credentials(x509_cred);
+ vnc_client_error(vs);
+ return -1;
+ }
+ if (vs->x509verify) {
+ VNC_DEBUG("Requesting a client certificate\n");
+ gnutls_certificate_server_set_request (vs->tls_session,
GNUTLS_CERT_REQUEST);
+ }
+
+ } else {
+ gnutls_anon_server_credentials anon_cred =
vnc_tls_initialize_anon_cred();
+ if (!anon_cred) {
+ gnutls_deinit(vs->tls_session);
+ vs->tls_session = NULL;
+ vnc_client_error(vs);
+ return -1;
+ }
+ if (gnutls_credentials_set(vs->tls_session, GNUTLS_CRD_ANON,
anon_cred) < 0) {
+ gnutls_deinit(vs->tls_session);
+ vs->tls_session = NULL;
+ gnutls_anon_free_server_credentials(anon_cred);
+ vnc_client_error(vs);
+ return -1;
+ }
+ }
+
+ gnutls_transport_set_ptr(vs->tls_session, (gnutls_transport_ptr_t)vs);
+ gnutls_transport_set_push_function(vs->tls_session, vnc_tls_push);
+ gnutls_transport_set_pull_function(vs->tls_session, vnc_tls_pull);
+ }
+
+ VNC_DEBUG("Start TLS handshake process\n");
+ return vnc_continue_handshake(vs);
+}
+
+static int protocol_client_vencrypt_auth(VncState *vs, char *data, size_t len)
+{
+ int auth = read_u32(data, 0);
+
+ if (auth != vs->subauth) {
+ VNC_DEBUG("Rejecting auth %d\n", auth);
+ vnc_write_u8(vs, 0); /* Reject auth */
+ vnc_flush(vs);
+ vnc_client_error(vs);
+ } else {
+ VNC_DEBUG("Accepting auth %d, starting handshake\n", auth);
+ vnc_write_u8(vs, 1); /* Accept auth */
+ vnc_flush(vs);
+
+ if (vnc_start_tls(vs) < 0) {
+ VNC_DEBUG("Failed to complete TLS\n");
+ return 0;
+ }
+
+ if (vs->wiremode == VNC_WIREMODE_TLS) {
+ VNC_DEBUG("Starting VeNCrypt subauth\n");
+ return start_auth_vencrypt_subauth(vs);
+ } else {
+ VNC_DEBUG("TLS handshake blocked\n");
+ return 0;
+ }
+ }
+ return 0;
+}
+
+static int protocol_client_vencrypt_init(VncState *vs, char *data, size_t len)
+{
+ if (data[0] != 0 ||
+ data[1] != 2) {
+ VNC_DEBUG("Unsupported VeNCrypt protocol %d.%d\n", (int)data[0],
(int)data[1]);
+ vnc_write_u8(vs, 1); /* Reject version */
+ vnc_flush(vs);
+ vnc_client_error(vs);
+ } else {
+ VNC_DEBUG("Sending allowed auth %d\n", vs->subauth);
+ vnc_write_u8(vs, 0); /* Accept version */
+ vnc_write_u8(vs, 1); /* Number of sub-auths */
+ vnc_write_u32(vs, vs->subauth); /* The supported auth */
+ vnc_flush(vs);
+ vnc_read_when(vs, protocol_client_vencrypt_auth, 4);
+ }
+ return 0;
+}
+
+static int start_auth_vencrypt(VncState *vs)
+{
+ /* Send VeNCrypt version 0.2 */
+ vnc_write_u8(vs, 0);
+ vnc_write_u8(vs, 2);
+
+ vnc_read_when(vs, protocol_client_vencrypt_init, 2);
+ return 0;
+}
+#endif /* CONFIG_VNC_TLS */
+
+static int protocol_client_auth(VncState *vs, char *data, size_t len)
+{
+ /* We only advertise 1 auth scheme at a time, so client
+ * must pick the one we sent. Verify this */
+ if (data[0] != vs->auth) { /* Reject auth */
+ VNC_DEBUG("Reject auth %d\n", (int)data[0]);
+ vnc_write_u32(vs, 1);
+ if (vs->minor >= 8) {
+ static const char err[] = "Authentication failed";
+ vnc_write_u32(vs, sizeof(err));
+ vnc_write(vs, err, sizeof(err));
+ }
+ vnc_client_error(vs);
+ } else { /* Accept requested auth */
+ VNC_DEBUG("Client requested auth %d\n", (int)data[0]);
+ switch (vs->auth) {
+ case VNC_AUTH_NONE:
+ VNC_DEBUG("Accept auth none\n");
+ if (vs->minor >= 8) {
+ vnc_write_u32(vs, 0); /* Accept auth completion */
+ vnc_flush(vs);
+ }
+ vnc_read_when(vs, protocol_client_init, 1);
+ break;
+
+ case VNC_AUTH_VNC:
+ VNC_DEBUG("Start VNC auth\n");
+ return start_auth_vnc(vs);
+
+#if CONFIG_VNC_TLS
+ case VNC_AUTH_VENCRYPT:
+ VNC_DEBUG("Accept VeNCrypt auth\n");;
+ return start_auth_vencrypt(vs);
+#endif /* CONFIG_VNC_TLS */
+
+ default: /* Should not be possible, but just in case */
+ VNC_DEBUG("Reject auth %d\n", vs->auth);
+ vnc_write_u8(vs, 1);
+ if (vs->minor >= 8) {
+ static const char err[] = "Authentication failed";
+ vnc_write_u32(vs, sizeof(err));
+ vnc_write(vs, err, sizeof(err));
+ }
+ vnc_client_error(vs);
+ }
+ }
+ return 0;
+}
+
+static int protocol_version(VncState *vs, char *version, size_t len)
+{
char local[13];
- int support, maj, min;
memcpy(local, version, 12);
local[12] = 0;
- /* protocol version check */
- if (sscanf(local, "RFB %03d.%03d\n", &maj, &min) != 2) {
- fprintf(stderr, "Protocol version error.\n");
+ if (sscanf(local, "RFB %03d.%03d\n", &vs->major, &vs->minor) != 2) {
+ VNC_DEBUG("Malformed protocol version %s\n", local);
vnc_client_error(vs);
return 0;
}
-
-
- support = 0;
- if (maj == 3) {
- if (min == 3 || min ==4) {
- support = 1;
- }
- }
-
- if (! support) {
- fprintf(stderr, "Client uses unsupported protocol version %d.%d.\n",
- maj, min);
+ VNC_DEBUG("Client request protocol version %d.%d\n", vs->major, vs->minor);
+ if (vs->major != 3 ||
+ (vs->minor != 3 &&
+ vs->minor != 4 &&
+ vs->minor != 5 &&
+ vs->minor != 7 &&
+ vs->minor != 8)) {
+ VNC_DEBUG("Unsupported client version\n");
+ vnc_write_u32(vs, VNC_AUTH_INVALID);
+ vnc_flush(vs);
vnc_client_error(vs);
return 0;
}
-
- if (*vncpasswd == '\0') {
- /* AuthType is None */
- vnc_write_u32(vs, 1);
+ /* Some broken clients report v3.4 or v3.5, which spec requires to be
treated
+ * as equivalent to v3.3 by servers
+ */
+ if (vs->minor == 4 || vs->minor == 5)
+ vs->minor = 3;
+
+ if (vs->minor == 3) {
+ if (vs->auth == VNC_AUTH_NONE) {
+ VNC_DEBUG("Tell client auth none\n");
+ vnc_write_u32(vs, vs->auth);
+ vnc_flush(vs);
+ vnc_read_when(vs, protocol_client_init, 1);
+ } else if (vs->auth == VNC_AUTH_VNC) {
+ VNC_DEBUG("Tell client VNC auth\n");
+ vnc_write_u32(vs, vs->auth);
+ vnc_flush(vs);
+ start_auth_vnc(vs);
+ } else {
+ VNC_DEBUG("Unsupported auth %d for protocol 3.3\n", vs->auth);
+ vnc_write_u32(vs, VNC_AUTH_INVALID);
+ vnc_flush(vs);
+ vnc_client_error(vs);
+ }
+ } else {
+ VNC_DEBUG("Telling client we support auth %d\n", vs->auth);
+ vnc_write_u8(vs, 1); /* num auth */
+ vnc_write_u8(vs, vs->auth);
+ vnc_read_when(vs, protocol_client_auth, 1);
vnc_flush(vs);
- vnc_read_when(vs, protocol_client_init, 1);
- } else {
- /* AuthType is VncAuth */
- vnc_write_u32(vs, 2);
-
- /* Challenge-Responce authentication */
- /* Send Challenge */
- make_challenge(challenge, AUTHCHALLENGESIZE);
- vnc_write(vs, challenge, AUTHCHALLENGESIZE);
- vnc_flush(vs);
- vnc_read_when(vs, protocol_response, AUTHCHALLENGESIZE);
}
return 0;
@@ -1485,9 +2129,10 @@ static void vnc_listen_read(void *opaque
vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen);
if (vs->csock != -1) {
+ VNC_DEBUG("New client on socket %d\n", vs->csock);
socket_set_nonblock(vs->csock);
qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, opaque);
- vnc_write(vs, "RFB 003.003\n", 12);
+ vnc_write(vs, "RFB 003.008\n", 12);
vnc_flush(vs);
vnc_read_when(vs, protocol_version, 12);
framebuffer_set_updated(vs, 0, 0, vs->ds->width, vs->ds->height);
@@ -1500,7 +2145,155 @@ static void vnc_listen_read(void *opaque
extern int parse_host_port(struct sockaddr_in *saddr, const char *str);
-int vnc_display_init(DisplayState *ds, const char *arg, int find_unused)
+void vnc_display_init(DisplayState *ds)
+{
+ VncState *vs;
+
+ vs = qemu_mallocz(sizeof(VncState));
+ if (!vs)
+ exit(1);
+
+ ds->opaque = vs;
+ vnc_state = vs;
+ vs->display = NULL;
+ vs->password = NULL;
+
+ vs->lsock = -1;
+ vs->csock = -1;
+ vs->depth = 4;
+ vs->last_x = -1;
+ vs->last_y = -1;
+
+ vs->ds = ds;
+
+ if (!keyboard_layout)
+ keyboard_layout = "en-us";
+
+ vs->kbd_layout = init_keyboard_layout(keyboard_layout);
+ if (!vs->kbd_layout)
+ exit(1);
+ vs->modifiers_state[0x45] = 1; /* NumLock on - on boot */
+
+ vs->ds->data = NULL;
+ vs->ds->dpy_update = vnc_dpy_update;
+ vs->ds->dpy_resize = vnc_dpy_resize;
+ vs->ds->dpy_refresh = vnc_dpy_refresh;
+
+ vnc_dpy_resize(vs->ds, 640, 400);
+}
+
+#if CONFIG_VNC_TLS
+static int vnc_set_x509_credential(VncState *vs,
+ const char *certdir,
+ const char *filename,
+ char **cred,
+ int ignoreMissing)
+{
+ struct stat sb;
+
+ if (*cred) {
+ qemu_free(*cred);
+ *cred = NULL;
+ }
+
+ if (!(*cred = qemu_malloc(strlen(certdir) + strlen(filename) + 2)))
+ return -1;
+
+ strcpy(*cred, certdir);
+ strcat(*cred, "/");
+ strcat(*cred, filename);
+
+ VNC_DEBUG("Check %s\n", *cred);
+ if (stat(*cred, &sb) < 0) {
+ qemu_free(*cred);
+ *cred = NULL;
+ if (ignoreMissing && errno == ENOENT)
+ return 0;
+ return -1;
+ }
+
+ return 0;
+}
+
+static int vnc_set_x509_credential_dir(VncState *vs,
+ const char *certdir)
+{
+ if (vnc_set_x509_credential(vs, certdir, X509_CA_CERT_FILE,
&vs->x509cacert, 0) < 0)
+ goto cleanup;
+ if (vnc_set_x509_credential(vs, certdir, X509_CA_CRL_FILE, &vs->x509cacrl,
1) < 0)
+ goto cleanup;
+ if (vnc_set_x509_credential(vs, certdir, X509_SERVER_CERT_FILE,
&vs->x509cert, 0) < 0)
+ goto cleanup;
+ if (vnc_set_x509_credential(vs, certdir, X509_SERVER_KEY_FILE,
&vs->x509key, 0) < 0)
+ goto cleanup;
+
+ return 0;
+
+ cleanup:
+ qemu_free(vs->x509cacert);
+ qemu_free(vs->x509cacrl);
+ qemu_free(vs->x509cert);
+ qemu_free(vs->x509key);
+ vs->x509cacert = vs->x509cacrl = vs->x509cert = vs->x509key = NULL;
+ return -1;
+}
+#endif /* CONFIG_VNC_TLS */
+
+void vnc_display_close(DisplayState *ds)
+{
+ VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
+
+ if (vs->display) {
+ qemu_free(vs->display);
+ vs->display = NULL;
+ }
+ if (vs->lsock != -1) {
+ qemu_set_fd_handler2(vs->lsock, NULL, NULL, NULL, NULL);
+ close(vs->lsock);
+ vs->lsock = -1;
+ }
+ if (vs->csock != -1) {
+ qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL);
+ closesocket(vs->csock);
+ vs->csock = -1;
+ buffer_reset(&vs->input);
+ buffer_reset(&vs->output);
+#if CONFIG_VNC_TLS
+ if (vs->tls_session) {
+ gnutls_deinit(vs->tls_session);
+ vs->tls_session = NULL;
+ }
+ vs->wiremode = VNC_WIREMODE_CLEAR;
+#endif /* CONFIG_VNC_TLS */
+ }
+ vs->auth = VNC_AUTH_INVALID;
+#if CONFIG_VNC_TLS
+ vs->subauth = VNC_AUTH_INVALID;
+ vs->x509verify = 0;
+#endif
+}
+
+int parse_host_port(struct sockaddr_in *saddr, const char *str);
+
+
+
+int vnc_display_password(DisplayState *ds, const char *password)
+{
+ VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
+
+ if (vs->password) {
+ qemu_free(vs->password);
+ vs->password = NULL;
+ }
+ if (password && password[0]) {
+ if (!(vs->password = qemu_strdup(password)))
+ return -1;
+ }
+
+ return 0;
+}
+
+int vnc_display_open(DisplayState *ds, const char *display, int find_unused)
{
struct sockaddr *addr;
struct sockaddr_in iaddr;
@@ -1510,51 +2303,115 @@ int vnc_display_init(DisplayState *ds, c
int reuse_addr, ret;
socklen_t addrlen;
const char *p;
- VncState *vs;
-
- vs = qemu_mallocz(sizeof(VncState));
- if (!vs)
- exit(1);
-
- ds->opaque = vs;
- vnc_state = vs;
- vs->display = arg;
-
- vs->lsock = -1;
- vs->csock = -1;
- vs->depth = 4;
- vs->last_x = -1;
- vs->last_y = -1;
-
- vs->ds = ds;
-
- if (!keyboard_layout)
- keyboard_layout = "en-us";
-
- vs->kbd_layout = init_keyboard_layout(keyboard_layout);
- if (!vs->kbd_layout)
- exit(1);
- vs->modifiers_state[0x45] = 1; /* NumLock on - on boot */
-
- vs->ds->data = NULL;
- vs->ds->dpy_update = vnc_dpy_update;
- vs->ds->dpy_resize = vnc_dpy_resize;
- vs->ds->dpy_refresh = vnc_dpy_refresh;
-
- vnc_dpy_resize(vs->ds, 640, 400);
-
- if (arg == NULL)
- arg = "localhost:0";
-
+ VncState *vs = ds ? (VncState *)ds->opaque : vnc_state;
+ const char *options;
+ int password = 0;
+#if CONFIG_VNC_TLS
+ int tls = 0, x509 = 0;
+#endif
+
+ if (display == NULL)
+ display = "localhost:0";
+
+ vnc_display_close(ds);
+ if (strcmp(display, "none") == 0)
+ return 0;
+
+ if (!(vs->display = strdup(display)))
+ return -1;
+
+ options = display;
+ while ((options = strchr(options, ','))) {
+ options++;
+ if (strncmp(options, "password", 8) == 0) {
+ password = 1; /* Require password auth */
+#if CONFIG_VNC_TLS
+ } else if (strncmp(options, "tls", 3) == 0) {
+ tls = 1; /* Require TLS */
+ } else if (strncmp(options, "x509", 4) == 0) {
+ char *start, *end;
+ x509 = 1; /* Require x509 certificates */
+ if (strncmp(options, "x509verify", 10) == 0)
+ vs->x509verify = 1; /* ...and verify client certs */
+
+ /* Now check for 'x509=/some/path' postfix
+ * and use that to setup x509 certificate/key paths */
+ start = strchr(options, '=');
+ end = strchr(options, ',');
+ if (start && (!end || (start < end))) {
+ int len = end ? end-(start+1) : strlen(start+1);
+ char *path = qemu_malloc(len+1);
+ strncpy(path, start+1, len);
+ path[len] = '\0';
+ VNC_DEBUG("Trying certificate path '%s'\n", path);
+ if (vnc_set_x509_credential_dir(vs, path) < 0) {
+ fprintf(stderr, "Failed to find x509 certificates/keys in
%s\n", path);
+ qemu_free(path);
+ qemu_free(vs->display);
+ vs->display = NULL;
+ return -1;
+ }
+ qemu_free(path);
+ } else {
+ fprintf(stderr, "No certificate path provided\n");
+ qemu_free(vs->display);
+ vs->display = NULL;
+ return -1;
+ }
+#endif
+ }
+ }
+
+ if (password) {
+#if CONFIG_VNC_TLS
+ if (tls) {
+ vs->auth = VNC_AUTH_VENCRYPT;
+ if (x509) {
+ VNC_DEBUG("Initializing VNC server with x509 password auth\n");
+ vs->subauth = VNC_AUTH_VENCRYPT_X509VNC;
+ } else {
+ VNC_DEBUG("Initializing VNC server with TLS password auth\n");
+ vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC;
+ }
+ } else {
+#endif
+ VNC_DEBUG("Initializing VNC server with password auth\n");
+ vs->auth = VNC_AUTH_VNC;
+#if CONFIG_VNC_TLS
+ vs->subauth = VNC_AUTH_INVALID;
+ }
+#endif
+ } else {
+#if CONFIG_VNC_TLS
+ if (tls) {
+ vs->auth = VNC_AUTH_VENCRYPT;
+ if (x509) {
+ VNC_DEBUG("Initializing VNC server with x509 no auth\n");
+ vs->subauth = VNC_AUTH_VENCRYPT_X509NONE;
+ } else {
+ VNC_DEBUG("Initializing VNC server with TLS no auth\n");
+ vs->subauth = VNC_AUTH_VENCRYPT_TLSNONE;
+ }
+ } else {
+#endif
+ VNC_DEBUG("Initializing VNC server with no auth\n");
+ vs->auth = VNC_AUTH_NONE;
+#if CONFIG_VNC_TLS
+ vs->subauth = VNC_AUTH_INVALID;
+ }
+#endif
+ }
#ifndef _WIN32
- if (strstart(arg, "unix:", &p)) {
+ if (strstart(display, "unix:", &p)) {
addr = (struct sockaddr *)&uaddr;
addrlen = sizeof(uaddr);
vs->lsock = socket(PF_UNIX, SOCK_STREAM, 0);
if (vs->lsock == -1) {
fprintf(stderr, "Could not create socket\n");
- exit(1);
+ free(vs->display);
+ vs->display = NULL;
+ return -1;
}
uaddr.sun_family = AF_UNIX;
@@ -1568,25 +2425,33 @@ int vnc_display_init(DisplayState *ds, c
addr = (struct sockaddr *)&iaddr;
addrlen = sizeof(iaddr);
+ if (parse_host_port(&iaddr, display) < 0) {
+ fprintf(stderr, "Could not parse VNC address\n");
+ free(vs->display);
+ vs->display = NULL;
+ return -1;
+ }
+
+ iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 5900);
+
vs->lsock = socket(PF_INET, SOCK_STREAM, 0);
if (vs->lsock == -1) {
fprintf(stderr, "Could not create socket\n");
- exit(1);
- }
-
- if (parse_host_port(&iaddr, arg) < 0) {
- fprintf(stderr, "Could not parse VNC address\n");
- exit(1);
- }
-
- iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 5900);
+ free(vs->display);
+ vs->display = NULL;
+ return -1;
+ }
reuse_addr = 1;
ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR,
(const char *)&reuse_addr, sizeof(reuse_addr));
if (ret == -1) {
fprintf(stderr, "setsockopt() failed\n");
- exit(1);
+ close(vs->lsock);
+ vs->lsock = -1;
+ free(vs->display);
+ vs->display = NULL;
+ return -1;
}
}
@@ -1596,18 +2461,24 @@ int vnc_display_init(DisplayState *ds, c
continue;
}
fprintf(stderr, "bind() failed\n");
- exit(1);
+ close(vs->lsock);
+ vs->lsock = -1;
+ free(vs->display);
+ vs->display = NULL;
+ return -1;
}
if (listen(vs->lsock, 1) == -1) {
fprintf(stderr, "listen() failed\n");
- exit(1);
- }
-
- ret = qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read,
NULL, vs);
- if (ret == -1) {
- exit(1);
- }
+ close(vs->lsock);
+ vs->lsock = -1;
+ free(vs->display);
+ vs->display = NULL;
+ return -1;
+ }
+
+ if (qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read,
NULL, vs) < 0)
+ return -1;
return ntohs(iaddr.sin_port);
}
@@ -1640,31 +2511,3 @@ int vnc_start_viewer(int port)
}
}
-unsigned int seed;
-
-static int make_challenge(unsigned char *random, int size)
-{
-
- set_seed(&seed);
- get_random(size, random);
-
- return 0;
-}
-
-static void set_seed(unsigned int *seedp)
-{
- *seedp += (unsigned int)(time(NULL)+getpid()+getpid()*987654+rand());
- srand(*seedp);
-
- return;
-}
-
-static void get_random(int len, unsigned char *buf)
-{
- int i;
-
- for (i=0; i<len; i++)
- buf[i] = (int) (256.0*rand()/(RAND_MAX+1.0));
-
- return;
-}
diff -r c17bfb091790 -r a07288a84785 tools/ioemu/xenstore.c
--- a/tools/ioemu/xenstore.c Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/ioemu/xenstore.c Tue Oct 30 15:34:44 2007 -0600
@@ -17,7 +17,7 @@
#include <sys/stat.h>
#include <fcntl.h>
-static struct xs_handle *xsh = NULL;
+struct xs_handle *xsh = NULL;
static char *media_filename[MAX_DISKS + MAX_SCSI_DISKS];
static QEMUTimer *insert_timer = NULL;
@@ -303,12 +303,19 @@ void xenstore_process_logdirty_event(voi
logdirty_bitmap_size *= sizeof (unsigned long); /* bytes */
/* Map the shared-memory segment */
- if ((shmid = shmget(key,
- 2 * logdirty_bitmap_size,
- S_IRUSR|S_IWUSR)) == -1
- || (seg = shmat(shmid, NULL, 0)) == (void *)-1) {
- fprintf(logfile, "Log-dirty: can't map segment %16.16llx (%s)\n",
- (unsigned long long) key, strerror(errno));
+ fprintf(logfile, "%s: key=%16.16llx size=%d\n", __FUNCTION__,
+ (unsigned long long)key, logdirty_bitmap_size);
+ shmid = shmget(key, 2 * logdirty_bitmap_size, S_IRUSR|S_IWUSR);
+ if (shmid == -1) {
+ fprintf(logfile, "Log-dirty: shmget failed: segment %16.16llx "
+ "(%s)\n", (unsigned long long)key, strerror(errno));
+ exit(1);
+ }
+
+ seg = shmat(shmid, NULL, 0);
+ if (seg == (void *)-1) {
+ fprintf(logfile, "Log-dirty: shmat failed: segment %16.16llx "
+ "(%s)\n", (unsigned long long)key, strerror(errno));
exit(1);
}
@@ -318,6 +325,9 @@ void xenstore_process_logdirty_event(voi
if (logdirty_bitmap_size != *(uint32_t *)seg) {
fprintf(logfile, "Log-dirty: got %u, calc %lu\n",
*(uint32_t *)seg, logdirty_bitmap_size);
+ /* Stale key: wait for next watch */
+ shmdt(seg);
+ seg = NULL;
return;
}
@@ -478,9 +488,8 @@ void xenstore_write_vncport(int display)
free(buf);
}
-int xenstore_read_vncpasswd(int domid)
-{
- extern char vncpasswd[64];
+int xenstore_read_vncpasswd(int domid, char *pwbuf, size_t pwbuflen)
+{
char *buf = NULL, *path, *uuid = NULL, *passwd = NULL;
unsigned int i, len, rc = 0;
@@ -506,16 +515,17 @@ int xenstore_read_vncpasswd(int domid)
passwd = xs_read(xsh, XBT_NULL, buf, &len);
if (passwd == NULL) {
fprintf(logfile, "xs_read(): vncpasswd get error. %s.\n", buf);
+ pwbuf[0] = '\0';
free(uuid);
free(path);
return rc;
}
- for (i=0; i<len && i<63; i++) {
- vncpasswd[i] = passwd[i];
- passwd[i] = '\0';
- }
- vncpasswd[len] = '\0';
+ for (i=0; i<len && i<pwbuflen; i++) {
+ pwbuf[i] = passwd[i];
+ }
+ pwbuf[len < (pwbuflen-1) ? len : (pwbuflen-1)] = '\0';
+ passwd[0] = '\0';
pasprintf(&buf, "%s/vncpasswd", uuid);
if (xs_write(xsh, XBT_NULL, buf, passwd, len) == 0) {
fprintf(logfile, "xs_write() vncpasswd failed.\n");
@@ -724,7 +734,7 @@ int xenstore_vm_write(int domid, char *k
pasprintf(&buf, "%s/%s", path, key);
rc = xs_write(xsh, XBT_NULL, buf, value, strlen(value));
- if (rc) {
+ if (rc == 0) {
fprintf(logfile, "xs_write(%s, %s): write error\n", buf, key);
goto out;
}
diff -r c17bfb091790 -r a07288a84785 tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/libxc/xc_domain.c Tue Oct 30 15:34:44 2007 -0600
@@ -378,9 +378,9 @@ int xc_domain_setmaxmem(int xc_handle,
int xc_domain_pin_memory_cacheattr(int xc_handle,
uint32_t domid,
- unsigned long start,
- unsigned long end,
- unsigned int type)
+ uint64_t start,
+ uint64_t end,
+ uint32_t type)
{
DECLARE_DOMCTL;
domctl.cmd = XEN_DOMCTL_pin_mem_cacheattr;
diff -r c17bfb091790 -r a07288a84785 tools/libxc/xc_domain_restore.c
--- a/tools/libxc/xc_domain_restore.c Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/libxc/xc_domain_restore.c Tue Oct 30 15:34:44 2007 -0600
@@ -169,7 +169,8 @@ static int uncanonicalize_pagetable(int
/* Load the p2m frame list, plus potential extended info chunk */
-static xen_pfn_t *load_p2m_frame_list(int io_fd, int *pae_extended_cr3)
+static xen_pfn_t *load_p2m_frame_list(
+ int io_fd, int *pae_extended_cr3, int *ext_vcpucontext)
{
xen_pfn_t *p2m_frame_list;
vcpu_guest_context_either_t ctxt;
@@ -200,7 +201,8 @@ static xen_pfn_t *load_p2m_frame_list(in
/* 4-character chunk signature + 4-byte remaining chunk size. */
if ( !read_exact(io_fd, chunk_sig, sizeof(chunk_sig)) ||
- !read_exact(io_fd, &chunk_bytes, sizeof(chunk_bytes)) )
+ !read_exact(io_fd, &chunk_bytes, sizeof(chunk_bytes)) ||
+ (tot_bytes < (chunk_bytes + 8)) )
{
ERROR("read extended-info chunk signature failed");
return NULL;
@@ -240,6 +242,10 @@ static xen_pfn_t *load_p2m_frame_list(in
& (1UL << VMASST_TYPE_pae_extended_cr3) )
*pae_extended_cr3 = 1;
}
+ else if ( !strncmp(chunk_sig, "extv", 4) )
+ {
+ *ext_vcpucontext = 1;
+ }
/* Any remaining bytes of this chunk: read and discard. */
while ( chunk_bytes )
@@ -289,7 +295,7 @@ int xc_domain_restore(int xc_handle, int
unsigned int hvm, unsigned int pae)
{
DECLARE_DOMCTL;
- int rc = 1, i, j, n, m, pae_extended_cr3 = 0;
+ int rc = 1, frc, i, j, n, m, pae_extended_cr3 = 0, ext_vcpucontext = 0;
unsigned long mfn, pfn;
unsigned int prev_pc, this_pc;
int verify = 0;
@@ -373,7 +379,8 @@ int xc_domain_restore(int xc_handle, int
if ( !hvm )
{
/* Load the p2m frame list, plus potential extended info chunk */
- p2m_frame_list = load_p2m_frame_list(io_fd, &pae_extended_cr3);
+ p2m_frame_list = load_p2m_frame_list(
+ io_fd, &pae_extended_cr3, &ext_vcpucontext);
if ( !p2m_frame_list )
goto out;
@@ -382,13 +389,12 @@ int xc_domain_restore(int xc_handle, int
domctl.domain = dom;
domctl.cmd = XEN_DOMCTL_set_address_size;
domctl.u.address_size.size = guest_width * 8;
- rc = do_domctl(xc_handle, &domctl);
- if ( rc != 0 )
+ frc = do_domctl(xc_handle, &domctl);
+ if ( frc != 0 )
{
ERROR("Unable to set guest address size.");
goto out;
}
- rc = 1;
}
/* We want zeroed memory so use calloc rather than malloc. */
@@ -713,18 +719,19 @@ int xc_domain_restore(int xc_handle, int
goto out;
}
- if ( (rc = xc_set_hvm_param(xc_handle, dom,
- HVM_PARAM_IOREQ_PFN, magic_pfns[0]))
- || (rc = xc_set_hvm_param(xc_handle, dom,
- HVM_PARAM_BUFIOREQ_PFN, magic_pfns[1]))
- || (rc = xc_set_hvm_param(xc_handle, dom,
- HVM_PARAM_STORE_PFN, magic_pfns[2]))
- || (rc = xc_set_hvm_param(xc_handle, dom,
- HVM_PARAM_PAE_ENABLED, pae))
- || (rc = xc_set_hvm_param(xc_handle, dom,
- HVM_PARAM_STORE_EVTCHN, store_evtchn)) )
- {
- ERROR("error setting HVM params: %i", rc);
+ if ( (frc = xc_set_hvm_param(xc_handle, dom,
+ HVM_PARAM_IOREQ_PFN, magic_pfns[0]))
+ || (frc = xc_set_hvm_param(xc_handle, dom,
+ HVM_PARAM_BUFIOREQ_PFN, magic_pfns[1]))
+ || (frc = xc_set_hvm_param(xc_handle, dom,
+ HVM_PARAM_STORE_PFN, magic_pfns[2]))
+ || (frc = xc_set_hvm_param(xc_handle, dom,
+ HVM_PARAM_PAE_ENABLED, pae))
+ || (frc = xc_set_hvm_param(xc_handle, dom,
+ HVM_PARAM_STORE_EVTCHN,
+ store_evtchn)) )
+ {
+ ERROR("error setting HVM params: %i", frc);
goto out;
}
*store_mfn = magic_pfns[2];
@@ -750,10 +757,15 @@ int xc_domain_restore(int xc_handle, int
goto out;
}
- rc = xc_domain_hvm_setcontext(xc_handle, dom, hvm_buf, rec_len);
- if ( rc )
+ frc = xc_domain_hvm_setcontext(xc_handle, dom, hvm_buf, rec_len);
+ if ( frc )
+ {
ERROR("error setting the HVM context");
-
+ goto out;
+ }
+
+ /* HVM success! */
+ rc = 0;
goto out;
}
@@ -929,7 +941,7 @@ int xc_domain_restore(int xc_handle, int
{
unsigned int count = 0;
unsigned long *pfntab;
- int nr_frees, rc;
+ int nr_frees;
if ( !read_exact(io_fd, &count, sizeof(count)) ||
(count > (1U << 28)) ) /* up to 1TB of address space */
@@ -973,10 +985,10 @@ int xc_domain_restore(int xc_handle, int
};
set_xen_guest_handle(reservation.extent_start, pfntab);
- if ( (rc = xc_memory_op(xc_handle, XENMEM_decrease_reservation,
- &reservation)) != nr_frees )
- {
- ERROR("Could not decrease reservation : %d", rc);
+ if ( (frc = xc_memory_op(xc_handle, XENMEM_decrease_reservation,
+ &reservation)) != nr_frees )
+ {
+ ERROR("Could not decrease reservation : %d", frc);
goto out;
}
else
@@ -1091,13 +1103,29 @@ int xc_domain_restore(int xc_handle, int
domctl.domain = (domid_t)dom;
domctl.u.vcpucontext.vcpu = i;
set_xen_guest_handle(domctl.u.vcpucontext.ctxt, &ctxt.c);
- rc = xc_domctl(xc_handle, &domctl);
- if ( rc != 0 )
+ frc = xc_domctl(xc_handle, &domctl);
+ if ( frc != 0 )
{
ERROR("Couldn't build vcpu%d", i);
goto out;
}
- rc = 1;
+
+ if ( !ext_vcpucontext )
+ continue;
+ if ( !read_exact(io_fd, &domctl.u.ext_vcpucontext, 128) ||
+ (domctl.u.ext_vcpucontext.vcpu != i) )
+ {
+ ERROR("Error when reading extended ctxt %d", i);
+ goto out;
+ }
+ domctl.cmd = XEN_DOMCTL_set_ext_vcpucontext;
+ domctl.domain = dom;
+ frc = xc_domctl(xc_handle, &domctl);
+ if ( frc != 0 )
+ {
+ ERROR("Couldn't set extended vcpu%d info\n", i);
+ goto out;
+ }
}
if ( !read_exact(io_fd, shared_info_page, PAGE_SIZE) )
diff -r c17bfb091790 -r a07288a84785 tools/libxc/xc_domain_save.c
--- a/tools/libxc/xc_domain_save.c Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/libxc/xc_domain_save.c Tue Oct 30 15:34:44 2007 -0600
@@ -777,16 +777,18 @@ static xen_pfn_t *map_and_save_p2m_table
*/
{
unsigned long signature = ~0UL;
- uint32_t chunk_sz = ((guest_width==8)
- ? sizeof(ctxt.x64)
- : sizeof(ctxt.x32));
- uint32_t tot_sz = chunk_sz + 8;
- char chunk_sig[] = "vcpu";
+ uint32_t chunk1_sz = ((guest_width==8)
+ ? sizeof(ctxt.x64)
+ : sizeof(ctxt.x32));
+ uint32_t chunk2_sz = 0;
+ uint32_t tot_sz = (chunk1_sz + 8) + (chunk2_sz + 8);
if ( !write_exact(io_fd, &signature, sizeof(signature)) ||
- !write_exact(io_fd, &tot_sz, sizeof(tot_sz)) ||
- !write_exact(io_fd, &chunk_sig, 4) ||
- !write_exact(io_fd, &chunk_sz, sizeof(chunk_sz)) ||
- !write_exact(io_fd, &ctxt, chunk_sz) )
+ !write_exact(io_fd, &tot_sz, sizeof(tot_sz)) ||
+ !write_exact(io_fd, "vcpu", 4) ||
+ !write_exact(io_fd, &chunk1_sz, sizeof(chunk1_sz)) ||
+ !write_exact(io_fd, &ctxt, chunk1_sz) ||
+ !write_exact(io_fd, "extv", 4) ||
+ !write_exact(io_fd, &chunk2_sz, sizeof(chunk2_sz)) )
{
ERROR("write: extended info");
goto out;
@@ -830,6 +832,7 @@ int xc_domain_save(int xc_handle, int io
void (*qemu_flip_buffer)(int, int))
{
xc_dominfo_t info;
+ DECLARE_DOMCTL;
int rc = 1, frc, i, j, last_iter, iter = 0;
int live = (flags & XCFLAGS_LIVE);
@@ -1095,7 +1098,6 @@ int xc_domain_save(int xc_handle, int io
while ( N < p2m_size )
{
unsigned int this_pc = (N * 100) / p2m_size;
- int rc;
if ( (this_pc - prev_pc) >= 5 )
{
@@ -1107,10 +1109,10 @@ int xc_domain_save(int xc_handle, int io
{
/* Slightly wasteful to peek the whole array evey time,
but this is fast enough for the moment. */
- rc = xc_shadow_control(
+ frc = xc_shadow_control(
xc_handle, dom, XEN_DOMCTL_SHADOW_OP_PEEK, to_skip,
p2m_size, NULL, 0, NULL);
- if ( rc != p2m_size )
+ if ( frc != p2m_size )
{
ERROR("Error peeking shadow bitmap");
goto out;
@@ -1601,6 +1603,20 @@ int xc_domain_save(int xc_handle, int io
ERROR("Error when writing to state file (1) (errno %d)", errno);
goto out;
}
+
+ domctl.cmd = XEN_DOMCTL_get_ext_vcpucontext;
+ domctl.domain = dom;
+ domctl.u.ext_vcpucontext.vcpu = i;
+ if ( xc_domctl(xc_handle, &domctl) < 0 )
+ {
+ ERROR("No extended context for VCPU%d", i);
+ goto out;
+ }
+ if ( !write_exact(io_fd, &domctl.u.ext_vcpucontext, 128) )
+ {
+ ERROR("Error when writing to state file (2) (errno %d)", errno);
+ goto out;
+ }
}
/*
diff -r c17bfb091790 -r a07288a84785 tools/libxc/xc_misc.c
--- a/tools/libxc/xc_misc.c Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/libxc/xc_misc.c Tue Oct 30 15:34:44 2007 -0600
@@ -10,7 +10,7 @@ int xc_readconsolering(int xc_handle,
int xc_readconsolering(int xc_handle,
char **pbuffer,
unsigned int *pnr_chars,
- int clear)
+ int clear, int incremental, uint32_t *pindex)
{
int ret;
DECLARE_SYSCTL;
@@ -19,14 +19,24 @@ int xc_readconsolering(int xc_handle,
sysctl.cmd = XEN_SYSCTL_readconsole;
set_xen_guest_handle(sysctl.u.readconsole.buffer, buffer);
- sysctl.u.readconsole.count = nr_chars;
- sysctl.u.readconsole.clear = clear;
+ sysctl.u.readconsole.count = nr_chars;
+ sysctl.u.readconsole.clear = clear;
+ sysctl.u.readconsole.incremental = 0;
+ if ( pindex )
+ {
+ sysctl.u.readconsole.index = *pindex;
+ sysctl.u.readconsole.incremental = incremental;
+ }
if ( (ret = lock_pages(buffer, nr_chars)) != 0 )
return ret;
if ( (ret = do_sysctl(xc_handle, &sysctl)) == 0 )
+ {
*pnr_chars = sysctl.u.readconsole.count;
+ if ( pindex )
+ *pindex = sysctl.u.readconsole.index;
+ }
unlock_pages(buffer, nr_chars);
diff -r c17bfb091790 -r a07288a84785 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/libxc/xenctrl.h Tue Oct 30 15:34:44 2007 -0600
@@ -549,7 +549,7 @@ int xc_readconsolering(int xc_handle,
int xc_readconsolering(int xc_handle,
char **pbuffer,
unsigned int *pnr_chars,
- int clear);
+ int clear, int incremental, uint32_t *pindex);
int xc_send_debug_keys(int xc_handle, char *keys);
@@ -616,9 +616,9 @@ int xc_domain_iomem_permission(int xc_ha
int xc_domain_pin_memory_cacheattr(int xc_handle,
uint32_t domid,
- unsigned long start,
- unsigned long end,
- unsigned int type);
+ uint64_t start,
+ uint64_t end,
+ uint32_t type);
unsigned long xc_make_page_below_4G(int xc_handle, uint32_t domid,
unsigned long mfn);
diff -r c17bfb091790 -r a07288a84785 tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/python/xen/lowlevel/xc/xc.c Tue Oct 30 15:34:44 2007 -0600
@@ -716,17 +716,19 @@ static PyObject *pyxc_readconsolering(Xc
PyObject *args,
PyObject *kwds)
{
- unsigned int clear = 0;
+ unsigned int clear = 0, index = 0, incremental = 0;
char _str[32768], *str = _str;
unsigned int count = 32768;
int ret;
- static char *kwd_list[] = { "clear", NULL };
-
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwd_list, &clear) )
- return NULL;
-
- ret = xc_readconsolering(self->xc_handle, &str, &count, clear);
+ static char *kwd_list[] = { "clear", "index", "incremental", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|iii", kwd_list,
+ &clear, &index, &incremental) )
+ return NULL;
+
+ ret = xc_readconsolering(self->xc_handle, &str, &count, clear,
+ incremental, &index);
if ( ret < 0 )
return pyxc_error_to_exception();
diff -r c17bfb091790 -r a07288a84785 tools/python/xen/util/acmpolicy.py
--- a/tools/python/xen/util/acmpolicy.py Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/python/xen/util/acmpolicy.py Tue Oct 30 15:34:44 2007 -0600
@@ -46,7 +46,7 @@ ACM_POLICY_UNDEFINED = 15
ACM_POLICY_UNDEFINED = 15
-ACM_SCHEMA_FILE = "/etc/xen/acm-security/policies/security_policy.xsd"
+ACM_SCHEMA_FILE = ACM_POLICIES_DIR + "security_policy.xsd"
ACM_LABEL_UNLABELED = "__UNLABELED__"
ACM_LABEL_UNLABELED_DISPLAY = "unlabeled"
@@ -263,7 +263,7 @@ class ACMPolicy(XSPolicy):
else:
#Not loaded in HV
self.dom = acmpol_new.dom
- self.compile()
+ rc = self.compile()
return rc, errors
@@ -842,9 +842,15 @@ class ACMPolicy(XSPolicy):
rc, mapfile, bin_pol = self.policy_create_map_and_bin()
if rc == 0:
- rc = self.__write_to_file(".map", mapfile)
- if rc != 0:
- log.error("Error writing map file")
+ try:
+ security.mapfile_lock()
+
+ rc = self.__write_to_file(".map", mapfile)
+ if rc != 0:
+ log.error("Error writing map file")
+
+ finally:
+ security.mapfile_unlock()
if rc == 0:
rc = self.__write_to_file(".bin", bin_pol)
@@ -919,7 +925,7 @@ class ACMPolicy(XSPolicy):
def policy_get_domain_label_formatted(self, domid):
label = self.policy_get_domain_label(domid)
if label == "":
- return ""
+ label = ACM_LABEL_UNLABELED
return "%s:%s:%s" % (xsconstants.ACM_POLICY_ID, self.get_name(), label)
def policy_get_domain_label_by_ssidref_formatted(self, ssidref):
@@ -941,6 +947,8 @@ class ACMPolicy(XSPolicy):
secpolcode = ACM_POLICY_UNDEFINED
unknown_ste = set()
unknown_chw = set()
+ unlabeled_ste = "__NULL_LABEL__"
+ unlabeled_chw = "__NULL_LABEL__"
rc = self.validate()
if rc:
@@ -979,6 +987,7 @@ class ACMPolicy(XSPolicy):
vms_with_chws.sort()
if ACM_LABEL_UNLABELED in vms_with_chws:
+ unlabeled_chw = ACM_LABEL_UNLABELED
vms_with_chws.remove(ACM_LABEL_UNLABELED) ; # @1
vms_with_stes = []
@@ -996,6 +1005,7 @@ class ACMPolicy(XSPolicy):
vms_with_stes.sort()
if ACM_LABEL_UNLABELED in vms_with_stes:
+ unlabeled_ste = ACM_LABEL_UNLABELED
vms_with_stes.remove(ACM_LABEL_UNLABELED) ; # @2
resnames = self.policy_get_resourcelabel_names()
@@ -1050,7 +1060,8 @@ class ACMPolicy(XSPolicy):
if len(vms_with_chws) > 0:
mapfile += \
- "LABEL->SSID ANY CHWALL __NULL_LABEL__ %x\n" % 0
+ "LABEL->SSID ANY CHWALL %-20s %x\n" % \
+ (unlabeled_chw, 0)
i = 0
for v in vms_with_chws:
mapfile += \
@@ -1061,7 +1072,8 @@ class ACMPolicy(XSPolicy):
if len(vms_with_stes) > 0 or len(resnames) > 0:
mapfile += \
- "LABEL->SSID ANY STE __NULL_LABEL__ %08x\n" % 0
+ "LABEL->SSID ANY STE %-20s %08x\n" % \
+ (unlabeled_ste, 0)
i = 0
for v in vms_with_stes:
mapfile += \
@@ -1260,9 +1272,11 @@ class ACMPolicy(XSPolicy):
if len(unknown_ste) > 0:
log.info("The following STEs in VM/res labels were unknown:" \
" %s" % list(unknown_ste))
+ rc = -xsconstants.XSERR_BAD_LABEL
if len(unknown_chw) > 0:
log.info("The following Ch. Wall types in labels were unknown:" \
" %s" % list(unknown_chw))
+ rc = -xsconstants.XSERR_BAD_LABEL
return rc, mapfile, all_bin.tostring()
def get_enforced_binary(self):
diff -r c17bfb091790 -r a07288a84785 tools/python/xen/util/xsm/acm/acm.py
--- a/tools/python/xen/util/xsm/acm/acm.py Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/python/xen/util/xsm/acm/acm.py Tue Oct 30 15:34:44 2007 -0600
@@ -27,6 +27,7 @@ from xen.lowlevel import acm
from xen.lowlevel import acm
from xen.xend import sxp
from xen.xend import XendConstants
+from xen.xend import XendOptions
from xen.xend.XendLogging import log
from xen.xend.XendError import VmError
from xen.util import dictio, xsconstants
@@ -655,6 +656,10 @@ def get_res_security_details(resource):
if policy == 'NULL':
log.info("Resource label for "+resource+" not in file, using DEFAULT.")
return default_security_details()
+
+ if policytype != xsconstants.ACM_POLICY_ID:
+ raise VmError("Unknown policy type '%s in label for resource '%s'" %
+ (policytype, resource))
# is this resource label for the running policy?
if policy == active_policy:
@@ -1077,9 +1082,14 @@ def set_resource_label(resource, policyt
if reslabel != "":
new_entry = { resource : tuple([policytype, policyref, reslabel])}
access_control.update(new_entry)
+ command = "add"
+ reslbl = ":".join([policytype, policyref, reslabel])
else:
if access_control.has_key(resource):
del access_control[resource]
+ command = "remove"
+ reslbl = ""
+ run_resource_label_change_script(resource, reslbl, command)
dictio.dict_write(access_control, "resources", res_label_filename)
finally:
resfile_unlock()
@@ -1269,6 +1279,7 @@ def change_acm_policy(bin_pol, del_array
label = reslabel_map[label]
elif label not in polnew_reslabels:
policytype = xsconstants.INVALID_POLICY_PREFIX + policytype
+ run_resource_label_change_script(key, "", "remove")
# Update entry
access_control[key] = \
tuple([ policytype, new_policyname, label ])
@@ -1373,11 +1384,24 @@ def get_security_label(self, xspol=None)
from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
xspol = XSPolicyAdminInstance().get_loaded_policy()
- if domid == 0:
- if xspol:
- label = xspol.policy_get_domain_label_formatted(domid)
- else:
- label = ""
- else:
- label = self.info.get('security_label', '')
+ label = ""
+ if xspol:
+ label = xspol.policy_get_domain_label_formatted(domid)
+ if domid != 0:
+ label = self.info.get('security_label', label)
return label
+
+def run_resource_label_change_script(resource, label, command):
+ script = XendOptions.instance().get_resource_label_change_script()
+ if script:
+ parms = {
+ 'resource' : resource,
+ 'label' : label,
+ 'command' : command,
+ }
+ log.info("Running resource label change script %s: %s" %
+ (script, parms))
+ parms.update(os.environ)
+ os.spawnve(os.P_NOWAIT, script[0], script, parms)
+ else:
+ log.info("No script given for relabeling of resources.")
diff -r c17bfb091790 -r a07288a84785 tools/python/xen/xend/XendCheckpoint.py
--- a/tools/python/xen/xend/XendCheckpoint.py Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/python/xen/xend/XendCheckpoint.py Tue Oct 30 15:34:44 2007 -0600
@@ -6,6 +6,7 @@
# this archive for more details.
import os
+import os.path
import re
import string
import threading
@@ -108,7 +109,7 @@ def save(fd, dominfo, network, live, dst
forkHelper(cmd, fd, saveInputHandler, False)
# put qemu device model state
- if hvm:
+ if os.path.exists("/var/lib/xen/qemu-save.%d" % dominfo.getDomid()):
write_exact(fd, QEMU_SIGNATURE, "could not write qemu signature")
qemu_fd = os.open("/var/lib/xen/qemu-save.%d" % dominfo.getDomid(),
os.O_RDONLY)
@@ -245,6 +246,8 @@ def restore(xd, fd, dominfo = None, paus
raise XendError('Could not read console MFN')
# get qemu state and create a tmp file for dm restore
+ # Even PV guests may have QEMU stat, but its not currently
+ # used so only bother with HVM currently.
if is_hvm:
qemu_signature = read_exact(fd, len(QEMU_SIGNATURE),
"invalid device model signature read")
diff -r c17bfb091790 -r a07288a84785 tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/python/xen/xend/XendConfig.py Tue Oct 30 15:34:44 2007 -0600
@@ -28,10 +28,12 @@ from xen.xend.XendDevices import XendDev
from xen.xend.XendDevices import XendDevices
from xen.xend.PrettyPrint import prettyprintstring
from xen.xend.XendConstants import DOM_STATE_HALTED
+from xen.xend.xenstore.xstransact import xstransact
from xen.xend.server.BlktapController import blktap_disk_types
from xen.xend.server.netif import randomMAC
from xen.util.blkif import blkdev_name_to_number
from xen.util import xsconstants
+import xen.util.auxbin
log = logging.getLogger("xend.XendConfig")
log.setLevel(logging.WARN)
@@ -126,7 +128,7 @@ XENAPI_PLATFORM_CFG = [ 'acpi', 'apic',
'fda', 'fdb', 'keymap', 'isa', 'localtime', 'monitor',
'nographic', 'pae', 'rtc_timeoffset', 'serial', 'sdl',
'soundhw','stdvga', 'usb', 'usbdevice', 'vnc',
- 'vncconsole', 'vncdisplay', 'vnclisten',
+ 'vncconsole', 'vncdisplay', 'vnclisten', 'timer_mode',
'vncpasswd', 'vncunused', 'xauthority', 'pci', 'vhpt']
# Xen API console 'other_config' keys.
@@ -233,8 +235,6 @@ LEGACY_XENSTORE_VM_PARAMS = [
'on_xend_start',
'on_xend_stop',
]
-
-DEFAULT_DM = '/usr/lib/xen/bin/qemu-dm'
##
## Config Choices
@@ -393,13 +393,14 @@ class XendConfig(dict):
self['name_label'] = 'Domain-' + self['uuid']
def _platform_sanity_check(self):
+ if 'keymap' not in self['platform'] and
XendOptions.instance().get_keymap():
+ self['platform']['keymap'] = XendOptions.instance().get_keymap()
+
+ if self.is_hvm() or self.has_rfb():
+ if 'device_model' not in self['platform']:
+ self['platform']['device_model'] =
xen.util.auxbin.pathTo("qemu-dm")
+
if self.is_hvm():
- if 'keymap' not in self['platform'] and
XendOptions.instance().get_keymap():
- self['platform']['keymap'] =
XendOptions.instance().get_keymap()
-
- if 'device_model' not in self['platform']:
- self['platform']['device_model'] = DEFAULT_DM
-
# Compatibility hack, can go away soon.
if 'soundhw' not in self['platform'] and \
self['platform'].get('enable_audio'):
@@ -744,16 +745,7 @@ class XendConfig(dict):
# coalesce hvm vnc frame buffer with vfb config
if self.is_hvm() and int(self['platform'].get('vnc', 0)) != 0:
# add vfb device if it isn't there already
- has_rfb = False
- for console_uuid in self['console_refs']:
- if self['devices'][console_uuid][1].get('protocol') == 'rfb':
- has_rfb = True
- break
- if self['devices'][console_uuid][0] == 'vfb':
- has_rfb = True
- break
-
- if not has_rfb:
+ if not self.has_rfb():
dev_config = ['vfb']
dev_config.append(['type', 'vnc'])
# copy VNC related params from platform config to vfb dev conf
@@ -764,6 +756,14 @@ class XendConfig(dict):
self.device_add('vfb', cfg_sxp = dev_config)
+
+ def has_rfb(self):
+ for console_uuid in self['console_refs']:
+ if self['devices'][console_uuid][1].get('protocol') == 'rfb':
+ return True
+ if self['devices'][console_uuid][0] == 'vfb':
+ return True
+ return False
def _sxp_to_xapi_unsupported(self, sxp_cfg):
"""Read in an SXP configuration object and populate
@@ -942,36 +942,43 @@ class XendConfig(dict):
# Marshall devices (running or from configuration)
if not ignore_devices:
- for cls in XendDevices.valid_devices():
- found = False
+ txn = xstransact()
+ try:
+ for cls in XendDevices.valid_devices():
+ found = False
- # figure if there is a dev controller is valid and running
- if domain and domain.getDomid() != None:
- try:
- controller = domain.getDeviceController(cls)
- configs = controller.configurations()
- for config in configs:
- if sxp.name(config) in ('vbd', 'tap'):
- # The bootable flag is never written to the
- # store as part of the device config.
- dev_uuid = sxp.child_value(config, 'uuid')
- dev_type, dev_cfg = self['devices'][dev_uuid]
- is_bootable = dev_cfg.get('bootable', 0)
- config.append(['bootable', int(is_bootable)])
-
- sxpr.append(['device', config])
-
- found = True
- except:
- log.exception("dumping sxp from device controllers")
- pass
+ # figure if there is a dev controller is valid and running
+ if domain and domain.getDomid() != None:
+ try:
+ controller = domain.getDeviceController(cls)
+ configs = controller.configurations(txn)
+ for config in configs:
+ if sxp.name(config) in ('vbd', 'tap'):
+ # The bootable flag is never written to the
+ # store as part of the device config.
+ dev_uuid = sxp.child_value(config, 'uuid')
+ dev_type, dev_cfg =
self['devices'][dev_uuid]
+ is_bootable = dev_cfg.get('bootable', 0)
+ config.append(['bootable',
int(is_bootable)])
+
+ sxpr.append(['device', config])
+
+ found = True
+ except:
+ log.exception("dumping sxp from device
controllers")
+ pass
- # if we didn't find that device, check the existing config
- # for a device in the same class
- if not found:
- for dev_type, dev_info in self.all_devices_sxpr():
- if dev_type == cls:
- sxpr.append(['device', dev_info])
+ # if we didn't find that device, check the existing config
+ # for a device in the same class
+ if not found:
+ for dev_type, dev_info in self.all_devices_sxpr():
+ if dev_type == cls:
+ sxpr.append(['device', dev_info])
+
+ txn.commit()
+ except:
+ txn.abort()
+ raise
return sxpr
diff -r c17bfb091790 -r a07288a84785 tools/python/xen/xend/XendConstants.py
--- a/tools/python/xen/xend/XendConstants.py Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/python/xen/xend/XendConstants.py Tue Oct 30 15:34:44 2007 -0600
@@ -46,6 +46,7 @@ HVM_PARAM_NVRAM_FD = 7
HVM_PARAM_NVRAM_FD = 7
HVM_PARAM_VHPT_SIZE = 8
HVM_PARAM_BUFPIOREQ_PFN = 9
+HVM_PARAM_TIMER_MODE = 10
restart_modes = [
"restart",
diff -r c17bfb091790 -r a07288a84785 tools/python/xen/xend/XendDomain.py
--- a/tools/python/xen/xend/XendDomain.py Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/python/xen/xend/XendDomain.py Tue Oct 30 15:34:44 2007 -0600
@@ -393,13 +393,22 @@ class XendDomain:
@rtype: None
"""
+ txn = xstransact()
+ try:
+ self._refreshTxn(txn, refresh_shutdown)
+ txn.commit()
+ except:
+ txn.abort()
+ raise
+
+ def _refreshTxn(self, transaction, refresh_shutdown):
running = self._running_domains()
# Add domains that are not already tracked but running in Xen,
# and update domain state for those that are running and tracked.
for dom in running:
domid = dom['domid']
if domid in self.domains:
- self.domains[domid].update(dom, refresh_shutdown)
+ self.domains[domid].update(dom, refresh_shutdown, transaction)
elif domid not in self.domains and dom['dying'] != 1:
try:
new_dom = XendDomainInfo.recreate(dom, False)
diff -r c17bfb091790 -r a07288a84785 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/python/xen/xend/XendDomainInfo.py Tue Oct 30 15:34:44 2007 -0600
@@ -819,12 +819,15 @@ class XendDomainInfo:
self._update_consoles()
- def _update_consoles(self):
+ def _update_consoles(self, transaction = None):
if self.domid == None or self.domid == 0:
return
# Update VT100 port if it exists
- self.console_port = self.readDom('console/port')
+ if transaction is None:
+ self.console_port = self.readDom('console/port')
+ else:
+ self.console_port = self.readDomTxn(transaction, 'console/port')
if self.console_port is not None:
serial_consoles = self.info.console_get_all('vt100')
if not serial_consoles:
@@ -837,7 +840,10 @@ class XendDomainInfo:
# Update VNC port if it exists and write to xenstore
- vnc_port = self.readDom('console/vnc-port')
+ if transaction is None:
+ vnc_port = self.readDom('console/vnc-port')
+ else:
+ vnc_port = self.readDomTxn(transaction, 'console/vnc-port')
if vnc_port is not None:
for dev_uuid, (dev_type, dev_info) in self.info['devices'].items():
if dev_type == 'vfb':
@@ -872,6 +878,27 @@ class XendDomainInfo:
def storeVm(self, *args):
return xstransact.Store(self.vmpath, *args)
+
+ def _readVmTxn(self, transaction, *args):
+ paths = map(lambda x: self.vmpath + "/" + x, args)
+ return transaction.read(*paths)
+
+ def _writeVmTxn(self, transaction, *args):
+ paths = map(lambda x: self.vmpath + "/" + x, args)
+ return transaction.write(*paths)
+
+ def _removeVmTxn(self, transaction, *args):
+ paths = map(lambda x: self.vmpath + "/" + x, args)
+ return transaction.remove(*paths)
+
+ def _gatherVmTxn(self, transaction, *args):
+ paths = map(lambda x: self.vmpath + "/" + x, args)
+ return transaction.gather(paths)
+
+ def storeVmTxn(self, transaction, *args):
+ paths = map(lambda x: self.vmpath + "/" + x, args)
+ return transaction.store(*paths)
+
#
# Function to update xenstore /dom/*
#
@@ -890,6 +917,28 @@ class XendDomainInfo:
def storeDom(self, *args):
return xstransact.Store(self.dompath, *args)
+
+
+ def readDomTxn(self, transaction, *args):
+ paths = map(lambda x: self.vmpath + "/" + x, args)
+ return transaction.read(*paths)
+
+ def gatherDomTxn(self, transaction, *args):
+ paths = map(lambda x: self.vmpath + "/" + x, args)
+ return transaction.gather(*paths)
+
+ def _writeDomTxn(self, transaction, *args):
+ paths = map(lambda x: self.vmpath + "/" + x, args)
+ return transaction.write(*paths)
+
+ def _removeDomTxn(self, transaction, *args):
+ paths = map(lambda x: self.vmpath + "/" + x, args)
+ return transaction.remove(*paths)
+
+ def storeDomTxn(self, transaction, *args):
+ paths = map(lambda x: self.vmpath + "/" + x, args)
+ return transaction.store(*paths)
+
def _recreateDom(self):
complete(self.dompath, lambda t: self._recreateDomFunc(t))
@@ -916,8 +965,15 @@ class XendDomainInfo:
else:
to_store[n] = str(v)
+ # Figure out if we need to tell xenconsoled to ignore this guest's
+ # console - device model will handle console if it is running
+ constype = "ioemu"
+ if 'device_model' not in self.info['platform']:
+ constype = "xenconsoled"
+
f('console/port', self.console_port)
f('console/ring-ref', self.console_mfn)
+ f('console/type', constype)
f('store/port', self.store_port)
f('store/ring-ref', self.store_mfn)
@@ -1455,10 +1511,16 @@ class XendDomainInfo:
def _releaseDevices(self, suspend = False):
"""Release all domain's devices. Nothrow guarantee."""
- if suspend and self.image:
- self.image.destroy(suspend)
- return
-
+ if self.image:
+ try:
+ log.debug("Destroying device model")
+ self.image.destroyDeviceModel()
+ except Exception, e:
+ log.exception("Device model destroy failed %s" % str(e))
+ else:
+ log.debug("No device model")
+
+ log.debug("Releasing devices")
t = xstransact("%s/device" % self.dompath)
for devclass in XendDevices.valid_devices():
for dev in t.list(devclass):
@@ -1583,6 +1645,11 @@ class XendDomainInfo:
self._recreateDom()
+ # Set timer configration of domain
+ if hvm:
+ xc.hvm_set_param(self.domid, HVM_PARAM_TIMER_MODE,
+ long(self.info["platform"].get("timer_mode")))
+
# Set maximum number of vcpus in domain
xc.domain_max_vcpus(self.domid, int(self.info['VCPUs_max']))
@@ -1709,11 +1776,6 @@ class XendDomainInfo:
bootloader_tidy(self)
if self.image:
- try:
- self.image.destroy()
- except:
- log.exception(
- "XendDomainInfo.cleanup: image.destroy() failed.")
self.image = None
try:
@@ -1761,10 +1823,9 @@ class XendDomainInfo:
self.console_mfn = console_mfn
self._introduceDomain()
- if self.info.is_hvm():
- self.image = image.create(self, self.info)
- if self.image:
- self.image.createDeviceModel(True)
+ self.image = image.create(self, self.info)
+ if self.image:
+ self.image.createDeviceModel(True)
self._storeDomDetails()
self._registerWatches()
self.refreshShutdown()
@@ -1882,8 +1943,8 @@ class XendDomainInfo:
ResumeDomain(self.domid)
except:
log.exception("XendDomainInfo.resume: xc.domain_resume failed on
domain %s." % (str(self.domid)))
- if self.is_hvm():
- self.image.resumeDeviceModel()
+ self.image.resumeDeviceModel()
+ log.debug("XendDomainInfo.resumeDomain: completed")
#
@@ -2211,7 +2272,7 @@ class XendDomainInfo:
(" as domain %s" % str(dom.domid)) or ""))
- def update(self, info = None, refresh = True):
+ def update(self, info = None, refresh = True, transaction = None):
"""Update with info from xc.domain_getinfo().
"""
log.trace("XendDomainInfo.update(%s) on domain %s", info,
@@ -2234,7 +2295,7 @@ class XendDomainInfo:
# TODO: we should eventually get rid of old_dom_states
self.info.update_config(info)
- self._update_consoles()
+ self._update_consoles(transaction)
if refresh:
self.refreshShutdown(info)
diff -r c17bfb091790 -r a07288a84785 tools/python/xen/xend/XendOptions.py
--- a/tools/python/xen/xend/XendOptions.py Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/python/xen/xend/XendOptions.py Tue Oct 30 15:34:44 2007 -0600
@@ -102,6 +102,15 @@ class XendOptions:
"""Default interface to listen for VNC connections on"""
xend_vnc_listen_default = '127.0.0.1'
+ """Use of TLS mode in QEMU VNC server"""
+ xend_vnc_tls = 0
+
+ """x509 certificate directory for QEMU VNC server"""
+ xend_vnc_x509_cert_dir = "/etc/xen/vnc"
+
+ """Verify incoming client x509 certs"""
+ xend_vnc_x509_verify = 0
+
"""Default session storage path."""
xend_domains_path_default = '/var/lib/xend/domains'
@@ -277,6 +286,26 @@ class XendOptions:
def get_keymap(self):
return self.get_config_value('keymap', None)
+
+ def get_resource_label_change_script(self):
+ s = self.get_config_value('resource-label-change-script')
+ if s:
+ result = s.split(" ")
+ result[0] = os.path.join(osdep.scripts_dir, result[0])
+ return result
+ else:
+ return None
+
+
+ def get_vnc_tls(self):
+ return self.get_config_string('vnc-tls', self.xend_vnc_tls)
+
+ def get_vnc_x509_cert_dir(self):
+ return self.get_config_string('vnc-x509-cert-dir',
self.xend_vnc_x509_cert_dir)
+
+ def get_vnc_x509_verify(self):
+ return self.get_config_string('vnc-x509-verify',
self.xend_vnc_x509_verify)
+
class XendOptionsFile(XendOptions):
diff -r c17bfb091790 -r a07288a84785 tools/python/xen/xend/XendXSPolicyAdmin.py
--- a/tools/python/xen/xend/XendXSPolicyAdmin.py Tue Oct 30 11:33:55
2007 -0600
+++ b/tools/python/xen/xend/XendXSPolicyAdmin.py Tue Oct 30 15:34:44
2007 -0600
@@ -28,7 +28,6 @@ from xen.util.acmpolicy import ACMPolicy
from xen.util.acmpolicy import ACMPolicy
from xen.xend.XendError import SecurityError
-XS_MANAGED_POLICIES_FILE = "/etc/xen/acm-security/policies/managed_policies"
class XSPolicyAdmin:
""" The class that handles the managed policies in the system.
@@ -45,28 +44,19 @@ class XSPolicyAdmin:
on the system (currently '1')
"""
self.maxpolicies = maxpolicies
- try:
- self.policies = dictio.dict_read("managed_policies",
- XS_MANAGED_POLICIES_FILE)
+ self.policies = {}
+ self.xsobjs = {}
+
+ act_pol_name = self.get_hv_loaded_policy_name()
+
+ ref = uuid.createString()
+ try:
+ self.xsobjs[ref] = ACMPolicy(name=act_pol_name, ref=ref)
+ self.policies[ref] = (act_pol_name, xsconstants.ACM_POLICY_ID)
except Exception, e:
- self.policies = {}
-
- self.xsobjs = {}
- for ref, data in self.policies.items():
- name = data[0]
- typ = data[1]
- try:
- if typ == xsconstants.ACM_POLICY_ID:
- try:
- self.xsobjs[ref] = ACMPolicy(name=name, ref=ref)
- except Exception, e:
- del self.policies[ref]
- else:
- del self.policies[ref]
- except Exception, e:
- log.error("XSPolicyAdmin: Could not find policy '%s': %s" %
- (name, str(e)))
- del self.policies[ref]
+ log.error("Could not find XML representation of policy '%s': "
+ "%s" % (act_pol_name,e))
+
log.debug("XSPolicyAdmin: Known policies: %s" % self.policies)
def isXSEnabled(self):
@@ -113,6 +103,7 @@ class XSPolicyAdmin:
if rc == 0:
self.rm_bootpolicy()
irc = self.activate_xspolicy(loadedpol, flags)
+ # policy is loaded; if setting the boot flag fails it's ok.
return (loadedpol, rc, errors)
try:
@@ -166,9 +157,6 @@ class XSPolicyAdmin:
xsconstants.ACM_POLICY_ID]) }
self.policies.update(new_entry)
self.xsobjs[ref] = acmpol
- dictio.dict_write(self.policies,
- "managed_policies",
- XS_MANAGED_POLICIES_FILE)
return (acmpol, xsconstants.XSERR_SUCCESS, errors)
def make_boot_policy(self, acmpol):
@@ -217,9 +205,6 @@ class XSPolicyAdmin:
if rc == xsconstants.XSERR_SUCCESS or force:
del self.policies[ref]
del self.xsobjs[ref]
- dictio.dict_write(self.policies,
- "managed_policies",
- XS_MANAGED_POLICIES_FILE)
rc = xsconstants.XSERR_SUCCESS
return rc
diff -r c17bfb091790 -r a07288a84785 tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/python/xen/xend/image.py Tue Oct 30 15:34:44 2007 -0600
@@ -17,7 +17,7 @@
#============================================================================
-import os, string
+import os, os.path, string
import re
import math
import time
@@ -31,6 +31,7 @@ from xen.xend.xenstore.xstransact import
from xen.xend.xenstore.xstransact import xstransact
from xen.xend.xenstore.xswatch import xswatch
from xen.xend import arch
+from xen.xend import XendOptions
xc = xen.lowlevel.xc.xc()
@@ -56,10 +57,9 @@ class ImageHandler:
defining in a subclass.
The method createDeviceModel() is called to create the domain device
- model if it needs one. The default is to do nothing.
-
- The method destroy() is called when the domain is destroyed.
- The default is to do nothing.
+ model.
+
+ The method destroyDeviceModel() is called to reap the device model
"""
ostype = None
@@ -91,6 +91,15 @@ 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.pid = None
+
+
def cleanupBootloading(self):
if self.bootloader:
@@ -173,25 +182,158 @@ class ImageHandler:
"""Build the domain. Define in subclass."""
raise NotImplementedError()
+ # Return a list of cmd line args to the device models based on the
+ # xm config file
+ def parseDeviceModelArgs(self, vmConfig):
+ ret = ["-domain-name", str(self.vm.info['name_label'])]
+
+ # Find RFB console device, and if it exists, make QEMU enable
+ # the VNC console.
+ if int(vmConfig['platform'].get('nographic', 0)) != 0:
+ # skip vnc init if nographic is set
+ ret.append('-nographic')
+ return ret
+
+ vnc_config = {}
+ has_vnc = int(vmConfig['platform'].get('vnc', 0)) != 0
+ has_sdl = int(vmConfig['platform'].get('sdl', 0)) != 0
+ 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
+ break
+
+ keymap = vmConfig['platform'].get("keymap")
+ if keymap:
+ ret.append("-k")
+ ret.append(keymap)
+
+ if has_vnc:
+ if not vnc_config:
+ for key in ('vncunused', 'vnclisten', 'vncdisplay',
+ 'vncpasswd'):
+ if key in vmConfig['platform']:
+ vnc_config[key] = vmConfig['platform'][key]
+ if vnc_config.has_key("vncpasswd"):
+ passwd = vnc_config["vncpasswd"]
+ else:
+ passwd = XendOptions.instance().get_vncpasswd_default()
+ vncopts = ""
+ if passwd:
+ self.vm.storeVm("vncpasswd", passwd)
+ vncopts = vncopts + ",password"
+ log.debug("Stored a VNC password for vfb access")
+ else:
+ log.debug("No VNC passwd configured for vfb access")
+
+ if XendOptions.instance().get_vnc_tls():
+ vncx509certdir = XendOptions.instance().get_vnc_x509_cert_dir()
+ vncx509verify = XendOptions.instance().get_vnc_x509_verify()
+
+ if not os.path.exists(vncx509certdir):
+ raise VmError("VNC x509 certificate dir %s does not exist"
% vncx509certdir)
+
+ if vncx509verify:
+ vncopts = vncopts + ",tls,x509verify=%s" % vncx509certdir
+ else:
+ vncopts = vncopts + ",tls,x509=%s" % vncx509certdir
+
+
+ vnclisten = vnc_config.get('vnclisten',
+
XendOptions.instance().get_vnclisten_address())
+ vncdisplay = vnc_config.get('vncdisplay', 0)
+ ret.append('-vnc')
+ ret.append("%s:%s%s" % (vnclisten, vncdisplay, vncopts))
+
+ if vnc_config.get('vncunused', 0):
+ ret.append('-vncunused')
+
+ elif has_sdl:
+ # SDL is default in QEMU.
+ pass
+ else:
+ ret.append('-nographic')
+
+ if int(vmConfig['platform'].get('monitor', 0)) != 0:
+ ret = ret + ['-monitor', 'vc']
+ return ret
+
+ def getDeviceModelArgs(self, restore = False):
+ args = [self.device_model]
+ args = args + ([ "-d", "%d" % self.vm.getDomid() ])
+ args = args + self.dmargs
+ return args
+
def createDeviceModel(self, restore = False):
- """Create device model for the domain (define in subclass if
needed)."""
- pass
-
+ if self.device_model is None:
+ return
+ if self.pid:
+ return
+ # Execute device model.
+ #todo: Error handling
+ args = self.getDeviceModelArgs(restore)
+ env = dict(os.environ)
+ if self.display:
+ env['DISPLAY'] = self.display
+ if self.xauthority:
+ env['XAUTHORITY'] = self.xauthority
+ if self.vncconsole:
+ args = args + ([ "-vncviewer" ])
+ log.info("spawning device models: %s %s", self.device_model, args)
+ # keep track of pid and spawned options to kill it later
+ self.pid = os.spawnve(os.P_NOWAIT, self.device_model, args, env)
+ self.vm.storeDom("image/device-model-pid", self.pid)
+ log.info("device model pid: %d", self.pid)
+
def saveDeviceModel(self):
- """Save device model for the domain (define in subclass if needed)."""
- pass
+ if self.device_model is None:
+ return
+ # Signal the device model to pause itself and save its state
+ xstransact.Store("/local/domain/0/device-model/%i"
+ % self.vm.getDomid(), ('command', 'save'))
+ # Wait for confirmation. Could do this with a watch but we'd
+ # still end up spinning here waiting for the watch to fire.
+ state = ''
+ count = 0
+ while state != 'paused':
+ state = xstransact.Read("/local/domain/0/device-model/%i/state"
+ % self.vm.getDomid())
+ time.sleep(0.1)
+ count += 1
+ if count > 100:
+ raise VmError('Timed out waiting for device model to save')
def resumeDeviceModel(self):
- """Unpause device model for the domain (define in subclass if
needed)."""
- pass
-
- def destroy(self):
- """Extra cleanup on domain destroy (define in subclass if needed)."""
- pass
-
+ if self.device_model is None:
+ return
+ # Signal the device model to resume activity after pausing to save.
+ xstransact.Store("/local/domain/0/device-model/%i"
+ % self.vm.getDomid(), ('command', 'continue'))
def recreate(self):
- pass
+ if self.device_model is None:
+ return
+ self.pid = self.vm.gatherDom(('image/device-model-pid', int))
+
+ def destroyDeviceModel(self):
+ if self.device_model is None:
+ return
+ if self.pid:
+ try:
+ os.kill(self.pid, signal.SIGKILL)
+ except OSError, exn:
+ log.exception(exn)
+ try:
+ 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
+ self.pid = None
+ state = xstransact.Remove("/local/domain/0/device-model/%i"
+ % self.vm.getDomid())
class LinuxImageHandler(ImageHandler):
@@ -229,6 +371,19 @@ class LinuxImageHandler(ImageHandler):
flags = self.flags,
vhpt = self.vhpt)
+ def parseDeviceModelArgs(self, vmConfig):
+ ret = ImageHandler.parseDeviceModelArgs(self, vmConfig)
+ # Equivalent to old xenconsoled behaviour. Should make
+ # it configurable in future
+ ret = ret + ["-serial", "pty"]
+ return ret
+
+ def getDeviceModelArgs(self, restore = False):
+ args = ImageHandler.getDeviceModelArgs(self, restore)
+ args = args + ([ "-M", "xenpv"])
+ return args
+
+
class PPC_LinuxImageHandler(LinuxImageHandler):
ostype = "linux"
@@ -262,15 +417,6 @@ class HVMImageHandler(ImageHandler):
if 'hvm' not in info['xen_caps']:
raise HVMRequired()
- self.dmargs = self.parseDeviceModelArgs(vmConfig)
- self.device_model = vmConfig['platform'].get('device_model')
- if not self.device_model:
- raise VmError("hvm: missing device model")
-
- self.display = vmConfig['platform'].get('display')
- self.xauthority = vmConfig['platform'].get('xauthority')
- self.vncconsole = vmConfig['platform'].get('vncconsole')
-
rtc_timeoffset = vmConfig['platform'].get('rtc_timeoffset')
self.vm.storeVm(("image/dmargs", " ".join(self.dmargs)),
@@ -278,49 +424,18 @@ class HVMImageHandler(ImageHandler):
("image/display", self.display))
self.vm.storeVm(("rtc/timeoffset", rtc_timeoffset))
- self.pid = None
-
self.apic = int(vmConfig['platform'].get('apic', 0))
self.acpi = int(vmConfig['platform'].get('acpi', 0))
-
-
- def buildDomain(self):
- store_evtchn = self.vm.getStorePort()
-
- mem_mb = self.getRequiredInitialReservation() / 1024
-
- log.debug("domid = %d", self.vm.getDomid())
- log.debug("image = %s", self.kernel)
- log.debug("store_evtchn = %d", store_evtchn)
- log.debug("memsize = %d", mem_mb)
- log.debug("vcpus = %d", self.vm.getVCpuCount())
- log.debug("acpi = %d", self.acpi)
- log.debug("apic = %d", self.apic)
-
- rc = xc.hvm_build(domid = self.vm.getDomid(),
- image = self.kernel,
- memsize = mem_mb,
- vcpus = self.vm.getVCpuCount(),
- acpi = self.acpi,
- apic = self.apic)
-
- rc['notes'] = { 'SUSPEND_CANCEL': 1 }
-
- rc['store_mfn'] = xc.hvm_get_param(self.vm.getDomid(),
- HVM_PARAM_STORE_PFN)
- xc.hvm_set_param(self.vm.getDomid(), HVM_PARAM_STORE_EVTCHN,
- store_evtchn)
-
- return rc
# Return a list of cmd line args to the device models based on the
# xm config file
def parseDeviceModelArgs(self, vmConfig):
+ ret = ImageHandler.parseDeviceModelArgs(self, vmConfig)
+ ret = ret + ['-vcpus', str(self.vm.getVCpuCount())]
+
dmargs = [ 'boot', 'fda', 'fdb', 'soundhw',
'localtime', 'serial', 'stdvga', 'isa',
- 'acpi', 'usb', 'usbdevice', 'keymap', 'pci' ]
-
- ret = ['-vcpus', str(self.vm.getVCpuCount())]
+ 'acpi', 'usb', 'usbdevice', 'pci' ]
for a in dmargs:
v = vmConfig['platform'].get(a)
@@ -349,7 +464,6 @@ class HVMImageHandler(ImageHandler):
# Handle disk/network related options
mac = None
- ret = ret + ["-domain-name", str(self.vm.info['name_label'])]
nics = 0
for devuuid in vmConfig['vbd_refs']:
@@ -378,130 +492,43 @@ class HVMImageHandler(ImageHandler):
ret.append("-net")
ret.append("tap,vlan=%d,bridge=%s" % (nics, bridge))
-
- #
- # Find RFB console device, and if it exists, make QEMU enable
- # the VNC console.
- #
- if int(vmConfig['platform'].get('nographic', 0)) != 0:
- # skip vnc init if nographic is set
- ret.append('-nographic')
- return ret
-
- vnc_config = {}
- has_vnc = int(vmConfig['platform'].get('vnc', 0)) != 0
- has_sdl = int(vmConfig['platform'].get('sdl', 0)) != 0
- 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
- break
-
- if has_vnc:
- if not vnc_config:
- for key in ('vncunused', 'vnclisten', 'vncdisplay',
- 'vncpasswd'):
- if key in vmConfig['platform']:
- vnc_config[key] = vmConfig['platform'][key]
-
- vnclisten = vnc_config.get('vnclisten',
- xenopts().get_vnclisten_address())
- vncdisplay = vnc_config.get('vncdisplay', 0)
- ret.append('-vnc')
- ret.append("%s:%d" % (vnclisten, vncdisplay))
-
- if vnc_config.get('vncunused', 0):
- ret.append('-vncunused')
-
- # Store vncpassword in xenstore
- vncpasswd = vnc_config.get('vncpasswd')
- if not vncpasswd:
- vncpasswd = xenopts().get_vncpasswd_default()
-
- if vncpasswd is None:
- raise VmError('vncpasswd is not setup in vmconfig or '
- 'xend-config.sxp')
-
- if vncpasswd != '':
- self.vm.storeVm('vncpasswd', vncpasswd)
- elif has_sdl:
- # SDL is default in QEMU.
- pass
- else:
- ret.append('-nographic')
-
- if int(vmConfig['platform'].get('monitor', 0)) != 0:
- ret = ret + ['-monitor', 'vc']
return ret
- def createDeviceModel(self, restore = False):
- if self.pid:
- return
- # Execute device model.
- #todo: Error handling
- args = [self.device_model]
- args = args + ([ "-d", "%d" % self.vm.getDomid() ])
- if arch.type == "ia64":
- args = args + ([ "-m", "%s" %
- (self.getRequiredInitialReservation() / 1024) ])
- args = args + self.dmargs
+ def getDeviceModelArgs(self, restore = False):
+ args = ImageHandler.getDeviceModelArgs(self, restore)
+ args = args + ([ "-M", "xenfv"])
if restore:
args = args + ([ "-loadvm", "/var/lib/xen/qemu-save.%d" %
self.vm.getDomid() ])
- env = dict(os.environ)
- if self.display:
- env['DISPLAY'] = self.display
- if self.xauthority:
- env['XAUTHORITY'] = self.xauthority
- if self.vncconsole:
- args = args + ([ "-vncviewer" ])
- log.info("spawning device models: %s %s", self.device_model, args)
- # keep track of pid and spawned options to kill it later
- self.pid = os.spawnve(os.P_NOWAIT, self.device_model, args, env)
- self.vm.storeDom("image/device-model-pid", self.pid)
- log.info("device model pid: %d", self.pid)
-
- def saveDeviceModel(self):
- # Signal the device model to pause itself and save its state
- xstransact.Store("/local/domain/0/device-model/%i"
- % self.vm.getDomid(), ('command', 'save'))
- # Wait for confirmation. Could do this with a watch but we'd
- # still end up spinning here waiting for the watch to fire.
- state = ''
- count = 0
- while state != 'paused':
- state = xstransact.Read("/local/domain/0/device-model/%i/state"
- % self.vm.getDomid())
- time.sleep(0.1)
- count += 1
- if count > 100:
- raise VmError('Timed out waiting for device model to save')
-
- def resumeDeviceModel(self):
- # Signal the device model to resume activity after pausing to save.
- xstransact.Store("/local/domain/0/device-model/%i"
- % self.vm.getDomid(), ('command', 'continue'))
-
- def recreate(self):
- self.pid = self.vm.gatherDom(('image/device-model-pid', int))
-
- def destroy(self, suspend = False):
- if self.pid and not suspend:
- try:
- os.kill(self.pid, signal.SIGKILL)
- except OSError, exn:
- log.exception(exn)
- try:
- 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
- self.pid = None
- state = xstransact.Remove("/local/domain/0/device-model/%i"
- % self.vm.getDomid())
+ return args
+
+ def buildDomain(self):
+ store_evtchn = self.vm.getStorePort()
+
+ mem_mb = self.getRequiredInitialReservation() / 1024
+
+ log.debug("domid = %d", self.vm.getDomid())
+ log.debug("image = %s", self.kernel)
+ log.debug("store_evtchn = %d", store_evtchn)
+ log.debug("memsize = %d", mem_mb)
+ log.debug("vcpus = %d", self.vm.getVCpuCount())
+ log.debug("acpi = %d", self.acpi)
+ log.debug("apic = %d", self.apic)
+
+ rc = xc.hvm_build(domid = self.vm.getDomid(),
+ image = self.kernel,
+ memsize = mem_mb,
+ vcpus = self.vm.getVCpuCount(),
+ acpi = self.acpi,
+ apic = self.apic)
+ rc['notes'] = { 'SUSPEND_CANCEL': 1 }
+
+ rc['store_mfn'] = xc.hvm_get_param(self.vm.getDomid(),
+ HVM_PARAM_STORE_PFN)
+ xc.hvm_set_param(self.vm.getDomid(), HVM_PARAM_STORE_EVTCHN,
+ store_evtchn)
+
+ return rc
class IA64_HVM_ImageHandler(HVMImageHandler):
@@ -528,6 +555,13 @@ class IA64_HVM_ImageHandler(HVMImageHand
def getRequiredShadowMemory(self, shadow_mem_kb, maxmem_kb):
# Explicit shadow memory is not a concept
return 0
+
+ def getDeviceModelArgs(self, restore = False):
+ args = HVMImageHandler.getDeviceModelArgs(self, restore)
+ args = args + ([ "-m", "%s" %
+ (self.getRequiredInitialReservation() / 1024) ])
+ return args
+
class IA64_Linux_ImageHandler(LinuxImageHandler):
diff -r c17bfb091790 -r a07288a84785
tools/python/xen/xend/server/ConsoleController.py
--- a/tools/python/xen/xend/server/ConsoleController.py Tue Oct 30 11:33:55
2007 -0600
+++ b/tools/python/xen/xend/server/ConsoleController.py Tue Oct 30 15:34:44
2007 -0600
@@ -19,9 +19,12 @@ class ConsoleController(DevController):
return (self.allocateDeviceID(), back, {})
- def getDeviceConfiguration(self, devid):
- result = DevController.getDeviceConfiguration(self, devid)
- devinfo = self.readBackend(devid, *self.valid_cfg)
+ def getDeviceConfiguration(self, devid, transaction = None):
+ result = DevController.getDeviceConfiguration(self, devid, transaction)
+ if transaction is None:
+ devinfo = self.readBackend(devid, *self.valid_cfg)
+ else:
+ devinfo = self.readBackendTxn(transaction, devid, *self.valid_cfg)
config = dict(zip(self.valid_cfg, devinfo))
config = dict([(key, val) for key, val in config.items()
if val != None])
diff -r c17bfb091790 -r a07288a84785
tools/python/xen/xend/server/DevController.py
--- a/tools/python/xen/xend/server/DevController.py Tue Oct 30 11:33:55
2007 -0600
+++ b/tools/python/xen/xend/server/DevController.py Tue Oct 30 15:34:44
2007 -0600
@@ -239,15 +239,15 @@ class DevController:
self.vm._removeVm("device/%s/%d" % (self.deviceClass, dev))
- def configurations(self):
- return map(self.configuration, self.deviceIDs())
-
-
- def configuration(self, devid):
+ def configurations(self, transaction = None):
+ return map(lambda x: self.configuration(x, transaction),
self.deviceIDs(transaction))
+
+
+ def configuration(self, devid, transaction = None):
"""@return an s-expression giving the current configuration of the
specified device. This would be suitable for giving to {@link
#createDevice} in order to recreate that device."""
- configDict = self.getDeviceConfiguration(devid)
+ configDict = self.getDeviceConfiguration(devid, transaction)
sxpr = [self.deviceClass]
for key, val in configDict.items():
if isinstance(val, (types.ListType, types.TupleType)):
@@ -273,13 +273,16 @@ class DevController:
'id', devid]]
- def getDeviceConfiguration(self, devid):
+ def getDeviceConfiguration(self, devid, transaction = None):
"""Returns the configuration of a device.
@note: Similar to L{configuration} except it returns a dict.
@return: dict
"""
- backdomid = xstransact.Read(self.frontendPath(devid), "backend-id")
+ if transaction is None:
+ backdomid = xstransact.Read(self.frontendPath(devid), "backend-id")
+ else:
+ backdomid = transaction.read(self.frontendPath(devid) +
"/backend-id")
if backdomid is None:
raise VmError("Device %s not connected" % devid)
@@ -416,14 +419,28 @@ class DevController:
else:
raise VmError("Device %s not connected" % devid)
+ def readBackendTxn(self, transaction, devid, *args):
+ frontpath = self.frontendPath(devid)
+ backpath = transaction.read(frontpath + "/backend")
+ if backpath:
+ paths = map(lambda x: backpath + "/" + x, args)
+ return transaction.read(*paths)
+ else:
+ raise VmError("Device %s not connected" % devid)
+
def readFrontend(self, devid, *args):
return xstransact.Read(self.frontendPath(devid), *args)
+
+ def readFrontendTxn(self, transaction, devid, *args):
+ paths = map(lambda x: self.frontendPath(devid) + "/" + x, args)
+ return transaction.read(*paths)
def deviceIDs(self, transaction = None):
"""@return The IDs of each of the devices currently configured for
this instance's deviceClass.
"""
fe = self.backendRoot()
+
if transaction:
return map(lambda x: int(x.split('/')[-1]), transaction.list(fe))
else:
diff -r c17bfb091790 -r a07288a84785 tools/python/xen/xend/server/blkif.py
--- a/tools/python/xen/xend/server/blkif.py Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/python/xen/xend/server/blkif.py Tue Oct 30 15:34:44 2007 -0600
@@ -124,19 +124,26 @@ class BlkifController(DevController):
(self.deviceClass, devid, config))
- def getDeviceConfiguration(self, devid):
+ def getDeviceConfiguration(self, devid, transaction = None):
"""Returns the configuration of a device.
@note: Similar to L{configuration} except it returns a dict.
@return: dict
"""
- config = DevController.getDeviceConfiguration(self, devid)
- devinfo = self.readBackend(devid, 'dev', 'type', 'params', 'mode',
- 'uuid')
+ config = DevController.getDeviceConfiguration(self, devid, transaction)
+ if transaction is None:
+ devinfo = self.readBackend(devid, 'dev', 'type', 'params', 'mode',
+ 'uuid')
+ else:
+ devinfo = self.readBackendTxn(transaction, devid,
+ 'dev', 'type', 'params', 'mode',
'uuid')
dev, typ, params, mode, uuid = devinfo
if dev:
- dev_type = self.readFrontend(devid, 'device-type')
+ if transaction is None:
+ dev_type = self.readFrontend(devid, 'device-type')
+ else:
+ dev_type = self.readFrontendTxn(transaction, devid,
'device-type')
if dev_type:
dev += ':' + dev_type
config['dev'] = dev
diff -r c17bfb091790 -r a07288a84785 tools/python/xen/xend/server/netif.py
--- a/tools/python/xen/xend/server/netif.py Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/python/xen/xend/server/netif.py Tue Oct 30 15:34:44 2007 -0600
@@ -183,17 +183,20 @@ class NetifController(DevController):
"network device")
- def getDeviceConfiguration(self, devid):
+ def getDeviceConfiguration(self, devid, transaction = None):
"""@see DevController.configuration"""
- result = DevController.getDeviceConfiguration(self, devid)
+ result = DevController.getDeviceConfiguration(self, devid, transaction)
config_path = "device/%s/%d/" % (self.deviceClass, devid)
devinfo = ()
for x in ( 'script', 'ip', 'bridge', 'mac',
'type', 'vifname', 'rate', 'uuid', 'model', 'accel',
'security_label'):
- y = self.vm._readVm(config_path + x)
+ if transaction is None:
+ y = self.vm._readVm(config_path + x)
+ else:
+ y = self.vm._readVmTxn(transaction, config_path + x)
devinfo += (y,)
(script, ip, bridge, mac, typ, vifname, rate, uuid,
model, accel, security_label) = devinfo
diff -r c17bfb091790 -r a07288a84785 tools/python/xen/xend/server/pciif.py
--- a/tools/python/xen/xend/server/pciif.py Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/python/xen/xend/server/pciif.py Tue Oct 30 15:34:44 2007 -0600
@@ -78,8 +78,8 @@ class PciController(DevController):
back['uuid'] = config.get('uuid','')
return (0, back, {})
- def getDeviceConfiguration(self, devid):
- result = DevController.getDeviceConfiguration(self, devid)
+ def getDeviceConfiguration(self, devid, transaction = None):
+ result = DevController.getDeviceConfiguration(self, devid, transaction)
num_devs = self.readBackend(devid, 'num_devs')
pci_devs = []
diff -r c17bfb091790 -r a07288a84785 tools/python/xen/xend/server/tpmif.py
--- a/tools/python/xen/xend/server/tpmif.py Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/python/xen/xend/server/tpmif.py Tue Oct 30 15:34:44 2007 -0600
@@ -75,9 +75,9 @@ class TPMifController(DevController):
return (devid, back, front)
- def getDeviceConfiguration(self, devid):
+ def getDeviceConfiguration(self, devid, transaction = None):
"""Returns the configuration of a device"""
- result = DevController.getDeviceConfiguration(self, devid)
+ result = DevController.getDeviceConfiguration(self, devid, transaction)
(instance, uuid, type) = \
self.readBackend(devid, 'instance',
diff -r c17bfb091790 -r a07288a84785 tools/python/xen/xend/server/vfbif.py
--- a/tools/python/xen/xend/server/vfbif.py Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/python/xen/xend/server/vfbif.py Tue Oct 30 15:34:44 2007 -0600
@@ -5,14 +5,6 @@ import xen.xend
import xen.xend
import os
-def spawn_detached(path, args, env):
- p = os.fork()
- if p == 0:
- os.spawnve(os.P_NOWAIT, path, args, env)
- os._exit(0)
- else:
- os.waitpid(p, 0)
-
CONFIG_ENTRIES = ['type', 'vncdisplay', 'vnclisten', 'vncpasswd', 'vncunused',
'display', 'xauthority', 'keymap',
'uuid', 'location', 'protocol']
@@ -35,73 +27,20 @@ class VfbifController(DevController):
return (devid, back, {})
- def getDeviceConfiguration(self, devid):
- result = DevController.getDeviceConfiguration(self, devid)
+ def getDeviceConfiguration(self, devid, transaction = None):
+ result = DevController.getDeviceConfiguration(self, devid, transaction)
- devinfo = self.readBackend(devid, *CONFIG_ENTRIES)
+ if transaction is None:
+ devinfo = self.readBackend(devid, *CONFIG_ENTRIES)
+ else:
+ devinfo = self.readBackendTxn(transaction, devid, *CONFIG_ENTRIES)
return dict([(CONFIG_ENTRIES[i], devinfo[i])
for i in range(len(CONFIG_ENTRIES))
if devinfo[i] is not None])
-
- def createDevice(self, config):
- DevController.createDevice(self, config)
- if self.vm.info.is_hvm():
- # is HVM, so qemu-dm will handle the vfb.
- return
-
- std_args = [ "--domid", "%d" % self.vm.getDomid(),
- "--title", self.vm.getName() ]
- t = config.get("type", None)
- if t == "vnc":
- passwd = None
- if config.has_key("vncpasswd"):
- passwd = config["vncpasswd"]
- else:
- passwd =
xen.xend.XendOptions.instance().get_vncpasswd_default()
- if passwd:
- self.vm.storeVm("vncpasswd", passwd)
- log.debug("Stored a VNC password for vfb access")
- else:
- log.debug("No VNC passwd configured for vfb access")
-
- # Try to start the vnc backend
- args = [xen.util.auxbin.pathTo("xen-vncfb")]
- if config.has_key("vncunused"):
- args += ["--unused"]
- elif config.has_key("vncdisplay"):
- args += ["--vncport", "%d" % (5900 +
int(config["vncdisplay"]))]
- vnclisten = config.get("vnclisten",
-
xen.xend.XendOptions.instance().get_vnclisten_address())
- args += [ "--listen", vnclisten ]
- if config.has_key("keymap"):
- args += ["-k", "%s" % config["keymap"]]
- else:
- xoptions = xen.xend.XendOptions.instance()
- if xoptions.get_keymap():
- args += ["-k", "%s" % xoptions.get_keymap()]
-
- spawn_detached(args[0], args + std_args, os.environ)
- elif t == "sdl":
- args = [xen.util.auxbin.pathTo("xen-sdlfb")]
- env = dict(os.environ)
- if config.has_key("display"):
- env['DISPLAY'] = config["display"]
- if config.has_key("xauthority"):
- env['XAUTHORITY'] = config["xauthority"]
- spawn_detached(args[0], args + std_args, env)
- else:
- raise VmError('Unknown vfb type %s (%s)' % (t, repr(config)))
-
-
def waitForDevice(self, devid):
- if self.vm.info.get('HVM_boot_policy'):
- log.debug('skip waiting for HVM vfb')
- # is a qemu-dm managed device, don't wait for hotplug for these.
- return
-
- DevController.waitForDevice(self, devid)
-
+ # is a qemu-dm managed device, don't wait for hotplug for these.
+ return
def reconfigureDevice(self, _, config):
""" Only allow appending location information of vnc port into
@@ -115,19 +54,16 @@ class VfbifController(DevController):
raise VmError('Refusing to reconfigure device vfb:%d' % devid)
def destroyDevice(self, devid, force):
- if self.vm.info.get('HVM_boot_policy'):
- # remove the backend xenstore entries for HVM guests no matter
- # what
- DevController.destroyDevice(self, devid, True)
- else:
- DevController.destroyDevice(self, devid, force)
+ # remove the backend xenstore entries no matter what
+ # because we kill qemu-dm with extreme prejudice
+ # not giving it a chance to remove them itself
+ DevController.destroyDevice(self, devid, True)
def migrate(self, deviceConfig, network, dst, step, domName):
- if self.vm.info.get('HVM_boot_policy'):
- return 0
- return DevController.migrate(self, deviceConfig, network, dst, step,
- domName)
+ # Handled by qemu-dm so no action needed
+ return 0
+
class VkbdifController(DevController):
"""Virtual keyboard controller. Handles all vkbd devices for a domain.
@@ -141,22 +77,15 @@ class VkbdifController(DevController):
return (devid, back, front)
def waitForDevice(self, config):
- if self.vm.info.get('HVM_boot_policy'):
- # is a qemu-dm managed device, don't wait for hotplug for these.
- return
-
- DevController.waitForDevice(self, config)
+ # is a qemu-dm managed device, don't wait for hotplug for these.
+ return
def destroyDevice(self, devid, force):
- if self.vm.info.get('HVM_boot_policy'):
- # remove the backend xenstore entries for HVM guests no matter
- # what
- DevController.destroyDevice(self, devid, True)
- else:
- DevController.destroyDevice(self, devid, force)
+ # remove the backend xenstore entries no matter what
+ # because we kill qemu-dm with extreme prejudice
+ # not giving it a chance to remove them itself
+ DevController.destroyDevice(self, devid, True)
def migrate(self, deviceConfig, network, dst, step, domName):
- if self.vm.info.get('HVM_boot_policy'):
- return 0
- return DevController.migrate(self, deviceConfig, network, dst, step,
- domName)
+ # Handled by qemu-dm so no action needed
+ return 0
diff -r c17bfb091790 -r a07288a84785 tools/python/xen/xm/addlabel.py
--- a/tools/python/xen/xm/addlabel.py Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/python/xen/xm/addlabel.py Tue Oct 30 15:34:44 2007 -0600
@@ -117,15 +117,18 @@ def add_resource_label(label, resource,
res_xapi,
"")
except Exception, e:
- security.err("Could not label this resource: %s" % e)
- else:
- security.err("'%s' is already labeled with '%s'" % (resource,old))
+ raise security.XSMError("Could not label this resource: %s" %
+ str(e))
+ else:
+ raise security.XSMError("'%s' is already labeled with '%s'" %
+ (resource,old))
def add_domain_label(label, configfile, policyref):
# sanity checks: make sure this label can be instantiated later on
ssidref = security.label2ssidref(label, policyref, 'dom')
- new_label = "access_control = ['policy=%s,label=%s']\n" % (policyref,
label)
+ new_label = "access_control = ['policy=%s,label=%s']\n" % \
+ (policyref, label)
if not os.path.isfile(configfile):
security.err("Configuration file \'" + configfile + "\' not found.")
config_fd = open(configfile, "ra+")
@@ -150,14 +153,14 @@ def add_domain_label_xapi(label, domainn
try:
old_lab = server.xenapi.VM.get_security_label(uuid)
rc = server.xenapi.VM.set_security_label(uuid, sec_lab, old_lab)
- except:
- rc = -1
+ except Exception, e:
+ raise security.XSMError("Could not label the domain: %s" % e)
if int(rc) < 0:
raise OptionError('Could not label domain.')
else:
ssidref = int(rc)
if ssidref != 0:
- print "Set the label of domain '%s' to '%s'. New ssidref = %08x" %
\
+ print "Set the label of domain '%s' to '%s'. New ssidref = %08x" %\
(domainname,label,ssidref)
else:
print "Set the label of dormant domain '%s' to '%s'." % \
diff -r c17bfb091790 -r a07288a84785 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/python/xen/xm/create.py Tue Oct 30 15:34:44 2007 -0600
@@ -193,6 +193,11 @@ gopts.var('pae', val='PAE',
gopts.var('pae', val='PAE',
fn=set_int, default=1,
use="Disable or enable PAE of HVM domain.")
+
+gopts.var('timer_mode', val='TIMER_MODE',
+ fn=set_int, default=0,
+ use="""Timer mode (0=delay virtual time when ticks are missed;
+ 1=virtual time is always wallclock time.""")
gopts.var('acpi', val='ACPI',
fn=set_int, default=1,
@@ -724,7 +729,7 @@ def configure_hvm(config_image, vals):
def configure_hvm(config_image, vals):
"""Create the config for HVM devices.
"""
- args = [ 'device_model', 'pae', 'vcpus', 'boot', 'fda', 'fdb',
+ args = [ 'device_model', 'pae', 'vcpus', 'boot', 'fda', 'fdb',
'timer_mode',
'localtime', 'serial', 'stdvga', 'isa', 'nographic', 'soundhw',
'vnc', 'vncdisplay', 'vncunused', 'vncconsole', 'vnclisten',
'sdl', 'display', 'xauthority', 'rtc_timeoffset', 'monitor',
@@ -1228,7 +1233,7 @@ def config_security_check(config, verbos
if verbose:
print " %s: PERMITTED" % (resource)
- except security.XSMError:
+ except security.ACMError:
print " %s: DENIED" % (resource)
(poltype, res_label, res_policy) = security.get_res_label(resource)
if not res_label:
diff -r c17bfb091790 -r a07288a84785 tools/python/xen/xm/rmlabel.py
--- a/tools/python/xen/xm/rmlabel.py Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/python/xen/xm/rmlabel.py Tue Oct 30 15:34:44 2007 -0600
@@ -50,9 +50,10 @@ def rm_resource_label(resource):
server.xenapi.XSPolicy.set_resource_label(resource,"",
oldlabel)
else:
- raise security.ACMError("Resource not labeled")
+ raise security.XSMError("Resource not labeled")
except Exception, e:
- print "Could not remove label from resource: %s" % e
+ raise security.XSMError("Could not remove label "
+ "from resource: %s" % e)
return
#build canonical resource name
@@ -128,7 +129,7 @@ def rm_domain_label_xapi(domainname):
old_lab = server.xenapi.VM.get_security_label(uuid)
server.xenapi.VM.set_security_label(uuid, "", old_lab)
except Exception, e:
- print('Could not remove label from domain: %s' % e)
+ raise security.XSMError('Could not remove label from domain: %s' % e)
def rm_vif_label(vmname, idx):
if xm_main.serverType != xm_main.SERVER_XEN_API:
@@ -142,16 +143,21 @@ def rm_vif_label(vmname, idx):
raise OptionError("Bad VIF index.")
vif_ref = server.xenapi.VIF.get_by_uuid(vif_refs[idx])
if not vif_ref:
- print "A VIF with this UUID does not exist."
+ raise security.XSMError("A VIF with this UUID does not exist.")
try:
old_lab = server.xenapi.VIF.get_security_label(vif_ref)
- rc = server.xenapi.VIF.set_security_label(vif_ref, "", old_lab)
- if int(rc) != 0:
- print "Could not remove the label from the VIF."
+ if old_lab != "":
+ rc = server.xenapi.VIF.set_security_label(vif_ref, "", old_lab)
+ if int(rc) != 0:
+ raise security.XSMError("Could not remove the label from"
+ " the VIF.")
+ else:
+ print "Successfully removed the label from the VIF."
else:
- print "Successfully removed the label from the VIF."
+ raise security.XSMError("VIF is not labeled.")
except Exception, e:
- print "Could not remove the label the VIF: %s" % str(e)
+ raise security.XSMError("Could not remove the label from the VIF: %s" %
+ str(e))
def main (argv):
diff -r c17bfb091790 -r a07288a84785 tools/python/xen/xm/setpolicy.py
--- a/tools/python/xen/xm/setpolicy.py Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/python/xen/xm/setpolicy.py Tue Oct 30 15:34:44 2007 -0600
@@ -23,6 +23,7 @@ import struct
import struct
import sys
import string
+import xen.util.xsm.xsm as security
from xen.util import xsconstants
from xen.util.acmpolicy import ACMPolicy
from xen.xm.opts import OptionError
@@ -100,21 +101,22 @@ def setpolicy(policytype, policy_name, f
flags,
overwrite)
except Exception, e:
- print "An error occurred setting the policy: %s" % str(e)
- return
+ raise security.XSMError("An error occurred setting the "
+ "policy: %s" % str(e))
xserr = int(policystate['xserr'])
if xserr != 0:
- print "An error occurred trying to set the policy: %s" % \
+ txt = "An error occurred trying to set the policy: %s." % \
xsconstants.xserr2string(abs(xserr))
errors = policystate['errors']
if len(errors) > 0:
- print "Hypervisor reported errors:"
+ txt += "Hypervisor reported errors:"
err = base64.b64decode(errors)
i = 0
while i + 7 < len(err):
code, data = struct.unpack("!ii", errors[i:i+8])
- print "(0x%08x, 0x%08x)" % (code, data)
+ txt += "(0x%08x, 0x%08x)" % (code, data)
i += 8
+ raise security.XSMError(txt)
else:
print "Successfully set the new policy."
diff -r c17bfb091790 -r a07288a84785 tools/python/xen/xm/xenapi_create.py
--- a/tools/python/xen/xm/xenapi_create.py Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/python/xen/xm/xenapi_create.py Tue Oct 30 15:34:44 2007 -0600
@@ -818,7 +818,7 @@ class sxp2xml:
def extract_platform(self, image, document):
- platform_keys = ['acpi', 'apic', 'pae', 'vhpt']
+ platform_keys = ['acpi', 'apic', 'pae', 'vhpt', 'timer_mode']
def extract_platform_key(key):
platform = document.createElement("platform")
diff -r c17bfb091790 -r a07288a84785 tools/xenfb/Makefile
--- a/tools/xenfb/Makefile Tue Oct 30 11:33:55 2007 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-XEN_ROOT=../..
-include $(XEN_ROOT)/tools/Rules.mk
-
-CFLAGS += -I$(XEN_LIBXC) -I$(XEN_XENSTORE)
-CFLAGS += -I$(XEN_ROOT)/tools/ioemu
-LDFLAGS += -L$(XEN_LIBXC) -L$(XEN_XENSTORE)
-
-.PHONY: all
-all: build
-
-.PHONY: build
-build:
- $(MAKE) vncfb sdlfb
-
-install: all
- $(INSTALL_DIR) $(DESTDIR)/usr/$(LIBDIR)/xen/bin
- $(INSTALL_PROG) vncfb $(DESTDIR)/usr/$(LIBDIR)/xen/bin/xen-vncfb
- $(INSTALL_PROG) sdlfb $(DESTDIR)/usr/$(LIBDIR)/xen/bin/xen-sdlfb
-
-sdlfb: sdlfb.o xenfb.o
-
-sdlfb.o: CFLAGS += $(shell sdl-config --cflags)
-sdlfb: LDLIBS += $(shell sdl-config --libs) -lxenctrl -lxenstore
-
-clean:
- $(RM) *.o *~ vncfb sdlfb
-
-vncfb: vncfb.o xenfb.o
-vncfb.o: CFLAGS += $(shell libvncserver-config --cflags)
-vncfb: LDLIBS += $(shell libvncserver-config --libs) -lxenctrl -lxenstore
-
-sdlfb.o xenfb.o vncfb.o: xenfb.h
diff -r c17bfb091790 -r a07288a84785 tools/xenfb/sdlfb.c
--- a/tools/xenfb/sdlfb.c Tue Oct 30 11:33:55 2007 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,342 +0,0 @@
-#include <SDL.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/select.h>
-#include <stdlib.h>
-#include <linux/input.h>
-#include <getopt.h>
-#include <string.h>
-#include "xenfb.h"
-
-struct SDLFBData
-{
- SDL_Surface *dst;
- SDL_Surface *src;
-};
-
-/*
- * Map from scancode to Linux input layer keycode. Scancodes are
- * hardware-specific. This map assumes a standard AT or PS/2
- * keyboard.
- *
- * Why use scancodes? We can't use key symbols, because they don't
- * identify keys --- they're what keys are mapped to. The standard
- * German keymap, for instance, maps both KEY_COMMA and KEY_102ND to
- * SDLK_LESS.
- */
-static int keymap[256] = {
- [9] = KEY_ESC,
- [10] = KEY_1,
- [11] = KEY_2,
- [12] = KEY_3,
- [13] = KEY_4,
- [14] = KEY_5,
- [15] = KEY_6,
- [16] = KEY_7,
- [17] = KEY_8,
- [18] = KEY_9,
- [19] = KEY_0,
- [20] = KEY_MINUS,
- [21] = KEY_EQUAL,
- [22] = KEY_BACKSPACE,
- [23] = KEY_TAB,
- [24] = KEY_Q,
- [25] = KEY_W,
- [26] = KEY_E,
- [27] = KEY_R,
- [28] = KEY_T,
- [29] = KEY_Y,
- [30] = KEY_U,
- [31] = KEY_I,
- [32] = KEY_O,
- [33] = KEY_P,
- [34] = KEY_LEFTBRACE,
- [35] = KEY_RIGHTBRACE,
- [36] = KEY_ENTER,
- [37] = KEY_LEFTCTRL,
- [38] = KEY_A,
- [39] = KEY_S,
- [40] = KEY_D,
- [41] = KEY_F,
- [42] = KEY_G,
- [43] = KEY_H,
- [44] = KEY_J,
- [45] = KEY_K,
- [46] = KEY_L,
- [47] = KEY_SEMICOLON,
- [48] = KEY_APOSTROPHE,
- [49] = KEY_GRAVE,
- [50] = KEY_LEFTSHIFT,
- [51] = KEY_BACKSLASH,
- [52] = KEY_Z,
- [53] = KEY_X,
- [54] = KEY_C,
- [55] = KEY_V,
- [56] = KEY_B,
- [57] = KEY_N,
- [58] = KEY_M,
- [59] = KEY_COMMA,
- [60] = KEY_DOT,
- [61] = KEY_SLASH,
- [62] = KEY_RIGHTSHIFT,
- [63] = KEY_KPASTERISK,
- [64] = KEY_LEFTALT,
- [65] = KEY_SPACE,
- [66] = KEY_CAPSLOCK,
- [67] = KEY_F1,
- [68] = KEY_F2,
- [69] = KEY_F3,
- [70] = KEY_F4,
- [71] = KEY_F5,
- [72] = KEY_F6,
- [73] = KEY_F7,
- [74] = KEY_F8,
- [75] = KEY_F9,
- [76] = KEY_F10,
- [77] = KEY_NUMLOCK,
- [78] = KEY_SCROLLLOCK,
- [79] = KEY_KP7,
- [80] = KEY_KP8,
- [81] = KEY_KP9,
- [82] = KEY_KPMINUS,
- [83] = KEY_KP4,
- [84] = KEY_KP5,
- [85] = KEY_KP6,
- [86] = KEY_KPPLUS,
- [87] = KEY_KP1,
- [88] = KEY_KP2,
- [89] = KEY_KP3,
- [90] = KEY_KP0,
- [91] = KEY_KPDOT,
- [94] = KEY_102ND, /* FIXME is this correct? */
- [95] = KEY_F11,
- [96] = KEY_F12,
- [108] = KEY_KPENTER,
- [109] = KEY_RIGHTCTRL,
- [112] = KEY_KPSLASH,
- [111] = KEY_SYSRQ,
- [113] = KEY_RIGHTALT,
- [97] = KEY_HOME,
- [98] = KEY_UP,
- [99] = KEY_PAGEUP,
- [100] = KEY_LEFT,
- [102] = KEY_RIGHT,
- [103] = KEY_END,
- [104] = KEY_DOWN,
- [105] = KEY_PAGEDOWN,
- [106] = KEY_INSERT,
- [107] = KEY_DELETE,
- [110] = KEY_PAUSE,
- [115] = KEY_LEFTMETA,
- [116] = KEY_RIGHTMETA,
- [117] = KEY_MENU,
-};
-
-static int btnmap[] = {
- [SDL_BUTTON_LEFT] = BTN_LEFT,
- [SDL_BUTTON_MIDDLE] = BTN_MIDDLE,
- [SDL_BUTTON_RIGHT] = BTN_RIGHT,
- /* FIXME not 100% sure about these: */
- [SDL_BUTTON_WHEELUP] = BTN_FORWARD,
- [SDL_BUTTON_WHEELDOWN] BTN_BACK
-};
-
-static void sdl_update(struct xenfb *xenfb, int x, int y, int width, int
height)
-{
- struct SDLFBData *data = xenfb->user_data;
- SDL_Rect r = { x, y, width, height };
- SDL_BlitSurface(data->src, &r, data->dst, &r);
- SDL_UpdateRect(data->dst, x, y, width, height);
-}
-
-static int sdl_on_event(struct xenfb *xenfb, SDL_Event *event)
-{
- int x, y, ret;
-
- switch (event->type) {
- case SDL_KEYDOWN:
- case SDL_KEYUP:
- if (keymap[event->key.keysym.scancode] == 0)
- break;
- ret = xenfb_send_key(xenfb,
- event->type == SDL_KEYDOWN,
- keymap[event->key.keysym.scancode]);
- if (ret < 0)
- fprintf(stderr, "Key %d %s lost (%s)\n",
- keymap[event->key.keysym.scancode],
- event->type == SDL_KEYDOWN ? "down" : "up",
- strerror(errno));
- break;
- case SDL_MOUSEMOTION:
- if (xenfb->abs_pointer_wanted) {
- SDL_GetMouseState(&x, &y);
- ret = xenfb_send_position(xenfb, x, y);
- } else {
- SDL_GetRelativeMouseState(&x, &y);
- ret = xenfb_send_motion(xenfb, x, y);
- }
- if (ret < 0)
- fprintf(stderr, "Pointer to %d,%d lost (%s)\n",
- x, y, strerror(errno));
- break;
- case SDL_MOUSEBUTTONDOWN:
- case SDL_MOUSEBUTTONUP:
- if (event->button.button >= sizeof(btnmap) / sizeof(*btnmap))
- break;
- if (btnmap[event->button.button] == 0)
- break;
- ret = xenfb_send_key(xenfb,
- event->type == SDL_MOUSEBUTTONDOWN,
- btnmap[event->button.button]);
- if (ret < 0)
- fprintf(stderr, "Button %d %s lost (%s)\n",
- btnmap[event->button.button] - BTN_MOUSE,
- event->type == SDL_MOUSEBUTTONDOWN ? "down" :
"up",
- strerror(errno));
- break;
- case SDL_QUIT:
- return 0;
- }
-
- return 1;
-}
-
-static struct option options[] = {
- { "domid", 1, NULL, 'd' },
- { "title", 1, NULL, 't' },
- { NULL }
-};
-
-int main(int argc, char **argv)
-{
- struct xenfb *xenfb;
- int domid = -1;
- char * title = NULL;
- fd_set readfds;
- int nfds;
- struct SDLFBData data;
- SDL_Rect r;
- struct timeval tv;
- SDL_Event event;
- int do_quit = 0;
- int opt;
- char *endp;
- int retval;
-
- while ((opt = getopt_long(argc, argv, "d:t:", options,
- NULL)) != -1) {
- switch (opt) {
- case 'd':
- domid = strtol(optarg, &endp, 10);
- if (endp == optarg || *endp) {
- fprintf(stderr, "Invalid domain id
specified\n");
- exit(1);
- }
- break;
- case 't':
- title = strdup(optarg);
- break;
- case '?':
- exit(1);
- }
- }
- if (optind != argc) {
- fprintf(stderr, "Invalid options!\n");
- exit(1);
- }
- if (domid <= 0) {
- fprintf(stderr, "Domain ID must be specified!\n");
- exit(1);
- }
-
- xenfb = xenfb_new();
- if (xenfb == NULL) {
- fprintf(stderr, "Could not create framebuffer (%s)\n",
- strerror(errno));
- exit(1);
- }
-
- if (xenfb_attach_dom(xenfb, domid) < 0) {
- fprintf(stderr, "Could not connect to domain (%s)\n",
- strerror(errno));
- exit(1);
- }
-
- if (SDL_Init(SDL_INIT_VIDEO) < 0) {
- fprintf(stderr, "Could not initialize SDL\n");
- exit(1);
- }
-
- data.dst = SDL_SetVideoMode(xenfb->width, xenfb->height, xenfb->depth,
- SDL_SWSURFACE);
- if (!data.dst) {
- fprintf(stderr, "SDL_SetVideoMode failed\n");
- exit(1);
- }
-
- data.src = SDL_CreateRGBSurfaceFrom(xenfb->pixels,
- xenfb->width, xenfb->height,
- xenfb->depth, xenfb->row_stride,
- 0xFF0000, 0xFF00, 0xFF, 0);
-
- if (!data.src) {
- fprintf(stderr, "SDL_CreateRGBSurfaceFrom failed\n");
- exit(1);
- }
-
- if (title == NULL)
- title = strdup("xen-sdlfb");
- SDL_WM_SetCaption(title, title);
-
- r.x = r.y = 0;
- r.w = xenfb->width;
- r.h = xenfb->height;
- SDL_BlitSurface(data.src, &r, data.dst, &r);
- SDL_UpdateRect(data.dst, 0, 0, xenfb->width, xenfb->height);
-
- xenfb->update = sdl_update;
- xenfb->user_data = &data;
-
- SDL_ShowCursor(0);
-
- /*
- * We need to wait for fds becoming ready or SDL events to
- * arrive. We time out the select after 10ms to poll for SDL
- * events. Clunky, but works. Could avoid the clunkiness
- * with a separate thread.
- */
- for (;;) {
- FD_ZERO(&readfds);
- nfds = xenfb_select_fds(xenfb, &readfds);
- tv = (struct timeval){0, 10000};
-
- if (select(nfds, &readfds, NULL, NULL, &tv) < 0) {
- if (errno == EINTR)
- continue;
- fprintf(stderr,
- "Can't select() on event channel (%s)\n",
- strerror(errno));
- break;
- }
-
- while (SDL_PollEvent(&event)) {
- if (!sdl_on_event(xenfb, &event))
- do_quit = 1;
- }
-
- if (do_quit)
- break;
-
- retval = xenfb_poll(xenfb, &readfds);
- if (retval == -2)
- xenfb_teardown(xenfb);
- if (retval < 0)
- break;
- }
-
- xenfb_delete(xenfb);
-
- SDL_Quit();
-
- return 0;
-}
diff -r c17bfb091790 -r a07288a84785 tools/xenfb/vncfb.c
--- a/tools/xenfb/vncfb.c Tue Oct 30 11:33:55 2007 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,522 +0,0 @@
-#define _GNU_SOURCE
-#include <errno.h>
-#include <getopt.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <unistd.h>
-#include <malloc.h>
-#include <rfb/rfb.h>
-#include <rfb/keysym.h>
-#include <linux/input.h>
-#include <xs.h>
-#include "xenfb.h"
-
-/* Grab key translation support routines from qemu directory. */
-#define qemu_mallocz(size) calloc(1, (size))
-static const char *bios_dir = "/usr/share/xen/qemu";
-#include "vnc_keysym.h"
-#include "keymaps.c"
-
-static unsigned char atkbd_set2_keycode[512] = {
-
- 0, 67, 65, 63, 61, 59, 60, 88, 0, 68, 66, 64, 62, 15, 41,117,
- 0, 56, 42, 93, 29, 16, 2, 0, 0, 0, 44, 31, 30, 17, 3, 0,
- 0, 46, 45, 32, 18, 5, 4, 95, 0, 57, 47, 33, 20, 19, 6,183,
- 0, 49, 48, 35, 34, 21, 7,184, 0, 0, 50, 36, 22, 8, 9,185,
- 0, 51, 37, 23, 24, 11, 10, 0, 0, 52, 53, 38, 39, 25, 12, 0,
- 0, 89, 40, 0, 26, 13, 0, 0, 58, 54, 28, 27, 0, 43, 0, 85,
- 0, 86, 91, 90, 92, 0, 14, 94, 0, 79,124, 75, 71,121, 0, 0,
- 82, 83, 80, 76, 77, 72, 1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
-
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 217,100,255, 0, 97,165, 0, 0,156, 0, 0, 0, 0, 0, 0,125,
- 173,114, 0,113, 0, 0, 0,126,128, 0, 0,140, 0, 0, 0,127,
- 159, 0,115, 0,164, 0, 0,116,158, 0,150,166, 0, 0, 0,142,
- 157, 0, 0, 0, 0, 0, 0, 0,155, 0, 98, 0, 0,163, 0, 0,
- 226, 0, 0, 0, 0, 0, 0, 0, 0,255, 96, 0, 0, 0,143, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0,105,102, 0, 0,112,
- 110,111,108,112,106,103, 0,119, 0,118,109, 0, 99,104,119, 0,
-
-};
-
-static unsigned char atkbd_unxlate_table[128] = {
-
- 0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
- 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
- 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
- 50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88, 5, 6, 4, 12, 3,
- 11, 2, 10, 1, 9,119,126,108,117,125,123,107,115,116,121,105,
- 114,122,112,113,127, 96, 97,120, 7, 15, 23, 31, 39, 47, 55, 63,
- 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
- 19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
-
-};
-
-unsigned char keycode_table[512];
-
-static void *kbd_layout;
-uint8_t modifiers_state[256];
-
-static int btnmap[] = {
- BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, BTN_SIDE,
- BTN_EXTRA, BTN_FORWARD, BTN_BACK, BTN_TASK
-};
-
-static void press_key_shift_down(struct xenfb* xenfb, int down, int scancode)
-{
- if (down)
- xenfb_send_key(xenfb, 1, keycode_table[0x2a]);
-
- if (xenfb_send_key(xenfb, down, keycode_table[scancode]) < 0)
- fprintf(stderr, "Key %d %s lost (%s)\n",
- scancode, "down", strerror(errno));
-
- if (!down)
- xenfb_send_key(xenfb, 0, keycode_table[0x2a]);
-}
-
-static void press_key_shift_up(struct xenfb* xenfb, int down, int scancode)
-{
- if (down) {
- if (modifiers_state[0x2a])
- xenfb_send_key(xenfb, 0, keycode_table[0x2a]);
- if (modifiers_state[0x36])
- xenfb_send_key(xenfb, 0, keycode_table[0x36]);
- }
-
- if (xenfb_send_key(xenfb, down, keycode_table[scancode]) < 0)
- fprintf(stderr, "Key %d %s lost (%s)\n",
- scancode, "down", strerror(errno));
-
- if (!down) {
- if (modifiers_state[0x2a])
- xenfb_send_key(xenfb, 1, keycode_table[0x2a]);
- if (modifiers_state[0x36])
- xenfb_send_key(xenfb, 1, keycode_table[0x36]);
- }
-}
-
-static void on_kbd_event(rfbBool down, rfbKeySym keycode, rfbClientPtr cl)
-{
- /*
- * We need to map to the key's Linux input layer keycode.
- * Unfortunately, we don't get the key here, only the
- * rfbKeySym, which is what the key is mapped to. Mapping
- * back to the key is impossible in general, even when you
- * know the keymap. For instance, the standard German keymap
- * maps both KEY_COMMA and KEY_102ND to XK_less. We simply
- * assume standard US layout. This sucks.
- */
- rfbScreenInfoPtr server = cl->screen;
- struct xenfb *xenfb = server->screenData;
- int scancode;
- int shift = 0;
- int shift_keys = 0;
-
- if (keycode >= 'A' && keycode <= 'Z') {
- keycode += 'a' - 'A';
- shift = 1;
- }
- else {
- shift = keysymIsShift(kbd_layout, keycode);
- }
- shift_keys = modifiers_state[0x2a] | modifiers_state[0x36];
-
- scancode = keysym2scancode(kbd_layout, keycode);
- if (scancode == 0)
- return;
-
- switch(scancode) {
- case 0x2a: /* Left Shift */
- case 0x36: /* Right Shift */
- case 0x1d: /* Left CTRL */
- case 0x9d: /* Right CTRL */
- case 0x38: /* Left ALT */
- case 0xb8: /* Right ALT */
- if (down)
- modifiers_state[scancode] = 1;
- else
- modifiers_state[scancode] = 0;
- xenfb_send_key(xenfb, down, keycode_table[scancode]);
- return;
- case 0x45: /* NumLock */
- if (!down)
- modifiers_state[scancode] ^= 1;
- xenfb_send_key(xenfb, down, keycode_table[scancode]);
- return;
- }
-
- if (keycodeIsKeypad(kbd_layout, scancode)) {
- /* If the numlock state needs to change then simulate an additional
- keypress before sending this one. This will happen if the user
- toggles numlock away from the VNC window.
- */
- if (keysymIsNumlock(kbd_layout, keycode)) {
- if (!modifiers_state[0x45]) {
- modifiers_state[0x45] = 1;
- xenfb_send_key(xenfb, 1, keycode_table[0x45]);
- xenfb_send_key(xenfb, 0, keycode_table[0x45]);
- }
- } else {
- if (modifiers_state[0x45]) {
- modifiers_state[0x45] = 0;
- xenfb_send_key(xenfb, 1, keycode_table[0x45]);
- xenfb_send_key(xenfb, 0, keycode_table[0x45]);
- }
- }
- }
-
- /* If the shift state needs to change then simulate an additional
- keypress before sending this one.
- */
- if (shift && !shift_keys) {
- press_key_shift_down(xenfb, down, scancode);
- return;
- }
- else if (!shift && shift_keys) {
- press_key_shift_up(xenfb, down, scancode);
- return;
- }
-
- if (xenfb_send_key(xenfb, down, keycode_table[scancode]) < 0)
- fprintf(stderr, "Key %d %s lost (%s)\n",
- scancode, down ? "down" : "up",
- strerror(errno));
-}
-
-static void on_ptr_event(int buttonMask, int x, int y, rfbClientPtr cl)
-{
- /* initial pointer state: at (0,0), buttons up */
- static int last_x, last_y, last_button;
- rfbScreenInfoPtr server = cl->screen;
- struct xenfb *xenfb = server->screenData;
- int i, last_down, down, ret;
-
- for (i = 0; i < 8; i++) {
- last_down = last_button & (1 << i);
- down = buttonMask & (1 << i);
- if (down == last_down)
- continue;
- if (i >= sizeof(btnmap) / sizeof(*btnmap))
- break;
- if (btnmap[i] == 0)
- break;
- if (xenfb_send_key(xenfb, down != 0, btnmap[i]) < 0)
- fprintf(stderr, "Button %d %s lost (%s)\n",
- i, down ? "down" : "up", strerror(errno));
- }
-
- if (x != last_x || y != last_y) {
- if (xenfb->abs_pointer_wanted)
- ret = xenfb_send_position(xenfb, x, y);
- else
- ret = xenfb_send_motion(xenfb, x - last_x, y - last_y);
- if (ret < 0)
- fprintf(stderr, "Pointer to %d,%d lost (%s)\n",
- x, y, strerror(errno));
- }
-
- last_button = buttonMask;
- last_x = x;
- last_y = y;
-}
-
-static void xenstore_write_vncport(struct xs_handle *xsh, int port, int domid)
-{
- char *buf, *path;
- char portstr[10];
-
- path = xs_get_domain_path(xsh, domid);
- if (path == NULL) {
- fprintf(stderr, "Can't get domain path (%s)\n",
- strerror(errno));
- goto out;
- }
-
- if (asprintf(&buf, "%s/console/vnc-port", path) == -1) {
- fprintf(stderr, "Can't make vncport path\n");
- goto out;
- }
-
- if (snprintf(portstr, sizeof(portstr), "%d", port) == -1) {
- fprintf(stderr, "Can't make vncport value\n");
- goto out;
- }
-
- if (!xs_write(xsh, XBT_NULL, buf, portstr, strlen(portstr)))
- fprintf(stderr, "Can't set vncport (%s)\n",
- strerror(errno));
-
- out:
- free(buf);
-}
-
-
-static int xenstore_read_vncpasswd(struct xs_handle *xsh, int domid, char
*pwbuf, int pwbuflen)
-{
- char buf[256], *path, *uuid = NULL, *passwd = NULL;
- unsigned int len, rc = 0;
-
- if (xsh == NULL) {
- return -1;
- }
-
- path = xs_get_domain_path(xsh, domid);
- if (path == NULL) {
- fprintf(stderr, "xs_get_domain_path() error\n");
- return -1;
- }
-
- snprintf(buf, 256, "%s/vm", path);
- uuid = xs_read(xsh, XBT_NULL, buf, &len);
- if (uuid == NULL) {
- fprintf(stderr, "xs_read(): uuid get error\n");
- free(path);
- return -1;
- }
-
- snprintf(buf, 256, "%s/vncpasswd", uuid);
- passwd = xs_read(xsh, XBT_NULL, buf, &len);
- if (passwd == NULL) {
- free(uuid);
- free(path);
- return rc;
- }
-
- strncpy(pwbuf, passwd, pwbuflen-1);
- pwbuf[pwbuflen-1] = '\0';
-
- fprintf(stderr, "Got a VNC password read from XenStore\n");
-
- passwd[0] = '\0';
- snprintf(buf, 256, "%s/vncpasswd", uuid);
- if (xs_write(xsh, XBT_NULL, buf, passwd, len) == 0) {
- fprintf(stderr, "xs_write() vncpasswd failed\n");
- rc = -1;
- }
-
- free(passwd);
- free(uuid);
- free(path);
-
- return rc;
-}
-
-static void vnc_update(struct xenfb *xenfb, int x, int y, int w, int h)
-{
- rfbScreenInfoPtr server = xenfb->user_data;
- rfbMarkRectAsModified(server, x, y, x + w, y + h);
-}
-
-static struct option options[] = {
- { "domid", 1, NULL, 'd' },
- { "vncport", 1, NULL, 'p' },
- { "title", 1, NULL, 't' },
- { "unused", 0, NULL, 'u' },
- { "listen", 1, NULL, 'l' },
- { "keymap", 1, NULL, 'k' },
- { NULL }
-};
-
-int main(int argc, char **argv)
-{
- rfbScreenInfoPtr server;
- char *fake_argv[7] = { "vncfb", "-rfbport", "5901",
- "-desktop", "xen-vncfb",
- "-listen", "127.0.0.1" };
- int fake_argc = sizeof(fake_argv) / sizeof(fake_argv[0]);
- int domid = -1, port = -1;
- char *title = NULL;
- char *listen = NULL;
- char *keymap = NULL;
- bool unused = false;
- int opt;
- struct xenfb *xenfb;
- fd_set readfds;
- int nfds;
- char portstr[10];
- char *endp;
- int r;
- struct xs_handle *xsh;
- char vncpasswd[1024];
- int i;
-
- vncpasswd[0] = '\0';
-
- while ((opt = getopt_long(argc, argv, "d:p:t:uk:", options,
- NULL)) != -1) {
- switch (opt) {
- case 'd':
- errno = 0;
- domid = strtol(optarg, &endp, 10);
- if (endp == optarg || *endp || errno) {
- fprintf(stderr, "Invalid domain id
specified\n");
- exit(1);
- }
- break;
- case 'p':
- errno = 0;
- port = strtol(optarg, &endp, 10);
- if (endp == optarg || *endp || errno) {
- fprintf(stderr, "Invalid port specified\n");
- exit(1);
- }
- break;
- case 't':
- title = strdup(optarg);
- break;
- case 'u':
- unused = true;
- break;
- case 'l':
- listen = strdup(optarg);
- break;
- case 'k':
- keymap = strdup(optarg);
- break;
- case '?':
- exit(1);
- }
- }
- if (optind != argc) {
- fprintf(stderr, "Invalid options!\n");
- exit(1);
- }
- if (domid <= 0) {
- fprintf(stderr, "Domain ID must be specified!\n");
- exit(1);
- }
-
- if (port <= 0)
- port = 5900 + domid;
- if (snprintf(portstr, sizeof(portstr), "%d", port) == -1) {
- fprintf(stderr, "Invalid port specified\n");
- exit(1);
- }
-
- if (keymap == NULL){
- keymap = "en-us";
- }
-
- kbd_layout = init_keyboard_layout(keymap);
- if( !kbd_layout ){
- fprintf(stderr, "Invalid keyboard_layout\n");
- exit(1);
- }
-
- for (i = 0; i < 128; i++) {
- keycode_table[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
- keycode_table[i | 0x80] =
- atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
- }
-
- for (i = 0; i < 256; i++ ) {
- modifiers_state[i] = 0;
- }
-
- fake_argv[2] = portstr;
-
- if (title != NULL)
- fake_argv[4] = title;
-
- if (listen != NULL)
- fake_argv[6] = listen;
-
- signal(SIGPIPE, SIG_IGN);
-
- xenfb = xenfb_new();
- if (xenfb == NULL) {
- fprintf(stderr, "Could not create framebuffer (%s)\n",
- strerror(errno));
- exit(1);
- }
-
- if (xenfb_attach_dom(xenfb, domid) < 0) {
- fprintf(stderr, "Could not connect to domain (%s)\n",
- strerror(errno));
- exit(1);
- }
-
- xsh = xs_daemon_open();
- if (xsh == NULL) {
- fprintf(stderr, "cannot open connection to xenstore\n");
- exit(1);
- }
-
-
- if (xenstore_read_vncpasswd(xsh, domid, vncpasswd,
- sizeof(vncpasswd)/sizeof(char)) < 0) {
- fprintf(stderr, "cannot read VNC password from xenstore\n");
- exit(1);
- }
-
-
- server = rfbGetScreen(&fake_argc, fake_argv,
- xenfb->width, xenfb->height,
- 8, 3, xenfb->depth / 8);
- if (server == NULL) {
- fprintf(stderr, "Could not create VNC server\n");
- exit(1);
- }
-
- xenfb->user_data = server;
- xenfb->update = vnc_update;
-
- if (unused)
- server->autoPort = true;
-
- if (vncpasswd[0]) {
- char **passwds = malloc(sizeof(char**)*2);
- if (!passwds) {
- fprintf(stderr, "cannot allocate memory (%s)\n",
- strerror(errno));
- exit(1);
- }
- fprintf(stderr, "Registered password\n");
- passwds[0] = vncpasswd;
- passwds[1] = NULL;
-
- server->authPasswdData = passwds;
- server->passwordCheck = rfbCheckPasswordByList;
- } else {
- fprintf(stderr, "Running with no password\n");
- }
- server->serverFormat.redShift = 16;
- server->serverFormat.greenShift = 8;
- server->serverFormat.blueShift = 0;
- server->kbdAddEvent = on_kbd_event;
- server->ptrAddEvent = on_ptr_event;
- server->frameBuffer = xenfb->pixels;
- server->screenData = xenfb;
- server->cursor = NULL;
- rfbInitServer(server);
-
- rfbRunEventLoop(server, -1, true);
-
- xenstore_write_vncport(xsh, server->port, domid);
-
- for (;;) {
- FD_ZERO(&readfds);
- nfds = xenfb_select_fds(xenfb, &readfds);
-
- if (select(nfds, &readfds, NULL, NULL, NULL) < 0) {
- if (errno == EINTR)
- continue;
- fprintf(stderr,
- "Can't select() on event channel (%s)\n",
- strerror(errno));
- break;
- }
-
- r = xenfb_poll(xenfb, &readfds);
- if (r == -2)
- xenfb_teardown(xenfb);
- if (r < 0)
- break;
- }
-
- rfbScreenCleanup(server);
- xenfb_delete(xenfb);
-
- return 0;
-}
diff -r c17bfb091790 -r a07288a84785 tools/xenfb/xenfb.c
--- a/tools/xenfb/xenfb.c Tue Oct 30 11:33:55 2007 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,779 +0,0 @@
-#include <stdarg.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <xenctrl.h>
-#include <xen/io/xenbus.h>
-#include <xen/io/fbif.h>
-#include <xen/io/kbdif.h>
-#include <xen/io/protocols.h>
-#include <sys/select.h>
-#include <stdbool.h>
-#include <xen/event_channel.h>
-#include <sys/mman.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <xs.h>
-
-#include "xenfb.h"
-
-// FIXME defend against malicious frontend?
-
-struct xenfb_device {
- const char *devicetype;
- char nodename[64]; /* backend xenstore dir */
- char otherend[64]; /* frontend xenstore dir */
- int otherend_id; /* frontend domid */
- enum xenbus_state state; /* backend state */
- void *page; /* shared page */
- evtchn_port_t port;
- struct xenfb_private *xenfb;
-};
-
-struct xenfb_private {
- struct xenfb pub;
- int evt_xch; /* event channel driver handle */
- int xc; /* hypervisor interface handle */
- struct xs_handle *xsh; /* xs daemon handle */
- struct xenfb_device fb, kbd;
- size_t fb_len; /* size of framebuffer */
- char protocol[64]; /* frontend protocol */
-};
-
-static void xenfb_detach_dom(struct xenfb_private *);
-
-static char *xenfb_path_in_dom(struct xs_handle *xsh,
- char *buf, size_t size,
- unsigned domid, const char *fmt, ...)
-{
- va_list ap;
- char *domp = xs_get_domain_path(xsh, domid);
- int n;
-
- if (domp == NULL)
- return NULL;
-
- n = snprintf(buf, size, "%s/", domp);
- free(domp);
- if (n >= size)
- return NULL;
-
- va_start(ap, fmt);
- n += vsnprintf(buf + n, size - n, fmt, ap);
- va_end(ap);
- if (n >= size)
- return NULL;
-
- return buf;
-}
-
-static int xenfb_xs_scanf1(struct xs_handle *xsh,
- const char *dir, const char *node,
- const char *fmt, void *dest)
-{
- char buf[1024];
- char *p;
- int ret;
-
- if (snprintf(buf, sizeof(buf), "%s/%s", dir, node) >= sizeof(buf)) {
- errno = ENOENT;
- return -1;
- }
- p = xs_read(xsh, XBT_NULL, buf, NULL);
- if (!p) {
- errno = ENOENT;
- return -1;
- }
- ret = sscanf(p, fmt, dest);
- free(p);
- if (ret != 1) {
- errno = EDOM;
- return -1;
- }
- return ret;
-}
-
-static int xenfb_xs_printf(struct xs_handle *xsh,
- const char *dir, const char *node, char *fmt, ...)
-{
- va_list ap;
- char key[1024];
- char val[1024];
- int n;
-
- if (snprintf(key, sizeof(key), "%s/%s", dir, node) >= sizeof(key)) {
- errno = ENOENT;
- return -1;
- }
-
- va_start(ap, fmt);
- n = vsnprintf(val, sizeof(val), fmt, ap);
- va_end(ap);
- if (n >= sizeof(val)) {
- errno = ENOSPC; /* close enough */
- return -1;
- }
-
- if (!xs_write(xsh, XBT_NULL, key, val, n))
- return -1;
- return 0;
-}
-
-static void xenfb_device_init(struct xenfb_device *dev,
- const char *type,
- struct xenfb_private *xenfb)
-{
- dev->devicetype = type;
- dev->otherend_id = -1;
- dev->port = -1;
- dev->xenfb = xenfb;
-}
-
-int xenfb_device_set_domain(struct xenfb_device *dev, int domid)
-{
- struct xenfb_private *xenfb = dev->xenfb;
-
- dev->otherend_id = domid;
-
- if (!xenfb_path_in_dom(xenfb->xsh,
- dev->otherend, sizeof(dev->otherend),
- domid, "device/%s/0", dev->devicetype)) {
- errno = ENOENT;
- return -1;
- }
- if (!xenfb_path_in_dom(xenfb->xsh,
- dev->nodename, sizeof(dev->nodename),
- 0, "backend/%s/%d/0", dev->devicetype, domid)) {
- errno = ENOENT;
- return -1;
- }
-
- return 0;
-}
-
-struct xenfb *xenfb_new(void)
-{
- struct xenfb_private *xenfb = malloc(sizeof(*xenfb));
- int serrno;
-
- if (xenfb == NULL)
- return NULL;
-
- memset(xenfb, 0, sizeof(*xenfb));
- xenfb->evt_xch = xenfb->xc = -1;
- xenfb_device_init(&xenfb->fb, "vfb", xenfb);
- xenfb_device_init(&xenfb->kbd, "vkbd", xenfb);
-
- xenfb->evt_xch = xc_evtchn_open();
- if (xenfb->evt_xch == -1)
- goto fail;
-
- xenfb->xc = xc_interface_open();
- if (xenfb->xc == -1)
- goto fail;
-
- xenfb->xsh = xs_daemon_open();
- if (!xenfb->xsh)
- goto fail;
-
- return &xenfb->pub;
-
- fail:
- serrno = errno;
- xenfb_delete(&xenfb->pub);
- errno = serrno;
- return NULL;
-}
-
-/* Remove the backend area in xenbus since the framebuffer really is
- going away. */
-void xenfb_teardown(struct xenfb *xenfb_pub)
-{
- struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
-
- xs_rm(xenfb->xsh, XBT_NULL, xenfb->fb.nodename);
- xs_rm(xenfb->xsh, XBT_NULL, xenfb->kbd.nodename);
-}
-
-
-void xenfb_delete(struct xenfb *xenfb_pub)
-{
- struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
-
- xenfb_detach_dom(xenfb);
- if (xenfb->xc >= 0)
- xc_interface_close(xenfb->xc);
- if (xenfb->evt_xch >= 0)
- xc_evtchn_close(xenfb->evt_xch);
- if (xenfb->xsh)
- xs_daemon_close(xenfb->xsh);
- free(xenfb);
-}
-
-static enum xenbus_state xenfb_read_state(struct xs_handle *xsh,
- const char *dir)
-{
- int ret, state;
-
- ret = xenfb_xs_scanf1(xsh, dir, "state", "%d", &state);
- if (ret < 0)
- return XenbusStateUnknown;
-
- if ((unsigned)state > XenbusStateClosed)
- state = XenbusStateUnknown;
- return state;
-}
-
-static int xenfb_switch_state(struct xenfb_device *dev,
- enum xenbus_state state)
-{
- struct xs_handle *xsh = dev->xenfb->xsh;
-
- if (xenfb_xs_printf(xsh, dev->nodename, "state", "%d", state) < 0)
- return -1;
- dev->state = state;
- return 0;
-}
-
-static int xenfb_wait_for_state(struct xs_handle *xsh, const char *dir,
- unsigned awaited)
-{
- unsigned state, dummy;
- char **vec;
-
- awaited |= 1 << XenbusStateUnknown;
-
- for (;;) {
- state = xenfb_read_state(xsh, dir);
- if ((1 << state) & awaited)
- return state;
-
- vec = xs_read_watch(xsh, &dummy);
- if (!vec)
- return -1;
- free(vec);
- }
-}
-
-static int xenfb_wait_for_backend_creation(struct xenfb_device *dev)
-{
- struct xs_handle *xsh = dev->xenfb->xsh;
- int state;
-
- if (!xs_watch(xsh, dev->nodename, ""))
- return -1;
- state = xenfb_wait_for_state(xsh, dev->nodename,
- (1 << XenbusStateInitialising)
- | (1 << XenbusStateClosed)
-#if 1 /* TODO fudging state to permit restarting; to be removed */
- | (1 << XenbusStateInitWait)
- | (1 << XenbusStateConnected)
- | (1 << XenbusStateClosing)
-#endif
- );
- xs_unwatch(xsh, dev->nodename, "");
-
- switch (state) {
-#if 1
- case XenbusStateInitWait:
- case XenbusStateConnected:
- printf("Fudging state to %d\n", XenbusStateInitialising); /*
FIXME */
-#endif
- case XenbusStateInitialising:
- case XenbusStateClosing:
- case XenbusStateClosed:
- break;
- default:
- return -1;
- }
-
- return 0;
-}
-
-static int xenfb_hotplug(struct xenfb_device *dev)
-{
- if (xenfb_xs_printf(dev->xenfb->xsh, dev->nodename,
- "hotplug-status", "connected"))
- return -1;
- return 0;
-}
-
-static int xenfb_wait_for_frontend_initialised(struct xenfb_device *dev)
-{
- switch (xenfb_wait_for_state(dev->xenfb->xsh, dev->otherend,
-#if 1 /* TODO fudging state to permit restarting; to be removed */
- (1 << XenbusStateInitialised)
- | (1 << XenbusStateConnected)
-#else
- 1 << XenbusStateInitialised,
-#endif
- )) {
-#if 1
- case XenbusStateConnected:
- printf("Fudging state to %d\n", XenbusStateInitialised); /*
FIXME */
-#endif
- case XenbusStateInitialised:
- break;
- default:
- return -1;
- }
-
- return 0;
-}
-
-static void xenfb_copy_mfns(int mode, int count, unsigned long *dst, void *src)
-{
- uint32_t *src32 = src;
- uint64_t *src64 = src;
- int i;
-
- for (i = 0; i < count; i++)
- dst[i] = (mode == 32) ? src32[i] : src64[i];
-}
-
-static int xenfb_map_fb(struct xenfb_private *xenfb, int domid)
-{
- struct xenfb_page *page = xenfb->fb.page;
- int n_fbmfns;
- int n_fbdirs;
- unsigned long *pgmfns = NULL;
- unsigned long *fbmfns = NULL;
- void *map, *pd;
- int mode, ret = -1;
-
- /* default to native */
- pd = page->pd;
- mode = sizeof(unsigned long) * 8;
-
- if (0 == strlen(xenfb->protocol)) {
- /*
- * Undefined protocol, some guesswork needed.
- *
- * Old frontends which don't set the protocol use
- * one page directory only, thus pd[1] must be zero.
- * pd[1] of the 32bit struct layout and the lower
- * 32 bits of pd[0] of the 64bit struct layout have
- * the same location, so we can check that ...
- */
- uint32_t *ptr32 = NULL;
- uint32_t *ptr64 = NULL;
-#if defined(__i386__)
- ptr32 = (void*)page->pd;
- ptr64 = ((void*)page->pd) + 4;
-#elif defined(__x86_64__)
- ptr32 = ((void*)page->pd) - 4;
- ptr64 = (void*)page->pd;
-#endif
- if (ptr32) {
- if (0 == ptr32[1]) {
- mode = 32;
- pd = ptr32;
- } else {
- mode = 64;
- pd = ptr64;
- }
- }
-#if defined(__x86_64__)
- } else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_32)) {
- /* 64bit dom0, 32bit domU */
- mode = 32;
- pd = ((void*)page->pd) - 4;
-#elif defined(__i386__)
- } else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_64)) {
- /* 32bit dom0, 64bit domU */
- mode = 64;
- pd = ((void*)page->pd) + 4;
-#endif
- }
-
- n_fbmfns = (xenfb->fb_len + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
- n_fbdirs = n_fbmfns * mode / 8;
- n_fbdirs = (n_fbdirs + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
-
- pgmfns = malloc(sizeof(unsigned long) * n_fbdirs);
- fbmfns = malloc(sizeof(unsigned long) * n_fbmfns);
- if (!pgmfns || !fbmfns)
- goto out;
-
- xenfb_copy_mfns(mode, n_fbdirs, pgmfns, pd);
- map = xc_map_foreign_pages(xenfb->xc, domid,
- PROT_READ, pgmfns, n_fbdirs);
- if (map == NULL)
- goto out;
- xenfb_copy_mfns(mode, n_fbmfns, fbmfns, map);
- munmap(map, n_fbdirs * XC_PAGE_SIZE);
-
- xenfb->pub.pixels = xc_map_foreign_pages(xenfb->xc, domid,
- PROT_READ | PROT_WRITE, fbmfns, n_fbmfns);
- if (xenfb->pub.pixels == NULL)
- goto out;
-
- ret = 0; /* all is fine */
-
- out:
- if (pgmfns)
- free(pgmfns);
- if (fbmfns)
- free(fbmfns);
- return ret;
-}
-
-static int xenfb_bind(struct xenfb_device *dev)
-{
- struct xenfb_private *xenfb = dev->xenfb;
- unsigned long mfn;
- evtchn_port_t evtchn;
-
- if (xenfb_xs_scanf1(xenfb->xsh, dev->otherend, "page-ref", "%lu",
- &mfn) < 0)
- return -1;
- if (xenfb_xs_scanf1(xenfb->xsh, dev->otherend, "event-channel", "%u",
- &evtchn) < 0)
- return -1;
-
- dev->port = xc_evtchn_bind_interdomain(xenfb->evt_xch,
- dev->otherend_id, evtchn);
- if (dev->port == -1)
- return -1;
-
- dev->page = xc_map_foreign_range(xenfb->xc, dev->otherend_id,
- XC_PAGE_SIZE, PROT_READ | PROT_WRITE, mfn);
- if (dev->page == NULL)
- return -1;
-
- return 0;
-}
-
-static void xenfb_unbind(struct xenfb_device *dev)
-{
- if (dev->page) {
- munmap(dev->page, XC_PAGE_SIZE);
- dev->page = NULL;
- }
- if (dev->port >= 0) {
- xc_evtchn_unbind(dev->xenfb->evt_xch, dev->port);
- dev->port = -1;
- }
-}
-
-static int xenfb_wait_for_frontend_connected(struct xenfb_device *dev)
-{
- switch (xenfb_wait_for_state(dev->xenfb->xsh, dev->otherend,
- 1 << XenbusStateConnected)) {
- case XenbusStateConnected:
- break;
- default:
- return -1;
- }
-
- return 0;
-}
-
-static void xenfb_dev_fatal(struct xenfb_device *dev, int err,
- const char *fmt, ...)
-{
- struct xs_handle *xsh = dev->xenfb->xsh;
- va_list ap;
- char errdir[80];
- char buf[1024];
- int n;
-
- fprintf(stderr, "%s ", dev->nodename); /* somewhat crude */
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
- if (err)
- fprintf(stderr, " (%s)", strerror(err));
- putc('\n', stderr);
-
- if (!xenfb_path_in_dom(xsh, errdir, sizeof(errdir), 0,
- "error/%s", dev->nodename))
- goto out; /* FIXME complain */
-
- va_start(ap, fmt);
- n = snprintf(buf, sizeof(buf), "%d ", err);
- snprintf(buf + n, sizeof(buf) - n, fmt, ap);
- va_end(ap);
-
- if (xenfb_xs_printf(xsh, buf, "error", "%s", buf) < 0)
- goto out; /* FIXME complain */
-
- out:
- xenfb_switch_state(dev, XenbusStateClosing);
-}
-
-int xenfb_attach_dom(struct xenfb *xenfb_pub, int domid)
-{
- struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
- struct xs_handle *xsh = xenfb->xsh;
- int val, serrno;
- struct xenfb_page *fb_page;
-
- xenfb_detach_dom(xenfb);
-
- xenfb_device_set_domain(&xenfb->fb, domid);
- xenfb_device_set_domain(&xenfb->kbd, domid);
-
- if (xenfb_wait_for_backend_creation(&xenfb->fb) < 0)
- goto error;
- if (xenfb_wait_for_backend_creation(&xenfb->kbd) < 0)
- goto error;
-
- if (xenfb_xs_printf(xsh, xenfb->kbd.nodename, "feature-abs-pointer",
"1"))
- goto error;
- if (xenfb_switch_state(&xenfb->fb, XenbusStateInitWait))
- goto error;
- if (xenfb_switch_state(&xenfb->kbd, XenbusStateInitWait))
- goto error;
-
- if (xenfb_hotplug(&xenfb->fb) < 0)
- goto error;
- if (xenfb_hotplug(&xenfb->kbd) < 0)
- goto error;
-
- if (!xs_watch(xsh, xenfb->fb.otherend, ""))
- goto error;
- if (!xs_watch(xsh, xenfb->kbd.otherend, ""))
- goto error;
-
- if (xenfb_wait_for_frontend_initialised(&xenfb->fb) < 0)
- goto error;
- if (xenfb_wait_for_frontend_initialised(&xenfb->kbd) < 0)
- goto error;
-
- if (xenfb_bind(&xenfb->fb) < 0)
- goto error;
- if (xenfb_bind(&xenfb->kbd) < 0)
- goto error;
-
- if (xenfb_xs_scanf1(xsh, xenfb->fb.otherend, "feature-update",
- "%d", &val) < 0)
- val = 0;
- if (!val) {
- errno = ENOTSUP;
- goto error;
- }
- if (xenfb_xs_scanf1(xsh, xenfb->fb.otherend, "protocol", "%63s",
- xenfb->protocol) < 0)
- xenfb->protocol[0] = '\0';
- xenfb_xs_printf(xsh, xenfb->fb.nodename, "request-update", "1");
-
- /* TODO check for permitted ranges */
- fb_page = xenfb->fb.page;
- xenfb->pub.depth = fb_page->depth;
- xenfb->pub.width = fb_page->width;
- xenfb->pub.height = fb_page->height;
- /* TODO check for consistency with the above */
- xenfb->fb_len = fb_page->mem_length;
- xenfb->pub.row_stride = fb_page->line_length;
-
- if (xenfb_map_fb(xenfb, domid) < 0)
- goto error;
-
- if (xenfb_switch_state(&xenfb->fb, XenbusStateConnected))
- goto error;
- if (xenfb_switch_state(&xenfb->kbd, XenbusStateConnected))
- goto error;
-
- if (xenfb_wait_for_frontend_connected(&xenfb->kbd) < 0)
- goto error;
- if (xenfb_xs_scanf1(xsh, xenfb->kbd.otherend, "request-abs-pointer",
- "%d", &val) < 0)
- val = 0;
- xenfb->pub.abs_pointer_wanted = val;
-
- return 0;
-
- error:
- serrno = errno;
- xenfb_detach_dom(xenfb);
- xenfb_dev_fatal(&xenfb->fb, serrno, "on fire");
- xenfb_dev_fatal(&xenfb->kbd, serrno, "on fire");
- errno = serrno;
- return -1;
-}
-
-static void xenfb_detach_dom(struct xenfb_private *xenfb)
-{
- xenfb_unbind(&xenfb->fb);
- xenfb_unbind(&xenfb->kbd);
- if (xenfb->pub.pixels) {
- munmap(xenfb->pub.pixels, xenfb->fb_len);
- xenfb->pub.pixels = NULL;
- }
-}
-
-static void xenfb_on_fb_event(struct xenfb_private *xenfb)
-{
- uint32_t prod, cons;
- struct xenfb_page *page = xenfb->fb.page;
-
- prod = page->out_prod;
- if (prod == page->out_cons)
- return;
- 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);
-
- switch (event->type) {
- case XENFB_TYPE_UPDATE:
- if (xenfb->pub.update)
- xenfb->pub.update(&xenfb->pub,
- event->update.x, event->update.y,
- event->update.width,
event->update.height);
- break;
- }
- }
- mb(); /* ensure we're done with ring contents */
- page->out_cons = cons;
- xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port);
-}
-
-static void xenfb_on_kbd_event(struct xenfb_private *xenfb)
-{
- struct xenkbd_page *page = xenfb->kbd.page;
-
- /* We don't understand any keyboard events, so just ignore them. */
- if (page->out_prod == page->out_cons)
- return;
- page->out_cons = page->out_prod;
- xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port);
-}
-
-static int xenfb_on_state_change(struct xenfb_device *dev)
-{
- enum xenbus_state state;
-
- state = xenfb_read_state(dev->xenfb->xsh, dev->otherend);
-
- switch (state) {
- case XenbusStateUnknown:
- /* There was an error reading the frontend state. The
- domain has probably gone away; in any case, there's
- not much point in us continuing. */
- return -1;
- case XenbusStateInitialising:
- case XenbusStateInitWait:
- case XenbusStateInitialised:
- case XenbusStateConnected:
- break;
- case XenbusStateClosing:
- xenfb_unbind(dev);
- xenfb_switch_state(dev, state);
- break;
- case XenbusStateClosed:
- xenfb_switch_state(dev, state);
- }
- return 0;
-}
-
-/* Returns 0 normally, -1 on error, or -2 if the domain went away. */
-int xenfb_poll(struct xenfb *xenfb_pub, fd_set *readfds)
-{
- struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
- evtchn_port_t port;
- unsigned dummy;
- char **vec;
- int r;
-
- if (FD_ISSET(xc_evtchn_fd(xenfb->evt_xch), readfds)) {
- port = xc_evtchn_pending(xenfb->evt_xch);
- if (port == -1)
- return -1;
-
- if (port == xenfb->fb.port)
- xenfb_on_fb_event(xenfb);
- else if (port == xenfb->kbd.port)
- xenfb_on_kbd_event(xenfb);
-
- if (xc_evtchn_unmask(xenfb->evt_xch, port) == -1)
- return -1;
- }
-
- if (FD_ISSET(xs_fileno(xenfb->xsh), readfds)) {
- vec = xs_read_watch(xenfb->xsh, &dummy);
- free(vec);
- r = xenfb_on_state_change(&xenfb->fb);
- if (r == 0)
- r = xenfb_on_state_change(&xenfb->kbd);
- if (r == -1)
- return -2;
- }
-
- return 0;
-}
-
-int xenfb_select_fds(struct xenfb *xenfb_pub, fd_set *readfds)
-{
- struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
- int fd1 = xc_evtchn_fd(xenfb->evt_xch);
- int fd2 = xs_fileno(xenfb->xsh);
-
- FD_SET(fd1, readfds);
- FD_SET(fd2, readfds);
- return fd1 > fd2 ? fd1 + 1 : fd2 + 1;
-}
-
-static int xenfb_kbd_event(struct xenfb_private *xenfb,
- union xenkbd_in_event *event)
-{
- uint32_t prod;
- struct xenkbd_page *page = xenfb->kbd.page;
-
- if (xenfb->kbd.state != XenbusStateConnected)
- return 0;
-
- prod = page->in_prod;
- if (prod - page->in_cons == XENKBD_IN_RING_LEN) {
- errno = EAGAIN;
- return -1;
- }
-
- mb(); /* ensure ring space available */
- XENKBD_IN_RING_REF(page, prod) = *event;
- wmb(); /* ensure ring contents visible */
- page->in_prod = prod + 1;
- return xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port);
-}
-
-int xenfb_send_key(struct xenfb *xenfb_pub, bool down, int keycode)
-{
- struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
- union xenkbd_in_event event;
-
- memset(&event, 0, XENKBD_IN_EVENT_SIZE);
- event.type = XENKBD_TYPE_KEY;
- event.key.pressed = down ? 1 : 0;
- event.key.keycode = keycode;
-
- return xenfb_kbd_event(xenfb, &event);
-}
-
-int xenfb_send_motion(struct xenfb *xenfb_pub, int rel_x, int rel_y)
-{
- struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
- union xenkbd_in_event event;
-
- memset(&event, 0, XENKBD_IN_EVENT_SIZE);
- event.type = XENKBD_TYPE_MOTION;
- event.motion.rel_x = rel_x;
- event.motion.rel_y = rel_y;
-
- return xenfb_kbd_event(xenfb, &event);
-}
-
-int xenfb_send_position(struct xenfb *xenfb_pub, int abs_x, int abs_y)
-{
- struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
- union xenkbd_in_event event;
-
- memset(&event, 0, XENKBD_IN_EVENT_SIZE);
- event.type = XENKBD_TYPE_POS;
- event.pos.abs_x = abs_x;
- event.pos.abs_y = abs_y;
-
- return xenfb_kbd_event(xenfb, &event);
-}
diff -r c17bfb091790 -r a07288a84785 tools/xenfb/xenfb.h
--- a/tools/xenfb/xenfb.h Tue Oct 30 11:33:55 2007 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-#ifndef _XENFB_H_
-#define _XENFB_H_
-
-#include <stdbool.h>
-#include <sys/types.h>
-
-struct xenfb
-{
- void *pixels;
-
- int row_stride;
- int depth;
- int width;
- int height;
- int abs_pointer_wanted;
-
- void *user_data;
-
- void (*update)(struct xenfb *xenfb, int x, int y, int width, int
height);
-};
-
-struct xenfb *xenfb_new(void);
-void xenfb_delete(struct xenfb *xenfb);
-void xenfb_teardown(struct xenfb *xenfb);
-
-int xenfb_attach_dom(struct xenfb *xenfb, int domid);
-
-int xenfb_select_fds(struct xenfb *xenfb, fd_set *readfds);
-int xenfb_poll(struct xenfb *xenfb, fd_set *readfds);
-
-int xenfb_send_key(struct xenfb *xenfb, bool down, int keycode);
-int xenfb_send_motion(struct xenfb *xenfb, int rel_x, int rel_y);
-int xenfb_send_position(struct xenfb *xenfb, int abs_x, int abs_y);
-
-#endif
diff -r c17bfb091790 -r a07288a84785 tools/xenstore/xenstored_watch.c
--- a/tools/xenstore/xenstored_watch.c Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/xenstore/xenstored_watch.c Tue Oct 30 15:34:44 2007 -0600
@@ -59,7 +59,16 @@ static void add_event(struct connection
if (!check_event_node(name)) {
/* Can this conn load node, or see that it doesn't exist? */
struct node *node = get_node(conn, name, XS_PERM_READ);
- if (!node && errno != ENOENT)
+ /*
+ * XXX We allow EACCES here because otherwise a non-dom0
+ * backend driver cannot watch for disappearance of a frontend
+ * xenstore directory. When the directory disappears, we
+ * revert to permissions of the parent directory for that path,
+ * which will typically disallow access for the backend.
+ * But this breaks device-channel teardown!
+ * Really we should fix this better...
+ */
+ if (!node && errno != ENOENT && errno != EACCES)
return;
}
diff -r c17bfb091790 -r a07288a84785 tools/xentrace/xentrace.c
--- a/tools/xentrace/xentrace.c Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/xentrace/xentrace.c Tue Oct 30 15:34:44 2007 -0600
@@ -394,7 +394,7 @@ int monitor_tbufs(int outfd)
}
mb(); /* read buffer, then update cons. */
- meta[i]->cons = meta[i]->prod;
+ meta[i]->cons = prod;
}
nanosleep(&opts.poll_sleep, NULL);
diff -r c17bfb091790 -r a07288a84785 tools/xm-test/lib/XmTestLib/XenAPIDomain.py
--- a/tools/xm-test/lib/XmTestLib/XenAPIDomain.py Tue Oct 30 11:33:55
2007 -0600
+++ b/tools/xm-test/lib/XmTestLib/XenAPIDomain.py Tue Oct 30 15:34:44
2007 -0600
@@ -38,7 +38,8 @@ class XenAPIConfig:
'memory_dynamic_max' ],
'kernel' : 'PV_kernel',
'ramdisk': 'PV_ramdisk',
- 'root' : 'PV_args'}
+ 'root' : 'PV_args',
+ 'extra' : 'PV_args' }
if isACMEnabled():
#A default so every VM can start with ACM enabled
self.opts["security_label"] = "ACM:xm-test:red"
@@ -47,6 +48,8 @@ class XenAPIConfig:
"""Set an option in the config"""
if name == "memory":
value <<= 20
+ if name == "root":
+ value = "root=" + value
if name in self.opttrlate.keys():
_name = self.opttrlate[name]
else:
@@ -56,7 +59,11 @@ class XenAPIConfig:
for _n in _name:
self.opts[_n] = value
else:
- self.opts[_name] = value
+ if not self.opts.get(_name) or \
+ not _name in [ "PV_args" ]:
+ self.opts[_name] = value
+ else:
+ self.opts[_name] += " " + value
def getOpt(self, name):
"""Return the value of a config option"""
diff -r c17bfb091790 -r a07288a84785
tools/xm-test/tests/security-acm/08_security-acm_xapi.py
--- a/tools/xm-test/tests/security-acm/08_security-acm_xapi.py Tue Oct 30
11:33:55 2007 -0600
+++ b/tools/xm-test/tests/security-acm/08_security-acm_xapi.py Tue Oct 30
15:34:44 2007 -0600
@@ -18,6 +18,9 @@ vm_label_green = xsconstants.ACM_POLICY
vm_label_green = xsconstants.ACM_POLICY_ID + ":xm-test:green"
vdi_label_red = xsconstants.ACM_POLICY_ID + ":xm-test:red"
vdi_label_green = xsconstants.ACM_POLICY_ID + ":xm-test:green"
+
+vm_label_unlabeled = xsconstants.ACM_POLICY_ID + ":xm-test:" + \
+ acmpolicy.ACM_LABEL_UNLABELED
vdi_file = "/dev/ram0"
vdi_path = "phy:" + vdi_file
@@ -105,7 +108,7 @@ if int(res) != 0:
FAIL("Should be able to unlabel the domain while it's halted.")
res = session.xenapi.VM.get_security_label(vm_uuid)
-if res != "":
+if res != vm_label_unlabeled:
FAIL("Unexpected VM security label after removal: %s" % res)
res = session.xenapi.VM.set_security_label(vm_uuid, vm_label_red, res)
diff -r c17bfb091790 -r a07288a84785 tools/xm-test/tests/vtpm/09_vtpm-xapi.py
--- a/tools/xm-test/tests/vtpm/09_vtpm-xapi.py Tue Oct 30 11:33:55 2007 -0600
+++ b/tools/xm-test/tests/vtpm/09_vtpm-xapi.py Tue Oct 30 15:34:44 2007 -0600
@@ -17,7 +17,7 @@ import commands
import commands
import os
-VTPM_RECORD_KEYS = [ 'backend', 'VM', 'uuid' ]
+VTPM_RECORD_KEYS = [ 'backend', 'VM', 'uuid', 'other_config' ]
try:
# XmTestAPIDomain tries to establish a connection to XenD
diff -r c17bfb091790 -r a07288a84785 unmodified_drivers/linux-2.6/README
--- a/unmodified_drivers/linux-2.6/README Tue Oct 30 11:33:55 2007 -0600
+++ b/unmodified_drivers/linux-2.6/README Tue Oct 30 15:34:44 2007 -0600
@@ -1,12 +1,12 @@ To build:
To build:
1. ./mkbuildtree
- NB. You can override paths to Xen sources and XenLinux sources via
- the XEN and XL environment variable.
+ NB. You can override paths to Xen sources and a (stub) XenLinux
+ build tree via the XEN and XL environment variable.
-2. make -C /path/to/kernel/source M=$PWD modules
- NB. The kernel sources here are your native kernel build tree, not
- the XenLinux sources referred to in step 1.
+2. make -C /path/to/kernel/build M=$PWD modules
+ NB. This is your native kernel build tree (or a distro provided
+ stub), not the XenLinux sources referred to in step 1.
You get four modules, xen-platform-pci.ko, xenbus.ko, xen-vbd.ko, and
xen-vnif.ko. Load xen-platform-pci first, then xenbus, and then
diff -r c17bfb091790 -r a07288a84785
unmodified_drivers/linux-2.6/compat-include/xen/platform-compat.h
--- a/unmodified_drivers/linux-2.6/compat-include/xen/platform-compat.h Tue Oct
30 11:33:55 2007 -0600
+++ b/unmodified_drivers/linux-2.6/compat-include/xen/platform-compat.h Tue Oct
30 15:34:44 2007 -0600
@@ -125,4 +125,12 @@ extern char *kasprintf(gfp_t gfp, const
#define DEFINE_RWLOCK(x) rwlock_t x = RW_LOCK_UNLOCKED
#endif
+#if defined(_LINUX_INTERRUPT_H) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
+typedef irqreturn_t (*irq_handler_t)(int, void *, struct pt_regs *);
#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
+#define setup_xen_features xen_setup_features
+#endif
+
+#endif
diff -r c17bfb091790 -r a07288a84785 unmodified_drivers/linux-2.6/overrides.mk
--- a/unmodified_drivers/linux-2.6/overrides.mk Tue Oct 30 11:33:55 2007 -0600
+++ b/unmodified_drivers/linux-2.6/overrides.mk Tue Oct 30 15:34:44 2007 -0600
@@ -11,4 +11,4 @@ ifeq ($(ARCH),ia64)
EXTRA_CFLAGS += -DCONFIG_VMX_GUEST
endif
-EXTRA_CFLAGS += -include $(srctree)/include/linux/autoconf.h
+EXTRA_CFLAGS += -include $(objtree)/include/linux/autoconf.h
diff -r c17bfb091790 -r a07288a84785
unmodified_drivers/linux-2.6/platform-pci/evtchn.c
--- a/unmodified_drivers/linux-2.6/platform-pci/evtchn.c Tue Oct 30
11:33:55 2007 -0600
+++ b/unmodified_drivers/linux-2.6/platform-pci/evtchn.c Tue Oct 30
15:34:44 2007 -0600
@@ -28,7 +28,6 @@
* IN THE SOFTWARE.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/spinlock.h>
@@ -48,7 +47,7 @@ void *shared_info_area;
static struct {
spinlock_t lock;
- irqreturn_t(*handler) (int, void *, struct pt_regs *);
+ irq_handler_t handler;
void *dev_id;
int evtchn;
int close:1; /* close on unbind_from_irqhandler()? */
@@ -146,7 +145,7 @@ EXPORT_SYMBOL(unmask_evtchn);
int bind_listening_port_to_irqhandler(
unsigned int remote_domain,
- irqreturn_t (*handler)(int, void *, struct pt_regs *),
+ irq_handler_t handler,
unsigned long irqflags,
const char *devname,
void *dev_id)
@@ -187,7 +186,7 @@ EXPORT_SYMBOL(bind_listening_port_to_irq
int bind_caller_port_to_irqhandler(
unsigned int caller_port,
- irqreturn_t (*handler)(int, void *, struct pt_regs *),
+ irq_handler_t handler,
unsigned long irqflags,
const char *devname,
void *dev_id)
@@ -254,13 +253,18 @@ void notify_remote_via_irq(int irq)
}
EXPORT_SYMBOL(notify_remote_via_irq);
-static irqreturn_t evtchn_interrupt(int irq, void *dev_id,
- struct pt_regs *regs)
+static irqreturn_t evtchn_interrupt(int irq, void *dev_id
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
+ , struct pt_regs *regs
+#else
+# define handler(irq, dev_id, regs) handler(irq, dev_id)
+#endif
+ )
{
unsigned int l1i, port;
/* XXX: All events are bound to vcpu0 but irq may be redirected. */
int cpu = 0; /*smp_processor_id();*/
- irqreturn_t(*handler) (int, void *, struct pt_regs *);
+ irq_handler_t handler;
shared_info_t *s = shared_info_area;
vcpu_info_t *v = &s->vcpu_info[cpu];
unsigned long l1, l2;
@@ -331,6 +335,10 @@ int xen_irq_init(struct pci_dev *pdev)
spin_lock_init(&irq_evtchn[irq].lock);
return request_irq(pdev->irq, evtchn_interrupt,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
SA_SHIRQ | SA_SAMPLE_RANDOM | SA_INTERRUPT,
+#else
+ IRQF_SHARED | IRQF_SAMPLE_RANDOM | IRQF_DISABLED,
+#endif
"xen-platform-pci", pdev);
}
diff -r c17bfb091790 -r a07288a84785
unmodified_drivers/linux-2.6/platform-pci/machine_reboot.c
--- a/unmodified_drivers/linux-2.6/platform-pci/machine_reboot.c Tue Oct
30 11:33:55 2007 -0600
+++ b/unmodified_drivers/linux-2.6/platform-pci/machine_reboot.c Tue Oct
30 15:34:44 2007 -0600
@@ -1,4 +1,3 @@
-#include <linux/config.h>
#include <linux/cpumask.h>
#include <linux/preempt.h>
#include <xen/evtchn.h>
diff -r c17bfb091790 -r a07288a84785
unmodified_drivers/linux-2.6/platform-pci/platform-pci.c
--- a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c Tue Oct 30
11:33:55 2007 -0600
+++ b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c Tue Oct 30
15:34:44 2007 -0600
@@ -367,7 +367,11 @@ static int __init platform_pci_module_in
{
int rc;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
rc = pci_module_init(&platform_driver);
+#else
+ rc = pci_register_driver(&platform_driver);
+#endif
if (rc) {
printk(KERN_INFO DRV_NAME
": No platform pci device model found\n");
diff -r c17bfb091790 -r a07288a84785 xen/arch/ia64/vmx/mmio.c
--- a/xen/arch/ia64/vmx/mmio.c Tue Oct 30 11:33:55 2007 -0600
+++ b/xen/arch/ia64/vmx/mmio.c Tue Oct 30 15:34:44 2007 -0600
@@ -55,53 +55,68 @@ static int hvm_buffered_io_intercept(ior
static int hvm_buffered_io_intercept(ioreq_t *p)
{
struct vcpu *v = current;
- spinlock_t *buffered_io_lock;
- buffered_iopage_t *buffered_iopage =
+ buffered_iopage_t *pg =
(buffered_iopage_t *)(v->domain->arch.hvm_domain.buffered_io_va);
- unsigned long tmp_write_pointer = 0;
+ buf_ioreq_t bp;
int i;
+ /* Ensure buffered_iopage fits in a page */
+ BUILD_BUG_ON(sizeof(buffered_iopage_t) > PAGE_SIZE);
+
/* ignore READ ioreq_t! */
- if ( p->dir == IOREQ_READ )
- return 0;
-
- for ( i = 0; i < HVM_BUFFERED_IO_RANGE_NR; i++ ) {
- if ( p->addr >= hvm_buffered_io_ranges[i]->start_addr &&
- p->addr + p->size - 1 < hvm_buffered_io_ranges[i]->start_addr +
- hvm_buffered_io_ranges[i]->length )
+ if (p->dir == IOREQ_READ)
+ return 0;
+
+ for (i = 0; i < HVM_BUFFERED_IO_RANGE_NR; i++) {
+ if (p->addr >= hvm_buffered_io_ranges[i]->start_addr &&
+ p->addr + p->size - 1 < hvm_buffered_io_ranges[i]->start_addr +
+ hvm_buffered_io_ranges[i]->length)
break;
}
- if ( i == HVM_BUFFERED_IO_RANGE_NR )
- return 0;
-
- buffered_io_lock = &v->domain->arch.hvm_domain.buffered_io_lock;
- spin_lock(buffered_io_lock);
-
- if ( buffered_iopage->write_pointer - buffered_iopage->read_pointer ==
- (unsigned long)IOREQ_BUFFER_SLOT_NUM ) {
+ if (i == HVM_BUFFERED_IO_RANGE_NR)
+ return 0;
+
+ bp.type = p->type;
+ bp.dir = p->dir;
+ switch (p->size) {
+ case 1:
+ bp.size = 0;
+ break;
+ case 2:
+ bp.size = 1;
+ break;
+ default:
+ /* Could use quad word semantics, but it only appears
+ * to be useful for timeoffset data. */
+ return 0;
+ }
+ bp.data = (uint16_t)p->data;
+ bp.addr = (uint32_t)p->addr;
+
+ spin_lock(&v->domain->arch.hvm_domain.buffered_io_lock);
+
+ if (pg->write_pointer - pg->read_pointer == IOREQ_BUFFER_SLOT_NUM) {
/* the queue is full.
* send the iopacket through the normal path.
* NOTE: The arithimetic operation could handle the situation for
* write_pointer overflow.
*/
- spin_unlock(buffered_io_lock);
- return 0;
- }
-
- tmp_write_pointer = buffered_iopage->write_pointer % IOREQ_BUFFER_SLOT_NUM;
-
- memcpy(&buffered_iopage->ioreq[tmp_write_pointer], p, sizeof(ioreq_t));
-
- /*make the ioreq_t visible before write_pointer*/
+ spin_unlock(&v->domain->arch.hvm_domain.buffered_io_lock);
+ return 0;
+ }
+
+ memcpy(&pg->buf_ioreq[pg->write_pointer % IOREQ_BUFFER_SLOT_NUM],
+ &bp, sizeof(bp));
+
+ /* Make the ioreq_t visible before write_pointer */
wmb();
- buffered_iopage->write_pointer++;
-
- spin_unlock(buffered_io_lock);
+ pg->write_pointer++;
+
+ spin_unlock(&v->domain->arch.hvm_domain.buffered_io_lock);
return 1;
}
-
static void low_mmio_access(VCPU *vcpu, u64 pa, u64 *val, size_t s, int dir)
{
@@ -110,32 +125,36 @@ static void low_mmio_access(VCPU *vcpu,
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|