[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] merge with xen-unstable.hg (staging)
# 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |